Bug 658242 - Search in bookmarks doesn't find javascript: bookmarks.
authorMarco Bonardo <mbonardo@mozilla.com>
Tue, 26 Jul 2011 15:12:38 +0200
changeset 74120 bb92a1746f596f4be197ac9dfa9bd24d36f3423b
parent 74119 8160165dfcb4eb737137782361cdbf99c4cc2617
child 74121 7454890376fc06f88c92278c1bef3424042b7c77
push idunknown
push userunknown
push dateunknown
bugs658242
milestone8.0a1
Bug 658242 - Search in bookmarks doesn't find javascript: bookmarks. r=dietrich
toolkit/components/places/SQLFunctions.cpp
toolkit/components/places/SQLFunctions.h
toolkit/components/places/mozIPlacesAutoComplete.idl
toolkit/components/places/nsNavHistory.cpp
toolkit/components/places/tests/queries/test_searchterms-bookmarklets.js
toolkit/components/places/tests/queries/xpcshell.ini
--- a/toolkit/components/places/SQLFunctions.cpp
+++ b/toolkit/components/places/SQLFunctions.cpp
@@ -226,31 +226,35 @@ namespace places {
     NS_ENSURE_SUCCESS(rv, rv);
 
     return NS_OK;
   }
 
   /* static */
   void
   MatchAutoCompleteFunction::fixupURISpec(const nsCString &aURISpec,
+                                          PRInt32 aMatchBehavior,
                                           nsCString &_fixedSpec)
   {
     nsCString unescapedSpec;
     (void)NS_UnescapeURL(aURISpec, esc_SkipControl | esc_AlwaysCopy,
                          unescapedSpec);
 
     // If this unescaped string is valid UTF-8, we'll use it.  Otherwise,
     // we will simply use our original string.
     NS_ASSERTION(_fixedSpec.IsEmpty(),
                  "Passing a non-empty string as an out parameter!");
     if (IsUTF8(unescapedSpec))
       _fixedSpec.Assign(unescapedSpec);
     else
       _fixedSpec.Assign(aURISpec);
 
+    if (aMatchBehavior == mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED)
+      return;
+
     if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("http://")))
       _fixedSpec.Cut(0, 7);
     else if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("https://")))
       _fixedSpec.Cut(0, 8);
     else if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("ftp://")))
       _fixedSpec.Cut(0, 6);
 
     if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("www.")))
@@ -314,16 +318,17 @@ namespace places {
   }
 
   /* 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_BOUNDARY:
       default:
         return findOnBoundary;
     };
   }
@@ -346,19 +351,22 @@ namespace places {
     #define HAS_BEHAVIOR(aBitName) \
       (searchBehavior & mozIPlacesAutoComplete::BEHAVIOR_##aBitName)
 
     nsCAutoString searchString;
     (void)aArguments->GetUTF8String(kArgSearchString, searchString);
     nsCString url;
     (void)aArguments->GetUTF8String(kArgIndexURL, url);
 
+    PRInt32 matchBehavior = aArguments->AsInt32(kArgIndexMatchBehavior);
+
     // We only want to filter javascript: URLs if we are not supposed to search
     // for them, and the search does not start with "javascript:".
-    if (!HAS_BEHAVIOR(JAVASCRIPT) &&
+    if (matchBehavior != mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED &&
+        !HAS_BEHAVIOR(JAVASCRIPT) &&
         !StringBeginsWith(searchString, NS_LITERAL_CSTRING("javascript:")) &&
         StringBeginsWith(url, NS_LITERAL_CSTRING("javascript:"))) {
       NS_ADDREF(*_result = new IntegerVariant(0));
       return NS_OK;
     }
 
     PRInt32 visitCount = aArguments->AsInt32(kArgIndexVisitCount);
     bool typed = aArguments->AsInt32(kArgIndexTyped) ? true : false;
@@ -376,23 +384,22 @@ namespace places {
       (HAS_BEHAVIOR(TAG) && tags.IsVoid()) ||
       (HAS_BEHAVIOR(OPENPAGE) && openPageCount == 0)
     );
     if (!matches) {
       NS_ADDREF(*_result = new IntegerVariant(0));
       return NS_OK;
     }
 
+    // Obtain our search function.
+    searchFunctionPtr searchFunction = getSearchFunction(matchBehavior);
+
     // Clean up our URI spec and prepare it for searching.
     nsCString fixedURI;
-    fixupURISpec(url, fixedURI);
-
-    // Obtain our search function.
-    PRInt32 matchBehavior = aArguments->AsInt32(kArgIndexMatchBehavior);
-    searchFunctionPtr searchFunction = getSearchFunction(matchBehavior);
+    fixupURISpec(url, matchBehavior, fixedURI);
 
     nsCAutoString title;
     (void)aArguments->GetUTF8String(kArgIndexTitle, title);
 
     // Determine if every token matches either the bookmark title, tags, page
     // title, or page URL.
     nsCWhitespaceTokenizer tokenizer(searchString);
     while (matches && tokenizer.hasMoreTokens()) {
--- a/toolkit/components/places/SQLFunctions.h
+++ b/toolkit/components/places/SQLFunctions.h
@@ -174,20 +174,24 @@ private:
 
   /**
    * Fixes a URI's spec such that it is ready to be searched.  This includes
    * unescaping escaped characters and removing certain specs that we do not
    * care to search for.
    *
    * @param aURISpec
    *        The spec of the URI to prepare for searching.
+   * @param aMatchBehavior
+   *        The matching behavior to use defined by one of the
+   *        mozIPlacesAutoComplete::MATCH_* values.
    * @param _fixedSpec
    *        An out parameter that is the fixed up string.
    */
