Commit db938e81 authored by Marco Bonardo's avatar Marco Bonardo
Browse files

Bug 462366 - correct bogus importBookmarksHTML behaviour, r=dietrich a=beltzner

parent e2b6cb71
Loading
Loading
Loading
Loading
+87 −61
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#   Giorgio Maone <g.maone@informaction.com>
#   Seth Spitzer <sspitzer@mozilla.com>
#   Asaf Romano <mano@mozilla.com>
#   Marco Bonardo <mak77@bonardo.net>
#
# 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
@@ -127,6 +128,9 @@ BrowserGlue.prototype = {
        subject.QueryInterface(Ci.nsISupportsPRBool);
        subject.data = true;
        break;
      case "places-init-complete":
        this._initPlaces();
        break;
      case "idle":
        if (this.idleService.idleTime > BOOKMARKS_ARCHIVE_IDLE_TIME * 1000) {
          // Back up bookmarks.
@@ -151,6 +155,7 @@ BrowserGlue.prototype = {
    osvr.addObserver(this, "quit-application-requested", false);
    osvr.addObserver(this, "quit-application-granted", false);
    osvr.addObserver(this, "session-save", false);
    osvr.addObserver(this, "places-init-complete", false);
  },

  // cleanup (called on application shutdown)
@@ -168,6 +173,7 @@ BrowserGlue.prototype = {
    osvr.removeObserver(this, "quit-application-requested");
    osvr.removeObserver(this, "quit-application-granted");
    osvr.removeObserver(this, "session-save");
    osvr.removeObserver(this, "places-init-complete");
  },

  _onAppDefaults: function()
@@ -192,9 +198,6 @@ BrowserGlue.prototype = {
                    "_blank", "chrome,centerscreen,modal,resizable=no", null);
    }

    // initialize Places
    this._initPlaces();

    // apply distribution customizations
    // prefs are applied in _onAppDefaults()
    var distro = new DistributionCustomizer();
@@ -426,7 +429,7 @@ BrowserGlue.prototype = {
                    }
                  ];

    // Set pref to indicate we've shown the notficiation.
    // Set pref to indicate we've shown the notification.
    var currentVersion = this._prefs.getIntPref("browser.rights.version");
    this._prefs.setBoolPref("browser.rights." + currentVersion + ".shown", true);

