Bug 1238160 - Test mozbrowser APIs to ensure no content exposure. r=bz
Check the various mozbrowser APIs to ensure they are allowed when you have
browser permission and blocked when you don't (like regular web content).
MozReview-Commit-ID: FPDA1lEUwRq
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -253,16 +253,17 @@ support-files =
iframe_postMessages.html
test_performance_observer.js
performance_observer.html
test_anonymousContent_style_csp.html^headers^
file_explicit_user_agent.sjs
referrer_change_server.sjs
file_change_policy_redirect.html
file_bug1198095.js
+ mozbrowser_api_utils.js
[test_anonymousContent_api.html]
[test_anonymousContent_append_after_reflow.html]
[test_anonymousContent_canvas.html]
skip-if = buildapp == 'b2g' # Requires webgl support
[test_anonymousContent_insert.html]
[test_anonymousContent_manipulate_content.html]
[test_anonymousContent_style_csp.html]
@@ -865,8 +866,10 @@ support-files = worker_postMessages.js
skip-if = e10s || os != 'linux' || buildapp != 'browser'
[test_explicit_user_agent.html]
[test_change_policy.html]
skip-if = buildapp == 'b2g' #no ssl support
[test_document.all_iteration.html]
[test_bug1198095.html]
[test_bug1187157.html]
[test_bug769117.html]
+[test_mozbrowser_apis_allowed.html]
+[test_mozbrowser_apis_blocked.html]
new file mode 100644
--- /dev/null
+++ b/dom/base/test/mozbrowser_api_utils.js
@@ -0,0 +1,72 @@
+const FRAME_URL = "http://example.org/";
+
+const METHODS = {
+ setVisible: {},
+ getVisible: {},
+ setActive: {},
+ getActive: {},
+ addNextPaintListener: {},
+ removeNextPaintListener: {},
+ sendMouseEvent: {},
+ sendTouchEvent: {},
+ goBack: {},
+ goForward: {},
+ reload: {},
+ stop: {},
+ download: {},
+ purgeHistory: {},
+ getScreenshot: {},
+ zoom: {},
+ getCanGoBack: {},
+ getCanGoForward: {},
+ getContentDimensions: {},
+ setInputMethodActive: { alwaysFails: true }, // needs input-manage
+ setNFCFocus: { alwaysFails: true }, // needs nfc-manager
+ findAll: {},
+ findNext: {},
+ clearMatch: {},
+ executeScript: { alwaysFails: true }, // needs browser:universalxss
+ getStructuredData: {},
+ getWebManifest: {},
+ mute: {},
+ unmute: {},
+ getMuted: {},
+ setVolume: {},
+ getVolume: {},
+};
+
+const ATTRIBUTES = [
+ "allowedAudioChannels",
+];
+
+function once(target, eventName, useCapture = false) {
+ info("Waiting for event: '" + eventName + "' on " + target + ".");
+
+ return new Promise(resolve => {
+ for (let [add, remove] of [
+ ["addEventListener", "removeEventListener"],
+ ["addMessageListener", "removeMessageListener"],
+ ]) {
+ if ((add in target) && (remove in target)) {
+ target[add](eventName, function onEvent(...aArgs) {
+ info("Got event: '" + eventName + "' on " + target + ".");
+ target[remove](eventName, onEvent, useCapture);
+ resolve(aArgs);
+ }, useCapture);
+ break;
+ }
+ }
+ });
+}
+
+function* loadFrame(attributes = {}) {
+ let iframe = document.createElement("iframe");
+ iframe.setAttribute("src", FRAME_URL);
+ for (let key in attributes) {
+ iframe.setAttribute(key, attributes[key]);
+ }
+ let loaded = once(iframe, "load");
+ document.body.appendChild(iframe);
+ yield loaded;
+ return iframe;
+}
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_mozbrowser_apis_allowed.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Verify mozbrowser APIs are allowed with browser permission</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="mozbrowser_api_utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body>
+<script type="application/javascript;version=1.8">
+ add_task(function*() {
+ yield new Promise(resolve => {
+ SpecialPowers.pushPrefEnv(
+ { "set": [["dom.mozBrowserFramesEnabled", true]] },
+ resolve);
+ });
+ });
+
+ add_task(function*() {
+ yield new Promise(resolve => {
+ SpecialPowers.pushPermissions([
+ { "type": "browser", "allow": 1, "context": document }
+ ], resolve);
+ });
+ });
+
+ add_task(function*() {
+ // Create <iframe mozbrowser>
+ let frame = yield loadFrame({
+ mozbrowser: "true"
+ });
+
+ // Verify that mozbrowser APIs are accessible
+ for (let method in METHODS) {
+ let { alwaysFails } = METHODS[method];
+ if (alwaysFails) {
+ ok(!(method in frame), `frame does not have method ${method}, ` +
+ `needs more permissions`);
+ } else {
+ ok(method in frame, `frame has method ${method}`);
+ }
+ }
+ for (let attribute of ATTRIBUTES) {
+ ok(attribute in frame, `frame has attribute ${attribute}`);
+ }
+ });
+</script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_mozbrowser_apis_blocked.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Verify mozbrowser APIs are blocked without browser permission</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <script type="text/javascript" src="mozbrowser_api_utils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+
+<body>
+<script type="application/javascript;version=1.8">
+ add_task(function*() {
+ yield new Promise(resolve => {
+ SpecialPowers.pushPrefEnv(
+ { "set": [["dom.mozBrowserFramesEnabled", true]] },
+ resolve);
+ });
+ });
+
+ add_task(function*() {
+ // Create <iframe mozbrowser>
+ let frame = yield loadFrame({
+ mozbrowser: "true"
+ });
+
+ // Verify that mozbrowser APIs are not accessible
+ for (let method in METHODS) {
+ ok(!(method in frame), `frame does not have method ${method}`);
+ }
+ for (let attribute of ATTRIBUTES) {
+ ok(!(attribute in frame), `frame does not have attribute ${attribute}`);
+ }
+ });
+</script>
+</body>
+</html>