Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,106 @@
/**
* AutoSelectionModel is responsible for toggling operator auto selection. If
* the mobile connection is busy, it caches the request and do it later once
* the mobile connection becomes available.
*
* @module panels/operator_settings/models/auto_selection_model
*/
define(function(require) {
'use strict';
var Defer = require('modules/defer');
var StateModel = require('modules/state_model');
var MobileConnectionWrapper =
require('panels/operator_settings/models/mobile_connection_wrapper');
// Auto selection state
const AS_STATE = {
UNKNOWN: 0,
ENABLED: 1,
DISABLED: 2
};
const AS_STATE_MAP = {
'manual': AS_STATE.DISABLED,
'automatic': AS_STATE.ENABLED
};
var AutoSelectionModel = function(connWrapper) {
return StateModel({
onInit: function() {
this._pendingRequest = null;
connWrapper.observe('state', (newState) => {
this._checkPendingRequest(newState);
});
return AS_STATE_MAP[connWrapper.networkSelectionMode] ||
AS_STATE.UNKNOWN;
},
onGetState: function() {
return Promise.resolve(AS_STATE_MAP[connWrapper.networkSelectionMode] ||
AS_STATE.UNKNOWN);
},
onSetState: function(state) {
switch (connWrapper.state) {
case MobileConnectionWrapper.STATE.IDLE:
if (state === AS_STATE.ENABLED) {
return connWrapper.setAutoSelection().then(() => {
return AS_STATE.ENABLED;
}, () => {
return Promise.reject(
AS_STATE_MAP[connWrapper.networkSelectionMode]);
});
} else {
return Promise.resolve(AS_STATE.DISABLED);
}
break;
case MobileConnectionWrapper.STATE.BUSY:
return this._getPendingRequest(state).promise;
}
},
_getPendingRequest: function(state) {
if (!this._pendingRequest) {
this._pendingRequest = Defer();
}
this._pendingRequest.state = state;
return this._pendingRequest;
},
_checkPendingRequest: function(newState) {
var pendingRequest = this._pendingRequest;
if (newState !== MobileConnectionWrapper.STATE.IDLE ||
pendingRequest === null) {
return;
}
this._pendingRequest = null;
switch (pendingRequest.state) {
case AS_STATE.ENABLED:
connWrapper.setAutoSelection().then(() => {
pendingRequest.resolve(AS_STATE.ENABLED);
}, () => {
pendingRequest.reject(
AS_STATE_MAP[connWrapper.networkSelectionMode]);
});
break;
case AS_STATE.DISABLED:
pendingRequest.resolve(AS_STATE.DISABLED);
break;
}
}
});
};
/**
* A static property. The enumeration of the possible states.
*
* @access public
* @memberOf AutoSelectionModel
* @type {Object}
*/
Object.defineProperty(AutoSelectionModel, 'STATE', {
get: function() {
return AS_STATE;
}
});
return AutoSelectionModel;
});

View file

