Part 2: Bug 1295807 - Implement the Proxy API. r=kmag
MozReview-Commit-ID: KCoak15Mic8
This commit is contained in:
62
toolkit/components/extensions/ext-proxy.js
Normal file
62
toolkit/components/extensions/ext-proxy.js
Normal 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(),
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
49
toolkit/components/extensions/schemas/proxy.json
Normal file
49
toolkit/components/extensions/schemas/proxy.json
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -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]
|
||||
|
||||
100
toolkit/components/extensions/test/mochitest/test_ext_proxy.html
Normal file
100
toolkit/components/extensions/test/mochitest/test_ext_proxy.html
Normal 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>
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user