diff --git a/browser/base/content/sanitize.js b/browser/base/content/sanitize.js index 153bfd651fea..ba10cafa492c 100644 --- a/browser/base/content/sanitize.js +++ b/browser/base/content/sanitize.js @@ -65,7 +65,13 @@ Sanitizer.prototype = { var itemsToClear = [...aItemsToClear]; } else { let branch = Services.prefs.getBranch(this.prefDomain); - itemsToClear = Object.keys(this.items).filter(itemName => branch.getBoolPref(itemName)); + itemsToClear = Object.keys(this.items).filter(itemName => { + try { + return branch.getBoolPref(itemName); + } catch (ex) { + return false; + } + }); } // Ensure open windows get cleared first, if they're in our list, so that they don't stick diff --git a/browser/components/places/tests/unit/test_clearHistory_shutdown.js b/browser/components/places/tests/unit/test_clearHistory_shutdown.js index a516e51bc24b..c87bffc4d73d 100644 --- a/browser/components/places/tests/unit/test_clearHistory_shutdown.js +++ b/browser/components/places/tests/unit/test_clearHistory_shutdown.js @@ -71,13 +71,11 @@ add_task(function* test_execute() { } do_print("Add cache."); yield storeCache(FTP_URL, "testData"); -}); -add_task(function* run_test_continue() { do_print("Simulate and wait shutdown."); yield shutdownPlaces(); - let stmt = DBConn().createStatement( + let stmt = DBConn(true).createStatement( "SELECT id FROM moz_places WHERE url = :page_url " ); @@ -93,13 +91,7 @@ add_task(function* run_test_continue() { do_print("Check cache"); // Check cache. - let promiseCacheChecked = checkCache(FTP_URL); - - do_print("Shutdown the download manager"); - // Shutdown the download manager. - Services.obs.notifyObservers(null, "quit-application", null); - - yield promiseCacheChecked; + yield checkCache(FTP_URL); }); function storeCache(aURL, aContent) { diff --git a/toolkit/components/places/PlacesUtils.jsm b/toolkit/components/places/PlacesUtils.jsm index e5a750c77225..c36121640d64 100644 --- a/toolkit/components/places/PlacesUtils.jsm +++ b/toolkit/components/places/PlacesUtils.jsm @@ -2075,6 +2075,19 @@ XPCOMUtils.defineLazyGetter(this, "bundle", function() { createBundle(PLACES_STRING_BUNDLE_URI); }); +// A promise resolved once the Sqlite.jsm connections +// can be closed. +let promiseCanCloseConnection = function() { + let TOPIC = "places-will-close-connection"; + return new Promise(resolve => { + let observer = function() { + Services.obs.removeObserver(observer, TOPIC); + resolve(); + } + Services.obs.addObserver(observer, TOPIC, false) + }); +}; + XPCOMUtils.defineLazyGetter(this, "gAsyncDBConnPromised", () => new Promise((resolve) => { Sqlite.cloneStorageConnection({ @@ -2082,12 +2095,23 @@ XPCOMUtils.defineLazyGetter(this, "gAsyncDBConnPromised", readOnly: true }).then(conn => { try { - Sqlite.shutdown.addBlocker( - "PlacesUtils read-only connection closing", - conn.close.bind(conn)); - PlacesUtils.history.shutdownClient.jsclient.addBlocker( - "PlacesUtils read-only connection closing", - conn.close.bind(conn)); + let state = "0. not started"; + + let promiseReady = promiseCanCloseConnection(); + let promiseShutdownComplete = Task.async(function*() { + // Don't close the connection as long as it might be used. + state = "1. waiting for `places-will-close-connection`"; + yield promiseReady; + + // But close the connection before Sqlite shutdown. + state = "2. closing the connection"; + yield conn.close(); + + state = "3. done"; + })(); + Sqlite.shutdown.addBlocker("PlacesUtils read-only connection closing", + promiseShutdownComplete, + () => state); } catch(ex) { // It's too late to block shutdown, just close the connection. conn.close(); @@ -2104,12 +2128,23 @@ XPCOMUtils.defineLazyGetter(this, "gAsyncDBWrapperPromised", connection: PlacesUtils.history.DBConnection, }).then(conn => { try { - Sqlite.shutdown.addBlocker( - "PlacesUtils wrapped connection closing", - conn.close.bind(conn)); - PlacesUtils.history.shutdownClient.jsclient.addBlocker( - "PlacesUtils wrapped connection closing", - conn.close.bind(conn)); + let state = "0. not started"; + + let promiseReady = promiseCanCloseConnection(); + let promiseShutdownComplete = Task.async(function*() { + // Don't close the connection as long as it might be used. + state = "1. waiting for `places-will-close-connection`"; + yield promiseReady; + + // But close the connection before Sqlite shutdown. + state = "2. closing the connection"; + yield conn.close(); + + state = "3. done"; + })(); + Sqlite.shutdown.addBlocker("PlacesUtils wrapped connection closing", + promiseShutdownComplete, + () => state); } catch(ex) { // It's too late to block shutdown, just close the connection. conn.close();