Bug 1263799 - Support IPC for TV service between B2G and content processes. Part 3 - Enhance TV mochitests. r=schien

MozReview-Commit-ID: IsCVCxtSzEn

--HG--
extra : rebase_source : 35d398296d2bfa96a41f938c8b4a9386b406b758
This commit is contained in:
Sean Lin 2015-12-18 16:33:16 +08:00
Родитель da1553afa4
Коммит 08a9eb457d
8 изменённых файлов: 346 добавлений и 101 удалений

Просмотреть файл

@ -44,34 +44,28 @@ function TVSimulatorService() {
// }
this._sourceListeners = {};
this._internalTuners = null;
this._scanCompleteTimer = null;
this._scanningWrapTunerData = null;
this._init();
try {
this.initData();
} catch (e) {
debug("Error: " + e + ", Cannot init the data.");
}
}
TVSimulatorService.prototype = {
classID: Components.ID("{94b065ad-d45a-436a-b394-6dabc3cf110f}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsITVSimulatorService,
Ci.nsITVService,
Ci.nsITimerCallback]),
Ci.nsITVService]),
_init: function TVSimInit() {
if (this._internalTuners) {
return;
}
// I try to load the testing mock data if related preference are already set.
// Otherwise, use to the simulation data from prefences.
// See /dom/tv/test/mochitest/head.js for more details.
let settingStr = "";
try {
settingStr = Services.prefs.getCharPref("dom.testing.tv_mock_data");
} catch(e) {
initData: function(aMockedData) {
// Use the passed-in mocked data. If it doesn't exist, then try to load the
// simulation data.
let settingStr = aMockedData;
if (!settingStr) {
try {
settingStr = this._getDummyData();
} catch(e) {
debug("TV Simulator service failed to load simulation data: " + e);
return;
throw Cr.NS_ERROR_FAILURE;
}
}
@ -81,8 +75,7 @@ TVSimulatorService.prototype = {
*
* Setting JSON file format:
*
* Note: This setting JSON is not allow empty array.
* If set the empty array, _init() will fail.
* Note: Empty arrays are not allowed in the format.
* e.g.
* - "tuners": []
* - "channels":[]
@ -121,13 +114,13 @@ TVSimulatorService.prototype = {
settingsObj = JSON.parse(settingStr);
} catch(e) {
debug("File load error: " + e);
return;
throw Cr.NS_ERROR_FAILURE;
}
// validation
if (!this._validateSettings(settingsObj)) {
debug("Failed to validate settings.");
return;
throw Cr.NS_ERROR_INVALID_ARG;
}
// Key is as follow
@ -299,70 +292,22 @@ TVSimulatorService.prototype = {
throw Cr.NS_ERROR_INVALID_ARG;
}
if (this._scanningWrapTunerData) {
aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
aCallback.notifyError(Ci.nsITVServiceCallback.TV_ERROR_FAILURE);
return;
}
this._scanningWrapTunerData = wrapTunerData;
aCallback.notifySuccess(null);
for (let [key, wrapChannelData] of wrapTunerData.channels) {
for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
listener.notifyChannelScanned(aTunerId, aSourceType, wrapChannelData.channel);
}
}
this._scanCompleteTimer = Cc["@mozilla.org/timer;1"]
.createInstance(Ci.nsITimer);
this._scanCompleteTimer.initWithCallback(this, 10,
Ci.nsITimer.TYPE_ONE_SHOT);
},
notify: function(aTimer) {
if (!this._scanningWrapTunerData) {
return;
}
this._scanCompleteTimer = null;
let tunerId = this._scanningWrapTunerData.tuner.id;
let sourceType = this._scanningWrapTunerData.sourceType;
let notifyResult = Cr.NS_OK;
for (let listener of this._getSourceListeners(tunerId, sourceType)) {
notifyResult = listener.notifyChannelScanComplete(tunerId, sourceType);
}
this._scanningWrapTunerData = null;
return notifyResult;
},
stopScanningChannels: function(aTunerId, aSourceType, aCallback) {
if (!aCallback) {
debug("aCallback is null\n");
throw Cr.NS_ERROR_INVALID_ARG;
}
if (!this._scanningWrapTunerData ||
aTunerId != this._scanningWrapTunerData.tuner.id ||
aSourceType != this._scanningWrapTunerData.sourceType) {
aCallback.notifyError(Cr.NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
this._scanningWrapTunerData = null;
if (this._scanCompleteTimer) {
this._scanCompleteTimer.cancel();
this._scanCompleteTimer = null;
}
for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
listener.notifyChannelScanStopped(aTunerId, aSourceType);
}
@ -464,6 +409,51 @@ TVSimulatorService.prototype = {
return videoBlobURL;
},
simulateChannelScanned: function(aTunerId, aSourceType) {
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
throw Cr.NS_ERROR_INVALID_ARG;
}
let listeners = this._getSourceListeners(aTunerId, aSourceType);
for (let [key, wrapChannelData] of wrapTunerData.channels) {
for (let listener of listeners) {
listener.notifyChannelScanned(aTunerId, aSourceType, wrapChannelData.channel);
}
}
},
simulateChannelScanComplete: function(aTunerId, aSourceType) {
for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
listener.notifyChannelScanComplete(aTunerId, aSourceType);
}
},
simulateChannelScanError: function(aTunerId, aSourceType) {
for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
listener.notifyChannelScanStopped(aTunerId, aSourceType);
}
},
simulateEITBroadcasted: function(aTunerId, aSourceType, aChannelNumber) {
let wrapTunerData = this._getWrapTunerData(aTunerId, aSourceType);
if (!wrapTunerData || !wrapTunerData.channels) {
throw Cr.NS_ERROR_INVALID_ARG;
}
let wrapChannelData = wrapTunerData.channels.get(aChannelNumber);
if (!wrapChannelData || !wrapChannelData.programs) {
throw Cr.NS_ERROR_INVALID_ARG;
}
for (let listener of this._getSourceListeners(aTunerId, aSourceType)) {
listener.notifyEITBroadcasted(aTunerId, aSourceType,
wrapChannelData.channel,
wrapChannelData.programs,
wrapChannelData.programs.length);
}
},
_getDummyData : function() {
// Load the setting file from local JSON file.
// Synchrhronous File Reading.

Просмотреть файл

@ -15,6 +15,13 @@ interface mozIDOMWindow;
[scriptable, uuid(3f670994-5915-415a-b906-7ead54bb3be1)]
interface nsITVSimulatorService : nsITVService
{
/*
* Init the simulation data.
*
* @param mockedData The preloaded mocked data in stringified JSON format.
*/
void initData([optional] in DOMString mockedData);
/*
* Get the URL of simulated video blob.
*
@ -29,4 +36,42 @@ interface nsITVSimulatorService : nsITVService
in DOMString channelNumber,
in mozIDOMWindow window,
[retval] out DOMString blobUrl);
/*
* Simulate some channels are scanned.
*
* @param tunerId The ID of the tuner.
* @param sourceType The source type to be used.
*/
void simulateChannelScanned(in DOMString tunerId,
in DOMString sourceType);
/*
* Simulate channel scanning complete.
*
* @param tunerId The ID of the tuner.
* @param sourceType The source type to be used.
*/
void simulateChannelScanComplete(in DOMString tunerId,
in DOMString sourceType);
/*
* Simulate error occurs during channel scanning.
*
* @param tunerId The ID of the tuner.
* @param sourceType The source type to be used.
*/
void simulateChannelScanError(in DOMString tunerId,
in DOMString sourceType);
/*
* Simulate EIT broadcasted.
*
* @param tunerId The ID of the tuner.
* @param sourceType The source type to be used.
* @param channelNumber The LCN (Logical Channel Number) of the channel.
*/
void simulateEITBroadcasted(in DOMString tunerId,
in DOMString sourceType,
in DOMString channelNumber);
};

Просмотреть файл

@ -1,40 +1,45 @@
"use strict";
function setupPrefsAndPermissions(callback) {
function setupPrefsAndPermissions(aCallback) {
setupPrefs(function() {
SpecialPowers.pushPermissions([
{"type":"tv", "allow":1, "context":document}
], callback);
], aCallback);
});
}
function setupPrefs(callback) {
let xhr = new XMLHttpRequest;
let data;
xhr.open("GET", "./mock_data.json", false);
xhr.send(null);
if (xhr.status == 200) {
data = xhr.responseText;
}
function setupPrefs(aCallback) {
SpecialPowers.pushPrefEnv({"set": [
["dom.tv.enabled", true],
["dom.ignore_webidl_scope_checks", true],
["dom.testing.tv_mock_data", data]
]}, function() {
callback();
aCallback();
});
}
function removePrefsAndPermissions(callback) {
function removePrefsAndPermissions(aCallback) {
SpecialPowers.popPrefEnv(function() {
SpecialPowers.popPermissions(callback);
SpecialPowers.popPermissions(aCallback);
});
}
function prepareTest(callback) {
function prepareTest(aCallback) {
removePrefsAndPermissions(function() {
setupPrefsAndPermissions(callback);
setupPrefsAndPermissions(function() {
initMockedData(aCallback);
});
});
}
function initMockedData(aCallback) {
let xhr = new XMLHttpRequest;
xhr.open("GET", "./mock_data.json", false);
xhr.send(null);
if (xhr.status == 200) {
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
gScript.addMessageListener('init-mocked-data-complete', aCallback);
gScript.sendAsyncMessage('init-mocked-data', xhr.responseText);
}
}

Просмотреть файл

@ -1,7 +1,9 @@
[DEFAULT]
skip-if = toolkit == "gonk"
support-files =
head.js
mock_data.json
tv_chrome_script.js
[test_tv_non_permitted_app.html]
[test_tv_permitted_app.html]
@ -17,4 +19,9 @@ support-files =
[test_tv_set_current_channel_during_scanning.html]
[test_tv_set_invalid_current_channel.html]
[test_tv_scan_channels_stopped.html]
skip-if = e10s || buildapp == 'b2g'
[test_tv_scan_channels_completed.html]
skip-if = e10s || buildapp == 'b2g'
[test_tv_scan_channels_error.html]
skip-if = e10s || buildapp == 'b2g'
[test_tv_eit_broadcasted.html]

Просмотреть файл

@ -0,0 +1,77 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test TVEITBroadcastedEvent for TV API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script type="application/javascript" src="./head.js"></script>
<script type="application/javascript">
function runTest() {
ok('tv' in navigator, "navigator.tv should exist.");
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
navigator.tv.getTuners().then(
function(aTuners) {
ok(aTuners.length > 0, "Got at least 1 tuner.");
aTuners[0].getSources().then(
function(aSources) {
ok(aSources.length > 0, "Got at least 1 source.");
var source = aSources[0];
source.oneitbroadcasted = function(aEvent) {
info("Received EIT broadcasted event.");
var programs = aEvent.programs;
for (var i = 0; i < programs.length; i++) {
ok(programs[i], "Program " + i + " should be set.")
}
gScript.destroy();
SimpleTest.finish();
};
source.getChannels().then(
function(aChannels) {
ok(aChannels.length > 0, "Got at least 1 channel.");
gScript.sendAsyncMessage('trigger-eit-broadcasted',
{ tunerId: aTuners[0].id,
sourceType: source.type,
channelNumber: aChannels[0].number });
},
function(aError) {
ok(false, "Error occurred when getting channels: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
},
function(aError) {
ok(false, "Error occurred when getting sources: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
},
function(aError) {
ok(false, "Error occurred when getting tuners: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
}
SimpleTest.waitForExplicitFinish();
prepareTest(runTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -16,6 +16,7 @@ function runTest() {
ok('tv' in navigator, "navigator.tv should exist.");
var isScannedEventFired = false;
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
navigator.tv.getTuners().then(
function(aTuners) {
@ -26,43 +27,47 @@ function runTest() {
ok(aSources.length > 0, "Got at least 1 source.");
var source = aSources[0];
source.oneitbroadcasted = function(aEvent) {
info("Received EIT broadcasted event.");
var programs = aEvent.programs;
for (var i = 0; i < programs.length; i++) {
ok(programs[i], "Program " + i + " should be set.")
}
};
source.onscanningstatechanged = function(aEvent) {
if (aEvent.state === 'scanned') {
isScannedEventFired = true;
if (!isScannedEventFired) {
isScannedEventFired = true;
gScript.sendAsyncMessage('trigger-channel-scan-complete',
{ tunerId: aTuners[0].id,
sourceType: source.type });
}
info("Received channel scanned event.");
ok(aEvent.channel, "Scanned channel should be set.");
} else if (aEvent.state === 'completed') {
ok(isScannedEventFired, "Received channel scanning completed event after channel scanned event.");
gScript.destroy();
SimpleTest.finish();
}
};
// TODO Bug 1088818 - Modify the behavior of channel scanning.
source.startScanning({}).then(
function() {},
function() {
gScript.sendAsyncMessage('trigger-channel-scanned',
{ tunerId: aTuners[0].id,
sourceType: source.type });
},
function(aError) {
ok(false, "Error occurred when starting scanning: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
},
function(aError) {
ok(false, "Error occurred when getting sources: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
},
function(aError) {
ok(false, "Error occurred when getting tuners: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);

Просмотреть файл

@ -0,0 +1,72 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Test channel scanning error for TV API</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script type="application/javascript" src="./head.js"></script>
<script type="application/javascript">
function runTest() {
ok('tv' in navigator, "navigator.tv should exist.");
var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('tv_chrome_script.js'));
navigator.tv.getTuners().then(
function(aTuners) {
ok(aTuners.length > 0, "Got at least 1 tuner.");
aTuners[0].getSources().then(
function(aSources) {
ok(aSources.length > 0, "Got at least 1 source.");
var source = aSources[0];
source.onscanningstatechanged = function(aEvent) {
if (aEvent.state === 'stopped') {
ok(true, "Received channel scanning stopped event.");
gScript.destroy();
SimpleTest.finish();
}
};
// TODO Bug 1088818 - Modify the behavior of channel scanning.
source.startScanning().then(
function() {
gScript.sendAsyncMessage('trigger-channel-scan-error',
{ tunerId: aTuners[0].id,
sourceType: source.type });
},
function(aError) {
ok(false, "Error occurred when starting scanning: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
},
function(aError) {
ok(false, "Error occurred when getting sources: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
},
function(aError) {
ok(false, "Error occurred when getting tuners: " + aError);
gScript.destroy();
SimpleTest.finish();
}
);
}
SimpleTest.waitForExplicitFinish();
prepareTest(runTest);
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -0,0 +1,44 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
'use strict';
const { classes: Cc, interfaces: Ci, manager: Cm, utils: Cu, results: Cr } = Components;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
addMessageListener('init-mocked-data', function(aData) {
var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
try {
service.QueryInterface(Ci.nsITVSimulatorService).initData(aData);
sendAsyncMessage('init-mocked-data-complete');
} catch (e) {}
});
addMessageListener('trigger-channel-scanned', function(aData) {
var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
try {
service.QueryInterface(Ci.nsITVSimulatorService).simulateChannelScanned(aData.tunerId, aData.sourceType);
} catch (e) {}
});
addMessageListener('trigger-channel-scan-complete', function(aData) {
var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
try {
service.QueryInterface(Ci.nsITVSimulatorService).simulateChannelScanComplete(aData.tunerId, aData.sourceType);
} catch (e) {}
});
addMessageListener('trigger-channel-scan-error', function(aData) {
var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
try {
service.QueryInterface(Ci.nsITVSimulatorService).simulateChannelScanError(aData.tunerId, aData.sourceType);
} catch (e) {}
});
addMessageListener('trigger-eit-broadcasted', function(aData) {
var service = Cc["@mozilla.org/tv/tvservice;1"].getService(Ci.nsITVService);
try {
service.QueryInterface(Ci.nsITVSimulatorService).simulateEITBroadcasted(aData.tunerId, aData.sourceType, aData.channelNumber);
} catch (e) {}
});