Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
284 lines
8.3 KiB
JavaScript
284 lines
8.3 KiB
JavaScript
/* global SIMSlotManager, Service, BaseModule, applications */
|
|
'use strict';
|
|
|
|
(function(exports) {
|
|
var SimLockManager = function(core) {
|
|
this.mobileConnections = core.mobileConnections;
|
|
};
|
|
SimLockManager.EVENTS = [
|
|
'simslotready',
|
|
'ftuopen',
|
|
'appopened',
|
|
'lockscreen-request-unlock',
|
|
'simslot-updated',
|
|
'simslot-cardstatechange',
|
|
'simslot-iccinfochange',
|
|
'attentionopening',
|
|
'attentionterminated',
|
|
'simlockskip',
|
|
'simlockback',
|
|
'simlockrequestclose',
|
|
'airplanemode-enabled',
|
|
'rocketbar-activating'
|
|
];
|
|
SimLockManager.SUB_MODULES = [
|
|
'SimLockSystemDialog'
|
|
];
|
|
BaseModule.create(SimLockManager, {
|
|
name: 'SimLockManager',
|
|
_duringCall: false,
|
|
_showPrevented: false,
|
|
_alreadyShown: false,
|
|
|
|
_handle_simslotready: function() {
|
|
this.showIfLocked();
|
|
},
|
|
|
|
_sim_lock_system_dialog_loaded: function() {
|
|
this.showIfLocked();
|
|
},
|
|
|
|
'_handle_simslot-updated': function(evt) {
|
|
this.showIfLocked(evt.detail.index);
|
|
},
|
|
|
|
'_handle_simslot-iccinfochange': function(evt) {
|
|
this.showIfLocked(evt.detail.index);
|
|
},
|
|
|
|
'_handle_simslot-cardstatechange': function(evt) {
|
|
this.showIfLocked(evt.detail.index);
|
|
},
|
|
|
|
'_handle_ftuopen': function() {
|
|
if (this.service.query('justUpgraded') === false) {
|
|
this.simLockSystemDialog.close();
|
|
} else {
|
|
this.showIfLocked();
|
|
}
|
|
},
|
|
|
|
_handle_simlockback: function(evt) {
|
|
var index = evt.detail._currentSlot.index;
|
|
this.showIfLocked(index - 1, false);
|
|
},
|
|
|
|
_handle_simlockskip: function(evt) {
|
|
var index = evt.detail._currentSlot.index;
|
|
if (index + 1 > this.mobileConnections.length - 1) {
|
|
evt.detail.close('skip');
|
|
} else {
|
|
if (!this.showIfLocked(index + 1, true)) {
|
|
evt.detail.close('skip');
|
|
}
|
|
}
|
|
},
|
|
|
|
_handle_simlockrequestclose: function(evt) {
|
|
var index = evt.detail._currentSlot.index;
|
|
if (index + 1 > this.mobileConnections.length - 1) {
|
|
evt.detail.close();
|
|
} else {
|
|
if (!this.showIfLocked(index + 1, false)) {
|
|
evt.detail.close();
|
|
}
|
|
}
|
|
},
|
|
|
|
_handle_attentionopening: function(evt) {
|
|
if (evt.detail.CLASS_NAME !== 'CallscreenWindow') {
|
|
return;
|
|
}
|
|
this._duringCall = true;
|
|
},
|
|
|
|
_handle_attentionterminated: function(evt) {
|
|
if (evt.detail.CLASS_NAME !== 'CallscreenWindow') {
|
|
return;
|
|
}
|
|
this._duringCall = false;
|
|
if (this._showPrevented) {
|
|
this._showPrevented = false;
|
|
|
|
// We show the SIM dialog right away otherwise the user won't
|
|
// be able to receive calls.
|
|
this.showIfLocked();
|
|
}
|
|
},
|
|
|
|
'_handle_lockscreen-request-unlock': function(evt) {
|
|
// Check whether the lock screen was unlocked from the camera or not.
|
|
// If the former is true, the SIM PIN dialog should not displayed after
|
|
// unlock, because the camera will be opened (Bug 849718)
|
|
if (evt.detail && evt.detail.activity &&
|
|
'record' === evt.detail.activity.name) {
|
|
this.simLockSystemDialog.close();
|
|
return;
|
|
}
|
|
var self = this;
|
|
// We should wait for lockscreen-appclosed event sent before checking
|
|
// the value of Service.query('locked') in showIfLocked method.
|
|
window.addEventListener('lockscreen-appclosed',
|
|
function lockscreenOnClosed() {
|
|
window.removeEventListener('lockscreen-appclosed',
|
|
lockscreenOnClosed);
|
|
self.showIfLocked();
|
|
});
|
|
},
|
|
|
|
_handle_appopened: function(evt) {
|
|
// If an app needs 'telephony' or 'sms' permissions (i.e. mobile
|
|
// connection) and the SIM card is locked, the SIM PIN unlock screen
|
|
// should be launched
|
|
|
|
var app = evt.detail;
|
|
|
|
if (!app || !app.manifest || !app.manifest.permissions) {
|
|
return;
|
|
}
|
|
|
|
// Ignore apps that don't require a mobile connection
|
|
if (!('telephony' in app.manifest.permissions ||
|
|
'sms' in app.manifest.permissions)) {
|
|
return;
|
|
}
|
|
|
|
// If the Settings app will open, don't prompt for SIM PIN entry
|
|
// although it has 'telephony' permission (Bug 861206)
|
|
var settingsManifestURL =
|
|
'app://settings.gaiamobile.org/manifest.webapp';
|
|
if (app.manifestURL == settingsManifestURL) {
|
|
if (this.simLockSystemDialog.visible) {
|
|
this.simLockSystemDialog.close();
|
|
}
|
|
return;
|
|
}
|
|
|
|
// If SIM is locked, cancel app opening in order to display
|
|
// it after the SIM PIN dialog is shown
|
|
this.showIfLocked();
|
|
// XXX: We don't block the app from launching if it requires SIM
|
|
// but only put the SIM PIN dialog upon the opening/opened app.
|
|
// Will revisit this in
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=SIMPIN-Dialog
|
|
},
|
|
|
|
'_handle_airplanemode-enabled': function(evt) {
|
|
this.simLockSystemDialog.close();
|
|
this._alreadyShown = false;
|
|
},
|
|
|
|
'_handle_rocketbar-activating': function(evt) {
|
|
this.simLockSystemDialog.close();
|
|
this._alreadyShown = false;
|
|
},
|
|
|
|
isBothSlotsLocked: function sl_isBothSlotsLocked() {
|
|
if (!SIMSlotManager.isMultiSIM() ||
|
|
SIMSlotManager.hasOnlyOneSIMCardDetected()) {
|
|
return false;
|
|
}
|
|
|
|
var simSlots = SIMSlotManager.getSlots();
|
|
var isBothLocked = true;
|
|
for (var i = 0; i < simSlots.length; i++) {
|
|
var currentSlot = simSlots[i];
|
|
var unknownState = currentSlot.isUnknownState();
|
|
var currentLocked = currentSlot.isLocked() || unknownState;
|
|
isBothLocked = isBothLocked && currentLocked;
|
|
}
|
|
return isBothLocked;
|
|
},
|
|
|
|
showIfLocked: function sl_showIfLocked(currentSlotIndex, skipped) {
|
|
if (!SIMSlotManager.ready) {
|
|
this.warn('SIMSlot not ready yet.');
|
|
return false;
|
|
}
|
|
|
|
if (!this.simLockSystemDialog) {
|
|
this.warn('dialog not ready.');
|
|
return false;
|
|
}
|
|
|
|
if (Service.query('locked')) {
|
|
this.warn('Lockscreen is on so hidden.');
|
|
return false;
|
|
}
|
|
|
|
if (currentSlotIndex === null && this.simLockSystemDialog.visible) {
|
|
this.warn('Already displayed.');
|
|
return false;
|
|
}
|
|
|
|
// FTU has its specific SIM PIN UI
|
|
if (this.service.query('isFtuRunning') &&
|
|
!this.service.query('justUpgraded')) {
|
|
this.warn('Running full ftu.');
|
|
this.simLockSystemDialog.close();
|
|
return false;
|
|
}
|
|
|
|
if (this._duringCall) {
|
|
this.warn('During call');
|
|
this._showPrevented = true;
|
|
return false;
|
|
}
|
|
|
|
if (!applications.ready) {
|
|
return false;
|
|
}
|
|
|
|
return SIMSlotManager.getSlots().some(function iterator(slot, index) {
|
|
// If currentSlotIndex is present then we just need to handle this slot
|
|
if (currentSlotIndex && index !== currentSlotIndex) {
|
|
return false;
|
|
}
|
|
|
|
if (!slot.simCard) {
|
|
this.warn('No SIM card in slot ' + (index + 1));
|
|
return false;
|
|
}
|
|
|
|
// Only render if not already displaying, or
|
|
// displaying and skipping
|
|
if (skipped == null && this.simLockSystemDialog.visible) {
|
|
return false;
|
|
}
|
|
|
|
// Always showing the first slot first.
|
|
if (!this._alreadyShown && this.isBothSlotsLocked() && index > 0) {
|
|
return false;
|
|
}
|
|
|
|
switch (slot.getCardState()) {
|
|
// do nothing in either unknown or null card states
|
|
case null:
|
|
case 'unknown':
|
|
this.warn('unknown SIM card state for slot ' + (index + 1));
|
|
break;
|
|
case 'pukRequired':
|
|
case 'pinRequired':
|
|
this.simLockSystemDialog.show(slot, skipped);
|
|
this._alreadyShown = true;
|
|
return true;
|
|
case 'networkLocked':
|
|
case 'corporateLocked':
|
|
case 'serviceProviderLocked':
|
|
case 'network1Locked':
|
|
case 'network2Locked':
|
|
case 'hrpdNetworkLocked':
|
|
case 'ruimCorporateLocked':
|
|
case 'ruimServiceProviderLocked':
|
|
this.simLockSystemDialog.show(slot, skipped);
|
|
this._alreadyShown = true;
|
|
return true;
|
|
default:
|
|
this.warn('SIM slot ' + (index + 1) + ' is not locked, skipping');
|
|
return false;
|
|
}
|
|
}, this);
|
|
}
|
|
});
|
|
}());
|
|
|