@ -0,0 +1,204 @@
/**
* MobileConnectionWrapper wraps functions that are used in the operator
* settings panel.
* The responsibility of the module is to ensure all of the functions reject if
* the mobile connection is busy. This is important because calling to these
* functions when the mobile connection is busy gecko may return with unknown
* errors, so we need to ensure this won't happen.
* The module also reports the mobile connection state so that the other module
* can do some scheduling on the operations or reflecting it on the UI.
*
* @module panels/operator_settings/models/mobile_connection_wrapper
*/
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var Observable = require('modules/mvvm/observable');
// Mobile connection state
const STATE = {
IDLE: 0,
BUSY: 1
};
// A structure that makes a task cancelable. It rejects with 'canceled' if
// the task is canceled.
function Task(promise) {
var canceled = false;
var task = new Promise((resolve, reject) => {
promise.then((result) => {
if (!canceled) {
resolve(result);
} else {
reject('canceled');
}
}, (error) => {
if (!canceled) {
reject(error);
} else {
reject('canceled');
}
});
});
task.cancel = function() {
canceled = true;
};
return task;
}
/**
* @class MobileConnetionWrapper
* @requires module:modules/base/module
* @requires module:modules/mvvm/observable
* @params {MozMobileConnection} conn
* @returns {MobileConnetionWrapper}
*/
var Wrapper = Module.create(function MobileConnetionWrapper(conn) {
this.super(Observable).call(this);
this._conn = conn;
this._curSearch = null;
this._state = STATE.IDLE;
}).extend(Observable);
/**
* A static property. The enumeration of the possible states.
*
* @access public
* @memberOf MobileConnetionWrapper
* @type {Object}
*/
Object.defineProperty(Wrapper, 'STATE', {
get: function() {
return STATE;
}
});
/**
* An observable property indicating the state of the mobile connection.
*
* @access public
* @readonly
* @memberOf MobileConnetionWrapper.prototype
* @type {MobileConnetionWrapper.STATE}
*/
Observable.defineObservableProperty(Wrapper.prototype, 'state', {
readonly: true
});
/**
* A property indicating the network selection mode.
*
* @access public
* @readonly
* @memberOf MobileConnetionWrapper.prototype
* @type {String}
*/
Object.defineProperty(Wrapper.prototype, 'networkSelectionMode', {
get: function() {
return this._conn.networkSelectionMode;
}
});
/**
* Ask the mobile connection to serach available operators. It rejects if
* the mobile connection is busy.
* The search can be stopped by calling to `stop`. If it is stopped, the
* promise never resolves nor rejects.
*
* @access public
* @memberOf MobileConnetionWrapper.prototype
* @returns {Promise}
*/
Wrapper.prototype.search = function mcw_search() {
this.debug('search');
if (this._state !== STATE.IDLE) {
this.error('mobile connection is busy');
return Promise.reject('busy');
}
this._state = STATE.BUSY;
this._curSearch = Task(this._conn.getNetworks());
return this._curSearch.then((networks) => {
this.debug('search completed');
this._state = STATE.IDLE;
return networks;
}).catch((error) => {
this._state = STATE.IDLE;
if (error === 'canceled') {
this.debug('search canceled');
} else {
this.debug('search error: ' + error);
}
return Promise.reject(error);
});
};
/**
* Stop the current search if any.
*
* @access public
* @memberOf MobileConnetionWrapper.prototype
*/
Wrapper.prototype.stop = function mcw_stop() {
this.debug('stop');
if (this._curSearch) {
this._curSearch.cancel();
this._curSearch = null;
}
};
/**
* Connect to a network. It rejects if the mobile connection is busy.
*
* @access public
* @memberOf MobileConnetionWrapper.prototype
* @params {MozMobileNetworkInfo} network
* @returns {Promise}
*/
Wrapper.prototype.connect = function mcw_connect(network) {
this.debug('connect');
if (this._state !== STATE.IDLE) {
return Promise.reject('busy');
}
this._state = STATE.BUSY;
return this._conn.selectNetwork(network).then(() => {
this.debug('select network succeed');
this._state = STATE.IDLE;
}).catch((error) => {
this.debug('select network error: ' + error);
this._state = STATE.IDLE;
return Promise.reject(error);
});
};
/**
* Request to select an operator automatically. It rejects if the mobile
* connection is busy.
*
* @access public
* @memberOf MobileConnetionWrapper.prototype
* @returns {Promise}
*/
Wrapper.prototype.setAutoSelection = function mcw_setAutoSelection() {
this.debug('setAutoSelection');
if (this._state !== STATE.IDLE) {
return Promise.reject('busy');
}
this._state = STATE.BUSY;
return this._conn.selectNetworkAutomatically().then(() => {
this.debug('setAutoSelection succeed');
this._state = STATE.IDLE;
}).catch((error) => {
this.debug('setAutoSelection error: ' + error);
this._state = STATE.IDLE;
return Promise.reject(error);
});
};
return Wrapper;
});

View file

@ -0,0 +1,140 @@
/**
* NetworkTypeManager provides a supported network type list of a mobile
* connection. It wraps setPreferredNetworkType and is responsible for updating
* the settings field when setting preferred network types.
*
* @module panels/operator_settings/models/network_type_manager
*/
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var Observable = require('modules/mvvm/observable');
var ObservableArray = require('modules/mvvm/observable_array');
var SettingsHelper = require('shared/settings_helper');
var NetworkInfo = require('modules/mobile/supported_network_info');
const SETTINGS_KEY = 'ril.radio.preferredNetworkType';
/**
* @class NetworkTypeManager
* @requires module:modules/base/module
* @requires module:modules/mvvm/observable
* @requires module:modules/mvvm/observable_array
* @requires module:shared/settings_helper
* @params {MozMobileConnection} conn
* @returns {NetworkTypeManager}
*/
var NetworkTypeManager = Module.create(function NetworkTypeManager(conn) {
if (!conn.setPreferredNetworkType) {
this.throw(`mobile connection does not support settings preferred network
type`);
}
this.super(Observable).call(this);
this._conn = conn;
this._serviceId = [].indexOf.call(navigator.mozMobileConnections, conn);
this._networkTypes = ObservableArray([]);
this._supportedNetworkInfo = null;
this._settingsHelper = SettingsHelper(SETTINGS_KEY);
this._init(conn);
}).extend(Observable);
/**
* Available network types.
*
* @access public
* @readonly
* @memberOf NetworkTypeManager.prototype
* @type {ObservableArray.<String>}
*/
Object.defineProperty(NetworkTypeManager.prototype, 'networkTypes', {
enumerable: true,
get: function() {
return this._networkTypes;
}
});
/**
* An observable property indicating the preferred network type.
*
* @access public
* @readonly
* @memberOf NetworkTypeManager.prototype
* @type {String}
*/
Observable.defineObservableProperty(NetworkTypeManager.prototype,
'preferredNetworkType', {
readonly: true,
value: null
});
/**
* Initialize the supported network type list.
*
* @access private
* @memberOf NetworkTypeManager.prototype
* @returns {Promise}
*/
NetworkTypeManager.prototype._init = function() {
this.getSupportedNetworkInfo().then((info) => {
if (!info.networkTypes) {
return Promise.reject('not-supported');
}
this._networkTypes.reset(info.networkTypes);
return this._conn.getPreferredNetworkType();
}).then((preferredNetworkType) => {
this._preferredNetworkType = preferredNetworkType;
}).catch((error) => {
if (error === 'not-supported') {
this.debug('_init: not-supported');
} else {
this.error('_init: could not retrieve network type: ' + error);
}
});
};
/**
* Get the supported network types of the mobile connection. The object also
* contains a method for get a proper l10n id for each network type.
*
* @access public
* @memberOf NetworkTypeManager.prototype
* @returns {Promise}
*/
NetworkTypeManager.prototype.getSupportedNetworkInfo = function() {
if (this._supportedNetworkInfo) {
return Promise.resolve(this._supportedNetworkInfo);
} else {
return new Promise((resolve) => {
NetworkInfo.getSupportedNetworkInfo(this._conn, (info) => {
this._supportedNetworkInfo = info;
resolve(info);
});
});
}
};
/**
* Set the preferred newtork type and update the settings field accordingly.
*
* @access public
* @memberOf NetworkTypeManager.prototype
* @params {String} networkType
* @returns {Promise}
*/
NetworkTypeManager.prototype.setPreferredNetworkType = function(networkType) {
return this._conn.setPreferredNetworkType(networkType).then(() => {
this._settingsHelper.get((values) => {
values[this._serviceId] = networkType;
this._settingsHelper.set(values);
});
this._preferredNetworkType = networkType;
}, (error) => {
this.error('setPreferredNetworkType: ' + error);
});
};
return NetworkTypeManager;
});

