Bug 463483 - matchOnlyTyped no longer honored with special filters. r=dietrich
authorEdward Lee <edward.lee@engineering.uiuc.edu>
Wed, 07 Jan 2009 15:47:56 -0800
changeset 23428 67aa0bc48118
parent 23427 3e1f7b96a3f2
child 23429 5a68110f39c1
push id4539
push useredward.lee@engineering.uiuc.edu
push date2009-01-07 23:49 +0000
treeherdermozilla-central@5a68110f39c1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdietrich
bugs463483, 463558
milestone1.9.2a1pre
Bug 463483 - matchOnlyTyped no longer honored with special filters. r=dietrich Bug 463558 - Switch matchOnlyTyped to restrict.typed "~" (default.behavior + 32)
browser/app/profile/firefox.js
toolkit/components/places/src/nsNavHistory.cpp
toolkit/components/places/src/nsNavHistory.h
toolkit/components/places/src/nsNavHistoryAutoComplete.cpp
toolkit/components/places/tests/autocomplete/test_special_search.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -209,17 +209,16 @@ pref("browser.urlbar.clickSelectsAll", f
 pref("browser.urlbar.clickSelectsAll", true);
 #endif
 #ifdef UNIX_BUT_NOT_MAC
 pref("browser.urlbar.doubleClickSelectsAll", true);
 #else
 pref("browser.urlbar.doubleClickSelectsAll", false);
 #endif
 pref("browser.urlbar.autoFill", false);
-pref("browser.urlbar.matchOnlyTyped", false);
 // 0: Match anywhere (e.g., middle of words)
 // 1: Match on word boundaries and then try matching anywhere
 // 2: Match only on word boundaries (e.g., after / or .)
 // 3: Match at the beginning of the url or title
 pref("browser.urlbar.matchBehavior", 1);
 // 0: Search nothing
 // 1: Search history (visited pages)
 // 2: Search bookmarks
@@ -236,23 +235,24 @@ pref("browser.urlbar.search.chunkSize", 
 pref("browser.urlbar.search.timeout", 100);
 
 // The special characters below can be typed into the urlbar to either restrict
 // the search to visited history, bookmarked, tagged pages; or force a match on
 // just the title text or url.
 pref("browser.urlbar.restrict.history", "^");
 pref("browser.urlbar.restrict.bookmark", "*");
 pref("browser.urlbar.restrict.tag", "+");
+pref("browser.urlbar.restrict.typed", "~");
 pref("browser.urlbar.match.title", "#");
 pref("browser.urlbar.match.url", "@");
 
 // The default behavior for the urlbar can be configured to use any combination
 // of the restrict or match filters with each additional filter restricting
 // more (intersection). Add the following values to set the behavior as the
-// default: 1: history, 2: bookmark, 4: tag, 8: title, 16: url
+// default: 1: history, 2: bookmark, 4: tag, 8: title, 16: url, 32: typed
 // E.g., 0 = show all results (no filtering), 1 = only visited pages in history,
 // 2 = only bookmarks, 3 = visited bookmarks, 1+16 = history matching in the url
 pref("browser.urlbar.default.behavior", 0);
 
 // Number of milliseconds to wait for the http headers (and thus
 // the Content-Disposition filename) before giving up and falling back to 
 // picking a filename without that info in hand so that the user sees some
 // feedback from their action.
--- a/toolkit/components/places/src/nsNavHistory.cpp
+++ b/toolkit/components/places/src/nsNavHistory.cpp
@@ -113,28 +113,28 @@
 // checking each one for every page visit, which will be somewhat slower.
 #define RECENT_EVENT_QUEUE_MAX_LENGTH 128
 
 // preference ID strings
 #define PREF_BRANCH_BASE                        "browser."
 #define PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN    "history_expire_days_min"
 #define PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX    "history_expire_days"
 #define PREF_BROWSER_HISTORY_EXPIRE_SITES       "history_expire_sites"
-#define PREF_AUTOCOMPLETE_ONLY_TYPED            "urlbar.matchOnlyTyped"
 #define PREF_AUTOCOMPLETE_MATCH_BEHAVIOR        "urlbar.matchBehavior"
 #define PREF_AUTOCOMPLETE_SEARCH_SOURCES        "urlbar.search.sources"
 #define PREF_AUTOCOMPLETE_FILTER_JAVASCRIPT     "urlbar.filter.javascript"
 #define PREF_AUTOCOMPLETE_ENABLED               "urlbar.autocomplete.enabled"
 #define PREF_AUTOCOMPLETE_MAX_RICH_RESULTS      "urlbar.maxRichResults"
 #define PREF_AUTOCOMPLETE_DEFAULT_BEHAVIOR      "urlbar.default.behavior"
 #define PREF_AUTOCOMPLETE_RESTRICT_HISTORY      "urlbar.restrict.history"
 #define PREF_AUTOCOMPLETE_RESTRICT_BOOKMARK     "urlbar.restrict.bookmark"
 #define PREF_AUTOCOMPLETE_RESTRICT_TAG          "urlbar.restrict.tag"
 #define PREF_AUTOCOMPLETE_MATCH_TITLE           "urlbar.match.title"
 #define PREF_AUTOCOMPLETE_MATCH_URL             "urlbar.match.url"
+#define PREF_AUTOCOMPLETE_RESTRICT_TYPED        "urlbar.restrict.typed"
 #define PREF_AUTOCOMPLETE_SEARCH_CHUNK_SIZE     "urlbar.search.chunkSize"
 #define PREF_AUTOCOMPLETE_SEARCH_TIMEOUT        "urlbar.search.timeout"
 #define PREF_DB_CACHE_PERCENTAGE                "history_cache_percentage"
 #define PREF_FRECENCY_NUM_VISITS                "places.frecency.numVisits"
 #define PREF_FRECENCY_CALC_ON_IDLE              "places.frecency.numCalcOnIdle"
 #define PREF_FRECENCY_CALC_ON_MIGRATE           "places.frecency.numCalcOnMigrate"
 #define PREF_FRECENCY_UPDATE_IDLE_TIME          "places.frecency.updateIdleTime"
 #define PREF_FRECENCY_FIRST_BUCKET_CUTOFF       "places.frecency.firstBucketCutoff"
@@ -314,22 +314,24 @@ const PRInt32 nsNavHistory::kGetInfoInde
 
 const PRInt32 nsNavHistory::kAutoCompleteIndex_URL = 0;
 const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1;
 const PRInt32 nsNavHistory::kAutoCompleteIndex_FaviconURL = 2;
 const PRInt32 nsNavHistory::kAutoCompleteIndex_ParentId = 3;
 const PRInt32 nsNavHistory::kAutoCompleteIndex_BookmarkTitle = 4;
 const PRInt32 nsNavHistory::kAutoCompleteIndex_Tags = 5;
 const PRInt32 nsNavHistory::kAutoCompleteIndex_VisitCount = 6;
+const PRInt32 nsNavHistory::kAutoCompleteIndex_Typed = 7;
 
 const PRInt32 nsNavHistory::kAutoCompleteBehaviorHistory = 1 << 0;
 const PRInt32 nsNavHistory::kAutoCompleteBehaviorBookmark = 1 << 1;
 const PRInt32 nsNavHistory::kAutoCompleteBehaviorTag = 1 << 2;
 const PRInt32 nsNavHistory::kAutoCompleteBehaviorTitle = 1 << 3;
 const PRInt32 nsNavHistory::kAutoCompleteBehaviorUrl = 1 << 4;
+const PRInt32 nsNavHistory::kAutoCompleteBehaviorTyped = 1 << 5;
 
 static const char* gQuitApplicationMessage = "quit-application";
 static const char* gXpcomShutdown = "xpcom-shutdown";
 static const char* gAutoCompleteFeedback = "autocomplete-will-enter-text";
 
 // annotation names
 const char nsNavHistory::kAnnotationPreviousEncoding[] = "history/encoding";
 
@@ -362,25 +364,25 @@ nsNavHistory::GetSingleton()
 
 // nsNavHistory::nsNavHistory
 
 nsNavHistory::nsNavHistory() : mBatchLevel(0),
                                mBatchHasTransaction(PR_FALSE),
                                mNowValid(PR_FALSE),
                                mExpireNowTimer(nsnull),
                                mExpire(this),
-                               mAutoCompleteOnlyTyped(PR_FALSE),
                                mAutoCompleteMatchBehavior(MATCH_BOUNDARY_ANYWHERE),
                                mAutoCompleteSearchSources(SEARCH_BOTH),
                                mAutoCompleteMaxResults(25),
                                mAutoCompleteRestrictHistory(NS_LITERAL_STRING("^")),
                                mAutoCompleteRestrictBookmark(NS_LITERAL_STRING("*")),
                                mAutoCompleteRestrictTag(NS_LITERAL_STRING("+")),
                                mAutoCompleteMatchTitle(NS_LITERAL_STRING("#")),
                                mAutoCompleteMatchUrl(NS_LITERAL_STRING("@")),
+                               mAutoCompleteRestrictTyped(NS_LITERAL_STRING("~")),
                                mAutoCompleteSearchChunkSize(100),
                                mAutoCompleteSearchTimeout(100),
                                mAutoCompleteDefaultBehavior(0),
                                mAutoCompleteCurrentBehavior(0),
                                mPreviousChunkOffset(-1),
                                mAutoCompleteFinishedSearch(PR_FALSE),
                                mExpireDaysMin(0),
                                mExpireDaysMax(0),
@@ -494,27 +496,27 @@ nsNavHistory::Init()
    ****************************************************************************/
 
   nsCOMPtr<nsIObserverService> observerService =
     do_GetService("@mozilla.org/observer-service;1", &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
   if (pbi) {
-    pbi->AddObserver(PREF_AUTOCOMPLETE_ONLY_TYPED, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_MATCH_BEHAVIOR, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_SEARCH_SOURCES, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_FILTER_JAVASCRIPT, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_MAX_RICH_RESULTS, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_DEFAULT_BEHAVIOR, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_HISTORY, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_BOOKMARK, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_TAG, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_MATCH_TITLE, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_MATCH_URL, this, PR_FALSE);
+    pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_TYPED, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_SEARCH_CHUNK_SIZE, this, PR_FALSE);
     pbi->AddObserver(PREF_AUTOCOMPLETE_SEARCH_TIMEOUT, this, PR_FALSE);
     pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX, this, PR_FALSE);
     pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN, this, PR_FALSE);
     pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_SITES, this, PR_FALSE);
   }
 
   observerService->AddObserver(this, gQuitApplicationMessage, PR_FALSE);
