mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central into places.
This commit is contained in:
commit
8c46198937
@ -221,10 +221,9 @@ function ensure_opentabs_match_db() {
|
||||
|
||||
try {
|
||||
var stmt = db.createStatement(
|
||||
"SELECT t.url, open_count, IFNULL(p_t.id, p.id) " +
|
||||
"SELECT t.url, open_count, p.id " +
|
||||
"FROM moz_openpages_temp t " +
|
||||
"LEFT JOIN moz_places p ON p.url = t.url " +
|
||||
"LEFT JOIN moz_places_temp p_t ON p_t.url = t.url");
|
||||
"LEFT JOIN moz_places p ON p.url = t.url ");
|
||||
} catch (e) {
|
||||
ok(false, "error creating db statement: " + e);
|
||||
return;
|
||||
|
@ -417,10 +417,7 @@ BrowserGlue.prototype = {
|
||||
}
|
||||
|
||||
// Load the "more info" page for a locked places.sqlite
|
||||
// This property is set earlier in the startup process:
|
||||
// nsPlacesDBFlush loads after profile-after-change and initializes
|
||||
// the history service, which sends out places-database-locked
|
||||
// which sets this property.
|
||||
// This property is set earlier by places-database-locked topic.
|
||||
if (this._isPlacesDatabaseLocked) {
|
||||
this._showPlacesLockedNotificationBox();
|
||||
}
|
||||
|
@ -53,9 +53,7 @@ let EXPECTED_NOTIFICATIONS = [
|
||||
"places-shutdown"
|
||||
, "places-will-close-connection"
|
||||
, "places-connection-closing"
|
||||
, "places-sync-finished"
|
||||
, "places-expiration-finished"
|
||||
, "places-sync-finished"
|
||||
, "places-connection-closed"
|
||||
];
|
||||
|
||||
|
@ -345,7 +345,6 @@
|
||||
@BINPATH@/components/toolkitplaces.manifest
|
||||
@BINPATH@/components/nsLivemarkService.js
|
||||
@BINPATH@/components/nsTaggingService.js
|
||||
@BINPATH@/components/nsPlacesDBFlush.js
|
||||
@BINPATH@/components/nsPlacesAutoComplete.manifest
|
||||
@BINPATH@/components/nsPlacesAutoComplete.js
|
||||
@BINPATH@/components/nsPlacesExpiration.js
|
||||
|
@ -1089,3 +1089,4 @@ extensions/inspector@mozilla.org/components/@DLL_PREFIX@inspector@DLL_SUFFIX@
|
||||
extensions/inspector@mozilla.org/chrome/icons/default/winInspectorMain.ico
|
||||
components/nsPlacesTransactionsService.js
|
||||
components/browserplaces.xpt
|
||||
components/nsPlacesDBFlush.js
|
||||
|
@ -130,7 +130,7 @@ GCONF_VERSION=1.2.1
|
||||
GIO_VERSION=2.0
|
||||
STARTUP_NOTIFICATION_VERSION=0.8
|
||||
DBUS_VERSION=0.60
|
||||
SQLITE_VERSION=3.7.1
|
||||
SQLITE_VERSION=3.7.3
|
||||
LIBNOTIFY_VERSION=0.4
|
||||
|
||||
MSMANIFEST_TOOL=
|
||||
|
@ -1,6 +1,6 @@
|
||||
This is sqlite 3.7.1
|
||||
This is sqlite 3.7.3
|
||||
|
||||
-- Shawn Wilsher <me@shawnwilsher.com>, 08/2010
|
||||
-- Shawn Wilsher <me@shawnwilsher.com>, 10/2010
|
||||
|
||||
See http://www.sqlite.org/ for more info.
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -48,6 +48,8 @@ MODULE = storage
|
||||
XPIDL_MODULE = storage
|
||||
GRE_MODULE = 1
|
||||
|
||||
# NOTE When adding something to this list, you probably need to add it to the
|
||||
# storage.h file too.
|
||||
XPIDLSRCS = \
|
||||
mozIStorageService.idl \
|
||||
mozIStorageConnection.idl \
|
||||
@ -70,6 +72,7 @@ XPIDLSRCS = \
|
||||
mozIStorageServiceQuotaManagement.idl \
|
||||
mozIStorageVacuumParticipant.idl \
|
||||
$(NULL)
|
||||
# SEE ABOVE NOTE!
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla
|
||||
|
||||
|
@ -59,6 +59,8 @@
|
||||
#include "mozIStorageBindingParams.h"
|
||||
#include "mozIStorageServiceQuotaManagement.h"
|
||||
#include "mozIStorageVacuumParticipant.h"
|
||||
#include "mozIStorageCompletionCallback.h"
|
||||
#include "mozIStorageAsyncStatement.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Native Language Helpers
|
||||
|
@ -271,7 +271,8 @@ AsyncStatement::~AsyncStatement()
|
||||
// nsCOMPtr. Which it is not; it's an nsRefPtr.
|
||||
Connection *forgottenConn = nsnull;
|
||||
mDBConnection.swap(forgottenConn);
|
||||
(void)::NS_ProxyRelease(forgottenConn->threadOpenedOn, forgottenConn);
|
||||
(void)::NS_ProxyRelease(forgottenConn->threadOpenedOn,
|
||||
static_cast<mozIStorageConnection *>(forgottenConn));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,7 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
private:
|
||||
nsCOMPtr<Connection> mConnection;
|
||||
nsRefPtr<Connection> mConnection;
|
||||
nsCOMPtr<nsIEventTarget> mCallingThread;
|
||||
nsCOMPtr<nsIRunnable> mCallbackEvent;
|
||||
};
|
||||
@ -352,9 +352,10 @@ Connection::~Connection()
|
||||
(void)Close();
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(
|
||||
Connection,
|
||||
mozIStorageConnection
|
||||
mozIStorageConnection,
|
||||
nsIInterfaceRequestor
|
||||
)
|
||||
|
||||
nsIEventTarget *
|
||||
@ -642,6 +643,22 @@ Connection::getFilename()
|
||||
return leafname;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIInterfaceRequestor
|
||||
|
||||
NS_IMETHODIMP
|
||||
Connection::GetInterface(const nsIID &aIID,
|
||||
void **_result)
|
||||
{
|
||||
if (aIID.Equals(NS_GET_IID(nsIEventTarget))) {
|
||||
nsIEventTarget *background = getAsyncExecutionTarget();
|
||||
NS_IF_ADDREF(background);
|
||||
*_result = background;
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStorageConnection
|
||||
|
||||
|
@ -38,12 +38,13 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef MOZSTORAGECONNECTION_H
|
||||
#define MOZSTORAGECONNECTION_H
|
||||
#ifndef mozilla_storage_Connection_h
|
||||
#define mozilla_storage_Connection_h
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsDataHashtable.h"
|
||||
@ -65,10 +66,12 @@ namespace mozilla {
|
||||
namespace storage {
|
||||
|
||||
class Connection : public mozIStorageConnection
|
||||
, public nsIInterfaceRequestor
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGECONNECTION
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
|
||||
/**
|
||||
* Structure used to describe user functions on the database connection.
|
||||
@ -244,4 +247,4 @@ private:
|
||||
} // namespace storage
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* MOZSTORAGECONNECTION_H */
|
||||
#endif // mozilla_storage_Connection_h
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "storage_test_harness.h"
|
||||
#include "prthread.h"
|
||||
#include "nsIEventTarget.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
#include "sqlite3.h"
|
||||
|
||||
@ -221,6 +222,14 @@ get_conn_async_thread(mozIStorageConnection *db)
|
||||
nsCOMPtr<nsIThread> asyncThread;
|
||||
threadMan->GetThreadFromPRThread(last_non_watched_thread,
|
||||
getter_AddRefs(asyncThread));
|
||||
|
||||
// Additionally, check that the thread we get as the background thread is the
|
||||
// same one as the one we report from getInterface.
|
||||
nsCOMPtr<nsIEventTarget> target = do_GetInterface(db);
|
||||
nsCOMPtr<nsIThread> allegedAsyncThread = do_QueryInterface(target);
|
||||
PRThread *allegedPRThread;
|
||||
(void)allegedAsyncThread->GetPRThread(&allegedPRThread);
|
||||
do_check_eq(allegedPRThread, last_non_watched_thread);
|
||||
return asyncThread.forget();
|
||||
}
|
||||
|
||||
|
@ -482,6 +482,18 @@ function test_clone_copies_overridden_functions()
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function test_getInterface()
|
||||
{
|
||||
let db = getOpenedDatabase();
|
||||
let target = db.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIEventTarget);
|
||||
// Just check that target is non-null. Other tests will ensure that it has
|
||||
// the correct value.
|
||||
do_check_true(target != null);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Test Runner
|
||||
|
||||
@ -513,6 +525,7 @@ var tests = [
|
||||
test_close_clone_fails,
|
||||
test_clone_copies_functions,
|
||||
test_clone_copies_overridden_functions,
|
||||
test_getInterface,
|
||||
];
|
||||
let index = 0;
|
||||
|
||||
|
@ -74,14 +74,6 @@ _class::HandleError(mozIStorageError *aError) \
|
||||
FAVICONSTEP_FAIL_IF_FALSE_RV(false, NS_OK); \
|
||||
}
|
||||
|
||||
#define ASYNC_STATEMENT_EMPTY_HANDLERESULT_IMPL(_class) \
|
||||
NS_IMETHODIMP \
|
||||
_class::HandleResult(mozIStorageResultSet* aResultSet) \
|
||||
{ \
|
||||
NS_NOTREACHED("Got an unexpected result?");\
|
||||
return NS_OK; \
|
||||
}
|
||||
|
||||
#define CONTENT_SNIFFING_SERVICES "content-sniffing-services"
|
||||
|
||||
/**
|
||||
@ -95,14 +87,6 @@ _class::HandleResult(mozIStorageResultSet* aResultSet) \
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AsyncFaviconStep
|
||||
|
||||
NS_IMPL_ISUPPORTS0(
|
||||
AsyncFaviconStep
|
||||
)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AsyncFaviconStepper
|
||||
|
||||
@ -263,10 +247,6 @@ AsyncFaviconStepperInternal::Cancel(bool aNotify)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// GetEffectivePageStep
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(
|
||||
GetEffectivePageStep
|
||||
, AsyncFaviconStep
|
||||
)
|
||||
ASYNC_STATEMENT_HANDLEERROR_IMPL(GetEffectivePageStep)
|
||||
|
||||
|
||||
@ -415,10 +395,6 @@ GetEffectivePageStep::CheckPageAndProceed()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// FetchDatabaseIconStep
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(
|
||||
FetchDatabaseIconStep
|
||||
, AsyncFaviconStep
|
||||
)
|
||||
ASYNC_STATEMENT_HANDLEERROR_IMPL(FetchDatabaseIconStep)
|
||||
|
||||
|
||||
@ -515,12 +491,7 @@ FetchDatabaseIconStep::HandleCompletion(PRUint16 aReason)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// EnsureDatabaseEntryStep
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(
|
||||
EnsureDatabaseEntryStep
|
||||
, AsyncFaviconStep
|
||||
)
|
||||
ASYNC_STATEMENT_HANDLEERROR_IMPL(EnsureDatabaseEntryStep)
|
||||
ASYNC_STATEMENT_EMPTY_HANDLERESULT_IMPL(EnsureDatabaseEntryStep)
|
||||
|
||||
|
||||
void
|
||||
@ -780,12 +751,7 @@ FetchNetworkIconStep::AsyncOnChannelRedirect(nsIChannel* oldChannel,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// SetFaviconDataStep
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(
|
||||
SetFaviconDataStep
|
||||
, AsyncFaviconStep
|
||||
)
|
||||
ASYNC_STATEMENT_HANDLEERROR_IMPL(SetFaviconDataStep)
|
||||
ASYNC_STATEMENT_EMPTY_HANDLERESULT_IMPL(SetFaviconDataStep)
|
||||
|
||||
|
||||
void
|
||||
@ -883,12 +849,7 @@ SetFaviconDataStep::HandleCompletion(PRUint16 aReason)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AssociateIconWithPageStep
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(
|
||||
AssociateIconWithPageStep
|
||||
, AsyncFaviconStep
|
||||
)
|
||||
ASYNC_STATEMENT_HANDLEERROR_IMPL(AssociateIconWithPageStep)
|
||||
ASYNC_STATEMENT_EMPTY_HANDLERESULT_IMPL(AssociateIconWithPageStep)
|
||||
|
||||
|
||||
void
|
||||
@ -956,12 +917,6 @@ AssociateIconWithPageStep::HandleCompletion(PRUint16 aReason)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// NotifyStep
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(
|
||||
NotifyStep
|
||||
, AsyncFaviconStep
|
||||
)
|
||||
|
||||
|
||||
void
|
||||
NotifyStep::Run()
|
||||
{
|
||||
|
@ -112,11 +112,9 @@ class AsyncFaviconStepper;
|
||||
* Executes a single async step on a favicon resource.
|
||||
* Once done, call backs to the stepper to proceed to the next step.
|
||||
*/
|
||||
class AsyncFaviconStep : public nsISupports
|
||||
class AsyncFaviconStep : public AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
AsyncFaviconStep() {}
|
||||
|
||||
/**
|
||||
@ -136,7 +134,6 @@ protected:
|
||||
nsCOMPtr<AsyncFaviconStepperInternal> mStepper;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Status definitions for the stepper.
|
||||
*/
|
||||
@ -276,10 +273,8 @@ private:
|
||||
* associate it with.
|
||||
*/
|
||||
class GetEffectivePageStep : public AsyncFaviconStep
|
||||
, public mozilla::places::AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
|
||||
GetEffectivePageStep();
|
||||
@ -297,10 +292,8 @@ private:
|
||||
* Fetch an existing icon and associated information from the database.
|
||||
*/
|
||||
class FetchDatabaseIconStep : public AsyncFaviconStep
|
||||
, public mozilla::places::AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
|
||||
FetchDatabaseIconStep() {};
|
||||
@ -313,11 +306,10 @@ public:
|
||||
* Requires mDBInsertIcon statement.
|
||||
*/
|
||||
class EnsureDatabaseEntryStep : public AsyncFaviconStep
|
||||
, public mozilla::places::AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
NS_IMETHOD HandleCompletion(PRUint16 aReason);
|
||||
NS_IMETHOD HandleError(mozIStorageError* aError);
|
||||
|
||||
EnsureDatabaseEntryStep() {};
|
||||
void Run();
|
||||
@ -361,11 +353,10 @@ private:
|
||||
* Saves icon data in the database if it has changed.
|
||||
*/
|
||||
class SetFaviconDataStep : public AsyncFaviconStep
|
||||
, public mozilla::places::AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
NS_IMETHOD HandleCompletion(PRUint16 aReason);
|
||||
NS_IMETHOD HandleError(mozIStorageError* aError);
|
||||
|
||||
SetFaviconDataStep() {};
|
||||
void Run();
|
||||
@ -376,11 +367,10 @@ public:
|
||||
* Associate icon with page.
|
||||
*/
|
||||
class AssociateIconWithPageStep : public AsyncFaviconStep
|
||||
, public mozilla::places::AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
NS_IMETHOD HandleCompletion(PRUint16 aReason);
|
||||
NS_IMETHOD HandleError(mozIStorageError* aError);
|
||||
|
||||
AssociateIconWithPageStep() {};
|
||||
void Run();
|
||||
@ -393,8 +383,6 @@ public:
|
||||
class NotifyStep : public AsyncFaviconStep
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NotifyStep() {};
|
||||
void Run();
|
||||
};
|
||||
|
@ -47,6 +47,24 @@ namespace places {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AsyncStatementCallback
|
||||
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
AsyncStatementCallback
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncStatementCallback::HandleResult(mozIStorageResultSet *aResultSet)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(false, "Was not expecting a resultset, but got it.");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncStatementCallback::HandleCompletion(PRUint16 aReason)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AsyncStatementCallback::HandleError(mozIStorageError *aError)
|
||||
{
|
||||
|
@ -55,13 +55,17 @@ namespace places {
|
||||
class AsyncStatementCallback : public mozIStorageStatementCallback
|
||||
{
|
||||
public:
|
||||
// Implement the error handler for asynchronous statements.
|
||||
NS_IMETHOD HandleError(mozIStorageError *aError);
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
AsyncStatementCallback() {}
|
||||
|
||||
protected:
|
||||
virtual ~AsyncStatementCallback() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Macro to use in place of NS_DECL_MOZISTORAGESTATEMENTCALLBACK to declare the
|
||||
* methods this class does not implement.
|
||||
* Macros to use in place of NS_DECL_MOZISTORAGESTATEMENTCALLBACK to declare the
|
||||
* methods this class assumes silent or notreached.
|
||||
*/
|
||||
#define NS_DECL_ASYNCSTATEMENTCALLBACK \
|
||||
NS_IMETHOD HandleResult(mozIStorageResultSet *); \
|
||||
@ -71,6 +75,24 @@ public:
|
||||
* Macros to use for lazy statements initialization in Places services that use
|
||||
* GetStatement() method.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#define RETURN_IF_STMT(_stmt, _sql) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (address_of(_stmt) == address_of(aStmt)) { \
|
||||
if (!_stmt) { \
|
||||
nsresult rv = mDBConn->CreateStatement(_sql, getter_AddRefs(_stmt)); \
|
||||
if (NS_FAILED(rv)) { \
|
||||
nsCAutoString err; \
|
||||
(void)mDBConn->GetLastErrorString(err); \
|
||||
(void)fprintf(stderr, "$$$ compiling statement failed with '%s'\n", \
|
||||
err.get()); \
|
||||
} \
|
||||
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && _stmt, nsnull); \
|
||||
} \
|
||||
return _stmt.get(); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
#else
|
||||
#define RETURN_IF_STMT(_stmt, _sql) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (address_of(_stmt) == address_of(aStmt)) { \
|
||||
@ -81,6 +103,7 @@ public:
|
||||
return _stmt.get(); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
#endif
|
||||
|
||||
// Async statements don't need to be scoped, they are reset when done.
|
||||
// So use this version for statements used async, scoped version for statements
|
||||
|
@ -159,11 +159,9 @@ Step::HandleCompletion(PRUint16 aReason)
|
||||
|
||||
namespace {
|
||||
|
||||
class VisitedQuery : public mozIStorageStatementCallback
|
||||
class VisitedQuery : public AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
static nsresult Start(nsIURI* aURI)
|
||||
{
|
||||
NS_PRECONDITION(aURI, "Null URI");
|
||||
@ -172,7 +170,7 @@ public:
|
||||
// If we are a content process, always remote the request to the
|
||||
// parent process.
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
mozilla::dom::ContentChild * cpc =
|
||||
mozilla::dom::ContentChild* cpc =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
NS_ASSERTION(cpc, "Content Protocol is NULL!");
|
||||
(void)cpc->SendStartVisitedQuery(aURI);
|
||||
@ -180,9 +178,8 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
nsNavHistory* navHist = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(navHist, NS_ERROR_FAILURE);
|
||||
mozIStorageStatement* stmt = navHist->GetStatementById(DB_IS_PAGE_VISITED);
|
||||
mozIStorageAsyncStatement* stmt =
|
||||
History::GetService()->GetIsVisitedStatement();
|
||||
NS_ENSURE_STATE(stmt);
|
||||
|
||||
// Bind by index for performance.
|
||||
@ -250,10 +247,6 @@ private:
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
bool mIsVisited;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
VisitedQuery,
|
||||
mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Fail-safe mechanism for ensuring that your task completes, no matter what.
|
||||
@ -266,7 +259,7 @@ class FailSafeFinishTask
|
||||
{
|
||||
public:
|
||||
FailSafeFinishTask()
|
||||
: mAppended(false)
|
||||
: mAppended(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -315,8 +308,6 @@ struct VisitURIData : public FailSafeFinishTask
|
||||
class UpdateFrecencyAndNotifyStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
UpdateFrecencyAndNotifyStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -346,10 +337,7 @@ public:
|
||||
NS_WARN_IF_FALSE(bookmarks, "Could not get bookmarks service");
|
||||
if (history && bookmarks) {
|
||||
// Update frecency *after* the visit info is in the db
|
||||
nsresult rv = history->UpdateFrecency(
|
||||
mData->placeId,
|
||||
bookmarks->IsRealBookmark(mData->placeId)
|
||||
);
|
||||
nsresult rv = history->UpdateFrecency(mData->placeId);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Could not update frecency");
|
||||
|
||||
// Notify nsNavHistory observers of visit, but only for certain types of
|
||||
@ -378,10 +366,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
UpdateFrecencyAndNotifyStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 5: Get newly created visit ID from moz_history_visits table.
|
||||
@ -389,8 +373,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class GetVisitIDStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
GetVisitIDStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -419,10 +401,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
GetVisitIDStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 4: Add visit to moz_history_visits table.
|
||||
@ -430,8 +408,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class AddVisitStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
AddVisitStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -509,10 +485,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
AddVisitStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 3: Callback for inserting or updating a moz_places entry.
|
||||
@ -521,8 +493,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class CheckLastVisitStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
CheckLastVisitStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -574,10 +544,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
CheckLastVisitStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 2a: Called only when a new entry is put into moz_places.
|
||||
@ -586,8 +552,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class FindNewIdStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
FindNewIdStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -615,10 +579,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
FindNewIdStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 2: Callback for checking for an existing URI in moz_places.
|
||||
@ -627,8 +587,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class CheckExistingStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
CheckExistingStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -712,10 +670,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
CheckExistingStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 1: See if there is an existing URI.
|
||||
@ -723,8 +677,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class StartVisitURIStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
StartVisitURIStep(nsAutoPtr<VisitURIData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -755,10 +707,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<VisitURIData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
StartVisitURIStep
|
||||
, Step
|
||||
)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Steps for SetURITitle
|
||||
@ -775,8 +723,6 @@ struct SetTitleData : public FailSafeFinishTask
|
||||
class TitleNotifyStep: public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
TitleNotifyStep(nsAutoPtr<SetTitleData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -794,10 +740,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<SetTitleData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
TitleNotifyStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 2: Set title.
|
||||
@ -805,8 +747,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class SetTitleStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
SetTitleStep(nsAutoPtr<SetTitleData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -865,10 +805,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<SetTitleData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
SetTitleStep
|
||||
, mozIStorageStatementCallback
|
||||
)
|
||||
|
||||
/**
|
||||
* Step 1: See if there is an existing URI.
|
||||
@ -876,8 +812,6 @@ NS_IMPL_ISUPPORTS1(
|
||||
class StartSetURITitleStep : public Step
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
StartSetURITitleStep(nsAutoPtr<SetTitleData> aData)
|
||||
: mData(aData)
|
||||
{
|
||||
@ -907,10 +841,6 @@ public:
|
||||
protected:
|
||||
nsAutoPtr<SetTitleData> mData;
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
StartSetURITitleStep
|
||||
, Step
|
||||
)
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
@ -1021,6 +951,37 @@ History::NotifyVisited(nsIURI* aURI)
|
||||
mObservers.RemoveEntry(aURI);
|
||||
}
|
||||
|
||||
mozIStorageAsyncStatement*
|
||||
History::GetIsVisitedStatement()
|
||||
{
|
||||
if (mIsVisitedStatement) {
|
||||
return mIsVisitedStatement;
|
||||
}
|
||||
|
||||
// If we don't yet have a database connection, go ahead and clone it now.
|
||||
if (!mReadOnlyDBConn) {
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, nsnull);
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> dbConn;
|
||||
(void)history->GetDBConnection(getter_AddRefs(dbConn));
|
||||
NS_ENSURE_TRUE(dbConn, nsnull);
|
||||
|
||||
(void)dbConn->Clone(PR_TRUE, getter_AddRefs(mReadOnlyDBConn));
|
||||
NS_ENSURE_TRUE(mReadOnlyDBConn, nsnull);
|
||||
}
|
||||
|
||||
// Now we can create our cached statement.
|
||||
nsresult rv = mReadOnlyDBConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id "
|
||||
"FROM moz_places h "
|
||||
"WHERE url = ?1 "
|
||||
"AND EXISTS(SELECT id FROM moz_historyvisits WHERE place_id = h.id LIMIT 1) "
|
||||
), getter_AddRefs(mIsVisitedStatement));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
return mIsVisitedStatement;
|
||||
}
|
||||
|
||||
/* static */
|
||||
History*
|
||||
History::GetService()
|
||||
@ -1075,6 +1036,14 @@ History::Shutdown()
|
||||
nsCOMPtr<Step> deadTaskWalking =
|
||||
dont_AddRef(static_cast<Step*>(mPendingVisits.PopFront()));
|
||||
}
|
||||
|
||||
// Clean up our statements and connection.
|
||||
if (mReadOnlyDBConn) {
|
||||
if (mIsVisitedStatement) {
|
||||
(void)mIsVisitedStatement->Finalize();
|
||||
}
|
||||
(void)mReadOnlyDBConn->AsyncClose(nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -48,6 +48,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsDeque.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
@ -71,7 +72,7 @@ public:
|
||||
* @param aURI
|
||||
* The URI to notify about.
|
||||
*/
|
||||
void NotifyVisited(nsIURI *aURI);
|
||||
void NotifyVisited(nsIURI* aURI);
|
||||
|
||||
/**
|
||||
* Append a task to the queue for SQL queries that need to happen
|
||||
@ -93,19 +94,38 @@ public:
|
||||
*/
|
||||
void CurrentTaskFinished();
|
||||
|
||||
/**
|
||||
* Obtains the statement to use to check if a URI is visited or not.
|
||||
*/
|
||||
mozIStorageAsyncStatement* GetIsVisitedStatement();
|
||||
|
||||
/**
|
||||
* Obtains a pointer to this service.
|
||||
*/
|
||||
static History *GetService();
|
||||
static History* GetService();
|
||||
|
||||
/**
|
||||
* Obtains a pointer that has had AddRef called on it. Used by the service
|
||||
* manager only.
|
||||
*/
|
||||
static History *GetSingleton();
|
||||
static History* GetSingleton();
|
||||
|
||||
private:
|
||||
~History();
|
||||
virtual ~History();
|
||||
|
||||
/**
|
||||
* A read-only database connection used for checking if a URI is visited.
|
||||
*
|
||||
* @note this should only be accessed by GetIsVisistedStatement and Shutdown.
|
||||
*/
|
||||
nsCOMPtr<mozIStorageConnection> mReadOnlyDBConn;
|
||||
|
||||
/**
|
||||
* An asynchronous statement to query if a URI is visited or not.
|
||||
*
|
||||
* @note this should only be accessed by GetIsVisistedStatement and Shutdown.
|
||||
*/
|
||||
nsCOMPtr<mozIStorageAsyncStatement> mIsVisitedStatement;
|
||||
|
||||
/**
|
||||
* Since visits rapidly fire at once, it's very likely to have race
|
||||
@ -132,21 +152,21 @@ private:
|
||||
*/
|
||||
void Shutdown();
|
||||
|
||||
static History *gService;
|
||||
static History* gService;
|
||||
|
||||
// Ensures new tasks aren't started on destruction.
|
||||
bool mShuttingDown;
|
||||
|
||||
typedef nsTArray<mozilla::dom::Link *> ObserverArray;
|
||||
typedef nsTArray<mozilla::dom::Link* > ObserverArray;
|
||||
|
||||
class KeyClass : public nsURIHashKey
|
||||
{
|
||||
public:
|
||||
KeyClass(const nsIURI *aURI)
|
||||
KeyClass(const nsIURI* aURI)
|
||||
: nsURIHashKey(aURI)
|
||||
{
|
||||
}
|
||||
KeyClass(const KeyClass &aOther)
|
||||
KeyClass(const KeyClass& aOther)
|
||||
: nsURIHashKey(aOther)
|
||||
{
|
||||
NS_NOTREACHED("Do not call me!");
|
||||
|
@ -82,11 +82,13 @@ EXTRA_DSO_LDOPTS += \
|
||||
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../../build
|
||||
|
||||
# This is the default value. Must be in sync with the one defined in SQLite.
|
||||
DEFINES += -DSQLITE_DEFAULT_PAGE_SIZE=32768
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
toolkitplaces.manifest \
|
||||
nsLivemarkService.js \
|
||||
nsTaggingService.js \
|
||||
nsPlacesDBFlush.js \
|
||||
nsPlacesExpiration.js \
|
||||
nsMicrosummaryService.js \
|
||||
PlacesCategoriesStarter.js \
|
||||
|
@ -126,8 +126,6 @@ nsPlacesDBUtils.prototype = {
|
||||
"DELETE FROM moz_annos WHERE id IN ( " +
|
||||
"SELECT id FROM moz_annos a " +
|
||||
"WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places_temp WHERE id = a.place_id LIMIT 1) " +
|
||||
"AND NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = a.place_id LIMIT 1) " +
|
||||
")");
|
||||
cleanupStatements.push(deleteOrphanAnnos);
|
||||
@ -202,7 +200,6 @@ nsPlacesDBUtils.prototype = {
|
||||
") AND id IN (" +
|
||||
"SELECT b.id FROM moz_bookmarks b " +
|
||||
"WHERE fk NOT NULL AND b.type = :bookmark_type " +
|
||||
"AND NOT EXISTS (SELECT url FROM moz_places_temp WHERE id = b.fk LIMIT 1) " +
|
||||
"AND NOT EXISTS (SELECT url FROM moz_places WHERE id = b.fk LIMIT 1) " +
|
||||
")");
|
||||
deleteNoPlaceItems.params["bookmark_type"] = PlacesUtils.bookmarks.TYPE_BOOKMARK;
|
||||
@ -361,7 +358,6 @@ nsPlacesDBUtils.prototype = {
|
||||
// D.11 remove old livemarks status items
|
||||
// Livemark status items are now static but some livemark has still old
|
||||
// status items bookmarks inside it. We should remove them.
|
||||
// Note: This does not need to query the temp table.
|
||||
let removeLivemarkStaticItems = DBConn.createStatement(
|
||||
"DELETE FROM moz_bookmarks WHERE type = :bookmark_type AND fk IN ( " +
|
||||
"SELECT id FROM moz_places WHERE url = :lmloading OR url = :lmfailed " +
|
||||
@ -390,8 +386,6 @@ nsPlacesDBUtils.prototype = {
|
||||
"DELETE FROM moz_favicons WHERE id IN (" +
|
||||
"SELECT id FROM moz_favicons f " +
|
||||
"WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places_temp WHERE favicon_id = f.id LIMIT 1) " +
|
||||
"AND NOT EXISTS" +
|
||||
"(SELECT id FROM moz_places WHERE favicon_id = f.id LIMIT 1) " +
|
||||
")");
|
||||
cleanupStatements.push(deleteOrphanIcons);
|
||||
@ -402,8 +396,6 @@ nsPlacesDBUtils.prototype = {
|
||||
"DELETE FROM moz_historyvisits WHERE id IN (" +
|
||||
"SELECT id FROM moz_historyvisits v " +
|
||||
"WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places_temp WHERE id = v.place_id LIMIT 1) " +
|
||||
"AND NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = v.place_id LIMIT 1) " +
|
||||
")");
|
||||
cleanupStatements.push(deleteOrphanVisits);
|
||||
@ -414,8 +406,6 @@ nsPlacesDBUtils.prototype = {
|
||||
"DELETE FROM moz_inputhistory WHERE place_id IN (" +
|
||||
"SELECT place_id FROM moz_inputhistory i " +
|
||||
"WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places_temp WHERE id = i.place_id LIMIT 1) " +
|
||||
"AND NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = i.place_id LIMIT 1) " +
|
||||
")");
|
||||
cleanupStatements.push(deleteOrphanInputHistory);
|
||||
@ -463,22 +453,17 @@ nsPlacesDBUtils.prototype = {
|
||||
|
||||
/* XXX needs test
|
||||
// L.2 recalculate visit_count
|
||||
// We're detecting errors only in disk table since temp tables could have
|
||||
// different values based on the number of visits not yet synced to disk.
|
||||
let detectWrongCountPlaces = DBConn.createStatement(
|
||||
"SELECT id FROM moz_places h " +
|
||||
"WHERE id NOT IN (SELECT id FROM moz_places_temp) " +
|
||||
"AND h.visit_count <> " +
|
||||
"WHERE h.visit_count <> " +
|
||||
"(SELECT count(*) FROM moz_historyvisits " +
|
||||
"WHERE place_id = h.id AND visit_type NOT IN (0,4,7,8))");
|
||||
while (detectWrongCountPlaces.executeStep()) {
|
||||
let placeId = detectWrongCountPlaces.getInt64(0);
|
||||
let fixCountForPlace = DBConn.createStatement(
|
||||
"UPDATE moz_places_view SET visit_count = ( " +
|
||||
"UPDATE moz_places SET visit_count = ( " +
|
||||
"(SELECT count(*) FROM moz_historyvisits " +
|
||||
"WHERE place_id = :place_id AND visit_type NOT IN (0,4,7,8)) + " +
|
||||
"(SELECT count(*) FROM moz_historyvisits_temp " +
|
||||
"WHERE place_id = :place_id AND visit_type NOT IN (0,4,7,8)) + " +
|
||||
"WHERE place_id = :place_id AND visit_type NOT IN (0,4,7,8)) + "
|
||||
") WHERE id = :place_id");
|
||||
fixCountForPlace.params["place_id"] = placeId;
|
||||
cleanupStatements.push(fixCountForPlace);
|
||||
|
@ -150,7 +150,6 @@ var PlacesUtils = {
|
||||
TOPIC_DATABASE_LOCKED: "places-database-locked",
|
||||
TOPIC_EXPIRATION_FINISHED: "places-expiration-finished",
|
||||
TOPIC_FEEDBACK_UPDATED: "places-autocomplete-feedback-updated",
|
||||
TOPIC_SYNC_FINISHED: "places-sync-finished",
|
||||
TOPIC_FAVICONS_EXPIRED: "places-favicons-expired",
|
||||
TOPIC_VACUUM_STARTING: "places-vacuum-starting",
|
||||
|
||||
|
@ -43,6 +43,10 @@
|
||||
#include "nsEscape.h"
|
||||
#include "mozIPlacesAutoComplete.h"
|
||||
#include "SQLFunctions.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsINavHistoryService.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsNavHistory.h"
|
||||
|
||||
using namespace mozilla::storage;
|
||||
|
||||
@ -294,5 +298,178 @@ namespace places {
|
||||
#undef HAS_BEHAVIOR
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Frecency Calculation Function
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// CalculateFrecencyFunction
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
CalculateFrecencyFunction::create(mozIStorageConnection *aDBConn)
|
||||
{
|
||||
nsCOMPtr<CalculateFrecencyFunction> function =
|
||||
new CalculateFrecencyFunction();
|
||||
NS_ENSURE_TRUE(function, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = aDBConn->CreateFunction(
|
||||
NS_LITERAL_CSTRING("calculate_frecency"), 1, function
|
||||
);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(
|
||||
CalculateFrecencyFunction,
|
||||
mozIStorageFunction
|
||||
)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStorageFunction
|
||||
|
||||
NS_IMETHODIMP
|
||||
CalculateFrecencyFunction::OnFunctionCall(mozIStorageValueArray *aArguments,
|
||||
nsIVariant **_result)
|
||||
{
|
||||
// Fetch arguments. Use default values if they were omitted.
|
||||
PRUint32 numEntries;
|
||||
nsresult rv = aArguments->GetNumEntries(&numEntries);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ASSERTION(numEntries > 0, "unexpected number of arguments");
|
||||
|
||||
PRInt64 pageId = aArguments->AsInt64(0);
|
||||
PRInt32 typed = numEntries > 1 ? aArguments->AsInt32(1) : 0;
|
||||
PRInt32 fullVisitCount = numEntries > 2 ? aArguments->AsInt32(2) : 0;
|
||||
PRInt64 bookmarkId = numEntries > 3 ? aArguments->AsInt64(3) : 0;
|
||||
PRInt32 visitCount = 0;
|
||||
PRInt32 hidden = 0;
|
||||
PRInt32 isQuery = 0;
|
||||
float pointsForSampledVisits = 0.0;
|
||||
|
||||
// This is a const version of the history object for thread-safety.
|
||||
const nsNavHistory* history = nsNavHistory::GetConstHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (pageId > 0) {
|
||||
// The page is already in the database, and we can fetch current
|
||||
// params from the database.
|
||||
nsCOMPtr<mozIStorageStatement> getPageInfo =
|
||||
history->GetStatementByStoragePool(DB_PAGE_INFO_FOR_FRECENCY);
|
||||
NS_ENSURE_STATE(getPageInfo);
|
||||
mozStorageStatementScoper infoScoper(getPageInfo);
|
||||
|
||||
rv = getPageInfo->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = getPageInfo->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"),
|
||||
NS_LITERAL_CSTRING("livemark/feedURI"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasResult;
|
||||
rv = getPageInfo->ExecuteStep(&hasResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(hasResult, NS_ERROR_UNEXPECTED);
|
||||
rv = getPageInfo->GetInt32(0, &typed);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = getPageInfo->GetInt32(1, &hidden);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = getPageInfo->GetInt32(2, &visitCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = getPageInfo->GetInt32(3, &fullVisitCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = getPageInfo->GetInt64(4, &bookmarkId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = getPageInfo->GetInt32(5, &isQuery);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get a sample of the last visits to the page, to calculate its weight.
|
||||
nsCOMPtr<mozIStorageStatement> getVisits =
|
||||
history->GetStatementByStoragePool(DB_VISITS_FOR_FRECENCY);
|
||||
NS_ENSURE_STATE(getVisits);
|
||||
mozStorageStatementScoper visitsScoper(getVisits);
|
||||
|
||||
rv = getVisits->BindInt64ByName(NS_LITERAL_CSTRING("page_id"), pageId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 numSampledVisits = 0;
|
||||
// The visits query is already limited to the last N visits.
|
||||
while (NS_SUCCEEDED(getVisits->ExecuteStep(&hasResult)) && hasResult) {
|
||||
numSampledVisits++;
|
||||
|
||||
PRInt32 visitType;
|
||||
rv = getVisits->GetInt32(1, &visitType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt32 bonus = history->GetFrecencyTransitionBonus(visitType, true);
|
||||
|
||||
// Always add the bookmark visit bonus.
|
||||
if (bookmarkId) {
|
||||
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_BOOKMARK, true);
|
||||
}
|
||||
|
||||
// If bonus was zero, we can skip the work to determine the weight.
|
||||
if (bonus) {
|
||||
PRInt32 ageInDays = getVisits->AsInt32(0);
|
||||
PRInt32 weight = history->GetFrecencyAgedWeight(ageInDays);
|
||||
pointsForSampledVisits += (float)(weight * (bonus / 100.0));
|
||||
}
|
||||
}
|
||||
|
||||
// If we found some visits for this page, use the calculated weight.
|
||||
if (numSampledVisits) {
|
||||
// fix for bug #412219
|
||||
if (!pointsForSampledVisits) {
|
||||
// For URIs with zero points in the sampled recent visits
|
||||
// but "browsing" type visits outside the sampling range, set
|
||||
// frecency to -visit_count, so they're still shown in autocomplete.
|
||||
NS_IF_ADDREF(*_result = new IntegerVariant(-visitCount));
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
// Estimate frecency using the last few visits.
|
||||
// Use NS_ceilf() so that we don't round down to 0, which
|
||||
// would cause us to completely ignore the place during autocomplete.
|
||||
NS_IF_ADDREF(*_result = new IntegerVariant((PRInt32) NS_ceilf(fullVisitCount * NS_ceilf(pointsForSampledVisits) / numSampledVisits)));
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// This page is unknown or has no visits. It could have just been added, so
|
||||
// use passed in or default values.
|
||||
|
||||
// The code below works well for guessing the frecency on import, and we'll
|
||||
// correct later once we have visits.
|
||||
// TODO: What if we don't have visits and we never visit? We could end up
|
||||
// with a really high value that keeps coming up in ac results? Should we
|
||||
// only do this on import? Have to figure it out.
|
||||
PRInt32 bonus = 0;
|
||||
|
||||
// Make it so something bookmarked and typed will have a higher frecency
|
||||
// than something just typed or just bookmarked.
|
||||
if (bookmarkId && !isQuery) {
|
||||
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_BOOKMARK, false);;
|
||||
// For unvisited bookmarks, produce a non-zero frecency, so that they show
|
||||
// up in URL bar autocomplete.
|
||||
fullVisitCount = 1;
|
||||
}
|
||||
|
||||
if (typed) {
|
||||
bonus += history->GetFrecencyTransitionBonus(nsINavHistoryService::TRANSITION_TYPED, false);
|
||||
}
|
||||
|
||||
// Assume "now" as our ageInDays, so use the first bucket.
|
||||
pointsForSampledVisits = history->GetFrecencyBucketWeight(1) * (bonus / (float)100.0);
|
||||
|
||||
// use NS_ceilf() so that we don't round down to 0, which
|
||||
// would cause us to completely ignore the place during autocomplete
|
||||
NS_IF_ADDREF(*_result = new IntegerVariant((PRInt32) NS_ceilf(fullVisitCount * NS_ceilf(pointsForSampledVisits))));
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace places
|
||||
} // namespace mozilla
|
||||
|
@ -208,6 +208,43 @@ private:
|
||||
static void fixupURISpec(const nsCString &aURISpec, nsString &_fixedSpec);
|
||||
};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Frecency Calculation Function
|
||||
|
||||
/**
|
||||
* This function is used to calculate frecency for a page.
|
||||
*
|
||||
* In SQL, you'd use it in when setting frecency like:
|
||||
* SET frecency = CALCULATE_FRECENCY(place_id).
|
||||
* Optional parameters must be passed in if the page is not yet in the database,
|
||||
* otherwise they will be fetched from it automatically.
|
||||
*
|
||||
* @param pageId
|
||||
* The id of the page. Pass -1 if the page is being added right now.
|
||||
* @param [optional] typed
|
||||
* Whether the page has been typed in. Default is false.
|
||||
* @param [optional] fullVisitCount
|
||||
* Count of all the visits (All types). Default is 0.
|
||||
* @param [optional] isBookmarked
|
||||
* Whether the page is bookmarked. Default is false.
|
||||
*/
|
||||
class CalculateFrecencyFunction : public mozIStorageFunction
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGEFUNCTION
|
||||
|
||||
/**
|
||||
* Registers the function with the specified database connection.
|
||||
*
|
||||
* @param aDBConn
|
||||
* The database connection to register with.
|
||||
*/
|
||||
static nsresult create(mozIStorageConnection *aDBConn);
|
||||
};
|
||||
|
||||
} // namespace places
|
||||
} // namespace storage
|
||||
|
||||
|
@ -103,7 +103,7 @@ class faviconAsyncLoader : public AsyncStatementCallback
|
||||
, public nsIRequestObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
faviconAsyncLoader(nsIChannel *aChannel, nsIOutputStream *aOutputStream) :
|
||||
mChannel(aChannel)
|
||||
@ -219,9 +219,9 @@ private:
|
||||
bool mReturnDefaultIcon;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(
|
||||
NS_IMPL_ISUPPORTS_INHERITED1(
|
||||
faviconAsyncLoader,
|
||||
mozIStorageStatementCallback,
|
||||
AsyncStatementCallback,
|
||||
nsIRequestObserver
|
||||
)
|
||||
|
||||
|
@ -136,23 +136,17 @@ nsAnnotationService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
"SELECT n.name "
|
||||
"FROM moz_anno_attributes n "
|
||||
"JOIN moz_annos a ON a.anno_attribute_id = n.id "
|
||||
"JOIN ( "
|
||||
"SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
") AS h ON h.id = a.place_id"));
|
||||
"JOIN moz_places h ON h.id = a.place_id "
|
||||
"WHERE h.url = :page_url"));
|
||||
|
||||
RETURN_IF_STMT(mDBGetPageAnnotationValue, NS_LITERAL_CSTRING(
|
||||
"SELECT a.id, a.place_id, :anno_name, a.mime_type, a.content, a.flags, "
|
||||
"a.expiration, a.type "
|
||||
"FROM moz_anno_attributes n "
|
||||
"JOIN moz_annos a ON n.id = a.anno_attribute_id "
|
||||
"JOIN ( "
|
||||
"SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
") AS h ON h.id = a.place_id "
|
||||
"WHERE n.name = :anno_name"));
|
||||
"JOIN moz_places h ON h.id = a.place_id "
|
||||
"WHERE h.url = :page_url "
|
||||
"AND n.name = :anno_name"));
|
||||
|
||||
RETURN_IF_STMT(mDBGetItemAnnotationValue, NS_LITERAL_CSTRING(
|
||||
"SELECT a.id, a.item_id, :anno_name, a.mime_type, a.content, a.flags, "
|
||||
@ -181,26 +175,22 @@ nsAnnotationService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
|
||||
RETURN_IF_STMT(mDBRemovePageAnnotation, NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_annos "
|
||||
"WHERE place_id = ( "
|
||||
"SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url) "
|
||||
"AND anno_attribute_id = "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)"));
|
||||
"WHERE place_id = (SELECT id FROM moz_places WHERE url = :page_url) "
|
||||
"AND anno_attribute_id = "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)"));
|
||||
|
||||
RETURN_IF_STMT(mDBRemoveItemAnnotation, NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_items_annos "
|
||||
"WHERE item_id = :item_id "
|
||||
"AND anno_attribute_id = "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)"));
|
||||
"AND anno_attribute_id = "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name)"));
|
||||
|
||||
RETURN_IF_STMT(mDBGetPagesWithAnnotation, NS_LITERAL_CSTRING(
|
||||
"SELECT IFNULL(h_t.url, h.url) AS coalesced_url "
|
||||
"SELECT h.url "
|
||||
"FROM moz_anno_attributes n "
|
||||
"JOIN moz_annos a ON n.id = a.anno_attribute_id "
|
||||
"LEFT JOIN moz_places h ON h.id = a.place_id "
|
||||
"LEFT JOIN moz_places_temp h_t ON h_t.id = a.place_id "
|
||||
"WHERE n.name = :anno_name AND coalesced_url NOT NULL"));
|
||||
"JOIN moz_places h ON h.id = a.place_id "
|
||||
"WHERE n.name = :anno_name"));
|
||||
|
||||
RETURN_IF_STMT(mDBGetItemsWithAnnotation, NS_LITERAL_CSTRING(
|
||||
"SELECT a.item_id "
|
||||
@ -212,12 +202,10 @@ nsAnnotationService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
"SELECT h.id, "
|
||||
"(SELECT id FROM moz_anno_attributes WHERE name = :anno_name) AS nameid, "
|
||||
"a.id, a.dateAdded "
|
||||
"FROM (SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
") AS h "
|
||||
"FROM moz_places h "
|
||||
"LEFT JOIN moz_annos a ON a.place_id = h.id "
|
||||
"AND a.anno_attribute_id = nameid"));
|
||||
"AND a.anno_attribute_id = nameid "
|
||||
"WHERE h.url = :page_url"));
|
||||
|
||||
RETURN_IF_STMT(mDBCheckItemAnnotation, NS_LITERAL_CSTRING(
|
||||
"SELECT b.id, "
|
||||
@ -1582,9 +1570,7 @@ nsAnnotationService::RemovePageAnnotations(nsIURI* aURI)
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_annos WHERE place_id = "
|
||||
"(SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url)"),
|
||||
"(SELECT id FROM moz_places WHERE url = :page_url)"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = URIBinder::Bind(statement, NS_LITERAL_CSTRING("page_url"), aURI);
|
||||
@ -1644,18 +1630,13 @@ nsAnnotationService::CopyPageAnnotations(nsIURI* aSourceURI,
|
||||
nsCOMPtr<mozIStorageStatement> sourceStmt;
|
||||
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT h.id, n.id, n.name, a2.id "
|
||||
"FROM ( "
|
||||
"SELECT id from moz_places_temp WHERE url = :source_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :source_url "
|
||||
") AS h "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_annos a ON a.place_id = h.id "
|
||||
"JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
|
||||
"LEFT JOIN moz_annos a2 ON a2.place_id = ( "
|
||||
"SELECT id FROM moz_places_temp WHERE url = :dest_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :dest_url "
|
||||
") AND a2.anno_attribute_id = n.id"),
|
||||
"LEFT JOIN moz_annos a2 ON a2.place_id = "
|
||||
"(SELECT id FROM moz_places WHERE url = :dest_url) "
|
||||
"AND a2.anno_attribute_id = n.id "
|
||||
"WHERE url = :source_url"),
|
||||
getter_AddRefs(sourceStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
@ -1669,12 +1650,9 @@ nsAnnotationService::CopyPageAnnotations(nsIURI* aSourceURI,
|
||||
"INSERT INTO moz_annos "
|
||||
"(place_id, anno_attribute_id, mime_type, content, flags, expiration, "
|
||||
"type, dateAdded, lastModified) "
|
||||
"SELECT ( "
|
||||
"SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
"), anno_attribute_id, mime_type, content, flags, expiration, type, "
|
||||
":date, :date "
|
||||
"SELECT (SELECT id FROM moz_places WHERE url = :page_url), "
|
||||
"anno_attribute_id, mime_type, content, flags, expiration, type, "
|
||||
":date, :date "
|
||||
"FROM moz_annos "
|
||||
"WHERE place_id = :page_id "
|
||||
"AND anno_attribute_id = :name_id"),
|
||||
|
@ -97,8 +97,7 @@ class ExpireFaviconsStatementCallbackNotifier : public AsyncStatementCallback
|
||||
{
|
||||
public:
|
||||
ExpireFaviconsStatementCallbackNotifier(bool* aFaviconsExpirationRunning);
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_ASYNCSTATEMENTCALLBACK
|
||||
NS_IMETHOD HandleCompletion(PRUint16 aReason);
|
||||
|
||||
private:
|
||||
bool* mFaviconsExpirationRunning;
|
||||
@ -171,30 +170,20 @@ nsFaviconService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
RETURN_IF_STMT(mDBGetIconInfoWithPage, NS_LITERAL_CSTRING(
|
||||
"SELECT id, length(data), expiration, data, mime_type, "
|
||||
"IFNULL(url = (SELECT f.url "
|
||||
"FROM ( "
|
||||
"SELECT favicon_id FROM moz_places_temp "
|
||||
"WHERE url = :page_url "
|
||||
"UNION ALL "
|
||||
"SELECT favicon_id FROM moz_places "
|
||||
"WHERE url = :page_url "
|
||||
") AS h "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
"WHERE h.url = :page_url "
|
||||
"LIMIT 1), "
|
||||
"0)"
|
||||
"0) "
|
||||
"FROM moz_favicons WHERE url = :icon_url"));
|
||||
|
||||
RETURN_IF_STMT(mDBGetURL, NS_LITERAL_CSTRING(
|
||||
"SELECT f.id, f.url, length(f.data), f.expiration "
|
||||
"FROM ( "
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places_temp "
|
||||
"WHERE url = :page_url "
|
||||
"UNION ALL "
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places "
|
||||
"WHERE url = :page_url "
|
||||
") AS h JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
"WHERE h.url = :page_url "
|
||||
"LIMIT 1"));
|
||||
|
||||
|
||||
RETURN_IF_STMT(mDBGetData, NS_LITERAL_CSTRING(
|
||||
"SELECT f.data, f.mime_type FROM moz_favicons f WHERE url = :icon_url"));
|
||||
|
||||
@ -208,10 +197,10 @@ nsFaviconService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
"WHERE id = :icon_id"));
|
||||
|
||||
RETURN_IF_STMT(mDBSetPageFavicon, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_places_view SET favicon_id = :icon_id WHERE id = :page_id"));
|
||||
"UPDATE moz_places SET favicon_id = :icon_id WHERE id = :page_id"));
|
||||
|
||||
RETURN_IF_STMT(mDBAssociateFaviconURIToPageURI, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_places_view "
|
||||
"UPDATE moz_places "
|
||||
"SET favicon_id = (SELECT id FROM moz_favicons WHERE url = :icon_url) "
|
||||
"WHERE url = :page_url"));
|
||||
|
||||
@ -220,15 +209,8 @@ nsFaviconService::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
"SET favicon_id = NULL "
|
||||
"WHERE favicon_id NOT NULL"));
|
||||
|
||||
RETURN_IF_STMT(mDBRemoveTempReferences, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_places_temp "
|
||||
"SET favicon_id = NULL "
|
||||
"WHERE favicon_id NOT NULL"));
|
||||
|
||||
RETURN_IF_STMT(mDBRemoveAllFavicons, NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_favicons WHERE id NOT IN ("
|
||||
"SELECT favicon_id FROM moz_places_temp WHERE favicon_id NOT NULL "
|
||||
"UNION ALL "
|
||||
"SELECT favicon_id FROM moz_places WHERE favicon_id NOT NULL "
|
||||
")"));
|
||||
|
||||
@ -262,16 +244,11 @@ nsFaviconService::ExpireAllFavicons()
|
||||
{
|
||||
mFaviconsExpirationRunning = true;
|
||||
|
||||
// We do this in 2 steps, first we null-out all favicons in the disk table,
|
||||
// then we do the same in the temp table. This is because the view UPDATE
|
||||
// trigger does not allow setting a NULL value to prevent dataloss.
|
||||
|
||||
mozIStorageBaseStatement *stmts[] = {
|
||||
GetStatement(mDBRemoveOnDiskReferences),
|
||||
GetStatement(mDBRemoveTempReferences),
|
||||
GetStatement(mDBRemoveAllFavicons),
|
||||
};
|
||||
NS_ENSURE_STATE(stmts[0] && stmts[1] && stmts[2]);
|
||||
NS_ENSURE_STATE(stmts[0] && stmts[1]);
|
||||
nsCOMPtr<mozIStoragePendingStatement> ps;
|
||||
nsCOMPtr<ExpireFaviconsStatementCallbackNotifier> callback =
|
||||
new ExpireFaviconsStatementCallbackNotifier(&mFaviconsExpirationRunning);
|
||||
@ -1051,7 +1028,6 @@ nsFaviconService::FinalizeStatements() {
|
||||
mDBUpdateIcon,
|
||||
mDBSetPageFavicon,
|
||||
mDBRemoveOnDiskReferences,
|
||||
mDBRemoveTempReferences,
|
||||
mDBRemoveAllFavicons,
|
||||
mDBAssociateFaviconURIToPageURI,
|
||||
};
|
||||
@ -1081,9 +1057,6 @@ nsFaviconService::GetFaviconDataAsync(nsIURI* aFaviconURI,
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// ExpireFaviconsStatementCallbackNotifier
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ExpireFaviconsStatementCallbackNotifier,
|
||||
mozIStorageStatementCallback)
|
||||
|
||||
ExpireFaviconsStatementCallbackNotifier::ExpireFaviconsStatementCallbackNotifier(
|
||||
bool* aFaviconsExpirationRunning)
|
||||
: mFaviconsExpirationRunning(aFaviconsExpirationRunning)
|
||||
@ -1111,11 +1084,3 @@ ExpireFaviconsStatementCallbackNotifier::HandleCompletion(PRUint16 aReason)
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
ExpireFaviconsStatementCallbackNotifier::HandleResult(mozIStorageResultSet* aResultSet)
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "You cannot use this statement callback to get async statements resultset");
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -190,7 +190,6 @@ private:
|
||||
nsCOMPtr<mozIStorageStatement> mDBSetPageFavicon;
|
||||
nsCOMPtr<mozIStorageStatement> mDBAssociateFaviconURIToPageURI;
|
||||
nsCOMPtr<mozIStorageStatement> mDBRemoveOnDiskReferences;
|
||||
nsCOMPtr<mozIStorageStatement> mDBRemoveTempReferences;
|
||||
nsCOMPtr<mozIStorageStatement> mDBRemoveAllFavicons;
|
||||
|
||||
static nsFaviconService* gFaviconService;
|
||||
|
@ -251,17 +251,12 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
|
||||
// Double ordering covers possible lastModified ties, that could happen when
|
||||
// importing, syncing or due to extensions.
|
||||
// Note: not using a JOIN is cheaper in this case.
|
||||
RETURN_IF_STMT(mDBFindURIBookmarks, NS_LITERAL_CSTRING(
|
||||
"SELECT b.id "
|
||||
"FROM moz_bookmarks b "
|
||||
"WHERE b.type = :item_type AND b.fk = ( "
|
||||
"SELECT id FROM moz_places_temp "
|
||||
"WHERE url = :page_url "
|
||||
"UNION "
|
||||
"SELECT id FROM moz_places "
|
||||
"WHERE url = :page_url "
|
||||
"LIMIT 1 "
|
||||
") "
|
||||
"WHERE b.fk = (SELECT id FROM moz_places WHERE url = :page_url) "
|
||||
"AND b.fk NOTNULL "
|
||||
"ORDER BY b.lastModified DESC, b.id DESC "));
|
||||
|
||||
// Select all children of a given folder, sorted by position.
|
||||
@ -271,15 +266,10 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
// by mDBGetURLPageInfo, and additionally contains columns for position,
|
||||
// item_child, and folder_child from moz_bookmarks.
|
||||
RETURN_IF_STMT(mDBGetChildren, NS_LITERAL_CSTRING(
|
||||
"SELECT IFNULL(h_t.id, h.id), IFNULL(h_t.url, h.url), "
|
||||
"COALESCE(b.title, h_t.title, h.title), "
|
||||
"IFNULL(h_t.rev_host, h.rev_host), "
|
||||
"IFNULL(h_t.visit_count, h.visit_count), "
|
||||
"IFNULL(h_t.last_visit_date, h.last_visit_date), "
|
||||
"f.url, null, b.id, b.dateAdded, b.lastModified, b.parent, null, "
|
||||
"b.position, b.type, b.fk, b.folder_type "
|
||||
"SELECT h.id, h.url, IFNULL(b.title, h.title), h.rev_host, h.visit_count, "
|
||||
"h.last_visit_date, f.url, null, b.id, b.dateAdded, b.lastModified, "
|
||||
"b.parent, null, b.position, b.type, b.fk, b.folder_type "
|
||||
"FROM moz_bookmarks b "
|
||||
"LEFT JOIN moz_places_temp h_t ON b.fk = h_t.id "
|
||||
"LEFT JOIN moz_places h ON b.fk = h.id "
|
||||
"LEFT JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
"WHERE b.parent = :parent "
|
||||
@ -298,8 +288,7 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
// Get bookmark/folder/separator properties.
|
||||
RETURN_IF_STMT(mDBGetItemProperties, NS_LITERAL_CSTRING(
|
||||
"SELECT b.id, "
|
||||
"IFNULL((SELECT url FROM moz_places_temp WHERE id = b.fk), "
|
||||
"(SELECT url FROM moz_places WHERE id = b.fk)), "
|
||||
"(SELECT url FROM moz_places WHERE id = b.fk), "
|
||||
"b.title, b.position, b.fk, b.parent, b.type, b.folder_type, "
|
||||
"b.dateAdded, b.lastModified "
|
||||
"FROM moz_bookmarks b "
|
||||
@ -323,12 +312,9 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
"SELECT 1 FROM moz_bookmarks WHERE fk = :page_id"));
|
||||
|
||||
RETURN_IF_STMT(mDBIsURIBookmarkedInDatabase, NS_LITERAL_CSTRING(
|
||||
"SELECT 1 FROM moz_bookmarks WHERE fk = ("
|
||||
"SELECT id FROM moz_places_temp WHERE url = :page_url "
|
||||
"UNION ALL "
|
||||
"SELECT id FROM moz_places WHERE url = :page_url "
|
||||
"LIMIT 1"
|
||||
")"));
|
||||
"SELECT 1 FROM moz_bookmarks b "
|
||||
"JOIN moz_places h ON b.fk = h.id "
|
||||
"WHERE h.url = :page_url"));
|
||||
|
||||
// Checks to make sure a place id is a bookmark, and isn't a livemark.
|
||||
RETURN_IF_STMT(mDBIsRealBookmark, NS_LITERAL_CSTRING(
|
||||
@ -363,19 +349,12 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
RETURN_IF_STMT(mDBSetItemIndex, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_bookmarks SET position = :item_index WHERE id = :item_id"));
|
||||
|
||||
// Get keyword text for bookmarked URI.
|
||||
RETURN_IF_STMT(mDBGetKeywordForURI, NS_LITERAL_CSTRING(
|
||||
"SELECT k.keyword "
|
||||
"FROM ( "
|
||||
"SELECT id FROM moz_places_temp "
|
||||
"WHERE url = :page_url "
|
||||
"UNION ALL "
|
||||
"SELECT id FROM moz_places "
|
||||
"WHERE url = :page_url "
|
||||
"LIMIT 1 "
|
||||
") AS h "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_bookmarks b ON b.fk = h.id "
|
||||
"JOIN moz_keywords k ON k.id = b.keyword_id"));
|
||||
"JOIN moz_keywords k ON k.id = b.keyword_id "
|
||||
"WHERE h.url = :page_url "));
|
||||
|
||||
RETURN_IF_STMT(mDBAdjustPosition, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_bookmarks SET position = position + :delta "
|
||||
@ -422,14 +401,6 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
// For most cases these levels of redirects should be fine though, it's hard
|
||||
// to hit a page that is 4 or 5 levels of redirects below a bookmarked page.
|
||||
//
|
||||
// Moreover this query does not mix-up all possible cases of disk and temp
|
||||
// tables. This is because we expect a redirects chain to be completely on
|
||||
// disk or completely in memory. We never bring back visits from disk to
|
||||
// memory, we sync visits on a timer (the chained visits have narrow times),
|
||||
// or on bookmarks changes. The likely possiblity that we break a chain in
|
||||
// the middle is so much smaller than the perf and readability hit we would
|
||||
// get making complete crossing joins.
|
||||
//
|
||||
// As a bonus the query also checks first if place_id is already a bookmark,
|
||||
// so you don't have to check that apart.
|
||||
|
||||
@ -442,31 +413,13 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY);
|
||||
|
||||
RETURN_IF_STMT(mDBFindRedirectedBookmark, NS_LITERAL_CSTRING(
|
||||
"SELECT IFNULL( "
|
||||
"(SELECT url FROM moz_places_temp WHERE id = :page_id), "
|
||||
"SELECT "
|
||||
"(SELECT url FROM moz_places WHERE id = :page_id) "
|
||||
") "
|
||||
"FROM moz_bookmarks b "
|
||||
"WHERE b.fk = :page_id "
|
||||
"UNION ALL " // Not directly bookmarked.
|
||||
"SELECT IFNULL( "
|
||||
"(SELECT url FROM moz_places_temp WHERE id = " COALESCE_PLACEID "), "
|
||||
"SELECT "
|
||||
"(SELECT url FROM moz_places WHERE id = " COALESCE_PLACEID ") "
|
||||
") "
|
||||
"FROM moz_historyvisits_temp self "
|
||||
"JOIN moz_bookmarks b ON b.fk = " COALESCE_PLACEID
|
||||
"LEFT JOIN moz_historyvisits_temp parent ON parent.id = self.from_visit "
|
||||
"LEFT JOIN moz_historyvisits_temp grandparent ON parent.from_visit = grandparent.id "
|
||||
"AND parent.visit_type IN (") + redirectsFragment + NS_LITERAL_CSTRING(") "
|
||||
"LEFT JOIN moz_historyvisits_temp greatgrandparent ON grandparent.from_visit = greatgrandparent.id "
|
||||
"AND grandparent.visit_type IN (") + redirectsFragment + NS_LITERAL_CSTRING(") "
|
||||
"WHERE self.visit_type IN (") + redirectsFragment + NS_LITERAL_CSTRING(") "
|
||||
"AND self.place_id = :page_id "
|
||||
"UNION ALL " // Not in the temp table.
|
||||
"SELECT IFNULL( "
|
||||
"(SELECT url FROM moz_places_temp WHERE id = " COALESCE_PLACEID "), "
|
||||
"(SELECT url FROM moz_places WHERE id = " COALESCE_PLACEID ") "
|
||||
") "
|
||||
"FROM moz_historyvisits self "
|
||||
"JOIN moz_bookmarks b ON b.fk = " COALESCE_PLACEID
|
||||
"LEFT JOIN moz_historyvisits parent ON parent.id = self.from_visit "
|
||||
@ -986,28 +939,8 @@ nsNavBookmarks::InsertBookmark(PRInt64 aFolder,
|
||||
rv = aURI->GetSpec(url);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// prevent place: queries from showing up in the URL bar autocomplete results
|
||||
PRBool isBookmark = !IsQueryURI(url);
|
||||
|
||||
if (isBookmark) {
|
||||
// if it is a livemark item (the parent is a livemark),
|
||||
// we pass in false for isBookmark. otherwise, unvisited livemark
|
||||
// items will appear in URL autocomplete before we visit them.
|
||||
PRBool parentIsLivemark;
|
||||
nsCOMPtr<nsILivemarkService> lms =
|
||||
do_GetService(NS_LIVEMARKSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = lms->IsLivemark(aFolder, &parentIsLivemark);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
isBookmark = !parentIsLivemark;
|
||||
}
|
||||
|
||||
// when we created the moz_place entry for the new bookmark
|
||||
// (a side effect of calling GetUrlIdFor()) frecency -1;
|
||||
// now we re-calculate the frecency for this moz_place entry.
|
||||
rv = history->UpdateFrecency(childID, isBookmark);
|
||||
// Re-calculate the frecency for this moz_place entry since it was set to -1.
|
||||
rv = history->UpdateFrecency(childID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = transaction.Commit();
|
||||
@ -1119,12 +1052,9 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (itemType == TYPE_BOOKMARK) {
|
||||
// UpdateFrecency needs to know whether placeId is still bookmarked.
|
||||
// Although we removed aItemId, placeId may still be bookmarked elsewhere;
|
||||
// IsRealBookmark will know.
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = history->UpdateFrecency(placeId, IsRealBookmark(placeId));
|
||||
rv = history->UpdateFrecency(placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = UpdateKeywordsHashForRemovedBookmark(aItemId);
|
||||
@ -1689,13 +1619,9 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolderId)
|
||||
folderChildrenInfo child = folderChildrenArray[i];
|
||||
if (child.itemType == TYPE_BOOKMARK) {
|
||||
PRInt64 placeId = child.placeId;
|
||||
|
||||
// UpdateFrecency needs to know whether placeId is still bookmarked.
|
||||
// Although we removed a child of aFolderId that bookmarked it, it may
|
||||
// still be bookmarked elsewhere; IsRealBookmark will know.
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
rv = history->UpdateFrecency(placeId, IsRealBookmark(placeId));
|
||||
rv = history->UpdateFrecency(placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = UpdateKeywordsHashForRemovedBookmark(child.itemId);
|
||||
@ -2566,20 +2492,12 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI* aNewURI)
|
||||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Upon changing the URI for a bookmark, update the frecency for the new place.
|
||||
// UpdateFrecency needs to know whether placeId is bookmarked (as opposed
|
||||
// to a livemark item). Bookmarking it is exactly what we did above.
|
||||
rv = history->UpdateFrecency(placeId, PR_TRUE /* isBookmarked */);
|
||||
rv = history->UpdateFrecency(placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Upon changing the URI for a bookmark, update the frecency for the old place.
|
||||
// UpdateFrecency again needs to know whether oldPlaceId is bookmarked. It may
|
||||
// no longer be, so we need to figure out whether it still is. Our strategy
|
||||
// is: find all bookmarks corresponding to oldPlaceId that are not livemark
|
||||
// items, i.e., whose parents are not livemarks. If any such bookmarks exist,
|
||||
// oldPlaceId is still bookmarked.
|
||||
|
||||
rv = history->UpdateFrecency(oldPlaceId, IsRealBookmark(oldPlaceId));
|
||||
// Upon changing the URI for a bookmark, update the frecency for the old
|
||||
// place as well.
|
||||
rv = history->UpdateFrecency(oldPlaceId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString spec;
|
||||
@ -2631,8 +2549,6 @@ nsNavBookmarks::GetBookmarkIdsForURITArray(nsIURI* aURI,
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBFindURIBookmarks);
|
||||
nsresult rv = URIBinder::Bind(stmt, NS_LITERAL_CSTRING("page_url"), aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("item_type"), TYPE_BOOKMARK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool more;
|
||||
while (NS_SUCCEEDED((rv = stmt->ExecuteStep(&more))) && more) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -61,6 +61,7 @@
|
||||
#include "nsICharsetResolver.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "nsINavBookmarksService.h"
|
||||
#include "nsIPrivateBrowsingService.h"
|
||||
@ -94,6 +95,12 @@
|
||||
#define TOPIC_AUTOCOMPLETE_FEEDBACK_UPDATED "places-autocomplete-feedback-updated"
|
||||
#endif
|
||||
|
||||
// Fired after frecency has been updated.
|
||||
#define TOPIC_FRECENCY_UPDATED "places-frecency-updated"
|
||||
|
||||
// Fired after frecency has been updated.
|
||||
#define TOPIC_FRECENCY_UPDATED "places-frecency-updated"
|
||||
|
||||
// Fired when Places is shutting down. Any code should stop accessing Places
|
||||
// APIs after this notification. If you need to listen for Places shutdown
|
||||
// you should only use this notification, next ones are intended only for
|
||||
@ -121,15 +128,29 @@ namespace places {
|
||||
|
||||
enum HistoryStatementId {
|
||||
DB_GET_PAGE_INFO_BY_URL = 0
|
||||
, DB_GET_TAGS = 1
|
||||
, DB_IS_PAGE_VISITED = 2
|
||||
, DB_INSERT_VISIT = 3
|
||||
, DB_RECENT_VISIT_OF_URL = 4
|
||||
, DB_GET_PAGE_VISIT_STATS = 5
|
||||
, DB_UPDATE_PAGE_VISIT_STATS = 6
|
||||
, DB_ADD_NEW_PAGE = 7
|
||||
, DB_GET_URL_PAGE_INFO = 8
|
||||
, DB_SET_PLACE_TITLE = 9
|
||||
, DB_GET_TAGS
|
||||
, DB_IS_PAGE_VISITED
|
||||
, DB_INSERT_VISIT
|
||||
, DB_RECENT_VISIT_OF_URL
|
||||
, DB_GET_PAGE_VISIT_STATS
|
||||
, DB_UPDATE_PAGE_VISIT_STATS
|
||||
, DB_ADD_NEW_PAGE
|
||||
, DB_GET_URL_PAGE_INFO
|
||||
, DB_SET_PLACE_TITLE
|
||||
, DB_PAGE_INFO_FOR_FRECENCY
|
||||
, DB_VISITS_FOR_FRECENCY
|
||||
};
|
||||
|
||||
enum JournalMode {
|
||||
// Default SQLite journal mode.
|
||||
JOURNAL_DELETE = 0
|
||||
// Can reduce fsyncs on Linux when journal is deleted (See bug 460315).
|
||||
// We fallback to this mode when WAL is unavailable.
|
||||
, JOURNAL_TRUNCATE
|
||||
// Unsafe in case of crashes on database swap or low memory.
|
||||
, JOURNAL_MEMORY
|
||||
// Can reduce number of fsyncs. We try to use this mode by default.
|
||||
, JOURNAL_WAL
|
||||
};
|
||||
|
||||
} // namespace places
|
||||
@ -200,6 +221,19 @@ public:
|
||||
return gHistoryService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by other components in the places directory to get a reference to a
|
||||
* const version of this history object.
|
||||
*
|
||||
* @return A pointer to a const version of the service if it exists,
|
||||
* NULL otherwise.
|
||||
*/
|
||||
static const nsNavHistory* GetConstHistoryService()
|
||||
{
|
||||
const nsNavHistory* const history = gHistoryService;
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database ID for the given URI, or 0 if not found and autoCreate
|
||||
* is false.
|
||||
@ -207,12 +241,7 @@ public:
|
||||
nsresult GetUrlIdFor(nsIURI* aURI, PRInt64* aEntryID,
|
||||
PRBool aAutoCreate);
|
||||
|
||||
nsresult CalculateFullVisitCount(PRInt64 aPlaceId, PRInt32 *aVisitCount);
|
||||
|
||||
nsresult UpdateFrecency(PRInt64 aPlaceId, PRBool aIsBookmark);
|
||||
nsresult UpdateFrecencyInternal(PRInt64 aPlaceId, PRInt32 aTyped,
|
||||
PRInt32 aHidden, PRInt32 aOldFrecency,
|
||||
PRBool aIsBookmark);
|
||||
nsresult UpdateFrecency(PRInt64 aPlaceId);
|
||||
|
||||
/**
|
||||
* Calculate frecencies for places that don't have a valid value yet
|
||||
@ -416,9 +445,12 @@ public:
|
||||
|
||||
mozIStorageStatement* GetStatementById(
|
||||
enum mozilla::places::HistoryStatementId aStatementId
|
||||
)
|
||||
) const
|
||||
{
|
||||
using namespace mozilla::places;
|
||||
|
||||
NS_ASSERTION(NS_IsMainThread(), "Can only get statement on main thread");
|
||||
|
||||
switch(aStatementId) {
|
||||
case DB_GET_PAGE_INFO_BY_URL:
|
||||
return mDBGetURLPageInfo;
|
||||
@ -440,10 +472,91 @@ public:
|
||||
return mDBGetURLPageInfo;
|
||||
case DB_SET_PLACE_TITLE:
|
||||
return mDBSetPlaceTitle;
|
||||
case DB_PAGE_INFO_FOR_FRECENCY:
|
||||
return mDBPageInfoForFrecency;
|
||||
case DB_VISITS_FOR_FRECENCY:
|
||||
return mDBVisitsForFrecency;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
mozIStorageStatement* GetStatementByStoragePool(
|
||||
enum mozilla::places::HistoryStatementId aStatementId
|
||||
) const
|
||||
{
|
||||
using namespace mozilla::places;
|
||||
|
||||
switch(aStatementId) {
|
||||
case DB_PAGE_INFO_FOR_FRECENCY:
|
||||
return NS_IsMainThread() ? mDBPageInfoForFrecency
|
||||
: mDBAsyncThreadPageInfoForFrecency;
|
||||
case DB_VISITS_FOR_FRECENCY:
|
||||
return NS_IsMainThread() ? mDBVisitsForFrecency
|
||||
: mDBAsyncThreadVisitsForFrecency;
|
||||
}
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
PRInt32 GetFrecencyAgedWeight(PRInt32 aAgeInDays) const
|
||||
{
|
||||
if (aAgeInDays <= mFirstBucketCutoffInDays) {
|
||||
return mFirstBucketWeight;
|
||||
}
|
||||
if (aAgeInDays <= mSecondBucketCutoffInDays) {
|
||||
return mSecondBucketWeight;
|
||||
}
|
||||
if (aAgeInDays <= mThirdBucketCutoffInDays) {
|
||||
return mThirdBucketWeight;
|
||||
}
|
||||
if (aAgeInDays <= mFourthBucketCutoffInDays) {
|
||||
return mFourthBucketWeight;
|
||||
}
|
||||
return mDefaultWeight;
|
||||
}
|
||||
|
||||
PRInt32 GetFrecencyBucketWeight(PRInt32 aBucketIndex) const
|
||||
{
|
||||
switch(aBucketIndex) {
|
||||
case 1:
|
||||
return mFirstBucketWeight;
|
||||
case 2:
|
||||
return mSecondBucketWeight;
|
||||
case 3:
|
||||
return mThirdBucketWeight;
|
||||
case 4:
|
||||
return mFourthBucketWeight;
|
||||
default:
|
||||
return mDefaultWeight;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32 GetFrecencyTransitionBonus(PRInt32 aTransitionType,
|
||||
bool aVisited) const
|
||||
{
|
||||
switch (aTransitionType) {
|
||||
case nsINavHistoryService::TRANSITION_EMBED:
|
||||
return mEmbedVisitBonus;
|
||||
case nsINavHistoryService::TRANSITION_FRAMED_LINK:
|
||||
return mFramedLinkVisitBonus;
|
||||
case nsINavHistoryService::TRANSITION_LINK:
|
||||
return mLinkVisitBonus;
|
||||
case nsINavHistoryService::TRANSITION_TYPED:
|
||||
return aVisited ? mTypedVisitBonus : mUnvisitedTypedBonus;
|
||||
case nsINavHistoryService::TRANSITION_BOOKMARK:
|
||||
return aVisited ? mBookmarkVisitBonus : mUnvisitedBookmarkBonus;
|
||||
case nsINavHistoryService::TRANSITION_DOWNLOAD:
|
||||
return mDownloadVisitBonus;
|
||||
case nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT:
|
||||
return mPermRedirectVisitBonus;
|
||||
case nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY:
|
||||
return mTempRedirectVisitBonus;
|
||||
default:
|
||||
// 0 == undefined (see bug #375777 for details)
|
||||
NS_WARN_IF_FALSE(!aTransitionType, "new transition but no bonus for frecency");
|
||||
return mDefaultVisitBonus;
|
||||
}
|
||||
}
|
||||
|
||||
PRInt64 GetNewSessionID();
|
||||
|
||||
/**
|
||||
@ -479,6 +592,7 @@ protected:
|
||||
nsCOMPtr<mozIStorageService> mDBService;
|
||||
nsCOMPtr<mozIStorageConnection> mDBConn;
|
||||
nsCOMPtr<nsIFile> mDBFile;
|
||||
PRInt32 mDBPageSize;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetURLPageInfo; // kGetInfoIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetIdPageInfo; // kGetInfoIndex_* results
|
||||
@ -531,9 +645,16 @@ protected:
|
||||
nsresult CalculateFrecency(PRInt64 aPageID, PRInt32 aTyped, PRInt32 aVisitCount, nsCAutoString &aURL, PRInt32 *aFrecency);
|
||||
nsresult CalculateFrecencyInternal(PRInt64 aPageID, PRInt32 aTyped, PRInt32 aVisitCount, PRBool aIsBookmarked, PRInt32 *aFrecency);
|
||||
nsCOMPtr<mozIStorageStatement> mDBVisitsForFrecency;
|
||||
nsCOMPtr<mozIStorageStatement> mDBUpdateFrecencyAndHidden;
|
||||
nsCOMPtr<mozIStorageStatement> mDBUpdateFrecency;
|
||||
nsCOMPtr<mozIStorageStatement> mDBUpdateHiddenOnFrecency;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetPlaceVisitStats;
|
||||
nsCOMPtr<mozIStorageStatement> mDBFullVisitCount;
|
||||
nsCOMPtr<mozIStorageStatement> mDBPageInfoForFrecency;
|
||||
|
||||
// Cached statements used in frecency calculation. Since it could happen on
|
||||
// both main thread or storage async thread, we keep two versions of them
|
||||
// for thread-safety.
|
||||
nsCOMPtr<mozIStorageStatement> mDBAsyncThreadVisitsForFrecency;
|
||||
nsCOMPtr<mozIStorageStatement> mDBAsyncThreadPageInfoForFrecency;
|
||||
|
||||
/**
|
||||
* Initializes the database file. If the database does not exist, was
|
||||
@ -546,6 +667,12 @@ protected:
|
||||
*/
|
||||
nsresult InitDBFile(PRBool aForceInit);
|
||||
|
||||
/**
|
||||
* Set journal mode on the database.
|
||||
*/
|
||||
nsresult SetJournalMode(enum mozilla::places::JournalMode aJournalMode);
|
||||
enum mozilla::places::JournalMode mCurrentJournalMode;
|
||||
|
||||
/**
|
||||
* Initializes the database. This performs any necessary migrations for the
|
||||
* database. All migration is done inside a transaction that is rolled back
|
||||
@ -560,7 +687,6 @@ protected:
|
||||
*/
|
||||
nsresult InitAdditionalDBItems();
|
||||
nsresult InitTempTables();
|
||||
nsresult InitViews();
|
||||
nsresult InitFunctions();
|
||||
nsresult InitStatements();
|
||||
nsresult ForceMigrateBookmarksDB(mozIStorageConnection *aDBConn);
|
||||
@ -570,6 +696,7 @@ protected:
|
||||
nsresult MigrateV8Up(mozIStorageConnection *aDBConn);
|
||||
nsresult MigrateV9Up(mozIStorageConnection *aDBConn);
|
||||
nsresult MigrateV10Up(mozIStorageConnection *aDBConn);
|
||||
nsresult MigrateV11Up(mozIStorageConnection *aDBConn);
|
||||
|
||||
nsresult RemovePagesInternal(const nsCString& aPlaceIdsQueryString);
|
||||
nsresult PreparePlacesForVisitsDelete(const nsCString& aPlaceIdsQueryString);
|
||||
|
@ -108,33 +108,6 @@ const kTitleTagsSeparator = " \u2013 ";
|
||||
|
||||
const kBrowserUrlbarBranch = "browser.urlbar.";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Global Functions
|
||||
|
||||
/**
|
||||
* Generates the SQL subquery to get the best favicon for a given revhost. This
|
||||
* is the favicon for the most recent visit.
|
||||
*
|
||||
* @param aTableName
|
||||
* The table to join to the moz_favicons table with. This must have a
|
||||
* column called favicon_id.
|
||||
* @return the SQL subquery (in string form) to get the best favicon.
|
||||
*/
|
||||
function best_favicon_for_revhost(aTableName)
|
||||
{
|
||||
return "(" +
|
||||
"SELECT f.url " +
|
||||
"FROM " + aTableName + " " +
|
||||
"JOIN moz_favicons f ON f.id = favicon_id " +
|
||||
"WHERE rev_host = IFNULL( " +
|
||||
"(SELECT rev_host FROM moz_places_temp WHERE id = b.fk), " +
|
||||
"(SELECT rev_host FROM moz_places WHERE id = b.fk) " +
|
||||
") " +
|
||||
"ORDER BY frecency DESC " +
|
||||
"LIMIT 1 " +
|
||||
")";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AutoCompleteStatementCallbackWrapper class
|
||||
|
||||
@ -211,32 +184,24 @@ function nsPlacesAutoComplete()
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Shared Constants for Smart Getters
|
||||
|
||||
// Define common pieces of various queries.
|
||||
// TODO bug 412736 in case of a frecency tie, break it with h.typed and
|
||||
// h.visit_count which is better than nothing. This is slow, so not doing it
|
||||
// yet...
|
||||
// Note: h.frecency is only selected because we need it for ordering.
|
||||
function sql_base_fragment(aTableName) {
|
||||
return "SELECT h.url, h.title, f.url, " + kBookTagSQLFragment + ", " +
|
||||
"h.visit_count, h.typed, h.id, :query_type, t.open_count, " +
|
||||
"h.frecency " +
|
||||
"FROM " + aTableName + " h " +
|
||||
"LEFT OUTER JOIN moz_favicons f ON f.id = h.favicon_id " +
|
||||
"LEFT OUTER JOIN moz_openpages_temp t ON t.url = h.url " +
|
||||
"WHERE h.frecency <> 0 " +
|
||||
"AND AUTOCOMPLETE_MATCH(:searchString, h.url, " +
|
||||
"IFNULL(bookmark, h.title), tags, " +
|
||||
"h.visit_count, h.typed, parent, " +
|
||||
"t.open_count, " +
|
||||
":matchBehavior, :searchBehavior) " +
|
||||
"{ADDITIONAL_CONDITIONS} ";
|
||||
}
|
||||
const SQL_BASE = sql_base_fragment("moz_places_temp") +
|
||||
"UNION ALL " +
|
||||
sql_base_fragment("moz_places") +
|
||||
"AND +h.id NOT IN (SELECT id FROM moz_places_temp) " +
|
||||
"ORDER BY h.frecency DESC, h.id DESC " +
|
||||
"LIMIT :maxResults";
|
||||
const SQL_BASE = "SELECT h.url, h.title, f.url, " + kBookTagSQLFragment + ", "
|
||||
+ "h.visit_count, h.typed, h.id, :query_type, "
|
||||
+ "t.open_count "
|
||||
+ "FROM moz_places h "
|
||||
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
+ "LEFT JOIN moz_openpages_temp t ON t.url = h.url "
|
||||
+ "WHERE h.frecency <> 0 "
|
||||
+ "AND AUTOCOMPLETE_MATCH(:searchString, h.url, "
|
||||
+ "IFNULL(bookmark, h.title), tags, "
|
||||
+ "h.visit_count, h.typed, parent, "
|
||||
+ "t.open_count, "
|
||||
+ ":matchBehavior, :searchBehavior) "
|
||||
+ "{ADDITIONAL_CONDITIONS} "
|
||||
+ "ORDER BY h.frecency DESC, h.id DESC "
|
||||
+ "LIMIT :maxResults";
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Smart Getters
|
||||
@ -269,60 +234,56 @@ function nsPlacesAutoComplete()
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_defaultQuery", function() {
|
||||
let replacementText = "";
|
||||
return this._db.createStatement(
|
||||
return this._db.createAsyncStatement(
|
||||
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_historyQuery", function() {
|
||||
let replacementText = "AND h.visit_count > 0";
|
||||
return this._db.createStatement(
|
||||
return this._db.createAsyncStatement(
|
||||
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_bookmarkQuery", function() {
|
||||
let replacementText = "AND bookmark IS NOT NULL";
|
||||
return this._db.createStatement(
|
||||
return this._db.createAsyncStatement(
|
||||
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_tagsQuery", function() {
|
||||
let replacementText = "AND tags IS NOT NULL";
|
||||
return this._db.createStatement(
|
||||
return this._db.createAsyncStatement(
|
||||
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_openPagesQuery", function() {
|
||||
return this._db.createStatement(
|
||||
"/* do not warn (bug 487789) */ " +
|
||||
"SELECT t.url, " +
|
||||
"COALESCE(h_t.title, h.title, t.url) AS c_title, f.url, " +
|
||||
kBookTagSQLFragment + ", " +
|
||||
"IFNULL(h_t.visit_count, h.visit_count) AS c_visit_count, " +
|
||||
"IFNULL(h_t.typed, h.typed) AS c_typed, " +
|
||||
"IFNULL(h_t.id, h.id), :query_type, t.open_count, " +
|
||||
"IFNULL(h_t.frecency, h.frecency) AS c_frecency " +
|
||||
"FROM moz_openpages_temp t " +
|
||||
"LEFT JOIN moz_places_temp h_t ON h_t.url = t.url " +
|
||||
"LEFT JOIN moz_places h ON h.url = t.url " +
|
||||
"LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) " +
|
||||
"WHERE t.open_count > 0 " +
|
||||
"AND AUTOCOMPLETE_MATCH(:searchString, t.url, " +
|
||||
"COALESCE(bookmark, c_title, t.url), tags, " +
|
||||
"c_visit_count, c_typed, parent, " +
|
||||
"t.open_count, " +
|
||||
":matchBehavior, :searchBehavior) " +
|
||||
"ORDER BY c_frecency DESC, t.ROWID DESC " +
|
||||
"LIMIT :maxResults"
|
||||
return this._db.createAsyncStatement(
|
||||
"SELECT t.url, "
|
||||
+ "IFNULL(h.title, t.url) AS c_title, f.url, "
|
||||
+ kBookTagSQLFragment + ", "
|
||||
+ "h.visit_count, h.typed, "
|
||||
+ "h.id, :query_type, t.open_count, h.frecency "
|
||||
+ "FROM moz_openpages_temp t "
|
||||
+ "LEFT JOIN moz_places h ON h.url = t.url "
|
||||
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
+ "WHERE t.open_count > 0 "
|
||||
+ "AND AUTOCOMPLETE_MATCH(:searchString, t.url, "
|
||||
+ "COALESCE(bookmark, c_title, t.url), tags, "
|
||||
+ "h.visit_count, h.typed, parent, "
|
||||
+ "t.open_count, "
|
||||
+ ":matchBehavior, :searchBehavior) "
|
||||
+ "ORDER BY h.frecency DESC, t.ROWID DESC "
|
||||
+ "LIMIT :maxResults"
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_typedQuery", function() {
|
||||
let replacementText = "AND h.typed = 1";
|
||||
return this._db.createStatement(
|
||||
return this._db.createAsyncStatement(
|
||||
SQL_BASE.replace("{ADDITIONAL_CONDITIONS}", replacementText, "g")
|
||||
);
|
||||
});
|
||||
@ -331,58 +292,55 @@ function nsPlacesAutoComplete()
|
||||
// In this query, we are taking kBookTagSQLFragment only for h.id because it
|
||||
// uses data from the moz_bookmarks table and we sync tables on bookmark
|
||||
// insert. So, most likely, h.id will always be populated when we have any
|
||||
// bookmark. We still need to join on moz_places_temp for other data (eg.
|
||||
// title).
|
||||
return this._db.createStatement(
|
||||
"/* do not warn (bug 487789) */ " +
|
||||
"SELECT IFNULL(h_t.url, h.url) AS c_url, " +
|
||||
"IFNULL(h_t.title, h.title) AS c_title, f.url, " +
|
||||
kBookTagSQLFragment + ", " +
|
||||
"IFNULL(h_t.visit_count, h.visit_count) AS c_visit_count, " +
|
||||
"IFNULL(h_t.typed, h.typed) AS c_typed, " +
|
||||
"IFNULL(h_t.id, h.id), :query_type, t.open_count, rank " +
|
||||
"FROM ( " +
|
||||
"SELECT ROUND(MAX(((i.input = :search_string) + " +
|
||||
"(SUBSTR(i.input, 1, LENGTH(:search_string)) = :search_string)) * " +
|
||||
"i.use_count), 1) AS rank, place_id " +
|
||||
"FROM moz_inputhistory i " +
|
||||
"GROUP BY i.place_id " +
|
||||
"HAVING rank > 0 " +
|
||||
") AS i " +
|
||||
"LEFT JOIN moz_places h ON h.id = i.place_id " +
|
||||
"LEFT JOIN moz_places_temp h_t ON h_t.id = i.place_id " +
|
||||
"LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) " +
|
||||
"LEFT JOIN moz_openpages_temp t ON t.url = c_url " +
|
||||
"WHERE c_url NOTNULL " +
|
||||
"AND AUTOCOMPLETE_MATCH(:searchString, c_url, " +
|
||||
"IFNULL(bookmark, c_title), tags, " +
|
||||
"c_visit_count, c_typed, parent, " +
|
||||
"t.open_count, " +
|
||||
":matchBehavior, :searchBehavior) " +
|
||||
"ORDER BY rank DESC, IFNULL(h_t.frecency, h.frecency) DESC"
|
||||
// bookmark.
|
||||
return this._db.createAsyncStatement(
|
||||
"/* do not warn (bug 487789) */ "
|
||||
+ "SELECT h.url, h.title, f.url, " + kBookTagSQLFragment + ", "
|
||||
+ "h.visit_count, h.typed, h.id, :query_type, t.open_count, rank "
|
||||
+ "FROM ( "
|
||||
+ "SELECT ROUND( "
|
||||
+ "MAX(((i.input = :search_string) + "
|
||||
+ "(SUBSTR(i.input, 1, LENGTH(:search_string)) = :search_string) "
|
||||
+ ") * i.use_count "
|
||||
+ ") , 1 " // Round at first decimal.
|
||||
+ ") AS rank, place_id "
|
||||
+ "FROM moz_inputhistory i "
|
||||
+ "GROUP BY i.place_id "
|
||||
+ "HAVING rank > 0 "
|
||||
+ ") AS i "
|
||||
+ "JOIN moz_places h ON h.id = i.place_id "
|
||||
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
+ "LEFT JOIN moz_openpages_temp t ON t.url = h.url "
|
||||
+ "WHERE AUTOCOMPLETE_MATCH(:searchString, h.url, "
|
||||
+ "IFNULL(bookmark, h.title), tags, "
|
||||
+ "h.visit_count, h.typed, parent, "
|
||||
+ "t.open_count, "
|
||||
+ ":matchBehavior, :searchBehavior) "
|
||||
+ "ORDER BY rank DESC, h.frecency DESC "
|
||||
);
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_keywordQuery", function() {
|
||||
return this._db.createStatement(
|
||||
"/* do not warn (bug 487787) */ " +
|
||||
"SELECT IFNULL( " +
|
||||
"(SELECT REPLACE(url, '%s', :query_string) FROM moz_places_temp WHERE id = b.fk), " +
|
||||
"(SELECT REPLACE(url, '%s', :query_string) FROM moz_places WHERE id = b.fk) " +
|
||||
") AS search_url, IFNULL(h_t.title, h.title), " +
|
||||
"COALESCE(f.url, " + best_favicon_for_revhost("moz_places_temp") + "," +
|
||||
best_favicon_for_revhost("moz_places") + "), b.parent, " +
|
||||
"b.title, NULL, IFNULL(h_t.visit_count, h.visit_count), " +
|
||||
"IFNULL(h_t.typed, h.typed), COALESCE(h_t.id, h.id, b.fk), " +
|
||||
":query_type, t.open_count " +
|
||||
"FROM moz_keywords k " +
|
||||
"JOIN moz_bookmarks b ON b.keyword_id = k.id " +
|
||||
"LEFT JOIN moz_places AS h ON h.url = search_url " +
|
||||
"LEFT JOIN moz_places_temp AS h_t ON h_t.url = search_url " +
|
||||
"LEFT JOIN moz_favicons f ON f.id = IFNULL(h_t.favicon_id, h.favicon_id) " +
|
||||
"LEFT JOIN moz_openpages_temp t ON t.url = search_url " +
|
||||
"WHERE LOWER(k.keyword) = LOWER(:keyword) " +
|
||||
"ORDER BY IFNULL(h_t.frecency, h.frecency) DESC"
|
||||
return this._db.createAsyncStatement(
|
||||
"/* do not warn (bug 487787) */ "
|
||||
+ "SELECT "
|
||||
+ "(SELECT REPLACE(url, '%s', :query_string) FROM moz_places WHERE id = b.fk) "
|
||||
+ "AS search_url, h.title, "
|
||||
+ "IFNULL(f.url, (SELECT f.url "
|
||||
+ "FROM moz_places "
|
||||
+ "JOIN moz_favicons f ON f.id = favicon_id "
|
||||
+ "WHERE rev_host = (SELECT rev_host FROM moz_places WHERE id = b.fk) "
|
||||
+ "ORDER BY frecency DESC "
|
||||
+ "LIMIT 1) "
|
||||
+ "), b.parent, b.title, NULL, h.visit_count, h.typed, IFNULL(h.id, b.fk), "
|
||||
+ ":query_type, t.open_count "
|
||||
+ "FROM moz_keywords k "
|
||||
+ "JOIN moz_bookmarks b ON b.keyword_id = k.id "
|
||||
+ "LEFT JOIN moz_places h ON h.url = search_url "
|
||||
+ "LEFT JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
+ "LEFT JOIN moz_openpages_temp t ON t.url = search_url "
|
||||
+ "WHERE LOWER(k.keyword) = LOWER(:keyword) "
|
||||
+ "ORDER BY h.frecency DESC "
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -1,384 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 ***** */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Constants
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
// A database flush should be the last operation during the shutdown process.
|
||||
const kTopicShutdown = "places-connection-closing";
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
const kDebugStopSync = "places-debug-stop-sync";
|
||||
const kDebugStartSync = "places-debug-start-sync";
|
||||
|
||||
const kSyncPrefName = "places.syncDBTableIntervalInSecs";
|
||||
const kDefaultSyncInterval = 120;
|
||||
|
||||
// Query Constants. These describe the queries we use.
|
||||
const kQuerySyncPlacesId = 0;
|
||||
const kQuerySyncHistoryVisitsId = 1;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Modules
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/PlacesUtils.jsm");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsPlacesDBFlush class
|
||||
|
||||
function nsPlacesDBFlush()
|
||||
{
|
||||
// Get our sync interval
|
||||
try {
|
||||
// We want to silently fail since getIntPref throws if it does not exist,
|
||||
// and use a default to fallback to.
|
||||
this._syncInterval = Services.prefs.getIntPref(kSyncPrefName);
|
||||
if (this._syncInterval <= 0)
|
||||
this._syncInterval = kDefaultSyncInterval;
|
||||
}
|
||||
catch (e) {
|
||||
// The preference did not exist, so use the default.
|
||||
this._syncInterval = kDefaultSyncInterval;
|
||||
}
|
||||
|
||||
// Register observers
|
||||
Services.obs.addObserver(this, kTopicShutdown, false);
|
||||
Services.obs.addObserver(this, kDebugStopSync, false);
|
||||
Services.obs.addObserver(this, kDebugStartSync, false);
|
||||
|
||||
let (pb2 = Services.prefs.QueryInterface(Ci.nsIPrefBranch2))
|
||||
pb2.addObserver(kSyncPrefName, this, false);
|
||||
|
||||
// Create our timer to update everything
|
||||
this._timer = this._newTimer();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Smart Getters
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "_db", function() {
|
||||
return PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.DBConnection;
|
||||
});
|
||||
}
|
||||
|
||||
nsPlacesDBFlush.prototype = {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIObserver
|
||||
|
||||
observe: function DBFlush_observe(aSubject, aTopic, aData)
|
||||
{
|
||||
if (aTopic == kTopicShutdown) {
|
||||
Services.obs.removeObserver(this, kTopicShutdown);
|
||||
Services.obs.removeObserver(this, kDebugStopSync);
|
||||
Services.obs.removeObserver(this, kDebugStartSync);
|
||||
|
||||
let (pb2 = Services.prefs.QueryInterface(Ci.nsIPrefBranch2))
|
||||
pb2.removeObserver(kSyncPrefName, this);
|
||||
|
||||
if (this._timer) {
|
||||
this._timer.cancel();
|
||||
this._timer = null;
|
||||
}
|
||||
|
||||
// Flush any remaining change to disk tables.
|
||||
this._flushWithQueries([kQuerySyncPlacesId, kQuerySyncHistoryVisitsId]);
|
||||
this._finalizeInternalStatements();
|
||||
}
|
||||
else if (aTopic == "nsPref:changed" && aData == kSyncPrefName) {
|
||||
// Get the new pref value, and then update our timer
|
||||
this._syncInterval = Services.prefs.getIntPref(kSyncPrefName);
|
||||
if (this._syncInterval <= 0)
|
||||
this._syncInterval = kDefaultSyncInterval;
|
||||
|
||||
// We may have canceled the timer already for batch updates, so we want to
|
||||
// exit early.
|
||||
if (!this._timer)
|
||||
return;
|
||||
|
||||
this._timer.cancel();
|
||||
this._timer = this._newTimer();
|
||||
}
|
||||
else if (aTopic == kDebugStopSync) {
|
||||
this._syncStopped = true;
|
||||
}
|
||||
else if (aTopic == kDebugStartSync) {
|
||||
if (_syncStopped in this)
|
||||
delete this._syncStopped;
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsINavBookmarkObserver
|
||||
|
||||
onBeginUpdateBatch: function DBFlush_onBeginUpdateBatch()
|
||||
{
|
||||
this._inBatchMode = true;
|
||||
|
||||
// We do not want to sync while we are doing batch work.
|
||||
this._timer.cancel();
|
||||
this._timer = null;
|
||||
},
|
||||
|
||||
onEndUpdateBatch: function DBFlush_onEndUpdateBatch()
|
||||
{
|
||||
this._inBatchMode = false;
|
||||
|
||||
// Restore our timer
|
||||
this._timer = this._newTimer();
|
||||
|
||||
// We need to sync now
|
||||
this._flushWithQueries([kQuerySyncPlacesId, kQuerySyncHistoryVisitsId]);
|
||||
},
|
||||
|
||||
onItemAdded: function(aItemId, aParentId, aIndex, aItemType)
|
||||
{
|
||||
// Sync only if we added a TYPE_BOOKMARK item. Note, we want to run the
|
||||
// least amount of queries as possible here for performance reasons.
|
||||
if (!this._inBatchMode && aItemType == PlacesUtils.bookmarks.TYPE_BOOKMARK)
|
||||
this._flushWithQueries([kQuerySyncPlacesId]);
|
||||
},
|
||||
|
||||
onItemChanged: function DBFlush_onItemChanged(aItemId, aProperty,
|
||||
aIsAnnotationProperty,
|
||||
aNewValue, aLastModified,
|
||||
aItemType)
|
||||
{
|
||||
if (!this._inBatchMode && aProperty == "uri")
|
||||
this._flushWithQueries([kQuerySyncPlacesId]);
|
||||
},
|
||||
|
||||
onBeforeItemRemoved: function() { },
|
||||
onItemRemoved: function() { },
|
||||
onItemVisited: function() { },
|
||||
onItemMoved: function() { },
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsINavHistoryObserver
|
||||
|
||||
// We currently only use the history observer to know when the history service
|
||||
// is activated. At that point, we actually get initialized, and our timer
|
||||
// to sync history is added.
|
||||
|
||||
// These methods share the name of the ones on nsINavBookmarkObserver, so
|
||||
// the implementations can be found above.
|
||||
//onBeginUpdateBatch: function() { },
|
||||
//onEndUpdateBatch: function() { },
|
||||
onVisit: function() { },
|
||||
onTitleChanged: function() { },
|
||||
onBeforeDeleteURI: function() { },
|
||||
onDeleteURI: function() { },
|
||||
onClearHistory: function() { },
|
||||
onPageChanged: function() { },
|
||||
onDeleteVisits: function() { },
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsITimerCallback
|
||||
|
||||
notify: function DBFlush_timerCallback()
|
||||
{
|
||||
let queries = [
|
||||
kQuerySyncPlacesId,
|
||||
kQuerySyncHistoryVisitsId,
|
||||
];
|
||||
this._flushWithQueries(queries);
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStorageStatementCallback
|
||||
|
||||
handleResult: function DBFlush_handleResult(aResultSet)
|
||||
{
|
||||
},
|
||||
|
||||
handleError: function DBFlush_handleError(aError)
|
||||
{
|
||||
Cu.reportError("Async statement execution returned with '" +
|
||||
aError.result + "', '" + aError.message + "'");
|
||||
},
|
||||
|
||||
handleCompletion: function DBFlush_handleCompletion(aReason)
|
||||
{
|
||||
if (aReason == Ci.mozIStorageStatementCallback.REASON_FINISHED) {
|
||||
// Dispatch a notification that sync has finished.
|
||||
Services.obs.notifyObservers(null, kSyncFinished, null);
|
||||
}
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsPlacesDBFlush
|
||||
_syncInterval: kDefaultSyncInterval,
|
||||
|
||||
/**
|
||||
* Execute async statements to flush tables with the specified queries.
|
||||
*
|
||||
* @param aQueryNames
|
||||
* The names of the queries to use with this flush.
|
||||
*/
|
||||
_flushWithQueries: function DBFlush_flushWithQueries(aQueryNames)
|
||||
{
|
||||
// No need to do extra work if we are in batch mode
|
||||
if (this._inBatchMode || this._syncStopped)
|
||||
return;
|
||||
|
||||
let statements = [];
|
||||
for (let i = 0; i < aQueryNames.length; i++)
|
||||
statements.push(this._getQuery(aQueryNames[i]));
|
||||
|
||||
// Execute sync statements async in a transaction
|
||||
this._db.executeAsync(statements, statements.length, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Finalizes all of our mozIStorageStatements so we can properly close the
|
||||
* database.
|
||||
*/
|
||||
_finalizeInternalStatements: function DBFlush_finalizeInternalStatements()
|
||||
{
|
||||
this._cachedStatements.forEach(function(stmt) {
|
||||
if (stmt instanceof Ci.mozIStorageAsyncStatement)
|
||||
stmt.finalize();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate the statement to synchronizes the moz_{aTableName} and
|
||||
* moz_{aTableName}_temp by copying all the data from the temporary table
|
||||
* into the permanent one.
|
||||
* Most of the work is done through triggers defined in nsPlacesTriggers.h,
|
||||
* they sync back to disk, then delete the data in the temporary table.
|
||||
*
|
||||
* @param aQueryType
|
||||
* Type of the query to build statement for.
|
||||
*/
|
||||
_cachedStatements: [],
|
||||
_getQuery: function DBFlush_getQuery(aQueryType)
|
||||
{
|
||||
// Statement creating can be expensive, so always cache if we can.
|
||||
if (aQueryType in this._cachedStatements) {
|
||||
let stmt = this._cachedStatements[aQueryType];
|
||||
|
||||
// Bind the appropriate parameters.
|
||||
let params = stmt.params;
|
||||
switch (aQueryType) {
|
||||
case kQuerySyncHistoryVisitsId:
|
||||
case kQuerySyncPlacesId:
|
||||
params.transition_type = Ci.nsINavHistoryService.TRANSITION_EMBED;
|
||||
break;
|
||||
}
|
||||
|
||||
return stmt;
|
||||
}
|
||||
|
||||
switch(aQueryType) {
|
||||
case kQuerySyncHistoryVisitsId:
|
||||
// For history table we want to leave embed visits in memory, since
|
||||
// those are expired with current session, so we are filtering them out.
|
||||
// Notice that instead we _want_ to sync framed_link visits, since those
|
||||
// come from user's actions.
|
||||
this._cachedStatements[aQueryType] = this._db.createAsyncStatement(
|
||||
"DELETE FROM moz_historyvisits_temp " +
|
||||
"WHERE visit_type <> :transition_type"
|
||||
);
|
||||
break;
|
||||
|
||||
case kQuerySyncPlacesId:
|
||||
// For places table we want to leave places associated with embed visits
|
||||
// in memory, they usually have hidden = 1 and at least an embed visit
|
||||
// in historyvisits_temp table.
|
||||
this._cachedStatements[aQueryType] = this._db.createAsyncStatement(
|
||||
"DELETE FROM moz_places_temp " +
|
||||
"WHERE id IN ( " +
|
||||
"SELECT id FROM moz_places_temp h " +
|
||||
"WHERE h.hidden <> 1 OR NOT EXISTS ( " +
|
||||
"SELECT id FROM moz_historyvisits_temp " +
|
||||
"WHERE place_id = h.id AND visit_type = :transition_type " +
|
||||
"LIMIT 1 " +
|
||||
") " +
|
||||
")"
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw "Unexpected statement!";
|
||||
}
|
||||
|
||||
// We only bind our own parameters when we have a cached statement, so we
|
||||
// call ourself since we now have a cached statement.
|
||||
return this._getQuery(aQueryType);
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates a new timer based on this._syncInterval.
|
||||
*
|
||||
* @returns a REPEATING_SLACK nsITimer that runs every this._syncInterval.
|
||||
*/
|
||||
_newTimer: function DBFlush_newTimer()
|
||||
{
|
||||
let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
timer.initWithCallback(this, this._syncInterval * 1000,
|
||||
Ci.nsITimer.TYPE_REPEATING_SLACK);
|
||||
return timer;
|
||||
},
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// nsISupports
|
||||
|
||||
classID: Components.ID("c1751cfc-e8f1-4ade-b0bb-f74edfb8ef6a"),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIObserver,
|
||||
Ci.nsINavBookmarkObserver,
|
||||
Ci.nsINavHistoryObserver,
|
||||
Ci.nsITimerCallback,
|
||||
Ci.mozIStorageStatementCallback,
|
||||
])
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Module Registration
|
||||
|
||||
let components = [nsPlacesDBFlush];
|
||||
var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
|
@ -211,23 +211,10 @@ const EXPIRATION_QUERIES = {
|
||||
QUERY_FIND_VISITS_TO_EXPIRE: {
|
||||
sql: "INSERT INTO expiration_notify "
|
||||
+ "(v_id, url, visit_date, expected_results) "
|
||||
+ "SELECT v.id, IFNULL(h_t.url, h.url) AS url, "
|
||||
+ "v.visit_date AS visit_date, "
|
||||
+ ":limit_visits AS expected_results "
|
||||
+ "FROM moz_historyvisits_temp v "
|
||||
+ "LEFT JOIN moz_places_temp AS h_t ON h_t.id = v.place_id "
|
||||
+ "LEFT JOIN moz_places AS h ON h.id = v.place_id "
|
||||
+ "WHERE ((SELECT COUNT(*) FROM moz_places_temp) + "
|
||||
+ "(SELECT COUNT(*) FROM moz_places)) > :max_uris "
|
||||
+ "UNION ALL "
|
||||
+ "SELECT v.id, IFNULL(h_t.url, h.url) AS url, "
|
||||
+ "v.visit_date AS visit_date, "
|
||||
+ ":limit_visits AS expected_results "
|
||||
+ "SELECT v.id, h.url, v.visit_date, :limit_visits "
|
||||
+ "FROM moz_historyvisits v "
|
||||
+ "LEFT JOIN moz_places_temp AS h_t ON h_t.id = v.place_id "
|
||||
+ "LEFT JOIN moz_places AS h ON h.id = v.place_id "
|
||||
+ "WHERE ((SELECT COUNT(*) FROM moz_places_temp) + "
|
||||
+ "(SELECT COUNT(*) FROM moz_places)) > :max_uris "
|
||||
+ "JOIN moz_places h ON h.id = v.place_id "
|
||||
+ "WHERE (SELECT COUNT(*) FROM moz_places) > :max_uris "
|
||||
+ "ORDER BY v.visit_date ASC "
|
||||
+ "LIMIT :limit_visits",
|
||||
actions: ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN | ACTION.IDLE |
|
||||
@ -236,7 +223,7 @@ const EXPIRATION_QUERIES = {
|
||||
|
||||
// Removes the previously found visits.
|
||||
QUERY_EXPIRE_VISITS: {
|
||||
sql: "DELETE FROM moz_historyvisits_view WHERE id IN ( "
|
||||
sql: "DELETE FROM moz_historyvisits WHERE id IN ( "
|
||||
+ "SELECT v_id FROM expiration_notify WHERE v_id NOTNULL "
|
||||
+ ")",
|
||||
actions: ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN | ACTION.IDLE |
|
||||
@ -249,26 +236,13 @@ const EXPIRATION_QUERIES = {
|
||||
QUERY_FIND_URIS_TO_EXPIRE: {
|
||||
sql: "INSERT INTO expiration_notify "
|
||||
+ "(p_id, url, visit_date, expected_results) "
|
||||
+ "SELECT h.id, h.url, h.last_visit_date AS visit_date, "
|
||||
+ ":limit_uris AS expected_results "
|
||||
+ "FROM moz_places_temp h "
|
||||
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
+ "LEFT JOIN moz_historyvisits_temp v_t ON h.id = v_t.place_id "
|
||||
+ "LEFT JOIN moz_bookmarks b ON h.id = b.fk "
|
||||
+ "WHERE v.id IS NULL "
|
||||
+ "AND v_t.id IS NULL "
|
||||
+ "AND b.id IS NULL "
|
||||
+ "AND h.ROWID <> IFNULL(:null_skips_last, (SELECT MAX(ROWID) FROM moz_places_temp)) "
|
||||
+ "UNION ALL "
|
||||
+ "SELECT h.id, h.url, h.last_visit_date AS visit_date, "
|
||||
+ ":limit_uris AS expected_results "
|
||||
+ "SELECT h.id, h.url, h.last_visit_date, :limit_uris "
|
||||
+ "FROM moz_places h "
|
||||
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
+ "LEFT JOIN moz_historyvisits_temp v_t ON h.id = v_t.place_id "
|
||||
+ "LEFT JOIN moz_bookmarks b ON h.id = b.fk "
|
||||
+ "WHERE v.id IS NULL "
|
||||
+ "AND v_t.id IS NULL "
|
||||
+ "AND b.id IS NULL "
|
||||
+ "AND h.ROWID <> IFNULL(:null_skips_last, (SELECT MAX(ROWID) FROM moz_places)) "
|
||||
+ "LIMIT :limit_uris",
|
||||
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN |
|
||||
ACTION.IDLE | ACTION.DEBUG
|
||||
@ -276,7 +250,7 @@ const EXPIRATION_QUERIES = {
|
||||
|
||||
// Expire found URIs from the database.
|
||||
QUERY_EXPIRE_URIS: {
|
||||
sql: "DELETE FROM moz_places_view WHERE id IN ( "
|
||||
sql: "DELETE FROM moz_places WHERE id IN ( "
|
||||
+ "SELECT p_id FROM expiration_notify WHERE p_id NOTNULL "
|
||||
+ ")",
|
||||
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.SHUTDOWN |
|
||||
@ -285,26 +259,13 @@ const EXPIRATION_QUERIES = {
|
||||
|
||||
// Expire orphan URIs from the database.
|
||||
QUERY_SILENT_EXPIRE_ORPHAN_URIS: {
|
||||
sql: "DELETE FROM moz_places_view WHERE id IN ( "
|
||||
+ "SELECT h.id "
|
||||
+ "FROM moz_places_temp h "
|
||||
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
+ "LEFT JOIN moz_historyvisits_temp v_t ON h.id = v_t.place_id "
|
||||
+ "LEFT JOIN moz_bookmarks b ON h.id = b.fk "
|
||||
+ "WHERE v.id IS NULL "
|
||||
+ "AND v_t.id IS NULL "
|
||||
+ "AND b.id IS NULL "
|
||||
+ "AND SUBSTR(h.url, 1, 6) <> 'place:' "
|
||||
+ "UNION ALL "
|
||||
sql: "DELETE FROM moz_places WHERE id IN ( "
|
||||
+ "SELECT h.id "
|
||||
+ "FROM moz_places h "
|
||||
+ "LEFT JOIN moz_historyvisits v ON h.id = v.place_id "
|
||||
+ "LEFT JOIN moz_historyvisits_temp v_t ON h.id = v_t.place_id "
|
||||
+ "LEFT JOIN moz_bookmarks b ON h.id = b.fk "
|
||||
+ "WHERE v.id IS NULL "
|
||||
+ "AND v_t.id IS NULL "
|
||||
+ "AND b.id IS NULL "
|
||||
+ "AND SUBSTR(h.url, 1, 6) <> 'place:' "
|
||||
+ "LIMIT :limit_uris "
|
||||
+ ")",
|
||||
actions: ACTION.CLEAR_HISTORY
|
||||
@ -315,9 +276,7 @@ const EXPIRATION_QUERIES = {
|
||||
sql: "DELETE FROM moz_favicons WHERE id IN ( "
|
||||
+ "SELECT f.id FROM moz_favicons f "
|
||||
+ "LEFT JOIN moz_places h ON f.id = h.favicon_id "
|
||||
+ "LEFT JOIN moz_places_temp h_t ON f.id = h_t.favicon_id "
|
||||
+ "WHERE h.favicon_id IS NULL "
|
||||
+ "AND h_t.favicon_id IS NULL "
|
||||
+ "LIMIT :limit_favicons "
|
||||
+ ")",
|
||||
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
|
||||
@ -329,12 +288,9 @@ const EXPIRATION_QUERIES = {
|
||||
sql: "DELETE FROM moz_annos WHERE id in ( "
|
||||
+ "SELECT a.id FROM moz_annos a "
|
||||
+ "LEFT JOIN moz_places h ON a.place_id = h.id "
|
||||
+ "LEFT JOIN moz_places_temp h_t ON a.place_id = h_t.id "
|
||||
+ "LEFT JOIN moz_historyvisits v ON a.place_id = v.place_id "
|
||||
+ "LEFT JOIN moz_historyvisits_temp v_t ON a.place_id = v_t.place_id "
|
||||
+ "WHERE (h.id IS NULL AND h_t.id IS NULL) "
|
||||
+ "OR (v.id IS NULL AND v_t.id IS NULL AND "
|
||||
+ "a.expiration <> :expire_never) "
|
||||
+ "WHERE h.id IS NULL "
|
||||
+ "OR (v.id IS NULL AND a.expiration <> :expire_never) "
|
||||
+ "LIMIT :limit_annos "
|
||||
+ ")",
|
||||
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
|
||||
@ -371,8 +327,6 @@ const EXPIRATION_QUERIES = {
|
||||
QUERY_EXPIRE_ANNOS_WITH_HISTORY: {
|
||||
sql: "DELETE FROM moz_annos "
|
||||
+ "WHERE expiration = :expire_with_history "
|
||||
+ "AND NOT EXISTS (SELECT id FROM moz_historyvisits_temp "
|
||||
+ "WHERE place_id = moz_annos.place_id LIMIT 1) "
|
||||
+ "AND NOT EXISTS (SELECT id FROM moz_historyvisits "
|
||||
+ "WHERE place_id = moz_annos.place_id LIMIT 1)",
|
||||
actions: ACTION.TIMED | ACTION.TIMED_OVERLIMIT | ACTION.CLEAR_HISTORY |
|
||||
@ -408,9 +362,7 @@ const EXPIRATION_QUERIES = {
|
||||
sql: "DELETE FROM moz_inputhistory WHERE place_id IN ( "
|
||||
+ "SELECT i.place_id FROM moz_inputhistory i "
|
||||
+ "LEFT JOIN moz_places h ON h.id = i.place_id "
|
||||
+ "LEFT JOIN moz_places_temp h_t ON h_t.id = i.place_id "
|
||||
+ "WHERE h.id IS NULL "
|
||||
+ "AND h_t.id IS NULL "
|
||||
+ "LIMIT :limit_inputhistory "
|
||||
+ ")",
|
||||
actions: ACTION.CLEAR_HISTORY | ACTION.SHUTDOWN | ACTION.IDLE | ACTION.DEBUG
|
||||
@ -610,8 +562,7 @@ nsPlacesExpiration.prototype = {
|
||||
// Check if we are over history capacity, if so visits must be expired.
|
||||
if (!this._cachedStatements["LIMIT_COUNT"]) {
|
||||
this._cachedStatements["LIMIT_COUNT"] = this._db.createAsyncStatement(
|
||||
"SELECT (SELECT COUNT(*) FROM moz_places_temp) + "
|
||||
+ "(SELECT COUNT(*) FROM moz_places)"
|
||||
"SELECT COUNT(*) FROM moz_places"
|
||||
);
|
||||
}
|
||||
let self = this;
|
||||
|
@ -49,55 +49,31 @@
|
||||
/**
|
||||
* moz_places
|
||||
*/
|
||||
#define CREATE_IDX_MOZ_PLACES_TEMP_URL \
|
||||
CREATE_PLACES_IDX( \
|
||||
"url_uniqueindex", "moz_places_temp", "url", "UNIQUE" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_PLACES_URL \
|
||||
CREATE_PLACES_IDX( \
|
||||
"url_uniqueindex", "moz_places", "url", "UNIQUE" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_PLACES_TEMP_FAVICON \
|
||||
CREATE_PLACES_IDX( \
|
||||
"faviconindex", "moz_places_temp", "favicon_id", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_PLACES_FAVICON \
|
||||
CREATE_PLACES_IDX( \
|
||||
"faviconindex", "moz_places", "favicon_id", "" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_PLACES_TEMP_REVHOST \
|
||||
CREATE_PLACES_IDX( \
|
||||
"hostindex", "moz_places_temp", "rev_host", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_PLACES_REVHOST \
|
||||
CREATE_PLACES_IDX( \
|
||||
"hostindex", "moz_places", "rev_host", "" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_PLACES_TEMP_VISITCOUNT \
|
||||
CREATE_PLACES_IDX( \
|
||||
"visitcount", "moz_places_temp", "visit_count", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_PLACES_VISITCOUNT \
|
||||
CREATE_PLACES_IDX( \
|
||||
"visitcount", "moz_places", "visit_count", "" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_PLACES_TEMP_FRECENCY \
|
||||
CREATE_PLACES_IDX( \
|
||||
"frecencyindex", "moz_places_temp", "frecency", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_PLACES_FRECENCY \
|
||||
CREATE_PLACES_IDX( \
|
||||
"frecencyindex", "moz_places", "frecency", "" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_PLACES_TEMP_LASTVISITDATE \
|
||||
CREATE_PLACES_IDX( \
|
||||
"lastvisitdateindex", "moz_places_temp", "last_visit_date", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_PLACES_LASTVISITDATE \
|
||||
CREATE_PLACES_IDX( \
|
||||
"lastvisitdateindex", "moz_places", "last_visit_date", "" \
|
||||
@ -107,28 +83,16 @@
|
||||
* moz_historyvisits
|
||||
*/
|
||||
|
||||
#define CREATE_IDX_MOZ_HISTORYVISITS_TEMP_PLACEDATE \
|
||||
CREATE_PLACES_IDX( \
|
||||
"placedateindex", "moz_historyvisits_temp", "place_id, visit_date", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_HISTORYVISITS_PLACEDATE \
|
||||
CREATE_PLACES_IDX( \
|
||||
"placedateindex", "moz_historyvisits", "place_id, visit_date", "" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_HISTORYVISITS_TEMP_FROMVISIT \
|
||||
CREATE_PLACES_IDX( \
|
||||
"fromindex", "moz_historyvisits_temp", "from_visit", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_HISTORYVISITS_FROMVISIT \
|
||||
CREATE_PLACES_IDX( \
|
||||
"fromindex", "moz_historyvisits", "from_visit", "" \
|
||||
)
|
||||
|
||||
#define CREATE_IDX_MOZ_HISTORYVISITS_TEMP_VISITDATE \
|
||||
CREATE_PLACES_IDX( \
|
||||
"dateindex", "moz_historyvisits_temp", "visit_date", "" \
|
||||
)
|
||||
#define CREATE_IDX_MOZ_HISTORYVISITS_VISITDATE \
|
||||
CREATE_PLACES_IDX( \
|
||||
"dateindex", "moz_historyvisits", "visit_date", "" \
|
||||
|
@ -40,8 +40,9 @@
|
||||
#ifndef __nsPlacesTables_h__
|
||||
#define __nsPlacesTables_h__
|
||||
|
||||
#define CREATE_MOZ_PLACES_BASE(__name, __temporary) NS_LITERAL_CSTRING( \
|
||||
"CREATE " __temporary " TABLE " __name " ( " \
|
||||
|
||||
#define CREATE_MOZ_PLACES NS_LITERAL_CSTRING( \
|
||||
"CREATE TABLE moz_places ( " \
|
||||
" id INTEGER PRIMARY KEY" \
|
||||
", url LONGVARCHAR" \
|
||||
", title LONGVARCHAR" \
|
||||
@ -54,22 +55,12 @@
|
||||
", last_visit_date INTEGER " \
|
||||
")" \
|
||||
)
|
||||
#define CREATE_MOZ_PLACES CREATE_MOZ_PLACES_BASE("moz_places", "")
|
||||
#define CREATE_MOZ_PLACES_TEMP CREATE_MOZ_PLACES_BASE("moz_places_temp", "TEMP")
|
||||
#define MOZ_PLACES_COLUMNS \
|
||||
"id, url, title, rev_host, visit_count, hidden, typed, favicon_id, " \
|
||||
"frecency, last_visit_date"
|
||||
#define CREATE_MOZ_PLACES_VIEW NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY VIEW moz_places_view AS " \
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places_temp " \
|
||||
"UNION ALL " \
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places " \
|
||||
"WHERE id NOT IN (SELECT id FROM moz_places_temp) " \
|
||||
)
|
||||
|
||||
|
||||
#define CREATE_MOZ_HISTORYVISITS_BASE(__name, __temporary) NS_LITERAL_CSTRING( \
|
||||
"CREATE " __temporary " TABLE " __name " (" \
|
||||
#define CREATE_MOZ_HISTORYVISITS NS_LITERAL_CSTRING( \
|
||||
"CREATE TABLE moz_historyvisits (" \
|
||||
" id INTEGER PRIMARY KEY" \
|
||||
", from_visit INTEGER" \
|
||||
", place_id INTEGER" \
|
||||
@ -78,19 +69,9 @@
|
||||
", session INTEGER" \
|
||||
")" \
|
||||
)
|
||||
#define CREATE_MOZ_HISTORYVISITS \
|
||||
CREATE_MOZ_HISTORYVISITS_BASE("moz_historyvisits", "")
|
||||
#define CREATE_MOZ_HISTORYVISITS_TEMP \
|
||||
CREATE_MOZ_HISTORYVISITS_BASE("moz_historyvisits_temp", "TEMP")
|
||||
#define MOZ_HISTORYVISITS_COLUMNS \
|
||||
"id, from_visit, place_id, visit_date, visit_type, session"
|
||||
#define CREATE_MOZ_HISTORYVISITS_VIEW NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY VIEW moz_historyvisits_view AS " \
|
||||
"SELECT " MOZ_HISTORYVISITS_COLUMNS " FROM moz_historyvisits_temp " \
|
||||
"UNION ALL " \
|
||||
"SELECT " MOZ_HISTORYVISITS_COLUMNS " FROM moz_historyvisits " \
|
||||
"WHERE id NOT IN (SELECT id FROM moz_historyvisits_temp) " \
|
||||
)
|
||||
|
||||
|
||||
#define CREATE_MOZ_INPUTHISTORY NS_LITERAL_CSTRING( \
|
||||
"CREATE TABLE moz_inputhistory (" \
|
||||
|
@ -73,198 +73,33 @@
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger allows for an insertion into moz_places_view. It enters the new
|
||||
* data into the temporary table, ensuring that the new id is one greater than
|
||||
* the largest id value found.
|
||||
* We have both sync and async users for this trigger, so it could happen that
|
||||
* an async statement tries to insert a page when a sync statement just added
|
||||
* it. We should ignore the insertion in such a case, the async implementer
|
||||
* will fetch the id of the existing entry.
|
||||
* This triggers update visit_count and last_visit_date based on historyvisits
|
||||
* table changes.
|
||||
*/
|
||||
#define CREATE_PLACES_VIEW_INSERT_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER moz_places_view_insert_trigger " \
|
||||
"INSTEAD OF INSERT " \
|
||||
"ON moz_places_view " \
|
||||
#define CREATE_HISTORYVISITS_AFTERINSERT_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TRIGGER moz_historyvisits_afterinsert_v2_trigger " \
|
||||
"AFTER INSERT ON moz_historyvisits FOR EACH ROW " \
|
||||
"BEGIN " \
|
||||
"INSERT OR IGNORE INTO moz_places_temp (" MOZ_PLACES_COLUMNS ") " \
|
||||
"VALUES (MAX(IFNULL((SELECT MAX(id) FROM moz_places_temp), 0), " \
|
||||
"IFNULL((SELECT MAX(id) FROM moz_places), 0)) + 1," \
|
||||
"NEW.url, NEW.title, NEW.rev_host, " \
|
||||
"IFNULL(NEW.visit_count, 0), " /* enforce having a value */ \
|
||||
"NEW.hidden, NEW.typed, NEW.favicon_id, NEW.frecency, " \
|
||||
"NEW.last_visit_date);" \
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger allows for the deletion of a record in moz_places_view. It
|
||||
* removes any entry in the temporary table, the permanent table, and any
|
||||
* associated entry in moz_openpages_temp.
|
||||
*/
|
||||
#define CREATE_PLACES_VIEW_DELETE_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER moz_places_view_delete_trigger " \
|
||||
"INSTEAD OF DELETE " \
|
||||
"ON moz_places_view " \
|
||||
"BEGIN " \
|
||||
"DELETE FROM moz_places_temp " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"DELETE FROM moz_places " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"DELETE FROM moz_openpages_temp " \
|
||||
"WHERE url = OLD.url; " \
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger allows for updates to a record in moz_places_view. It first
|
||||
* copies the row from the permanent table over to the temp table if it does not
|
||||
* exist in the temporary table. Then, it will update the temporary table with
|
||||
* the new data.
|
||||
* We use INSERT OR IGNORE to avoid looking if the place already exists in the
|
||||
* temp table.
|
||||
*/
|
||||
#define CREATE_PLACES_VIEW_UPDATE_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER moz_places_view_update_trigger " \
|
||||
"INSTEAD OF UPDATE " \
|
||||
"ON moz_places_view " \
|
||||
"BEGIN " \
|
||||
"INSERT OR IGNORE INTO moz_places_temp (" MOZ_PLACES_COLUMNS ") " \
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"UPDATE moz_places_temp " \
|
||||
"SET url = IFNULL(NEW.url, OLD.url), " \
|
||||
"title = IFNULL(NEW.title, OLD.title), " \
|
||||
"rev_host = IFNULL(NEW.rev_host, OLD.rev_host), " \
|
||||
"visit_count = IFNULL(NEW.visit_count, OLD.visit_count), " \
|
||||
"hidden = IFNULL(NEW.hidden, OLD.hidden), " \
|
||||
"typed = IFNULL(NEW.typed, OLD.typed), " \
|
||||
"favicon_id = IFNULL(NEW.favicon_id, OLD.favicon_id), " \
|
||||
"frecency = IFNULL(NEW.frecency, OLD.frecency), " \
|
||||
"last_visit_date = IFNULL(NEW.last_visit_date, OLD.last_visit_date) " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger allows for an insertion into moz_historyvisits_view. It enters
|
||||
* the new data into the temporary table, ensuring that the new id is one
|
||||
* greater than the largest id value found. It then updates moz_places_view
|
||||
* with the new visit count.
|
||||
* We use INSERT OR IGNORE to avoid looking if the place already exists in the
|
||||
* temp table.
|
||||
* In this case when updating last_visit_date we can simply check the maximum
|
||||
* between new visit date and the actual cached value (or 0 if it is NULL).
|
||||
*/
|
||||
#define CREATE_HISTORYVISITS_VIEW_INSERT_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER moz_historyvisits_view_insert_trigger " \
|
||||
"INSTEAD OF INSERT " \
|
||||
"ON moz_historyvisits_view " \
|
||||
"BEGIN " \
|
||||
"INSERT INTO moz_historyvisits_temp (" MOZ_HISTORYVISITS_COLUMNS ") " \
|
||||
"VALUES (MAX(IFNULL((SELECT MAX(id) FROM moz_historyvisits_temp), 0), " \
|
||||
"IFNULL((SELECT MAX(id) FROM moz_historyvisits), 0)) + 1, " \
|
||||
"NEW.from_visit, NEW.place_id, NEW.visit_date, NEW.visit_type, " \
|
||||
"NEW.session); " \
|
||||
"INSERT OR IGNORE INTO moz_places_temp (" MOZ_PLACES_COLUMNS ") " \
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places " \
|
||||
"WHERE id = NEW.place_id " \
|
||||
"AND NEW.visit_type NOT IN (" EXCLUDED_VISIT_TYPES "); " \
|
||||
"UPDATE moz_places_temp " \
|
||||
"SET visit_count = visit_count + 1 " \
|
||||
"WHERE id = NEW.place_id " \
|
||||
"AND NEW.visit_type NOT IN (" EXCLUDED_VISIT_TYPES "); " \
|
||||
"UPDATE moz_places_temp " \
|
||||
"SET last_visit_date = MAX(IFNULL(last_visit_date, 0), NEW.visit_date)" \
|
||||
"UPDATE moz_places SET " \
|
||||
"visit_count = visit_count + (SELECT NEW.visit_type NOT IN (" EXCLUDED_VISIT_TYPES ")), "\
|
||||
"last_visit_date = MAX(IFNULL(last_visit_date, 0), NEW.visit_date) " \
|
||||
"WHERE id = NEW.place_id;" \
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger allows for the deletion of a record in moz_historyvisits_view.
|
||||
* It removes any entry in the temporary table, and removes any entry in the
|
||||
* permanent table as well. It then updates moz_places_view with the new visit
|
||||
* count.
|
||||
* We use INSERT OR IGNORE to avoid looking if the place already exists in the
|
||||
* temp table.
|
||||
*/
|
||||
#define CREATE_HISTORYVISITS_VIEW_DELETE_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER moz_historyvisits_view_delete_trigger " \
|
||||
"INSTEAD OF DELETE " \
|
||||
"ON moz_historyvisits_view " \
|
||||
#define CREATE_HISTORYVISITS_AFTERDELETE_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TRIGGER moz_historyvisits_afterdelete_v2_trigger " \
|
||||
"AFTER DELETE ON moz_historyvisits FOR EACH ROW " \
|
||||
"BEGIN " \
|
||||
"DELETE FROM moz_historyvisits_temp " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"DELETE FROM moz_historyvisits " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"INSERT OR IGNORE INTO moz_places_temp (" MOZ_PLACES_COLUMNS ") " \
|
||||
"SELECT " MOZ_PLACES_COLUMNS " FROM moz_places " \
|
||||
"WHERE id = OLD.place_id " \
|
||||
"AND OLD.visit_type NOT IN (" EXCLUDED_VISIT_TYPES "); " \
|
||||
"UPDATE moz_places_temp " \
|
||||
"SET visit_count = visit_count - 1 " \
|
||||
"WHERE id = OLD.place_id " \
|
||||
"AND OLD.visit_type NOT IN (" EXCLUDED_VISIT_TYPES "); " \
|
||||
"UPDATE moz_places_temp " \
|
||||
"SET last_visit_date = " \
|
||||
"(SELECT visit_date FROM moz_historyvisits_temp " \
|
||||
"WHERE place_id = OLD.place_id " \
|
||||
"UNION ALL " \
|
||||
"SELECT visit_date FROM moz_historyvisits " \
|
||||
"WHERE place_id = OLD.place_id " \
|
||||
"ORDER BY visit_date DESC LIMIT 1) " \
|
||||
"WHERE id = OLD.place_id; " \
|
||||
"UPDATE moz_places SET " \
|
||||
"visit_count = visit_count - (SELECT OLD.visit_type NOT IN (" EXCLUDED_VISIT_TYPES ")), "\
|
||||
"last_visit_date = (SELECT visit_date FROM moz_historyvisits " \
|
||||
"WHERE place_id = OLD.place_id " \
|
||||
"ORDER BY visit_date DESC LIMIT 1) " \
|
||||
"WHERE id = OLD.place_id;" \
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger allows for updates to a record in moz_historyvisits_view. It
|
||||
* first copies the row from the permanent table over to the temp table if it
|
||||
* does not exist in the temporary table. Then it will update the temporary
|
||||
* table with the new data.
|
||||
* We use INSERT OR IGNORE to avoid looking if the visit already exists in the
|
||||
* temp table.
|
||||
*/
|
||||
#define CREATE_HISTORYVISITS_VIEW_UPDATE_TRIGGER NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER moz_historyvisits_view_update_trigger " \
|
||||
"INSTEAD OF UPDATE " \
|
||||
"ON moz_historyvisits_view " \
|
||||
"BEGIN " \
|
||||
"INSERT OR IGNORE INTO moz_historyvisits_temp (" MOZ_HISTORYVISITS_COLUMNS ") " \
|
||||
"SELECT " MOZ_HISTORYVISITS_COLUMNS " FROM moz_historyvisits " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"UPDATE moz_historyvisits_temp " \
|
||||
"SET from_visit = IFNULL(NEW.from_visit, OLD.from_visit), " \
|
||||
"place_id = IFNULL(NEW.place_id, OLD.place_id), " \
|
||||
"visit_date = IFNULL(NEW.visit_date, OLD.visit_date), " \
|
||||
"visit_type = IFNULL(NEW.visit_type, OLD.visit_type), " \
|
||||
"session = IFNULL(NEW.session, OLD.session) " \
|
||||
"WHERE id = OLD.id; " \
|
||||
"END" \
|
||||
)
|
||||
|
||||
/**
|
||||
* This trigger moves the data out of a temporary table into the permanent one
|
||||
* before deleting from the temporary table.
|
||||
*
|
||||
* Note - it's OK to use an INSERT OR REPLACE here because the only conflict
|
||||
* that will happen is the primary key. As a result, the row will be deleted,
|
||||
* and the replacement will be inserted with the same id.
|
||||
*/
|
||||
#define CREATE_TEMP_SYNC_TRIGGER_BASE(__table, __columns) NS_LITERAL_CSTRING( \
|
||||
"CREATE TEMPORARY TRIGGER " __table "_beforedelete_trigger " \
|
||||
"BEFORE DELETE ON " __table "_temp FOR EACH ROW " \
|
||||
"BEGIN " \
|
||||
"INSERT OR REPLACE INTO " __table " (" __columns ") " \
|
||||
"SELECT " __columns " FROM " __table "_temp " \
|
||||
"WHERE id = OLD.id;" \
|
||||
"END" \
|
||||
)
|
||||
#define CREATE_MOZ_PLACES_SYNC_TRIGGER \
|
||||
CREATE_TEMP_SYNC_TRIGGER_BASE("moz_places", MOZ_PLACES_COLUMNS)
|
||||
#define CREATE_MOZ_HISTORYVISITS_SYNC_TRIGGER \
|
||||
CREATE_TEMP_SYNC_TRIGGER_BASE("moz_historyvisits", MOZ_HISTORYVISITS_COLUMNS)
|
||||
|
||||
|
||||
/**
|
||||
* This trigger removes a row from moz_openpages_temp when open_count reaches 0.
|
||||
*/
|
||||
|
@ -8,12 +8,6 @@ contract @mozilla.org/browser/tagging-service;1 {bbc23860-2553-479d-8b78-94d9038
|
||||
component {1dcc23b0-d4cb-11dc-9ad6-479d56d89593} nsTaggingService.js
|
||||
contract @mozilla.org/autocomplete/search;1?name=places-tag-autocomplete {1dcc23b0-d4cb-11dc-9ad6-479d56d89593}
|
||||
|
||||
# nsPlacesDBFlush.js
|
||||
component {c1751cfc-e8f1-4ade-b0bb-f74edfb8ef6a} nsPlacesDBFlush.js
|
||||
contract @mozilla.org/places/sync;1 {c1751cfc-e8f1-4ade-b0bb-f74edfb8ef6a}
|
||||
category bookmark-observers nsPlacesDBFlush @mozilla.org/places/sync;1
|
||||
category history-observers nsPlacesDBFlush @mozilla.org/places/sync;1
|
||||
|
||||
# nsPlacesExpiration.js
|
||||
component {705a423f-2f69-42f3-b9fe-1517e0dee56f} nsPlacesExpiration.js
|
||||
contract @mozilla.org/places/expiration;1 {705a423f-2f69-42f3-b9fe-1517e0dee56f}
|
||||
|
@ -49,7 +49,6 @@ MODULE = test_places
|
||||
XPCSHELL_TESTS = \
|
||||
autocomplete \
|
||||
expiration \
|
||||
sync \
|
||||
bookmarks \
|
||||
queries \
|
||||
unit \
|
||||
|
@ -72,7 +72,7 @@ function run_test()
|
||||
// open the result container
|
||||
queryRes.root.containerOpen = true;
|
||||
// debug queries
|
||||
// dump_table("moz_places_view");
|
||||
// dump_table("moz_places");
|
||||
do_check_eq(queryRes.root.childCount, 1);
|
||||
// call the untested code path
|
||||
listener.onValueRemoved(null, uri.spec, true);
|
||||
|
@ -36,8 +36,6 @@ var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnectio
|
||||
function getColumn(table, column, fromColumnName, fromColumnValue)
|
||||
{
|
||||
var stmt = conn.createStatement(
|
||||
"SELECT " + column + " FROM " + table + "_temp WHERE " + fromColumnName + "=:val " +
|
||||
"UNION ALL " +
|
||||
"SELECT " + column + " FROM " + table + " WHERE " + fromColumnName + "=:val " +
|
||||
"LIMIT 1");
|
||||
try {
|
||||
|
@ -51,8 +51,6 @@ var conn = PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase).DBConnectio
|
||||
function getColumn(table, column, fromColumnName, fromColumnValue)
|
||||
{
|
||||
var stmt = conn.createStatement(
|
||||
"SELECT " + column + " FROM " + table + "_temp WHERE " + fromColumnName + "=:val " +
|
||||
"UNION ALL " +
|
||||
"SELECT " + column + " FROM " + table + " WHERE " + fromColumnName + "=:val " +
|
||||
"LIMIT 1");
|
||||
try {
|
||||
|
@ -182,16 +182,12 @@ do_get_place(nsIURI* aURI, PlaceRecord& result)
|
||||
do_check_success(rv);
|
||||
|
||||
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT id, hidden, typed, visit_count FROM moz_places_temp "
|
||||
"WHERE url=?1 "
|
||||
"UNION ALL "
|
||||
"SELECT id, hidden, typed, visit_count FROM moz_places "
|
||||
"WHERE url=?1 "
|
||||
"LIMIT 1"
|
||||
), getter_AddRefs(stmt));
|
||||
do_check_success(rv);
|
||||
|
||||
rv = stmt->BindUTF8StringParameter(0, spec);
|
||||
rv = stmt->BindUTF8StringByIndex(0, spec);
|
||||
do_check_success(rv);
|
||||
|
||||
PRBool hasResults;
|
||||
@ -222,16 +218,13 @@ do_get_lastVisit(PRInt64 placeId, VisitRecord& result)
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
|
||||
nsresult rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT id, from_visit, visit_type FROM moz_historyvisits_temp "
|
||||
"WHERE place_id=?1 "
|
||||
"UNION ALL "
|
||||
"SELECT id, from_visit, visit_type FROM moz_historyvisits "
|
||||
"WHERE place_id=?1 "
|
||||
"LIMIT 1"
|
||||
), getter_AddRefs(stmt));
|
||||
do_check_success(rv);
|
||||
|
||||
rv = stmt->BindInt64Parameter(0, placeId);
|
||||
rv = stmt->BindInt64ByIndex(0, placeId);
|
||||
do_check_success(rv);
|
||||
|
||||
PRBool hasResults;
|
||||
|
@ -90,7 +90,7 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy,
|
||||
// Update dateAdded for the last added annotation.
|
||||
sql = "UPDATE moz_annos SET dateAdded = :expire_date, lastModified = :last_modified " +
|
||||
"WHERE id = (SELECT a.id FROM moz_annos a " +
|
||||
"LEFT JOIN moz_places_view h on h.id = a.place_id " +
|
||||
"LEFT JOIN moz_places h on h.id = a.place_id " +
|
||||
"WHERE h.url = :id " +
|
||||
"ORDER BY a.dateAdded DESC LIMIT 1)";
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ function add_old_anno(aIdentifier, aName, aValue, aExpirePolicy,
|
||||
"WHERE id = ( " +
|
||||
"SELECT a.id FROM moz_annos a " +
|
||||
"JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id " +
|
||||
"JOIN moz_places_view h on h.id = a.place_id " +
|
||||
"JOIN moz_places h on h.id = a.place_id " +
|
||||
"WHERE h.url = :id " +
|
||||
"AND n.name = :anno_name " +
|
||||
"ORDER BY a.dateAdded DESC LIMIT 1 " +
|
||||
|
@ -257,7 +257,7 @@ function dump_table(aName)
|
||||
function page_in_database(aUrl)
|
||||
{
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT id FROM moz_places_view WHERE url = :url"
|
||||
"SELECT id FROM moz_places WHERE url = :url"
|
||||
);
|
||||
stmt.params.url = aUrl;
|
||||
try {
|
||||
@ -459,6 +459,57 @@ function check_JSON_backup() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Waits for a frecency update then calls back.
|
||||
*
|
||||
* @param aUrl
|
||||
* Address of the page we are waiting frecency for.
|
||||
* @param aValidator
|
||||
* Validator function for the current frecency. If it returns true we
|
||||
* have the expected frecency, otherwise we wait for next update.
|
||||
* @param aCallback
|
||||
* function invoked when frecency update finishes.
|
||||
* @param aCbScope
|
||||
* "this" scope for the callback
|
||||
* @param aCbArguments
|
||||
* array of arguments to be passed to the callback
|
||||
*
|
||||
* @note since frecency is something that can be changed by a bunch of stuff
|
||||
* like adding and removing visits, bookmarks we use a polling strategy.
|
||||
*/
|
||||
function waitForFrecency(aUrl, aValidator, aCallback, aCbScope, aCbArguments) {
|
||||
Services.obs.addObserver(function (aSubject, aTopic, aData) {
|
||||
let frecency = frecencyForUrl(aUrl);
|
||||
if (!aValidator(frecency)) {
|
||||
return;
|
||||
}
|
||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
||||
aCallback.apply(aCbScope, aCbArguments);
|
||||
}, "places-frecency-updated", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the frecency of a url.
|
||||
*
|
||||
* @param aURL
|
||||
* the URL to get frecency for.
|
||||
* @return the frecency value.
|
||||
*/
|
||||
function frecencyForUrl(aUrl)
|
||||
{
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT frecency FROM moz_places WHERE url = ?1"
|
||||
);
|
||||
stmt.bindUTF8StringParameter(0, aUrl);
|
||||
if (!stmt.executeStep())
|
||||
throw "No result for frecency.";
|
||||
let frecency = stmt.getInt32(0);
|
||||
stmt.finalize();
|
||||
|
||||
return frecency;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two times in usecs, considering eventual platform timers skews.
|
||||
*
|
||||
@ -478,33 +529,3 @@ function is_time_ordered(before, after) {
|
||||
return after - before > -skew;
|
||||
}
|
||||
|
||||
|
||||
// These tests are known to randomly fail due to bug 507790 when database
|
||||
// flushes are active, so we turn off syncing for them.
|
||||
let (randomFailingSyncTests = [
|
||||
"test_multi_word_tags.js",
|
||||
"test_removeVisitsByTimeframe.js",
|
||||
"test_utils_getURLsForContainerNode.js",
|
||||
"test_exclude_livemarks.js",
|
||||
"test_402799.js",
|
||||
"test_results-as-visit.js",
|
||||
"test_sorting.js",
|
||||
"test_redirectsMode.js",
|
||||
"test_384228.js",
|
||||
"test_395593.js",
|
||||
"test_containersQueries_sorting.js",
|
||||
"test_browserGlue_smartBookmarks.js",
|
||||
"test_browserGlue_distribution.js",
|
||||
"test_331487.js",
|
||||
"test_tags.js",
|
||||
"test_385829.js",
|
||||
"test_405938_restore_queries.js",
|
||||
]) {
|
||||
let currentTestFilename = do_get_file(_TEST_FILE[0], true).leafName;
|
||||
if (randomFailingSyncTests.indexOf(currentTestFilename) != -1) {
|
||||
print("Test " + currentTestFilename +
|
||||
" is known random due to bug 507790, disabling PlacesDBFlush.");
|
||||
let sync = Cc["@mozilla.org/places/sync;1"].getService(Ci.nsIObserver);
|
||||
sync.observe(null, "places-debug-stop-sync", null);
|
||||
}
|
||||
}
|
||||
|
@ -158,11 +158,11 @@ function checkDB(data){
|
||||
ghist.addURI(this.mChannel.URI, true, true, referrer);
|
||||
|
||||
// Get all pages visited from the original typed one
|
||||
var sql = "SELECT url FROM moz_historyvisits_view " +
|
||||
"JOIN moz_places_view h ON h.id = place_id " +
|
||||
var sql = "SELECT url FROM moz_historyvisits " +
|
||||
"JOIN moz_places h ON h.id = place_id " +
|
||||
"WHERE from_visit IN " +
|
||||
"(SELECT v.id FROM moz_historyvisits_view v " +
|
||||
"JOIN moz_places_view p ON p.id = v.place_id " +
|
||||
"(SELECT v.id FROM moz_historyvisits v " +
|
||||
"JOIN moz_places p ON p.id = v.place_id " +
|
||||
"WHERE p.url = ?1)";
|
||||
var stmt = mDBConn.createStatement(sql);
|
||||
stmt.bindUTF8StringParameter(0, typedURI.spec);
|
||||
|
@ -109,8 +109,8 @@ function run_test() {
|
||||
function continue_test() {
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT v.id, h.url, v.from_visit, v.visit_date, v.visit_type, v.session " +
|
||||
"FROM moz_historyvisits_view v " +
|
||||
"JOIN moz_places_view h on h.id = v.place_id " +
|
||||
"FROM moz_historyvisits v " +
|
||||
"JOIN moz_places h on h.id = v.place_id " +
|
||||
"ORDER BY v.id ASC");
|
||||
const EXPECTED = [
|
||||
{ id: 1,
|
||||
|
@ -85,7 +85,7 @@ function populateDB(aArray) {
|
||||
if (qdata.title && !qdata.isDetails) {
|
||||
// Set the page title synchronously, otherwise setPageTitle is LAZY.
|
||||
let stmt = DBConn().createStatement(
|
||||
"UPDATE moz_places_view SET title = :title WHERE url = :url"
|
||||
"UPDATE moz_places SET title = :title WHERE url = :url"
|
||||
);
|
||||
stmt.params.title = qdata.title;
|
||||
stmt.params.url = qdata.uri;
|
||||
@ -102,7 +102,7 @@ function populateDB(aArray) {
|
||||
// Set a fake visit_count, this is not a real count but can be used
|
||||
// to test sorting by visit_count.
|
||||
let stmt = DBConn().createStatement(
|
||||
"UPDATE moz_places_view SET visit_count = :vc WHERE url = :url");
|
||||
"UPDATE moz_places SET visit_count = :vc WHERE url = :url");
|
||||
stmt.params.vc = qdata.visitCount;
|
||||
stmt.params.url = qdata.uri;
|
||||
try {
|
||||
|
@ -100,10 +100,8 @@ function run_test() {
|
||||
testData[i].title = null;
|
||||
}
|
||||
|
||||
dump_table("moz_places");
|
||||
dump_table("moz_places_temp");
|
||||
dump_table("moz_historyvisits");
|
||||
dump_table("moz_historyvisits_temp");
|
||||
//dump_table("moz_places");
|
||||
//dump_table("moz_historyvisits");
|
||||
|
||||
var numSortFunc = function (a,b) { return (a - b); };
|
||||
var arrs = testDataTyped.concat(testDataDownload).concat(testDataBookmark)
|
||||
|
@ -1,136 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Google Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Shawn Wilsher <me@shawnwilsher.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
|
||||
* 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 ***** */
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
// Import common head.
|
||||
let (commonFile = do_get_file("../head_common.js", false)) {
|
||||
let uri = Services.io.newFileURI(commonFile);
|
||||
Services.scriptloader.loadSubScript(uri.spec, this);
|
||||
}
|
||||
|
||||
// Put any other stuff relative to this test folder below.
|
||||
|
||||
|
||||
/**
|
||||
* Function tests to see if the place associated with the bookmark with id
|
||||
* aBookmarkId has the uri aExpectedURI. The event will call do_test_finished()
|
||||
* if aFinish is true.
|
||||
*
|
||||
* @param aBookmarkId
|
||||
* The bookmark to check against.
|
||||
* @param aExpectedURI
|
||||
* The URI we expect to be in moz_places.
|
||||
* @param aExpected
|
||||
* Indicates if we expect to get a result or not.
|
||||
* @param [optional] aFinish
|
||||
* Indicates if the test should be completed or not.
|
||||
*/
|
||||
function new_test_bookmark_uri_event(aBookmarkId, aExpectedURI, aExpected, aFinish)
|
||||
{
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT moz_places.url " +
|
||||
"FROM moz_bookmarks INNER JOIN moz_places " +
|
||||
"ON moz_bookmarks.fk = moz_places.id " +
|
||||
"WHERE moz_bookmarks.id = ?1"
|
||||
);
|
||||
stmt.bindInt64Parameter(0, aBookmarkId);
|
||||
|
||||
if (aExpected) {
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(stmt.getUTF8String(0), aExpectedURI);
|
||||
}
|
||||
else {
|
||||
do_check_false(stmt.executeStep());
|
||||
}
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
|
||||
if (aFinish)
|
||||
do_test_finished();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function tests to see if the place associated with the visit with id aVisitId
|
||||
* has the uri aExpectedURI. The event will call do_test_finished() if aFinish is
|
||||
* true.
|
||||
*
|
||||
* @param aVisitId
|
||||
* The visit to check against.
|
||||
* @param aExpectedURI
|
||||
* The URI we expect to be in moz_places.
|
||||
* @param aExpected
|
||||
* Indicates if we expect to get a result or not.
|
||||
* @param [optional] aFinish
|
||||
* Indicates if the test should be completed or not.
|
||||
*/
|
||||
function new_test_visit_uri_event(aVisitId, aExpectedURI, aExpected, aFinish)
|
||||
{
|
||||
let stmt = DBConn().createStatement(
|
||||
"SELECT moz_places.url " +
|
||||
"FROM moz_historyvisits INNER JOIN moz_places " +
|
||||
"ON moz_historyvisits.place_id = moz_places.id " +
|
||||
"WHERE moz_historyvisits.id = ?1"
|
||||
);
|
||||
stmt.bindInt64Parameter(0, aVisitId);
|
||||
|
||||
if (aExpected) {
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(stmt.getUTF8String(0), aExpectedURI);
|
||||
}
|
||||
else {
|
||||
do_check_false(stmt.executeStep());
|
||||
}
|
||||
stmt.reset();
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
|
||||
if (aFinish)
|
||||
do_test_finished();
|
||||
}
|
||||
|
@ -1,126 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (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 ***** */
|
||||
|
||||
/**
|
||||
* Bug 493933 - When sorting bookmarks BY NONE we should take in count partitioning.
|
||||
*
|
||||
* When we have a bookmarks results sorted BY NONE, could be the order depends
|
||||
* on current status of disk and temp tables due to how the query executes the
|
||||
* UNION. We must ensure their order is correct.
|
||||
*/
|
||||
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 600;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
var observer = {
|
||||
_runCount: 0,
|
||||
one: null,
|
||||
two: null,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
// Skip the first sync.
|
||||
if (++this._runCount < 2)
|
||||
return;
|
||||
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
|
||||
// Sanity check positions.
|
||||
do_check_true(this.one < this.two);
|
||||
do_check_eq(bs.getItemIndex(this.one), 0);
|
||||
do_check_eq(bs.getItemIndex(this.two), 1);
|
||||
|
||||
check_results();
|
||||
|
||||
// Now add a visit to the second bookmark, so that it is in temp table.
|
||||
hs.addVisit(uri("http://2.mozilla.org/"), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
|
||||
// Nothing should change in results.
|
||||
check_results();
|
||||
|
||||
// Cleanup.
|
||||
bs.removeFolderChildren(bs.toolbarFolder);
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function check_results() {
|
||||
// Create a bookmarks query.
|
||||
var options = hs.getNewQueryOptions();
|
||||
options.queryType = Ci.nsINavHistoryQueryOptions.QUERY_TYPE_BOOKMARKS;
|
||||
var query = hs.getNewQuery();
|
||||
query.setFolders([bs.toolbarFolder], 1);
|
||||
query.searchTerms = "mozilla";
|
||||
var result = hs.executeQuery(query, options);
|
||||
var root = result.root;
|
||||
root.containerOpen = true;
|
||||
do_check_eq(root.childCount, 2);
|
||||
do_check_eq(root.getChild(0).title, "mozilla 1");
|
||||
do_check_eq(root.getChild(1).title, "mozilla 2");
|
||||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a large value so we don't sync
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Add two bookmarks and check their index
|
||||
observer.one = bs.insertBookmark(bs.toolbarFolder,
|
||||
uri("http://1.mozilla.org/"),
|
||||
bs.DEFAULT_INDEX, "mozilla 1");
|
||||
observer.two = bs.insertBookmark(bs.toolbarFolder,
|
||||
uri("http://2.mozilla.org/"),
|
||||
bs.DEFAULT_INDEX, "mozilla 2");
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const SYNC_INTERVAL = 600; // ten minutes
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
// Used to update observer itemId
|
||||
var bookmarksObserver = {
|
||||
onItemAdded: function(aItemId, aNewParent, aNewIndex) {
|
||||
observer.itemId = aItemId;
|
||||
}
|
||||
}
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
var observer = {
|
||||
itemId: -1,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
do_check_neq(this.itemId, -1);
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
bs.removeObserver(bookmarksObserver);
|
||||
// Check that moz_places table has been correctly synced
|
||||
new_test_bookmark_uri_event(this.itemId, TEST_URI, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a really large value so it won't
|
||||
// run before the test finishes.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Insert a new bookmark
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder, uri(TEST_URI),
|
||||
bs.DEFAULT_INDEX, "test");
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const SYNC_INTERVAL = 600; // ten minutes
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
// Used to check if we are batching and to update observer itemId
|
||||
var bookmarksObserver = {
|
||||
_batching: false,
|
||||
onBeginUpdateBatch: function() {
|
||||
this._batching = true;
|
||||
},
|
||||
onEndUpdateBatch: function() {
|
||||
this._batching = false;
|
||||
},
|
||||
onItemAdded: function(aItemId, aNewParent, aNewIndex) {
|
||||
observer.itemId = aItemId;
|
||||
}
|
||||
}
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
var observer = {
|
||||
itemId: -1,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
dump(this.itemId);
|
||||
// item id must be valid
|
||||
do_check_neq(this.itemId, -1);
|
||||
// Check that we are not in a batch
|
||||
do_check_false(bookmarksObserver._batching);
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
bs.removeObserver(bookmarksObserver);
|
||||
// Check that tables have been correctly synced
|
||||
new_test_bookmark_uri_event(this.itemId, TEST_URI, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Set the preference for the timer to a really large value, so it won't
|
||||
// run before the test finishes.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Add a bookmark in batch mode
|
||||
let id = -1;
|
||||
bs.runInBatchMode({
|
||||
runBatched: function(aUserData)
|
||||
{
|
||||
id = bs.insertBookmark(bs.unfiledBookmarksFolder, uri(TEST_URI),
|
||||
bs.DEFAULT_INDEX, "test");
|
||||
// We should not sync during a batch
|
||||
new_test_bookmark_uri_event(id, TEST_URI, false);
|
||||
}
|
||||
}, null);
|
||||
// Ensure the bookmark has been added
|
||||
do_check_neq(id, -1);
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 1;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
var observer = {
|
||||
visitId: -1,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished && this.visitId != -1) {
|
||||
// sanity check: visitId set by history observer should be the same we
|
||||
// have added
|
||||
do_check_eq(this.visitId, visitId);
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
// Check the visit
|
||||
new_test_visit_uri_event(this.visitId, TEST_URI, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
// Used to update observer visitId
|
||||
var historyObserver = {
|
||||
onVisit: function(aURI, aVisitId, aTime, aSessionId, aReferringId,
|
||||
aTransitionType, aAdded) {
|
||||
observer.visitId = aVisitId;
|
||||
hs.removeObserver(this, false);
|
||||
}
|
||||
}
|
||||
hs.addObserver(historyObserver, false);
|
||||
|
||||
// used for sanity check
|
||||
var visitId = -1;
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a small value
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Now add the visit
|
||||
visitId = hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
// Used to check if we are batching
|
||||
var bookmarksObserver = {
|
||||
_batching: false,
|
||||
onBeginUpdateBatch: function() {
|
||||
this._batching = true;
|
||||
},
|
||||
onEndUpdateBatch: function() {
|
||||
this._batching = false;
|
||||
}
|
||||
}
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
// Used to update observer visitId
|
||||
var historyObserver = {
|
||||
onVisit: function(aURI, aVisitId, aTime, aSessionId, aReferringId,
|
||||
aTransitionType, aAdded) {
|
||||
observer.visitId = aVisitId;
|
||||
}
|
||||
}
|
||||
hs.addObserver(historyObserver, false);
|
||||
|
||||
var observer = {
|
||||
visitId: -1,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
// visit id must be valid
|
||||
do_check_neq(this.visitId, -1);
|
||||
// Check that we are not in a batch
|
||||
do_check_false(bookmarksObserver._batching);
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
bs.removeObserver(bookmarksObserver);
|
||||
hs.removeObserver(historyObserver);
|
||||
// Check that tables have been correctly synced
|
||||
new_test_visit_uri_event(this.visitId, TEST_URI, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Add a visit in batch mode
|
||||
let id = -1;
|
||||
bs.runInBatchMode({
|
||||
runBatched: function(aUserData)
|
||||
{
|
||||
id = hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
// We should not sync during a batch
|
||||
new_test_visit_uri_event(id, TEST_URI, false);
|
||||
}
|
||||
}, null);
|
||||
// Ensure the visit has been added
|
||||
do_check_neq(id, -1);
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
const MODIFIED_URI = "http://test.com/index.html";
|
||||
|
||||
const SYNC_INTERVAL = 600; // ten minutes
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
// Used to update observer itemId
|
||||
var bookmarksObserver = {
|
||||
onItemAdded: function(aItemId, aNewParent, aNewIndex, aItemType) {
|
||||
observer.itemId = aItemId;
|
||||
},
|
||||
onItemChanged: function(aItemId, aProperty, aNewValue, aLastModified,
|
||||
aItemType) {
|
||||
if (aProperty == "uri")
|
||||
do_check_eq(observer.itemId, aItemId);
|
||||
}
|
||||
}
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
var observer = {
|
||||
itemId: -1,
|
||||
_runCount: 0,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
// item id must be valid
|
||||
do_check_neq(this.itemId, -1);
|
||||
if (++this._runCount == 1) {
|
||||
// First sync is fired by adding the bookmark
|
||||
// Check that tables have been synced after insertBookmark
|
||||
new_test_bookmark_uri_event(this.itemId, TEST_URI, true);
|
||||
// Now modify the bookmark
|
||||
bs.changeBookmarkURI(this.itemId, uri(MODIFIED_URI));
|
||||
}
|
||||
else if (this._runCount == 2) {
|
||||
// Second sync is fired by changing the bookmark's uri
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
bs.removeObserver(bookmarksObserver);
|
||||
// Check that tables have been synced after changeBookmarkURI
|
||||
new_test_bookmark_uri_event(this.itemId, MODIFIED_URI, true, true);
|
||||
}
|
||||
else
|
||||
do_throw("Too many places sync calls");
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Set the preference for the timer to a really large value, so it won't
|
||||
// run before the test finishes.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Insert a new bookmark
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder, uri(TEST_URI),
|
||||
bs.DEFAULT_INDEX, "test");
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,94 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 600; // ten minutes
|
||||
const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
|
||||
|
||||
var historyObserver = {
|
||||
onVisit: function(aURI, aVisitId, aTime, aSessionId, aReferringId,
|
||||
aTransitionType, aAdded) {
|
||||
observer.visitId = aVisitId;
|
||||
hs.removeObserver(this);
|
||||
}
|
||||
}
|
||||
hs.addObserver(historyObserver, false);
|
||||
|
||||
var observer = {
|
||||
visitId: -1,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == TOPIC_CONNECTION_CLOSED) {
|
||||
os.removeObserver(this, aTopic);
|
||||
|
||||
// visit id must be valid
|
||||
do_check_neq(this.visitId, -1);
|
||||
// Check that tables have been correctly synced
|
||||
new_test_visit_uri_event(this.visitId, TEST_URI, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, TOPIC_CONNECTION_CLOSED, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Set the preference for the timer to a really large value, so it won't
|
||||
// run before the test finishes.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Now add a visit
|
||||
hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
|
||||
// Notify that we are quitting the app - we should sync!
|
||||
shutdownPlaces();
|
||||
|
||||
// Test will continue on sync notification.
|
||||
do_test_pending();
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (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 os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const PREF_SYNC_INTERVAL = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 600; // ten minutes
|
||||
const TOPIC_SYNC_FINISHED = "places-sync-finished";
|
||||
const TOPIC_CONNECTION_CLOSED = "places-connection-closed";
|
||||
|
||||
var historyObserver = {
|
||||
visitId: -1,
|
||||
cleared: false,
|
||||
onVisit: function(aURI, aVisitId, aTime, aSessionId, aReferringId,
|
||||
aTransitionType, aAdded) {
|
||||
this.visitId = aVisitId;
|
||||
},
|
||||
onClearHistory: function() {
|
||||
// check browserHistory returns no entries
|
||||
do_check_eq(0, bh.count);
|
||||
this.cleared = true;
|
||||
hs.removeObserver(this);
|
||||
}
|
||||
}
|
||||
hs.addObserver(historyObserver, false);
|
||||
|
||||
var observer = {
|
||||
_runCount: 0,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == TOPIC_SYNC_FINISHED) {
|
||||
if (++this._runCount == 1) {
|
||||
// The first sync is due to the insert bookmark.
|
||||
// Simulate a clear private data just before shutdown.
|
||||
bh.removeAllPages();
|
||||
os.addObserver(shutdownObserver, TOPIC_CONNECTION_CLOSED, false);
|
||||
// Immediately notify shutdown.
|
||||
shutdownPlaces();
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove the observer, we don't need it anymore.
|
||||
os.removeObserver(this, TOPIC_SYNC_FINISHED);
|
||||
|
||||
// Visit id must be valid.
|
||||
do_check_neq(historyObserver.visitId, -1);
|
||||
// History must have been cleared.
|
||||
do_check_true(historyObserver.cleared);
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, TOPIC_SYNC_FINISHED, false);
|
||||
|
||||
let shutdownObserver = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
os.removeObserver(this, aTopic);
|
||||
do_check_false(PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
|
||||
.DBConnection.connectionReady);
|
||||
|
||||
let dbConn = DBConn();
|
||||
do_check_true(dbConn.connectionReady);
|
||||
|
||||
// Check that frecency for not cleared items (bookmarks) has been
|
||||
// converted to -MAX(visit_count, 1), so we will be able to
|
||||
// recalculate frecency starting from most frecent bookmarks.
|
||||
let stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE frecency > 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h WHERE h.frecency = -2 " +
|
||||
"AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that all visit_counts have been brought to 0
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
dbConn.asyncClose(function() {
|
||||
do_check_false(dbConn.connectionReady);
|
||||
|
||||
do_test_finished();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
do_test_pending();
|
||||
|
||||
// Set the preference for the timer to a really large value, so it won't
|
||||
// run before the test finishes.
|
||||
prefs.setIntPref(PREF_SYNC_INTERVAL, SYNC_INTERVAL);
|
||||
|
||||
// Now add a visit before creating bookmark, and one later
|
||||
hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder, uri(TEST_URI),
|
||||
bs.DEFAULT_INDEX, "bookmark");
|
||||
hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (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 ***** */
|
||||
|
||||
/*
|
||||
* This test checks that embed visits are not synced down to disk, we hold
|
||||
* them in memory since they're going to be purged at session close
|
||||
*
|
||||
* We instead sync to disk FRAMED_LINK visits.
|
||||
*/
|
||||
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
const EMBED_URI = "http://embed.test.com/";
|
||||
const PLACE_URI = "place:test.com/";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 1;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
var transitions = [ hs.TRANSITION_LINK,
|
||||
hs.TRANSITION_TYPED,
|
||||
hs.TRANSITION_BOOKMARK,
|
||||
hs.TRANSITION_EMBED,
|
||||
hs.TRANSITION_FRAMED_LINK,
|
||||
hs.TRANSITION_REDIRECT_PERMANENT,
|
||||
hs.TRANSITION_REDIRECT_TEMPORARY,
|
||||
hs.TRANSITION_DOWNLOAD ];
|
||||
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished && this.visitId != -1) {
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
|
||||
// Check that moz_places table has been correctly synced
|
||||
var stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE url = :url");
|
||||
stmt.params["url"] = TEST_URI;
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp WHERE url = :url");
|
||||
stmt.params["url"] = TEST_URI;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE url = :url");
|
||||
stmt.params["url"] = EMBED_URI;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp WHERE url = :url");
|
||||
stmt.params["url"] = EMBED_URI;
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE url = :url");
|
||||
stmt.params["url"] = PLACE_URI;
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp WHERE url = :url");
|
||||
stmt.params["url"] = PLACE_URI;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that all visits but embed ones are in disk table
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT count(*) FROM moz_historyvisits h WHERE visit_type <> :t_embed");
|
||||
stmt.params["t_embed"] = hs.TRANSITION_EMBED;
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(stmt.getInt32(0), (transitions.length - 1) * 2);
|
||||
stmt.finalize();
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_historyvisits h WHERE visit_type = :t_embed");
|
||||
stmt.params["t_embed"] = hs.TRANSITION_EMBED;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_historyvisits_temp h WHERE visit_type = :t_embed");
|
||||
stmt.params["t_embed"] = hs.TRANSITION_EMBED;
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_historyvisits_temp h WHERE visit_type <> :t_embed");
|
||||
stmt.params["t_embed"] = hs.TRANSITION_EMBED;
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a small value
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Add a visit for every transition type on TEST_URI
|
||||
// Embed visit should stay in temp table, while other should be synced
|
||||
// Place entry for this uri should be synced to disk table
|
||||
transitions.forEach(function addVisit(aTransition) {
|
||||
hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
aTransition, false, 0);
|
||||
});
|
||||
|
||||
// Add an embed visit for EMBED_URI
|
||||
// Embed visit should stay in temp table
|
||||
// Place entry for this uri should stay in temp table
|
||||
hs.addVisit(uri(EMBED_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_EMBED, false, 0);
|
||||
|
||||
// Add a visit for every transition type on PLACE_URI
|
||||
// Embed visit should stay in temp table
|
||||
// Place entry for this uri should be synced to disk table
|
||||
transitions.forEach(function addVisit(aTransition) {
|
||||
hs.addVisit(uri(PLACE_URI), Date.now() * 1000, null,
|
||||
aTransition, false, 0);
|
||||
});
|
||||
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,134 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (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 ***** */
|
||||
|
||||
/*
|
||||
* This test ensures favicons are correctly expired by expireAllFavicons API,
|
||||
* both synced and unsynced favicons should be expired.
|
||||
*/
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var dbConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var icons = Cc["@mozilla.org/browser/favicon-service;1"].
|
||||
getService(Ci.nsIFaviconService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
const TEST_ICON_URI = "http://test.com/favicon.ico";
|
||||
const TEST_NOSYNC_URI = "http://nosync.test.com/";
|
||||
const TEST_NOSYNC_ICON_URI = "http://nosync.test.com/favicon.ico";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 600;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
const kExpirationFinished = "places-favicons-expired";
|
||||
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
|
||||
// Add a not synced page with a visit.
|
||||
hs.addVisit(uri(TEST_NOSYNC_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
// Set a favicon for the page.
|
||||
icons.setFaviconUrlForPage(uri(TEST_NOSYNC_URI), uri(TEST_NOSYNC_ICON_URI));
|
||||
|
||||
// Check both a synced and a not-synced favicons exist.
|
||||
let stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE url = :url AND favicon_id NOT NULL");
|
||||
stmt.params["url"] = TEST_URI;
|
||||
do_check_true(stmt.executeStep());
|
||||
|
||||
stmt.finalize();
|
||||
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp WHERE url = :url AND favicon_id NOT NULL");
|
||||
stmt.params["url"] = TEST_NOSYNC_URI;
|
||||
do_check_true(stmt.executeStep());
|
||||
|
||||
stmt.finalize();
|
||||
|
||||
// Expire all favicons.
|
||||
icons.expireAllFavicons();
|
||||
}
|
||||
else if (aTopic == kExpirationFinished) {
|
||||
os.removeObserver(this, kExpirationFinished);
|
||||
// Check all favicons have been removed.
|
||||
let stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_favicons");
|
||||
do_check_false(stmt.executeStep());
|
||||
|
||||
stmt.finalize();
|
||||
|
||||
stmt = dbConn.createStatement(
|
||||
"SELECT id FROM moz_places_view WHERE favicon_id NOT NULL");
|
||||
do_check_false(stmt.executeStep());
|
||||
|
||||
stmt.finalize();
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
os.addObserver(observer, kExpirationFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a large value so we don't sync.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Add a page with a visit.
|
||||
let visitId = hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
// Set a favicon for the page.
|
||||
icons.setFaviconUrlForPage(uri(TEST_URI), uri(TEST_ICON_URI));
|
||||
|
||||
// Now add a bookmark to force a sync.
|
||||
bs.insertBookmark(bs.toolbarFolder, uri(TEST_URI), bs.DEFAULT_INDEX, "visited");
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (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 ***** */
|
||||
|
||||
/*
|
||||
* This test checks that when we add an item we sync only if its type is
|
||||
* TYPE_BOOKMARKS
|
||||
*/
|
||||
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 600;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
var syncObserver = {
|
||||
_numSyncs: 0,
|
||||
finalSync: false,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
if (++this._numSyncs > 1 || !this.finalSync)
|
||||
do_throw("We synced too many times: " + this._numSyncs);
|
||||
|
||||
// remove the observers
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
bs.removeObserver(bookmarksObserver, false);
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(syncObserver, kSyncFinished, false);
|
||||
|
||||
var bookmarksObserver = {
|
||||
onItemAdded: function(aItemId, aNewParent, aNewIndex) {
|
||||
if (bs.getItemType(aItemId) == bs.TYPE_BOOKMARK)
|
||||
syncObserver.finalSync = true;
|
||||
}
|
||||
}
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// dynamic container sample
|
||||
do_load_manifest("../unit/nsDynamicContainerServiceSample.manifest");
|
||||
|
||||
// First set the preference for the timer to a large value, so it won't sync
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Add a folder
|
||||
bs.createFolder(bs.toolbarFolder, "folder", bs.DEFAULT_INDEX);
|
||||
|
||||
// Add a dynamic container
|
||||
bs.createDynamicContainer(bs.toolbarFolder, "dynamic",
|
||||
"@mozilla.org/browser/remote-container-sample;1",
|
||||
bs.DEFAULT_INDEX);
|
||||
|
||||
// Add a separator
|
||||
bs.insertSeparator(bs.toolbarFolder, bs.DEFAULT_INDEX);
|
||||
|
||||
// Add a bookmark, this will trigger final sync
|
||||
bs.insertBookmark(bs.toolbarFolder, uri(TEST_URI), bs.DEFAULT_INDEX, "bookmark");
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77@bonardo.net> (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 bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 600;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
// Set the preference for the timer to a large value so we don't sync.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Now add another visit, be sure to use a different session, so we
|
||||
// will also test grouping by uri.
|
||||
hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 1);
|
||||
|
||||
// Create the history menu query.
|
||||
var options = hs.getNewQueryOptions();
|
||||
options.maxResults = 10;
|
||||
options.resultType = options.RESULTS_AS_URI;
|
||||
options.sortingMode = options.SORT_BY_DATE_DESCENDING;
|
||||
var query = hs.getNewQuery();
|
||||
var result = hs.executeQuery(query, options);
|
||||
var root = result.root;
|
||||
root.containerOpen = true;
|
||||
do_check_eq(root.childCount, 1);
|
||||
root.containerOpen = false;
|
||||
|
||||
// Create the most visited query.
|
||||
options = hs.getNewQueryOptions();
|
||||
options.maxResults = 10;
|
||||
options.resultType = options.RESULTS_AS_URI;
|
||||
options.sortingMode = options.SORT_BY_VISITCOUNT_DESCENDING;
|
||||
query = hs.getNewQuery();
|
||||
result = hs.executeQuery(query, options);
|
||||
root = result.root;
|
||||
root.containerOpen = true;
|
||||
do_check_eq(root.childCount, 1);
|
||||
root.containerOpen = false;
|
||||
|
||||
// Create basic uri query.
|
||||
options = hs.getNewQueryOptions();
|
||||
query = hs.getNewQuery();
|
||||
result = hs.executeQuery(query, options);
|
||||
root = result.root;
|
||||
root.containerOpen = true;
|
||||
do_check_eq(root.childCount, 1);
|
||||
root.containerOpen = false;
|
||||
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a small value so we sync
|
||||
prefs.setIntPref(kSyncPrefName, 1);
|
||||
|
||||
// Now add the visit
|
||||
let visitId = hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
do_test_pending();
|
||||
}
|
@ -1,150 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* This test ensures that adding a bookmark (which has an implicit sync), then
|
||||
* adding another one that has the same place, we end up with only one entry in
|
||||
* moz_places.
|
||||
*/
|
||||
|
||||
var bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var db = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const SYNC_INTERVAL = 600; // ten minutes
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
// Used to update observer itemId
|
||||
var bookmarksObserver = {
|
||||
onItemAdded: function(aItemId, aNewParent, aNewIndex) {
|
||||
observer.itemIds.push(aItemId);
|
||||
}
|
||||
}
|
||||
bs.addObserver(bookmarksObserver, false);
|
||||
|
||||
var observer = {
|
||||
itemIds: [],
|
||||
_placeId: -1,
|
||||
_runCount: 0,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished) {
|
||||
if (++this._runCount == 1) {
|
||||
let itemId = this.itemIds[this._runCount - 1];
|
||||
// item id must be valid
|
||||
do_check_neq(itemId, null);
|
||||
// Ensure tables have been synced
|
||||
new_test_bookmark_uri_event(itemId, TEST_URI, true);
|
||||
|
||||
// Get the place_id
|
||||
let stmt = db.createStatement(
|
||||
"SELECT fk " +
|
||||
"FROM moz_bookmarks " +
|
||||
"WHERE id = ?"
|
||||
);
|
||||
stmt.bindInt64Parameter(0, itemId);
|
||||
do_check_true(stmt.executeStep());
|
||||
this._placeId = stmt.getInt64(0);
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
// place id must be valid
|
||||
do_check_true(this._placeId > 0);
|
||||
}
|
||||
else if (this._runCount == 2) {
|
||||
let itemId = this.itemIds[this._runCount - 1];
|
||||
// item id must be valid
|
||||
do_check_neq(itemId, null);
|
||||
// Ensure it was added
|
||||
new_test_bookmark_uri_event(itemId, TEST_URI, true);
|
||||
|
||||
// Check to make sure we have the same place_id
|
||||
stmt = db.createStatement(
|
||||
"SELECT * " +
|
||||
"FROM moz_bookmarks " +
|
||||
"WHERE id = ?1 " +
|
||||
"AND fk = ?2"
|
||||
);
|
||||
stmt.bindInt64Parameter(0, itemId);
|
||||
stmt.bindInt64Parameter(1, this._placeId);
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
|
||||
// remove the observer, we don't need to observe sync on quit
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
bs.removeObserver(bookmarksObserver);
|
||||
// test ends here
|
||||
do_test_finished();
|
||||
}
|
||||
else
|
||||
do_throw("Too many places sync calls");
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// Set the preference for the timer to a really large value, so it won't
|
||||
// run before the test finishes.
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Add the first bookmark
|
||||
let id1 = bs.insertBookmark(bs.unfiledBookmarksFolder, uri(TEST_URI),
|
||||
bs.DEFAULT_INDEX, "test");
|
||||
|
||||
// Now we add another bookmark to a different folder
|
||||
let id2 = bs.insertBookmark(bs.toolbarFolder, uri(TEST_URI),
|
||||
bs.DEFAULT_INDEX, "test");
|
||||
do_check_neq(id1, id2);
|
||||
|
||||
do_test_pending();
|
||||
}
|
@ -1,152 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
* 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
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* This test ensures that when adding a visit, then syncing, and adding another
|
||||
* visit to the same url creates two visits and that we only end up with one
|
||||
* entry in moz_places.
|
||||
*/
|
||||
|
||||
var hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
var db = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
var prefs = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefService).
|
||||
getBranch("places.");
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const TEST_URI = "http://test.com/";
|
||||
|
||||
const kSyncPrefName = "syncDBTableIntervalInSecs";
|
||||
const SYNC_INTERVAL = 1;
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
|
||||
var observer = {
|
||||
visitId: -1,
|
||||
_runCount: 0,
|
||||
_placeId: -1,
|
||||
_lastVisitId: -1,
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == kSyncFinished && this.visitId != -1) {
|
||||
// Check the visit
|
||||
new_test_visit_uri_event(this.visitId, TEST_URI, true);
|
||||
|
||||
// sanity check: visitId set by history observer should be the same we
|
||||
// have added
|
||||
do_check_eq(this.visitId, visitIds[this._runCount]);
|
||||
|
||||
if (++this._runCount == 1) {
|
||||
// Get the place_id and pass it on
|
||||
let stmt = db.createStatement(
|
||||
"SELECT place_id " +
|
||||
"FROM moz_historyvisits " +
|
||||
"WHERE id = ?1"
|
||||
);
|
||||
stmt.bindInt64Parameter(0, this.visitId);
|
||||
do_check_true(stmt.executeStep());
|
||||
this._placeId = stmt.getInt64(0);
|
||||
this._lastVisitId = this.visitId;
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
|
||||
// clear cached value before continue test
|
||||
this.visitId = -1;
|
||||
continue_test();
|
||||
}
|
||||
else if (this._runCount == 2) {
|
||||
do_check_neq(this.visitId, this._lastVisitId);
|
||||
// Get the place_id and check for equality
|
||||
let stmt = db.createStatement(
|
||||
"SELECT place_id " +
|
||||
"FROM moz_historyvisits " +
|
||||
"WHERE id = ?1"
|
||||
);
|
||||
stmt.bindInt64Parameter(0, this.visitId);
|
||||
do_check_true(stmt.executeStep());
|
||||
do_check_eq(this._placeId, stmt.getInt64(0));
|
||||
stmt.finalize();
|
||||
stmt = null;
|
||||
|
||||
// remove the observers
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
hs.removeObserver(historyObserver, false);
|
||||
do_test_finished();
|
||||
}
|
||||
else
|
||||
do_throw("bad runCount!");
|
||||
}
|
||||
}
|
||||
}
|
||||
os.addObserver(observer, kSyncFinished, false);
|
||||
|
||||
// Used to update observer visitId
|
||||
var historyObserver = {
|
||||
onVisit: function(aURI, aVisitId, aTime, aSessionId, aReferringId,
|
||||
aTransitionType, aAdded) {
|
||||
do_check_true(aVisitId > 0);
|
||||
observer.visitId = aVisitId;
|
||||
}
|
||||
}
|
||||
hs.addObserver(historyObserver, false);
|
||||
|
||||
// used for sanity checks
|
||||
var visitIds = [];
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// First set the preference for the timer to a small value
|
||||
prefs.setIntPref(kSyncPrefName, SYNC_INTERVAL);
|
||||
|
||||
// Now add the first visit
|
||||
visitIds[0] = hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function continue_test()
|
||||
{
|
||||
// Now we add another visit
|
||||
visitIds[1] = hs.addVisit(uri(TEST_URI), Date.now() * 1000, null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
}
|
@ -45,8 +45,6 @@ var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
var bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory);
|
||||
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
var ios = Cc["@mozilla.org/network/io-service;1"].
|
||||
getService(Components.interfaces.nsIIOService);
|
||||
|
||||
/**
|
||||
* Function prohibits an attempt to pop up a confirmation
|
||||
@ -249,22 +247,13 @@ function run_test() {
|
||||
var pb = get_PBSvc();
|
||||
|
||||
if (pb) { // Private Browsing might not be available
|
||||
// need to catch places sync notifications
|
||||
var os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
do_test_pending();
|
||||
|
||||
var prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||
getService(Ci.nsIPrefBranch);
|
||||
prefBranch.setBoolPref("browser.privatebrowsing.keep_current_session", true);
|
||||
|
||||
var bookmark_A_URI = ios.newURI("http://google.com/", null, null);
|
||||
var bookmark_B_URI = ios.newURI("http://bugzilla.mozilla.org/", null, null);
|
||||
var onBookmarkAAdded = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
Services.prefs.setBoolPref("browser.privatebrowsing.keep_current_session", true);
|
||||
|
||||
var bookmark_A_URI = NetUtil.newURI("http://google.com/");
|
||||
var bookmark_B_URI = NetUtil.newURI("http://bugzilla.mozilla.org/");
|
||||
var onBookmarkAAdded = function() {
|
||||
check_placesItem_Count();
|
||||
|
||||
// Bookmark-A should be bookmarked, data should be retrievable
|
||||
@ -298,16 +287,11 @@ function run_test() {
|
||||
do_check_true(bmsvc.isBookmarked(bookmark_A_URI));
|
||||
do_check_eq("google",bmsvc.getKeywordForURI(bookmark_A_URI));
|
||||
|
||||
os.addObserver(onBookmarkBAdded, kSyncFinished, false);
|
||||
|
||||
// Create Bookmark-B
|
||||
myBookmarks[1] = create_bookmark(bookmark_B_URI,"title 2", "bugzilla");
|
||||
}
|
||||
onBookmarkBAdded();
|
||||
};
|
||||
var onBookmarkBAdded = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
os.removeObserver(this, kSyncFinished);
|
||||
|
||||
var onBookmarkBAdded = function() {
|
||||
// A check on the history count should be same as before, 7 history entries with
|
||||
// now 2 bookmark items (A) and bookmark (B), so we set num_places_entries to 9
|
||||
num_places_entries = 10; // Bookmark-B successfully added but not the history entries.
|
||||
@ -330,9 +314,8 @@ function run_test() {
|
||||
do_check_true(bhist.isVisited(uri(visited_uri)));
|
||||
}
|
||||
|
||||
prefBranch.clearUserPref("browser.privatebrowsing.keep_current_session");
|
||||
Services.prefs.clearUserPref("browser.privatebrowsing.keep_current_session");
|
||||
do_test_finished();
|
||||
}
|
||||
};
|
||||
|
||||
// History database should be empty
|
||||
@ -344,8 +327,6 @@ function run_test() {
|
||||
// History database should have entries
|
||||
do_check_true(histsvc.hasHistoryEntries);
|
||||
|
||||
os.addObserver(onBookmarkAAdded, kSyncFinished, false);
|
||||
|
||||
// Create Bookmark-A
|
||||
myBookmarks[0] = create_bookmark(bookmark_A_URI,"title 1", "google");
|
||||
|
||||
@ -354,5 +335,7 @@ function run_test() {
|
||||
do_check_true(bhist.isVisited(uri(visited_uri)));
|
||||
do_check_true(uri_in_db(uri(visited_uri)));
|
||||
}
|
||||
|
||||
onBookmarkAAdded();
|
||||
}
|
||||
}
|
||||
|
@ -44,275 +44,230 @@
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=412132
|
||||
*/
|
||||
|
||||
const bmServ =
|
||||
Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
const histServ =
|
||||
Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
const lmServ =
|
||||
Cc["@mozilla.org/browser/livemark-service;2"].
|
||||
getService(Ci.nsILivemarkService);
|
||||
const bmServ = PlacesUtils.bookmarks;
|
||||
const histServ = PlacesUtils.history;
|
||||
const lmServ = PlacesUtils.livemarks;
|
||||
|
||||
var defaultBookmarksMaxId;
|
||||
var dbConn;
|
||||
var tests = [];
|
||||
|
||||
tests.push({
|
||||
let tests = [
|
||||
{
|
||||
desc: ["Frecency of unvisited, separately bookmarked livemark item's URI ",
|
||||
"should be zero after bookmark's URI changed."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
var lmItemURL;
|
||||
var lmItemURI;
|
||||
var bmId;
|
||||
var frecencyBefore;
|
||||
var frecencyAfter;
|
||||
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
lmItemURL = "http://example.com/livemark-item";
|
||||
lmItemURI = uri(lmItemURL);
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0.");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
frecencyBefore = getFrecency(lmItemURL);
|
||||
do_check_neq(frecencyBefore, 0);
|
||||
|
||||
bmServ.changeBookmarkURI(bmId, uri("http://example.com/new-uri"));
|
||||
|
||||
// URI's only "bookmark" is now unvisited livemark item => frecency = 0.
|
||||
frecencyAfter = getFrecency(lmItemURL);
|
||||
do_check_eq(frecencyAfter, 0);
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/new-uri"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["Frecency of visited, separately bookmarked livemark item's URI ",
|
||||
"should not be zero after bookmark's URI changed."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
var lmItemURL;
|
||||
var lmItemURI;
|
||||
var bmId;
|
||||
var frecencyBefore;
|
||||
var frecencyAfter;
|
||||
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
lmItemURL = "http://example.com/livemark-item";
|
||||
lmItemURI = uri(lmItemURL);
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
let lmItemURI = uri(lmItemURL);
|
||||
createLivemark(lmItemURI);
|
||||
bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
frecencyBefore = getFrecency(lmItemURL);
|
||||
do_check_neq(frecencyBefore, 0);
|
||||
visit(uri(aUrl));
|
||||
|
||||
visit(lmItemURI);
|
||||
|
||||
bmServ.changeBookmarkURI(bmId, uri("http://example.com/new-uri"));
|
||||
|
||||
// URI's only "bookmark" is now *visited* livemark item => frecency != 0.
|
||||
frecencyAfter = getFrecency(lmItemURL);
|
||||
do_check_neq(frecencyAfter, 0);
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/new-uri"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After changing URI of bookmark, frecency of bookmark's original URI ",
|
||||
"should be zero if original URI is unvisited and no longer ",
|
||||
"bookmarked."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
var url;
|
||||
var bmId;
|
||||
var frecencyBefore;
|
||||
var frecencyAfter;
|
||||
let url = "http://example.com/1";
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(url, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [url, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId) {
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
url = "http://example.com/1";
|
||||
bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/2"));
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
frecencyBefore = getFrecency(url);
|
||||
do_check_neq(frecencyBefore, 0);
|
||||
|
||||
bmServ.changeBookmarkURI(bmId, uri("http://example.com/2"));
|
||||
|
||||
// Unvisited URI no longer bookmarked => frecency should = 0.
|
||||
frecencyAfter = getFrecency(url);
|
||||
do_check_eq(frecencyAfter, 0);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After changing URI of bookmark, frecency of bookmark's original URI ",
|
||||
"should not be zero if original URI is visited."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
var bmURL;
|
||||
var bmURI;
|
||||
var bmId;
|
||||
var frecencyBefore;
|
||||
var frecencyAfter;
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(bmURL),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
bmURL = "http://example.com/1";
|
||||
bmURI = uri(bmURL);
|
||||
|
||||
bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
frecencyBefore = getFrecency(bmURL);
|
||||
do_check_neq(frecencyBefore, 0);
|
||||
|
||||
visit(bmURI);
|
||||
bmServ.changeBookmarkURI(bmId, uri("http://example.com/2"));
|
||||
|
||||
// *Visited* URI no longer bookmarked => frecency should != 0.
|
||||
frecencyAfter = getFrecency(bmURL);
|
||||
do_check_neq(frecencyAfter, 0);
|
||||
visit(uri(aUrl));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl, aItemId]);
|
||||
},
|
||||
check2: function (aUrl, aItemId)
|
||||
{
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/2"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check3, this, [aUrl]);
|
||||
},
|
||||
check3: function (aUrl)
|
||||
{
|
||||
print("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After changing URI of bookmark, frecency of bookmark's original URI ",
|
||||
"should not be zero if original URI is still bookmarked."].join(""),
|
||||
run: function ()
|
||||
{
|
||||
var bmURL;
|
||||
var bmURI;
|
||||
var bm1Id;
|
||||
var bm2Id;
|
||||
var frecencyBefore;
|
||||
var frecencyAfter;
|
||||
let bmURL = "http://example.com/1";
|
||||
let bm1Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(bmURL),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
|
||||
bmURL = "http://example.com/1";
|
||||
bmURI = uri(bmURL);
|
||||
let bm2Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(bmURL),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bm1Id]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
bm1Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 1 title");
|
||||
|
||||
bm2Id = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
frecencyBefore = getFrecency(bmURL);
|
||||
do_check_neq(frecencyBefore, 0);
|
||||
|
||||
bmServ.changeBookmarkURI(bm1Id, uri("http://example.com/2"));
|
||||
|
||||
// URI still bookmarked => frecency should != 0.
|
||||
frecencyAfter = getFrecency(bmURL);
|
||||
do_check_neq(frecencyAfter, 0);
|
||||
bmServ.changeBookmarkURI(aItemId, uri("http://example.com/2"));
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI still bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: "Changing the URI of a nonexistent bookmark should fail.",
|
||||
run: function ()
|
||||
{
|
||||
var stmt;
|
||||
var maxId;
|
||||
var bmId;
|
||||
|
||||
function tryChange(itemId)
|
||||
{
|
||||
var failed;
|
||||
|
||||
failed= false;
|
||||
try
|
||||
{
|
||||
try {
|
||||
bmServ.changeBookmarkURI(itemId + 1, uri("http://example.com/2"));
|
||||
do_throw("Nonexistent bookmark should throw.");
|
||||
}
|
||||
catch (exc)
|
||||
{
|
||||
failed= true;
|
||||
}
|
||||
do_check_true(failed);
|
||||
catch (exc) {}
|
||||
}
|
||||
|
||||
// First try a straight-up bogus item ID, one greater than the current max
|
||||
// ID.
|
||||
stmt = dbConn.createStatement("SELECT MAX(id) FROM moz_bookmarks");
|
||||
let stmt = DBConn().createStatement("SELECT MAX(id) FROM moz_bookmarks");
|
||||
stmt.executeStep();
|
||||
maxId = stmt.getInt32(0);
|
||||
let maxId = stmt.getInt32(0);
|
||||
stmt.finalize();
|
||||
tryChange(maxId + 1);
|
||||
|
||||
// Now add a bookmark, delete it, and check.
|
||||
bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri("http://example.com/"),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri("http://example.com/"),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
bmServ.removeItem(bmId);
|
||||
tryChange(bmId);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
function createLivemark(lmItemURI)
|
||||
{
|
||||
var lmId;
|
||||
var lmItemId;
|
||||
|
||||
lmId = lmServ.createLivemarkFolderOnly(bmServ.unfiledBookmarksFolder,
|
||||
"livemark title",
|
||||
uri("http://www.mozilla.org/"),
|
||||
uri("http://www.mozilla.org/news.rdf"),
|
||||
-1);
|
||||
lmItemId = bmServ.insertBookmark(lmId,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
return lmItemId;
|
||||
}
|
||||
|
||||
function getFrecency(url)
|
||||
{
|
||||
var sql;
|
||||
var stmt;
|
||||
var frecency;
|
||||
|
||||
sql = "SELECT frecency FROM moz_places_view WHERE url = ?1";
|
||||
stmt = dbConn.createStatement(sql);
|
||||
stmt.bindUTF8StringParameter(0, url);
|
||||
do_check_true(stmt.executeStep());
|
||||
frecency = stmt.getInt32(0);
|
||||
print("frecency=" + frecency);
|
||||
stmt.finalize();
|
||||
|
||||
return frecency;
|
||||
}
|
||||
|
||||
function prepTest(testName, callback)
|
||||
{
|
||||
print("Test: " + testName);
|
||||
waitForClearHistory(function() {
|
||||
dbConn.executeSimpleSQL("DELETE FROM moz_places_view");
|
||||
dbConn.executeSimpleSQL("DELETE FROM moz_bookmarks WHERE id > " +
|
||||
defaultBookmarksMaxId);
|
||||
callback();
|
||||
runNextTest();
|
||||
});
|
||||
let lmId = lmServ.createLivemarkFolderOnly(bmServ.unfiledBookmarksFolder,
|
||||
"livemark title",
|
||||
uri("http://www.mozilla.org/"),
|
||||
uri("http://www.mozilla.org/news.rdf"),
|
||||
-1);
|
||||
return bmServ.insertBookmark(lmId,
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
}
|
||||
|
||||
function visit(uri)
|
||||
@ -330,27 +285,19 @@ function visit(uri)
|
||||
function run_test()
|
||||
{
|
||||
do_test_pending();
|
||||
var stmt;
|
||||
|
||||
dbConn =
|
||||
Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
|
||||
stmt = dbConn.createStatement("SELECT MAX(id) FROM moz_bookmarks");
|
||||
stmt.executeStep();
|
||||
defaultBookmarksMaxId = stmt.getInt32(0);
|
||||
stmt.finalize();
|
||||
do_check_true(defaultBookmarksMaxId > 0);
|
||||
|
||||
runNextTest();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
let currentTest;
|
||||
function runNextTest() {
|
||||
function run_next_test()
|
||||
{
|
||||
if (tests.length) {
|
||||
currentTest = tests.shift();
|
||||
prepTest(currentTest.desc, currentTest.run);
|
||||
let test = tests.shift();
|
||||
print("\n ***Test: " + test.desc);
|
||||
waitForClearHistory(function() {
|
||||
DBConn().executeSimpleSQL("DELETE FROM moz_places");
|
||||
remove_all_bookmarks();
|
||||
test.run.call(test);
|
||||
});
|
||||
}
|
||||
else {
|
||||
do_test_finished();
|
||||
|
@ -57,7 +57,7 @@ function add_visit(aURI, aVisitDate, aVisitType) {
|
||||
aVisitType != hs.TRANSITION_DOWNLOAD)
|
||||
visit_count ++;
|
||||
// Get the place id
|
||||
var sql = "SELECT place_id FROM moz_historyvisits_view WHERE id = ?1";
|
||||
var sql = "SELECT place_id FROM moz_historyvisits WHERE id = ?1";
|
||||
var stmt = mDBConn.createStatement(sql);
|
||||
stmt.bindInt64Parameter(0, visitId);
|
||||
do_check_true(stmt.executeStep());
|
||||
|
@ -138,8 +138,8 @@ let historyObserver = {
|
||||
return;
|
||||
|
||||
// dump tables, useful if the test fails.
|
||||
dump_table("moz_places_temp");
|
||||
dump_table("moz_favicons");
|
||||
//dump_table("moz_places");
|
||||
//dump_table("moz_favicons");
|
||||
|
||||
// Ensure we have been called by the last test.
|
||||
do_check_true(pageURI.equals(uri("http://test4.bar/")));
|
||||
|
@ -37,245 +37,201 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Get services.
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let bh = hs.QueryInterface(Ci.nsIBrowserHistory);
|
||||
let mDBConn = hs.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
let as = Cc["@mozilla.org/browser/annotation-service;1"].
|
||||
getService(Ci.nsIAnnotationService);
|
||||
let os = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
let lms = Cc["@mozilla.org/browser/livemark-service;2"].
|
||||
getService(Ci.nsILivemarkService);
|
||||
|
||||
const kSyncFinished = "places-sync-finished";
|
||||
const kExpirationFinished = "places-expiration-finished";
|
||||
|
||||
// Number of expected sync notifications, we expect one per bookmark.
|
||||
const EXPECTED_SYNCS = 4;
|
||||
let mDBConn = DBConn();
|
||||
|
||||
function add_fake_livemark() {
|
||||
let lmId = lms.createLivemarkFolderOnly(bs.toolbarFolder,
|
||||
"Livemark",
|
||||
uri("http://www.mozilla.org/"),
|
||||
uri("http://www.mozilla.org/test.xml"),
|
||||
bs.DEFAULT_INDEX);
|
||||
// add a visited child
|
||||
bs.insertBookmark(lmId, uri("http://visited.livemark.com/"),
|
||||
bs.DEFAULT_INDEX, "visited");
|
||||
hs.addVisit(uri("http://visited.livemark.com/"), Date.now(), null,
|
||||
hs.TRANSITION_BOOKMARK, false, 0);
|
||||
// add an unvisited child
|
||||
bs.insertBookmark(lmId, uri("http://unvisited.livemark.com/"),
|
||||
bs.DEFAULT_INDEX, "unvisited");
|
||||
let lmId = PlacesUtils.livemarks.createLivemarkFolderOnly(
|
||||
PlacesUtils.toolbarFolderId, "Livemark",
|
||||
uri("http://www.mozilla.org/"), uri("http://www.mozilla.org/test.xml"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX
|
||||
);
|
||||
// Add a visited child.
|
||||
PlacesUtils.bookmarks.insertBookmark(lmId,
|
||||
uri("http://visited.livemark.com/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"visited");
|
||||
PlacesUtils.history.addVisit(uri("http://visited.livemark.com/"),
|
||||
Date.now(), null,
|
||||
Ci.nsINavHistoryService.TRANSITION_BOOKMARK,
|
||||
false, 0);
|
||||
// Add an unvisited child.
|
||||
PlacesUtils.bookmarks.insertBookmark(lmId,
|
||||
uri("http://unvisited.livemark.com/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"unvisited");
|
||||
}
|
||||
|
||||
let observer = {
|
||||
onBeginUpdateBatch: function() {
|
||||
},
|
||||
onEndUpdateBatch: function() {
|
||||
},
|
||||
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) {
|
||||
},
|
||||
onTitleChanged: function(aURI, aPageTitle) {
|
||||
},
|
||||
onBeforeDeleteURI: function(aURI) {
|
||||
},
|
||||
onDeleteURI: function(aURI) {
|
||||
},
|
||||
let historyObserver = {
|
||||
onBeginUpdateBatch: function() {},
|
||||
onEndUpdateBatch: function() {},
|
||||
onVisit: function() {},
|
||||
onTitleChanged: function() {},
|
||||
onBeforeDeleteURI: function() {},
|
||||
onDeleteURI: function(aURI) {},
|
||||
onPageChanged: function() {},
|
||||
onDeleteVisits: function() {},
|
||||
|
||||
onClearHistory: function() {
|
||||
PlacesUtils.history.removeObserver(this, false);
|
||||
|
||||
// check browserHistory returns no entries
|
||||
do_check_eq(0, bh.count);
|
||||
do_check_eq(0, PlacesUtils.bhistory.count);
|
||||
|
||||
let expirationObserver = {
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
os.removeObserver(this, kExpirationFinished, false);
|
||||
|
||||
Services.obs.removeObserver(this, aTopic, false);
|
||||
|
||||
// Check that frecency for not cleared items (bookmarks) has been converted
|
||||
// to -MAX(visit_count, 1), so we will be able to recalculate frecency
|
||||
// starting from most frecent bookmarks.
|
||||
// Memory table has been updated, disk table has not
|
||||
// starting from most frecent bookmarks.
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp WHERE frecency > 0 LIMIT 1");
|
||||
"SELECT h.id FROM moz_places h WHERE h.frecency > 0 ");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places_temp h WHERE h.frecency = -2 " +
|
||||
"SELECT h.id FROM moz_places h WHERE h.frecency = -2 " +
|
||||
"AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that all visit_counts have been brought to 0
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp WHERE visit_count <> 0 LIMIT 1");
|
||||
"SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that history tables are empty
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT * FROM (SELECT id FROM moz_historyvisits_temp LIMIT 1) " +
|
||||
"UNION ALL " +
|
||||
"SELECT * FROM (SELECT id FROM moz_historyvisits LIMIT 1)");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// force a sync and check again disk tables, insertBookmark will do that
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder, uri("place:folder=4"),
|
||||
bs.DEFAULT_INDEX, "shortcut");
|
||||
// Check that all moz_places entries except bookmarks and place: have been removed
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h WHERE SUBSTR(h.url, 1, 6) <> 'place:' "+
|
||||
"AND NOT EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that we only have favicons for retained places
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT f.id FROM moz_favicons f WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE favicon_id = f.id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that we only have annotations for retained places
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT a.id FROM moz_annos a WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = a.place_id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that we only have inputhistory for retained places
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT i.place_id FROM moz_inputhistory i WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = i.place_id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that place:uris have frecency 0
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h " +
|
||||
"WHERE SUBSTR(h.url, 1, 6) = 'place:' AND h.frecency <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that livemarks children don't have frecency <> 0
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h " +
|
||||
"JOIN moz_bookmarks b ON h.id = b.fk " +
|
||||
"JOIN moz_bookmarks bp ON bp.id = b.parent " +
|
||||
"JOIN moz_items_annos t ON t.item_id = bp.id " +
|
||||
"JOIN moz_anno_attributes n ON t.anno_attribute_id = n.id " +
|
||||
"WHERE n.name = 'livemark/feedURI' AND h.frecency <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
os.addObserver(expirationObserver, kExpirationFinished, false);
|
||||
Services.obs.addObserver(expirationObserver,
|
||||
PlacesUtils.TOPIC_EXPIRATION_FINISHED,
|
||||
false);
|
||||
},
|
||||
|
||||
onPageChanged: function(aURI, aWhat, aValue) {
|
||||
},
|
||||
onDeleteVisits: function() {
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(Ci.nsINavHistoryObserver) ||
|
||||
iid.equals(Ci.nsISupports)) {
|
||||
return this;
|
||||
}
|
||||
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsINavHistoryObserver,
|
||||
]),
|
||||
}
|
||||
hs.addObserver(observer, false);
|
||||
PlacesUtils.history.addObserver(historyObserver, false);
|
||||
|
||||
let syncObserver = {
|
||||
_runCount: 0,
|
||||
observe: function (aSubject, aTopic, aData) {
|
||||
if (++this._runCount < EXPECTED_SYNCS)
|
||||
return;
|
||||
if (this._runCount == EXPECTED_SYNCS) {
|
||||
bh.removeAllPages();
|
||||
return;
|
||||
}
|
||||
os.removeObserver(this, kSyncFinished, false);
|
||||
|
||||
// Sanity: check that places temp table is empty
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT id FROM moz_places_temp LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that frecency for not cleared items (bookmarks) has been converted
|
||||
// to -MAX(visit_count, 1), so we will be able to recalculate frecency
|
||||
// starting from most frecent bookmarks.
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE frecency > 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h WHERE h.frecency = -2 " +
|
||||
"AND EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
|
||||
do_check_true(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that all visit_counts have been brought to 0
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT id FROM moz_places WHERE visit_count <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that all moz_places entries except bookmarks and place: have been removed
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h WHERE SUBSTR(h.url, 1, 6) <> 'place:' "+
|
||||
"AND NOT EXISTS (SELECT id FROM moz_bookmarks WHERE fk = h.id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that we only have favicons for retained places
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT f.id FROM moz_favicons f WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE favicon_id = f.id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that we only have annotations for retained places
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT a.id FROM moz_annos a WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = a.place_id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that we only have inputhistory for retained places
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT i.place_id FROM moz_inputhistory i WHERE NOT EXISTS " +
|
||||
"(SELECT id FROM moz_places WHERE id = i.place_id) LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that place:uris have frecency 0
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h " +
|
||||
"WHERE SUBSTR(h.url, 1, 6) = 'place:' AND h.frecency <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
// Check that livemarks children don't have frecency <> 0
|
||||
stmt = mDBConn.createStatement(
|
||||
"SELECT h.id FROM moz_places h " +
|
||||
"JOIN moz_bookmarks b ON h.id = b.fk " +
|
||||
"JOIN moz_bookmarks bp ON bp.id = b.parent " +
|
||||
"JOIN moz_items_annos t ON t.item_id = bp.id " +
|
||||
"JOIN moz_anno_attributes n ON t.anno_attribute_id = n.id " +
|
||||
"WHERE n.name = 'livemark/feedURI' AND h.frecency <> 0 LIMIT 1");
|
||||
do_check_false(stmt.executeStep());
|
||||
stmt.finalize();
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
os.addObserver(syncObserver, kSyncFinished, false);
|
||||
|
||||
// main
|
||||
function run_test() {
|
||||
// places-init-complete is notified after run_test, and it will
|
||||
// run a first frecency fix through async statements.
|
||||
// To avoid random failures we have to run after all of this.
|
||||
Services.obs.addObserver(function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(arguments.callee, aTopic, false);
|
||||
do_execute_soon(continue_test);
|
||||
}, PlacesUtils.TOPIC_INIT_COMPLETE, false);
|
||||
|
||||
do_test_pending();
|
||||
}
|
||||
|
||||
function continue_test() {
|
||||
// Add a livemark with a visited and an unvisited child
|
||||
add_fake_livemark();
|
||||
|
||||
// Add a bunch of visits
|
||||
hs.addVisit(uri("http://typed.mozilla.org"), Date.now(), null,
|
||||
hs.TRANSITION_TYPED, false, 0);
|
||||
|
||||
hs.addVisit(uri("http://link.mozilla.org"), Date.now(), null,
|
||||
hs.TRANSITION_LINK, false, 0);
|
||||
hs.addVisit(uri("http://download.mozilla.org"), Date.now(), null,
|
||||
hs.TRANSITION_DOWNLOAD, false, 0);
|
||||
hs.addVisit(uri("http://invalid.mozilla.org"), Date.now(), null,
|
||||
0, false, 0); // invalid transition
|
||||
hs.addVisit(uri("http://redir_temp.mozilla.org"), Date.now(),
|
||||
uri("http://link.mozilla.org"), hs.TRANSITION_REDIRECT_TEMPORARY,
|
||||
true, 0);
|
||||
hs.addVisit(uri("http://redir_perm.mozilla.org"), Date.now(),
|
||||
uri("http://link.mozilla.org"), hs.TRANSITION_REDIRECT_PERMANENT,
|
||||
true, 0);
|
||||
PlacesUtils.history.addVisit(uri("http://typed.mozilla.org/"), Date.now(),
|
||||
null, Ci.nsINavHistoryService.TRANSITION_TYPED,
|
||||
false, 0);
|
||||
PlacesUtils.history.addVisit(uri("http://link.mozilla.org/"), Date.now(),
|
||||
null, Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
false, 0);
|
||||
PlacesUtils.history.addVisit(uri("http://download.mozilla.org/"), Date.now(),
|
||||
null, Ci.nsINavHistoryService.TRANSITION_DOWNLOAD,
|
||||
false, 0);
|
||||
PlacesUtils.history.addVisit(uri("http://invalid.mozilla.org/"), Date.now(),
|
||||
null, 0, false, 0); // Use an invalid transition.
|
||||
PlacesUtils.history.addVisit(uri("http://redir_temp.mozilla.org/"), Date.now(),
|
||||
uri("http://link.mozilla.org/"),
|
||||
Ci.nsINavHistoryService.TRANSITION_REDIRECT_TEMPORARY,
|
||||
true, 0);
|
||||
PlacesUtils.history.addVisit(uri("http://redir_perm.mozilla.org/"), Date.now(),
|
||||
uri("http://link.mozilla.org/"),
|
||||
Ci.nsINavHistoryService.TRANSITION_REDIRECT_PERMANENT,
|
||||
true, 0);
|
||||
|
||||
// add a place: bookmark
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder, uri("place:folder=4"),
|
||||
bs.DEFAULT_INDEX, "shortcut");
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri("place:folder=4"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"shortcut");
|
||||
|
||||
// Add an expire never annotation
|
||||
// Actually expire never annotations are removed as soon as a page is removed
|
||||
// from the database, so this should act as a normal visit.
|
||||
as.setPageAnnotation(uri("http://download.mozilla.org"), "never", "never", 0,
|
||||
as.EXPIRE_NEVER);
|
||||
PlacesUtils.annotations.setPageAnnotation(uri("http://download.mozilla.org/"),
|
||||
"never", "never", 0,
|
||||
PlacesUtils.annotations.EXPIRE_NEVER);
|
||||
|
||||
// Add a bookmark
|
||||
// Bookmarked page should have history cleared and frecency = -old_visit_count
|
||||
// This will also finally sync temp tables to disk
|
||||
bs.insertBookmark(bs.unfiledBookmarksFolder, uri("http://typed.mozilla.org"),
|
||||
bs.DEFAULT_INDEX, "bookmark");
|
||||
PlacesUtils.bookmarks.insertBookmark(PlacesUtils.unfiledBookmarksFolderId,
|
||||
uri("http://typed.mozilla.org/"),
|
||||
PlacesUtils.bookmarks.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
|
||||
// this visit is not synced to disk
|
||||
hs.addVisit(uri("http://typed.mozilla.org"), Date.now(), null,
|
||||
hs.TRANSITION_BOOKMARK, false, 0);
|
||||
PlacesUtils.history.addVisit(uri("http://typed.mozilla.org/"), Date.now(),
|
||||
null, PlacesUtils.history.TRANSITION_BOOKMARK,
|
||||
false, 0);
|
||||
|
||||
do_test_pending();
|
||||
// Add a last page and wait for its frecency.
|
||||
PlacesUtils.history.addVisit(uri("http://frecency.mozilla.org/"), Date.now(),
|
||||
null, Ci.nsINavHistoryService.TRANSITION_LINK,
|
||||
false, 0);
|
||||
waitForFrecency("http://frecency.mozilla.org/", function (aFrecency) aFrecency > 0,
|
||||
function () {
|
||||
PlacesUtils.bhistory.removeAllPages();
|
||||
}, this, []);
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ function run_test() {
|
||||
|
||||
_("Now that places has migrated, check that it calculated frecencies");
|
||||
var stmt = places.DBConnection.createStatement(
|
||||
"SELECT COUNT(*) FROM moz_places_view WHERE frecency < 0");
|
||||
"SELECT COUNT(*) FROM moz_places WHERE frecency < 0");
|
||||
stmt.executeAsync({
|
||||
handleResult: function(results) {
|
||||
_("Should always get a result from COUNT(*)");
|
||||
|
@ -36,18 +36,14 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
const histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
|
||||
const dbConn = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
const bmsvc = PlacesUtils.bookmarks;
|
||||
const histsvc = PlacesUtils.history;
|
||||
|
||||
const NOW = Date.now() * 1000;
|
||||
const TEST_URI = uri("http://example.com/");
|
||||
const PLACE_URI = uri("place:queryType=0&sort=8&maxResults=10");
|
||||
const TEST_URL = "http://example.com/";
|
||||
const TEST_URI = uri(TEST_URL);
|
||||
const PLACE_URL = "place:queryType=0&sort=8&maxResults=10";
|
||||
const PLACE_URI = uri(PLACE_URL);
|
||||
|
||||
var gTests = [
|
||||
{
|
||||
@ -62,16 +58,16 @@ var gTests = [
|
||||
false,
|
||||
0);
|
||||
}
|
||||
|
||||
print("Get frecency.");
|
||||
var frecency = getFrecencyForURI(TEST_URI);
|
||||
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
this.continue_run, this);
|
||||
},
|
||||
continue_run: function () {
|
||||
print("Remove visits using timerange outside the URI's visits.");
|
||||
histsvc.QueryInterface(Ci.nsIBrowserHistory).
|
||||
removeVisitsByTimeframe(NOW - 10, NOW);
|
||||
|
||||
print("URI should still exist in moz_places.");
|
||||
do_check_true(uriExistsInMozPlaces(TEST_URI));
|
||||
do_check_true(page_in_database(TEST_URL));
|
||||
|
||||
print("Run a history query and check that all visits still exist.");
|
||||
var query = histsvc.getNewQuery();
|
||||
@ -92,7 +88,8 @@ var gTests = [
|
||||
isVisited(TEST_URI));
|
||||
|
||||
print("Frecency should be unchanged.");
|
||||
do_check_eq(getFrecencyForURI(TEST_URI), frecency);
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
run_next_test, Components.utils.getGlobalForObject(this));
|
||||
}
|
||||
},
|
||||
|
||||
@ -115,15 +112,16 @@ var gTests = [
|
||||
bmsvc.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
|
||||
print("Get frecency.");
|
||||
var frecency = getFrecencyForURI(TEST_URI);
|
||||
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
this.continue_run, this);
|
||||
},
|
||||
continue_run: function () {
|
||||
print("Remove visits using timerange outside the URI's visits.");
|
||||
histsvc.QueryInterface(Ci.nsIBrowserHistory).
|
||||
removeVisitsByTimeframe(NOW - 10, NOW);
|
||||
|
||||
print("URI should still exist in moz_places.");
|
||||
do_check_true(uriExistsInMozPlaces(TEST_URI));
|
||||
do_check_true(page_in_database(TEST_URL));
|
||||
|
||||
print("Run a history query and check that all visits still exist.");
|
||||
var query = histsvc.getNewQuery();
|
||||
@ -144,7 +142,8 @@ var gTests = [
|
||||
isVisited(TEST_URI));
|
||||
|
||||
print("Frecency should be unchanged.");
|
||||
do_check_eq(getFrecencyForURI(TEST_URI), frecency);
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
run_next_test, Components.utils.getGlobalForObject(this));
|
||||
}
|
||||
},
|
||||
|
||||
@ -160,16 +159,16 @@ var gTests = [
|
||||
false,
|
||||
0);
|
||||
}
|
||||
|
||||
print("Get frecency.");
|
||||
var frecency = getFrecencyForURI(TEST_URI);
|
||||
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
this.continue_run, this);
|
||||
},
|
||||
continue_run: function () {
|
||||
print("Remove the 5 most recent visits.");
|
||||
histsvc.QueryInterface(Ci.nsIBrowserHistory).
|
||||
removeVisitsByTimeframe(NOW - 4, NOW);
|
||||
|
||||
print("URI should still exist in moz_places.");
|
||||
do_check_true(uriExistsInMozPlaces(TEST_URI));
|
||||
do_check_true(page_in_database(TEST_URL));
|
||||
|
||||
print("Run a history query and check that only the older 5 visits " +
|
||||
"still exist.");
|
||||
@ -191,7 +190,8 @@ var gTests = [
|
||||
isVisited(TEST_URI));
|
||||
|
||||
print("Frecency should be unchanged.");
|
||||
do_check_eq(getFrecencyForURI(TEST_URI), frecency);
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
run_next_test, Components.utils.getGlobalForObject(this));
|
||||
}
|
||||
},
|
||||
|
||||
@ -213,16 +213,16 @@ var gTests = [
|
||||
TEST_URI,
|
||||
bmsvc.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
|
||||
print("Get frecency.");
|
||||
var frecency = getFrecencyForURI(TEST_URI);
|
||||
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
this.continue_run, this);
|
||||
},
|
||||
continue_run: function () {
|
||||
print("Remove the 5 most recent visits.");
|
||||
histsvc.QueryInterface(Ci.nsIBrowserHistory).
|
||||
removeVisitsByTimeframe(NOW - 4, NOW);
|
||||
|
||||
print("URI should still exist in moz_places.");
|
||||
do_check_true(uriExistsInMozPlaces(TEST_URI));
|
||||
do_check_true(page_in_database(TEST_URL));
|
||||
|
||||
print("Run a history query and check that only the older 5 visits " +
|
||||
"still exist.");
|
||||
@ -244,7 +244,8 @@ var gTests = [
|
||||
isVisited(TEST_URI));
|
||||
|
||||
print("Frecency should be unchanged.");
|
||||
do_check_eq(getFrecencyForURI(TEST_URI), frecency);
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency > 0,
|
||||
run_next_test, Components.utils.getGlobalForObject(this));
|
||||
}
|
||||
},
|
||||
|
||||
@ -266,7 +267,7 @@ var gTests = [
|
||||
removeVisitsByTimeframe(NOW - 10, NOW);
|
||||
|
||||
print("URI should no longer exist in moz_places.");
|
||||
do_check_false(uriExistsInMozPlaces(TEST_URI));
|
||||
do_check_false(page_in_database(TEST_URL));
|
||||
|
||||
print("Run a history query and check that no visits exist.");
|
||||
var query = histsvc.getNewQuery();
|
||||
@ -281,6 +282,7 @@ var gTests = [
|
||||
print("nsIGlobalHistory2.isVisited should return false.");
|
||||
do_check_false(histsvc.QueryInterface(Ci.nsIGlobalHistory2).
|
||||
isVisited(TEST_URI));
|
||||
run_next_test();
|
||||
}
|
||||
},
|
||||
|
||||
@ -302,7 +304,7 @@ var gTests = [
|
||||
removeVisitsByTimeframe(NOW - 10, NOW);
|
||||
|
||||
print("URI should still exist in moz_places.");
|
||||
do_check_true(uriExistsInMozPlaces(PLACE_URI));
|
||||
do_check_true(page_in_database(PLACE_URL));
|
||||
|
||||
print("Run a history query and check that no visits exist.");
|
||||
var query = histsvc.getNewQuery();
|
||||
@ -319,7 +321,8 @@ var gTests = [
|
||||
isVisited(PLACE_URI));
|
||||
|
||||
print("Frecency should be 0.");
|
||||
do_check_eq(getFrecencyForURI(PLACE_URI), 0);
|
||||
waitForFrecency(PLACE_URL, function (aFrecency) aFrecency == 0,
|
||||
run_next_test, Components.utils.getGlobalForObject(this));
|
||||
}
|
||||
},
|
||||
|
||||
@ -347,7 +350,7 @@ var gTests = [
|
||||
removeVisitsByTimeframe(NOW - 10, NOW);
|
||||
|
||||
print("URI should still exist in moz_places.");
|
||||
do_check_true(uriExistsInMozPlaces(TEST_URI));
|
||||
do_check_true(page_in_database(TEST_URL));
|
||||
|
||||
print("Run a history query and check that no visits exist.");
|
||||
var query = histsvc.getNewQuery();
|
||||
@ -367,62 +370,31 @@ var gTests = [
|
||||
do_check_true(bmsvc.isBookmarked(TEST_URI));
|
||||
|
||||
print("Frecency should be -visit_count == -10.");
|
||||
do_check_eq(getFrecencyForURI(TEST_URI), -10);
|
||||
waitForFrecency(TEST_URL, function (aFrecency) aFrecency == -10,
|
||||
run_next_test, Components.utils.getGlobalForObject(this));
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Removes history and bookmarks.
|
||||
*/
|
||||
function deleteAllHistoryAndBookmarks() {
|
||||
histsvc.QueryInterface(Ci.nsIBrowserHistory).removeAllPages();
|
||||
remove_all_bookmarks();
|
||||
function run_test()
|
||||
{
|
||||
do_test_pending();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the frecency of a URI.
|
||||
*
|
||||
* @param aURI
|
||||
* the URI of a place
|
||||
* @return the frecency of aURI
|
||||
*/
|
||||
function getFrecencyForURI(aURI) {
|
||||
let sql = "SELECT frecency FROM moz_places_view WHERE url = :url";
|
||||
let stmt = dbConn.createStatement(sql);
|
||||
stmt.params.url = aURI.spec;
|
||||
do_check_true(stmt.executeStep());
|
||||
let frecency = stmt.getInt32(0);
|
||||
stmt.finalize();
|
||||
|
||||
return frecency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the URI exists in moz_places and false otherwise.
|
||||
*
|
||||
* @param aURI
|
||||
* the URI of a place
|
||||
*/
|
||||
function uriExistsInMozPlaces(aURI) {
|
||||
let sql = "SELECT id FROM moz_places_view WHERE url = :url";
|
||||
let stmt = dbConn.createStatement(sql);
|
||||
stmt.params.url = aURI.spec;
|
||||
var exists = stmt.executeStep();
|
||||
stmt.finalize();
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function run_test() {
|
||||
gTests.forEach(function (t) {
|
||||
deleteAllHistoryAndBookmarks();
|
||||
print("------ RUNNING TEST: " + t.desc);
|
||||
t.run();
|
||||
});
|
||||
deleteAllHistoryAndBookmarks();
|
||||
function run_next_test() {
|
||||
if (gTests.length) {
|
||||
let test = gTests.shift();
|
||||
print("\n ***Test: " + test.desc);
|
||||
waitForClearHistory(function() {
|
||||
DBConn().executeSimpleSQL("DELETE FROM moz_places");
|
||||
remove_all_bookmarks();
|
||||
test.run.call(test);
|
||||
});
|
||||
}
|
||||
else {
|
||||
do_test_finished();
|
||||
}
|
||||
}
|
||||
|
@ -45,27 +45,17 @@
|
||||
* bookmark is deleted.
|
||||
*/
|
||||
|
||||
const bmServ =
|
||||
Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
const histServ =
|
||||
Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
const lmServ =
|
||||
Cc["@mozilla.org/browser/livemark-service;2"].
|
||||
getService(Ci.nsILivemarkService);
|
||||
const bmServ = PlacesUtils.bookmarks;
|
||||
const histServ = PlacesUtils.history;
|
||||
const lmServ = PlacesUtils.livemarks;
|
||||
|
||||
const dbConn =
|
||||
Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
let tests = [
|
||||
|
||||
var tests = [];
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["Frecency of unvisited, separately bookmarked livemark item's URI ",
|
||||
"should be zero after bookmark removed."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
@ -75,22 +65,31 @@ tests.push({
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(lmItemURL), 0);
|
||||
|
||||
bmServ.removeItem(bmId);
|
||||
|
||||
// URI's only "bookmark" is now unvisited livemark item => frecency = 0.
|
||||
do_check_eq(getFrecency(lmItemURL), 0);
|
||||
runNextTest();
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["Frecency of visited, separately bookmarked livemark item's URI ",
|
||||
"should not be zero after bookmark removed."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
@ -100,44 +99,62 @@ tests.push({
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(lmItemURL), 0);
|
||||
|
||||
visit(lmItemURI);
|
||||
bmServ.removeItem(bmId);
|
||||
|
||||
// URI's only "bookmark" is now *visited* livemark item => frecency != 0.
|
||||
do_check_neq(getFrecency(lmItemURL), 0);
|
||||
runNextTest();
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After removing bookmark, frecency of bookmark's URI should be zero ",
|
||||
"if URI is unvisited and no longer bookmarked."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
let url = "http://example.com/1";
|
||||
let bmId = bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(url, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [url, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(url), 0);
|
||||
|
||||
bmServ.removeItem(bmId);
|
||||
|
||||
// Unvisited URI no longer bookmarked => frecency should = 0.
|
||||
do_check_eq(getFrecency(url), 0);
|
||||
runNextTest();
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After removing bookmark, frecency of bookmark's URI should not be ",
|
||||
"zero if URI is visited."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
|
||||
@ -145,23 +162,32 @@ tests.push({
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bmId]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
|
||||
visit(bmURI);
|
||||
bmServ.removeItem(bmId);
|
||||
|
||||
// *Visited* URI no longer bookmarked => frecency should != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
runNextTest();
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After removing bookmark, frecency of bookmark's URI should not be ",
|
||||
"zero if URI is still bookmarked."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
|
||||
@ -174,23 +200,32 @@ tests.push({
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL, bm1Id]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
|
||||
bmServ.removeItem(bm1Id);
|
||||
|
||||
// URI still bookmarked => frecency should != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
runNextTest();
|
||||
bmServ.removeItem(aItemId);
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI still bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["Frecency of unvisited, separately bookmarked livemark item's URI ",
|
||||
"should be zero after all children removed from bookmark's ",
|
||||
"parent."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
@ -201,23 +236,32 @@ tests.push({
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(lmItemURL), 0);
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL]);
|
||||
},
|
||||
check1: function (aUrl)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
|
||||
// URI's only "bookmark" is now unvisited livemark item => frecency = 0.
|
||||
do_check_eq(getFrecency(lmItemURL), 0);
|
||||
runNextTest();
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now unvisited livemark item => frecency = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["Frecency of visited, separately bookmarked livemark item's URI ",
|
||||
"should not be zero after all children removed from bookmark's ",
|
||||
"parent."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
// Add livemark and bookmark. Bookmark's URI is the URI of the livemark's
|
||||
// only item.
|
||||
let lmItemURL = "http://example.com/livemark-item";
|
||||
@ -227,45 +271,63 @@ tests.push({
|
||||
lmItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(lmItemURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [lmItemURL]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(lmItemURL), 0);
|
||||
|
||||
visit(lmItemURI);
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
|
||||
// URI's only "bookmark" is now *visited* livemark item => frecency != 0.
|
||||
do_check_neq(getFrecency(lmItemURL), 0);
|
||||
runNextTest();
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("URI's only bookmark is now *visited* livemark item => frecency != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After removing all children from bookmark's parent, frecency of ",
|
||||
"bookmark's URI should be zero if URI is unvisited and no longer ",
|
||||
"bookmarked."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
let url = "http://example.com/1";
|
||||
bmServ.insertBookmark(bmServ.unfiledBookmarksFolder,
|
||||
uri(url),
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(url), 0);
|
||||
waitForFrecency(url, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [url]);
|
||||
},
|
||||
check1: function (aUrl, aItemId)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
|
||||
// Unvisited URI no longer bookmarked => frecency should = 0.
|
||||
do_check_eq(getFrecency(url), 0);
|
||||
runNextTest();
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency == 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("Unvisited URI no longer bookmarked => frecency should = 0");
|
||||
do_check_eq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After removing all children from bookmark's parent, frecency of ",
|
||||
"bookmark's URI should not be zero if URI is visited."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
|
||||
@ -273,24 +335,33 @@ tests.push({
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark title");
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL]);
|
||||
},
|
||||
check1: function (aUrl)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
|
||||
visit(bmURI);
|
||||
visit(uri(aUrl));
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
|
||||
// *Visited* URI no longer bookmarked => frecency should != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
runNextTest();
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
print("*Visited* URI no longer bookmarked => frecency should != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
tests.push({
|
||||
{
|
||||
desc: ["After removing all children from bookmark's parent, frecency of ",
|
||||
"bookmark's URI should not be zero if URI is still ",
|
||||
"bookmarked."].join(""),
|
||||
run: function () {
|
||||
run: function ()
|
||||
{
|
||||
let bmURL = "http://example.com/1";
|
||||
let bmURI = uri(bmURL);
|
||||
|
||||
@ -303,17 +374,27 @@ tests.push({
|
||||
bmURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"bookmark 2 title");
|
||||
|
||||
// Bookmarked => frecency of URI should be != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
waitForFrecency(bmURL, function(aFrecency) aFrecency > 0,
|
||||
this.check1, this, [bmURL]);
|
||||
},
|
||||
check1: function (aUrl)
|
||||
{
|
||||
print("Bookmarked => frecency of URI should be != 0");
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
|
||||
bmServ.removeFolderChildren(bmServ.unfiledBookmarksFolder);
|
||||
|
||||
waitForFrecency(aUrl, function(aFrecency) aFrecency > 0,
|
||||
this.check2, this, [aUrl]);
|
||||
},
|
||||
check2: function (aUrl)
|
||||
{
|
||||
// URI still bookmarked => frecency should != 0.
|
||||
do_check_neq(getFrecency(bmURL), 0);
|
||||
runNextTest();
|
||||
do_check_neq(frecencyForUrl(aUrl), 0);
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -330,30 +411,10 @@ function createLivemark(aLmChildItemURI) {
|
||||
uri("http://example.com/"),
|
||||
uri("http://example.com/rdf"),
|
||||
-1);
|
||||
let lmChildItemId = bmServ.insertBookmark(lmItemId,
|
||||
aLmChildItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
return lmChildItemId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the frecency of a Place.
|
||||
*
|
||||
* @param aURL
|
||||
* the URL of a Place
|
||||
* @return the frecency of aURL
|
||||
*/
|
||||
function getFrecency(aURL) {
|
||||
let sql = "SELECT frecency FROM moz_places_view WHERE url = :url";
|
||||
let stmt = dbConn.createStatement(sql);
|
||||
stmt.params.url = aURL;
|
||||
do_check_true(stmt.executeStep());
|
||||
let frecency = stmt.getInt32(0);
|
||||
print("frecency=" + frecency);
|
||||
stmt.finalize();
|
||||
|
||||
return frecency;
|
||||
return bmServ.insertBookmark(lmItemId,
|
||||
aLmChildItemURI,
|
||||
bmServ.DEFAULT_INDEX,
|
||||
"livemark item title");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -375,15 +436,18 @@ function visit(aURI) {
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
runNextTest();
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
function run_next_test() {
|
||||
if (tests.length) {
|
||||
let test = tests.shift();
|
||||
print("Test " + + ": " + test.desc);
|
||||
remove_all_bookmarks();
|
||||
waitForClearHistory(test.run);
|
||||
print("\n ***Test: " + test.desc);
|
||||
waitForClearHistory(function() {
|
||||
DBConn().executeSimpleSQL("DELETE FROM moz_places");
|
||||
remove_all_bookmarks();
|
||||
test.run.call(test);
|
||||
});
|
||||
}
|
||||
else {
|
||||
do_test_finished();
|
||||
|
Loading…
Reference in New Issue
Block a user