View file

@ -0,0 +1,100 @@
/**
* OperatorItem is a model presenting the information and the current connecting
* status of an operator. OperatorManager is responsible for update the
* information of this type of objects.
*/
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var Observable = require('modules/mvvm/observable');
const STATE = {
IDLE: 'idle',
CONNECTING: 'connecting',
CONNECTED: 'connected',
FAILED: 'failed'
};
const TYPE = {
AVAILABLE: 'available',
FORBIDDEN: 'forbidden',
UNKNOWN: 'unknown'
};
var OperatorItem = Module.create(function OperatorItem(network) {
this.super(Observable).call(this);
this._network = network;
this._name = network.shortName || network.longName;
switch (network.state) {
case 'connected':
case 'current':
this._state = STATE.CONNECTED;
this._type = TYPE.AVAILABLE;
break;
case 'available':
this._state = STATE.IDLE;
this._type = TYPE.AVAILABLE;
break;
case 'forbidden':
this._state = STATE.IDLE;
this._type = TYPE.FORBIDDEN;
break;
default:
this._state = STATE.IDLE;
this._type = TYPE.UNKNOWN;
break;
}
this.observe('state', this._updateInfo.bind(this));
this._updateInfo();
}).extend(Observable);
Object.defineProperty(OperatorItem, 'STATE', {
get: function() {
return STATE;
}
});
Object.defineProperty(OperatorItem, 'TYPE', {
get: function() {
return TYPE;
}
});
Object.defineProperty(OperatorItem.prototype, 'name', {
get: function() {
return this._name;
}
});
Object.defineProperty(OperatorItem.prototype, 'network', {
get: function() {
return this._network;
}
});
Observable.defineObservableProperty(OperatorItem.prototype, 'state', {
readonly: true,
value: null
});
Observable.defineObservableProperty(OperatorItem.prototype, 'info', {
readonly: true,
value: ''
});
OperatorItem.prototype.setState = function oi_setState(state) {
this._state = state;
};
OperatorItem.prototype._updateInfo = function oi__updateInfo() {
// We display the type of the operator item if it is not connecting,
// otherwise we display the conection state.
this._info = this._state === STATE.IDLE ? this._type : this._state;
this._info = this._info || TYPE.UNKNOWN;
};
return OperatorItem;
});

View file

