Bug 1458910 - Merge nsPIPlacesDatabase into nsINavHistoryService. r=standard8

MozReview-Commit-ID: LacXKR32Jn3

--HG--
extra : rebase_source : 27f7d939ab9acab6eb4896e8fc1348e74aee35cf
This commit is contained in:
Marco Bonardo 2018-05-10 10:39:12 +02:00
parent 4021845f39
commit c77855f4fe
24 changed files with 66 additions and 190 deletions

View File

@ -242,43 +242,6 @@ function promiseOpenAndLoadWindow(aOptions, aWaitForDelayedStartup = false) {
});
}
/**
* Waits for all pending async statements on the default connection, before
* proceeding with aCallback.
*
* @param aCallback
* Function to be called when done.
* @param aScope
* Scope for the callback.
* @param aArguments
* Arguments array for the callback.
*
* @note The result is achieved by asynchronously executing a query requiring
* a write lock. Since all statements on the same connection are
* serialized, the end of this write operation means that all writes are
* complete. Note that WAL makes so that writers don't block readers, but
* this is a problem only across different connections.
*/
function waitForAsyncUpdates(aCallback, aScope, aArguments) {
let scope = aScope || this;
let args = aArguments || [];
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let begin = db.createAsyncStatement("BEGIN EXCLUSIVE");
begin.executeAsync();
begin.finalize();
let commit = db.createAsyncStatement("COMMIT");
commit.executeAsync({
handleResult() {},
handleError() {},
handleCompletion(aReason) {
aCallback.apply(scope, args);
}
});
commit.finalize();
}
function whenNewTabLoaded(aWindow, aCallback) {
aWindow.BrowserOpenTab();

View File

@ -776,8 +776,8 @@ WindowHelper.prototype = {
* this.onload to a function to execute onload. It should close the dialog
* when done so that the tests may continue. Set this.onunload to a function
* to execute onunload. this.onunload is optional. If it returns true, the
* caller is expected to call waitForAsyncUpdates at some point; if false is
* returned, waitForAsyncUpdates is called automatically.
* caller is expected to call promiseAsyncUpdates at some point; if false is
* returned, promiseAsyncUpdates is called automatically.
*/
open() {
let wh = this;

View File

@ -65,43 +65,6 @@ function promiseClipboard(aPopulateClipboardFn, aFlavor) {
});
}
/**
* Waits for all pending async statements on the default connection, before
* proceeding with aCallback.
*
* @param aCallback
* Function to be called when done.
* @param aScope
* Scope for the callback.
* @param aArguments
* Arguments array for the callback.
*
* @note The result is achieved by asynchronously executing a query requiring
* a write lock. Since all statements on the same connection are
* serialized, the end of this write operation means that all writes are
* complete. Note that WAL makes so that writers don't block readers, but
* this is a problem only across different connections.
*/
function waitForAsyncUpdates(aCallback, aScope, aArguments) {
let scope = aScope || this;
let args = aArguments || [];
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let begin = db.createAsyncStatement("BEGIN EXCLUSIVE");
begin.executeAsync();
begin.finalize();
let commit = db.createAsyncStatement("COMMIT");
commit.executeAsync({
handleResult() {},
handleError() {},
handleCompletion(aReason) {
aCallback.apply(scope, args);
}
});
commit.finalize();
}
function synthesizeClickOnSelectedTreeCell(aTree, aOptions) {
let tbo = aTree.treeBoxObject;
if (tbo.view.selection.count != 1)

View File

@ -240,10 +240,7 @@ var Sanitizer = {
// hasn't been closed by the time we use it.
// Though, if this is a sanitize on shutdown, we already have a blocker.
if (!progress.isShutdown) {
let shutdownClient = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsPIPlacesDatabase)
.shutdownClient
.jsclient;
let shutdownClient = PlacesUtils.history.shutdownClient.jsclient;
shutdownClient.addBlocker("sanitize.js: Sanitize",
promise,
{

View File

@ -401,8 +401,7 @@ var WinTaskbarJumpList =
var query = PlacesUtils.history.getNewQuery();
// Return the pending statement to the caller, to allow cancelation.
return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQuery(query, options, {
return PlacesUtils.history.asyncExecuteLegacyQuery(query, options, {
handleResult(aResultSet) {
for (let row; (row = aResultSet.getNextRow());) {
try {

View File

@ -1851,8 +1851,7 @@ var PlacesUtils = {
XPCOMUtils.defineLazyGetter(PlacesUtils, "history", function() {
let hs = Cc["@mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService)
.QueryInterface(Ci.nsPIPlacesDatabase);
.getService(Ci.nsINavHistoryService);
return Object.freeze(new Proxy(hs, {
get(target, name) {
let property, object;

View File

@ -28,13 +28,13 @@ class Database;
* PHASE 2 (Modern clients shutdown)
* Modern clients should instead register as a blocker by passing a promise to
* nsPIPlacesDatabase::shutdownClient (for example see Sanitizer.jsm), so they
* nsINavHistoryService::shutdownClient (for example see Sanitizer.jsm), so they
* block Places shutdown until the promise is resolved.
* When profile-change-teardown is observed by async shutdown, it calls
* ClientsShutdownBlocker::BlockShutdown. This class is registered as a teardown
* phase blocker in Database::Init (see Database::mClientsShutdown).
* ClientsShutdownBlocker::BlockShudown waits for all the clients registered
* through nsPIPlacesDatabase::shutdownClient. When all the clients are done,
* through nsINavHistoryService::shutdownClient. When all the clients are done,
* its `Done` method is invoked, and it stops blocking the shutdown phase, so
* that it can continue.
*

View File

@ -25,7 +25,6 @@ if CONFIG['MOZ_PLACES']:
'nsIFaviconService.idl',
'nsINavBookmarksService.idl',
'nsITaggingService.idl',
'nsPIPlacesDatabase.idl',
]
EXPORTS.mozilla.places = [

View File

@ -16,6 +16,11 @@ interface nsIURI;
interface nsIVariant;
interface nsIFile;
interface mozIStorageConnection;
interface mozIStorageStatementCallback;
interface mozIStoragePendingStatement;
interface nsIAsyncShutdownClient;
interface nsINavHistoryContainerResultNode;
interface nsINavHistoryQueryResultNode;
interface nsINavHistoryQuery;
@ -624,9 +629,6 @@ interface nsINavHistoryResult : nsISupports
/**
* Similar to nsIRDFObserver for history. Note that we don't pass the data
* source since that is always the global history.
*
* DANGER! If you are in the middle of a batch transaction, there may be a
* database transaction active. You can still access the DB, but be careful.
*/
@ -1386,4 +1388,40 @@ interface nsINavHistoryService : nsISupports
* The hash mode: `""` (default), `"prefix_lo"`, or `"prefix_hi"`.
*/
unsigned long long hashURL(in ACString aSpec, [optional] in ACString aMode);
/**
* The database connection used by Places.
*/
readonly attribute mozIStorageConnection DBConnection;
/**
* Asynchronously executes the statement created from a query.
*
* @see nsINavHistoryService::executeQuery
* @note THIS IS A TEMPORARY API. Don't rely on it, since it will be replaced
* in future versions by a real async querying API.
* @note Results obtained from this method differ from results obtained from
* executeQuery, because there is additional filtering and sorting
* done by the latter. Thus you should use executeQuery, unless you
* are absolutely sure that the returned results are fine for
* your use-case.
*/
mozIStoragePendingStatement asyncExecuteLegacyQuery(
in nsINavHistoryQuery aQuery,
in nsINavHistoryQueryOptions aOptions,
in mozIStorageStatementCallback aCallback);
/**
* Hook for clients who need to perform actions during/by the end of
* the shutdown of the database.
* May be null if it's too late to get one.
*/
readonly attribute nsIAsyncShutdownClient shutdownClient;
/**
* Hook for internal clients who need to perform actions just before the
* connection gets closed.
* May be null if it's too late to get one.
*/
readonly attribute nsIAsyncShutdownClient connectionShutdownClient;
};

View File

@ -179,7 +179,6 @@ NS_INTERFACE_MAP_BEGIN(nsNavHistory)
NS_INTERFACE_MAP_ENTRY(nsINavHistoryService)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsPIPlacesDatabase)
NS_INTERFACE_MAP_ENTRY(mozIStorageVacuumParticipant)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINavHistoryService)
NS_IMPL_QUERY_CLASSINFO(nsNavHistory)
@ -2269,10 +2268,6 @@ nsNavHistory::OnEndVacuum(bool aSucceeded)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
//// nsPIPlacesDatabase
NS_IMETHODIMP
nsNavHistory::GetDBConnection(mozIStorageConnection **_DBConnection)
{

View File

@ -7,7 +7,6 @@
#define nsNavHistory_h_
#include "nsINavHistoryService.h"
#include "nsPIPlacesDatabase.h"
#include "nsINavBookmarksService.h"
#include "nsIFaviconService.h"
#include "nsIGlobalHistory2.h"
@ -78,7 +77,6 @@ class nsIAutoCompleteController;
class nsNavHistory final : public nsSupportsWeakReference
, public nsINavHistoryService
, public nsIObserver
, public nsPIPlacesDatabase
, public mozIStorageVacuumParticipant
{
friend class PlacesSQLQueryBuilder;
@ -89,7 +87,6 @@ public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSINAVHISTORYSERVICE
NS_DECL_NSIOBSERVER
NS_DECL_NSPIPLACESDATABASE
NS_DECL_MOZISTORAGEVACUUMPARTICIPANT
/**

View File

@ -1,59 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 sts=2
* 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/. */
#include "nsISupports.idl"
interface mozIStorageConnection;
interface nsINavHistoryQuery;
interface nsINavHistoryQueryOptions;
interface mozIStorageStatementCallback;
interface mozIStoragePendingStatement;
interface nsIAsyncShutdownClient;
/**
* This is a private interface used by Places components to get access to the
* 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(366ee63e-a413-477d-9ad6-8d6863e89401)]
interface nsPIPlacesDatabase : nsISupports
{
/**
* The database connection used by Places.
*/
readonly attribute mozIStorageConnection DBConnection;
/**
* Asynchronously executes the statement created from a query.
*
* @see nsINavHistoryService::executeQuery
* @note THIS IS A TEMPORARY API. Don't rely on it, since it will be replaced
* in future versions by a real async querying API.
* @note Results obtained from this method differ from results obtained from
* executeQuery, because there is additional filtering and sorting
* done by the latter. Thus you should use executeQuery, unless you
* are absolutely sure that the returned results are fine for
* your use-case.
*/
mozIStoragePendingStatement asyncExecuteLegacyQuery(
in nsINavHistoryQuery aQuery,
in nsINavHistoryQueryOptions aOptions,
in mozIStorageStatementCallback aCallback);
/**
* Hook for clients who need to perform actions during/by the end of
* the shutdown of the database.
* May be null if it's too late to get one.
*/
readonly attribute nsIAsyncShutdownClient shutdownClient;
/**
* Hook for internal clients who need to perform actions just before the
* connection gets closed.
* May be null if it's too late to get one.
*/
readonly attribute nsIAsyncShutdownClient connectionShutdownClient;
};

View File

@ -390,9 +390,7 @@ function nsPlacesExpiration() {
// Smart Getters
XPCOMUtils.defineLazyGetter(this, "_db", function() {
let db = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsPIPlacesDatabase).
DBConnection;
let db = PlacesUtils.history.DBConnection;
// Create the temporary notifications table.
let stmt = db.createAsyncStatement(

View File

@ -58,8 +58,7 @@ TaggingService.prototype = {
return -1;
// Using bookmarks service API for this would be a pain.
// Until tags implementation becomes sane, go the query way.
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let db = PlacesUtils.history.DBConnection;
let stmt = db.createStatement(
`SELECT id FROM moz_bookmarks
WHERE parent = :tag_id
@ -178,8 +177,7 @@ TaggingService.prototype = {
*/
_removeTagIfEmpty: function TS__removeTagIfEmpty(aTagId, aSource) {
let count = 0;
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let db = PlacesUtils.history.DBConnection;
let stmt = db.createStatement(
`SELECT count(*) AS count FROM moz_bookmarks
WHERE parent = :tag_id`
@ -247,8 +245,7 @@ TaggingService.prototype = {
if (tagId == -1)
return uris;
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let db = PlacesUtils.history.DBConnection;
let stmt = db.createStatement(
`SELECT h.url FROM moz_places h
JOIN moz_bookmarks b ON b.fk = h.id
@ -311,8 +308,7 @@ TaggingService.prototype = {
if (!this.__tagFolders) {
this.__tagFolders = [];
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let db = PlacesUtils.history.DBConnection;
let stmt = db.createStatement(
"SELECT id, title FROM moz_bookmarks WHERE parent = :tags_root "
);
@ -372,8 +368,7 @@ TaggingService.prototype = {
// Using bookmarks service API for this would be a pain.
// Until tags implementation becomes sane, go the query way.
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let db = PlacesUtils.history.DBConnection;
let stmt = db.createStatement(
`SELECT id, parent
FROM moz_bookmarks

View File

@ -6,8 +6,7 @@
// Get database connection
try {
var mDBConn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
var mDBConn = PlacesUtils.history.DBConnection;
} catch (ex) {
do_throw("Could not get database connection\n");
}

View File

@ -1,4 +1,4 @@
var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
var conn = PlacesUtils.history.DBConnection;
/**
* Gets a single column value from either the places or historyvisits table.

View File

@ -12,7 +12,7 @@ function promiseObserve(name, checkFn) {
});
}
var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
var conn = PlacesUtils.history.DBConnection;
/**
* Gets a single column value from either the places or historyvisits table.

View File

@ -27,8 +27,7 @@ const TRANSITION_DOWNLOAD = PlacesUtils.history.TRANSITION_DOWNLOAD;
*/
function fieldForUrl(aURI, aFieldName, aCallback) {
let url = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
let stmt = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection.createAsyncStatement(
let stmt = PlacesUtils.history.DBConnection.createAsyncStatement(
`SELECT ${aFieldName} FROM moz_places WHERE url_hash = hash(:page_url) AND url = :page_url`
);
stmt.params.page_url = url;

View File

@ -20,7 +20,6 @@
#include "mozIStorageAsyncStatement.h"
#include "mozIStorageStatementCallback.h"
#include "mozIStoragePendingStatement.h"
#include "nsPIPlacesDatabase.h"
#include "nsIObserver.h"
#include "prinrval.h"
#include "prtime.h"
@ -218,11 +217,10 @@ already_AddRefed<mozIStorageConnection>
do_get_db()
{
nsCOMPtr<nsINavHistoryService> history = do_get_NavHistory();
nsCOMPtr<nsPIPlacesDatabase> database = do_QueryInterface(history);
do_check_true(database);
do_check_true(history);
nsCOMPtr<mozIStorageConnection> dbConn;
nsresult rv = database->GetDBConnection(getter_AddRefs(dbConn));
nsresult rv = history->GetDBConnection(getter_AddRefs(dbConn));
do_check_success(rv);
return dbConn.forget();
}

View File

@ -97,8 +97,7 @@ function uri(aSpec) {
var gDBConn;
function DBConn(aForceNewConnection) {
if (!aForceNewConnection) {
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.DBConnection;
let db = PlacesUtils.history.DBConnection;
if (db.connectionReady)
return db;
}

View File

@ -14,8 +14,7 @@ add_task(async function test_history_query() {
let query = PlacesUtils.history.getNewQuery();
return new Promise(resolve => {
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQuery(query, options, {
PlacesUtils.history.asyncExecuteLegacyQuery(query, options, {
handleResult(aResultSet) {
for (let row; (row = aResultSet.getNextRow());) {
try {
@ -51,8 +50,7 @@ add_task(async function test_bookmarks_query() {
let query = PlacesUtils.history.getNewQuery();
return new Promise(resolve => {
PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
.asyncExecuteLegacyQuery(query, options, {
PlacesUtils.history.asyncExecuteLegacyQuery(query, options, {
handleResult(aResultSet) {
for (let row; (row = aResultSet.getNextRow());) {
try {

View File

@ -149,7 +149,7 @@ add_task(async function test_execute() {
// test for schema changes in bug 373239
// get direct db connection
var db = histsvc.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
var db = histsvc.DBConnection;
var q = "SELECT id FROM moz_bookmarks";
var statement;
try {

View File

@ -20,7 +20,7 @@ var ts = PlacesUtils.tagging;
var as = PlacesUtils.annotations;
var fs = PlacesUtils.favicons;
var mDBConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
var mDBConn = hs.DBConnection;
// ------------------------------------------------------------------------------
// Helpers

View File

@ -616,8 +616,7 @@ var PlacesProvider = {
// Execute the query.
let query = PlacesUtils.history.getNewQuery();
let db = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase);
db.asyncExecuteLegacyQuery(query, options, callback);
PlacesUtils.history.asyncExecuteLegacyQuery(query, options, callback);
},
/**