Bug 742776 - Use a case sensitive match for the URI path in inline autocomplete query.
authorMarco Bonardo <mbonardo@mozilla.com>
Thu, 19 Apr 2012 22:17:04 +0200
changeset 95313 853ae8c135f9e904c8c1d23ebf869af313bf0124
parent 95312 df8d8d06a7bd19decb85ea3a166b332cf449fff4
child 95314 4209594a01af72ea2e31a46c69c9750f17e2725d
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs742776
milestone14.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 742776 - Use a case sensitive match for the URI path in inline autocomplete query. r=gavin a=desktop-only
toolkit/components/places/SQLFunctions.cpp
toolkit/components/places/SQLFunctions.h
toolkit/components/places/mozIPlacesAutoComplete.idl
toolkit/components/places/nsPlacesAutoComplete.js
toolkit/components/places/tests/inline/test_casing.js
--- a/toolkit/components/places/SQLFunctions.cpp
+++ b/toolkit/components/places/SQLFunctions.cpp
@@ -315,25 +315,38 @@ namespace places {
     // We don't need to check CaseInsensitiveUTF8CharsEqual's error condition
     // (stored in |dummy|), since the function will return false if it
     // encounters an error.
 
     return false;
   }
 
   /* static */
+  bool
+  MatchAutoCompleteFunction::findBeginningCaseSensitive(
+    const nsDependentCSubstring &aToken,
+    const nsACString &aSourceString)
+  {
+    NS_PRECONDITION(!aToken.IsEmpty(), "Don't search for an empty token!");
+
+    return StringBeginsWith(aSourceString, aToken);
+  }
+
+  /* static */
   MatchAutoCompleteFunction::searchFunctionPtr
   MatchAutoCompleteFunction::getSearchFunction(PRInt32 aBehavior)
   {
     switch (aBehavior) {
       case mozIPlacesAutoComplete::MATCH_ANYWHERE:
       case mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED:
         return findAnywhere;
       case mozIPlacesAutoComplete::MATCH_BEGINNING:
         return findBeginning;
+      case mozIPlacesAutoComplete::MATCH_BEGINNING_CASE_SENSITIVE:
+        return findBeginningCaseSensitive;
       case mozIPlacesAutoComplete::MATCH_BOUNDARY:
       default:
         return findOnBoundary;
     };
   }
 
   NS_IMPL_THREADSAFE_ISUPPORTS1(
     MatchAutoCompleteFunction,
--- a/toolkit/components/places/SQLFunctions.h
+++ b/toolkit/components/places/SQLFunctions.h
@@ -142,16 +142,28 @@ private:
    * @param aSourceString
    *        The string to search.
    * @return true if found, false otherwise.
    */
   static bool findBeginning(const nsDependentCSubstring &aToken,
                             const nsACString &aSourceString);
 
   /**
+   * Tests if aSourceString starts with aToken in a case sensitive way.
+   *
+   * @param aToken
+   *        The string to search for.
+   * @param aSourceString
+   *        The string to search.
+   * @return true if found, false otherwise.
+   */
+  static bool findBeginningCaseSensitive(const nsDependentCSubstring &aToken,
+                                         const nsACString &aSourceString);
+
+  /**
    * Searches aSourceString for aToken anywhere in the string in a case-
    * insensitive way.
    *
    * @param aToken
    *        The string to search for.
    * @param aSourceString
    *        The string to search.
    * @return true if found, false otherwise.
--- a/toolkit/components/places/mozIPlacesAutoComplete.idl
+++ b/toolkit/components/places/mozIPlacesAutoComplete.idl
@@ -74,16 +74,22 @@ interface mozIPlacesAutoComplete : nsISu
   const long MATCH_BEGINNING = 3;
 
   /**
    * Match anywhere in each searchable term without doing any transformation
    * or stripping on the underlying data.
    */
   const long MATCH_ANYWHERE_UNMODIFIED = 4;
 
+  /**
+   * Match only the beginning of each search term using a case sensitive
+   * comparator.
+   */
+  const long MATCH_BEGINNING_CASE_SENSITIVE = 5;
+
   //////////////////////////////////////////////////////////////////////////////
   //// Search Behavior Constants
 
   /**
    * Search through history.
    */
   const long BEHAVIOR_HISTORY = 1 << 0;
 
--- a/toolkit/components/places/nsPlacesAutoComplete.js
+++ b/toolkit/components/places/nsPlacesAutoComplete.js
@@ -71,16 +71,17 @@ const kTopicShutdown = "places-shutdown"
 const kPrefChanged = "nsPref:changed";
 
 // Match type constants.  These indicate what type of search function we should
 // be using.
 const MATCH_ANYWHERE = Ci.mozIPlacesAutoComplete.MATCH_ANYWHERE;
 const MATCH_BOUNDARY_ANYWHERE = Ci.mozIPlacesAutoComplete.MATCH_BOUNDARY_ANYWHERE;
 const MATCH_BOUNDARY = Ci.mozIPlacesAutoComplete.MATCH_BOUNDARY;
 const MATCH_BEGINNING = Ci.mozIPlacesAutoComplete.MATCH_BEGINNING;
+const MATCH_BEGINNING_CASE_SENSITIVE = Ci.mozIPlacesAutoComplete.MATCH_BEGINNING_CASE_SENSITIVE;
 
 // AutoComplete index constants.  All AutoComplete queries will provide these
 // columns in this order.
 const kQueryIndexURL = 0;
 const kQueryIndexTitle = 1;
 const kQueryIndexFaviconURL = 2;
 const kQueryIndexBookmarked = 3;
 const kQueryIndexBookmarkTitle = 4;
@@ -1434,21 +1435,30 @@ urlInlineComplete.prototype = {
     // We don't need to search if we have no "/" separator, or if it's at
     // the end of the search text.
     if (lastSlashIndex == -1 ||
         lastSlashIndex == this._currentSearchString.length - 1) {
       this._finishSearch();
       return;
     }
 
+    // The URIs in the database are fixed up, so we can match on a lowercased
+    // host, but the path must be matched in a case sensitive way.
+    let pathIndex =
+      this._originalSearchString.indexOf("/", this._strippedPrefix.length);
+    this._currentSearchString = fixupSearchText(
+      this._originalSearchString.slice(0, pathIndex).toLowerCase() +
+      this._originalSearchString.slice(pathIndex)
+    );
+
     // Within the standard autocomplete query, we only search the beginning
     // of URLs for 1 result.
     let query = this._asyncQuery;
     let (params = query.params) {
-      params.matchBehavior = MATCH_BEGINNING;
+      params.matchBehavior = MATCH_BEGINNING_CASE_SENSITIVE;
       params.searchBehavior = Ci.mozIPlacesAutoComplete["BEHAVIOR_URL"];
       params.searchString = this._currentSearchString;
     }
 
     // Execute the async query
     let wrapper = new AutoCompleteStatementCallbackWrapper(this, this._db);
     this._pendingQuery = wrapper.executeAsync([query]);
   },
--- a/toolkit/components/places/tests/inline/test_casing.js
+++ b/toolkit/components/places/tests/inline/test_casing.js
@@ -9,26 +9,44 @@ add_autocomplete_test([
   function () {
     addBookmark({ url: "http://mozilla.org/test/" });
   }
 ]);
 
 add_autocomplete_test([
   "Searching for cased entry 2",
   "mozilla.org/T",
-  { autoFilled: "mozilla.org/Test/", completed: "mozilla.org/test/" },
+  { autoFilled: "mozilla.org/T", completed: "mozilla.org/T" },
   function () {
     addBookmark({ url: "http://mozilla.org/test/" });
   }
 ]);
 
 add_autocomplete_test([
   "Searching for cased entry 3",
+  "mozilla.org/T",
+  { autoFilled: "mozilla.org/Test/", completed: "mozilla.org/Test/" },
+  function () {
+    addBookmark({ url: "http://mozilla.org/Test/" });
+  }
+]);
+
+add_autocomplete_test([
+  "Searching for cased entry 4",
   "mOzilla.org/t",
-  { autoFilled: "mOzilla.org/test/", completed: "mozilla.org/Test/" },
+  { autoFilled: "mOzilla.org/t", completed: "mOzilla.org/t" },
+  function () {
+    addBookmark({ url: "http://mozilla.org/Test/" });
+  },
+]);
+
+add_autocomplete_test([
+  "Searching for cased entry 5",
+  "mOzilla.org/T",
+  { autoFilled: "mOzilla.org/Test/", completed: "mozilla.org/Test/" },
   function () {
     addBookmark({ url: "http://mozilla.org/Test/" });
   },
 ]);
 
 add_autocomplete_test([
   "Searching for untrimmed cased entry",
   "http://mOz",
@@ -45,22 +63,40 @@ add_autocomplete_test([
   function () {
     addBookmark({ url: "http://www.mozilla.org/Test/" });
   },
 ]);
 
 add_autocomplete_test([
   "Searching for untrimmed cased entry with path",
   "http://mOzilla.org/t",
-  { autoFilled: "http://mOzilla.org/test/", completed: "http://mozilla.org/Test/" },
+  { autoFilled: "http://mOzilla.org/t", completed: "http://mOzilla.org/t" },
+  function () {
+    addBookmark({ url: "http://mozilla.org/Test/" });
+  },
+]);
+
+add_autocomplete_test([
+  "Searching for untrimmed cased entry with path 2",
+  "http://mOzilla.org/T",
+  { autoFilled: "http://mOzilla.org/Test/", completed: "http://mozilla.org/Test/" },
   function () {
     addBookmark({ url: "http://mozilla.org/Test/" });
   },
 ]);
 
 add_autocomplete_test([
   "Searching for untrimmed cased entry with www and path",
   "http://www.mOzilla.org/t",
-  { autoFilled: "http://www.mOzilla.org/test/", completed: "http://www.mozilla.org/Test/" },
+  { autoFilled: "http://www.mOzilla.org/t", completed: "http://www.mOzilla.org/t" },
   function () {
     addBookmark({ url: "http://www.mozilla.org/Test/" });
   },
 ]);
+
+add_autocomplete_test([
+  "Searching for untrimmed cased entry with www and path 2",
+  "http://www.mOzilla.org/T",
+  { autoFilled: "http://www.mOzilla.org/Test/", completed: "http://www.mozilla.org/Test/" },
+  function () {
+    addBookmark({ url: "http://www.mozilla.org/Test/" });
+  },
+]);