@ -0,0 +1,227 @@
/**
* OperatorManager manages the connection to operators. We can set automatic
* operator selection or serach for available operators for manual connection.
* The operator item provided in the list can actively report the connection
* state so it can be easily bound to UI elements.
*
* @module panels/operator_settings/models/operator_manager
*/
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var Observable = require('modules/mvvm/observable');
var ObservableArray = require('modules/mvvm/observable_array');
var OperatorItem = require('panels/operator_settings/models/operator_item');
var MobileConnectionWrapper =
require('panels/operator_settings/models/mobile_connection_wrapper');
var AutoSelectionModel =
require('panels/operator_settings/models/auto_selection_model');
const RECONNECT_TIMEOUT = 5000;
/**
* @class OperatorManager
* @requires module:modules/base/module
* @requires module:modules/mvvm/observable
* @requires module:modules/mvvm/observable_array
* @requires module:panels/operator_settings/models/operator_item
* @requires module:panels/operator_settings/models/mobile_connection_wrapper
* @requires module:panels/operator_settings/models/auto_selection_model
* @params {MozMobileConnection} conn
* @returns {OperatorManager}
*/
var OperatorManager = Module.create(function OperatorManager(conn) {
this.super(Observable).call(this);
this._connWrapper = MobileConnectionWrapper(conn);
this._operators = ObservableArray();
this._autoSelectionModel = AutoSelectionModel(this._connWrapper);
// bind the two properties.
this._autoSelectionState = this._autoSelectionModel.targetState;
this._autoSelectionModel.observe('targetState', (newState) => {
this._autoSelectionState = newState;
});
this.observe('_autoSelectionState', (newState) => {
this._autoSelectionModel.targetState = newState;
});
this.observe('_autoSelectionState', (newState) => {
if (newState === AutoSelectionModel.STATE.ENABLED) {
this._connectedOperatorItem = null;
} else if (newState === AutoSelectionModel.STATE.DISABLED) {
this.search();
}
});
this._connecting = false;
this._connectedOperatorItem = null;
}).extend(Observable);
/**
* A static property. The enumeration of the possible states.
*
* @access public
* @memberOf OperatorManager
* @type {Object}
*/
Object.defineProperty(OperatorManager, 'AUTO_SELECTION_STATE', {
get: function() {
return AutoSelectionModel.STATE;
}
});
/**
* The search result of the currently available operators.
*
* @access public
* @readonly
* @memberOf OperatorManager.prototype
* @type {ObservableArray.<OperatorItem>}
*/
Object.defineProperty(OperatorManager.prototype, 'operators', {
get: function() {
return this._operators;
}
});
/**
* An observable property indicating the automatic selection state.
*
* @access public
* @readonly
* @memberOf OperatorManager.prototype
* @type {OperatorManager.AUTO_SELECTION_STATE}
*/
Observable.defineObservableProperty(OperatorManager.prototype,
'autoSelectionState', {
readonly: true,
value: null
});
/**
* An observable property indicating the currently connected operator.
*
* @access public
* @readonly
* @memberOf OperatorManager.prototype
* @type {OperatorItem}
*/
Observable.defineObservableProperty(OperatorManager.prototype,
'connectedOperatorItem', {
readonly: true,
value: null
});
/**
* An observable property indicating the searching status.
*
* @access public
* @readonly
* @memberOf OperatorManager.prototype
* @type {Boolean}
*/
Observable.defineObservableProperty(OperatorManager.prototype,
'searching', {
readonly: true,
value: false
});
/**
* Request to search available operators and update the operator list.
*
* @access public
* @memberOf OperatorManager.prototype
* @returns {Promise}
*/
OperatorManager.prototype.search = function() {
if (this._searching) {
return Promise.resolve();
}
this.debug('search');
this._searching = true;
return this._connWrapper.search().then((networks) => {
networks = networks || [];
var operators = networks.map((network) => OperatorItem(network));
operators.forEach((operator) => {
if (operator.network.state === OperatorItem.STATE.CONNECTED) {
this._connectedOperatorItem = operator;
}
});
this._operators.reset(operators);
}).catch((error) => {
if (error !== 'busy') {
// keep the original operators if other errors.
this._operators.reset([]);
}
this.error('could not retrieve any network operator: ' + error);
}).then(() => {
this._searching = false;
});
};
/**
* Stop the search.
*
* @access public
* @memberOf OperatorManager.prototype
*/
OperatorManager.prototype.stop = function() {
this._connWrapper.stop();
this._searching = false;
};
/**
* Connect to a network. If it fails, reconnect to the original operator 5
* seconds later.
*
* @access public
* @memberOf OperatorManager.prototype
* @params {OperatorItem} operatorItem
* @returns {Promise}
*/
OperatorManager.prototype.connect = function(operatorItem) {
if (this._connecting || operatorItem === this._connectedOperatorItem) {
return Promise.resolve();
}
this.debug('connect');
this._connecting = true;
operatorItem.setState(OperatorItem.STATE.CONNECTING);
return this._connWrapper.connect(operatorItem.network).then(() => {
operatorItem.setState(OperatorItem.STATE.CONNECTED);
this._connectedOperatorItem = operatorItem;
}).catch((error) => {
this.error('unable to connect to the network: ' + error);
operatorItem.setState(OperatorItem.STATE.FAILED);
// recover the connection
setTimeout(function(originalOperatorItem) {
operatorItem.setState(OperatorItem.STATE.IDLE);
if (originalOperatorItem &&
this.autoSelectionState === AutoSelectionModel.STATE.DISABLED) {
this.connect(originalOperatorItem);
}
}.bind(this, this._connectedOperatorItem), RECONNECT_TIMEOUT);
}).then(() => {
this._connecting = false;
});
};
/**
* Request to select an operator automatically.
*
* @access public
* @memberOf OperatorManager.prototype
* @params {Boolean} enabled
*/
OperatorManager.prototype.setAutoSelection = function(enabled) {
this.debug('setAutoSelection: ' + enabled);
this._autoSelectionModel.targetState = enabled ?
AutoSelectionModel.STATE.ENABLED : AutoSelectionModel.STATE.DISABLED;
};
return OperatorManager;
});

