diff --git a/apps/settings/js/call_iccs.js b/apps/settings/js/call_iccs.js index 29e66ab85e73..8ed2a35b5487 100644 --- a/apps/settings/js/call_iccs.js +++ b/apps/settings/js/call_iccs.js @@ -12,6 +12,7 @@ var IccHandlerForCallSettings = (function(window, document, undefined) { var CARDSTATE_MAPPING = { 'pinRequired' : 'simCardLockedMsg', 'pukRequired' : 'simCardLockedMsg', + 'permanentBlocked': 'simCardBlockedMsg', 'networkLocked' : 'simLockedPhone', 'serviceProviderLocked' : 'simLockedPhone', 'corporateLocked' : 'simLockedPhone', diff --git a/apps/settings/js/carrier_iccs.js b/apps/settings/js/carrier_iccs.js index 7405eed40584..7016ac7e6bf6 100644 --- a/apps/settings/js/carrier_iccs.js +++ b/apps/settings/js/carrier_iccs.js @@ -12,6 +12,7 @@ var IccHandlerForCarrierSettings = (function(window, document, undefined) { var CARDSTATE_MAPPING = { 'pinRequired' : 'simCardLockedMsg', 'pukRequired' : 'simCardLockedMsg', + 'permanentBlocked': 'simCardBlockedMsg', 'networkLocked' : 'simLockedPhone', 'serviceProviderLocked' : 'simLockedPhone', 'corporateLocked' : 'simLockedPhone', diff --git a/apps/settings/js/simcard_manager.js b/apps/settings/js/simcard_manager.js index 5e182d314b15..591b3cfb3f12 100644 --- a/apps/settings/js/simcard_manager.js +++ b/apps/settings/js/simcard_manager.js @@ -36,6 +36,7 @@ this.addVoiceChangeEventOnConns(); this.addCardStateChangeEventOnIccs(); + this.addLocalizedChangeEventOnIccs(); // because in fugu, airplaneMode will not change cardState // but we still have to make UI consistent. In this way, @@ -173,7 +174,7 @@ }, initSimCardManagerUI: function() { this.initSimCardsUI(); - this.initSelectOptionsUI(); + this.updateSelectOptionsUI(); // we only inject basic DOM from templates before // , so we have to map UI to its info @@ -208,8 +209,7 @@ localize(this.simManagerSecurityDesc); } }, - initSelectOptionsUI: function() { - + updateSelectOptionsUI: function() { var firstCardInfo = this.simcards[0].getInfo(); var secondCardInfo = this.simcards[1].getInfo(); @@ -217,19 +217,19 @@ if (!firstCardInfo.absent && !secondCardInfo.absent) { SimSettingsHelper.getCardIndexFrom('outgoingCall', function(cardIndex) { - this.initSelectOptionUI('outgoingCall', cardIndex, + this.updateSelectOptionUI('outgoingCall', cardIndex, this.simManagerOutgoingCallSelect); }.bind(this)); SimSettingsHelper.getCardIndexFrom('outgoingMessages', function(cardIndex) { - this.initSelectOptionUI('outgoingMessages', cardIndex, + this.updateSelectOptionUI('outgoingMessages', cardIndex, this.simManagerOutgoingMessagesSelect); }.bind(this)); SimSettingsHelper.getCardIndexFrom('outgoingData', function(cardIndex) { - this.initSelectOptionUI('outgoingData', cardIndex, + this.updateSelectOptionUI('outgoingData', cardIndex, this.simManagerOutgoingDataSelect); }.bind(this)); } else { @@ -257,15 +257,21 @@ this.simManagerOutgoingDataSelect.disabled = true; // then change related UI - this.initSelectOptionUI('outgoingCall', selectedCardIndex, + this.updateSelectOptionUI('outgoingCall', selectedCardIndex, this.simManagerOutgoingCallSelect); - this.initSelectOptionUI('outgoingMessages', selectedCardIndex, + this.updateSelectOptionUI('outgoingMessages', selectedCardIndex, this.simManagerOutgoingMessagesSelect); - this.initSelectOptionUI('outgoingData', selectedCardIndex, + this.updateSelectOptionUI('outgoingData', selectedCardIndex, this.simManagerOutgoingDataSelect); } }, - initSelectOptionUI: function(storageKey, selectedCardIndex, selectDOM) { + updateSelectOptionUI: function(storageKey, selectedCardIndex, selectDOM) { + // We have to remove old options first + while (selectDOM.firstChild) { + selectDOM.removeChild(selectDOM.firstChild); + } + + // then insert the new ones this.simcards.forEach(function(simcard, index) { var simcardInfo = simcard.getInfo(); var option = document.createElement('option'); @@ -297,7 +303,6 @@ } }, isSimCardLocked: function(cardState) { - var lockedState = [ 'pinRequired', 'pukRequired', @@ -309,6 +314,12 @@ // make sure the card is in locked mode or not return lockedState.indexOf(cardState) !== -1; }, + isSimCardBlocked: function(cardState) { + var uselessState = [ + 'permanentBlocked' + ]; + return uselessState.indexOf(cardState) !== -1; + }, addVoiceChangeEventOnConns: function() { var conns = window.navigator.mozMobileConnections; for (var i = 0; i < conns.length; i++) { @@ -328,6 +339,15 @@ } } }, + addLocalizedChangeEventOnIccs: function() { + var conns = window.navigator.mozMobileConnections; + window.addEventListener('localized', function() { + for (var i = 0; i < conns.length; i++) { + var iccId = conns[i].iccId; + this.updateCardStateWithUI(i, iccId); + } + }.bind(this)); + }, addChangeEventOnIccByIccId: function(iccId) { var self = this; var icc = window.navigator.mozIccManager.getIccById(iccId); @@ -335,6 +355,13 @@ icc.addEventListener('cardstatechange', function() { var cardIndex = self.getCardIndexByIccId(iccId); self.updateCardStateWithUI(cardIndex, iccId); + + // If we make PUK locked for more than 10 times, + // we sould get `permanentBlocked` state, in this way + // we have to update select/options + if (self.isSimCardBlocked(icc.cardState)) { + self.updateSelectOptionsUI(); + } }); } }, @@ -375,6 +402,8 @@ if (this.isSimCardLocked(cardState)) { simcard.setState('locked'); + } else if (this.isSimCardBlocked(cardState)) { + simcard.setState('blocked'); } else { // TODO: // we have to call Gecko API here to make sure the diff --git a/apps/settings/js/simcard_manager_simcard_helper.js b/apps/settings/js/simcard_manager_simcard_helper.js index f90f6db62c61..ce2888161dcb 100644 --- a/apps/settings/js/simcard_manager_simcard_helper.js +++ b/apps/settings/js/simcard_manager_simcard_helper.js @@ -15,7 +15,18 @@ var SimUIModel = function(cardIndex) { this.cardIndex = cardIndex; - // state list + /* + * We have following states and would try to reflect them on + * related UI. Take `locked` state for example, it doesn't mean + * that this SIm is locked (we have to access icc.cardState + * to make sure the SIM is locked), instead, it means that + * SimCardManager has to show a small `locker` icon on the screen. + * + * The reason why we need this Model is because UX needs different + * look and feel based on different cardState, in this way, I + * think this would be better to use separate propeties to reflect + * each UI on the screen so that we can change them easily. + */ this.enabled = false; this.absent = false; this.locked = false; @@ -56,6 +67,15 @@ this.operator = _('sim-pin-locked'); break; + case 'blocked': + this.enabled = true; + this.absent = true; + this.locked = false; + this.number = ''; + this.operator = ''; + this.name = _('noSimCard'); + break; + case 'normal': this.enabled = true; this.absent = false; diff --git a/apps/settings/js/telephony_items_handler.js b/apps/settings/js/telephony_items_handler.js index 730c47d44584..71adc3ac39de 100644 --- a/apps/settings/js/telephony_items_handler.js +++ b/apps/settings/js/telephony_items_handler.js @@ -31,6 +31,7 @@ var TelephonyItemsHandler = (function(window, document, undefined) { var CARD_STATE_MAPPING = { 'pinRequired' : 'simCardLockedMsg', 'pukRequired' : 'simCardLockedMsg', + 'permanentBlocked': 'simCardBlockedMsg', 'networkLocked' : 'simLockedPhone', 'serviceProviderLocked' : 'simLockedPhone', 'corporateLocked' : 'simLockedPhone', diff --git a/apps/settings/locales/settings.en-US.properties b/apps/settings/locales/settings.en-US.properties index e9451a85db2b..0a424bf6b076 100644 --- a/apps/settings/locales/settings.en-US.properties +++ b/apps/settings/locales/settings.en-US.properties @@ -764,6 +764,7 @@ pinAttemptMsg3[many]=You have {{n}} tries left to enter the correct code before pinAttemptMsg3[other]=You have {{n}} tries left to enter the correct code before locking the SIM card. pinLastChanceMsg=This is your last chance to enter the correct PIN. Otherwise, you must enter the PUK code to use this SIM card. simCardLockedMsg=The SIM card is locked. +simCardBlockedMsg=The SIM card is blocked. enterPukMsg=You must enter the Personal Unlocking Key (PUK) code for the SIM card. Refer to your SIM card documentation or contact your carrier for more information. enterPuk2Msg=You must enter the Personal Unlocking Key (PUK2) code for the SIM card. Refer to your SIM card documentation or contact your carrier for more information. pukErrorMsg=The PUK code is incorrect. diff --git a/apps/settings/test/unit/simcard_manager_simcard_helper_test.js b/apps/settings/test/unit/simcard_manager_simcard_helper_test.js index 19f41e538827..03af9a91ce67 100644 --- a/apps/settings/test/unit/simcard_manager_simcard_helper_test.js +++ b/apps/settings/test/unit/simcard_manager_simcard_helper_test.js @@ -1,3 +1,5 @@ +/* global requireApp, mocha, suite, suiteSetup, suiteTeardown, + setup, MockL10n, SimUIModel, assert, test */ 'use strict'; requireApp('settings/test/unit/mock_l10n.js'); @@ -51,7 +53,7 @@ suite('SimUIModel', function() { }); }); - suite('lock state > ', function() { + suite('locked state > ', function() { setup(function() { fakeSimcard.setState('locked'); }); @@ -67,6 +69,22 @@ suite('SimUIModel', function() { }); }); + suite('blocked state > ', function() { + setup(function() { + fakeSimcard.setState('blocked'); + }); + + test('set state to blocked successfully', function() { + var cardInfo = fakeSimcard.getInfo(); + assert.isTrue(cardInfo.enabled); + assert.isTrue(cardInfo.absent); + assert.isFalse(cardInfo.locked); + assert.equal(cardInfo.name, 'noSimCard'); + assert.equal(cardInfo.number, ''); + assert.equal(cardInfo.operator, ''); + }); + }); + suite('normal state > ', function() { var fakeNumber = '0123456789'; var fakeOperator = 'chunghwa telecom'; diff --git a/apps/settings/test/unit/simcard_manager_test.js b/apps/settings/test/unit/simcard_manager_test.js index 273fa105136c..94b500ee28f4 100644 --- a/apps/settings/test/unit/simcard_manager_test.js +++ b/apps/settings/test/unit/simcard_manager_test.js @@ -519,20 +519,20 @@ suite('SimCardManager > ', function() { suite('initSimCardManagerUI > ', function() { setup(function() { this.sinon.stub(SimCardManager, 'initSimCardsUI'); - this.sinon.stub(SimCardManager, 'initSelectOptionsUI'); + this.sinon.stub(SimCardManager, 'updateSelectOptionsUI'); this.sinon.stub(SimCardManager, 'updateSimCardsUI'); this.sinon.stub(SimCardManager, 'updateSimSecurityUI'); SimCardManager.initSimCardManagerUI(); }); test('all related methods are exectued', function() { assert.ok(SimCardManager.initSimCardsUI.called); - assert.ok(SimCardManager.initSelectOptionsUI.called); + assert.ok(SimCardManager.updateSelectOptionsUI.called); assert.ok(SimCardManager.updateSimCardsUI.called); assert.ok(SimCardManager.updateSimSecurityUI.called); }); }); - suite('initSelectOptionUI > ', function() { + suite('updateSelectOptionUI > ', function() { var selectedIndex = 1; var fakeSelect; @@ -544,19 +544,19 @@ suite('SimCardManager > ', function() { }); test('if storageKey is outgoingCall, we would add "always ask" option', function() { - SimCardManager.initSelectOptionUI('outgoingCall', + SimCardManager.updateSelectOptionUI('outgoingCall', selectedIndex, fakeSelect); assert.equal(fakeSelect.length, 3); }); test('if storageKey is outgoingMessages, we would add "always ask" option', function() { - SimCardManager.initSelectOptionUI('outgoingMessages', + SimCardManager.updateSelectOptionUI('outgoingMessages', selectedIndex, fakeSelect); assert.equal(fakeSelect.length, 3); }); test('if storageKey is outgoingData, we won\'t add "always ask" option', function() { - SimCardManager.initSelectOptionUI('outgoingData', + SimCardManager.updateSelectOptionUI('outgoingData', selectedIndex, fakeSelect); assert.equal(fakeSelect.length, 2); }); @@ -629,6 +629,38 @@ suite('SimCardManager > ', function() { }); }); + suite('We can change options when simcard is blocked', function() { + var fakeLockedIccId = '123456789'; + + suiteSetup(function() { + sinon.stub(SimCardManager, 'updateCardStateWithUI'); + sinon.stub(SimCardManager, 'updateSelectOptionsUI'); + + window.navigator.mozIccManager.addIcc(fakeLockedIccId, { + 'cardState' : 'permanentBlocked' + }); + + SimCardManager.addChangeEventOnIccByIccId(fakeLockedIccId); + + var callback = + window.navigator.mozIccManager.getIccById( + fakeLockedIccId + )._eventListeners.cardstatechange[0]; + callback(); + }); + + suiteTeardown(function() { + SimCardManager.updateCardStateWithUI.restore(); + SimCardManager.updateSelectOptionsUI.restore(); + window.navigator.mozIccManager.removeIcc(fakeLockedIccId); + }); + + test('change successfully', function() { + assert.isTrue(SimCardManager.updateCardStateWithUI.called); + assert.isTrue(SimCardManager.updateSelectOptionsUI.called); + }); + }); + // helpers function initCards(count) { SimCardManager.simcards = [];