Skip to content
This repository has been archived by the owner on Nov 3, 2021. It is now read-only.

Commit

Permalink
Merge pull request #32758 from russnicoletti/bug-1210860
Browse files Browse the repository at this point in the history
Bug 1210860 - Video app launch time regression from 2.2 release r=pdahiya,gandalf
  • Loading branch information
Russ Nicoletti committed Oct 29, 2015
2 parents cc8f81c + bbc28e0 commit 6c15484
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 59 deletions.
6 changes: 3 additions & 3 deletions apps/video/index.html
Expand Up @@ -51,12 +51,12 @@
<div id="app-container">
<div id="two-column-spearator"></div>
<section role="region" id="thumbnail-views">
<gaia-header ignore-dir id="picker-header" action="back" class="thumbnails-list">
<gaia-header ignore-dir id="picker-header" action="back" class="thumbnails-list" no-font-fit>
<h1 id="picker-title" data-l10n-id="pick-title"></h1>
<h1 id="thumbnail-list-title">Video</h1>
</gaia-header>
<gaia-header ignore-dir id="thumbnails-select-top" action="close"
class="thumbnails-select">
class="thumbnails-select" no-font-fit>
<h1 id="thumbnails-number-selected"></h1>
</gaia-header>

Expand Down Expand Up @@ -87,7 +87,7 @@ <h1 id="thumbnails-number-selected"></h1>
<div id="spinner-overlay" class="hidden" role="progress"
data-l10n-id="spinner-overlay"><div id="spinner"></div></div>
<!-- video controls header -->
<gaia-header ignore-dir id="player-header" action="back" class="video-controls">
<gaia-header ignore-dir id="player-header" action="back" class="video-controls" no-font-fit>
<h1 id="video-title"></h1>
<button id="options" data-icon="more"
data-l10n-id="options-more"></button>
Expand Down
32 changes: 26 additions & 6 deletions apps/video/js/db.js
Expand Up @@ -39,12 +39,6 @@ function initDB() {
}
};

videodb.onready = function() {
storageState = false;
updateDialog();
enumerateDB();
};

videodb.onscanend = function() {
// If this was the first scan after startup, then tell
// performance monitors that the app is finally fully loaded and stable.
Expand All @@ -63,6 +57,22 @@ function initDB() {
videodb.ondeleted = function(event) {
event.detail.forEach(videoDeleted);
};

videodb.onenumerable = function() {
storageState = false;
updateDialog();
enumerateDB();
};

// The video app is relying on the mediadb auto-scanning to scan the db
// when it becomes ready or when the SD card has been mounted or remounted.
// This 'ready' handler is responsible for removing the 'unplug your ...'
// overlay (displayed when USB storage is enabled when the device is connected
// via USB cable), when the USB cable is unplugged.
videodb.onready = function() {
storageState = false;
updateDialog();
};
}

// Remember whether we've already run the enumeration step
Expand Down Expand Up @@ -122,6 +132,16 @@ function enumerateDB() {
// and is ready to interact with.
window.performance.mark('visuallyLoaded');
window.performance.mark('contentInteractive');

// Remove the attribute to trigger gaia header font-fit logic, defer it
// until now to postpone the overhead. Also, do this asynchronously to
// avoid interrupting the enumerating of the db.
setTimeout(function() {
var headers = document.querySelectorAll('gaia-header');
for (var i = 0; i < headers.length; ++i) {
headers[i].removeAttribute('no-font-fit');
}
});
}
}
}
Expand Down
103 changes: 56 additions & 47 deletions apps/video/js/video.js
Expand Up @@ -110,6 +110,8 @@ var loadingChecker =

var lastPlayTime = 0;

init();

// Workaround to fix issue reported in Bug 1214157
// We would like to pause video playback when interrupted by competing audio.
// Audio Channel API throws interruptbegin event after play event (Bug 1192748)
Expand Down Expand Up @@ -157,26 +159,17 @@ document.addEventListener('visibilitychange', function visibilityChange() {
}
});