@@ -454,46 +457,73 @@ BrowserGlue.prototype = {

  /**
   * Initialize Places
   * - imports the bookmarks html file if bookmarks datastore is empty
   * - imports the bookmarks html file if bookmarks database is empty, try to
   *   restore bookmarks from a JSON backup if the backend indicates that the
   *   database was corrupt.
   *
   * These prefs can be set up by the frontend:
   *
   * WARNING: setting these preferences to true will overwite existing bookmarks
   *
   * These prefs are set by the backend services upon creation (or recreation)
   * of the Places db:
   * - browser.places.importBookmarksHTML
   *   Set to false by the history service to indicate we need to re-import.
   *   Set to true will import the bookmarks.html file from the profile folder.
   * - browser.places.smartBookmarksVersion
   *   Set during HTML import to indicate that Smart Bookmarks were created.
   *   Set to -1 to disable Smart Bookmarks creation.
   *   Set to 0 to restore current Smart Bookmarks.
   *
   * These prefs are set up by the frontend:
   * - browser.bookmarks.restore_default_bookmarks
   *   Set to true by safe-mode dialog to indicate we must restore default
   *   bookmarks.
   */
  _initPlaces: function bg__initPlaces() {
    // we need to instantiate the history service before checking
    // the browser.places.importBookmarksHTML pref, as
    // nsNavHistory::ForceMigrateBookmarksDB() will set that pref
    // if we need to force a migration (due to a schema change)
    // We must instantiate the history service since it will tell us if we
    // need to import or restore bookmarks due to first-run, corruption or
    // forced migration (due to a major schema change).
    var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
                  getService(Ci.nsINavHistoryService);
    var databaseStatus = histsvc.databaseStatus;

    var importBookmarks = false;
    var restoreDefaultBookmarks = false;
    // If the database is corrupt or has been newly created we should
    // import bookmarks.
    var importBookmarks = databaseStatus != histsvc.DATABASE_STATUS_OK;

    // Check if user or an extension has required to import bookmarks.html
    var importBookmarksHTML = false;
    try {
      restoreDefaultBookmarks = this._prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
      importBookmarksHTML =
        this._prefs.getBoolPref("browser.places.importBookmarksHTML");
      if (importBookmarksHTML)
        importBookmarks = true;
    } catch(ex) {}

    // Check if Safe Mode or the user has required to restore bookmarks from
    // default profile's bookmarks.html
    var restoreDefaultBookmarks = false;
    try {
      restoreDefaultBookmarks =
        this._prefs.getBoolPref("browser.bookmarks.restore_default_bookmarks");
      if (restoreDefaultBookmarks) {
        // Ensure that we already have a bookmarks backup for today
        this._archiveBookmarks();
      // we will restore bookmarks from html
        importBookmarks = true;
      }
    else {
      try {
        importBookmarks = this._prefs.getBoolPref("browser.places.importBookmarksHTML");
    } catch(ex) {}

    // If the user did not require to restore default bookmarks, or import
    // from bookmarks.html, we will try to restore from JSON
    if (importBookmarks && !restoreDefaultBookmarks && !importBookmarksHTML) {
      // get latest JSON backup
      Cu.import("resource://gre/modules/utils.js");
      var bookmarksFile = PlacesUtils.getMostRecentBackup();
      if (bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
        // restore from JSON backup
        PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
        importBookmarks = false;
      }
      else {
        // No backup was available we will try to import from bookmarks.html
        importBookmarks = true;
      }
    }

    if (!importBookmarks) {
@@ -502,25 +532,19 @@ BrowserGlue.prototype = {
      this.ensurePlacesDefaultQueriesInitialized();
    }
    else {
      // get latest backup
      Cu.import("resource://gre/modules/utils.js");
      var bookmarksFile = PlacesUtils.getMostRecentBackup();

      if (!restoreDefaultBookmarks &&
          bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
        // restore a JSON backup
        PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
      }
      else {
        // if there's no JSON backup or we are restoring default bookmarks
      // Create a new Organizer left pane folder root, the old will not be
      // valid anymore.
      this._prefs.setIntPref("browser.places.leftPaneFolderId", -1);

      // ensurePlacesDefaultQueriesInitialized() is called by import.
      this._prefs.setIntPref("browser.places.smartBookmarksVersion", 0);

      // Get bookmarks folder
      var dirService = Cc["@mozilla.org/file/directory_service;1"].
                       getService(Ci.nsIProperties);

      var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);

      // User wants to restore default bookmarks
      if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
        // get bookmarks.html file from default profile folder
        bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
@@ -536,12 +560,14 @@ BrowserGlue.prototype = {
        // Report the error, but ignore it.
        Cu.reportError(err);
      }

      // Reset preferences, so we won't try to import again at next run
      if (importBookmarksHTML)
        this._prefs.setBoolPref("browser.places.importBookmarksHTML", false);
      if (restoreDefaultBookmarks)
        this._prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
                                false);
    }
    }

    // Initialize bookmark archiving on idle.
    // Once a day, either on idle or shutdown, bookmarks are backed up.
+21 −1
Original line number Diff line number Diff line
@@ -1057,7 +1057,7 @@ interface nsINavHistoryQueryOptions : nsISupports
  nsINavHistoryQueryOptions clone();
};

[scriptable, uuid(8b258ff6-b591-4da5-8b7c-0665b27d09cc)]
[scriptable, uuid(437f539b-d541-4a0f-a200-6f9a6d45cce2)]
interface nsINavHistoryService : nsISupports
{
  /**
@@ -1103,6 +1103,26 @@ interface nsINavHistoryService : nsISupports
   */
  const unsigned long TRANSITION_DOWNLOAD = 7;

  /**
   * Set when database is coherent
   */
  const unsigned short DATABASE_STATUS_OK = 0;

  /**
   * Set when database did not exist and we created a new one
   */
  const unsigned short DATABASE_STATUS_CREATE = 1;

  /**
   * Set when database was corrupt and we replaced it
   */
  const unsigned short DATABASE_STATUS_CORRUPT = 2;

  /**
   * Returns the current database status
   */
  readonly attribute unsigned short databaseStatus;

  /**
   * True if there is any history. This can be used in UI to determine whether
   * the "clear history" button should be enabled or not. This is much better
+6 −5
Original line number Diff line number Diff line
@@ -519,12 +519,13 @@ nsNavBookmarks::InitRoots()
  rv = prefService->GetBranch("", getter_AddRefs(prefBranch));
  NS_ENSURE_SUCCESS(rv, rv);

  PRBool importDefaults = PR_TRUE;
  rv = prefBranch->GetBoolPref("browser.places.importDefaults", &importDefaults);
  if (NS_FAILED(rv) || importDefaults) {
    rv = InitDefaults();
  PRUint16 databaseStatus = nsINavHistoryService::DATABASE_STATUS_OK;
  rv = History()->GetDatabaseStatus(&databaseStatus);
  NS_ENSURE_SUCCESS(rv, rv);
    rv = prefBranch->SetBoolPref("browser.places.importDefaults", PR_FALSE);

  if (NS_FAILED(rv) ||
      databaseStatus != nsINavHistoryService::DATABASE_STATUS_OK) {
    rv = InitDefaults();
    NS_ENSURE_SUCCESS(rv, rv);
  }

+52 −38
Original line number Diff line number Diff line
@@ -155,10 +155,6 @@
#define PREF_FRECENCY_DEFAULT_VISIT_BONUS       "places.frecency.defaultVisitBonus"
#define PREF_FRECENCY_UNVISITED_BOOKMARK_BONUS  "places.frecency.unvisitedBookmarkBonus"
#define PREF_FRECENCY_UNVISITED_TYPED_BONUS     "places.frecency.unvisitedTypedBonus"
#define PREF_BROWSER_IMPORT_BOOKMARKS           "browser.places.importBookmarksHTML"
#define PREF_BROWSER_IMPORT_DEFAULTS            "browser.places.importDefaults"
#define PREF_BROWSER_SMARTBOOKMARKSVERSION      "browser.places.smartBookmarksVersion"
#define PREF_BROWSER_LEFTPANEFOLDERID           "browser.places.leftPaneFolderId"

// Default (integer) value of PREF_DB_CACHE_PERCENTAGE from 0-100
// This is 6% of machine memory, giving 15MB for a user with 256MB of memory.
@@ -286,6 +282,23 @@ protected:
  nsNavHistory& mNavHistory;
};

class PlacesInitCompleteEvent : public nsRunnable {
  public:
  NS_IMETHOD Run() {
    nsresult rv;
    nsCOMPtr<nsIObserverService> observerService =
      do_GetService("@mozilla.org/observer-service;1", &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = observerService->NotifyObservers(nsnull,
                                          PLACES_INIT_COMPLETE_EVENT_TOPIC,
                                          nsnull);
    NS_ENSURE_SUCCESS(rv, rv);

    return NS_OK;
  }
};

// if adding a new one, be sure to update nsNavBookmarks statements and
// its kGetChildrenIndex_* constants
const PRInt32 nsNavHistory::kGetInfoIndex_PageID = 0;
@@ -372,7 +385,8 @@ nsNavHistory::nsNavHistory() : mBatchLevel(0),
                               mExpireSites(0),
                               mNumVisitsForFrecency(10),
                               mTagsFolder(-1),
                               mInPrivateBrowsing(PRIVATEBROWSING_NOTINITED)
                               mInPrivateBrowsing(PRIVATEBROWSING_NOTINITED),
                               mDatabaseStatus(DATABASE_STATUS_OK)
{
#ifdef LAZY_ADD
  mLazyTimerSet = PR_TRUE;
@@ -427,6 +441,13 @@ nsNavHistory::Init()
  }
  NS_ENSURE_SUCCESS(rv, rv);

  // Notify we have finished database initialization
  // Enqueue the notification, so if we init another service that requires
  // nsNavHistoryService we don't recursive try to get it.
  nsCOMPtr<PlacesInitCompleteEvent> completeEvent = new PlacesInitCompleteEvent();
  rv = NS_DispatchToMainThread(completeEvent);
  NS_ENSURE_SUCCESS(rv, rv);

#ifdef MOZ_XUL
  rv = InitAutoComplete();
  NS_ENSURE_SUCCESS(rv, rv);
@@ -551,7 +572,6 @@ nsNavHistory::InitDBFile(PRBool aForceInit)
  NS_ENSURE_SUCCESS(rv, rv);

  // if forcing, backup and remove the old file
  PRBool dbExists;
  if (aForceInit) {
    // backup the database
    nsCOMPtr<nsIFile> backup;
@@ -566,12 +586,19 @@ nsNavHistory::InitDBFile(PRBool aForceInit)
    // and remove the file
    rv = mDBFile->Remove(PR_FALSE);
    NS_ENSURE_SUCCESS(rv, rv);
    dbExists = PR_FALSE;

    // If aForceInit is true we were unable to initialize or upgrade the current
    // database, so it was corrupt.
    mDatabaseStatus = DATABASE_STATUS_CORRUPT;
  }
  else {
    // file exists?
    PRBool dbExists = PR_TRUE;
    rv = mDBFile->Exists(&dbExists);
    NS_ENSURE_SUCCESS(rv, rv);
    // If the database didn't previously exist, we create it.
    if (!dbExists)
      mDatabaseStatus = DATABASE_STATUS_CREATE;
  }

  // open the database
@@ -579,7 +606,8 @@ nsNavHistory::InitDBFile(PRBool aForceInit)
  NS_ENSURE_SUCCESS(rv, rv);
  rv = mDBService->OpenUnsharedDatabase(mDBFile, getter_AddRefs(mDBConn));
  if (rv == NS_ERROR_FILE_CORRUPTED) {
    dbExists = PR_FALSE;
    // The database is corrupt, we create a new one.
    mDatabaseStatus = DATABASE_STATUS_CORRUPT;

    // backup file
    nsCOMPtr<nsIFile> backup;
@@ -600,33 +628,12 @@ nsNavHistory::InitDBFile(PRBool aForceInit)
  }
  NS_ENSURE_SUCCESS(rv, rv);

  // if the db didn't previously exist, or was corrupted, re-import bookmarks.
  if (!dbExists) {
    nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
    if (prefs) {
      rv = prefs->SetBoolPref(PREF_BROWSER_IMPORT_BOOKMARKS, PR_TRUE);
      NS_ENSURE_SUCCESS(rv, rv);

      rv = prefs->SetBoolPref(PREF_BROWSER_IMPORT_DEFAULTS, PR_TRUE);
      NS_ENSURE_SUCCESS(rv, rv);  

      // if the places.sqlite gets deleted/corrupted the queries should be created again
      rv = prefs->SetIntPref(PREF_BROWSER_SMARTBOOKMARKSVERSION, 0);
      NS_ENSURE_SUCCESS(rv, rv);  
      
      // we must create a new Organizer left pane folder root, the old will not be valid anymore
      rv = prefs->SetIntPref(PREF_BROWSER_LEFTPANEFOLDERID, -1);
      NS_ENSURE_SUCCESS(rv, rv); 
    }
  }

  return NS_OK;
}

// nsNavHistory::InitDB
//


#define PLACES_SCHEMA_VERSION 8

nsresult
@@ -900,6 +907,13 @@ nsNavHistory::InitializeIdleTimer()
  return NS_OK;
}

NS_IMETHODIMP
nsNavHistory::GetDatabaseStatus(PRUint16 *aDatabaseStatus)
{
  *aDatabaseStatus = mDatabaseStatus;
  return NS_OK;
}

// nsNavHistory::UpdateSchemaVersion
//
// Called by the individual services' InitTables()
@@ -1332,12 +1346,12 @@ nsNavHistory::ForceMigrateBookmarksDB(mozIStorageConnection* aDBConn)
  rv = nsNavBookmarks::InitTables(aDBConn);
  NS_ENSURE_SUCCESS(rv, rv);

  // set pref indicating bookmarks.html should be imported.
  nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
  if (prefs) {
    prefs->SetBoolPref(PREF_BROWSER_IMPORT_BOOKMARKS, PR_TRUE);
  }
  return rv;
  // We have done a new database init, so we mark this as if the database has
  // been created now, so the frontend can distinguish this status and import
  // if needed.
  mDatabaseStatus = DATABASE_STATUS_CREATE;

  return NS_OK;
}

// nsNavHistory::MigrateV3Up
+4 −0
Original line number Diff line number Diff line
@@ -121,6 +121,8 @@
// mInPrivateBrowsing member
#define PRIVATEBROWSING_NOTINITED (PRBool(0xffffffff))

#define PLACES_INIT_COMPLETE_EVENT_TOPIC "places-init-complete"

struct AutoCompleteIntermediateResult;
class AutoCompleteResultComparator;
class mozIAnnotationService;
@@ -835,6 +837,8 @@ protected:
  PRInt64 mTagsFolder;

  PRBool mInPrivateBrowsing;

  PRBool mDatabaseStatus;
};

/**
Loading