Bug 483086. r=gavin, a=beltzner
authorRyan Flint <rflint@ryanflint.com>
Wed, 18 Mar 2009 00:28:56 -0400
changeset 23806 87ebf1fc30f1830aa3aa90b02ddd28bad1d77aac
parent 23805 007e38c25862158ed3da9b3d38a4e0396a7028a4
child 23807 f195dc8f2d4728c8c33e88c933b4230e9d7d03b1
push id926
push userrflint@ryanflint.com
push dateWed, 18 Mar 2009 04:30:19 +0000
reviewersgavin, beltzner
bugs483086
milestone1.9.1b4pre
Bug 483086. r=gavin, a=beltzner
browser/components/search/test/483086-1.xml
browser/components/search/test/483086-2.xml
browser/components/search/test/Makefile.in
browser/components/search/test/browser_483086.js
toolkit/components/search/nsSearchService.js
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/483086-1.xml
@@ -0,0 +1,10 @@
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+                       xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+  <ShortName>483086a</ShortName>
+  <Description>Bug 483086 Test 1</Description>
+  <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC</Image>
+  <Url type="text/html" method="GET" template="http://localhost:8888/browser/browser/components/search/test/?search">
+    <Param name="test" value="{searchTerms}"/>
+  </Url>
+  <moz:SearchForm>foo://example.com</moz:SearchForm>
+</OpenSearchDescription>
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/483086-2.xml
@@ -0,0 +1,10 @@
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+                       xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+  <ShortName>483086b</ShortName>
+  <Description>Bug 483086 Test 2</Description>
+  <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC</Image>
+  <Url type="text/html" method="GET" template="http://localhost:8888/browser/browser/components/search/test/?search">
+    <Param name="test" value="{searchTerms}"/>
+  </Url>
+  <moz:SearchForm>http://example.com</moz:SearchForm>
+</OpenSearchDescription>
--- a/browser/components/search/test/Makefile.in
+++ b/browser/components/search/test/Makefile.in
@@ -43,12 +43,15 @@ relativesrcdir  =  browser/components/se
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES = 	  browser_405664.js \
 	                  browser_415700.js \
 	                  testEngine.xml \
 	                  browser_426329.js \
