Bug 1331968: Implement the moz: protocol handler to redirect to a fixed website. r?gijs draft
authorDave Townsend <dtownsend@oxymoronical.com>
Wed, 18 Jan 2017 14:10:46 -0800
changeset 463910 a0352696e8c375adedbeb468ea8865f04bb1f303
parent 463251 7715d62057e50fdafddeca167ecf2d1dbd79b35b
child 542812 96235ae65e8f70286324dd6090766e0e5ab9d06c
push id42220
push userdtownsend@mozilla.com
push dateFri, 20 Jan 2017 00:28:02 +0000
reviewersgijs
bugs1331968
milestone53.0a1
Bug 1331968: Implement the moz: protocol handler to redirect to a fixed website. r?gijs The protocol handler is intentionally simple. It works for the entering into the urlbar case but not a lot else. Included some basic tests. MozReview-Commit-ID: 4FQ1irdt3Nj
browser/components/BrowserComponents.manifest
browser/components/moz.build
browser/components/mozProtocolHandler.js
browser/components/tests/browser/browser.ini
browser/components/tests/browser/browser_mozprotocol.js
browser/components/tests/browser/mozprotocol.html
browser/installer/package-manifest.in
caps/tests/mochitest/browser_checkloaduri.js
--- a/browser/components/BrowserComponents.manifest
+++ b/browser/components/BrowserComponents.manifest
@@ -37,8 +37,11 @@ category command-line-validator b-browse
 
 component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js
 contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc}
 category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
 #ifndef MOZ_MULET
 contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}
 #endif
