Part 2: Bug 1295807 - Implement the Proxy API. r=kmag

MozReview-Commit-ID: KCoak15Mic8
This commit is contained in:
Matthew Wein
2017-03-03 02:16:01 +00:00
parent 7c3aae7284
commit b55d4608af
8 changed files with 289 additions and 1 deletions

View File

@@ -0,0 +1,62 @@
/* 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/. */
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";
var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ProxyScriptContext",
"resource://gre/modules/ProxyScriptContext.jsm");
var {
SingletonEventManager,
} = ExtensionUtils;
// WeakMap[Extension -> ProxyScriptContext]
let proxyScriptContextMap = new WeakMap();
/* eslint-disable mozilla/balanced-listeners */
extensions.on("shutdown", (type, extension) => {
let proxyScriptContext = proxyScriptContextMap.get(extension);
if (proxyScriptContext) {
proxyScriptContext.unload();
proxyScriptContextMap.delete(extension);
}
});
/* eslint-enable mozilla/balanced-listeners */
extensions.registerSchemaAPI("proxy", "addon_parent", context => {
let {extension} = context;
return {
proxy: {
registerProxyScript: (url) => {
// Unload the current proxy script if one is loaded.
if (proxyScriptContextMap.has(extension)) {
proxyScriptContextMap.get(extension).unload();
proxyScriptContextMap.delete(extension);
}
let proxyScriptContext = new ProxyScriptContext(extension, url);
if (proxyScriptContext.load()) {
proxyScriptContextMap.set(extension, proxyScriptContext);
}
},
onProxyError: new SingletonEventManager(context, "proxy.onProxyError", fire => {
let listener = (name, error) => {
fire.async(error);
};
extension.on("proxy-error", listener);
return () => {
extension.off("proxy-error", listener);
};
}).api(),
},
};
});

View File