-  static void fixupURISpec(const nsCString &aURISpec, nsCString &_fixedSpec);
+  static void fixupURISpec(const nsCString &aURISpec, PRInt32 aMatchBehavior,
+                           nsCString &_fixedSpec);
 };
 
 
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Frecency Calculation Function
 
 /**
--- a/toolkit/components/places/mozIPlacesAutoComplete.idl
+++ b/toolkit/components/places/mozIPlacesAutoComplete.idl
@@ -68,16 +68,22 @@ interface mozIPlacesAutoComplete : nsISu
    */
   const long MATCH_BOUNDARY = 2;
 
   /**
    * Match only the beginning of each search term.
    */
   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;
+
   //////////////////////////////////////////////////////////////////////////////
   //// Search Behavior Constants
 
   /**
    * Search through history.
    */
   const long BEHAVIOR_HISTORY = 1 << 0;
 
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -5701,17 +5701,17 @@ nsNavHistory::QueryToSelectClause(nsNavH
   // search terms
   PRBool hasSearchTerms;
   if (NS_SUCCEEDED(aQuery->GetHasSearchTerms(&hasSearchTerms)) && hasSearchTerms) {
     // Re-use the autocomplete_match function.  Setting the behavior to 0
     // it can match everything and work as a nice case insensitive comparator.
     clause.Condition("AUTOCOMPLETE_MATCH(").Param(":search_string")
           .Str(", h.url, page_title, tags, ")
           .Str(nsPrintfCString(17, "0, 0, 0, 0, %d, 0)",
-                               mozIPlacesAutoComplete::MATCH_ANYWHERE).get());
+                               mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED).get());
   }
 
   // min and max visit count
   if (aQuery->MinVisits() >= 0)
     clause.Condition("h.visit_count >=").Param(":min_visits");
 
   if (aQuery->MaxVisits() >= 0)
     clause.Condition("h.visit_count <=").Param(":max_visits");
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/queries/test_searchterms-bookmarklets.js
@@ -0,0 +1,67 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Check that bookmarklets are returned by searches with searchTerms.
+
+let testData = [
+  { isInQuery: true
+  , isBookmark: true
+  , title: "bookmark 1"
+  , uri: "http://mozilla.org/script/"
+  },
+
+  { isInQuery: true
+  , isBookmark: true
+  , title: "bookmark 2"
+  , uri: "javascript:alert('moz');"
+  }
+];
+
+add_test(function test_seach_by_title()
+{
+  let query = PlacesUtils.history.getNewQuery();
+  query.searchTerms = "bookmark";
+  let options = PlacesUtils.history.getNewQueryOptions();
+  options.queryType = options.QUERY_TYPE_BOOKMARKS;
+  let root = PlacesUtils.history.executeQuery(query, options).root;
+  root.containerOpen = true;
+  compareArrayToResult(testData, root);
+  root.containerOpen = false;
+
+  run_next_test();
+});
+
+add_test(function test_seach_by_schemeToken()
+{
+  let query = PlacesUtils.history.getNewQuery();
+  query.searchTerms = "script";
+  let options = PlacesUtils.history.getNewQueryOptions();
+  options.queryType = options.QUERY_TYPE_BOOKMARKS;
+  let root = PlacesUtils.history.executeQuery(query, options).root;
+  root.containerOpen = true;
+  compareArrayToResult(testData, root);
+  root.containerOpen = false;
+
+  run_next_test();
+});
+
+add_test(function test_seach_by_uriAndTitle()
+{
+  let query = PlacesUtils.history.getNewQuery();
+  query.searchTerms = "moz";
+  let options = PlacesUtils.history.getNewQueryOptions();
+  options.queryType = options.QUERY_TYPE_BOOKMARKS;
+  let root = PlacesUtils.history.executeQuery(query, options).root;
+  root.containerOpen = true;
+  compareArrayToResult(testData, root);
+  root.containerOpen = false;
+
+  run_next_test();
+});
+
+function run_test()
+{
+  populateDB(testData);
+
+  run_next_test();
+}
--- a/toolkit/components/places/tests/queries/xpcshell.ini
+++ b/toolkit/components/places/tests/queries/xpcshell.ini
@@ -12,12 +12,13 @@ tail =
 [test_history_queries_titles_liveUpdate.js]
 [test_onlyBookmarked.js]
 [test_querySerialization.js]
 [test_redirectsMode.js]
 [test_results-as-tag-contents-query.js]
 [test_results-as-visit.js]
 [test_searchterms-domain.js]
 [test_searchterms-uri.js]
+[test_searchterms-bookmarklets.js]
 [test_sort-date-site-grouping.js]
 [test_sorting.js]
 [test_tags.js]
 [test_transitions.js]