define(function(require) { 'use strict'; var AirplaneModeHelper = require('shared/airplane_mode_helper'); var SIMSlotManager = require('shared/simslot_manager'); var DialogService = require('modules/dialog_service'); var Sanitizer = require('shared/sanitizer'); var Toaster = require('shared/toaster'); var SimSecurity = require('modules/sim_security'); var SimPin = function(elements) { this._elements = elements; }; SimPin.prototype = { init: function simpin_init() { AirplaneModeHelper.ready(() => { this.conns = window.navigator.mozMobileConnections; this.iccManager = window.navigator.mozIccManager; this.isAirplaneMode = (AirplaneModeHelper.getStatus() === 'enabled'); this._elements.simPinContainer.addEventListener('click', this); this._elements.simPinContainer.addEventListener('change', this.simPinSwitched.bind(this)); this.addIccDetectedEvent(); this.addIccUndetectedEvent(); this.addAirplaneModeChangeEvent(); this.initSimPinBack(); this.initSimPinsUI(); this.updateSimPinsUI(); this.addChangeEventOnIccs(); }); }, simPinView: function({simIndex, simPinArgs}) { return Sanitizer.escapeHTML `
  • `; }, initSimPinBack: function simpin_initSimPinBack() { // Because this panel is used in one-sim & two-sim structures, // the entry point of sim security is different. // // In this way, we have to make sure users can go back to the // right panel. this._elements.simPinHeader.dataset.href = SIMSlotManager.isMultiSIM() ? '#sim-manager': '#root'; }, initSimPinsUI: function simpin_initSimPinsUI() { var simPinHTMLs = []; [].forEach.call(this.conns, (conn, index) => { var simPinIndex = index + 1; if (!SIMSlotManager.isMultiSIM()) { simPinIndex = ''; } simPinHTMLs.push( this.simPinView({ 'simIndex': index.toString(), 'simPinArgs': JSON.stringify({ 'index': simPinIndex }) }) ); }); this._elements.simPinContainer.innerHTML = simPinHTMLs.join(''); }, updateSimPinUI: function simpin_updateSimPinUI(cardIndex) { var iccId = this.conns[cardIndex].iccId; var icc = this.iccManager.getIccById(iccId); var changeSimPinItem = this._elements.simPinContainer.querySelector( '.simpin-change-' + cardIndex); var simPinCheckbox = this._elements.simPinContainer.querySelector( '.simpin-enabled-' + cardIndex + ' gaia-switch'); var isSimAvailable = icc && icc.cardState && icc.cardState !== 'unknown'; // when fugu is in airplane mode, icc.cardState will not be changed ... // in this way, we have to use isAirplaneMode to check this situation if (!isSimAvailable || this.isAirplaneMode) { simPinCheckbox.disabled = true; changeSimPinItem.hidden = true; return Promise.resolve(); } // with SIM card, query its status return SimSecurity.getCardLock(cardIndex, 'pin').then((result) => { var enabled = result.enabled; simPinCheckbox.disabled = false; simPinCheckbox.checked = enabled; changeSimPinItem.hidden = !enabled; }, () => { console.log('onerror'); console.log('cardIndex', cardIndex); }); }, updateSimPinsUI: function simpin_updateSimPinsUI() { [].forEach.call(this.conns, (simcard, cardIndex) => { this.updateSimPinUI(cardIndex); }); }, handleEvent: function simpin_handleEvent(evt) { var target = evt.target; var cardIndex = target.dataset && target.dataset.simIndex; var type = target.dataset && target.dataset.type; // We need number type cardIndex = parseInt(cardIndex, 10); switch (type) { case 'changeSimPin': this.changeSimPin(cardIndex); break; } }, /** * Handles user enabling the sim pin. * This is outside of handleEvent due to gaia-switch firing both a click * and a change event, and wanting to handle the switch state only when * it changes. */ simPinSwitched: function simpin_simPinSwitched(evt) { var target = evt.target; var cardIndex = target.dataset && target.dataset.simIndex; cardIndex = parseInt(cardIndex, 10); this.checkSimPin(target, cardIndex); }, checkSimPin: function simpin_checkSimPin(checkbox, cardIndex) { var enabled = checkbox.checked; var iccId = this.conns[cardIndex].iccId; var icc = this.iccManager.getIccById(iccId); switch (icc.cardState) { case 'pukRequired': return DialogService.show('simpin-dialog', { method: 'unlock_puk', cardIndex: cardIndex }).then((result) => { var type = result.type; if (type === 'submit') { // successful unlock puk will be in simcard lock enabled state checkbox.checked = true; this.updateSimPinUI(cardIndex); } else { checkbox.checked = !enabled; this.updateSimPinUI(cardIndex); } }); default: var action = enabled ? 'enable_lock' : 'disable_lock'; return DialogService.show('simpin-dialog', { method: action, cardIndex: cardIndex }).then((result) => { var type = result.type; if (type === 'submit') { this.updateSimPinUI(cardIndex); } else { checkbox.checked = !enabled; this.updateSimPinUI(cardIndex); } }); } }, changeSimPin: function(cardIndex) { return DialogService.show('simpin-dialog', { method: 'change_pin', cardIndex: cardIndex }).then(function(result) { var type = result.type; if (type === 'submit') { var toast; if (SIMSlotManager.isMultiSIM()) { toast = { messageL10nId: 'simPinChangedSuccessfullyWithIndex', messageL10nArgs: {'index': +(cardIndex) + 1}, latency: 3000, useTransition: true }; } else { toast = { messageL10nId: 'simPinChangedSuccessfully', latency: 3000, useTransition: true }; } Toaster.showToast(toast); } }); }, addIccDetectedEvent: function simpin_addIccDetectedEvent() { // if there is a change that icc instance is available // we can update its cardstatus to make it reflect the // real world. this.iccManager.addEventListener('iccdetected', (evt) => { var iccId = evt.iccId; var icc = this.iccManager.getIccById(iccId); if (icc) { var cardIndex = this.getCardIndexByIccId(iccId); // we have to update its status and add change event // for it to make it reflect status on to UI this.updateSimPinUI(cardIndex); this.addChangeEventOnIccByIccId(iccId); } }); }, addIccUndetectedEvent: function simpin_addIccDetectedEvent() { // if there is a change that icc instance is not available // we have to update all cards' status this.iccManager.addEventListener('iccundetected', (evt) => { this.updateSimPinsUI(); }); }, addAirplaneModeChangeEvent: function simpin_addAirplaneModeChangeEvent() { AirplaneModeHelper.addEventListener('statechange', (status) => { this.isAirplaneMode = (status === 'enabled'); this.updateSimPinsUI(); }); }, addChangeEventOnIccs: function simpin_addChangeEventOnIccs() { for (var i = 0; i < this.conns.length; i++) { var iccId = this.conns[i].iccId; var icc = this.iccManager.getIccById(iccId); if (icc) { this.addChangeEventOnIccByIccId(iccId); } } }, addChangeEventOnIccByIccId: function simpin_addChangeEventOnIccByIccId(iccId) { var icc = this.iccManager.getIccById(iccId); if (icc) { icc.addEventListener('cardstatechange', () => { var cardIndex = this.getCardIndexByIccId(iccId); this.updateSimPinUI(cardIndex); }); } }, getCardIndexByIccId: function simpin_getCardIndexByIccId(iccId) { var cardIndex; for (var i = 0; i < this.conns.length; i++) { if (this.conns[i].iccId == iccId) { cardIndex = i; } } return cardIndex; } }; return function ctor_simpin(elements) { return new SimPin(elements); }; });