/* global BaseModule, LogoLoader */ 'use strict'; (function(exports) { const DEFAULT_RESOURCES = { poweron: { video: '/resources/power/carrier_power_on.mp4', image: '/resources/power/carrier_power_on.png' }, poweroff: { video: '/resources/power/carrier_power_off.mp4', image: '/resources/power/carrier_power_off.png' } }; const ATT_PWRON_VIDEO = 'poweron.video'; const ATT_PWRON_IMG = 'poweron.image'; const ATT_PWROFF_VIDEO = 'poweroff.video'; const ATT_PWROFF_IMG = 'poweroff.image'; var CoverScreen = function() {}; CoverScreen.SETTINGS = [ 'operatorResources.power' ]; CoverScreen.SERVICES = [ 'poweroff', 'animatePoweronLogo' ]; BaseModule.create(CoverScreen, { name: 'CoverScreen', EVENT_PREFIX: 'initlogo', ready: false, animated: false, readyCallBack: null, DEBUG: false, SETTING_POWER: 'operatorResources.power', _start: function() { // We need to lock the orientation as early as we could. screen.mozLockOrientation('default'); this.carrierLogo = document.getElementById('carrier-logo'); this.osLogo = document.getElementById('os-logo'); this.service.request('registerHierarchy', this); }, _removeCarrierPowerOn: function ilh_removeCarrierPowerOn() { var self = this; if (this.carrierLogo && this.carrierLogo.parentNode) { this.carrierLogo.parentNode.removeChild(self.carrierLogo); this._setReady(); } else { document.addEventListener('DOMContentLoaded', function() { if (self.carrierLogo) { self.carrierLogo.parentNode.removeChild(self.carrierLogo); } self._setReady(); }); } }, _appendCarrierPowerOn: function ilh_appendCarrierPowerOn() { this.debug('appending power on logo'); if (this.carrierLogo) { this.carrierLogo.appendChild(this.poweronLogoLoader.element); this._setReady(); } else { var self = this; document.addEventListener('DOMContentLoaded', function() { self.carrierLogo.appendChild(self.poweronLogoLoader.element); self._setReady(); }); } }, _setReady: function ilh_setReady() { this.ready = true; var elem = this.poweronLogoLoader.element; if (elem && elem.tagName.toLowerCase() == 'video') { // Play video just after the element is first painted. window.addEventListener('mozChromeEvent', function startVideo(e) { if (e.detail.type == 'system-first-paint') { window.removeEventListener('mozChromeEvent', startVideo); if (elem && elem.ended === false) { elem.play(); } } }); } if (this.readyCallBack) { this.readyCallBack(); this.readyCallBack = null; } this.publish('-activated'); }, _waitReady: function ilh_waitReady(callback) { this.readyCallBack = callback; }, setDefaultValues: function () { if (!this._poweron) { this._poweron = {}; } if (!this._poweroff) { this._poweroff = {}; } this._poweron.video = DEFAULT_RESOURCES.poweron.video; this._poweron.image = DEFAULT_RESOURCES.poweron.image; this._poweroff.video = DEFAULT_RESOURCES.poweroff.video; this._poweroff.image = DEFAULT_RESOURCES.poweroff.image; }, '_observe_operatorResources.power': function(powerValues) { if (!powerValues) { this.debug('No power on settings found, using default.'); this.setDefaultValues(); this.poweron(); return; } if (!this._poweron) { this._poweron = {}; } if (!this._poweroff) { this._poweroff = {}; } this._poweron.video = powerValues[ATT_PWRON_VIDEO] || DEFAULT_RESOURCES.poweron.video; this._poweron.image = powerValues[ATT_PWRON_IMG] || DEFAULT_RESOURCES.poweron.image; this._poweroff.video = powerValues[ATT_PWROFF_VIDEO] || DEFAULT_RESOURCES.poweroff.video; this._poweroff.image = powerValues[ATT_PWROFF_IMG] || DEFAULT_RESOURCES.poweroff.image; }, poweron: function() { this.debug('start poweron logo: ' + JSON.stringify(this._poweron)); this.poweronLogoLoader = new LogoLoader(this._poweron); this.poweronLogoLoader.onnotfound = this._removeCarrierPowerOn.bind(this); this.poweronLogoLoader.onload = this._appendCarrierPowerOn.bind(this); }, isActive: function() { return this.ready && !this.animated; }, animatePoweronLogo: function ilh_animate(callback) { var self = this; if (!this.ready) { this._waitReady(this.animatePoweronLogo.bind(this, callback)); return; } if (this.animated) { return; } this.debug('stopping poweron logo'); this.animated = true; this.publish('-deactivated'); this.service.request('unregisterHierarchy', this); // No carrier logo - Just animate OS logo. if (!this.poweronLogoLoader.found) { this.osLogo.classList.add('hide'); // Has carrier logo - Animate carrier logo, then OS logo. } else { // CarrierLogo is not transparent until now // to prevent flashing. this.carrierLogo.className = 'transparent'; var elem = this.poweronLogoLoader.element; if (elem.tagName.toLowerCase() == 'video' && !elem.ended) { // compability: ensure movie being played here in case // system-first-paint is not supported by Gecko. elem.play(); elem.onended = function() { elem.classList.add('hide'); }; } else { elem.classList.add('hide'); } self.carrierLogo.addEventListener('transitionend', function transCarrierLogo(evt) { evt.stopPropagation(); self.carrierLogo.removeEventListener('transitionend', transCarrierLogo); if (elem.tagName.toLowerCase() == 'video') { // XXX workaround of bug 831747 // Unload the video. This releases the video decoding hardware // so other apps can use it. elem.removeAttribute('src'); elem.load(); } self.carrierLogo.parentNode.removeChild(self.carrierLogo); delete self.carrierLogo; // Don't entrain the DOM nodes. self.osLogo.classList.add('hide'); self.carrierPowerOnElement = null; }); } self.osLogo.addEventListener('transitionend', function transOsLogo() { self.osLogo.removeEventListener('transitionend', transOsLogo); self.osLogo.parentNode.removeChild(self.osLogo); delete self.osLogo; // Don't entrain the DOM nodes. window.performance.mark('osLogoEnd'); window.dispatchEvent(new CustomEvent('logohidden')); if (callback) { callback(); } }); }, poweroff: function(reboot) { this.debug('start poweroff logo'); var power = navigator.mozPower; var self = this; if (!power) { return; } // Early return if we are already shutting down. if (document.getElementById('poweroff-splash')) { return; } this.publish('will-shutdown', null, true); // Show shutdown animation before actually performing shutdown. // * step1: fade-in poweroff-splash. // * step2: - As default, 3-ring animation is performed on the screen. // - Manufacturer can customize the animation using mp4/png // file to replace the default. var div = document.createElement('div'); div.dataset.zIndexLevel = 'poweroff-splash'; div.id = 'poweroff-splash'; this.poweroffLogoLoader = new LogoLoader(this._poweroff); this.poweroffLogoLoader.onload = function(elem) { // Perform customized animation. div.appendChild(elem); div.className = 'step1'; if (elem.tagName.toLowerCase() == 'video' && !elem.ended) { elem.onended = function() { elem.classList.add('hide'); // XXX workaround of bug 831747 // Unload the video. This releases the video decoding hardware // so other apps can use it. elem.removeAttribute('src'); elem.load(); }; elem.play(); } else { div.addEventListener('animationend', function() { elem.classList.add('hide'); if (elem.tagName.toLowerCase() == 'video') { // XXX workaround of bug 831747 // Unload the video. This releases the video decoding hardware // so other apps can use it. elem.removeAttribute('src'); elem.load(); } }); } elem.addEventListener('transitionend', function() { self._actualPowerOff(reboot); }); document.getElementById('screen').appendChild(div); }; this.poweroffLogoLoader.onnotfound = function() { // - Perform OS default animation. // The overall animation ends when the inner span of the bottom ring // is animated, so we store it for detecting. var inner; for (var i = 1; i <= 3; i++) { var outer = document.createElement('span'); outer.className = 'poweroff-ring'; outer.id = 'poweroff-ring-' + i; div.appendChild(outer); inner = document.createElement('span'); outer.appendChild(inner); } div.className = 'step1'; var nextAnimation = function nextAnimation(e) { // Switch to next class if (e.target == div) { div.className = 'step2'; } if (e.target != inner) { return; } self._actualPowerOff(reboot); }; div.addEventListener('animationend', nextAnimation); document.getElementById('screen').appendChild(div); }; }, /** * Helper for powering the device off. * @memberof SleepMenu.prototype * @param {Boolean} isReboot Whether or not to reboot the phone. */ _actualPowerOff: function sm_actualPowerOff(isReboot) { this.debug('stopping poweroff logo and poweroff/reboot'); var power = navigator.mozPower; if (isReboot) { power.reboot(); } else { power.powerOff(); } } }); // We need to start as early as possible. exports.CoverScreen = BaseModule.instantiate('CoverScreen'); exports.CoverScreen.start(); }(window));