@@ -2003,20 +2005,16 @@ nsNavHistory::LoadPrefs(PRBool aInitiali
   // NOTE: if history is disabled in preferences, then mExpireDaysMax == 0
   if (mExpireDaysMax && mExpireDaysMax < mExpireDaysMin)
     mExpireDaysMax = mExpireDaysMin;
   if (NS_FAILED(mPrefBranch->GetIntPref(PREF_BROWSER_HISTORY_EXPIRE_SITES,
                                         &mExpireSites)))
     mExpireSites = EXPIRATION_CAP_SITES;
   
 #ifdef MOZ_XUL
-  PRBool oldCompleteOnlyTyped = mAutoCompleteOnlyTyped;
-  mPrefBranch->GetBoolPref(PREF_AUTOCOMPLETE_ONLY_TYPED,
-                           &mAutoCompleteOnlyTyped);
-
   PRInt32 matchBehavior = 1;
   mPrefBranch->GetIntPref(PREF_AUTOCOMPLETE_MATCH_BEHAVIOR,
                           &matchBehavior);
   switch (matchBehavior) {
     case 0:
       mAutoCompleteMatchBehavior = MATCH_ANYWHERE;
       break;
     case 2:
@@ -2071,22 +2069,19 @@ nsNavHistory::LoadPrefs(PRBool aInitiali
                            getter_Copies(prefStr));
   mAutoCompleteRestrictTag = NS_ConvertUTF8toUTF16(prefStr);
   mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_MATCH_TITLE,
                            getter_Copies(prefStr));
   mAutoCompleteMatchTitle = NS_ConvertUTF8toUTF16(prefStr);
   mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_MATCH_URL,
                            getter_Copies(prefStr));
   mAutoCompleteMatchUrl = NS_ConvertUTF8toUTF16(prefStr);