View file

@ -0,0 +1,99 @@
/**
* PanelModel determines the current connecting mode based on the the voice type
* and hardware supported network modes.
*
* @module panels/operator_settings/models/panel_model
*/
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var Observable = require('modules/mvvm/observable');
var NetworkInfo = require('modules/mobile/supported_network_info');
const NETWORK_TYPE_CATEGORY = {
'gprs': 'gsm',
'edge': 'gsm',
'umts': 'gsm',
'hsdpa': 'gsm',
'hsupa': 'gsm',
'hspa': 'gsm',
'hspa+': 'gsm',
'lte': 'gsm',
'gsm': 'gsm',
'is95a': 'cdma',
'is95b': 'cdma',
'1xrtt': 'cdma',
'evdo0': 'cdma',
'evdoa': 'cdma',
'evdob': 'cdma',
'ehrpd': 'cdma'
};
/**
* @class OperatorSettingsPanelModel
* @requires module:modules/base/module
* @requires module:modules/mvvm/observable
* @params {MozMobileConnection} conn
* @returns {OperatorSettingsPanelModel}
*/
var PanelModel = Module.create(function OperatorSettingsPanelModel(conn) {
this.super(Observable).call(this);
this._voiceType = conn.voice && conn.voice.type;
NetworkInfo.getSupportedNetworkInfo(conn, (result) => {
if (result.gsm || result.wcdma || result.lte) {
this._hardwareSupportedMode = 'gsm';
} else {
this._hardwareSupportedMode = 'cdma';
}
});
conn.addEventListener('voicechange', () => {
this._voiceType = conn.voice && conn.voice.type;
});
}).extend(Observable);
/**
* An observable property indicating the hardware supported network mode.
*
* @access private
* @memberOf OperatorSettingsPanelModel.prototype
* @type {String}
*/
Observable.defineObservableProperty(PanelModel.prototype,
'_hardwareSupportedMode', {
value: null
});
/**
* An observable property indicating the current connected voice type.
*
* @access private
* @memberOf OperatorSettingsPanelModel.prototype
* @type {String}
*/
Observable.defineObservableProperty(PanelModel.prototype, '_voiceType', {
value: null
});
/**
* An observable property indicating the current connecting mode. The possible
* values are 'gsm' and 'cdma'.
*
* @access public
* @memberOf OperatorSettingsPanelModel.prototype
* @type {String}
*/
Observable.defineObservableProperty(PanelModel.prototype, 'connectingMode', {
dependency: ['_voiceType', '_hardwareSupportedMode'],
get: function() {
if (this._voiceType) {
return NETWORK_TYPE_CATEGORY[this._voiceType];
} else {
return this._hardwareSupportedMode;
}
}
});
return PanelModel;
});

View file

@ -0,0 +1,85 @@
/**
* RoamingPreferenceManager provides functions for setting roaming preference
* and update the settings fiels accordingly.
*
* @module panels/operator_settings/models/roaming_preference_manager
*/
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var Observable = require('modules/mvvm/observable');
var SettingsHelper = require('shared/settings_helper');
const SETTINGS_KEY = 'ril.roaming.preference';
/**
* @class RoamingPreferenceManager
* @requires module:modules/base/module
* @requires module:modules/mvvm/observable
* @requires module:shared/settings_helper
* @params {MozMobileConnection} conn
* @returns {RoamingPreferenceManager}
*/
var RoamingPreferenceManager =
Module.create(function RoamingPreferenceManager(conn) {
if (!conn.setRoamingPreference) {
this.throw(`mobile connection does not support setting roaming
preference`);
}
this.super(Observable).call(this);
this._conn = conn;
this._serviceId = [].indexOf.call(navigator.mozMobileConnections, conn);
var defaultRoamingPreferences =
[].map.call(navigator.mozMobileConnections, () => { return 'any'; });
this._settingsHelper =
SettingsHelper(SETTINGS_KEY, defaultRoamingPreferences);
this._init(conn);
}).extend(Observable);
/**
* An observable property indicating the current preference.
*
* @access public
* @readonly
* @memberOf RoamingPreferenceManager.prototype
* @type {String}
*/
Observable.defineObservableProperty(RoamingPreferenceManager.prototype,
'preference', {
readonly: true,
value: null
});
RoamingPreferenceManager.prototype._init = function(conn) {
this._conn.getRoamingPreference().then((preference) => {
this._preference = preference;
}).catch((error) => {
this.error('_init: could not retrieve roaming preference type: ' + error);
});
};
/**
* Set the preference and update the settings field accordingly.
*
* @access public
* @memberOf RoamingPreferenceManager.prototype
* @params {String} pref
* @returns {Promise}
*/
RoamingPreferenceManager.prototype.setRoamingPreference = function(pref) {
return this._conn.setRoamingPreference(pref).then(() => {
this._settingsHelper.get((values) => {
values[this._serviceId] = pref;
this._settingsHelper.set(values);
});
this._preference = pref;
}, (error) => {
this.error('setRoamingPreference: ' + error);
});
};
return RoamingPreferenceManager;
});