@@ -12,6 +12,75 @@ category webextension-scripts idle chrome://extensions/content/ext-idle.js
category webextension-scripts management chrome://extensions/content/ext-management.js
category webextension-scripts notifications chrome://extensions/content/ext-notifications.js
category webextension-scripts privacy chrome://extensions/content/ext-privacy.js
category webextension-scripts proxy chrome://extensions/content/ext-proxy.js
category webextension-scripts runtime chrome://extensions/content/ext-runtime.js
category webextension-scripts storage chrome://extensions/content/ext-storage.js
category webextension-scripts theme chrome://extensions/content/ext-theme.js
category webextension-scripts topSites chrome://extensions/content/ext-topSites.js
category webextension-scripts webNavigation chrome://extensions/content/ext-webNavigation.js
category webextension-scripts webRequest chrome://extensions/content/ext-webRequest.js
# scripts specific for content process.
category webextension-scripts-content extension chrome://extensions/content/ext-c-extension.js
category webextension-scripts-content i18n chrome://extensions/content/ext-i18n.js
category webextension-scripts-content runtime chrome://extensions/content/ext-c-runtime.js
category webextension-scripts-content storage chrome://extensions/content/ext-c-storage.js
category webextension-scripts-content test chrome://extensions/content/ext-c-test.js
# scripts specific for devtools extension contexts.
category webextension-scripts-devtools extension chrome://extensions/content/ext-c-extension.js
category webextension-scripts-devtools i18n chrome://extensions/content/ext-i18n.js
category webextension-scripts-devtools runtime chrome://extensions/content/ext-c-runtime.js
category webextension-scripts-devtools storage chrome://extensions/content/ext-c-storage.js
category webextension-scripts-devtools test chrome://extensions/content/ext-c-test.js
# scripts that must run in the same process as addon code.
category webextension-scripts-addon backgroundPage chrome://extensions/content/ext-c-backgroundPage.js
category webextension-scripts-addon extension chrome://extensions/content/ext-c-extension.js
category webextension-scripts-addon i18n chrome://extensions/content/ext-i18n.js
#ifndef ANDROID
category webextension-scripts-addon identity chrome://extensions/content/ext-c-identity.js
#endif
category webextension-scripts-addon runtime chrome://extensions/content/ext-c-runtime.js
category webextension-scripts-addon storage chrome://extensions/content/ext-c-storage.js
category webextension-scripts-addon test chrome://extensions/content/ext-c-test.js
# schemas
category webextension-schemas alarms chrome://extensions/content/schemas/alarms.json
category webextension-schemas contextualIdentities chrome://extensions/content/schemas/contextual_identities.json
category webextension-schemas cookies chrome://extensions/content/schemas/cookies.json
category webextension-schemas downloads chrome://extensions/content/schemas/downloads.json
category webextension-schemas events chrome://extensions/content/schemas/events.json
category webextension-schemas extension chrome://extensions/content/schemas/extension.json
category webextension-schemas extension_types chrome://extensions/content/schemas/extension_types.json
category webextension-schemas handlers chrome://extensions/content/schemas/extension_protocol_handlers.json
category webextension-schemas i18n chrome://extensions/content/schemas/i18n.json
#ifndef ANDROID
category webextension-schemas identity chrome://extensions/content/schemas/identity.json
#endif
category webextension-schemas idle chrome://extensions/content/schemas/idle.json
category webextension-schemas management chrome://extensions/content/schemas/management.json
category webextension-schemas native_host_manifest chrome://extensions/content/schemas/native_host_manifest.json
category webextension-schemas notifications chrome://extensions/content/schemas/notifications.json
category webextension-schemas privacy chrome://extensions/content/schemas/privacy.json
category webextension-schemas proxy chrome://extensions/content/schemas/proxy.json
category webextension-schemas runtime chrome://extensions/content/schemas/runtime.json
category webextension-schemas storage chrome://extensions/content/schemas/storage.json
category webextension-schemas test chrome://extensions/content/schemas/test.json
category webextension-schemas theme chrome://extensions/content/schemas/theme.json# scripts
category webextension-scripts alarms chrome://extensions/content/ext-alarms.js
category webextension-scripts backgroundPage chrome://extensions/content/ext-backgroundPage.js
category webextension-scripts contextualIdentities chrome://extensions/content/ext-contextualIdentities.js
category webextension-scripts cookies chrome://extensions/content/ext-cookies.js
category webextension-scripts downloads chrome://extensions/content/ext-downloads.js
category webextension-scripts extension chrome://extensions/content/ext-extension.js
category webextension-scripts geolocation chrome://extensions/content/ext-geolocation.js
category webextension-scripts handlers chrome://extensions/content/ext-protocolHandlers.js
category webextension-scripts i18n chrome://extensions/content/ext-i18n.js
category webextension-scripts idle chrome://extensions/content/ext-idle.js
category webextension-scripts management chrome://extensions/content/ext-management.js
category webextension-scripts notifications chrome://extensions/content/ext-notifications.js
category webextension-scripts privacy chrome://extensions/content/ext-privacy.js
category webextension-scripts runtime chrome://extensions/content/ext-runtime.js
category webextension-scripts storage chrome://extensions/content/ext-storage.js
category webextension-scripts theme chrome://extensions/content/ext-theme.js
@@ -70,3 +139,8 @@ category webextension-schemas top_sites chrome://extensions/content/schemas/top_
category webextension-schemas types chrome://extensions/content/schemas/types.json
category webextension-schemas web_navigation chrome://extensions/content/schemas/web_navigation.json
category webextension-schemas web_request chrome://extensions/content/schemas/web_request.json
category webextension-schemas top_sites chrome://extensions/content/schemas/top_sites.json
category webextension-schemas types chrome://extensions/content/schemas/types.json
category webextension-schemas web_navigation chrome://extensions/content/schemas/web_navigation.json
category webextension-schemas web_request chrome://extensions/content/schemas/web_request.json

View File

@@ -18,6 +18,7 @@ toolkit.jar:
content/extensions/ext-notifications.js
content/extensions/ext-privacy.js
content/extensions/ext-protocolHandlers.js
content/extensions/ext-proxy.js
content/extensions/ext-runtime.js
content/extensions/ext-storage.js
content/extensions/ext-theme.js

View File

@@ -22,6 +22,7 @@ toolkit.jar:
content/extensions/schemas/manifest.json
content/extensions/schemas/native_host_manifest.json
content/extensions/schemas/notifications.json
content/extensions/schemas/proxy.json
content/extensions/schemas/privacy.json
content/extensions/schemas/runtime.json
content/extensions/schemas/storage.json