+	                  browser_483086.js \
+	                  483086-1.xml \
+	                  483086-2.xml \
 	                  $(NULL)
 
 libs:: $(_BROWSER_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/browser/components/search/test/browser_483086.js
@@ -0,0 +1,90 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *  Ryan Flint <rflint@dslr.net> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+let gSS = Cc["@mozilla.org/browser/search-service;1"].
+           getService(Ci.nsIBrowserSearchService);
+let gObs = Cc["@mozilla.org/observer-service;1"].
+           getService(Ci.nsIObserverService);
+
+function test() {
+  waitForExplicitFinish();
+
+  let observer = {
+    observe: function(aSubject, aTopic, aData) {
+      switch (aData) {
+        case "engine-added":
+          let engine = gSS.getEngineByName("483086a");
+          ok(engine, "Test engine 1 installed");
+          isnot(engine.searchForm, "foo://example.com",
+                "Invalid SearchForm URL dropped");
+          gSS.removeEngine(engine);
+          break;
+        case "engine-removed":
+          gObs.removeObserver(this, "browser-search-engine-modified");
+          test2();
+          break;
+      }
+    }
+  };
+
+  gObs.addObserver(observer, "browser-search-engine-modified", false);
+  gSS.addEngine("http://localhost:8888/browser/browser/components/search/test/483086-1.xml",
+                Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00",
+                false);
+}
+
+function test2() {
+  let observer = {
+    observe: function(aSubject, aTopic, aData) {
+      switch (aData) {
+        case "engine-added":
+          let engine = gSS.getEngineByName("483086b");
+          ok(engine, "Test engine 2 installed");
+          is(engine.searchForm, "http://example.com", "SearchForm is correct");
+          gSS.removeEngine(engine);
+          break;
+        case "engine-removed":  
+          gObs.removeObserver(this, "browser-search-engine-modified");
+          finish();
+          break;
+      }
+    }
+  };
+
+  gObs.addObserver(observer, "browser-search-engine-modified", false);
+  gSS.addEngine("http://localhost:8888/browser/browser/components/search/test/483086-2.xml",
+                Ci.nsISearchEngine.DATA_XML, "data:image/x-icon;%00",
+                false);
+}
--- a/toolkit/components/search/nsSearchService.js
+++ b/toolkit/components/search/nsSearchService.js
@@ -87,17 +87,17 @@ const SHERLOCK_FILE_EXT = "src";
 // Delay for lazy serialization (ms)
 const LAZY_SERIALIZE_DELAY = 100;
 
 // Delay for batching invalidation of the JSON cache (ms)
 const CACHE_INVALIDATION_DELAY = 1000;
 
 // Current cache version. This should be incremented if the format of the cache
 // file is modified.
-const CACHE_VERSION = 3;
+const CACHE_VERSION = 4;
 
 const ICON_DATAURL_PREFIX = "data:image/x-icon;base64,";
 
 // Supported extensions for Sherlock plugin icons
 const SHERLOCK_ICON_EXTENSIONS = [".gif", ".png", ".jpg", ".jpeg"];
 
 const NEW_LINES = /(\r\n|\r|\n)/;
 
@@ -1050,17 +1050,27 @@ Engine.prototype = {
   _hidden: null,
   // The engine's name.
   _name: null,
   // The engine type. See engine types (TYPE_) defined above.
   _type: null,
   // The name of the charset used to submit the search terms.
   _queryCharset: null,
   // A URL string pointing to the engine's search form.
-  _searchForm: null,
+  __searchForm: null,
+  get _searchForm() {
+    return this.__searchForm;
+  },
+  set _searchForm(aValue) {
+    if (/^https?:/i.test(aValue))
+      this.__searchForm = aValue;
+    else
+      LOG("_searchForm: Invalid URL dropped for " + this._name ||
+          "the current engine");
+  },
   // The URI object from which the engine was retrieved.
   // This is null for local plugins, and is used for error messages and logging.
   _uri: null,
   // Whether to obtain user confirmation before adding the engine. This is only
   // used when the engine is first added to the list.
   _confirm: false,
   // Whether to set this as the current engine as soon as it is loaded.  This
   // is only used when the engine is first added to the list.
@@ -1978,17 +1988,17 @@ Engine.prototype = {
     this._description = aJson.description;
     if (aJson._hasPreferredIcon == undefined)
       this._hasPreferredIcon = true;
     else
       this._hasPreferredIcon = false;
     this._hidden = aJson.hidden || null;
     this._type = aJson.type || SEARCH_TYPE_MOZSEARCH;
     this._queryCharset = aJson.queryCharset || DEFAULT_QUERY_CHARSET;
-    this._searchForm = aJson.searchForm;
+    this.__searchForm = aJson.__searchForm;
     this.__installLocation = aJson._installLocation || SEARCH_APP_DIR;
     this._updateInterval = aJson._updateInterval || null;
     this._updateURL = aJson._updateURL || null;
     this._iconUpdateURL = aJson._iconUpdateURL || null;
     if (aJson._readOnly == undefined)
       this._readOnly = true;
     else
       this._readOnly = false;
@@ -2010,17 +2020,17 @@ Engine.prototype = {
    * @returns An object suitable for serialization as JSON.
    **/
   _serializeToJSON: function SRCH_ENG__serializeToJSON(aFilter) {
     var json = {
       _id: this._id,
       _name: this._name,
       description: this.description,
       filePath: this._file.QueryInterface(Ci.nsILocalFile).persistentDescriptor,
-      searchForm: this.searchForm,
+      __searchForm: this.__searchForm,
       _iconURL: this._iconURL,
       _urls: [url._serializeToJSON() for each(url in this._urls)] 
     };
 
     if (this._installLocation != SEARCH_APP_DIR || !aFilter)
       json._installLocation = this._installLocation;
     if (this._updateInterval || !aFilter)
       json._updateInterval = this._updateInterval;