View file

@ -0,0 +1,142 @@
define(function(require) {
'use strict';
var SettingsPanel = require('modules/settings_panel');
var DsdsSettings = require('dsds_settings');
// Models
var PanelModel = require('panels/operator_settings/models/panel_model');
var NetworkTypeManager =
require('panels/operator_settings/models/network_type_manager');
var RoamingPreferenceManager =
require('panels/operator_settings/models/roaming_preference_manager');
var OperatorManager =
require('panels/operator_settings/models/operator_manager');
// Views
var NetworkTypeSelector =
require('panels/operator_settings/views/network_type_selector');
var RoamingPreferenceSelector =
require('panels/operator_settings/views/roaming_preference_selector');
var AutoSelectionCheckbox =
require('panels/operator_settings/views/auto_selection_checkbox');
var AvailableOperatorList =
require('panels/operator_settings/views/available_operator_list');
return function() {
return SettingsPanel({
onInit: function(panel) {
this._panel = panel;
this._elements = {
header: panel.querySelector('gaia-header'),
networkTypeSelector:
panel.querySelector('.preferred-network-type select'),
roamingPreferenceMenuItem:
panel.querySelector('.operator-roaming-preference'),
roamingPreferenceSelector:
panel.querySelector('.operator-roaming-preference select'),
autoSelectionMenuItem: panel.querySelector('.auto-select'),
autoSelectionCheckbox: panel.querySelector(
'.auto-select gaia-switch'),
availableOperators: panel.querySelector('.available-operators')
};
if (navigator.mozMobileConnections.length > 1) {
this._elements.header.dataset.href = '#carrier-detail';
} else {
this._elements.header.dataset.href = '#carrier';
}
// Create the view modules for each part.
this._networkTypeSelector =
NetworkTypeSelector(this._elements.networkTypeSelector);
this._roamingPreferenceSelector =
RoamingPreferenceSelector(this._elements.roamingPreferenceSelector);
this._autoSelectionCheckbox =
AutoSelectionCheckbox(this._elements.autoSelectionCheckbox);
this._availableOperatorList =
AvailableOperatorList(this._elements.availableOperators);
this._boundOnConnectingModeChange =
this._onConnectingModeChange.bind(this);
},
onBeforeShow: function(panel) {
var serviceId = DsdsSettings.getIccCardIndexForCellAndDataSettings();
var panelModel = this._getInstance(PanelModel, serviceId);
var operatorManager = this._getInstance(OperatorManager, serviceId);
var roamingPreferenceManager =
this._getInstance(RoamingPreferenceManager, serviceId);
var networkTypeManager =
this._getInstance(NetworkTypeManager, serviceId);
// When auto selection state changes, we need to update the visibility
// of the selectors of preferred network types and roaming preferences.
this._setPanelModel(panelModel);
// Link the manager corresponding to the current mobile connection to
// the view modules.
this._availableOperatorList.init(operatorManager);
this._roamingPreferenceSelector.init(roamingPreferenceManager);
this._autoSelectionCheckbox.init(operatorManager);
// init of this._networkTypeSelector returns a promise.
return this._networkTypeSelector.init(networkTypeManager);
},
onHide: function() {
this._setPanelModel(null);
this._networkTypeSelector.uninit();
this._roamingPreferenceSelector.uninit();
this._autoSelectionCheckbox.uninit();
this._availableOperatorList.uninit();
},
/**
* Returns the instance of ctor corrsponding to serviceId
*
* @params {Function} ctor
* A constructor.
* @params {Number} serviceId
* @returns {Object}
*/
_getInstance: function(ctor, serviceId) {
if (!this._instances) {
this._instances = new Map();
}
if (!this._instances.has(ctor)) {
this._instances.set(ctor, {});
}
// Only create one instance per a service id.
var instance = this._instances.get(ctor)[serviceId];
if (!instance) {
var conn = navigator.mozMobileConnections[serviceId];
instance = ctor(conn);
this._instances.get(ctor)[serviceId] = instance;
}
return instance;
},
_setPanelModel: function(panelModel) {
if (this._panelModel) {
this._panelModel.unobserve('connectingMode',
this._boundOnConnectingModeChange);
}
this._panelModel = panelModel;
if (this._panelModel) {
this._panelModel = panelModel;
panelModel.observe('connectingMode',
this._boundOnConnectingModeChange);
this._onConnectingModeChange(panelModel.connectingMode);
}
},
_onConnectingModeChange: function(mode) {
// Roaming preference is only available on CDMA devices and operator
// selection is only availabe on GSM devices. For world phones we update
// the visibility of the items based on the current connecting mode.
this._elements.roamingPreferenceMenuItem.hidden = (mode !== 'cdma');
this._elements.autoSelectionMenuItem.hidden =
this._elements.availableOperators.hidden = (mode !== 'gsm');
}
});
};
});

View file

