Bug 801049 - Communicate the privacy bit of the active window to the search suggestion service so that it knows whether to put the channel it creates in private browsing mode or not; r=gavin
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 15 Oct 2012 18:59:33 -0400
changeset 110348 b39bc1f5e0f8bc44f43c59d7af273e059928a5c6
parent 110347 b0029df270acda809b02b803f9be1afdba205caa
child 110349 cc55531de6310e8968caa8eed6cd10f24bf0fe2b
push id23680
push useremorley@mozilla.com
push dateTue, 16 Oct 2012 08:09:24 +0000
treeherdermozilla-central@8f145599e4bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgavin
bugs801049
milestone19.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 801049 - Communicate the privacy bit of the active window to the search suggestion service so that it knows whether to put the channel it creates in private browsing mode or not; r=gavin I'm using the autocompletesearchparam as a vehicle for delivering the privacy information into the guts of nsSearchSuggestions. The alternative solution will involve modifying the autocomplete interfaces, which is even more horrible than what the code here does. It's not that bad if you think of autocompletesearchparam attribute as an opaque value which is used to transfer information to the nsIAutoCompleteSearch implementations, which is what it is!
browser/components/search/content/search.xml
browser/components/search/test/browser_426329.js
toolkit/components/search/nsSearchSuggestions.js
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -618,16 +618,30 @@
           // Add observer for suggest preference
           var prefs = Components.classes["@mozilla.org/preferences-service;1"]
                               .getService(Components.interfaces.nsIPrefBranch);
           prefs.addObserver("browser.search.suggest.enabled", this, false);
         ]]></body>
       </method>
 
       <!--
+        This overrides the searchParam property in autocomplete.xml.  We're
+        hijacking this property as a vehicle for delivering the privacy
+        information about the window into the guys of nsSearchSuggestions.
+
+        Note that the setter is the same as the parent.  We were not sure whether
+        we can override just the getter.  If that proves to be the case, the setter
+        can be removed.
+      -->
+      <property name="searchParam"
+                onget="return this.getAttribute('autocompletesearchparam') +
+                       (PrivateBrowsingUtils.isWindowPrivate(window) ? '|private' : '');"
+                onset="this.setAttribute('autocompletesearchparam', val); return val;"/>
+
+      <!--
         This method overrides the autocomplete binding's openPopup (essentially
         duplicating the logic from the autocomplete popup binding's
         openAutocompletePopup method), modifying it so that the popup is aligned with
         the inner textbox, but sized to not extend beyond the search bar border.
       -->
       <method name="openPopup">
         <body><![CDATA[
           var popup = this.popup;
--- a/browser/components/search/test/browser_426329.js
+++ b/browser/components/search/test/browser_426329.js
@@ -188,17 +188,17 @@ function test() {
 
       testSearchHistory();
     }, 5000);
   }
 
   function testSearchHistory() {
     var textbox = searchBar._textbox;
     for (var i = 0; i < searchEntries.length; i++) {
-      let exists = textbox._formHistSvc.entryExists(textbox.searchParam, searchEntries[i]);
+      let exists = textbox._formHistSvc.entryExists(textbox.getAttribute("autocompletesearchparam"), searchEntries[i]);
       ok(exists, "form history entry '" + searchEntries[i] + "' should exist");
     }
     testAutocomplete();
   }
 
   function testAutocomplete() {
     var popup = searchBar.textbox.popup;
     popup.addEventListener("popupshowing", function() {
--- a/toolkit/components/search/nsSearchSuggestions.js
+++ b/toolkit/components/search/nsSearchSuggestions.js
@@ -394,36 +394,47 @@ SuggestAutoComplete.prototype = {
    * @param listener        object implementing nsIAutoCompleteObserver which
    *                        we notify when results are ready.
    */
   startSearch: function(searchString, searchParam, previousResult, listener) {
     // Don't reuse a previous form history result when it no longer applies.
     if (!previousResult)
       this._formHistoryResult = null;
 
+    var formHistorySearchParam = searchParam.split("|")[0];
+
+    // Receive the information about the privacy mode of the window to which
+    // this search box belongs.  The front-end's search.xml bindings passes this
+    // information in the searchParam parameter.  The alternative would have
+    // been to modify nsIAutoCompleteSearch to add an argument to startSearch
+    // and patch all of autocomplete to be aware of this, but the searchParam
+    // argument is already an opaque argument, so this solution is hopefully
+    // less hackish (although still gross.)
+    var privacyMode = (searchParam.split("|")[1] == "private");
+
     // Start search immediately if possible, otherwise once the search
     // service is initialized
     if (Services.search.isInitialized) {
-      this._triggerSearch(searchString, searchParam, listener);
+      this._triggerSearch(searchString, formHistorySearchParam, listener, privacyMode);
       return;
     }
 
     Services.search.init((function startSearch_cb(aResult) {
       if (!Components.isSuccessCode(aResult)) {
         Cu.reportError("Could not initialize search service, bailing out: " + aResult);
         return;
       }
-      this._triggerSearch(searchString, searchParam, listener);
+      this._triggerSearch(searchString, formHistorySearchParam, listener, privacyMode);
     }).bind(this));
   },
 
   /**
    * Actual implementation of search.
    */
-  _triggerSearch: function(searchString, searchParam, listener) {
+  _triggerSearch: function(searchString, searchParam, listener, privacyMode) {
     // If there's an existing request, stop it. There is no smart filtering
     // here as there is when looking through history/form data because the
     // result set returned by the server is different for every typed value -
     // "ocean breathes" does not return a subset of the results returned for
     // "ocean", for example. This does nothing if there is no current request.
     this.stopSearch();
 
     this._listener = listener;
@@ -449,16 +460,19 @@ SuggestAutoComplete.prototype = {
     this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                     createInstance(Ci.nsIXMLHttpRequest);
     var submission = engine.getSubmission(searchString,
                                           SEARCH_RESPONSE_SUGGESTION_JSON);
     this._suggestURI = submission.uri;
     var method = (submission.postData ? "POST" : "GET");
     this._request.open(method, this._suggestURI.spec, true);
     this._request.channel.notificationCallbacks = new SearchSuggestLoadListener();
+    if (this._request.channel instanceof Ci.nsIPrivateBrowsingChannel) {
+      this._request.channel.setPrivate(privacyMode);
+    }
 
     var self = this;
     function onReadyStateChange() {
       self.onReadyStateChange();
     }
     this._request.onreadystatechange = onReadyStateChange;
     this._request.send(submission.postData);