Bug 737841 - Part 3: remove no more useful redirectsMode query option.
authorMarco Bonardo <mbonardo@mozilla.com>
Sat, 07 Apr 2012 01:17:53 +0200
changeset 94519 b94616a8d514973c005d75a9692f00f024102725
parent 94518 52a1ab08417af171997678dcb4f29f31cf2c6999
child 94520 3be23dcd43e45a3e108aded097c0065a6b244698
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)
bugs737841
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 737841 - Part 3: remove no more useful redirectsMode query option. r=dietrich rs=gavin
browser/base/content/browser-places.js
browser/components/nsBrowserGlue.js
browser/components/places/tests/unit/head_bookmarks.js
browser/modules/NewTabUtils.jsm
browser/modules/WindowsJumpLists.jsm
netwerk/test/unit/test_URIs.js
services/sync/tests/unit/test_bookmark_smart_bookmarks.js
toolkit/components/places/PlacesDBUtils.jsm
toolkit/components/places/nsINavHistoryService.idl
toolkit/components/places/nsNavHistory.cpp
toolkit/components/places/nsNavHistoryQuery.cpp
toolkit/components/places/nsNavHistoryQuery.h
toolkit/components/places/tests/head_common.js
toolkit/components/places/tests/queries/head_queries.js
toolkit/components/places/tests/queries/test_querySerialization.js
toolkit/components/places/tests/queries/test_redirects.js
toolkit/components/places/tests/queries/test_redirectsMode.js
toolkit/components/places/tests/queries/xpcshell.ini
toolkit/components/places/tests/unit/test_preventive_maintenance.js
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -502,17 +502,17 @@ function HistoryMenu(aPopupShowingEvent)
   // views definitions, and we don't need them there.
   // Defining the prototype inheritance in the prototype itself would cause
   // browser.js to halt on "PlacesMenu is not defined" error.
   this.__proto__.__proto__ = PlacesMenu.prototype;
   XPCOMUtils.defineLazyServiceGetter(this, "_ss",
                                      "@mozilla.org/browser/sessionstore;1",
                                      "nsISessionStore");
   PlacesMenu.call(this, aPopupShowingEvent,
-                  "place:redirectsMode=2&sort=4&maxResults=15");
+                  "place:sort=4&maxResults=15");
 }
 
 HistoryMenu.prototype = {
   toggleRecentlyClosedTabs: function HM_toggleRecentlyClosedTabs() {
     // enable/disable the Recently Closed Tabs sub menu
     var undoMenu = this._rootElt.getElementsByClassName("recentlyClosedTabsMenu")[0];
 
     // no restorable tabs, so disable menu
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1347,17 +1347,17 @@ BrowserGlue.prototype = {
   ensurePlacesDefaultQueriesInitialized:
   function BG_ensurePlacesDefaultQueriesInitialized() {
     // This is actual version of the smart bookmarks, must be increased every
     // time smart bookmarks change.
     // When adding a new smart bookmark below, its newInVersion property must
     // be set to the version it has been added in, we will compare its value
     // to users' smartBookmarksVersion and add new smart bookmarks without
     // recreating old deleted ones.
-    const SMART_BOOKMARKS_VERSION = 3;
+    const SMART_BOOKMARKS_VERSION = 4;
     const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark";
     const SMART_BOOKMARKS_PREF = "browser.places.smartBookmarksVersion";
 
     // TODO bug 399268: should this be a pref?
     const MAX_RESULTS = 10;
 
     // Get current smart bookmarks version.  If not set, create them.
     let smartBookmarksCurrentVersion = 0;
@@ -1375,19 +1375,17 @@ BrowserGlue.prototype = {
       runBatched: function BG_EPDQI_runBatched() {
         let menuIndex = 0;
         let toolbarIndex = 0;
         let bundle = Services.strings.createBundle("chrome://browser/locale/places/places.properties");
 
         let smartBookmarks = {
           MostVisited: {
             title: bundle.GetStringFromName("mostVisitedTitle"),
-            uri: NetUtil.newURI("place:redirectsMode=" +
-                                Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET +
-                                "&sort=" +
+            uri: NetUtil.newURI("place:sort=" +
                                 Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                                 "&maxResults=" + MAX_RESULTS),
             parent: PlacesUtils.toolbarFolderId,
             position: toolbarIndex++,
             newInVersion: 1
           },
           RecentlyBookmarked: {
             title: bundle.GetStringFromName("recentlyBookmarkedTitle"),
--- a/browser/components/places/tests/unit/head_bookmarks.js
+++ b/browser/components/places/tests/unit/head_bookmarks.js
@@ -97,15 +97,15 @@ let (XULAppInfo = {
 
 
 const FILENAME_BOOKMARKS_HTML = "bookmarks.html";
 let (backup_date = new Date().toLocaleFormat("%Y-%m-%d")) {
   const FILENAME_BOOKMARKS_JSON = "bookmarks-" + backup_date + ".json";
 }
 
 // Smart bookmarks constants.
-const SMART_BOOKMARKS_VERSION = 3;
+const SMART_BOOKMARKS_VERSION = 4;
 const SMART_BOOKMARKS_ON_TOOLBAR = 1;
 const SMART_BOOKMARKS_ON_MENU = 3; // Takes in count the additional separator.
 
 // Default bookmarks constants.
 const DEFAULT_BOOKMARKS_ON_TOOLBAR = 1;
 const DEFAULT_BOOKMARKS_ON_MENU = 1;
--- a/browser/modules/NewTabUtils.jsm
+++ b/browser/modules/NewTabUtils.jsm
@@ -427,19 +427,16 @@ let PlacesProvider = {
    */
   getLinks: function PlacesProvider_getLinks(aCallback) {
     let options = PlacesUtils.history.getNewQueryOptions();
     options.maxResults = HISTORY_RESULTS_LIMIT;
 
     // Sort by frecency, descending.
     options.sortingMode = Ci.nsINavHistoryQueryOptions.SORT_BY_FRECENCY_DESCENDING
 
-    // We don't want source redirects for this query.
-    options.redirectsMode = Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET;
-
     let links = [];
 
     let callback = {
       handleResult: function (aResultSet) {
         let row;
 
         while (row = aResultSet.getNextRow()) {
           let url = row.getResultByIndex(1);
--- a/browser/modules/WindowsJumpLists.jsm
+++ b/browser/modules/WindowsJumpLists.jsm
@@ -472,18 +472,16 @@ var WinTaskbarJumpList =
    * Nav history helpers
    */
 
   _getHistoryResults:
   function WTBLJL__getHistoryResults(aSortingMode, aLimit, aCallback, aScope) {
     var options = PlacesUtils.history.getNewQueryOptions();
     options.maxResults = aLimit;
     options.sortingMode = aSortingMode;
-    // We don't want source redirects for these queries.
-    options.redirectsMode = Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET;
     var query = PlacesUtils.history.getNewQuery();
 
     // Return the pending statement to the caller, to allow cancelation.
     return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
                               .asyncExecuteLegacyQueries([query], 1, options, {
       handleResult: function (aResultSet) {
         for (let row; (row = aResultSet.getNextRow());) {
           try {
--- a/netwerk/test/unit/test_URIs.js
+++ b/netwerk/test/unit/test_URIs.js
@@ -224,20 +224,20 @@ var gTests = [
     ref:     "",
     nsIURL:  false, nsINestedURI: false },
   { spec:    "blob:123456",
     scheme:  "blob",
     prePath: "blob:",
     path:    "123456",
     ref:     "",
     nsIURL:  false, nsINestedURI: false, immutable: true },
-  { spec:    "place:redirectsMode=2&sort=8&maxResults=10",
+  { spec:    "place:sort=8&maxResults=10",
     scheme:  "place",
     prePath: "place:",
-    path:    "redirectsMode=2&sort=8&maxResults=10",
+    path:    "sort=8&maxResults=10",
     ref:     "",
     nsIURL:  false, nsINestedURI: false },
   { spec:    "resource://gre/",
     scheme:  "resource",
     prePath: "resource://gre",
     path:    "/",
     ref:     "",
     nsIURL:  true, nsINestedURI: false },
--- a/services/sync/tests/unit/test_bookmark_smart_bookmarks.js
+++ b/services/sync/tests/unit/test_bookmark_smart_bookmarks.js
@@ -68,19 +68,17 @@ add_test(function test_annotation_upload
     // This can happen in XULRunner.
     clearBookmarks();
     _("Start count is now " + startCount);
   }
 
   _("Create a smart bookmark in the toolbar.");
   let parent = PlacesUtils.toolbarFolderId;
   let uri =
-    Utils.makeURI("place:redirectsMode=" +
-                  Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET +
-                  "&sort=" +
+    Utils.makeURI("place:sort=" +
                   Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                   "&maxResults=10");
   let title = "Most Visited";
 
   let mostVisitedID = newSmartBookmark(parent, uri, -1, title, "MostVisited");
 
   _("New item ID: " + mostVisitedID);
   do_check_true(!!mostVisitedID);
@@ -175,19 +173,17 @@ add_test(function test_annotation_upload
   }
 });
 
 add_test(function test_smart_bookmarks_duped() {
   new SyncTestingInfrastructure();
 
   let parent = PlacesUtils.toolbarFolderId;
   let uri =
-    Utils.makeURI("place:redirectsMode=" +
-                  Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET +
-                  "&sort=" +
+    Utils.makeURI("place:sort=" +
                   Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING +
                   "&maxResults=10");
   let title = "Most Visited";
   let mostVisitedID = newSmartBookmark(parent, uri, -1, title, "MostVisited");
   let mostVisitedGUID = store.GUIDForId(mostVisitedID);
   
   let record = store.createRecord(mostVisitedGUID);
   
--- a/toolkit/components/places/PlacesDBUtils.jsm
+++ b/toolkit/components/places/PlacesDBUtils.jsm
@@ -706,16 +706,29 @@ let PlacesDBUtils = {
         "SELECT h.id FROM moz_places h " +
         "WHERE visit_count <> (SELECT count(*) FROM moz_historyvisits v " +
                               "WHERE v.place_id = h.id AND visit_type NOT IN (0,4,7,8)) " +
            "OR last_visit_date <> (SELECT MAX(visit_date) FROM moz_historyvisits v " +
                                   "WHERE v.place_id = h.id) " +
       ")");
     cleanupStatements.push(fixVisitStats);
 
+    // L.3 recalculate hidden for redirects.
+    let fixRedirectsHidden = DBConn.createAsyncStatement(
+      "UPDATE moz_places " +
+      "SET hidden = 1 " +
+      "WHERE id IN ( " +
+        "SELECT h.id FROM moz_places h " +
+        "JOIN moz_historyvisits src ON src.place_id = h.id " +
+        "JOIN moz_historyvisits dst ON dst.from_visit = src.id AND dst.visit_type IN (5,6) " +
+        "LEFT JOIN moz_bookmarks on fk = h.id AND fk ISNULL " +
+        "GROUP BY src.place_id HAVING count(*) = visit_count " +
+      ")");
+    cleanupStatements.push(fixRedirectsHidden);
+
     // MAINTENANCE STATEMENTS SHOULD GO ABOVE THIS POINT!
 
     return cleanupStatements;
   },
 
   /**
    * Tries to vacuum the database.
    *
--- a/toolkit/components/places/nsINavHistoryService.idl
+++ b/toolkit/components/places/nsINavHistoryService.idl
@@ -1035,17 +1035,17 @@ interface nsINavHistoryQuery : nsISuppor
    * Creates a new query item with the same parameters of this one.
    */
   nsINavHistoryQuery clone();
 };
 
 /**
  * This object represents the global options for executing a query.
  */
-[scriptable, uuid(d46a1ae7-aef8-47a2-9a5c-e6347253f9b2)]
+[scriptable, uuid(8198dfa7-8061-4766-95cb-fa86b3c00a47)]
 interface nsINavHistoryQueryOptions : nsISupports
 {
   /**
    * You can ask for the results to be pre-sorted. Since the DB has indices
    * of many items, it can produce sorted results almost for free. These should
    * be self-explanatory.
    *
    * Note: re-sorting is slower, as is sorting by title or when you have a
@@ -1196,48 +1196,24 @@ interface nsINavHistoryQueryOptions : ns
    *
    * Note that this has no effect on folder links, which are place: URIs
    * returned by nsINavBookmarkService.GetFolderURI. These are always expanded
    * and will appear as bookmark folders.
    */
   attribute boolean expandQueries;
 
   /**
-   * Most items in history are marked "hidden." Only toplevel pages that the
-   * user sees in the URL bar are not hidden. Hidden things include the content
-   * of iframes and all images on web pages. Normally, you don't want these
-   * things. If you do, set this flag and you'll get all items, even hidden
-   * ones. Does nothing for bookmark queries. Defaults to false.
+   * Some pages in history are marked "hidden" and thus don't appear by default
+   * in queries.  These include automatic framed visits and redirects.  Setting
+   * this attribute will return all pages, even hidden ones.  Does nothing for
+   * bookmark queries. Defaults to false.
    */
   attribute boolean includeHidden;
 
   /**
-   * Include both redirected-from and redirected-to pages into results.
-   */
-  const unsigned short REDIRECTS_MODE_ALL = 0;
-  /**
-   * Query results will not include redirected-to pages, but will include
-   * redirected-from pages.
-   */
-  const unsigned short REDIRECTS_MODE_SOURCE = 1;
-  /**
-   * Query results will not include redirected-from pages but will include
-   * redirected-to pages.
-   */
-  const unsigned short REDIRECTS_MODE_TARGET = 2;
-
-  /**
-   * Defines how redirects should be handled, see REDIRECTS_MODE_* constants
-   * above.
-   * Defaults to REDIRECTS_MODE_ALL.
-   * Note: this option is effective only on QUERY_TYPE_HISTORY.
-   */
-  attribute unsigned short redirectsMode;
-
-  /**
    * This is the maximum number of results that you want. The query is exeucted,
    * the results are sorted, and then the top 'maxResults' results are taken
    * and returned. Set to 0 (the default) to get all results.
    *
    * THIS DOES NOT WORK IN CONJUNCTION WITH SORTING BY TITLE. This is because
    * sorting by title requires us to sort after using locale-sensetive sorting
    * (as opposed to letting the database do it for us).
    *
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -1627,20 +1627,20 @@ nsNavHistory::ExecuteQueries(nsINavHisto
 
   NS_ADDREF(*_retval = result);
   return NS_OK;
 }
 
 // determine from our nsNavHistoryQuery array and nsNavHistoryQueryOptions
 // if this is the place query from the history menu.
 // from browser-menubar.inc, our history menu query is:
-// place:redirectsMode=2&sort=4&maxResults=10
+// place:sort=4&maxResults=10
 // note, any maxResult > 0 will still be considered a history menu query
-// or if this is the place query from the "Most Visited" item in the "Smart Bookmarks" folder:
-// place:redirectsMode=2&sort=8&maxResults=10
+// or if this is the place query from the "Most Visited" item in the
+// "Smart Bookmarks" folder: place:sort=8&maxResults=10
 // note, any maxResult > 0 will still be considered a Most Visited menu query
 static
 bool IsOptimizableHistoryQuery(const nsCOMArray<nsNavHistoryQuery>& aQueries,
                                  nsNavHistoryQueryOptions *aOptions,
                                  PRUint16 aSortMode)
 {
   if (aQueries.Count() != 1)
     return false;
@@ -1744,17 +1744,16 @@ private:
 
   const nsCString& mConditions;
   bool mUseLimit;
   bool mHasSearchTerms;
 
   PRUint16 mResultType;
   PRUint16 mQueryType;
   bool mIncludeHidden;
-  PRUint16 mRedirectsMode;
   PRUint16 mSortingMode;
   PRUint32 mMaxResults;
 
   nsCString mQueryString;
   nsCString mGroupBy;
   bool mHasDateColumns;
   bool mSkipOrderBy;
   nsNavHistory::StringHash& mAddParams;
@@ -1767,17 +1766,16 @@ PlacesSQLQueryBuilder::PlacesSQLQueryBui
     nsNavHistory::StringHash& aAddParams,
     bool aHasSearchTerms)
 : mConditions(aConditions)
 , mUseLimit(aUseLimit)
 , mHasSearchTerms(aHasSearchTerms)
 , mResultType(aOptions->ResultType())
 , mQueryType(aOptions->QueryType())
 , mIncludeHidden(aOptions->IncludeHidden())
-, mRedirectsMode(aOptions->RedirectsMode())
 , mSortingMode(aOptions->SortingMode())
 , mMaxResults(aOptions->MaxResults())
 , mSkipOrderBy(false)
 , mAddParams(aAddParams)
 {
   mHasDateColumns = (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_BOOKMARKS);
 }
 
@@ -2244,37 +2242,16 @@ PlacesSQLQueryBuilder::SelectAsTag()
 nsresult
 PlacesSQLQueryBuilder::Where()
 {
 
   // Set query options
   nsCAutoString additionalVisitsConditions;
   nsCAutoString additionalPlacesConditions;
 
-  if (mRedirectsMode == nsINavHistoryQueryOptions::REDIRECTS_MODE_SOURCE) {
-    // At least one visit that is not a redirect target should exist.
-    additionalVisitsConditions += NS_LITERAL_CSTRING(
-      "AND visit_type NOT IN ") +
-      nsPrintfCString("(%d,%d) ", nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
-                                  nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY);
-  }
-  else if (mRedirectsMode == nsINavHistoryQueryOptions::REDIRECTS_MODE_TARGET) {
-    // At least one visit that is not a redirect source should exist.
-    additionalPlacesConditions += nsPrintfCString(1024,
-      "AND EXISTS ( "
-        "SELECT id "
-        "FROM moz_historyvisits v "
-        "WHERE place_id = h.id "
-          "AND NOT EXISTS(SELECT id FROM moz_historyvisits "
-                         "WHERE from_visit = v.id AND visit_type IN (%d,%d)) "
-      ") ",
-      nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
-      nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY);
-  }
-
   if (!mIncludeHidden) {
     additionalPlacesConditions += NS_LITERAL_CSTRING("AND hidden = 0 ");
   }
 
   if (mQueryType == nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY) {
     // last_visit_date is updated for any kind of visit, so it's a good
     // indicator whether the page has visits.
     additionalPlacesConditions += NS_LITERAL_CSTRING(
@@ -2503,43 +2480,17 @@ nsNavHistory::ConstructQueryString(
       queryString.Append(NS_LITERAL_CSTRING("last_visit_date DESC "));
     else
       queryString.Append(NS_LITERAL_CSTRING("visit_count DESC "));
 
     queryString.Append(NS_LITERAL_CSTRING("LIMIT "));
     queryString.AppendInt(aOptions->MaxResults());
 
     nsCAutoString additionalQueryOptions;
-    if (aOptions->RedirectsMode() ==
-          nsINavHistoryQueryOptions::REDIRECTS_MODE_SOURCE) {
-      // At least one visit that is not a redirect target should exist.
-      additionalQueryOptions +=  nsPrintfCString(256,
-        "AND EXISTS ( "
-          "SELECT id "
-          "FROM moz_historyvisits "
-          "WHERE place_id = h.id "
-            "AND visit_type NOT IN (%d,%d)"
-        ") ",
-        TRANSITION_REDIRECT_PERMANENT,
-        TRANSITION_REDIRECT_TEMPORARY);
-    }
-    else if (aOptions->RedirectsMode() ==
-              nsINavHistoryQueryOptions::REDIRECTS_MODE_TARGET) {
-      // At least one visit that is not a redirect source should exist.
-      additionalQueryOptions += nsPrintfCString(1024,
-        "AND EXISTS ( "
-          "SELECT id "
-          "FROM moz_historyvisits v "
-          "WHERE place_id = h.id "
-            "AND NOT EXISTS(SELECT id FROM moz_historyvisits "
-                           "WHERE from_visit = v.id AND visit_type IN (%d,%d)) "
-        ") ",
-        TRANSITION_REDIRECT_PERMANENT,
-        TRANSITION_REDIRECT_TEMPORARY);
-    }
+
     queryString.ReplaceSubstring("{QUERY_OPTIONS}",
                                   additionalQueryOptions.get());
     return NS_OK;
   }
 
   nsCAutoString conditions;
   for (PRInt32 i = 0; i < aQueries.Count(); i++) {
     nsCString queryClause;
--- a/toolkit/components/places/nsNavHistoryQuery.cpp
+++ b/toolkit/components/places/nsNavHistoryQuery.cpp
@@ -166,17 +166,16 @@ static void SetOptionsKeyUint32(const ns
 #define QUERYKEY_SORTING_ANNOTATION "sortingAnnotation"
 #define QUERYKEY_RESULT_TYPE "type"
 #define QUERYKEY_EXCLUDE_ITEMS "excludeItems"
 #define QUERYKEY_EXCLUDE_QUERIES "excludeQueries"
 #define QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS "excludeReadOnlyFolders"
 #define QUERYKEY_EXPAND_QUERIES "expandQueries"
 #define QUERYKEY_FORCE_ORIGINAL_TITLE "originalTitle"
 #define QUERYKEY_INCLUDE_HIDDEN "includeHidden"
-#define QUERYKEY_REDIRECTS_MODE "redirectsMode"
 #define QUERYKEY_MAX_RESULTS "maxResults"
 #define QUERYKEY_QUERY_TYPE "queryType"
 #define QUERYKEY_TAG "tag"
 #define QUERYKEY_NOTTAGS "!tags"
 #define QUERYKEY_ASYNC_ENABLED "asyncEnabled"
 #define QUERYKEY_TRANSITION "transition"
 
 inline void AppendAmpersandIfNonempty(nsACString& aString)
@@ -589,23 +588,16 @@ nsNavHistory::QueriesToQueryString(nsINa
   }
 
   // include hidden
   if (options->IncludeHidden()) {
     AppendAmpersandIfNonempty(queryString);
     queryString += NS_LITERAL_CSTRING(QUERYKEY_INCLUDE_HIDDEN "=1");
   }
 
-  // redirects mode
-  if (options->RedirectsMode() !=  nsINavHistoryQueryOptions::REDIRECTS_MODE_ALL) {
-    AppendAmpersandIfNonempty(queryString);
-    queryString += NS_LITERAL_CSTRING(QUERYKEY_REDIRECTS_MODE "=");
-    AppendInt16(queryString, options->RedirectsMode());
-  }
-
   // max results
   if (options->MaxResults()) {
     AppendAmpersandIfNonempty(queryString);
     queryString += NS_LITERAL_CSTRING(QUERYKEY_MAX_RESULTS "=");
     AppendInt32(queryString, options->MaxResults());
   }
 
   // queryType
@@ -871,20 +863,16 @@ nsNavHistory::TokensToQueries(const nsTA
     // expand queries
     } else if (kvp.key.EqualsLiteral(QUERYKEY_EXPAND_QUERIES)) {
       SetOptionsKeyBool(kvp.value, aOptions,
                         &nsINavHistoryQueryOptions::SetExpandQueries);
     // include hidden
     } else if (kvp.key.EqualsLiteral(QUERYKEY_INCLUDE_HIDDEN)) {
       SetOptionsKeyBool(kvp.value, aOptions,
                         &nsINavHistoryQueryOptions::SetIncludeHidden);
-    // query type
-    } else if (kvp.key.EqualsLiteral(QUERYKEY_REDIRECTS_MODE)) {
-      SetOptionsKeyUint16(kvp.value, aOptions,
-                          &nsINavHistoryQueryOptions::SetRedirectsMode);
     // max results
     } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_RESULTS)) {
       SetOptionsKeyUint32(kvp.value, aOptions,
                           &nsINavHistoryQueryOptions::SetMaxResults);
     // query type
     } else if (kvp.key.EqualsLiteral(QUERYKEY_QUERY_TYPE)) {
       SetOptionsKeyUint16(kvp.value, aOptions,
                           &nsINavHistoryQueryOptions::SetQueryType);
@@ -1516,30 +1504,16 @@ nsNavHistoryQueryOptions::GetIncludeHidd
 }
 NS_IMETHODIMP
 nsNavHistoryQueryOptions::SetIncludeHidden(bool aIncludeHidden)
 {
   mIncludeHidden = aIncludeHidden;
   return NS_OK;
 }
 
-// redirectsMode
-NS_IMETHODIMP
-nsNavHistoryQueryOptions::GetRedirectsMode(PRUint16* _retval)
-{
-  *_retval = mRedirectsMode;
-  return NS_OK;
-}
-NS_IMETHODIMP
-nsNavHistoryQueryOptions::SetRedirectsMode(PRUint16 aRedirectsMode)
-{
-  mRedirectsMode = aRedirectsMode;
-  return NS_OK;
-}
-
 // maxResults
 NS_IMETHODIMP
 nsNavHistoryQueryOptions::GetMaxResults(PRUint32* aMaxResults)
 {
   *aMaxResults = mMaxResults;
   return NS_OK;
 }
 NS_IMETHODIMP
--- a/toolkit/components/places/nsNavHistoryQuery.h
+++ b/toolkit/components/places/nsNavHistoryQuery.h
@@ -136,17 +136,16 @@ public:
   nsNavHistoryQueryOptions()
   : mSort(0)
   , mResultType(0)
   , mExcludeItems(false)
   , mExcludeQueries(false)
   , mExcludeReadOnlyFolders(false)
   , mExpandQueries(true)
   , mIncludeHidden(false)
-  , mRedirectsMode(nsINavHistoryQueryOptions::REDIRECTS_MODE_ALL)
   , mMaxResults(0)
   , mQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY)
   , mAsyncEnabled(false)
   { }
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYQUERYOPTIONS_IID)
 
   NS_DECL_ISUPPORTS
@@ -154,17 +153,16 @@ public:
 
   PRUint16 SortingMode() const { return mSort; }
   PRUint16 ResultType() const { return mResultType; }
   bool ExcludeItems() const { return mExcludeItems; }
   bool ExcludeQueries() const { return mExcludeQueries; }
   bool ExcludeReadOnlyFolders() const { return mExcludeReadOnlyFolders; }
   bool ExpandQueries() const { return mExpandQueries; }
   bool IncludeHidden() const { return mIncludeHidden; }
-  PRUint16 RedirectsMode() const { return mRedirectsMode; }
   PRUint32 MaxResults() const { return mMaxResults; }
   PRUint16 QueryType() const { return mQueryType; }
   bool AsyncEnabled() const { return mAsyncEnabled; }
 
   nsresult Clone(nsNavHistoryQueryOptions **aResult);
 
 private:
   nsNavHistoryQueryOptions(const nsNavHistoryQueryOptions& other) {} // no copy
@@ -179,17 +177,16 @@ private:
   nsCString mSortingAnnotation;
   nsCString mParentAnnotationToExclude;
   PRUint16 mResultType;
   bool mExcludeItems;
   bool mExcludeQueries;
   bool mExcludeReadOnlyFolders;
   bool mExpandQueries;
   bool mIncludeHidden;
-  PRUint16 mRedirectsMode;
   PRUint32 mMaxResults;
   PRUint16 mQueryType;
   bool mAsyncEnabled;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryQueryOptions, NS_NAVHISTORYQUERYOPTIONS_IID)
 
 #endif // nsNavHistoryQuery_h_
--- a/toolkit/components/places/tests/head_common.js
+++ b/toolkit/components/places/tests/head_common.js
@@ -877,16 +877,17 @@ NavHistoryResultObserver.prototype = {
  * @param aPlaceInfo
  *        Can be an nsIURI, in such a case a single LINK visit will be added.
  *        Otherwise can be an object describing the visit to add, or an array
  *        of these objects:
  *          { uri: nsIURI of the page,
  *            transition: one of the TRANSITION_* from nsINavHistoryService,
  *            [optional] title: title of the page,
  *            [optional] visitDate: visit date in microseconds from the epoch
+ *            [optional] referrer: nsIURI of the referrer for this visit
  *          }
  * @param [optional] aCallback
  *        Function to be invoked on completion.
  * @param [optional] aStack
  *        The stack frame used to report errors.
  */
 function addVisits(aPlaceInfo, aCallback, aStack)
 {
@@ -905,17 +906,18 @@ function addVisits(aPlaceInfo, aCallback
   let now = Date.now();
   for (let i = 0; i < places.length; i++) {
     if (!places[i].title) {
       places[i].title = "test visit for " + places[i].uri.spec;
     }
     places[i].visits = [{
       transitionType: places[i].transition === undefined ? TRANSITION_LINK
                                                          : places[i].transition,
-      visitDate: places[i].visitDate || (now++) * 1000
+      visitDate: places[i].visitDate || (now++) * 1000,
+      referrerURI: places[i].referrer
     }];
   }
 
   PlacesUtils.asyncHistory.updatePlaces(
     places,
     {
       handleError: function AAV_handleError() {
         do_throw("Unexpected error in adding visit.", stack);
--- a/toolkit/components/places/tests/queries/head_queries.js
+++ b/toolkit/components/places/tests/queries/head_queries.js
@@ -102,16 +102,35 @@ function populateDB(aArray) {
                 print("Error while setting visit_count.");
               }
               finally {
                 stmt.finalize();
               }
             }
           }
 
+          if (qdata.isRedirect) {
+            // Redirect sources added through the docshell are properly marked
+            // as redirects and get hidden state, the API doesn't have that
+            // power (And actually doesn't make much sense to add redirects
+            // through the API).
+            let stmt = DBConn().createStatement(
+              "UPDATE moz_places SET hidden = 1 WHERE url = :url");
+            stmt.params.url = qdata.uri;
+            try {
+              stmt.execute();
+            }
+            catch (ex) {
+              print("Error while setting visit_count.");
+            }
+            finally {
+              stmt.finalize();
+            }
+          }
+
           if (qdata.isDetails) {
             // Then we add extraneous page details for testing
             PlacesUtils.history.addPageWithDetails(uri(qdata.uri),
                                                    qdata.title, qdata.lastVisit);
           }
 
           if (qdata.markPageAsTyped){
             PlacesUtils.bhistory.markPageAsTyped(uri(qdata.uri));
--- a/toolkit/components/places/tests/queries/test_querySerialization.js
+++ b/toolkit/components/places/tests/queries/test_querySerialization.js
@@ -500,33 +500,16 @@ const queryOptionSwitches = [
       function (aQuery, aQueryOptions) {
         aQueryOptions.queryType = aQueryOptions.QUERY_TYPE_HISTORY;
       },
       function (aQuery, aQueryOptions) {
         aQueryOptions.queryType = aQueryOptions.QUERY_TYPE_UNIFIED;
       }
     ]
   },
-  // redirectsMode
-  {
-    property: "redirectsMode",
-    desc:     "nsINavHistoryQueryOptions.redirectsMode",
-    matches:  simplePropertyMatches,
-    runs:     [
-      function (aQuery, aQueryOptions) {
-        aQueryOptions.redirectsMode = aQueryOptions.REDIRECTS_MODE_ALL;
-      },
-      function (aQuery, aQueryOptions) {
-        aQueryOptions.redirectsMode = aQueryOptions.REDIRECTS_MODE_TARGET;
-      },
-      function (aQuery, aQueryOptions) {
-        aQueryOptions.redirectsMode = aQueryOptions.REDIRECTS_MODE_SOURCE;
-      }
-    ]
-  },
 ];
 
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * Enumerates all the sequences of the cartesian product of the arrays contained
  * in aSequences.  Examples:
  *
rename from toolkit/components/places/tests/queries/test_redirectsMode.js
rename to toolkit/components/places/tests/queries/test_redirects.js
--- a/toolkit/components/places/tests/queries/test_redirectsMode.js
+++ b/toolkit/components/places/tests/queries/test_redirects.js
@@ -1,100 +1,54 @@
-/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et: */
-/* ***** 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 Places Test 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):
- *   Marco Bonardo <mak77@bonardo.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 ***** */
+/* 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/. */
 
 // Array of visits we will add to the database, will be populated later
 // in the test.
 let visits = [];
 
 /**
  * Takes a sequence of query options, and compare query results obtained through
  * them with a custom filtered array of visits, based on the values we are
  * expecting from the query.
  *
  * @param  aSequence
  *         an array that contains query options in the form:
- *         [includeHidden, redirectsMode, maxResults, sortingMode]
+ *         [includeHidden, maxResults, sortingMode]
  */
 function check_results_callback(aSequence) {
   // Sanity check: we should receive 3 parameters.
-  do_check_eq(aSequence.length, 4);
+  do_check_eq(aSequence.length, 3);
   let includeHidden = aSequence[0];
-  let redirectsMode = aSequence[1];
-  let maxResults = aSequence[2];
-  let sortingMode = aSequence[3];
+  let maxResults = aSequence[1];
+  let sortingMode = aSequence[2];
   print("\nTESTING: includeHidden(" + includeHidden + ")," +
-                  " redirectsMode(" + redirectsMode + ")," +
                   " maxResults("    + maxResults    + ")," +
                   " sortingMode("   + sortingMode   + ").");
 
+  function isHidden(aVisit) {
+    return aVisit.transType == Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK ||
+           aVisit.isRedirect;
+  }
+
   // Build expectedData array.
   let expectedData = visits.filter(function (aVisit, aIndex, aArray) {
     // Embed visits never appear in results.
     if (aVisit.transType == Ci.nsINavHistoryService.TRANSITION_EMBED)
       return false;
 
-    if (aVisit.transType == Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK &&
-      !includeHidden) {
+    if (!includeHidden && isHidden(aVisit)) {
       // If the page has any non-hidden visit, then it's visible.
       if (visits.filter(function (refVisit) {
-            return refVisit.uri == aVisit.uri &&
-                   refVisit.transType != Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK;
+        return refVisit.uri == aVisit.uri && !isHidden(refVisit);
           }).length == 0)
         return false;
     }
 
-    if (redirectsMode == Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_SOURCE) {
-      // Filter out any redirect target.
-      return aVisit.transType != Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT &&
-             aVisit.transType != Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY;
-    }
-
-    if (redirectsMode == Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET) {
-      // Filter out any entry that is a redirect source.
-      return visits.filter(function (refVisit) {
-        return !refVisit.isRedirect && refVisit.uri == aVisit.uri;
-      }).length > 0;
-    }
-
     return true;
   });
 
   // Remove duplicates, since queries are RESULTS_AS_URI (unique pages).
   let seen = [];
   expectedData = expectedData.filter(function (aData) {
     if (seen.indexOf(aData.uri) != -1)
       return false;
@@ -124,17 +78,16 @@ function check_results_callback(aSequenc
   if (maxResults) {
     expectedData = expectedData.slice(0, maxResults);
   }
 
   // Create a new query with required options.
   let query = PlacesUtils.history.getNewQuery();
   let options = PlacesUtils.history.getNewQueryOptions();
   options.includeHidden = includeHidden;
-  options.redirectsMode = redirectsMode;
   options.sortingMode = sortingMode;
   if (maxResults)
     options.maxResults = maxResults;
 
   // Compare resultset with expectedData.
   let result = PlacesUtils.history.executeQuery(query, options);
   let root = result.root;
   root.containerOpen = true;
@@ -251,16 +204,17 @@ function add_visits_to_database() {
   ];
 
   // we add a visit for each of the above transition types.
   t.forEach(function (transition) visits.push(
     { isVisit: true,
       transType: transition,
       uri: "http://" + transition + ".example.com/",
       title: transition + "-example",
+      isRedirect: true,
       lastVisit: timeInMicroseconds--,
       visitCount: (transition == Ci.nsINavHistoryService.TRANSITION_EMBED ||
                    transition == Ci.nsINavHistoryService.TRANSITION_FRAMED_LINK) ? 0 : visitCount++,
       isInQuery: true }));
 
   // Add a REDIRECT_TEMPORARY layer of visits for each of the above visits.
   t.forEach(function (transition) visits.push(
     { isVisit: true,
@@ -298,16 +252,17 @@ function add_visits_to_database() {
     return null;
   }
   t.forEach(function (transition) visits.push(
     { isVisit: true,
       transType: Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
       uri: "http://" + transition + ".example.com/",
       title: getLastValue("http://" + transition + ".example.com/", "title"),
       lastVisit: getLastValue("http://" + transition + ".example.com/", "lastVisit"),
+      isRedirect: true,
       referrer: "http://" + transition + ".redirect.perm.example.com/",
       visitCount: getLastValue("http://" + transition + ".example.com/", "visitCount"),
       isInQuery: true }));
 
   // Add an unvisited bookmark in the database, it should never appear.
   visits.push({ isBookmark: true,
     uri: "http://unvisited.bookmark.com/",
     parentFolder: PlacesUtils.bookmarksMenuFolderId,
@@ -329,24 +284,21 @@ function run_test() {
   // Frecency and hidden are updated asynchronously, wait for them.
   waitForAsyncUpdates(continue_test);
  }
 
  function continue_test() {
   // This array will be used by cartProd to generate a matrix of all possible
   // combinations.
   let includeHidden_options = [true, false];
-  let redirectsMode_options =  [Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_ALL,
-                                Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_SOURCE,
-                                Ci.nsINavHistoryQueryOptions.REDIRECTS_MODE_TARGET];
   let maxResults_options = [5, 10, 20, null];
   // These sortingMode are choosen to toggle using special queries for history
   // menu and most visited smart bookmark.
   let sorting_options = [Ci.nsINavHistoryQueryOptions.SORT_BY_NONE,
                          Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING,
                          Ci.nsINavHistoryQueryOptions.SORT_BY_DATE_DESCENDING];
   // Will execute check_results_callback() for each generated combination.
-  cartProd([includeHidden_options, redirectsMode_options, maxResults_options, sorting_options],
+  cartProd([includeHidden_options, maxResults_options, sorting_options],
            check_results_callback);
 
   remove_all_bookmarks();
   waitForClearHistory(do_test_finished);
 }
--- a/toolkit/components/places/tests/queries/xpcshell.ini
+++ b/toolkit/components/places/tests/queries/xpcshell.ini
@@ -7,17 +7,17 @@ tail =
 [test_abstime-annotation-uri.js]
 [test_async.js]
 [test_containersQueries_sorting.js]
 [test_excludeReadOnlyFolders.js]
 [test_history_queries_tags_liveUpdate.js]
 [test_history_queries_titles_liveUpdate.js]
 [test_onlyBookmarked.js]
 [test_querySerialization.js]
-[test_redirectsMode.js]
+[test_redirects.js]
 # Bug 676989: test hangs consistently on Android
 skip-if = os == "android"
 [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]
--- a/toolkit/components/places/tests/unit/test_preventive_maintenance.js
+++ b/toolkit/components/places/tests/unit/test_preventive_maintenance.js
@@ -1141,16 +1141,64 @@ tests.push({
     do_check_false(stmt.executeStep());
     stmt.finalize();
   }
 });
 
 //------------------------------------------------------------------------------
 
 tests.push({
+  name: "L.3",
+  desc: "recalculate hidden for redirects.",
+
+  setup: function() {
+    addVisits([
+      { uri: NetUtil.newURI("http://l3.moz.org/"),
+        transition: TRANSITION_TYPED },
+      { uri: NetUtil.newURI("http://l3.moz.org/redirecting/"),
+        transition: TRANSITION_TYPED },
+      { uri: NetUtil.newURI("http://l3.moz.org/redirecting2/"),
+        transition: TRANSITION_REDIRECT_TEMPORARY,
+        referrer: NetUtil.newURI("http://l3.moz.org/redirecting/") },
+      { uri: NetUtil.newURI("http://l3.moz.org/target/"),
+        transition: TRANSITION_REDIRECT_PERMANENT,
+        referrer: NetUtil.newURI("http://l3.moz.org/redirecting2/") },
+    ]);
+  },
+
+  asyncCheck: function(aCallback) {
+    let stmt = mDBConn.createAsyncStatement(
+      "SELECT h.url FROM moz_places h WHERE h.hidden = 1"
+    );
+    stmt.executeAsync({
+      _count: 0,
+      handleResult: function(aResultSet) {
+        for (let row; (row = aResultSet.getNextRow());) {
+          let url = row.getResultByIndex(0);
+          do_check_true(/redirecting/.test(url));
+          this._count++;
+        }
+      },
+      handleError: function(aError) {
+      },
+      handleCompletion: function(aReason) {
+        dump_table("moz_places");
+        dump_table("moz_historyvisits");
+        do_check_eq(aReason, Ci.mozIStorageStatementCallback.REASON_FINISHED);
+        do_check_eq(this._count, 2);
+        aCallback();
+      }
+    });
+    stmt.finalize();
+  }
+});
+
+//------------------------------------------------------------------------------
+
+tests.push({
   name: "Z",
   desc: "Sanity: Preventive maintenance does not touch valid items",
 
   _uri1: uri("http://www1.mozilla.org"),
   _uri2: uri("http://www2.mozilla.org"),
   _folderId: null,
   _bookmarkId: null,
   _separatorId: null,