/* 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));