-
-  if (!aInitializing && oldCompleteOnlyTyped != mAutoCompleteOnlyTyped) {
-    // update the autocomplete statements if the option has changed.
-    nsresult rv = CreateAutoCompleteQueries();
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
+  mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_RESTRICT_TYPED,
+                           getter_Copies(prefStr));
+  mAutoCompleteRestrictTyped = NS_ConvertUTF8toUTF16(prefStr);
 
   // Clear out the search on any pref change to invalidate cached search
   mCurrentSearchString = EmptyString();
 #endif
 
   // get the frecency prefs
   nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
   if (prefs) {
--- a/toolkit/components/places/src/nsNavHistory.h
+++ b/toolkit/components/places/src/nsNavHistory.h
@@ -672,18 +672,20 @@ protected:
   //
   static const PRInt32 kAutoCompleteIndex_URL;
   static const PRInt32 kAutoCompleteIndex_Title;
   static const PRInt32 kAutoCompleteIndex_FaviconURL;
   static const PRInt32 kAutoCompleteIndex_ParentId;
   static const PRInt32 kAutoCompleteIndex_BookmarkTitle;
   static const PRInt32 kAutoCompleteIndex_Tags;
   static const PRInt32 kAutoCompleteIndex_VisitCount;
+  static const PRInt32 kAutoCompleteIndex_Typed;
   nsCOMPtr<mozIStorageStatement> mDBCurrentQuery; //  kAutoCompleteIndex_* results
   nsCOMPtr<mozIStorageStatement> mDBAutoCompleteQuery; //  kAutoCompleteIndex_* results
+  nsCOMPtr<mozIStorageStatement> mDBAutoCompleteTypedQuery; //  kAutoCompleteIndex_* results
   mozIStorageStatement* GetDBAutoCompleteHistoryQuery();
   nsCOMPtr<mozIStorageStatement> mDBAutoCompleteHistoryQuery; //  kAutoCompleteIndex_* results
   mozIStorageStatement* GetDBAutoCompleteStarQuery();
   nsCOMPtr<mozIStorageStatement> mDBAutoCompleteStarQuery; //  kAutoCompleteIndex_* results
   mozIStorageStatement* GetDBAutoCompleteTagsQuery();
   nsCOMPtr<mozIStorageStatement> mDBAutoCompleteTagsQuery; //  kAutoCompleteIndex_* results
   nsCOMPtr<mozIStorageStatement> mDBPreviousQuery; //  kAutoCompleteIndex_* results
   nsCOMPtr<mozIStorageStatement> mDBAdaptiveQuery; //  kAutoCompleteIndex_* results
@@ -719,25 +721,27 @@ protected:
   SearchSource mAutoCompleteSearchSources;
   PRBool mAutoCompleteFilterJavascript;
   PRInt32 mAutoCompleteMaxResults;
   nsString mAutoCompleteRestrictHistory;
   nsString mAutoCompleteRestrictBookmark;
   nsString mAutoCompleteRestrictTag;
   nsString mAutoCompleteMatchTitle;
   nsString mAutoCompleteMatchUrl;
+  nsString mAutoCompleteRestrictTyped;
   PRInt32 mAutoCompleteSearchChunkSize;
   PRInt32 mAutoCompleteSearchTimeout;
   nsCOMPtr<nsITimer> mAutoCompleteTimer;
 
   static const PRInt32 kAutoCompleteBehaviorHistory;
   static const PRInt32 kAutoCompleteBehaviorBookmark;
   static const PRInt32 kAutoCompleteBehaviorTag;
   static const PRInt32 kAutoCompleteBehaviorTitle;
   static const PRInt32 kAutoCompleteBehaviorUrl;
+  static const PRInt32 kAutoCompleteBehaviorTyped;
 
   PRInt32 mAutoCompleteDefaultBehavior; // kAutoCompleteBehavior* bitmap
   PRInt32 mAutoCompleteCurrentBehavior; // kAutoCompleteBehavior* bitmap
 
   // Original search string for case-sensitive usage
   nsString mOrigSearchString;
   // Search string and tokens for case-insensitive matching
   nsString mCurrentSearchString;
--- a/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp
+++ b/toolkit/components/places/src/nsNavHistoryAutoComplete.cpp
@@ -197,33 +197,34 @@ void GetAutoCompleteBaseQuery(nsACString
 // slower. Limiting moz_places with OFFSET+LIMIT will mostly help speed
 // of first chunks, that are usually most wanted.
 // Can do this only if there aren't additional conditions on final resultset.
 
 // Note: h.frecency is selected because we need it for ordering, but will
 // not be read later and we don't have an associated kAutoCompleteIndex_
   aQuery = NS_LITERAL_CSTRING(
       "SELECT h.url, h.title, f.url") + BOOK_TAG_SQL + NS_LITERAL_CSTRING(", "
-        "h.visit_count, h.frecency "
+        "h.visit_count, h.typed, h.frecency "
       "FROM moz_places_temp h "
       "LEFT OUTER JOIN moz_favicons f ON f.id = h.favicon_id "
       "WHERE h.frecency <> 0 "
       "{ADDITIONAL_CONDITIONS} "
       "UNION ALL "
       "SELECT * FROM ( "
         "SELECT h.url, h.title, f.url") + BOOK_TAG_SQL + NS_LITERAL_CSTRING(", "
-          "h.visit_count, h.frecency "
+          "h.visit_count, h.typed, h.frecency "
         "FROM moz_places h "
         "LEFT OUTER JOIN moz_favicons f ON f.id = h.favicon_id "
         "WHERE h.id NOT IN (SELECT id FROM moz_places_temp) "
         "AND h.frecency <> 0 "
         "{ADDITIONAL_CONDITIONS} "
         "ORDER BY h.frecency DESC LIMIT (?2 + ?3) "
       ") "
-      "ORDER BY 8 DESC LIMIT ?2 OFFSET ?3");
+      // ORDER BY h.frecency
+      "ORDER BY 9 DESC LIMIT ?2 OFFSET ?3");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsNavHistoryAutoComplete Helper Functions
 
 /**
  * Returns true if the string starts with javascript:
  */
@@ -466,31 +467,37 @@ nsNavHistory::GetDBFeedbackIncrease()
 //    a separate function so it can be re-created when the option changes.
 //    We are not lazy creating these queries because they will be most likely
 //    used on first search, and we don't want to lag on first autocomplete use.
 nsresult
 nsNavHistory::CreateAutoCompleteQueries()
 {
   nsCString AutoCompleteQuery;
   GetAutoCompleteBaseQuery(AutoCompleteQuery);
-  AutoCompleteQuery.ReplaceSubstring("{ADDITIONAL_CONDITIONS}",
-                                     (mAutoCompleteOnlyTyped ?
-                                        "AND h.typed = 1" : ""));
+  AutoCompleteQuery.ReplaceSubstring("{ADDITIONAL_CONDITIONS}", "");
   nsresult rv = mDBConn->CreateStatement(AutoCompleteQuery,
-                                getter_AddRefs(mDBAutoCompleteQuery));
+    getter_AddRefs(mDBAutoCompleteQuery));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCString AutoCompleteTypedQuery;
+  GetAutoCompleteBaseQuery(AutoCompleteTypedQuery);
+  AutoCompleteTypedQuery.ReplaceSubstring("{ADDITIONAL_CONDITIONS}",
+                                          "AND h.typed = 1");
+  rv = mDBConn->CreateStatement(AutoCompleteTypedQuery,
+    getter_AddRefs(mDBAutoCompleteTypedQuery));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // In this query we are taking BOOK_TAG_SQL only for h.id because it
   // uses data from moz_bookmarks table and we sync tables on bookmark insert.
   // So, most likely, h.id will always be populated when we have any bookmark.
   // We still need to join on moz_places_temp for other data (eg. title).
   nsCString sql = NS_LITERAL_CSTRING(
     "SELECT IFNULL(h_t.url, h.url), IFNULL(h_t.title, h.title), f.url ") +
       BOOK_TAG_SQL + NS_LITERAL_CSTRING(", "
-      "IFNULL(h_t.visit_count, h.visit_count), rank "
+      "IFNULL(h_t.visit_count, h.visit_count), IFNULL(h_t.typed, h.typed), rank "
     "FROM ( "
       "SELECT ROUND(MAX(((i.input = ?2) + (SUBSTR(i.input, 1, LENGTH(?2)) = ?2)) * "
         "i.use_count), 1) AS rank, place_id "
       "FROM moz_inputhistory i "
       "GROUP BY i.place_id HAVING rank > 0 "
       ") AS i "
     "LEFT JOIN moz_places h ON h.id = i.place_id "
     "LEFT JOIN moz_places_temp h_t ON h_t.id = i.place_id "
@@ -504,17 +511,18 @@ nsNavHistory::CreateAutoCompleteQueries(
     "SELECT IFNULL( "
         "(SELECT REPLACE(url, '%s', ?2) FROM moz_places_temp WHERE id = b.fk), "
         "(SELECT REPLACE(url, '%s', ?2) FROM moz_places WHERE id = b.fk) "
       ") AS search_url, IFNULL(h_t.title, h.title), "
       "COALESCE(f.url, "
         BEST_FAVICON_FOR_REVHOST("moz_places_temp") ", "
         BEST_FAVICON_FOR_REVHOST("moz_places")
       "), "
-      "b.parent, b.title, NULL, IFNULL(h_t.visit_count, h.visit_count) "
+      "b.parent, b.title, NULL, IFNULL(h_t.visit_count, h.visit_count), "
+      "IFNULL(h_t.typed, h.typed) "
     "FROM moz_keywords k "
     "JOIN moz_bookmarks b ON b.keyword_id = k.id "
     "LEFT JOIN moz_places AS h ON h.url = search_url "
     "LEFT JOIN moz_places_temp AS h_t ON h_t.url = search_url "
     "LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) "
     "WHERE LOWER(k.keyword) = LOWER(?1) "
     "ORDER BY IFNULL(h_t.frecency, h.frecency) DESC");
   rv = mDBConn->CreateStatement(sql, getter_AddRefs(mDBKeywordQuery));
@@ -728,17 +736,17 @@ nsNavHistory::StartSearch(const nsAStrin
           bindings += NS_LITERAL_CSTRING(",");
 
         // +2 to skip over the ?1 for the tag root parameter
         bindings += nsPrintfCString("?%d", i + 2);
       }
 
       nsCString sql = NS_LITERAL_CSTRING(
         "SELECT h.url, h.title, f.url") + BOOK_TAG_SQL + NS_LITERAL_CSTRING(", "
-          "h.visit_count "
+          "h.visit_count, h.typed "
         "FROM ( "
           "SELECT * FROM moz_places_temp "
           "WHERE url IN (") + bindings + NS_LITERAL_CSTRING(") "
           "UNION ALL "
           "SELECT * FROM moz_places "
           "WHERE id NOT IN (SELECT id FROM moz_places_temp) "
           "AND url IN (") + bindings + NS_LITERAL_CSTRING(") "
         ") AS h "
@@ -880,28 +888,31 @@ nsNavHistory::ProcessTokensForSpecialSea
     else if (token->Equals(mAutoCompleteRestrictBookmark))
       SET_BEHAVIOR(Bookmark);
     else if (token->Equals(mAutoCompleteRestrictTag))
       SET_BEHAVIOR(Tag);
     else if (token->Equals(mAutoCompleteMatchTitle))
       SET_BEHAVIOR(Title);
     else if (token->Equals(mAutoCompleteMatchUrl))
       SET_BEHAVIOR(Url);
+    else if (token->Equals(mAutoCompleteRestrictTyped))
+      SET_BEHAVIOR(Typed);
     else
       needToRemove = PR_FALSE;
 
     // Remove the token if it's special search token
     if (needToRemove)
       (void)mCurrentSearchTokens.RemoveStringAt(i);
   }
 
   // We can use optimized queries for restricts, so check for the most
   // restrictive query first
   mDBCurrentQuery = GET_BEHAVIOR(Tag) ? GetDBAutoCompleteTagsQuery() :
     GET_BEHAVIOR(Bookmark) ? GetDBAutoCompleteStarQuery() :
+    GET_BEHAVIOR(Typed) ? static_cast<mozIStorageStatement *>(mDBAutoCompleteTypedQuery) :
     GET_BEHAVIOR(History) ? GetDBAutoCompleteHistoryQuery() :
     static_cast<mozIStorageStatement *>(mDBAutoCompleteQuery);
 }
 
 nsresult
 nsNavHistory::AutoCompleteKeywordSearch()
 {
   mozStorageStatementScoper scope(mDBKeywordQuery);
@@ -1058,16 +1069,18 @@ nsNavHistory::AutoCompleteProcessSearch(
       }
 
       nsAutoString entryTags;
       rv = aQuery->GetString(kAutoCompleteIndex_Tags, entryTags);
       NS_ENSURE_SUCCESS(rv, rv);
       PRInt32 visitCount = 0;
       rv = aQuery->GetInt32(kAutoCompleteIndex_VisitCount, &visitCount);
       NS_ENSURE_SUCCESS(rv, rv);
+      PRInt32 typed = 0;
+      rv = aQuery->GetInt32(kAutoCompleteIndex_Typed, &typed);
 
       // Always prefer the bookmark title unless it's empty
       nsAutoString title =
         entryBookmarkTitle.IsEmpty() ? entryTitle : entryBookmarkTitle;
 
       nsString style;
       switch (aType) {
         case QUERY_KEYWORD: {
@@ -1086,16 +1099,17 @@ nsNavHistory::AutoCompleteProcessSearch(
           if (aHasMoreResults)
             *aHasMoreResults = PR_TRUE;
 
           // Keep track of if we've matched all the filter requirements such as
           // only history items, only bookmarks, only tags. If a given restrict
           // is active, make sure a corresponding condition is *not* true. If
           // any are violated, matchAll will be false.
           PRBool matchAll = !((GET_BEHAVIOR(History) && visitCount == 0) ||
+                              (GET_BEHAVIOR(Typed) && typed == 0) ||
                               (GET_BEHAVIOR(Bookmark) && !parentId) ||
                               (GET_BEHAVIOR(Tag) && entryTags.IsEmpty()));
 
           // Unescape the url to search for unescaped terms
           nsString entryURL = FixupURIText(escapedEntryURL);
 
           // Determine if every token matches either the bookmark title, tags,
           // page title, or page url
--- a/toolkit/components/places/tests/autocomplete/test_special_search.js
+++ b/toolkit/components/places/tests/autocomplete/test_special_search.js
@@ -77,16 +77,20 @@ addPageBook(9, 1, 1, [1]); // title
 addPageBook(10, 0, 0, [1]); // url
 addPageBook(11, 1, 1, [1]); // title and url
 
 // Remove pages from history to treat them as unvisited, so pages that do have
 // visits are 0,1,2,3,5,10
 for each (let uri in [4,6,7,8,9,11])
   histsvc.removePage(toURI(kURIs[uri]));
 
+// Set some pages as typed
+for each (let uri in [0,3,10])
+  histsvc.addVisit(toURI(kURIs[uri]), Date.now() * 1000, null, histsvc.TRANSITION_TYPED, false, 0);
+
 // Provide for each test: description; search terms; array of gPages indices of
 // pages that should match; optional function to be run before the test
 let gTests = [
   // Test restricting searches
   ["0: History restrict",
    "^", [0,1,2,3,5,10]],
   ["1: Star restrict",
    "*", [4,5,6,7,8,9,10,11]],
@@ -107,44 +111,58 @@ let gTests = [
   ["7: foo * -> is star",
    "foo *", [5,6,7,8,9,10,11]],
   ["8: foo # -> in title",
    "foo #", [1,3,5,7,8,9,10,11]],
   ["9: foo @ -> in url",
    "foo @", [2,3,6,7,10,11]],
   ["10: foo + -> is tag",
    "foo +", [8,9,10,11]],
+  ["10.1: foo ~ -> is typed",
+   "foo ~", [3,10]],
 
   // Test various pairs of special searches
   ["11: foo ^ * -> history, is star",
    "foo ^ *", [5,10]],
   ["12: foo ^ # -> history, in title",
    "foo ^ #", [1,3,5,10]],
   ["13: foo ^ @ -> history, in url",
    "foo ^ @", [2,3,10]],
   ["14: foo ^ + -> history, is tag",
    "foo ^ +", [10]],
+  ["14.1: foo ^ ~ -> history, is typed",
+   "foo ^ ~", [3,10]],
   ["15: foo * # -> is star, in title",
    "foo * #", [5,7,8,9,10,11]],
   ["16: foo * @ -> is star, in url",
    "foo * @", [6,7,10,11]],
   ["17: foo * + -> same as +",
    "foo * +", [8,9,10,11]],
+  ["17.1: foo * ~ -> is star, is typed",
+   "foo * ~", [10]],
   ["18: foo # @ -> in title, in url",
    "foo # @", [3,7,10,11]],
   ["19: foo # + -> in title, is tag",
    "foo # +", [8,9,10,11]],
+  ["19.1: foo # ~ -> in title, is typed",
+   "foo # ~", [3,10]],
   ["20: foo @ + -> in url, is tag",
    "foo @ +", [10,11]],
+  ["20.1: foo @ ~ -> in url, is typed",
+   "foo @ ~", [3,10]],
+  ["20.2: foo + ~ -> is tag, is typed",
+   "foo + ~", [10]],
 
   // Test default usage by setting certain bits of default.behavior to 1
   ["21: foo -> default history",
    "foo", [1,2,3,5,10], function() makeDefault(1)],
   ["22: foo -> default history, is star",
    "foo", [5,10], function() makeDefault(3)],
+  ["22.1: foo -> default history, is star, is typed",
+   "foo", [10], function() makeDefault(35)],
   ["23: foo -> default history, is star, in url",
    "foo", [10], function() makeDefault(19)],
 
   // Change the default to be less restrictive to make sure we find more
   ["24: foo -> default is star, in url",
    "foo", [6,7,10,11], function() makeDefault(18)],
   ["25: foo -> default in url",
    "foo", [2,3,6,7,10,11], function() makeDefault(16)],