Bug 1048618: Send nsIURIFixupInfo to the parent process. r=gijs
authorDave Townsend <dtownsend@oxymoronical.com>
Tue, 02 Sep 2014 18:34:01 -0400
changeset 203214 4650bedd769150b8d8ecceb9c37cc462a1d19b00
parent 203213 e58cd57dde2f0e234c3bf23feb1966a78d4dbfc9
child 203215 b5646b91eff55c17707d654c53d62345b159cecb
push id27424
push userryanvm@gmail.com
push dateWed, 03 Sep 2014 19:35:53 +0000
treeherdermozilla-central@bfef88becbba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgijs
bugs1048618
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1048618: Send nsIURIFixupInfo to the parent process. r=gijs
browser/base/content/browser.js
browser/base/content/content.js
browser/base/content/test/general/browser_urlbarSearchSingleWordNotification.js
browser/base/content/test/general/head.js
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -667,52 +667,37 @@ var gPopupBlockerObserver = {
   dontShowMessage: function ()
   {
     var showMessage = gPrefService.getBoolPref("privacy.popups.showBrowserMessage");
     gPrefService.setBoolPref("privacy.popups.showBrowserMessage", !showMessage);
     gBrowser.getNotificationBox().removeCurrentNotification();
   }
 };
 
-function gKeywordURIFixup(fixupInfo, topic, data) {
-  fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
+function gKeywordURIFixup({ target: browser, data: fixupInfo }) {
+  let deserializeURI = (spec) => spec ? makeURI(spec) : null;
 
   // We get called irrespective of whether we did a keyword search, or
   // whether the original input would be vaguely interpretable as a URL,
   // so figure that out first.
-  let alternativeURI = fixupInfo.fixedURI;
+  let alternativeURI = deserializeURI(fixupInfo.fixedURI);
   if (!fixupInfo.fixupUsedKeyword || !alternativeURI) {
     return;
   }
 
-  // We should have a document loader...
-  let docshellRef = fixupInfo.consumer;
-  try {
-    docshellRef.QueryInterface(Ci.nsIDocumentLoader);
-  } catch (ex) {
-    return;
-  }
-
-  if (!docshellRef.document)
-    return;
-
-  // ... from which we can deduce the browser
-  let browser = gBrowser.getBrowserForDocument(docshellRef.document);
-  if (!browser)
-    return;
-
   // At this point we're still only just about to load this URI.
   // When the async DNS lookup comes back, we may be in any of these states:
   // 1) still on the previous URI, waiting for the preferredURI (keyword
   //    search) to respond;
   // 2) at the keyword search URI (preferredURI)
   // 3) at some other page because the user stopped navigation.
   // We keep track of the currentURI to detect case (1) in the DNS lookup
   // callback.
   let previousURI = browser.currentURI;
+  let preferredURI = deserializeURI(fixupInfo.preferredURI);
 
   // now swap for a weak ref so we don't hang on to browser needlessly
   // even if the DNS query takes forever
   let weakBrowser = Cu.getWeakReference(browser);
   browser = null;
 
   // Additionally, we need the host of the parsed url
   let hostName = alternativeURI.host;
@@ -733,17 +718,17 @@ function gKeywordURIFixup(fixupInfo, top
   let onLookupComplete = (request, record, status) => {
     let browser = weakBrowser.get();
     if (!Components.isSuccessCode(status) || !browser)
       return;
 
     let currentURI = browser.currentURI;
     // If we're in case (3) (see above), don't show an info bar.
     if (!currentURI.equals(previousURI) &&
-        !currentURI.equals(fixupInfo.preferredURI)) {
+        !currentURI.equals(preferredURI)) {
       return;
     }
 
     // show infobar offering to visit the host
     let notificationBox = gBrowser.getNotificationBox(browser);
     if (notificationBox.getNotificationWithValue("keyword-uri-fixup"))
       return;
 
@@ -1082,17 +1067,17 @@ var gBrowserInit = {
 #endif
 
     Services.obs.addObserver(gSessionHistoryObserver, "browser:purge-session-history", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-disabled", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-started", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-blocked", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-failed", false);
     Services.obs.addObserver(gXPInstallObserver, "addon-install-complete", false);
-    Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
+    window.messageManager.addMessageListener("Browser:URIFixup", gKeywordURIFixup);
 
     BrowserOffline.init();
     OfflineApps.init();
     IndexedDBPromptHelper.init();
     gRemoteTabsUI.init();
 
     // Initialize the full zoom setting.
     // We do this before the session restore service gets initialized so we can
@@ -1388,17 +1373,17 @@ var gBrowserInit = {
       FullZoom.destroy();
 
       Services.obs.removeObserver(gSessionHistoryObserver, "browser:purge-session-history");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-disabled");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-started");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-blocked");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-failed");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete");
-      Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
+      window.messageManager.removeMessageListener("Browser:URIFixup", gKeywordURIFixup);
 
       try {
         gPrefService.removeObserver(gHomeButton.prefDomain, gHomeButton);
       } catch (ex) {
         Cu.reportError(ex);
       }
 
       if (typeof WindowsPrefSync !== 'undefined') {
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -629,16 +629,43 @@ let DOMFullscreenHandler = {
       sendAsyncMessage("MozEnteredDomFullscreen", {
         origin: this._fullscreenDoc.nodePrincipal.origin,
       });
     }
   }
 };
 DOMFullscreenHandler.init();
 
+function gKeywordURIFixup(fixupInfo) {
+  fixupInfo.QueryInterface(Ci.nsIURIFixupInfo);
+
+  // Ignore info from other docshells
+  let parent = fixupInfo.consumer.QueryInterface(Ci.nsIDocShellTreeItem).sameTypeRootTreeItem;
+  if (parent != docShell)
+    return;
+
+  let data = {};
+  for (let f of Object.keys(fixupInfo)) {
+    if (f == "consumer" || typeof fixupInfo[f] == "function")
+      continue;
+
+    if (fixupInfo[f] && fixupInfo[f] instanceof Ci.nsIURI) {
+      data[f] = fixupInfo[f].spec;
+    } else {
+      data[f] = fixupInfo[f];
+    }
+  }
+
+  sendAsyncMessage("Browser:URIFixup", data);
+}
+Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
+addEventListener("unload", () => {
+  Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
+}, false);
+
 addMessageListener("Browser:AppTab", function(message) {
   docShell.isAppTab = message.data.isAppTab;
 });
 
 let WebBrowserChrome = {
   onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
     return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
   },
--- a/browser/base/content/test/general/browser_urlbarSearchSingleWordNotification.js
+++ b/browser/base/content/test/general/browser_urlbarSearchSingleWordNotification.js
@@ -10,18 +10,20 @@ registerCleanupFunction(function() {
     notificationObserver.disconnect();
   }
 });
 
 function promiseNotificationForTab(aBrowser, value, expected, tab=aBrowser.selectedTab) {
   let deferred = Promise.defer();
   let notificationBox = aBrowser.getNotificationBox(tab.linkedBrowser);
   if (expected) {
+    info("Waiting for " + value + " notification");
     let checkForNotification = function() {
       if (notificationBox.getNotificationWithValue(value)) {
+        info("Saw the notification");
         notificationObserver.disconnect();
         notificationObserver = null;
         deferred.resolve();
       }
     }
     if (notificationObserver) {
       notificationObserver.disconnect();
     }
@@ -43,22 +45,23 @@ function* runURLBarSearchTest(valueToOpe
     expectedURI = "http://" + valueToOpen + "/";
   } else {
     yield new Promise(resolve => {
       Services.search.init(resolve);
     });
     expectedURI = Services.search.defaultEngine.getSubmission(valueToOpen, null, "keyword").uri.spec;
   }
   aWindow.gURLBar.focus();
-  let docLoadPromise = waitForDocLoadAndStopIt(expectedURI, aWindow.gBrowser);
+  let docLoadPromise = waitForDocLoadAndStopIt(expectedURI, aWindow.gBrowser.selectedBrowser);
   EventUtils.synthesizeKey("VK_RETURN", {}, aWindow);
 
-  yield docLoadPromise;
-
-  yield promiseNotificationForTab(aWindow.gBrowser, "keyword-uri-fixup", expectNotification);
+  yield Promise.all([
+    docLoadPromise,
+    promiseNotificationForTab(aWindow.gBrowser, "keyword-uri-fixup", expectNotification)
+  ]);
 }
 
 add_task(function* test_navigate_full_domain() {
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   yield* runURLBarSearchTest("www.mozilla.org", false, false);
   gBrowser.removeTab(tab);
 });
 
@@ -83,17 +86,17 @@ function get_test_function_for_localhost
     let browser = win.gBrowser;
     let tab = browser.selectedTab = browser.addTab();
 
     Services.prefs.setBoolPref(pref, false);
     yield* runURLBarSearchTest(hostName, true, true, win);
 
     let notificationBox = browser.getNotificationBox(tab.linkedBrowser);
     let notification = notificationBox.getNotificationWithValue("keyword-uri-fixup");
-    let docLoadPromise = waitForDocLoadAndStopIt("http://" + hostName + "/", browser);
+    let docLoadPromise = waitForDocLoadAndStopIt("http://" + hostName + "/", tab.linkedBrowser);
     notification.querySelector(".notification-button-default").click();
 
     // check pref value
     let prefValue = Services.prefs.getBoolPref(pref);
     is(prefValue, !isPrivate, "Pref should have the correct state.");
 
     yield docLoadPromise;
     browser.removeTab(tab);
--- a/browser/base/content/test/general/head.js
+++ b/browser/base/content/test/general/head.js
@@ -389,37 +389,52 @@ function promiseClearHistory() {
  * Waits for the next top-level document load in the current browser.  The URI
  * of the document is compared against aExpectedURL.  The load is then stopped
  * before it actually starts.
  *
  * @param aExpectedURL
  *        The URL of the document that is expected to load.
  * @return promise
  */
-function waitForDocLoadAndStopIt(aExpectedURL, aBrowser=gBrowser) {
-  let deferred = Promise.defer();
-  let progressListener = {
-    onStateChange: function (webProgress, req, flags, status) {
-      info("waitForDocLoadAndStopIt: onStateChange: " + req.name);
-      let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
-                     Ci.nsIWebProgressListener.STATE_START;
-      if ((flags & docStart) && webProgress.isTopLevel) {
-        info("waitForDocLoadAndStopIt: Document start: " +
-             req.QueryInterface(Ci.nsIChannel).URI.spec);
-        is(req.originalURI.spec, aExpectedURL,
-           "waitForDocLoadAndStopIt: The expected URL was loaded");
-        req.cancel(Components.results.NS_ERROR_FAILURE);
-        aBrowser.removeProgressListener(progressListener);
-        deferred.resolve();
-      }
-    },
-  };
-  aBrowser.addProgressListener(progressListener);
-  info("waitForDocLoadAndStopIt: Waiting for URL: " + aExpectedURL);
-  return deferred.promise;
+function waitForDocLoadAndStopIt(aExpectedURL, aBrowser=gBrowser.selectedBrowser) {
+  function content_script() {
+    let { interfaces: Ci, utils: Cu } = Components;
+    Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+    let wp = docShell.QueryInterface(Ci.nsIWebProgress);
+
+    let progressListener = {
+      onStateChange: function (webProgress, req, flags, status) {
+        dump("waitForDocLoadAndStopIt: onStateChange " + flags.toString(16) + ": " + req.name + "\n");
+        let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
+                       Ci.nsIWebProgressListener.STATE_START;
+        if (((flags & docStart) == docStart) && webProgress.isTopLevel) {
+          dump("waitForDocLoadAndStopIt: Document start: " +
+               req.QueryInterface(Ci.nsIChannel).URI.spec + "\n");
+          req.cancel(Components.results.NS_ERROR_FAILURE);
+          wp.removeProgressListener(progressListener);
+          sendAsyncMessage("Test:WaitForDocLoadAndStopIt", { uri: req.originalURI.spec });
+        }
+      },
+      QueryInterface: XPCOMUtils.generateQI(["nsISupportsWeakReference"])
+    };
+    wp.addProgressListener(progressListener, wp.NOTIFY_ALL);
+  }
+
+  return new Promise((resolve, reject) => {
+    function complete({ data }) {
+      is(data.uri, aExpectedURL, "waitForDocLoadAndStopIt: The expected URL was loaded");
+      mm.removeMessageListener("Test:WaitForDocLoadAndStopIt", complete);
+      resolve();
+    }
+
+    let mm = aBrowser.messageManager;
+    mm.loadFrameScript("data:,(" + content_script.toString() + ")();", true);
+    mm.addMessageListener("Test:WaitForDocLoadAndStopIt", complete);
+    info("waitForDocLoadAndStopIt: Waiting for URL: " + aExpectedURL);
+  });
 }
 
 /**
  * Waits for the next load to complete in the current browser.
  *
  * @return promise
  */
 function waitForDocLoadComplete(aBrowser=gBrowser) {