navigator.mozL10n.once(function() {

// Tell performance monitors that our chrome is visible
window.performance.mark('navigationLoaded');

// Reformatting eventlistener is handled by ThumbnailList
IntlHelper.define('date-group', 'datetime', {
month: 'long',
year: 'numeric',
// We get headphoneschange event when the headphones is plugged or unplugged
var acm = navigator.mozAudioChannelManager;
if (acm) {
acm.addEventListener('headphoneschange', function onheadphoneschange() {
if (!acm.headphones && playing) {
setVideoPlaying(false);
}
});
}

init();

// Tell performance monitors that our chrome is ready to interact with.
window.performance.mark('navigationInteractive');
});

// we don't need to wait for l10n ready to have correct css layout.
initLayout();
initThumbnailSize();
navigator.mozSetMessageHandler('activity', handleActivityEvents);

if (!isPhone) {
navigator.mozL10n.ready(function localizeThumbnailListTitle() {
Expand All @@ -190,43 +183,59 @@ if (!isPhone) {
}

function init() {

// Tell performance monitors that our chrome is visible
window.performance.mark('navigationLoaded');

// Reformatting eventlistener is handled by ThumbnailList
IntlHelper.define('date-group', 'datetime', {
month: 'long',
year: 'numeric',
});

thumbnailList = new ThumbnailList(ThumbnailDateGroup, dom.thumbnails);
ThumbnailItem.titleMaxLines = isPhone ? 2 : (isPortrait ? 4 : 2);

// Initializing the database does not need to wait for l10n to be ready.
// Also, db initialization should start as soon as possible to reduce
// the time until the app is 'visuallyLoaded'.
initDB();

// if video is not start with activity mode, we need to wire all event
// handlers.
if (!navigator.mozHasPendingMessage('activity')) {
// options button only needed by normal mode. if we are under pick activity,
// there is only pick view enabled that is enabled at showPickView();
initOptionsButtons();
}
addUIEventListeners();
initLayout();
initThumbnailSize();

function addUIEventListeners() {
// if video is not start with activity mode, we need to wire all event
// handlers.
if (!navigator.mozHasPendingMessage('activity')) {
// options button only needed by normal mode. if we are under pick
// activity, there is only pick view enabled that is enabled at
// showPickView();
initOptionsButtons();
}

initPlayerControls();
ForwardRewindController.init(dom.player, dom.seekForward, dom.seekBackward);
// Ensure code that accesses html dir is executed after
// `documentElement.dir` is set.
navigator.mozL10n.once(function() {
initPlayerControls();
});

ForwardRewindController.init(dom.player, dom.seekForward, dom.seekBackward);

// We get headphoneschange event when the headphones is plugged or unplugged
var acm = navigator.mozAudioChannelManager;
if (acm) {
acm.addEventListener('headphoneschange', function onheadphoneschange() {
if (!acm.headphones && playing) {
setVideoPlaying(false);
// the overlay action button may be used in both normal mode and activity
// mode, we need to wire its event handler here.
dom.overlayActionButton.addEventListener('click', function() {
if (pendingPick) {
cancelPick();
} else if (currentOverlay === 'empty') {
launchCameraApp();
}
});
}

navigator.mozSetMessageHandler('activity', handleActivityEvents);

// the overlay action button may be used in both normal mode and activity
// mode, we need to wire its event handler here.
dom.overlayActionButton.addEventListener('click', function() {
if (pendingPick) {
cancelPick();
} else if (currentOverlay === 'empty') {
launchCameraApp();
}
});
// Tell performance monitors that our chrome is ready to interact with.
window.performance.mark('navigationInteractive');
}
}

function initThumbnailSize() {
Expand Down Expand Up @@ -866,7 +875,7 @@ function setControlsVisibility(visible) {
}

function movePlayHead(percent) {
if (navigator.mozL10n.language.direction === 'ltr') {
if (document.documentElement.dir === 'ltr') {
dom.playHead.style.left = percent;
}
else {
Expand Down Expand Up @@ -1323,7 +1332,7 @@ function handleSliderTouchMove(event) {
}

function getTouchPos() {
return (navigator.mozL10n.language.direction === 'ltr') ?
return (document.documentElement.dir === 'ltr') ?
(touch.clientX - sliderRect.left) :
(sliderRect.right - touch.clientX);
}
Expand Down
15 changes: 15 additions & 0 deletions apps/video/test/unit/mock_forward_rewind_controller.js
@@ -0,0 +1,15 @@
/* exported MockForwardRewindController */
'use strict';

var MockForwardRewindController = (function() {

function init(video, forward, backward) {}

function uninit(video, forward, backward) {}

return {
init: init,
uninit: uninit
};

}());
41 changes: 38 additions & 3 deletions apps/video/test/unit/video_test.js
Expand Up @@ -12,7 +12,8 @@
MockThumbnailGroup,l10nAssert,showInfoView,hideInfoView,
updateSelection,setButtonPaused,handleSliderTouchStart,MockMediaDB,
handleSliderTouchEnd,loadingChecker,MockL10n,VideoUtils,
updateDialog,LAYOUT_MODE,showPlayer,hidePlayer,MockThumbnailItem */
updateDialog,LAYOUT_MODE,showPlayer,hidePlayer,MockThumbnailItem,
MockThumbnailGroup,MockForwardRewindController,MockIntlHelper */
'use strict';

require('/shared/js/lazy_loader.js');
Expand All @@ -22,9 +23,11 @@ require('/shared/test/unit/mocks/mock_lazy_loader.js');
require('/shared/test/unit/mocks/mock_screen_layout.js');
require('/shared/test/unit/mocks/mock_video_stats.js');
require('/shared/test/unit/mocks/mock_l10n.js');
require('/shared/test/unit/mocks//mock_intl_helper.js');
requireApp('/video/js/video_utils.js');
requireApp('/video/test/unit/mock_metadata.js');
requireApp('/video/test/unit/mock_mediadb.js');
requireApp('/video/test/unit/mock_forward_rewind_controller.js');
requireApp('/video/test/unit/mock_thumbnail_group.js');
requireApp('/video/test/unit/mock_thumbnail_item.js');
requireApp('/video/test/unit/mock_video_loading_checker.js');
Expand All @@ -36,6 +39,11 @@ requireApp('/video/js/thumbnail_list.js');
var videodb; // Declared in db.js
var startParsingMetadata; // Declared in metadata.js
var ThumbnailItem;
var ThumbnailDateGroup;
var ForwardRewindController;
var IntlHelper;
var initDB;
var init;

function containsClass(element, value) {
return element.classList.contains(value);
Expand Down Expand Up @@ -73,6 +81,14 @@ suite('Video App Unit Tests', function() {

nativeMozL10n = navigator.mozL10n;
navigator.mozL10n = MockL10n;
IntlHelper = MockIntlHelper;

ThumbnailItem = MockThumbnailItem;
ThumbnailDateGroup = MockThumbnailGroup;

init = sinon.stub();
initDB = sinon.stub();
ForwardRewindController = MockForwardRewindController;

// we don't want to trigger once/ready callbacks
sinon.stub(navigator.mozL10n, 'once');
Expand Down Expand Up @@ -2097,7 +2113,8 @@ suite('Video App Unit Tests', function() {
suiteSetup(function() {
fastSeekSpy = sinon.spy(dom.player, 'fastSeek');
sliderRect = {'left': 10,
'width': 200};
'width': 200,
'right': 190};
});

setup(function() {
Expand All @@ -2110,16 +2127,34 @@ suite('Video App Unit Tests', function() {
fastSeekSpy.restore();
});

test('#handleSliderTouchMove: update the slider', function() {
test('#handleSliderTouchMove: update the slider (ltr)', function() {

document.documentElement.dir = 'ltr';
dom.playHead.style.left = '';
dom.playHead.style.right = '';
handleSliderTouchMove(successEvent);

assert.isTrue(containsClass(dom.playHead, 'active'));
assert.equal(dom.playHead.style.left, '50%');
assert.equal(dom.playHead.style.right, '');
assert.equal(dom.elapsedTime.style.width, '50%');
assert.isTrue(fastSeekSpy.calledOnce);
});

test('#handleSliderTouchMove: update the slider (rtl)', function() {

document.documentElement.dir = 'rtl';
dom.playHead.style.left = '';
dom.playHead.style.right = '';
handleSliderTouchMove(successEvent);

assert.isTrue(containsClass(dom.playHead, 'active'));
assert.equal(dom.playHead.style.right, '40%');
assert.equal(dom.playHead.style.left, '');
assert.equal(dom.elapsedTime.style.width, '40%');
assert.isTrue(fastSeekSpy.calledOnce);
});

test('#handleSliderTouchMove: not dragging', function() {
dragging = false;

Expand Down

0 comments on commit 6c15484

Please sign in to comment.