Bug 1399070 move launchWebAuthFlow to parent to fix opening auth window when remote, r=zombie draft
authorShane Caraveo <scaraveo@mozilla.com>
Thu, 14 Sep 2017 09:18:27 -0700
changeset 664929 eaec4890e559e0c969b6d7721ee94dcbda85c4f6
parent 664928 943c2c2a1daf5cd0d3287c1974eb510615d5ed5b
child 731592 df734dc98f6a21ce17e8aef49f895f4d51a24eb6
push id79861
push usermixedpuppy@gmail.com
push dateThu, 14 Sep 2017 16:18:51 +0000
reviewerszombie
bugs1399070
milestone57.0a1
Bug 1399070 move launchWebAuthFlow to parent to fix opening auth window when remote, r=zombie MozReview-Commit-ID: GAdlxYUM6rr
browser/components/extensions/ext-browser.json
toolkit/components/extensions/ext-c-identity.js
toolkit/components/extensions/ext-identity.js
toolkit/components/extensions/jar.mn
--- a/browser/components/extensions/ext-browser.json
+++ b/browser/components/extensions/ext-browser.json
@@ -84,18 +84,22 @@
     "url": "chrome://browser/content/ext-history.js",
     "schema": "chrome://browser/content/schemas/history.json",
     "scopes": ["addon_parent"],
     "paths": [
       ["history"]
     ]
   },
   "identity": {
+    "url": "chrome://extensions/content/ext-identity.js",
     "schema": "chrome://extensions/content/schemas/identity.json",
-    "scopes": ["addon_parent"]
+    "scopes": ["addon_parent"],
+    "paths": [
+      ["identity"]
+    ]
   },
   "menusInternal": {
     "url": "chrome://browser/content/ext-menus.js",
     "schema": "chrome://browser/content/schemas/menus.json",
     "scopes": ["addon_parent"],
     "paths": [
       ["menusInternal"]
     ]
--- a/toolkit/components/extensions/ext-c-identity.js
+++ b/toolkit/components/extensions/ext-c-identity.js
@@ -1,155 +1,35 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 var {Constructor: CC} = Components;
 
-XPCOMUtils.defineLazyModuleGetter(this, "Services",
-                                  "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
                                   "resource://services-common/utils.js");
 XPCOMUtils.defineLazyPreferenceGetter(this, "redirectDomain",
                                       "extensions.webextensions.identity.redirectDomain");
 
 let CryptoHash = CC("@mozilla.org/security/hash;1", "nsICryptoHash", "initWithString");
 
-Cu.importGlobalProperties(["URL", "XMLHttpRequest", "TextEncoder"]);
-
-var {
-  promiseDocumentLoaded,
-} = ExtensionUtils;
+Cu.importGlobalProperties(["URL", "TextEncoder"]);
 
 const computeHash = str => {
   let byteArr = new TextEncoder().encode(str);
   let hash = new CryptoHash("sha1");
   hash.update(byteArr, byteArr.length);
   return CommonUtils.bytesAsHex(hash.finish(false));
 };
 
-const checkRedirected = (url, redirectURI) => {
-  return new Promise((resolve, reject) => {
-    let xhr = new XMLHttpRequest();
-    xhr.open("HEAD", url);
-    // We expect this if the user has not authenticated.
-    xhr.onload = () => {
-      reject(0);
-    };
-    // An unexpected error happened, log for extension authors.
-    xhr.onerror = () => {
-      reject(xhr.status);
-    };
-    // Catch redirect to our redirect_uri before a new request is made.
-    xhr.channel.notificationCallbacks = {
-      QueryInterface: XPCOMUtils.generateQI([Ci.nsIInterfaceRequestor, Ci.nsIChannelEventSync]),
-
-      getInterface: XPCOMUtils.generateQI([Ci.nsIChannelEventSink]),
-
-      asyncOnChannelRedirect(oldChannel, newChannel, flags, callback) {
-        let responseURL = newChannel.URI.spec;
-        if (responseURL.startsWith(redirectURI)) {
-          resolve(responseURL);
-          // Cancel the redirect.
-          callback.onRedirectVerifyCallback(Components.results.NS_BINDING_ABORTED);
-          return;
-        }
-        callback.onRedirectVerifyCallback(Components.results.NS_OK);
-      },
-    };
-    xhr.send();
-  });
-};
-
-const openOAuthWindow = (details, redirectURI) => {
-  let args = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
-  let supportsStringPrefURL = Cc["@mozilla.org/supports-string;1"]
-                                .createInstance(Ci.nsISupportsString);
-  supportsStringPrefURL.data = details.url;
-  args.appendElement(supportsStringPrefURL);
-
-  let window = Services.ww.openWindow(null,
-                                      Services.prefs.getCharPref("browser.chromeURL"),
-                                      "launchWebAuthFlow_dialog",
-                                      "chrome,location=yes,centerscreen,dialog=no,resizable=yes",
-                                      args);
-
-  return new Promise((resolve, reject) => {
-    let wpl;
-
-    // If the user just closes the window we need to reject
-    function unloadlistener() {
-      window.removeEventListener("unload", unloadlistener);
-      window.gBrowser.removeTabsProgressListener(wpl);
-      reject({message: "User cancelled or denied access."});
-    }
-
-    wpl = {
-      onLocationChange(browser, webProgress, request, locationURI) {
-        if (locationURI.spec.startsWith(redirectURI)) {
-          resolve(locationURI.spec);
-          window.removeEventListener("unload", unloadlistener);
-          window.gBrowser.removeTabsProgressListener(wpl);
-          window.close();
-        }
-      },
-      onProgressChange() {},
-      onStatusChange() {},
-      onSecurityChange() {},
-    };
-
-    promiseDocumentLoaded(window.document).then(() => {
-      window.gBrowser.addTabsProgressListener(wpl);
-      window.addEventListener("unload", unloadlistener);
-    });
-  });
-};
-
 this.identity = class extends ExtensionAPI {
   getAPI(context) {
     let {extension} = context;
     return {
       identity: {
-        launchWebAuthFlow: function(details) {
-          // In OAuth2 the url should have a redirect_uri param, parse the url and grab it
-          let url, redirectURI;
-          try {
-            url = new URL(details.url);
-          } catch (e) {
-            return Promise.reject({message: "details.url is invalid"});
-          }
-          try {
-            redirectURI = new URL(url.searchParams.get("redirect_uri"));
-            if (!redirectURI) {
-              return Promise.reject({message: "redirect_uri is missing"});
-            }
-          } catch (e) {
-            return Promise.reject({message: "redirect_uri is invalid"});
-          }
-          if (!redirectURI.href.startsWith(this.getRedirectURL())) {
-            // Any url will work, but we suggest addons use getRedirectURL.
-            Services.console.logStringMessage("WebExtensions: redirect_uri should use browser.identity.getRedirectURL");
-          }
-
-          // If the request is automatically redirected the user has already
-          // authorized and we do not want to show the window.
-          return checkRedirected(details.url, redirectURI).catch((requestError) => {
-            // requestError is zero or xhr.status
-            if (requestError !== 0) {
-              Cu.reportError(`browser.identity auth check failed with ${requestError}`);
-              return Promise.reject({message: "Invalid request"});
-            }
-            if (!details.interactive) {
-              return Promise.reject({message: `Requires user interaction`});
-            }
-
-            return openOAuthWindow(details, redirectURI);
-          });
-        },
-
         getRedirectURL: function(path = "") {
           let hash = computeHash(extension.id);
           let url = new URL(`https://${hash}.${redirectDomain}/`);
           url.pathname = path;
           return url.href;
         },
       },
     };
copy from toolkit/components/extensions/ext-c-identity.js
copy to toolkit/components/extensions/ext-identity.js
--- a/toolkit/components/extensions/ext-c-identity.js
+++ b/toolkit/components/extensions/ext-identity.js
@@ -1,36 +1,21 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
-var {Constructor: CC} = Components;
-
 XPCOMUtils.defineLazyModuleGetter(this, "Services",
                                   "resource://gre/modules/Services.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
-                                  "resource://services-common/utils.js");
-XPCOMUtils.defineLazyPreferenceGetter(this, "redirectDomain",
-                                      "extensions.webextensions.identity.redirectDomain");
 
-let CryptoHash = CC("@mozilla.org/security/hash;1", "nsICryptoHash", "initWithString");
-
-Cu.importGlobalProperties(["URL", "XMLHttpRequest", "TextEncoder"]);
+Cu.importGlobalProperties(["URL", "XMLHttpRequest"]);
 
 var {
   promiseDocumentLoaded,
 } = ExtensionUtils;
 
-const computeHash = str => {
-  let byteArr = new TextEncoder().encode(str);
-  let hash = new CryptoHash("sha1");
-  hash.update(byteArr, byteArr.length);
-  return CommonUtils.bytesAsHex(hash.finish(false));
-};
-
 const checkRedirected = (url, redirectURI) => {
   return new Promise((resolve, reject) => {
     let xhr = new XMLHttpRequest();
     xhr.open("HEAD", url);
     // We expect this if the user has not authenticated.
     xhr.onload = () => {
       reject(0);
     };
@@ -100,17 +85,16 @@ const openOAuthWindow = (details, redire
       window.gBrowser.addTabsProgressListener(wpl);
       window.addEventListener("unload", unloadlistener);
     });
   });
 };
 
 this.identity = class extends ExtensionAPI {
   getAPI(context) {
-    let {extension} = context;
     return {
       identity: {
         launchWebAuthFlow: function(details) {
           // In OAuth2 the url should have a redirect_uri param, parse the url and grab it
           let url, redirectURI;
           try {
             url = new URL(details.url);
           } catch (e) {
@@ -119,39 +103,28 @@ this.identity = class extends ExtensionA
           try {
             redirectURI = new URL(url.searchParams.get("redirect_uri"));
             if (!redirectURI) {
               return Promise.reject({message: "redirect_uri is missing"});
             }
           } catch (e) {
             return Promise.reject({message: "redirect_uri is invalid"});
           }
-          if (!redirectURI.href.startsWith(this.getRedirectURL())) {
-            // Any url will work, but we suggest addons use getRedirectURL.
-            Services.console.logStringMessage("WebExtensions: redirect_uri should use browser.identity.getRedirectURL");
-          }
 
           // If the request is automatically redirected the user has already
           // authorized and we do not want to show the window.
           return checkRedirected(details.url, redirectURI).catch((requestError) => {
             // requestError is zero or xhr.status
             if (requestError !== 0) {
               Cu.reportError(`browser.identity auth check failed with ${requestError}`);
               return Promise.reject({message: "Invalid request"});
             }
             if (!details.interactive) {
               return Promise.reject({message: `Requires user interaction`});
             }
 
             return openOAuthWindow(details, redirectURI);
           });
         },
-
-        getRedirectURL: function(path = "") {
-          let hash = computeHash(extension.id);
-          let url = new URL(`https://${hash}.${redirectDomain}/`);
-          url.pathname = path;
-          return url.href;
-        },
       },
     };
   }
 };
--- a/toolkit/components/extensions/jar.mn
+++ b/toolkit/components/extensions/jar.mn
@@ -10,16 +10,19 @@ toolkit.jar:
     content/extensions/ext-browser-content.js
     content/extensions/ext-browserSettings.js
     content/extensions/ext-contextualIdentities.js
     content/extensions/ext-clipboard.js
     content/extensions/ext-cookies.js
     content/extensions/ext-downloads.js
     content/extensions/ext-extension.js
     content/extensions/ext-i18n.js
+#ifndef ANDROID
+    content/extensions/ext-identity.js
+#endif
     content/extensions/ext-idle.js
     content/extensions/ext-management.js
     content/extensions/ext-notifications.js
     content/extensions/ext-permissions.js
     content/extensions/ext-privacy.js
     content/extensions/ext-protocolHandlers.js
     content/extensions/ext-proxy.js
     content/extensions/ext-runtime.js