+
+component {47a45e5f-691e-4799-8686-14f8d3fc0f8c} mozProtocolHandler.js
+contract @mozilla.org/network/protocol;1?name=moz {47a45e5f-691e-4799-8686-14f8d3fc0f8c}
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -36,16 +36,17 @@ XPIDL_SOURCES += [
 
 XPIDL_MODULE = 'browsercompsbase'
 
 EXTRA_PP_COMPONENTS += [
     'BrowserComponents.manifest',
 ]
 
 EXTRA_COMPONENTS += [
+    'mozProtocolHandler.js',
     'nsBrowserContentHandler.js',
     'nsBrowserGlue.js',
 ]
 
 EXTRA_JS_MODULES += [
     'distribution.js',
 ]
 
new file mode 100644
--- /dev/null
+++ b/browser/components/mozProtocolHandler.js
@@ -0,0 +1,49 @@
+/* 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/. */
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+
+function mozProtocolHandler() {
+  XPCOMUtils.defineLazyPreferenceGetter(this, "urlToLoad", "browser.mozprotocol.url",
+                                        "https://www.mozilla.org/protocol");
+}
+
+mozProtocolHandler.prototype = {
+  scheme: "moz",
+  defaultPort: -1,
+  protocolFlags: Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD,
+
+  newURI(spec, charset, base) {
+    let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
+    if (base) {
+      uri.spec = base.resolve(spec);
+    } else {
+      uri.spec = spec;
+    }
+    return uri;
+  },
+
+  newChannel2(uri, loadInfo) {
+    let realURL = NetUtil.newURI(this.urlToLoad);
+    let channel = Services.io.newChannelFromURIWithLoadInfo(realURL, loadInfo)
+    channel.loadFlags |= Ci.nsIChannel.LOAD_REPLACE;
+    return channel;
+  },
+
+  newChannel(uri) {
+    return this.newChannel(uri, null);
+  },
+
+  classID: Components.ID("{47a45e5f-691e-4799-8686-14f8d3fc0f8c}"),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([mozProtocolHandler]);
--- a/browser/components/tests/browser/browser.ini
+++ b/browser/components/tests/browser/browser.ini
@@ -1,6 +1,9 @@
 [DEFAULT]
 
 [browser_bug538331.js]
 skip-if = !updater
 reason = test depends on update channel
 [browser_contentpermissionprompt.js]
+[browser_mozprotocol.js]
+support-files = 
+  mozprotocol.html
new file mode 100644
--- /dev/null
+++ b/browser/components/tests/browser/browser_mozprotocol.js
@@ -0,0 +1,14 @@
+// Check that entering moz://a into the address bar directs us to a new url
+add_task(function*() {
+  let path = getRootDirectory(gTestPath).substring("chrome://mochitests/content/".length);
+  yield SpecialPowers.pushPrefEnv({
+    set: [["browser.mozprotocol.url", `https://example.com/${path}mozprotocol.html`]],
+  });
+
+  yield BrowserTestUtils.withNewTab("about:blank", function*() {
+    gBrowser.loadURI("moz://a");
+    yield BrowserTestUtils.waitForLocationChange(gBrowser,
+      `https://example.com/${path}mozprotocol.html`);
+    ok(true, "Made it to the expected page");
+  });
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/tests/browser/mozprotocol.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+<p><a id="link" href="moz://a">Test</a></p>
+</body>
+</html>
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -356,16 +356,17 @@
 @BINPATH@/components/nsDNSServiceDiscovery.manifest
 @BINPATH@/components/nsDNSServiceDiscovery.js
 #endif
 @RESPATH@/browser/components/BrowserFeeds.manifest
 @RESPATH@/browser/components/FeedConverter.js
 @RESPATH@/browser/components/FeedWriter.js
 @RESPATH@/browser/components/WebContentConverter.js
 @RESPATH@/browser/components/BrowserComponents.manifest
+@RESPATH@/browser/components/mozProtocolHandler.js
 @RESPATH@/browser/components/nsBrowserContentHandler.js
 @RESPATH@/browser/components/nsBrowserGlue.js
 @RESPATH@/browser/components/nsSetDefaultBrowser.manifest
 @RESPATH@/browser/components/nsSetDefaultBrowser.js
 @RESPATH@/browser/components/devtools-startup.manifest
 @RESPATH@/browser/components/devtools-startup.js
 @RESPATH@/browser/components/webideCli.js
 @RESPATH@/browser/components/webideComponents.manifest
--- a/caps/tests/mochitest/browser_checkloaduri.js
+++ b/caps/tests/mochitest/browser_checkloaduri.js
@@ -16,58 +16,62 @@ const URLs = new Map([
     ["feed:chrome://foo/content/bar.xul", false, false, false],
     ["view-source:http://www.example2.com", false, false, true],
     ["view-source:https://www.example2.com", false, false, true],
     ["view-source:feed:http://www.example2.com", false, false, true],
     ["feed:view-source:http://www.example2.com", false, false, false],
     ["data:text/html,Hi", true, false, true],
     ["view-source:data:text/html,Hi", false, false, true],
     ["javascript:alert('hi')", true, false, true],
+    ["moz://a", false, false, true],
   ]],
   ["feed:http://www.example.com", [
     ["http://www.example2.com", true, true, true],
     ["feed:http://www.example2.com", true, true, true],
     ["https://www.example2.com", true, true, true],
     ["feed:https://www.example2.com", true, true, true],
     ["chrome://foo/content/bar.xul", false, false, true],
     ["feed:chrome://foo/content/bar.xul", false, false, false],
     ["view-source:http://www.example2.com", false, false, true],
     ["view-source:https://www.example2.com", false, false, true],
     ["view-source:feed:http://www.example2.com", false, false, true],
     ["feed:view-source:http://www.example2.com", false, false, false],
     ["data:text/html,Hi", true, false, true],
     ["view-source:data:text/html,Hi", false, false, true],
     ["javascript:alert('hi')", true, false, true],
+    ["moz://a", false, false, true],
   ]],
   ["view-source:http://www.example.com", [
     ["http://www.example2.com", true, true, true],
     ["feed:http://www.example2.com", false, false, true],
     ["https://www.example2.com", true, true, true],
     ["feed:https://www.example2.com", false, false, true],
     ["chrome://foo/content/bar.xul", false, false, true],
     ["feed:chrome://foo/content/bar.xul", false, false, false],
     ["view-source:http://www.example2.com", true, true, true],
     ["view-source:https://www.example2.com", true, true, true],
     ["view-source:feed:http://www.example2.com", false, false, true],
     ["feed:view-source:http://www.example2.com", false, false, false],
     ["data:text/html,Hi", true, false, true],
     ["view-source:data:text/html,Hi", true, false, true],
     ["javascript:alert('hi')", true, false, true],
+    ["moz://a", false, false, true],
   ]],
   ["about:foo", [
     ["about:foo?", true, true, true],
     ["about:foo?bar", true, true, true],
     ["about:foo#", true, true, true],
     ["about:foo#bar", true, true, true],
     ["about:foo?#", true, true, true],
     ["about:foo?bar#baz", true, true, true],
     ["about:bar", false, false, true],
     ["about:bar?foo#baz", false, false, true],
     ["about:bar?foo", false, false, true],
     ["http://www.example.com/", true, true, true],
+    ["moz://a", false, false, true],
   ]],
 ]);
 
 function testURL(source, target, canLoad, canLoadWithoutInherit, canCreate, flags) {
   let threw = false;
   let targetURI;
   try {
     targetURI = makeURI(target);