@ -0,0 +1,43 @@
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var OperatorManager =
require('panels/operator_settings/models/operator_manager');
var AutoSelectionCheckbox =
Module.create(function AutoSelectionCheckbox(root) {
this._root = root;
this._manager = null;
this._root.addEventListener('change', () => {
this._manager.setAutoSelection(this._root.checked);
});
this._boundUpdate = this._update.bind(this);
});
AutoSelectionCheckbox.prototype._update = function(state) {
this._root.checked =
state === OperatorManager.AUTO_SELECTION_STATE.ENABLED ||
state === OperatorManager.AUTO_SELECTION_STATE.ENABLING;
};
AutoSelectionCheckbox.prototype.init = function(manager) {
this._manager = manager;
if (!this._manager) {
return;
}
this._manager.observe('autoSelectionState', this._boundUpdate);
this._boundUpdate(this._manager.autoSelectionState);
};
AutoSelectionCheckbox.prototype.uninit = function() {
if (!this._manager) {
return;
}
this._manager.unobserve('autoSelectionState', this._boundUpdate);
this._manager = null;
};
return AutoSelectionCheckbox;
});

View file

@ -0,0 +1,110 @@
define(function(require) {
'use strict';
var ListView = require('modules/mvvm/list_view');
var OperatorManager =
require('panels/operator_settings/models/operator_manager');
var OperatorItemTemplate =
require('panels/operator_settings/views/operator_item_template');
function AvailableOperatorList(root) {
this._operatorManager = null;
this._root = root;
this._elements = {
operatorListRoot: root.querySelector('.available-operators-list'),
searchBtnListItem: root.querySelector('.search-btn-li'),
searchBtn: root.querySelector('.search-btn'),
operatorListInfo: root.querySelector('.search-info')
};
this._operatorListView =
ListView(this._elements.operatorListRoot, null,
OperatorItemTemplate((operatorItem) => {
this._operatorManager.connect(operatorItem);
}));
this._elements.searchBtn.addEventListener('click', () => {
this._operatorManager.search();
});
this._boundUpdateVisibility = this._updateVisibility.bind(this);
this._boundUpdateInfo = this._updateInfo.bind(this);
}
AvailableOperatorList.prototype.init = function(operatorManager) {
this._operatorManager = operatorManager;
if (!this._operatorManager) {
return;
}
// When auto selection state changes, we need to update the visibility of
// the items.
this._operatorManager.observe('autoSelectionState',
this._boundUpdateVisibility);
this._boundUpdateVisibility(this._operatorManager.autoSelectionState);
// Update the information.
this._operatorManager.observe('autoSelectionState',
this._boundUpdateInfo);
this._operatorManager.observe('searching', this._boundUpdateInfo);
this._boundUpdateInfo();
this._operatorListView.set(this._operatorManager.operators);
this._operatorListView.enabled = true;
};
AvailableOperatorList.prototype.uninit = function() {
if (!this._operatorManager) {
return;
}
this._operatorManager.unobserve('autoSelectionState',
this._boundUpdateVisibility);
this._operatorManager.unobserve('autoSelectionState',
this._boundUpdateInfo);
this._operatorManager.unobserve('searching', this._boundUpdateInfo);
this._operatorListView.set(null);
this._operatorListView.enabled = false;
this._operatorManager = null;
};
AvailableOperatorList.prototype._updateVisibility =
function(autoSelectionState) {
switch (autoSelectionState) {
case OperatorManager.AUTO_SELECTION_STATE.ENABLED:
this._elements.operatorListRoot.hidden = true;
this._elements.searchBtnListItem.hidden = true;
break;
case OperatorManager.AUTO_SELECTION_STATE.DISABLED:
this._elements.operatorListRoot.hidden = false;
this._elements.searchBtnListItem.hidden = false;
break;
}
};
AvailableOperatorList.prototype._updateInfo = function() {
switch (this._operatorManager.autoSelectionState) {
case OperatorManager.AUTO_SELECTION_STATE.ENABLED:
this._elements.operatorListInfo.hidden = false;
this._elements.operatorListInfo
.setAttribute('data-l10n-id', 'operator-turnAutoSelectionOff');
break;
case OperatorManager.AUTO_SELECTION_STATE.DISABLED:
if (this._operatorManager.searching) {
this._elements.operatorListInfo.hidden = false;
this._elements.operatorListInfo
.setAttribute('data-l10n-id', 'scanning');
} else {
this._elements.operatorListInfo.hidden = true;
}
break;
}
};
return function(root) {
return new AvailableOperatorList(root);
};
});

View file

@ -0,0 +1,35 @@
define(function(require) {
'use strict';
function Template(networkTypeMap, networkType, recycled) {
/**
* A network list item has the following HTML structure:
* <option>
* Network Type
* </option>
*/
var container = null;
if (recycled) {
container = recycled;
} else {
container = document.createElement('option');
}
container.value = networkType;
var textInfo = networkTypeMap(networkType);
if (textInfo.l10nId) {
container.setAttribute('data-l10n-id', textInfo.l10nId);
} else if (textInfo.text) {
container.textContent = textInfo.text;
} else {
container.textContent = networkType;
}
return container;
}
return function TemplateFactory(networkTypeMap) {
return Template.bind(null, networkTypeMap);
};
});

