summaryrefslogtreecommitdiffstats
path: root/b2g/components/test/mochitest
diff options
context:
space:
mode:
Diffstat (limited to 'b2g/components/test/mochitest')
-rw-r--r--b2g/components/test/mochitest/SandboxPromptTest.html57
-rw-r--r--b2g/components/test/mochitest/filepicker_path_handler_chrome.js31
-rw-r--r--b2g/components/test/mochitest/mochitest.ini28
-rw-r--r--b2g/components/test/mochitest/permission_handler_chrome.js36
-rw-r--r--b2g/components/test/mochitest/presentation_prompt_handler_chrome.js94
-rw-r--r--b2g/components/test/mochitest/presentation_ui_glue_handler_chrome.js32
-rw-r--r--b2g/components/test/mochitest/screenshot_helper.js40
-rw-r--r--b2g/components/test/mochitest/systemapp_helper.js173
-rw-r--r--b2g/components/test/mochitest/test_filepicker_path.html130
-rw-r--r--b2g/components/test/mochitest/test_permission_deny.html83
-rw-r--r--b2g/components/test/mochitest/test_permission_gum_remember.html170
-rw-r--r--b2g/components/test/mochitest/test_permission_visibilitychange.html57
-rw-r--r--b2g/components/test/mochitest/test_presentation_device_prompt.html145
-rw-r--r--b2g/components/test/mochitest/test_presentation_request_ui_glue.html105
-rw-r--r--b2g/components/test/mochitest/test_sandbox_permission.html104
-rw-r--r--b2g/components/test/mochitest/test_screenshot.html31
-rw-r--r--b2g/components/test/mochitest/test_systemapp.html31
17 files changed, 1347 insertions, 0 deletions
diff --git a/b2g/components/test/mochitest/SandboxPromptTest.html b/b2g/components/test/mochitest/SandboxPromptTest.html
new file mode 100644
index 000000000..54f5fdd48
--- /dev/null
+++ b/b2g/components/test/mochitest/SandboxPromptTest.html
@@ -0,0 +1,57 @@
+<html>
+<body>
+<script>
+
+var actions = [
+ {
+ permissions: ["video-capture"],
+ action: function() {
+ // invoke video-capture permission prompt
+ navigator.mozGetUserMedia({video: true}, function () {}, function () {});
+ }
+ },
+ {
+ permissions: ["audio-capture", "video-capture"],
+ action: function() {
+ // invoke audio-capture + video-capture permission prompt
+ navigator.mozGetUserMedia({audio: true, video: true}, function () {}, function () {});
+ }
+ },
+ {
+ permissions: ["audio-capture"],
+ action: function() {
+ // invoke audio-capture permission prompt
+ navigator.mozGetUserMedia({audio: true}, function () {}, function () {});
+ }
+ },
+ {
+ permissions: ["geolocation"],
+ action: function() {
+ // invoke geolocation permission prompt
+ navigator.geolocation.getCurrentPosition(function (pos) {});
+ }
+ },
+ {
+ permissions: ["desktop-notification"],
+ action: function() {
+ // invoke desktop-notification prompt
+ Notification.requestPermission(function (perm) {});
+ }
+ },
+];
+
+// The requested permissions are specified in query string.
+var permissions = JSON.parse(decodeURIComponent(window.location.search.substring(1)));
+for (var i = 0; i < actions.length; i++) {
+ if(permissions.length === actions[i].permissions.length &&
+ permissions.every(function(permission) {
+ return actions[i].permissions.indexOf(permission) >= 0;
+ })) {
+ actions[i].action();
+ break;
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/filepicker_path_handler_chrome.js b/b2g/components/test/mochitest/filepicker_path_handler_chrome.js
new file mode 100644
index 000000000..a175746cb
--- /dev/null
+++ b/b2g/components/test/mochitest/filepicker_path_handler_chrome.js
@@ -0,0 +1,31 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this file,
+* You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+
+// use ppmm to handle file-picker message.
+var ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1']
+ .getService(Ci.nsIMessageListenerManager);
+
+var pickResult = null;
+
+function processPickMessage(message) {
+ let sender = message.target.QueryInterface(Ci.nsIMessageSender);
+ // reply FilePicker's message
+ sender.sendAsyncMessage('file-picked', pickResult);
+ // notify caller
+ sendAsyncMessage('file-picked-posted', { type: 'file-picked-posted' });
+}
+
+function updatePickResult(result) {
+ pickResult = result;
+ sendAsyncMessage('pick-result-updated', { type: 'pick-result-updated' });
+}
+
+ppmm.addMessageListener('file-picker', processPickMessage);
+// use update-pick-result to change the expected pick result.
+addMessageListener('update-pick-result', updatePickResult);
diff --git a/b2g/components/test/mochitest/mochitest.ini b/b2g/components/test/mochitest/mochitest.ini
new file mode 100644
index 000000000..97df32ea2
--- /dev/null
+++ b/b2g/components/test/mochitest/mochitest.ini
@@ -0,0 +1,28 @@
+[DEFAULT]
+support-files =
+ permission_handler_chrome.js
+ SandboxPromptTest.html
+ filepicker_path_handler_chrome.js
+ screenshot_helper.js
+ systemapp_helper.js
+ presentation_prompt_handler_chrome.js
+ presentation_ui_glue_handler_chrome.js
+
+[test_filepicker_path.html]
+skip-if = toolkit != "gonk"
+[test_permission_deny.html]
+skip-if = toolkit != "gonk"
+[test_permission_gum_remember.html]
+skip-if = true # Bug 1019572 - frequent timeouts
+[test_sandbox_permission.html]
+skip-if = toolkit != "gonk"
+[test_screenshot.html]
+skip-if = toolkit != "gonk"
+[test_systemapp.html]
+skip-if = toolkit != "gonk"
+[test_presentation_device_prompt.html]
+skip-if = toolkit != "gonk"
+[test_permission_visibilitychange.html]
+skip-if = toolkit != "gonk"
+[test_presentation_request_ui_glue.html]
+skip-if = toolkit != "gonk"
diff --git a/b2g/components/test/mochitest/permission_handler_chrome.js b/b2g/components/test/mochitest/permission_handler_chrome.js
new file mode 100644
index 000000000..9bf3e7819
--- /dev/null
+++ b/b2g/components/test/mochitest/permission_handler_chrome.js
@@ -0,0 +1,36 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+function debug(str) {
+ dump("CHROME PERMISSON HANDLER -- " + str + "\n");
+}
+
+var Cc = Components.classes;
+var Ci = Components.interfaces;
+var Cu = Components.utils;
+
+const { Services } = Cu.import("resource://gre/modules/Services.jsm");
+const { SystemAppProxy } = Cu.import("resource://gre/modules/SystemAppProxy.jsm");
+
+var eventHandler = function(evt) {
+ if (!evt.detail || evt.detail.type !== "permission-prompt") {
+ return;
+ }
+
+ sendAsyncMessage("permission-request", evt.detail);
+};
+
+SystemAppProxy.addEventListener("mozChromeEvent", eventHandler);
+
+// need to remove ChromeEvent listener after test finished.
+addMessageListener("teardown", function() {
+ SystemAppProxy.removeEventListener("mozChromeEvent", eventHandler);
+});
+
+addMessageListener("permission-response", function(detail) {
+ SystemAppProxy._sendCustomEvent('mozContentEvent', detail);
+});
+
diff --git a/b2g/components/test/mochitest/presentation_prompt_handler_chrome.js b/b2g/components/test/mochitest/presentation_prompt_handler_chrome.js
new file mode 100644
index 000000000..4407e58d2
--- /dev/null
+++ b/b2g/components/test/mochitest/presentation_prompt_handler_chrome.js
@@ -0,0 +1,94 @@
+/* -*- 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';
+
+ function debug(str) {
+ dump('presentation_prompt_handler_chrome: ' + str + '\n');
+ }
+
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+const { XPCOMUtils } = Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm');
+
+const manager = Cc["@mozilla.org/presentation-device/manager;1"]
+ .getService(Ci.nsIPresentationDeviceManager);
+
+const prompt = Cc['@mozilla.org/presentation-device/prompt;1']
+ .getService(Ci.nsIPresentationDevicePrompt);
+
+function TestPresentationDevice(options) {
+ this.id = options.id;
+ this.name = options.name;
+ this.type = options.type;
+}
+
+TestPresentationDevice.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDevice]),
+ establishSessionTransport: function() {
+ return null;
+ },
+};
+
+function TestPresentationRequest(options) {
+ this.origin = options.origin;
+ this.requestURL = options.requestURL;
+}
+
+TestPresentationRequest.prototype = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIPresentationDeviceRequest]),
+ select: function(device) {
+ let result = {
+ type: 'select',
+ device: {
+ id: device.id,
+ name: device.name,
+ type: device.type,
+ },
+ };
+ sendAsyncMessage('presentation-select-result', result);
+ },
+ cancel: function() {
+ let result = {
+ type: 'cancel',
+ };
+ sendAsyncMessage('presentation-select-result', result);
+ },
+};
+
+var testDevice = null;
+
+addMessageListener('setup', function(device_options) {
+ testDevice = new TestPresentationDevice(device_options);
+ manager.QueryInterface(Ci.nsIPresentationDeviceListener).addDevice(testDevice);
+ sendAsyncMessage('setup-complete');
+});
+
+var eventHandler = function(evt) {
+ if (!evt.detail || evt.detail.type !== 'presentation-select-device') {
+ return;
+ }
+
+ sendAsyncMessage('presentation-select-device', evt.detail);
+};
+
+SystemAppProxy.addEventListener('mozChromeEvent', eventHandler);
+
+// need to remove ChromeEvent listener after test finished.
+addMessageListener('teardown', function() {
+ if (testDevice) {
+ manager.removeDevice(testDevice);
+ }
+ SystemAppProxy.removeEventListener('mozChromeEvent', eventHandler);
+});
+
+addMessageListener('trigger-device-prompt', function(request_options) {
+ let request = new TestPresentationRequest(request_options);
+ prompt.promptDeviceSelection(request);
+});
+
+addMessageListener('presentation-select-response', function(detail) {
+ SystemAppProxy._sendCustomEvent('mozContentEvent', detail);
+});
+
diff --git a/b2g/components/test/mochitest/presentation_ui_glue_handler_chrome.js b/b2g/components/test/mochitest/presentation_ui_glue_handler_chrome.js
new file mode 100644
index 000000000..fac16db6c
--- /dev/null
+++ b/b2g/components/test/mochitest/presentation_ui_glue_handler_chrome.js
@@ -0,0 +1,32 @@
+/* -*- 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';
+
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+const { XPCOMUtils } = Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+const { SystemAppProxy } = Cu.import('resource://gre/modules/SystemAppProxy.jsm');
+
+const glue = Cc["@mozilla.org/presentation/requestuiglue;1"]
+ .createInstance(Ci.nsIPresentationRequestUIGlue);
+
+SystemAppProxy.addEventListener('mozPresentationChromeEvent', function(aEvent) {
+ if (!aEvent.detail || aEvent.detail.type !== 'presentation-launch-receiver') {
+ return;
+ }
+ sendAsyncMessage('presentation-launch-receiver', aEvent.detail);
+});
+
+addMessageListener('trigger-ui-glue', function(aData) {
+ var promise = glue.sendRequest(aData.url, aData.sessionId);
+ promise.then(function(aFrame) {
+ sendAsyncMessage('iframe-resolved', aFrame);
+ }).catch(function() {
+ sendAsyncMessage('iframe-rejected');
+ });
+});
+
+addMessageListener('trigger-presentation-content-event', function(aDetail) {
+ SystemAppProxy._sendCustomEvent('mozPresentationContentEvent', aDetail);
+});
diff --git a/b2g/components/test/mochitest/screenshot_helper.js b/b2g/components/test/mochitest/screenshot_helper.js
new file mode 100644
index 000000000..0320a14c1
--- /dev/null
+++ b/b2g/components/test/mochitest/screenshot_helper.js
@@ -0,0 +1,40 @@
+var Cu = Components.utils;
+var Ci = Components.interfaces;
+
+Cu.importGlobalProperties(['File']);
+
+const { Services } = Cu.import("resource://gre/modules/Services.jsm");
+
+// Load a duplicated copy of the jsm to prevent messing with the currently running one
+var scope = {};
+Services.scriptloader.loadSubScript("resource://gre/modules/Screenshot.jsm", scope);
+const { Screenshot } = scope;
+
+var index = -1;
+function next() {
+ index++;
+ if (index >= steps.length) {
+ assert.ok(false, "Shouldn't get here!");
+ return;
+ }
+ try {
+ steps[index]();
+ } catch(ex) {
+ assert.ok(false, "Caught exception: " + ex);
+ }
+}
+
+var steps = [
+ function getScreenshot() {
+ let screenshot = Screenshot.get();
+ assert.ok(screenshot instanceof File,
+ "Screenshot.get() returns a File");
+ next();
+ },
+
+ function endOfTest() {
+ sendAsyncMessage("finish");
+ }
+];
+
+next();
diff --git a/b2g/components/test/mochitest/systemapp_helper.js b/b2g/components/test/mochitest/systemapp_helper.js
new file mode 100644
index 000000000..768b221fe
--- /dev/null
+++ b/b2g/components/test/mochitest/systemapp_helper.js
@@ -0,0 +1,173 @@
+var Cu = Components.utils;
+
+const { Services } = Cu.import("resource://gre/modules/Services.jsm");
+
+// Load a duplicated copy of the jsm to prevent messing with the currently running one
+var scope = {};
+Services.scriptloader.loadSubScript("resource://gre/modules/SystemAppProxy.jsm", scope);
+const { SystemAppProxy } = scope;
+
+var frame;
+var customEventTarget;
+
+var index = -1;
+function next() {
+ index++;
+ if (index >= steps.length) {
+ assert.ok(false, "Shouldn't get here!");
+ return;
+ }
+ try {
+ steps[index]();
+ } catch(ex) {
+ assert.ok(false, "Caught exception: " + ex);
+ }
+}
+
+// Listen for events received by the system app document
+// to ensure that we receive all of them, in an expected order and time
+var isLoaded = false;
+var isReady = false;
+var n = 0;
+function listener(event) {
+ if (!isLoaded) {
+ assert.ok(false, "Received event before the iframe is loaded");
+ return;
+ }
+ n++;
+ if (n == 1) {
+ assert.equal(event.type, "mozChromeEvent");
+ assert.equal(event.detail.name, "first");
+ } else if (n == 2) {
+ assert.equal(event.type, "custom");
+ assert.equal(event.detail.name, "second");
+
+ next(); // call checkEventPendingBeforeLoad
+ } else if (n == 3) {
+ if (!isReady) {
+ assert.ok(false, "Received event before the iframe is loaded");
+ return;
+ }
+
+ assert.equal(event.type, "custom");
+ assert.equal(event.detail.name, "third");
+ } else if (n == 4) {
+ if (!isReady) {
+ assert.ok(false, "Received event before the iframe is loaded");
+ return;
+ }
+
+ assert.equal(event.type, "mozChromeEvent");
+ assert.equal(event.detail.name, "fourth");
+
+ next(); // call checkEventDispatching
+ } else if (n == 5) {
+ assert.equal(event.type, "custom");
+ assert.equal(event.detail.name, "fifth");
+ } else if (n === 6) {
+ assert.equal(event.type, "mozChromeEvent");
+ assert.equal(event.detail.name, "sixth");
+ } else if (n === 7) {
+ assert.equal(event.type, "custom");
+ assert.equal(event.detail.name, "seventh");
+ assert.equal(event.target, customEventTarget);
+
+ next(); // call checkEventListening();
+ } else {
+ assert.ok(false, "Unexpected event of type " + event.type);
+ }
+}
+
+
+var steps = [
+ function earlyEvents() {
+ // Immediately try to send events
+ SystemAppProxy._sendCustomEvent("mozChromeEvent", { name: "first" }, true);
+ SystemAppProxy._sendCustomEvent("custom", { name: "second" }, true);
+ next();
+ },
+
+ function createFrame() {
+ // Create a fake system app frame
+ let win = Services.wm.getMostRecentWindow("navigator:browser");
+ let doc = win.document;
+ frame = doc.createElement("iframe");
+ doc.documentElement.appendChild(frame);
+
+ customEventTarget = frame.contentDocument.body;
+
+ // Ensure that events are correctly sent to the frame.
+ // `listener` is going to call next()
+ frame.contentWindow.addEventListener("mozChromeEvent", listener);
+ frame.contentWindow.addEventListener("custom", listener);
+
+ // Ensure that listener being registered before the system app is ready
+ // are correctly removed from the pending list
+ function removedListener() {
+ assert.ok(false, "Listener isn't correctly removed from the pending list");
+ }
+ SystemAppProxy.addEventListener("mozChromeEvent", removedListener);
+ SystemAppProxy.removeEventListener("mozChromeEvent", removedListener);
+
+ // Register it to the JSM
+ SystemAppProxy.registerFrame(frame);
+ assert.ok(true, "Frame created and registered");
+
+ frame.contentWindow.addEventListener("load", function onload() {
+ frame.contentWindow.removeEventListener("load", onload);
+ assert.ok(true, "Frame document loaded");
+
+ // Declare that the iframe is now loaded.
+ // That should dispatch early events
+ isLoaded = true;
+ SystemAppProxy.setIsLoaded();
+ assert.ok(true, "Frame declared as loaded");
+
+ let gotFrame = SystemAppProxy.getFrame();
+ assert.equal(gotFrame, frame, "getFrame returns the frame we passed");
+
+ // Once pending events are received,
+ // we will run checkEventDispatching from `listener` function
+ });
+
+ frame.setAttribute("src", "data:text/html,system app");
+ },
+
+ function checkEventPendingBeforeLoad() {
+ // Frame is loaded but not ready,
+ // these events should queue before the System app is ready.
+ SystemAppProxy._sendCustomEvent("custom", { name: "third" });
+ SystemAppProxy.dispatchEvent({ name: "fourth" });
+
+ isReady = true;
+ SystemAppProxy.setIsReady();
+ // Once this 4th event is received, we will run checkEventDispatching
+ },
+
+ function checkEventDispatching() {
+ // Send events after the iframe is ready,
+ // they should be dispatched right away
+ SystemAppProxy._sendCustomEvent("custom", { name: "fifth" });
+ SystemAppProxy.dispatchEvent({ name: "sixth" });
+ SystemAppProxy._sendCustomEvent("custom", { name: "seventh" }, false, customEventTarget);
+ // Once this 7th event is received, we will run checkEventListening
+ },
+
+ function checkEventListening() {
+ SystemAppProxy.addEventListener("mozContentEvent", function onContentEvent(event) {
+ assert.equal(event.detail.name, "first-content", "received a system app event");
+ SystemAppProxy.removeEventListener("mozContentEvent", onContentEvent);
+
+ next();
+ });
+ let win = frame.contentWindow;
+ win.dispatchEvent(new win.CustomEvent("mozContentEvent", { detail: {name: "first-content"} }));
+ },
+
+ function endOfTest() {
+ frame.remove();
+ sendAsyncMessage("finish");
+ }
+];
+
+next();
diff --git a/b2g/components/test/mochitest/test_filepicker_path.html b/b2g/components/test/mochitest/test_filepicker_path.html
new file mode 100644
index 000000000..92c00dc68
--- /dev/null
+++ b/b2g/components/test/mochitest/test_filepicker_path.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=949944
+-->
+<head>
+<meta charset="utf-8">
+<title>Permission Prompt Test</title>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body onload="processTestCase()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=949944"> [B2G][Helix][Browser][Wallpaper] use new File([blob], filename) to return a blob with filename when picking</a>
+<script type="application/javascript">
+
+'use strict';
+
+var testCases = [
+ // case 1: returns blob with name
+ { pickedResult: { success: true,
+ result: {
+ type: 'text/plain',
+ blob: new Blob(['1234567890'],
+ { type: 'text/plain' }),
+ name: 'test1.txt'
+ }
+ },
+ fileName: 'test1.txt' },
+ // case 2: returns blob without name
+ { pickedResult: { success: true,
+ result: {
+ type: 'text/plain',
+ blob: new Blob(['1234567890'],
+ { type: 'text/plain' })
+ }
+ },
+ fileName: 'blob.txt' },
+ // case 3: returns blob with full path name
+ { pickedResult: { success: true,
+ result: {
+ type: 'text/plain',
+ blob: new Blob(['1234567890'],
+ { type: 'text/plain' }),
+ name: '/full/path/test3.txt'
+ }
+ },
+ fileName: 'test3.txt' },
+ // case 4: returns blob relative path name
+ { pickedResult: { success: true,
+ result: {
+ type: 'text/plain',
+ blob: new Blob(['1234567890'],
+ { type: 'text/plain' }),
+ name: 'relative/path/test4.txt'
+ }
+ },
+ fileName: 'test4.txt' },
+ // case 5: returns file with name
+ { pickedResult: { success: true,
+ result: {
+ type: 'text/plain',
+ blob: new File(['1234567890'],
+ 'useless-name.txt',
+ { type: 'text/plain' }),
+ name: 'test5.txt'
+ }
+ },
+ fileName: 'test5.txt'},
+ // case 6: returns file without name. This case may fail because we
+ // need to make sure the File can be sent through
+ // sendAsyncMessage API.
+ { pickedResult: { success: true,
+ result: {
+ type: 'text/plain',
+ blob: new File(['1234567890'],
+ 'test6.txt',
+ { type: 'text/plain' })
+ }
+ },
+ fileName: 'test6.txt'}
+];
+
+var chromeJS = SimpleTest.getTestFileURL('filepicker_path_handler_chrome.js');
+var chromeScript = SpecialPowers.loadChromeScript(chromeJS);
+var activeTestCase;
+
+chromeScript.addMessageListener('pick-result-updated', handleMessage);
+chromeScript.addMessageListener('file-picked-posted', handleMessage);
+
+// handle messages returned from chromeScript
+function handleMessage(data) {
+ var fileInput = document.getElementById('fileInput');
+ switch (data.type) {
+ case 'pick-result-updated':
+ fileInput.click();
+ break;
+ case 'file-picked-posted':
+ is(fileInput.value, activeTestCase.fileName,
+ 'File should be able to send through message.');
+ processTestCase();
+ break;
+ }
+}
+
+function processTestCase() {
+ if (!testCases.length) {
+ SimpleTest.finish();
+ return;
+ }
+ activeTestCase = testCases.shift();
+ var expectedResult = activeTestCase.pickedResult;
+ if (navigator.userAgent.indexOf('Windows') > -1 &&
+ expectedResult.result.name) {
+ // If we run at a window box, we need to translate the path from '/' to '\\'
+ var name = expectedResult.result.name;
+ name = name.replace('/', '\\');
+ // If the name is an absolute path, we need to prepend drive letter.
+ if (name.startsWith('\\')) {
+ name = 'C:' + name;
+ }
+ // update the expected name.
+ expectedResult.result.name = name
+ }
+ chromeScript.sendAsyncMessage('update-pick-result', expectedResult);
+}
+
+</script>
+<input type="file" id="fileInput">
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_permission_deny.html b/b2g/components/test/mochitest/test_permission_deny.html
new file mode 100644
index 000000000..29c35bdec
--- /dev/null
+++ b/b2g/components/test/mochitest/test_permission_deny.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=981113
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Permission Deny Test</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=981113">Test Permission Deny</a>
+<script type="application/javascript;version=1.8">
+
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+const PROMPT_ACTION = SpecialPowers.Ci.nsIPermissionManager.PROMPT_ACTION;
+
+var gUrl = SimpleTest.getTestFileURL('permission_handler_chrome.js');
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+var gTests = [
+ {
+ 'video': true,
+ },
+ {
+ 'audio': true,
+ 'video': true,
+ },
+ {
+ 'audio': true,
+ },
+];
+
+function runNext() {
+ if (gTests.length > 0) {
+ // Put the requested permission in query string
+ let requestedType = gTests.shift();
+ info('getUserMedia for ' + JSON.stringify(requestedType));
+ navigator.mozGetUserMedia(requestedType, function success() {
+ ok(false, 'unexpected success, permission request should be denied');
+ runNext();
+ }, function failure(err) {
+ is(err.name, 'SecurityError', 'expected permission denied');
+ runNext();
+ });
+ } else {
+ info('test finished, teardown');
+ gScript.sendAsyncMessage('teardown', '');
+ gScript.destroy();
+ SimpleTest.finish();
+ }
+}
+
+gScript.addMessageListener('permission-request', function(detail) {
+ let response = {
+ id: detail.id,
+ type: 'permission-deny',
+ remember: false,
+ };
+ gScript.sendAsyncMessage('permission-response', response);
+});
+
+// Need to change camera permission from ALLOW to PROMPT, otherwise
+// MediaManager will automatically allow video-only gUM request.
+SpecialPowers.pushPermissions([
+ {type: 'video-capture', allow: PROMPT_ACTION, context: document},
+ {type: 'audio-capture', allow: PROMPT_ACTION, context: document},
+ {type: 'camera', allow: PROMPT_ACTION, context: document},
+ ], function() {
+ SpecialPowers.pushPrefEnv({
+ 'set': [
+ ['media.navigator.permission.disabled', false],
+ ]
+ }, runNext);
+ }
+);
+</script>
+</pre>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_permission_gum_remember.html b/b2g/components/test/mochitest/test_permission_gum_remember.html
new file mode 100644
index 000000000..1ebfea1ca
--- /dev/null
+++ b/b2g/components/test/mochitest/test_permission_gum_remember.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=978660
+-->
+<head>
+ <meta charset="utf-8">
+ <title>gUM Remember Permission Test</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=978660">Test remembering gUM Permission</a>
+<script type="application/javascript;version=1.8">
+
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+const PROMPT_ACTION = SpecialPowers.Ci.nsIPermissionManager.PROMPT_ACTION;
+
+var gUrl = SimpleTest.getTestFileURL('permission_handler_chrome.js');
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+gScript.addMessageListener('permission-request', function(detail) {
+ ok(false, 'unexpected mozChromeEvent for permission prompt');
+ let response = {
+ id: detail.id,
+ type: 'permission-deny',
+ remember: false,
+ };
+ gScript.sendAsyncMessage('permission-response', response);
+});
+
+var gTests = [
+ {
+ 'audio': true,
+ 'video': {facingMode: 'environment', required: ['facingMode']},
+ },
+ {
+ 'video': {facingMode: 'environment', required: ['facingMode']},
+ },
+ {
+ 'audio': true,
+ },
+];
+
+function testGranted() {
+ info('test remember permission granted');
+ return new Promise(function(resolve, reject) {
+ let steps = [].concat(gTests);
+ function nextStep() {
+ if (steps.length > 0) {
+ let requestedType = steps.shift();
+ info('getUserMedia for ' + JSON.stringify(requestedType));
+ navigator.mozGetUserMedia(requestedType, function success(stream) {
+ ok(true, 'expected gUM success');
+ stream.stop();
+ nextStep();
+ }, function failure(err) {
+ ok(false, 'unexpected gUM fail: ' + err);
+ nextStep();
+ });
+ } else {
+ resolve();
+ }
+ }
+
+ SpecialPowers.pushPermissions([
+ {type: 'video-capture', allow: true, context: document},
+ {type: 'audio-capture', allow: true, context: document},
+ ], nextStep);
+ });
+}
+
+function testDenied() {
+ info('test remember permission denied');
+ return new Promise(function(resolve, reject) {
+ let steps = [].concat(gTests);
+ function nextStep() {
+ if (steps.length > 0) {
+ let requestedType = steps.shift();
+ info('getUserMedia for ' + JSON.stringify(requestedType));
+ navigator.mozGetUserMedia(requestedType, function success(stream) {
+ ok(false, 'unexpected gUM success');
+ stream.stop();
+ nextStep();
+ }, function failure(err) {
+ ok(true, 'expected gUM fail: ' + err);
+ nextStep();
+ });
+ } else {
+ resolve();
+ }
+ }
+
+ SpecialPowers.pushPermissions([
+ {type: 'video-capture', allow: false, context: document},
+ {type: 'audio-capture', allow: false, context: document},
+ ], nextStep);
+ });
+}
+
+function testPartialDeniedAudio() {
+ info('test remember permission partial denied: audio');
+ return new Promise(function(resolve, reject) {
+ info('getUserMedia for video and audio');
+ function nextStep() {
+ navigator.mozGetUserMedia({video: {facingMode: 'environment', required: ['facingMode']},
+ audio: true}, function success(stream) {
+ ok(false, 'unexpected gUM success');
+ stream.stop();
+ resolve();
+ }, function failure(err) {
+ ok(true, 'expected gUM fail: ' + err);
+ resolve();
+ });
+ }
+
+ SpecialPowers.pushPermissions([
+ {type: 'video-capture', allow: true, context: document},
+ {type: 'audio-capture', allow: false, context: document},
+ ], nextStep);
+ });
+}
+
+function testPartialDeniedVideo() {
+ info('test remember permission partial denied: video');
+ return new Promise(function(resolve, reject) {
+ info('getUserMedia for video and audio');
+ function nextStep() {
+ navigator.mozGetUserMedia({video: {facingMode: 'environment', required: ['facingMode']},
+ audio: true}, function success(stream) {
+ ok(false, 'unexpected gUM success');
+ stream.stop();
+ resolve();
+ }, function failure(err) {
+ ok(true, 'expected gUM fail: ' + err);
+ resolve();
+ });
+ }
+
+ SpecialPowers.pushPermissions([
+ {type: 'video-capture', allow: false, context: document},
+ {type: 'audio-capture', allow: true, context: document},
+ ], nextStep);
+ });
+}
+
+function runTests() {
+ testGranted()
+ .then(testDenied)
+ .then(testPartialDeniedAudio)
+ .then(testPartialDeniedVideo)
+ .then(function() {
+ info('test finished, teardown');
+ gScript.sendAsyncMessage('teardown', '');
+ gScript.destroy();
+ SimpleTest.finish();
+ });
+}
+
+SpecialPowers.pushPrefEnv({
+ 'set': [
+ ['media.navigator.permission.disabled', false],
+ ]
+}, runTests);
+</script>
+</pre>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_permission_visibilitychange.html b/b2g/components/test/mochitest/test_permission_visibilitychange.html
new file mode 100644
index 000000000..cd5694b42
--- /dev/null
+++ b/b2g/components/test/mochitest/test_permission_visibilitychange.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=951997
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Permission Prompt Test</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1020179">Permission prompt visibilitychange test</a>
+<script type="application/javascript;version=1.8">
+
+"use strict";
+
+var gUrl = SimpleTest.getTestFileURL("permission_handler_chrome.js");
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+
+function testDone() {
+ gScript.sendAsyncMessage("teardown", "");
+ gScript.destroy();
+ SimpleTest.finish();
+ alert("setVisible::true");
+}
+
+function runTest() {
+ navigator.geolocation.getCurrentPosition(
+ function (pos) {
+ ok(false, "unexpected success, permission request should be canceled");
+ testDone();
+ }, function (err) {
+ ok(true, "success, permission request is canceled");
+ testDone();
+ });
+}
+
+gScript.addMessageListener("permission-request", function (detail) {
+ info("got permission-request!!!!\n");
+ alert("setVisible::false");
+});
+
+// Add permissions to this app. We use ALLOW_ACTION here. The ContentPermissionPrompt
+// should prompt for permission, not allow it without prompt.
+SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
+ function() {
+ SpecialPowers.addPermission("geolocation",
+ SpecialPowers.Ci.nsIPermissionManager.PROMPT_ACTION, document);
+ runTest();
+ });
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_presentation_device_prompt.html b/b2g/components/test/mochitest/test_presentation_device_prompt.html
new file mode 100644
index 000000000..9feeca795
--- /dev/null
+++ b/b2g/components/test/mochitest/test_presentation_device_prompt.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML>
+<html>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Presentation Device Selection</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Test for Presentation Device Selection</a>
+<script type="application/javascript;version=1.8">
+
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+var contentEventHandler = null;
+
+var gUrl = SimpleTest.getTestFileURL('presentation_prompt_handler_chrome.js');
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+
+function testSetup() {
+ info('setup for device selection');
+ return new Promise(function(resolve, reject) {
+ let device = {
+ id: 'test-id',
+ name: 'test-name',
+ type: 'test-type',
+ };
+ gScript.addMessageListener('setup-complete', function() {
+ resolve(device);
+ });
+ gScript.sendAsyncMessage('setup', device);
+ });
+}
+
+function testSelected(device) {
+ info('test device selected by user');
+ return new Promise(function(resolve, reject) {
+ let request = {
+ origin: 'test-origin',
+ requestURL: 'test-requestURL',
+ };
+
+ gScript.addMessageListener('presentation-select-device', function contentEventHandler(detail) {
+ gScript.removeMessageListener('presentation-select-device', contentEventHandler);
+ ok(true, 'receive user prompt for device selection');
+ is(detail.origin, request.origin, 'expected origin');
+ is(detail.requestURL, request.requestURL, 'expected requestURL');
+ let response = {
+ id: detail.id,
+ type: 'presentation-select-result',
+ deviceId: device.id,
+ };
+ gScript.sendAsyncMessage('presentation-select-response', response);
+
+ gScript.addMessageListener('presentation-select-result', function resultHandler(result) {
+ gScript.removeMessageListener('presentation-select-result', resultHandler);
+ is(result.type, 'select', 'expect device selected');
+ is(result.device.id, device.id, 'expected device id');
+ is(result.device.name, device.name, 'expected device name');
+ is(result.device.type, device.type, 'expected devcie type');
+ resolve();
+ });
+ });
+
+ gScript.sendAsyncMessage('trigger-device-prompt', request);
+ });
+}
+
+function testSelectedNotExisted() {
+ info('test selected device doesn\'t exist');
+ return new Promise(function(resolve, reject) {
+ gScript.addMessageListener('presentation-select-device', function contentEventHandler(detail) {
+ gScript.removeMessageListener('presentation-select-device', contentEventHandler);
+ ok(true, 'receive user prompt for device selection');
+ let response = {
+ id: detail.id,
+ type: 'presentation-select-deny',
+ deviceId: undefined, // simulate device Id that doesn't exist
+ };
+ gScript.sendAsyncMessage('presentation-select-response', response);
+
+ gScript.addMessageListener('presentation-select-result', function resultHandler(result) {
+ gScript.removeMessageListener('presentation-select-result', resultHandler);
+ is(result.type, 'cancel', 'expect user cancel');
+ resolve();
+ });
+ });
+
+ let request = {
+ origin: 'test-origin',
+ requestURL: 'test-requestURL',
+ };
+ gScript.sendAsyncMessage('trigger-device-prompt', request);
+ });
+}
+
+function testDenied() {
+ info('test denial of device selection');
+ return new Promise(function(resolve, reject) {
+ gScript.addMessageListener('presentation-select-device', function contentEventHandler(detail) {
+ gScript.removeMessageListener('presentation-select-device', contentEventHandler);
+ ok(true, 'receive user prompt for device selection');
+ let response = {
+ id: detail.id,
+ type: 'presentation-select-deny',
+ };
+ gScript.sendAsyncMessage('presentation-select-response', response);
+
+ gScript.addMessageListener('presentation-select-result', function resultHandler(result) {
+ gScript.removeMessageListener('presentation-select-result', resultHandler);
+ is(result.type, 'cancel', 'expect user cancel');
+ resolve();
+ });
+ });
+
+ let request = {
+ origin: 'test-origin',
+ requestURL: 'test-requestURL',
+ };
+ gScript.sendAsyncMessage('trigger-device-prompt', request);
+ });
+}
+
+function runTests() {
+ testSetup()
+ .then(testSelected)
+ .then(testSelectedNotExisted)
+ .then(testDenied)
+ .then(function() {
+ info('test finished, teardown');
+ gScript.sendAsyncMessage('teardown');
+ gScript.destroy();
+ SimpleTest.finish();
+ });
+}
+
+window.addEventListener('load', runTests);
+</script>
+</pre>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_presentation_request_ui_glue.html b/b2g/components/test/mochitest/test_presentation_request_ui_glue.html
new file mode 100644
index 000000000..29ac37221
--- /dev/null
+++ b/b2g/components/test/mochitest/test_presentation_request_ui_glue.html
@@ -0,0 +1,105 @@
+<!DOCTYPE HTML>
+<html>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Presentation UI Glue</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Test for Presentation UI Glue</a>
+<script type="application/javascript;version=1.8">
+
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('presentation_ui_glue_handler_chrome.js'));
+
+var obs = SpecialPowers.Cc["@mozilla.org/observer-service;1"]
+ .getService(SpecialPowers.Ci.nsIObserverService);
+
+var url = 'http://example.com';
+var sessionId = 'sessionId';
+
+function testLaunchReceiver() {
+ return new Promise(function(aResolve, aReject) {
+ gScript.addMessageListener('presentation-launch-receiver', function launchReceiverHandler(aDetail) {
+ gScript.removeMessageListener('presentation-launch-receiver', launchReceiverHandler);
+ ok(true, "A presentation-launch-receiver mozPresentationChromeEvent should be received.");
+ is(aDetail.url, url, "Url should be the same.");
+ is(aDetail.id, sessionId, "Session ID should be the same.");
+
+ aResolve();
+ });
+
+ gScript.sendAsyncMessage('trigger-ui-glue',
+ { url: url,
+ sessionId : sessionId });
+ });
+}
+
+function testReceiverLaunched() {
+ return new Promise(function(aResolve, aReject) {
+ gScript.addMessageListener('iframe-resolved', function iframeResolvedHandler(aFrame) {
+ gScript.removeMessageListener('iframe-resolved', iframeResolvedHandler);
+ ok(true, "The promise should be resolved.");
+
+ aResolve();
+ });
+
+ var iframe = document.createElement('iframe');
+ iframe.setAttribute('remote', 'true');
+ iframe.setAttribute('mozbrowser', 'true');
+ iframe.setAttribute('src', 'http://example.com');
+ document.body.appendChild(iframe);
+
+ gScript.sendAsyncMessage('trigger-presentation-content-event',
+ { type: 'presentation-receiver-launched',
+ id: sessionId,
+ frame: iframe });
+ });
+}
+
+function testLaunchError() {
+ return new Promise(function(aResolve, aReject) {
+ gScript.addMessageListener('presentation-launch-receiver', function launchReceiverHandler(aDetail) {
+ gScript.removeMessageListener('presentation-launch-receiver', launchReceiverHandler);
+ ok(true, "A presentation-launch-receiver mozPresentationChromeEvent should be received.");
+ is(aDetail.url, url, "Url should be the same.");
+ is(aDetail.id, sessionId, "Session ID should be the same.");
+
+ gScript.addMessageListener('iframe-rejected', function iframeRejectedHandler() {
+ gScript.removeMessageListener('iframe-rejected', iframeRejectedHandler);
+ ok(true, "The promise should be rejected.");
+ aResolve();
+ });
+
+ gScript.sendAsyncMessage('trigger-presentation-content-event',
+ { type: 'presentation-receiver-permission-denied',
+ id: sessionId });
+ });
+
+ gScript.sendAsyncMessage('trigger-ui-glue',
+ { url: url,
+ sessionId : sessionId });
+ });
+}
+
+function runTests() {
+ testLaunchReceiver()
+ .then(testReceiverLaunched)
+ .then(testLaunchError)
+ .then(function() {
+ info('test finished, teardown');
+ gScript.destroy();
+ SimpleTest.finish();
+ });
+}
+
+window.addEventListener('load', runTests);
+</script>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_sandbox_permission.html b/b2g/components/test/mochitest/test_sandbox_permission.html
new file mode 100644
index 000000000..cd13599a3
--- /dev/null
+++ b/b2g/components/test/mochitest/test_sandbox_permission.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=951997
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Permission Prompt Test</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=951997">Permission prompt web content test</a>
+<script type="application/javascript;version=1.8">
+
+"use strict";
+
+const APP_URL = "SandboxPromptTest.html";
+
+var iframe;
+var gUrl = SimpleTest.getTestFileURL("permission_handler_chrome.js");
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+var gResult = [
+ {
+ "video-capture": ["back"],
+ },
+ {
+ "audio-capture": [""],
+ "video-capture": ["back"],
+ },
+ {
+ "audio-capture": [""],
+ },
+ {
+ "geolocation": [],
+ },
+ {
+ "desktop-notification": [],
+ }
+];
+
+function runNext() {
+ if (gResult.length > 0) {
+ // Put the requested permission in query string
+ let requestedPermission = JSON.stringify(Object.keys(gResult[0]));
+ info('request permissions for ' + requestedPermission);
+ iframe.src = APP_URL + '?' + encodeURIComponent(requestedPermission);
+ } else {
+ info('test finished, teardown');
+ gScript.sendAsyncMessage("teardown", "");
+ gScript.destroy();
+ SimpleTest.finish();
+ }
+}
+
+// Create a sanbox iframe.
+function loadBrowser() {
+ iframe = document.createElement("iframe");
+ SpecialPowers.wrap(iframe).mozbrowser = true;
+ iframe.src = 'about:blank';
+ document.body.appendChild(iframe);
+
+ iframe.addEventListener("load", function onLoad() {
+ iframe.removeEventListener("load", onLoad);
+ runNext();
+ });
+}
+
+gScript.addMessageListener("permission-request", function (detail) {
+ let permissions = detail.permissions;
+ let expectedValue = gResult.shift();
+ let permissionTypes = Object.keys(permissions);
+
+ is(permissionTypes.length, Object.keys(expectedValue).length, "expected number of permissions");
+
+ for (let type of permissionTypes) {
+ ok(expectedValue.hasOwnProperty(type), "expected permission type");
+ for (let i in permissions[type]) {
+ is(permissions[type][i], expectedValue[type][i], "expected permission option");
+ }
+ }
+ runNext();
+});
+
+// Add permissions to this app. We use ALLOW_ACTION here. The ContentPermissionPrompt
+// should prompt for permission, not allow it without prompt.
+SpecialPowers.pushPrefEnv({"set": [["media.navigator.permission.disabled", false]]},
+ function() {
+ SpecialPowers.addPermission('video-capture',
+ SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
+ SpecialPowers.addPermission('audio-capture',
+ SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
+ SpecialPowers.addPermission('geolocation',
+ SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
+ SpecialPowers.addPermission('desktop-notification',
+ SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION, document);
+ loadBrowser();
+ });
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_screenshot.html b/b2g/components/test/mochitest/test_screenshot.html
new file mode 100644
index 000000000..d2eeb8d48
--- /dev/null
+++ b/b2g/components/test/mochitest/test_screenshot.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1136784
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Screenshot Test</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1136784">Screenshot.jsm</a>
+<script type="application/javascript">
+
+"use strict";
+
+var gUrl = SimpleTest.getTestFileURL("screenshot_helper.js");
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+
+SimpleTest.waitForExplicitFinish();
+gScript.addMessageListener("finish", function () {
+ SimpleTest.ok(true, "chrome test script finished");
+ gScript.destroy();
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/b2g/components/test/mochitest/test_systemapp.html b/b2g/components/test/mochitest/test_systemapp.html
new file mode 100644
index 000000000..450094a50
--- /dev/null
+++ b/b2g/components/test/mochitest/test_systemapp.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=963239
+-->
+<head>
+ <meta charset="utf-8">
+ <title>SystemAppProxy Test</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=963239">SystemAppProxy.jsm</a>
+<script type="application/javascript">
+
+"use strict";
+
+var gUrl = SimpleTest.getTestFileURL("systemapp_helper.js");
+var gScript = SpecialPowers.loadChromeScript(gUrl);
+
+SimpleTest.waitForExplicitFinish();
+gScript.addMessageListener("finish", function () {
+ SimpleTest.ok(true, "chrome test script finished");
+ gScript.destroy();
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>