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

This commit is contained in:
Marco Bonardo 2008-11-12 21:45:53 +01:00
Родитель 9a113df763
Коммит edfba4482d
6 изменённых файлов: 173 добавлений и 105 удалений

Просмотреть файл

@ -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) {}
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) {}
// 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();
importBookmarks = true;
}
} 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,45 +532,41 @@ BrowserGlue.prototype = {
this.ensurePlacesDefaultQueriesInitialized();
}
else {
// get latest backup
Cu.import("resource://gre/modules/utils.js");
var bookmarksFile = PlacesUtils.getMostRecentBackup();
// Create a new Organizer left pane folder root, the old will not be
// valid anymore.
this._prefs.setIntPref("browser.places.leftPaneFolderId", -1);
if (!restoreDefaultBookmarks &&
bookmarksFile && bookmarksFile.leafName.match("\.json$")) {
// restore a JSON backup
PlacesUtils.restoreBookmarksFromJSONFile(bookmarksFile);
// 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);
bookmarksFile.append("bookmarks.html");
}
else {
// if there's no JSON backup or we are restoring default bookmarks
// ensurePlacesDefaultQueriesInitialized() is called by import.
this._prefs.setIntPref("browser.places.smartBookmarksVersion", 0);
// import the file
try {
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
} catch (err) {
// Report the error, but ignore it.
Cu.reportError(err);
}
var dirService = Cc["@mozilla.org/file/directory_service;1"].
getService(Ci.nsIProperties);
var bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
if (restoreDefaultBookmarks || !bookmarksFile.exists()) {
// get bookmarks.html file from default profile folder
bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
bookmarksFile.append("bookmarks.html");
}
// import the file
try {
var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
getService(Ci.nsIPlacesImportExportService);
importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
} catch (err) {
// 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);
}
if (restoreDefaultBookmarks)
this._prefs.setBoolPref("browser.bookmarks.restore_default_bookmarks",
false);
}
// Initialize bookmark archiving on idle.

Просмотреть файл

@ -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

Просмотреть файл

@ -519,13 +519,14 @@ 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) {
PRUint16 databaseStatus = nsINavHistoryService::DATABASE_STATUS_OK;
rv = History()->GetDatabaseStatus(&databaseStatus);
NS_ENSURE_SUCCESS(rv, rv);
if (NS_FAILED(rv) ||
databaseStatus != nsINavHistoryService::DATABASE_STATUS_OK) {
rv = InitDefaults();
NS_ENSURE_SUCCESS(rv, rv);
rv = prefBranch->SetBoolPref("browser.places.importDefaults", PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
};
/**

Просмотреть файл

@ -90,6 +90,9 @@ function uri_in_db(aURI) {
// main
function run_test() {
// we have a new profile, so we should have imported bookmarks
do_check_eq(histsvc.databaseStatus, histsvc.DATABASE_STATUS_CREATE);
// add a visit
var testURI = uri("http://mozilla.com");
add_visit(testURI);