Bug 1096534 - ContentSearch should load the search URL in the tab sending the search message, not the current tab. r=mak, a=sledru
authorDrew Willcoxon <adw@mozilla.com>
Mon, 08 Dec 2014 11:05:27 -0800
changeset 242373 c10821ae262316e6332837523f0be3f706a7bb12
parent 242372 7dfea2969d9ebdf7f4119bcf6b3b4a30efbd05d7
child 242374 5733fa345bde2c12dfce96d64d20f5f3c0186adb
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak, sledru
bugs1096534
milestone36.0a2
Bug 1096534 - ContentSearch should load the search URL in the tab sending the search message, not the current tab. r=mak, a=sledru
browser/modules/ContentSearch.jsm
browser/modules/test/browser_ContentSearch.js
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -200,21 +200,33 @@ this.ContentSearch = {
   },
 
   _onMessageSearch: function (msg, data) {
     this._ensureDataHasProperties(data, [
       "engineName",
       "searchString",
       "whence",
     ]);
-    let browserWin = msg.target.ownerDocument.defaultView;
     let engine = Services.search.getEngineByName(data.engineName);
-    browserWin.BrowserSearch.recordSearchInHealthReport(engine, data.whence, data.selection);
     let submission = engine.getSubmission(data.searchString, "", data.whence);
-    browserWin.loadURI(submission.uri.spec, null, submission.postData);
+    let browser = msg.target;
+    try {
+      browser.loadURIWithFlags(submission.uri.spec,
+                               Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
+                               submission.postData);
+    }
+    catch (err) {
+      // The browser may have been closed between the time its content sent the
+      // message and the time we handle it.  In that case, trying to call any
+      // method on it will throw.
+      return Promise.resolve();
+    }
+    let win = browser.ownerDocument.defaultView;
+    win.BrowserSearch.recordSearchInHealthReport(engine, data.whence,
+                                                 data.selection || null);
     return Promise.resolve();
   },
 
   _onMessageSetCurrentEngine: function (msg, data) {
     Services.search.currentEngine = Services.search.getEngineByName(data);
     return Promise.resolve();
   },
 
--- a/browser/modules/test/browser_ContentSearch.js
+++ b/browser/modules/test/browser_ContentSearch.js
@@ -97,34 +97,44 @@ add_task(function* search() {
     whence: "ContentSearchTest",
   };
   gMsgMan.sendAsyncMessage(TEST_MSG, {
     type: "Search",
     data: data,
   });
   let submissionURL =
     engine.getSubmission(data.searchString, "", data.whence).uri.spec;
-  let deferred = Promise.defer();
-  let listener = {
-    onStateChange: function (webProg, req, flags, status) {
-      let url = req.originalURI.spec;
-      info("onStateChange " + url);
-      let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
-                     Ci.nsIWebProgressListener.STATE_START;
-      if ((flags & docStart) && webProg.isTopLevel && url == submissionURL) {
-        gBrowser.removeProgressListener(listener);
-        ok(true, "Search URL loaded");
-        req.cancel(Components.results.NS_ERROR_FAILURE);
-        deferred.resolve();
-      }
-    }
+  yield waitForLoadAndStopIt(gBrowser.selectedBrowser, submissionURL);
+});
+
+add_task(function* searchInBackgroundTab() {
+  // This test is like search(), but it opens a new tab after starting a search
+  // in another.  In other words, it performs a search in a background tab.  The
+  // search page should be loaded in the same tab that performed the search, in
+  // the background tab.
+  yield addTab();
+  let searchBrowser = gBrowser.selectedBrowser;
+  let engine = Services.search.currentEngine;
+  let data = {
+    engineName: engine.name,
+    searchString: "ContentSearchTest",
+    whence: "ContentSearchTest",
   };
-  gBrowser.addProgressListener(listener);
-  info("Waiting for search URL to load: " + submissionURL);
-  yield deferred.promise;
+  gMsgMan.sendAsyncMessage(TEST_MSG, {
+    type: "Search",
+    data: data,
+  });
+
+  let newTab = gBrowser.addTab();
+  gBrowser.selectedTab = newTab;
+  registerCleanupFunction(() => gBrowser.removeTab(newTab));
+
+  let submissionURL =
+    engine.getSubmission(data.searchString, "", data.whence).uri.spec;
+  yield waitForLoadAndStopIt(searchBrowser, submissionURL);
 });
 
 add_task(function* badImage() {
   yield addTab();
   // If the bad image URI caused an exception to be thrown within ContentSearch,
   // then we'll hang waiting for the CurrentState responses triggered by the new
   // engine.  That's what we're testing, and obviously it shouldn't happen.
   let vals = yield waitForNewEngine("contentSearchBadImage.xml", 1);
@@ -314,16 +324,43 @@ function waitForNewEngine(basename, numI
       ok(false, "addEngine failed with error code " + errCode);
       addDeferred.reject();
     },
   });
 
   return Promise.all([addDeferred.promise].concat(eventPromises));
 }
 
+function waitForLoadAndStopIt(browser, expectedURL) {
+  let deferred = Promise.defer();
+  let listener = {
+    onStateChange: function (webProg, req, flags, status) {
+      if (req instanceof Ci.nsIChannel) {
+        let url = req.originalURI.spec;
+        info("onStateChange " + url);
+        let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
+                       Ci.nsIWebProgressListener.STATE_START;
+        if ((flags & docStart) && webProg.isTopLevel && url == expectedURL) {
+          browser.removeProgressListener(listener);
+          ok(true, "Expected URL loaded");
+          req.cancel(Components.results.NS_ERROR_FAILURE);
+          deferred.resolve();
+        }
+      }
+    },
+    QueryInterface: XPCOMUtils.generateQI([
+      Ci.nsIWebProgressListener,
+      Ci.nsISupportsWeakReference,
+    ]),
+  };
+  browser.addProgressListener(listener);
+  info("Waiting for URL to load: " + expectedURL);
+  return deferred.promise;
+}
+
 function addTab() {
   let deferred = Promise.defer();
   let tab = gBrowser.addTab();
   gBrowser.selectedTab = tab;
   tab.linkedBrowser.addEventListener("load", function load() {
     tab.linkedBrowser.removeEventListener("load", load, true);
     let url = getRootDirectory(gTestPath) + TEST_CONTENT_SCRIPT_BASENAME;
     gMsgMan = tab.linkedBrowser.messageManager;