View File

@@ -0,0 +1,49 @@
[
{
"namespace": "manifest",
"types": [
{
"$extend": "Permission",
"choices": [{
"type": "string",
"enum": [
"proxy"
]
}]
}
]
},
{
"namespace": "proxy",
"description": "Use the browser.proxy API to register proxy scripts in Firefox. Proxy scripts in Firefox are proxy auto-config files with extra contextual information and support for additional return types.",
"permissions": ["proxy"],
"functions": [
{
"name": "registerProxyScript",
"type": "function",
"description": "Registers the proxy script for the extension.",
"async": true,
"parameters": [
{
"name": "url",
"type": "string",
"format": "strictRelativeUrl"
}
]
}
],
"events": [
{
"name": "onProxyError",
"type": "function",
"description": "Notifies about proxy script errors.",
"parameters": [
{
"name": "error",
"type": "object"
}
]
}
]
}
]

View File

@@ -74,6 +74,7 @@ skip-if = os == 'android' # Android does not support multiple windows.
skip-if = os == 'android' # Android support Bug 1336194
[test_ext_notifications.html]
[test_ext_permission_xhr.html]
[test_ext_proxy.html]
[test_ext_runtime_connect.html]
[test_ext_runtime_connect_twoway.html]
[test_ext_runtime_connect2.html]

View File

@@ -0,0 +1,100 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Tests for the proxy API</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="/tests/SimpleTest/ExtensionTestUtils.js"></script>
<script type="text/javascript" src="head.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<script type="text/javascript">
/* eslint no-unused-vars: ["error", {"args": "none", "varsIgnorePattern": "^(FindProxyForURL)$"}] */
"use strict";
function* testProxyScript(script, expected) {
let extension = ExtensionTestUtils.loadExtension({
background() {
browser.proxy.onProxyError.addListener(error => {
browser.test.sendMessage("proxy-error-received", error);
});
browser.proxy.registerProxyScript("proxy_script.js");
},
manifest: {
"permissions": ["proxy"],
},
files: {
"proxy_script.js": String(script).replace(/^.*?\{([^]*)\}$/, "$1"),
},
});
yield extension.startup();
let win = window.open("http://example.com/");
let error = yield extension.awaitMessage("proxy-error-received");
is(error.message, expected.message, "Correct error message received");
win.close();
if (expected.errorInfo) {
ok(error.fileName.includes("proxy_script.js"), "Error should include file name");
is(error.lineNumber, 3, "Error should include line number");
ok(error.stack.includes("proxy_script.js:3:9"), "Error should include stack trace");
}
yield extension.unload();
}
add_task(function* test_invalid_FindProxyForURL_type() {
yield testProxyScript(
() => { }, {
message: "The proxy script must define FindProxyForURL as a function",
});
yield testProxyScript(
() => {
var FindProxyForURL = 5; // eslint-disable-line mozilla/var-only-at-top-level
}, {
message: "The proxy script must define FindProxyForURL as a function",
});
});
add_task(function* test_invalid_FindProxyForURL_return_type() {
yield testProxyScript(
() => {
function FindProxyForURL() {
return 5;
}
}, {
message: "FindProxyForURL: Return type must be a string",
});
yield testProxyScript(
() => {
function FindProxyForURL() {
return "INVALID";
}
}, {
message: "FindProxyForURL: Invalid Proxy Rule: INVALID",
});
});
add_task(function* test_runtime_error_in_FindProxyForURL() {
yield testProxyScript(
() => {
function FindProxyForURL() {
return not_defined; // eslint-disable-line no-undef
}
}, {
message: "not_defined is not defined",
errorInfo: true,
});
});
</script>
</body>
</html>

View File

@@ -1,6 +1,6 @@
"use strict";
/* no-unused-vars": ["error", {"args": "none", "varsIgnorePattern": "^(FindProxyForURL)$"}] */
/* eslint no-unused-vars: ["error", {"args": "none", "varsIgnorePattern": "^(FindProxyForURL)$"}] */
Cu.import("resource://gre/modules/Extension.jsm");
Cu.import("resource://gre/modules/ProxyScriptContext.jsm");