Bug 862401: make sure nsDefaultURIFixup::KeywordToURI propagates POST data. sr=bz, r=gavin, a=bajaj
authorMike de Boer <mdeboer@mozilla.com>
Wed, 01 May 2013 13:04:21 +0200
changeset 142668 dc0f26005df30bad2e36766fc4480c9b3019930b
parent 142667 df78311932f1a72f95af42cac8ec7323dceada0f
child 142669 ef115eb9325eda60162c9945ffdc69e85cb7a177
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, gavin, bajaj
bugs862401
milestone23.0a2
Bug 862401: make sure nsDefaultURIFixup::KeywordToURI propagates POST data. sr=bz, r=gavin, a=bajaj
browser/base/content/test/Makefile.in
browser/base/content/test/POSTSearchEngine.xml
browser/base/content/test/browser_keywordSearch_postData.js
browser/base/content/test/print_postdata.sjs
caps/src/nsScriptSecurityManager.cpp
docshell/base/nsDefaultURIFixup.cpp
docshell/base/nsDefaultURIFixup.h
docshell/base/nsDocShell.cpp
docshell/base/nsIURIFixup.idl
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -59,16 +59,19 @@ endif
 # browser_drag.js is disabled, as it needs to be updated for the new behavior from bug 320638.
 
 # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
 
 _BROWSER_FILES = \
                  head.js \
                  browser_typeAheadFind.js \
                  browser_keywordSearch.js \
+                 browser_keywordSearch_postData.js \
+                 POSTSearchEngine.xml \
+                 print_postdata.sjs \
                  browser_alltabslistener.js \
                  browser_bug304198.js \
                  title_test.svg \
                  browser_bug329212.js \
                  browser_bug356571.js \
                  browser_bug380960.js \
                  browser_bug386835.js \
                  browser_bug405137.js \
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/POSTSearchEngine.xml
@@ -0,0 +1,6 @@
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
+  <ShortName>POST Search</ShortName>
+  <Url type="text/html" method="POST" template="http://mochi.test:8888/browser/browser/base/content/test/print_postdata.sjs">
+    <Param name="searchterms" value="{searchTerms}"/>
+  </Url>
+</OpenSearchDescription>
copy from browser/base/content/test/browser_keywordSearch.js
copy to browser/base/content/test/browser_keywordSearch_postData.js
--- a/browser/base/content/test/browser_keywordSearch.js
+++ b/browser/base/content/test/browser_keywordSearch_postData.js
@@ -2,85 +2,93 @@
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  **/
 
 var gTests = [
   {
     name: "normal search (search service)",
     testText: "test search",
-    searchURL: Services.search.defaultEngine.getSubmission("test search", null, "keyword").uri.spec
+    expectText: "test+search"
   },
   {
     name: "?-prefixed search (search service)",
     testText: "?   foo  ",
-    searchURL: Services.search.defaultEngine.getSubmission("foo", null, "keyword").uri.spec
+    expectText: "foo"
   }
 ];
 
 function test() {
   waitForExplicitFinish();
 
-  let windowObserver = {
-    observe: function(aSubject, aTopic, aData) {
-      if (aTopic == "domwindowopened") {
-        ok(false, "Alert window opened");
-        let win = aSubject.QueryInterface(Ci.nsIDOMEventTarget);
-        win.addEventListener("load", function() {
-          win.removeEventListener("load", arguments.callee, false);
-          win.close();
-        }, false);
-        executeSoon(finish);
-      }
-    }
-  };
-
-  Services.ww.registerNotification(windowObserver);
-
   let tab = gBrowser.selectedTab = gBrowser.addTab();
 
-  let listener = {
-    onStateChange: function onLocationChange(webProgress, req, flags, status) {
-      // Only care about document starts
-      let docStart = Ci.nsIWebProgressListener.STATE_IS_DOCUMENT |
-                     Ci.nsIWebProgressListener.STATE_START;
-      if (!(flags & docStart))
-        return;
+  let searchObserver = function search_observer(aSubject, aTopic, aData) {
+    let engine = aSubject.QueryInterface(Ci.nsISearchEngine);
+    info("Observer: " + aData + " for " + engine.name);
+
+    if (aData != "engine-added")
+      return;
+
+    if (engine.name != "POST Search")
+      return;
 
-      info("received document start");
+    Services.search.defaultEngine = engine;
+
+    registerCleanupFunction(function () {
+      Services.search.removeEngine(engine);
+    });
 
-      ok(req instanceof Ci.nsIChannel, "req is a channel");
-      is(req.originalURI.spec, gCurrTest.searchURL, "search URL was loaded");
-      info("Actual URI: " + req.URI.spec);
+    // ready to execute the tests!
+    executeSoon(nextTest);
+  };
 
-      executeSoon(nextTest);
-    }
-  }
-  gBrowser.addProgressListener(listener);
+  Services.obs.addObserver(searchObserver, "browser-search-engine-modified", false);
 
   registerCleanupFunction(function () {
-    Services.ww.unregisterNotification(windowObserver);
+    gBrowser.removeTab(tab);
 
-    gBrowser.removeProgressListener(listener);
-    gBrowser.removeTab(tab);
+    Services.obs.removeObserver(searchObserver, "browser-search-engine-modified");
   });
 
-  nextTest();
+  Services.search.addEngine("http://test:80/browser/browser/base/content/test/POSTSearchEngine.xml",
+                            Ci.nsISearchEngine.DATA_XML, null, false);
 }
 
 var gCurrTest;
 function nextTest() {
   if (gTests.length) {
     gCurrTest = gTests.shift();
     doTest();
   } else {
     finish();
   }
 }
 
 function doTest() {
   info("Running test: " + gCurrTest.name);
 
+  waitForLoad(function () {
+    let loadedText = gBrowser.contentDocument.body.textContent;
+    ok(loadedText, "search page loaded");
+    let needle = "searchterms=" + gCurrTest.expectText;
+    is(loadedText, needle, "The query POST data should be returned in the response");
+    nextTest();
+  });
+
   // Simulate a user entering search terms
   gURLBar.value = gCurrTest.testText;
   gURLBar.focus();
   EventUtils.synthesizeKey("VK_RETURN", {});
 }