View file

@ -0,0 +1,88 @@
define(function(require) {
'use strict';
var DialogService = require('modules/dialog_service');
var Module = require('modules/base/module');
var CustomizedNetworkTypeMap = require('modules/customized_network_type_map');
var ListView = require('modules/mvvm/list_view');
var NetworkTypeItemTemplate =
require('panels/operator_settings/views/network_type_item_template');
var NetworkTypeSelector = Module.create(function NetworkTypeSelector(root) {
this._root = root;
this._manager = null;
this._customizedNetworkTypeMap = null;
this._networkTypeMap = null;
var networkTypeItemTemplate =
NetworkTypeItemTemplate(this._getTextInfoForNetworkType.bind(this));
this._networkTypeOptions =
ListView(this._root, null, networkTypeItemTemplate);
this._root.addEventListener('blur', () => {
this._manager.setPreferredNetworkType(this._root.value).catch(() => {
DialogService.alert('preferredNetworkTypeAlertErrorMessage', {
title: 'preferredNetworkTypeAlertTitle'
});
});
});
this._boundUpdateSelector = this._updateSelector.bind(this);
});
NetworkTypeSelector.prototype._getTextInfoForNetworkType = function(type) {
if (this._customizedNetworkTypeMap &&
type in this._customizedNetworkTypeMap) {
return {
text: this._customizedNetworkTypeMap[type]
};
} else if (this._networkTypeMap) {
return {
l10nId: this._networkTypeMap(type)
};
} else {
return type;
}
};
NetworkTypeSelector.prototype._updateSelector = function(type) {
this._root.value = type;
};
NetworkTypeSelector.prototype.init = function(networkTypeManager) {
this._manager = networkTypeManager;
if (!this._manager) {
return;
}
return CustomizedNetworkTypeMap.get().then((customizedMap) => {
this._customizedNetworkTypeMap = customizedMap;
}).then(() => {
return this._manager.getSupportedNetworkInfo();
}).then((info) => {
this._networkTypeMap = info.l10nIdForType;
this._networkTypeOptions.set(this._manager.networkTypes);
this._networkTypeOptions.enabled = true;
// When auto selection state changes, we need to update the visibility of
// the items.
this._manager.observe('preferredNetworkType', this._boundUpdateSelector);
this._updateSelector(this._manager.preferredNetworkType);
});
};
NetworkTypeSelector.prototype.uninit = function() {
if (!this._manager) {
return;
}
this._manager.unobserve('preferredNetworkType', this._boundUpdateSelector);
this._networkTypeOptions.set(null);
this._networkTypeOptions.enabled = false;
this._manager = null;
};
return NetworkTypeSelector;
});

View file

@ -0,0 +1,54 @@
define(function(require) {
'use strict';
function OperatorItemTemplate(onItemClick, operatorItem, recycled) {
/**
* A network list item has the following HTML structure:
* <li>
* <a>
* <span>Network Name</span>
* <small>Network Info</small>
* </a>
* </li>
*/
var container = null;
var name;
var info;
var link;
if (recycled) {
container = recycled;
name = container.querySelector('span');
info = container.querySelector('small');
link = container.querySelector('a');
} else {
name = document.createElement('span');
info = document.createElement('small');
link = document.createElement('a');
container = document.createElement('li');
link.appendChild(name);
link.appendChild(info);
container.appendChild(link);
container.classList.add('operatorItem');
}
name.textContent = operatorItem.name;
operatorItem.observe('info', function() {
info.setAttribute('data-l10n-id', 'operator-info-' + operatorItem.info);
});
info.setAttribute('data-l10n-id', 'operator-info-' + operatorItem.info);
if (typeof onItemClick === 'function') {
container.onclick = function() {
onItemClick(operatorItem);
};
}
return container;
}
return function OperatorItemTemplateFactory(onItemClick) {
return OperatorItemTemplate.bind(null, onItemClick);
};
});

View file

@ -0,0 +1,39 @@
define(function(require) {
'use strict';
var Module = require('modules/base/module');
var RoamingPreferenceSelector =
Module.create(function RoamingPreferenceSelector(root) {
this._root = root;
this._manager = null;
this._root.addEventListener('blur', () => {
this._manager.setRoamingPreference(this._root.value);
});
this._boundUpdateSelector = this._updateSelector.bind(this);
});
RoamingPreferenceSelector.prototype._updateSelector = function(preference) {
this._root.value = preference;
};
RoamingPreferenceSelector.prototype.init = function(manager) {
this._manager = manager;
if (!this._manager) {
return;
}
this._manager.observe('preference', this._boundUpdateSelector);
this._boundUpdateSelector(this._manager.preference);
};
RoamingPreferenceSelector.prototype.uninit = function() {
if (!this._manager) {
return;
}
this._manager.unobserve('preference', this._boundUpdateSelector);
this._manager = null;
};
return RoamingPreferenceSelector;
});