From 396bdf1f019a5d412ca161f96f58950b5e4b2cae Mon Sep 17 00:00:00 2001 From: "mak77@bonardo.net" Date: Thu, 13 Nov 2008 22:45:49 -0800 Subject: [PATCH] Bug 463471 - temp tables are not correctly synced to disk when the user clear private data on shutdown (r=sdwilsh, r=dietrich) --- .../places/public/nsPIPlacesDatabase.idl | 15 ++- .../places/src/nsAnnotationService.cpp | 28 ++++++ .../places/src/nsAnnotationService.h | 5 + .../places/src/nsFaviconService.cpp | 18 ++++ .../components/places/src/nsFaviconService.h | 7 +- .../components/places/src/nsNavBookmarks.cpp | 29 ++++++ .../components/places/src/nsNavBookmarks.h | 5 + .../components/places/src/nsNavHistory.cpp | 95 +++++++++++++++++++ toolkit/components/places/src/nsNavHistory.h | 29 +++--- .../places/src/nsNavHistoryExpire.cpp | 18 ++-- .../places/src/nsNavHistoryResult.cpp | 5 +- .../components/places/src/nsPlacesDBFlush.js | 21 +++- .../components/places/tests/sync/head_sync.js | 37 ++++++-- ...nsPIPlacesDatabase_commitPendingChanges.js | 75 +++++++++++++++ ...acesDatabase_finalizeInternalStatements.js | 49 ++++++++++ 15 files changed, 403 insertions(+), 33 deletions(-) create mode 100644 toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_commitPendingChanges.js create mode 100644 toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_finalizeInternalStatements.js diff --git a/toolkit/components/places/public/nsPIPlacesDatabase.idl b/toolkit/components/places/public/nsPIPlacesDatabase.idl index d36cc1e23a0..1d5fe54478d 100644 --- a/toolkit/components/places/public/nsPIPlacesDatabase.idl +++ b/toolkit/components/places/public/nsPIPlacesDatabase.idl @@ -46,11 +46,24 @@ interface mozIStorageConnection; * database. If outside consumers wish to use this, they should only read from * the database so they do not break any internal invariants. */ -[scriptable, uuid(daa7d3ba-8e24-4228-93b5-2c188bad7d36)] +[scriptable, uuid(8e6d4f8a-4b8e-4026-9fca-517c4494ddb7)] interface nsPIPlacesDatabase : nsISupports { /** * The database connection used by Places. */ readonly attribute mozIStorageConnection DBConnection; + + /** + * Finalizes all Places internal statements, allowing to safely close the + * database connection. + */ + void finalizeInternalStatements(); + + /** + * Commits all pending history changes, call this before finalizing + * statements and closing the database connection to ensure safety for all + * history data. + */ + void commitPendingChanges(); }; diff --git a/toolkit/components/places/src/nsAnnotationService.cpp b/toolkit/components/places/src/nsAnnotationService.cpp index 140b578deec..4ecaa9d96e9 100644 --- a/toolkit/components/places/src/nsAnnotationService.cpp +++ b/toolkit/components/places/src/nsAnnotationService.cpp @@ -2007,3 +2007,31 @@ nsAnnotationService::CallSetForItemObservers(PRInt64 aItemId, const nsACString& for (PRInt32 i = 0; i < mObservers.Count(); i ++) mObservers[i]->OnItemAnnotationSet(aItemId, aName); } + +nsresult +nsAnnotationService::FinalizeStatements() { + mozIStorageStatement* stmts[] = { + mDBSetAnnotation, + mDBSetItemAnnotation, + mDBGetAnnotation, + mDBGetItemAnnotation, + mDBGetAnnotationNames, + mDBGetItemAnnotationNames, + mDBGetAnnotationFromURI, + mDBGetAnnotationFromItemId, + mDBGetAnnotationNameID, + mDBAddAnnotationName, + mDBAddAnnotation, + mDBAddItemAnnotation, + mDBRemoveAnnotation, + mDBRemoveItemAnnotation, + mDBGetItemsWithAnnotation + }; + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) { + nsresult rv = nsNavHistory::FinalizeStatement(stmts[i]); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} diff --git a/toolkit/components/places/src/nsAnnotationService.h b/toolkit/components/places/src/nsAnnotationService.h index 9eb8852999d..49187b8b64d 100644 --- a/toolkit/components/places/src/nsAnnotationService.h +++ b/toolkit/components/places/src/nsAnnotationService.h @@ -78,6 +78,11 @@ public: return gAnnotationService; } + /** + * Finalize all internal statements. + */ + nsresult FinalizeStatements(); + NS_DECL_ISUPPORTS NS_DECL_NSIANNOTATIONSERVICE diff --git a/toolkit/components/places/src/nsFaviconService.cpp b/toolkit/components/places/src/nsFaviconService.cpp index 60e8afbd081..2e3e8512902 100644 --- a/toolkit/components/places/src/nsFaviconService.cpp +++ b/toolkit/components/places/src/nsFaviconService.cpp @@ -1011,6 +1011,24 @@ nsFaviconService::OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen, return NS_OK; } +nsresult +nsFaviconService::FinalizeStatements() { + mozIStorageStatement* stmts[] = { + mDBGetURL, + mDBGetData, + mDBGetIconInfo, + mDBInsertIcon, + mDBUpdateIcon, + mDBSetPageFavicon + }; + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) { + nsresult rv = nsNavHistory::FinalizeStatement(stmts[i]); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} NS_IMPL_ISUPPORTS4(FaviconLoadListener, nsIRequestObserver, diff --git a/toolkit/components/places/src/nsFaviconService.h b/toolkit/components/places/src/nsFaviconService.h index 3e781c1f635..baae9ff7fcc 100644 --- a/toolkit/components/places/src/nsFaviconService.h +++ b/toolkit/components/places/src/nsFaviconService.h @@ -90,10 +90,15 @@ public: static nsresult OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen, const nsACString& aMimeType, nsACString& aNewData, nsACString& aNewMimeType); + + /** + * Finalize all internal statements. + */ + nsresult FinalizeStatements(); + NS_DECL_ISUPPORTS NS_DECL_NSIFAVICONSERVICE - private: ~nsFaviconService(); diff --git a/toolkit/components/places/src/nsNavBookmarks.cpp b/toolkit/components/places/src/nsNavBookmarks.cpp index fbf2d28a40f..e1d496ab6f6 100644 --- a/toolkit/components/places/src/nsNavBookmarks.cpp +++ b/toolkit/components/places/src/nsNavBookmarks.cpp @@ -432,6 +432,35 @@ nsNavBookmarks::InitStatements() return NS_OK; } +nsresult +nsNavBookmarks::FinalizeStatements() { + mozIStorageStatement* stmts[] = { + mDBGetChildren, + mDBFindURIBookmarks, + mDBFolderCount, + mDBGetItemIndex, + mDBGetChildAt, + mDBGetItemProperties, + mDBGetItemIdForGUID, + mDBGetRedirectDestinations, + mDBInsertBookmark, + mDBIsBookmarkedInDatabase, + mDBGetLastBookmarkID, + mDBSetItemDateAdded, + mDBSetItemLastModified, + mDBSetItemIndex, + mDBGetKeywordForURI, + mDBGetKeywordForBookmark, + mDBGetURIForKeyword + }; + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) { + nsresult rv = nsNavHistory::FinalizeStatement(stmts[i]); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} // nsNavBookmarks::InitRoots // diff --git a/toolkit/components/places/src/nsNavBookmarks.h b/toolkit/components/places/src/nsNavBookmarks.h index 276ebf99ff6..3d9fd4ea614 100644 --- a/toolkit/components/places/src/nsNavBookmarks.h +++ b/toolkit/components/places/src/nsNavBookmarks.h @@ -104,6 +104,11 @@ public: PRBool ItemExists(PRInt64 aItemId); + /** + * Finalize all internal statements. + */ + nsresult FinalizeStatements(); + private: static nsNavBookmarks *sInstance; diff --git a/toolkit/components/places/src/nsNavHistory.cpp b/toolkit/components/places/src/nsNavHistory.cpp index 4ba8001926a..5fb4f6469d2 100644 --- a/toolkit/components/places/src/nsNavHistory.cpp +++ b/toolkit/components/places/src/nsNavHistory.cpp @@ -5279,6 +5279,57 @@ nsNavHistory::GetDBConnection(mozIStorageConnection **_DBConnection) return NS_OK; } +NS_IMETHODIMP +nsNavHistory::FinalizeInternalStatements() +{ + NS_ASSERTION(NS_IsMainThread(), "This can only be called on the main thread"); + +#ifdef LAZY_ADD + // Kill lazy timer or it could fire later when statements won't be valid + // anymore. + // At this point we should have called CommitPendingChanges before the last + // sync, so all data is saved to disk and we can finalize all statements. + if (mLazyTimer) + mLazyTimer->Cancel(); + NS_ABORT_IF_FALSE(mLazyMessages.Length() == 0, + "There are pending lazy messages, did you call CommitPendingChanges()?"); +#endif + + // nsNavHistory + nsresult rv = FinalizeStatements(); + NS_ENSURE_SUCCESS(rv, rv); + + // nsNavBookmarks + nsNavBookmarks* bookmarks = nsNavBookmarks::GetBookmarksService(); + NS_ENSURE_TRUE(bookmarks, NS_ERROR_OUT_OF_MEMORY); + rv = bookmarks->FinalizeStatements(); + NS_ENSURE_SUCCESS(rv, rv); + + // nsAnnotationService + nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService(); + NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY); + rv = annosvc->FinalizeStatements(); + NS_ENSURE_SUCCESS(rv, rv); + + // nsFaviconService + nsFaviconService* iconsvc = nsFaviconService::GetFaviconService(); + NS_ENSURE_TRUE(iconsvc, NS_ERROR_OUT_OF_MEMORY); + rv = iconsvc->FinalizeStatements(); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; +} + +NS_IMETHODIMP +nsNavHistory::CommitPendingChanges() +{ + #ifdef LAZY_ADD + CommitLazyMessages(); + #endif + + return NS_OK; +} + // nsIObserver ***************************************************************** NS_IMETHODIMP @@ -7455,6 +7506,50 @@ nsNavHistory::GetDBOldFrecencies() return mDBOldFrecencies; } +nsresult +nsNavHistory::FinalizeStatements() { + mozIStorageStatement* stmts[] = { + mDBGetURLPageInfo, + mDBGetIdPageInfo, + mDBRecentVisitOfURL, + mDBRecentVisitOfPlace, + mDBInsertVisit, + mDBGetPageVisitStats, + mDBIsPageVisited, + mDBUpdatePageVisitStats, + mDBAddNewPage, + mDBGetTags, + mFoldersWithAnnotationQuery, + mDBSetPlaceTitle, + mDBVisitToURLResult, + mDBVisitToVisitResult, + mDBBookmarkToUrlResult, + mDBVisitsForFrecency, + mDBUpdateFrecencyAndHidden, + mDBGetPlaceVisitStats, + mDBGetBookmarkParentsForPlace, + mDBFullVisitCount, + mDBInvalidFrecencies, + mDBOldFrecencies, + mDBCurrentQuery, + mDBAutoCompleteQuery, + mDBAutoCompleteHistoryQuery, + mDBAutoCompleteStarQuery, + mDBAutoCompleteTagsQuery, + mDBPreviousQuery, + mDBAdaptiveQuery, + mDBKeywordQuery, + mDBFeedbackIncrease + }; + + for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) { + nsresult rv = nsNavHistory::FinalizeStatement(stmts[i]); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + // nsICharsetResolver ********************************************************** NS_IMETHODIMP diff --git a/toolkit/components/places/src/nsNavHistory.h b/toolkit/components/places/src/nsNavHistory.h index 33d79143c93..432e98b9d37 100644 --- a/toolkit/components/places/src/nsNavHistory.h +++ b/toolkit/components/places/src/nsNavHistory.h @@ -197,17 +197,6 @@ public: return gHistoryService; } - /** - * Call this function before doing any database reads. It will ensure that - * any data not flushed to the DB yet is flushed. - */ - void SyncDB() - { - #ifdef LAZY_ADD - CommitLazyMessages(); - #endif - } - #ifdef LAZY_ADD /** * Adds a lazy message for adding a favicon. Used by the favicon service so @@ -400,6 +389,19 @@ public: typedef nsDataHashtable StringHash; + /** + * Helper method to finalize a statement + */ + static nsresult + FinalizeStatement(mozIStorageStatement *aStatement) { + nsresult rv; + if (aStatement) { + rv = aStatement->Finalize(); + NS_ENSURE_SUCCESS(rv, rv); + } + return NS_OK; + } + private: ~nsNavHistory(); @@ -444,6 +446,11 @@ protected: mozIStorageStatement *GetDBBookmarkToUrlResult(); nsCOMPtr mDBBookmarkToUrlResult; // kGetInfoIndex_* results + /** + * Finalize all internal statements. + */ + nsresult FinalizeStatements(); + // nsICharsetResolver NS_DECL_NSICHARSETRESOLVER diff --git a/toolkit/components/places/src/nsNavHistoryExpire.cpp b/toolkit/components/places/src/nsNavHistoryExpire.cpp index 9b2502a250c..d051329c1bf 100644 --- a/toolkit/components/places/src/nsNavHistoryExpire.cpp +++ b/toolkit/components/places/src/nsNavHistoryExpire.cpp @@ -257,18 +257,10 @@ nsNavHistoryExpire::ClearHistory() "SELECT h.id FROM moz_places_temp h " "WHERE " "EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) " - "OR EXISTS " - "(SELECT id FROM moz_annos WHERE place_id = h.id AND expiration = ") + - nsPrintfCString("%d", nsIAnnotationService::EXPIRE_NEVER) + - NS_LITERAL_CSTRING(") " "UNION ALL " "SELECT h.id FROM moz_places h " "WHERE " "EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) " - "OR EXISTS " - "(SELECT id FROM moz_annos WHERE place_id = h.id AND expiration = ") + - nsPrintfCString("%d", nsIAnnotationService::EXPIRE_NEVER) + - NS_LITERAL_CSTRING(") " ")")); NS_ENSURE_SUCCESS(rv, rv); @@ -837,7 +829,9 @@ nsNavHistoryExpire::ExpireAnnotations(mozIStorageConnection* aConnection) NS_ENSURE_SUCCESS(rv, rv); rv = expirePagesStatement->Execute(); NS_ENSURE_SUCCESS(rv, rv); - + rv = expirePagesStatement->Reset(); + NS_ENSURE_SUCCESS(rv, rv); + // remove days item annos rv = expireItemsStatement->BindInt32Parameter(0, nsIAnnotationService::EXPIRE_DAYS); NS_ENSURE_SUCCESS(rv, rv); @@ -845,6 +839,8 @@ nsNavHistoryExpire::ExpireAnnotations(mozIStorageConnection* aConnection) NS_ENSURE_SUCCESS(rv, rv); rv = expireItemsStatement->Execute(); NS_ENSURE_SUCCESS(rv, rv); + rv = expireItemsStatement->Reset(); + NS_ENSURE_SUCCESS(rv, rv); // remove weeks annos rv = expirePagesStatement->BindInt32Parameter(0, nsIAnnotationService::EXPIRE_WEEKS); @@ -853,6 +849,8 @@ nsNavHistoryExpire::ExpireAnnotations(mozIStorageConnection* aConnection) NS_ENSURE_SUCCESS(rv, rv); rv = expirePagesStatement->Execute(); NS_ENSURE_SUCCESS(rv, rv); + rv = expirePagesStatement->Reset(); + NS_ENSURE_SUCCESS(rv, rv); // remove weeks item annos rv = expireItemsStatement->BindInt32Parameter(0, nsIAnnotationService::EXPIRE_WEEKS); @@ -861,6 +859,8 @@ nsNavHistoryExpire::ExpireAnnotations(mozIStorageConnection* aConnection) NS_ENSURE_SUCCESS(rv, rv); rv = expireItemsStatement->Execute(); NS_ENSURE_SUCCESS(rv, rv); + rv = expireItemsStatement->Reset(); + NS_ENSURE_SUCCESS(rv, rv); // remove months annos rv = expirePagesStatement->BindInt32Parameter(0, nsIAnnotationService::EXPIRE_MONTHS); diff --git a/toolkit/components/places/src/nsNavHistoryResult.cpp b/toolkit/components/places/src/nsNavHistoryResult.cpp index 7ca7cefbe9f..0d29910d58c 100644 --- a/toolkit/components/places/src/nsNavHistoryResult.cpp +++ b/toolkit/components/places/src/nsNavHistoryResult.cpp @@ -2195,7 +2195,10 @@ nsNavHistoryQueryResultNode::GetHasChildren(PRBool* aHasChildren) rv = hasTagsStatement->BindInt64Parameter(0, tagsFolderId); NS_ENSURE_SUCCESS(rv, rv); - return hasTagsStatement->ExecuteStep(aHasChildren); + rv = hasTagsStatement->ExecuteStep(aHasChildren); + NS_ENSURE_SUCCESS(rv, rv); + + return NS_OK; } // For history containers query we must check if we have any history diff --git a/toolkit/components/places/src/nsPlacesDBFlush.js b/toolkit/components/places/src/nsPlacesDBFlush.js index 5a9fb21248f..9ae5fd13501 100644 --- a/toolkit/components/places/src/nsPlacesDBFlush.js +++ b/toolkit/components/places/src/nsPlacesDBFlush.js @@ -103,7 +103,26 @@ nsPlacesDBFlush.prototype = { this._prefs.QueryInterface(Ci.nsIPrefBranch2).removeObserver("", this); this._timer.cancel(); this._timer = null; - this._syncTables(["places", "historyvisits"]); + // Other components could still make changes to history at this point, + // for example to clear private data on shutdown, so here we dispatch + // an event to the main thread so that we will sync after + // quit-application ensuring all data have been saved. + let tm = Cc["@mozilla.org/thread-manager;1"]. + getService(Ci.nsIThreadManager); + tm.mainThread.dispatch({ + _self: this, + run: function() { + let pip = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsPIPlacesDatabase); + pip.commitPendingChanges(); + this._self._syncTables(["places", "historyvisits"]); + // Close the database connection, this was the last sync and we can't + // ensure database coherence from now on. + pip.finalizeInternalStatements(); + this._self._db.close(); + } + }, Ci.nsIThread.DISPATCH_NORMAL); + } else if (aTopic == "nsPref:changed" && aData == kSyncPrefName) { // Get the new pref value, and then update our timer diff --git a/toolkit/components/places/tests/sync/head_sync.js b/toolkit/components/places/tests/sync/head_sync.js index a2a02fa40ce..b0096773046 100644 --- a/toolkit/components/places/tests/sync/head_sync.js +++ b/toolkit/components/places/tests/sync/head_sync.js @@ -111,9 +111,7 @@ clearDB(); */ function dump_table(aName) { - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; + let db = DBConn() let stmt = db.createStatement("SELECT * FROM " + aName); dump("\n*** Printing data from " + aName + ":\n"); @@ -185,9 +183,7 @@ function finish_test() */ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFinish) { - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; + let db = DBConn(); let stmt = db.createStatement( "SELECT moz_places.url " + "FROM moz_bookmarks INNER JOIN moz_places " + @@ -227,9 +223,7 @@ function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFini */ function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) { - let db = Cc["@mozilla.org/browser/nav-history-service;1"]. - getService(Ci.nsPIPlacesDatabase). - DBConnection; + let db = DBConn(); let stmt = db.createStatement( "SELECT moz_places.url " + "FROM moz_historyvisits INNER JOIN moz_places " + @@ -253,6 +247,31 @@ function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish) finish_test(); } +/** + * Function gets current database connection, if the connection has been closed + * it will try to reconnect to the places.sqlite database. + */ +function DBConn() +{ + let db = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsPIPlacesDatabase). + DBConnection; + if (db.connectionReady) + return db; + + // open a new connection if needed + let file = dirSvc.get('ProfD', Ci.nsIFile); + file.append("places.sqlite"); + let storageService = Cc["@mozilla.org/storage/service;1"]. + getService(Ci.mozIStorageService); + try { + var dbConn = storageService.openDatabase(file); + } catch (ex) { + return null; + } + return dbConn; +} + // profile-after-change doesn't create components in xpcshell, so we have to do // it ourselves Cc["@mozilla.org/places/sync;1"].getService(Ci.nsISupports); diff --git a/toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_commitPendingChanges.js b/toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_commitPendingChanges.js new file mode 100644 index 00000000000..34bcce1ae7c --- /dev/null +++ b/toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_commitPendingChanges.js @@ -0,0 +1,75 @@ +/* -*- 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 Unit Test Code. + * + * The Initial Developer of the Original Code is Mozilla Corp. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo (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 ***** */ + +var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); +var pip = hs.QueryInterface(Ci.nsPIPlacesDatabase); +var mDBConn = pip.DBConnection; +var gh = hs.QueryInterface(Ci.nsIGlobalHistory2); +var iconsvc = Cc["@mozilla.org/browser/favicon-service;1"]. + getService(Ci.nsIFaviconService); + +const TEST_URI = "http://www.mozilla.org/"; +const TEST_TITLE = "testTitle"; + +// main +function run_test() { + var testURI = uri(TEST_URI); + var faviconURI = uri(TEST_URI + "favicon.ico"); + + // Add a uri lazy message + gh.addURI(testURI, false, true, null); + // Add a favicon lazy message + iconsvc.setFaviconUrlForPage(testURI, faviconURI); + // Add a title lazy message + hs.setPageTitle(testURI, TEST_TITLE); + + // Commit all pending changes (lazy messages) + pip.commitPendingChanges(); + + // Check database values, we can't use APIs because them would check + // lazy queue. + let stmt = mDBConn.createStatement( + "SELECT id FROM moz_places_temp WHERE url = :url AND title = :title " + + "AND favicon_id = (SELECT id FROM moz_favicons WHERE url = :favicon_url)"); + stmt.params["url"] = testURI.spec; + stmt.params["title"] = TEST_TITLE; + stmt.params["favicon_url"] = faviconURI.spec; + do_check_true(stmt.executeStep()); + stmt.finalize(); +} diff --git a/toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_finalizeInternalStatements.js b/toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_finalizeInternalStatements.js new file mode 100644 index 00000000000..075627ce3da --- /dev/null +++ b/toolkit/components/places/tests/unit/test_nsPIPlacesDatabase_finalizeInternalStatements.js @@ -0,0 +1,49 @@ +/* -*- 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 Unit Test Code. + * + * The Initial Developer of the Original Code is Mozilla Corp. + * Portions created by the Initial Developer are Copyright (C) 2008 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Marco Bonardo (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 ***** */ + +// main +function run_test() { + var hs = Cc["@mozilla.org/browser/nav-history-service;1"]. + getService(Ci.nsINavHistoryService); + + var mDBConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection; + + hs.QueryInterface(Ci.nsPIPlacesDatabase).finalizeInternalStatements(); + mDBConn.close(); + do_check_false(mDBConn.connectionReady); +}