+
+
+function waitForLoad(cb) {
+  let browser = gBrowser.selectedBrowser;
+  browser.addEventListener("load", function listener() {
+    if (browser.currentURI.spec == "about:blank")
+      return;
+    info("Page loaded: " + browser.currentURI.spec);
+    browser.removeEventListener("load", listener, true);
+
+    cb();
+  }, true);
+}
copy from content/base/test/bug435425.sjs
copy to browser/base/content/test/print_postdata.sjs
--- a/content/base/test/bug435425.sjs
+++ b/browser/base/content/test/print_postdata.sjs
@@ -1,24 +1,22 @@
 const CC = Components.Constructor;
 const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
                              "nsIBinaryInputStream",
                              "setInputStream");
 
-function handleRequest(request, response)
-{
+function handleRequest(request, response) {
   response.setHeader("Content-Type", "text/plain", false);
   if (request.method == "GET") {
     response.write(request.queryString);
   } else {
     var body = new BinaryInputStream(request.bodyInputStream);
 
     var avail;
     var bytes = [];
 
     while ((avail = body.available()) > 0)
       Array.prototype.push.apply(bytes, body.readByteArray(avail));
 
     var data = String.fromCharCode.apply(null, bytes);
     response.bodyOutputStream.write(data, data.length);
   }
 }
-
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -1559,17 +1559,17 @@ nsScriptSecurityManager::CheckLoadURIStr
         nsIURIFixup::FIXUP_FLAG_NONE,
         nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP,
         nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
         nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP |
         nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI
     };
 
     for (uint32_t i = 0; i < ArrayLength(flags); ++i) {
-        rv = fixup->CreateFixupURI(aTargetURIStr, flags[i],
+        rv = fixup->CreateFixupURI(aTargetURIStr, flags[i], nullptr,
                                    getter_AddRefs(target));
         NS_ENSURE_SUCCESS(rv, rv);
 
         rv = CheckLoadURIWithPrincipal(aPrincipal, target, aFlags);
         NS_ENSURE_SUCCESS(rv, rv);
     }
 
     return rv;
--- a/docshell/base/nsDefaultURIFixup.cpp
+++ b/docshell/base/nsDefaultURIFixup.cpp
@@ -108,17 +108,18 @@ nsDefaultURIFixup::CreateExposableURI(ns
     // return the fixed-up URI
     *aReturn = uri;
     NS_ADDREF(*aReturn);
     return NS_OK;
 }
 
 /* nsIURI createFixupURI (in nsAUTF8String aURIText, in unsigned long aFixupFlags); */
 NS_IMETHODIMP
-nsDefaultURIFixup::CreateFixupURI(const nsACString& aStringURI, uint32_t aFixupFlags, nsIURI **aURI)
+nsDefaultURIFixup::CreateFixupURI(const nsACString& aStringURI, uint32_t aFixupFlags,
+                                  nsIInputStream **aPostData, nsIURI **aURI)
 {
     NS_ENSURE_ARG(!aStringURI.IsEmpty());
     NS_ENSURE_ARG_POINTER(aURI);
 
     nsresult rv;
     *aURI = nullptr;
 
     nsAutoCString uriString(aStringURI);
@@ -142,17 +143,17 @@ nsDefaultURIFixup::CreateFixupURI(const 
     {
         nsCOMPtr<nsIURI> uri;
         uint32_t newFixupFlags = aFixupFlags & ~FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
 
         rv =  CreateFixupURI(Substring(uriString,
                                        sizeof("view-source:") - 1,
                                        uriString.Length() -
                                          (sizeof("view-source:") - 1)),
-                             newFixupFlags, getter_AddRefs(uri));
+                             newFixupFlags, aPostData, getter_AddRefs(uri));
         if (NS_FAILED(rv))
             return NS_ERROR_FAILURE;
         nsAutoCString spec;
         uri->GetSpec(spec);
         uriString.Assign(NS_LITERAL_CSTRING("view-source:") + spec);
     }
     else {
         // Check for if it is a file URL
@@ -238,17 +239,17 @@ nsDefaultURIFixup::CreateFixupURI(const 
     // See if it is a keyword
     // Test whether keywords need to be fixed up
     bool fixupKeywords = false;
     if (aFixupFlags & FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP) {
         nsresult rv = Preferences::GetBool("keyword.enabled", &fixupKeywords);
         NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
         if (fixupKeywords)
         {
-            KeywordURIFixup(uriString, aURI);
+            KeywordURIFixup(uriString, aPostData, aURI);
             if(*aURI)
                 return NS_OK;
         }
     }
 
     // Prune duff protocol schemes
     //
     //   ://totallybroken.url.com
@@ -304,28 +305,32 @@ nsDefaultURIFixup::CreateFixupURI(const 
     if (*aURI && aFixupFlags & FIXUP_FLAGS_MAKE_ALTERNATE_URI) {
         MakeAlternateURI(*aURI);
     }
 
     // If we still haven't been able to construct a valid URI, try to force a
     // keyword match.  This catches search strings with '.' or ':' in them.
     if (!*aURI && fixupKeywords)
     {
-        KeywordToURI(aStringURI, aURI);
+        KeywordToURI(aStringURI, aPostData, aURI);
         if(*aURI)
             return NS_OK;
     }
 
     return rv;
 }
 
 NS_IMETHODIMP nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
+                                              nsIInputStream **aPostData,
                                               nsIURI **aURI)
 {
     *aURI = nullptr;
+    if (aPostData) {
+        *aPostData = nullptr;
+    }
     NS_ENSURE_STATE(Preferences::GetRootBranch());
 
     // Strip leading "?" and leading/trailing spaces from aKeyword
     nsAutoCString keyword(aKeyword);
     if (StringBeginsWith(keyword, NS_LITERAL_CSTRING("?"))) {
         keyword.Cut(0, 1);
     }
     keyword.Trim(" ");
@@ -349,23 +354,26 @@ NS_IMETHODIMP nsDefaultURIFixup::Keyword
                                            NS_LITERAL_STRING("keyword"),
                                            getter_AddRefs(submission));
             else
               defaultEngine->GetSubmission(NS_ConvertUTF8toUTF16(keyword),
                                            EmptyString(),
                                            NS_LITERAL_STRING("keyword"),
                                            getter_AddRefs(submission));
             if (submission) {
-                // The submission depends on POST data (i.e. the search engine's
-                // "method" is POST), we can't use this engine for keyword
-                // searches
                 nsCOMPtr<nsIInputStream> postData;
                 submission->GetPostData(getter_AddRefs(postData));
-                if (postData) {
-                    return NS_ERROR_NOT_AVAILABLE;
+                if (aPostData) {
+                  postData.forget(aPostData);
+                } else if (postData) {
+                  // The submission specifies POST data (i.e. the search
+                  // engine's "method" is POST), but our caller didn't allow
+                  // passing post data back. No point passing back a URL that
+                  // won't load properly.
+                  return NS_ERROR_FAILURE;
                 }
 
                 // This notification is meant for Firefox Health Report so it
                 // can increment counts from the search engine. The assumption
                 // here is that this keyword/submission will eventually result
                 // in a search. Since we only generate a URI here, there is the
                 // possibility we'll increment the counter without actually
                 // incurring a search. A robust solution would involve currying
@@ -757,18 +765,19 @@ const char * nsDefaultURIFixup::GetFileS
 }
 
 const char * nsDefaultURIFixup::GetCharsetForUrlBar()
 {
   const char *charset = GetFileSystemCharset();
   return charset;
 }
 
-nsresult nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString, 
-                                            nsIURI** aURI)
+void nsDefaultURIFixup::KeywordURIFixup(const nsACString & aURIString,
+                                        nsIInputStream **aPostData,
+                                        nsIURI** aURI)
 {
     // These are keyword formatted strings
     // "what is mozilla"
     // "what is mozilla?"
     // "docshell site:mozilla.org" - has no dot/colon in the first space-separated substring
     // "?mozilla" - anything that begins with a question mark
     // "?site:mozilla.org docshell"
     // Things that have a quote before the first dot/colon
@@ -797,23 +806,18 @@ nsresult nsDefaultURIFixup::KeywordURIFi
     uint32_t quoteLoc = std::min(uint32_t(aURIString.FindChar('"')),
                                uint32_t(aURIString.FindChar('\'')));
 
     if (((spaceLoc < dotLoc || quoteLoc < dotLoc) &&
          (spaceLoc < colonLoc || quoteLoc < colonLoc) &&
          (spaceLoc < qMarkLoc || quoteLoc < qMarkLoc)) ||
         qMarkLoc == 0)
     {
-        KeywordToURI(aURIString, aURI);
+        KeywordToURI(aURIString, aPostData, aURI);
     }
-
-    if(*aURI)
-        return NS_OK;
-
-    return NS_ERROR_FAILURE;
 }
 
 
 nsresult NS_NewURIFixup(nsIURIFixup **aURIFixup)
 {
     nsDefaultURIFixup *fixup = new nsDefaultURIFixup;
     if (fixup == nullptr)
     {
--- a/docshell/base/nsDefaultURIFixup.h
+++ b/docshell/base/nsDefaultURIFixup.h
@@ -24,17 +24,17 @@ public:
 
 protected:
     virtual ~nsDefaultURIFixup();
 
 private:
     /* additional members */
     nsresult FileURIFixup(const nsACString &aStringURI, nsIURI** aURI);
     nsresult ConvertFileToStringURI(const nsACString& aIn, nsCString& aOut);
-    nsresult KeywordURIFixup(const nsACString &aStringURI, nsIURI** aURI);
+    void KeywordURIFixup(const nsACString &aStringURI, nsIInputStream** aPostData, nsIURI** aURI);
     bool PossiblyByteExpandedFileName(const nsAString& aIn);
     bool PossiblyHostPortUrl(const nsACString& aUrl);
     bool MakeAlternateURI(nsIURI *aURI);
     bool IsLikelyFTP(const nsCString& aHostSpec);
     const char * GetFileSystemCharset();
     const char * GetCharsetForUrlBar();
 
     nsCString mFsCharset;
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3998,16 +3998,17 @@ nsDocShell::LoadURI(const PRUnichar * aU
                     nsIInputStream * aHeaderStream)
 {
     NS_ASSERTION((aLoadFlags & 0xf) == 0, "Unexpected flags");
     
     if (!IsNavigationAllowed()) {
       return NS_OK; // JS may not handle returning of an error code
     }
     nsCOMPtr<nsIURI> uri;
+    nsCOMPtr<nsIInputStream> postStream(aPostStream);
     nsresult rv = NS_OK;
 
     // Create a URI from our string; if that succeeds, we want to
     // change aLoadFlags to not include the ALLOW_THIRD_PARTY_FIXUP
     // flag.
 
     NS_ConvertUTF16toUTF8 uriString(aURI);
     // Cleanup the empty spaces that might be on each end.
@@ -4029,16 +4030,17 @@ nsDocShell::LoadURI(const PRUnichar * aU
         uint32_t fixupFlags = 0;
         if (aLoadFlags & LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP) {
           fixupFlags |= nsIURIFixup::FIXUP_FLAG_ALLOW_KEYWORD_LOOKUP;
         }
         if (aLoadFlags & LOAD_FLAGS_URI_IS_UTF8) {
           fixupFlags |= nsIURIFixup::FIXUP_FLAG_USE_UTF8;
         }
         rv = sURIFixup->CreateFixupURI(uriString, fixupFlags,
+                                       getter_AddRefs(postStream),
                                        getter_AddRefs(uri));
     }
     // else no fixup service so just use the URI we created and see
     // what happens
 
     if (NS_ERROR_MALFORMED_URI == rv) {
         DisplayLoadError(rv, uri, aURI);
     }
@@ -4062,17 +4064,17 @@ nsDocShell::LoadURI(const PRUnichar * aU
     aLoadFlags &= ~EXTRA_LOAD_FLAGS;
 
     nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     rv = CreateLoadInfo(getter_AddRefs(loadInfo));
     if (NS_FAILED(rv)) return rv;
     
     uint32_t loadType = MAKE_LOAD_TYPE(LOAD_NORMAL, aLoadFlags);
     loadInfo->SetLoadType(ConvertLoadTypeToDocShellLoadInfo(loadType));
-    loadInfo->SetPostDataStream(aPostStream);
+    loadInfo->SetPostDataStream(postStream);
     loadInfo->SetReferrer(aReferringURI);
     loadInfo->SetHeadersStream(aHeaderStream);
 
     rv = LoadURI(uri, loadInfo, extraFlags, true);
 
     // Save URI string in case it's needed later when
     // sending to search engine service in EndPageLoad()
     mOriginalUriString = uriString; 
@@ -6653,16 +6655,17 @@ nsDocShell::EndPageLoad(nsIWebProgress *
             return NS_OK;
         }
 
         if (sURIFixup) {
             //
             // Try and make an alternative URI from the old one
             //
             nsCOMPtr<nsIURI> newURI;
+            nsCOMPtr<nsIInputStream> newPostData;
 
             nsAutoCString oldSpec;
             url->GetSpec(oldSpec);
       
             //
             // First try keyword fixup
             //
             if (aStatus == NS_ERROR_UNKNOWN_HOST && mAllowKeywordFixup) {
@@ -6693,16 +6696,17 @@ nsDocShell::EndPageLoad(nsIWebProgress *
                     (scheme.Find("http") != 0)) {
                     keywordsEnabled = false;
                 }
 
                 if (keywordsEnabled && (kNotFound == dotLoc)) {
                     // only send non-qualified hosts to the keyword server
                     if (!mOriginalUriString.IsEmpty()) {
                         sURIFixup->KeywordToURI(mOriginalUriString,
+                                                getter_AddRefs(newPostData),
                                                 getter_AddRefs(newURI));
                     }
                     else {
                         //
                         // If this string was passed through nsStandardURL by
                         // chance, then it may have been converted from UTF-8 to
                         // ACE, which would result in a completely bogus keyword
                         // query.  Here we try to recover the original Unicode
@@ -6712,21 +6716,25 @@ nsDocShell::EndPageLoad(nsIWebProgress *
                         // Since we don't have access to the exact original string
                         // that was entered by the user, this will just have to do.
                         bool isACE;
                         nsAutoCString utf8Host;
                         nsCOMPtr<nsIIDNService> idnSrv =
                             do_GetService(NS_IDNSERVICE_CONTRACTID);
                         if (idnSrv &&
                             NS_SUCCEEDED(idnSrv->IsACE(host, &isACE)) && isACE &&
-                            NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host)))
+                            NS_SUCCEEDED(idnSrv->ConvertACEtoUTF8(host, utf8Host))) {
                             sURIFixup->KeywordToURI(utf8Host,
+                                                    getter_AddRefs(newPostData),
                                                     getter_AddRefs(newURI));
-                        else
-                            sURIFixup->KeywordToURI(host, getter_AddRefs(newURI));
+                        } else {
+                            sURIFixup->KeywordToURI(host,
+                                                    getter_AddRefs(newPostData),
+                                                    getter_AddRefs(newURI));
+                        }
                     }
                 } // end keywordsEnabled
             }
 
             //
             // Now try change the address, e.g. turn http://foo into
             // http://www.foo.com
             //
@@ -6749,18 +6757,20 @@ nsDocShell::EndPageLoad(nsIWebProgress *
                             // Keyword lookup made a new URI so no need to try
                             // an alternate one.
                             doCreateAlternate = false;
                         }
                     }
                 }
                 if (doCreateAlternate) {
                     newURI = nullptr;
+                    newPostData = nullptr;
                     sURIFixup->CreateFixupURI(oldSpec,
                       nsIURIFixup::FIXUP_FLAGS_MAKE_ALTERNATE_URI,
+                                              getter_AddRefs(newPostData),
                                               getter_AddRefs(newURI));
                 }
             }
 
             // Did we make a new URI that is different to the old one? If so
             // load it.
             //
             if (newURI) {
@@ -6771,17 +6781,17 @@ nsDocShell::EndPageLoad(nsIWebProgress *
                 if (!sameURI) {
                     nsAutoCString newSpec;
                     newURI->GetSpec(newSpec);
                     NS_ConvertUTF8toUTF16 newSpecW(newSpec);
 
                     return LoadURI(newSpecW.get(),  // URI string
                                    LOAD_FLAGS_NONE, // Load flags
                                    nullptr,          // Referring URI
-                                   nullptr,          // Post data stream
+                                   newPostData,      // Post data stream
                                    nullptr);         // Headers stream
                 }
             }
         }
 
         // Well, fixup didn't work :-(
         // It is time to throw an error dialog box, and be done with it...
 
--- a/docshell/base/nsIURIFixup.idl
+++ b/docshell/base/nsIURIFixup.idl
@@ -2,21 +2,22 @@
  *
  * 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/. */
 
 #include "nsISupports.idl"
 
 interface nsIURI;
+interface nsIInputStream;
 
 /**
  * Interface implemented by objects capable of fixing up strings into URIs
  */
-[scriptable, uuid(773081ac-9f81-4bdb-9e7a-5e87b4361f09)]
+[scriptable, uuid(552a23bb-c1b2-426e-a801-d346c6a98f1d)]
 interface nsIURIFixup : nsISupports
 {
     /** No fixup flags. */
     const unsigned long FIXUP_FLAG_NONE = 0;
 
     /**
      * Allow the fixup to use a keyword lookup service to complete the URI.
      * The fixup object implementer should honour this flag and only perform
@@ -49,19 +50,30 @@ interface nsIURIFixup : nsISupports
 
     /**
      * Converts the specified string into a URI, first attempting
      * to correct any errors in the syntax or other vagaries. Returns
      * a wellformed URI or nullptr if it can't.
      *
      * @param aURIText    Candidate URI.
      * @param aFixupFlags Flags that govern ways the URI may be fixed up.
+     * @param aPostData   The POST data to submit with the returned
+     *                    URI (see nsISearchSubmission).
      */
-    nsIURI createFixupURI(in AUTF8String aURIText, in unsigned long aFixupFlags);
+    nsIURI createFixupURI(in AUTF8String aURIText, in unsigned long aFixupFlags,
+                          [optional] out nsIInputStream aPostData);
 
     /**
      * Converts the specified keyword string into a URI.  Note that it's the
      * caller's responsibility to check whether keywords are enabled and
      * whether aKeyword is a sensible keyword.
+     *
+     * @param aKeyword  The keyword string to convert into a URI
+     * @param aPostData The POST data to submit to the returned URI
+     *                  (see nsISearchSubmission).
+     *
+     * @throws NS_ERROR_FAILURE if the resulting URI requires submission of POST
+     *         data and aPostData is null.
      */
-    nsIURI keywordToURI(in AUTF8String aKeyword);
+    nsIURI keywordToURI(in AUTF8String aKeyword,
+                        [optional] out nsIInputStream aPostData);
 };