Bug 483980 - Allow history/bookmark observer components to register with a startup category

This changeset allows for history and bookmark observers to be registered via
the category manager.  This means the bookmarks service does not have to be
initialized at startup to register observers with it, as well as the history
service.
r=sdwilsh
r=mak
r=dietrich
This commit is contained in:
Mark Finkle ext:(%2C%20Shawn%20Wilsher%20%3Cme%40shawnwilsher.com%3E%2C%20Marco%20Bonardo%20%3Cmak77%40bonardo.net%3E) 2009-03-25 15:31:36 -05:00
Родитель 9bebb41ad8
Коммит ced4389b1a
29 изменённых файлов: 812 добавлений и 74 удалений

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

@ -330,3 +330,13 @@ function dump_table(aName)
stmt.finalize();
stmt = null;
}
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

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

@ -41,9 +41,7 @@
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
@ -52,6 +50,9 @@ var os = Cc['@mozilla.org/observer-service;1'].
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).

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

@ -54,6 +54,7 @@
#include "nsPlacesTriggers.h"
#include "nsPlacesTables.h"
#include "nsPlacesIndexes.h"
#include "nsPlacesMacros.h"
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ID = 0;
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Type = 1;
@ -88,7 +89,7 @@ nsNavBookmarks* nsNavBookmarks::sInstance = nsnull;
nsNavBookmarks::nsNavBookmarks()
: mItemCount(0), mRoot(0), mBookmarksRoot(0), mTagRoot(0), mToolbarFolder(0), mBatchLevel(0),
mBatchHasTransaction(PR_FALSE)
mBatchHasTransaction(PR_FALSE), mCanNotify(false), mCacheObservers("bookmark-observers")
{
NS_ASSERTION(!sInstance, "Multiple nsNavBookmarks instances!");
sInstance = this;
@ -125,6 +126,8 @@ nsNavBookmarks::Init()
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
mCanNotify = true;
// Add observers
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
@ -1106,7 +1109,7 @@ nsNavBookmarks::InsertBookmark(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex,
AddBookmarkToHash(childID, 0);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemAdded(rowId, aFolder, index))
// If the bookmark has been added to a tag container, notify all
@ -1124,7 +1127,7 @@ nsNavBookmarks::InsertBookmark(PRInt64 aFolder, nsIURI *aItem, PRInt32 aIndex,
if (bookmarks.Length()) {
for (PRUint32 i = 0; i < bookmarks.Length(); i++) {
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("tags"),
PR_FALSE, EmptyCString()))
}
@ -1172,7 +1175,7 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId)
return NS_OK;
}
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnBeforeItemRemoved(aItemId))
mozStorageTransaction transaction(mDBConn, PR_FALSE);
@ -1211,7 +1214,7 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId)
NS_ENSURE_SUCCESS(rv, rv);
}
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemRemoved(aItemId, folderId, childIndex))
if (itemType == TYPE_BOOKMARK) {
@ -1232,7 +1235,7 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId)
if (bookmarks.Length()) {
for (PRUint32 i = 0; i < bookmarks.Length(); i++) {
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("tags"),
PR_FALSE, EmptyCString()))
}
@ -1381,7 +1384,7 @@ nsNavBookmarks::CreateContainerWithID(PRInt64 aItemId, PRInt64 aParent,
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemAdded(id, aParent, index))
*aIndex = index;
@ -1446,7 +1449,7 @@ nsNavBookmarks::InsertSeparator(PRInt64 aParent, PRInt32 aIndex,
rv = transaction.Commit();
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemAdded(rowId, aParent, index))
return NS_OK;
@ -1583,7 +1586,7 @@ nsNavBookmarks::RemoveFolder(PRInt64 aFolderId)
{
NS_ENSURE_TRUE(aFolderId != mRoot, NS_ERROR_INVALID_ARG);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnBeforeItemRemoved(aFolderId))
mozStorageTransaction transaction(mDBConn, PR_FALSE);
@ -1657,7 +1660,7 @@ nsNavBookmarks::RemoveFolder(PRInt64 aFolderId)
mToolbarFolder = 0;
}
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemRemoved(aFolderId, parent, index))
return NS_OK;
@ -1775,7 +1778,7 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolderId)
folderChildrenInfo child = folderChildrenArray[i];
// Notify observers that we are about to remove this child.
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnBeforeItemRemoved(child.itemId))
if (child.itemType == TYPE_FOLDER) {
@ -1848,7 +1851,7 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolderId)
for (PRInt32 i = folderChildrenArray.Length() - 1; i >= 0 ; i--) {
folderChildrenInfo child = folderChildrenArray[i];
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemRemoved(child.itemId,
child.parentId,
child.index));
@ -1869,7 +1872,7 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolderId)
if (bookmarks.Length()) {
for (PRUint32 i = 0; i < bookmarks.Length(); i++) {
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("tags"),
PR_FALSE, EmptyCString()))
}
@ -2026,7 +2029,7 @@ nsNavBookmarks::MoveItem(PRInt64 aItemId, PRInt64 aNewParent, PRInt32 aIndex)
NS_ENSURE_SUCCESS(rv, rv);
// notify bookmark observers
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemMoved(aItemId, oldParent, oldIndex, aNewParent,
newIndex))
@ -2101,7 +2104,7 @@ nsNavBookmarks::SetItemDateAdded(PRInt64 aItemId, PRTime aDateAdded)
nsresult rv = SetItemDateInternal(mDBSetItemDateAdded, aItemId, aDateAdded);
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aItemId, NS_LITERAL_CSTRING("dateAdded"),
PR_FALSE, nsPrintfCString(16, "%lld", aDateAdded)));
return NS_OK;
@ -2132,7 +2135,7 @@ nsNavBookmarks::SetItemLastModified(PRInt64 aItemId, PRTime aLastModified)
nsresult rv = SetItemDateInternal(mDBSetItemLastModified, aItemId, aLastModified);
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aItemId, NS_LITERAL_CSTRING("lastModified"),
PR_FALSE, nsPrintfCString(16, "%lld", aLastModified)));
return NS_OK;
@ -2255,7 +2258,7 @@ nsNavBookmarks::SetItemTitle(PRInt64 aItemId, const nsACString &aTitle)
rv = statement->Execute();
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aItemId, NS_LITERAL_CSTRING("title"),
PR_FALSE, aTitle));
return NS_OK;
@ -2633,7 +2636,7 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI *aNewURI)
NS_ENSURE_SUCCESS(rv, rv);
// Pass the new URI to OnItemChanged.
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aBookmarkId, NS_LITERAL_CSTRING("uri"), PR_FALSE, spec))
return NS_OK;
@ -2760,11 +2763,11 @@ nsNavBookmarks::SetItemIndex(PRInt64 aItemId, PRInt32 aNewIndex)
// XXX (bug 484096) this is really inefficient and we should look into using
// onItemChanged here!
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnBeforeItemRemoved(aItemId))
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemRemoved(aItemId, parent, oldIndex))
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemAdded(aItemId, parent, aNewIndex))
return NS_OK;
@ -2850,7 +2853,7 @@ nsNavBookmarks::SetKeywordForBookmark(PRInt64 aBookmarkId, const nsAString& aKey
transaction.Commit();
// Pass the new keyword to OnItemChanged.
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aBookmarkId, NS_LITERAL_CSTRING("keyword"),
PR_FALSE, NS_ConvertUTF16toUTF8(aKeyword)))
@ -2936,7 +2939,7 @@ nsNavBookmarks::BeginUpdateBatch()
if (mBatchHasTransaction)
conn->BeginTransaction();
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnBeginUpdateBatch())
}
return NS_OK;
@ -2949,7 +2952,7 @@ nsNavBookmarks::EndUpdateBatch()
if (mBatchHasTransaction)
mDBConn->CommitTransaction();
mBatchHasTransaction = PR_FALSE;
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnEndUpdateBatch())
}
return NS_OK;
@ -3022,7 +3025,7 @@ nsNavBookmarks::OnVisit(nsIURI *aURI, PRInt64 aVisitID, PRTime aTime,
if (bookmarks.Length()) {
for (PRUint32 i = 0; i < bookmarks.Length(); i++)
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemVisited(bookmarks[i], aVisitID, aTime))
}
}
@ -3050,7 +3053,7 @@ nsNavBookmarks::OnDeleteURI(nsIURI *aURI)
if (bookmarks.Length()) {
for (PRUint32 i = 0; i < bookmarks.Length(); i ++)
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("cleartime"),
PR_FALSE, EmptyCString()))
}
@ -3099,7 +3102,7 @@ nsNavBookmarks::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
NS_ENSURE_STATE(queries.Count() == 1);
NS_ENSURE_STATE(queries[0]->Folders().Length() == 1);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(queries[0]->Folders()[0], NS_LITERAL_CSTRING("favicon"),
PR_FALSE, NS_ConvertUTF16toUTF8(aValue)));
}
@ -3111,7 +3114,7 @@ nsNavBookmarks::OnPageChanged(nsIURI *aURI, PRUint32 aWhat,
if (bookmarks.Length()) {
for (PRUint32 i = 0; i < bookmarks.Length(); i ++)
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(bookmarks[i], NS_LITERAL_CSTRING("favicon"),
PR_FALSE, NS_ConvertUTF16toUTF8(aValue)));
}
@ -3142,7 +3145,7 @@ nsNavBookmarks::OnItemAnnotationSet(PRInt64 aItemId, const nsACString& aName)
nsresult rv = SetItemDateInternal(mDBSetItemLastModified, aItemId, PR_Now());
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aItemId, aName, PR_TRUE, EmptyCString()));
return NS_OK;
@ -3161,7 +3164,7 @@ nsNavBookmarks::OnItemAnnotationRemoved(PRInt64 aItemId, const nsACString& aName
nsresult rv = SetItemDateInternal(mDBSetItemLastModified, aItemId, PR_Now());
NS_ENSURE_SUCCESS(rv, rv);
ENUMERATE_WEAKARRAY(mObservers, nsINavBookmarkObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavBookmarkObserver,
OnItemChanged(aItemId, aName, PR_TRUE, EmptyCString()));
return NS_OK;

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

@ -45,6 +45,7 @@
#include "nsNavHistory.h"
#include "nsNavHistoryResult.h" // need for Int64 hashtable
#include "nsToolkitCompsCID.h"
#include "nsCategoryCache.h"
class nsIOutputStream;
@ -296,6 +297,10 @@ private:
nsString mType;
PRInt32 mIndex;
};
// Used to enable and disable the observer notifications.
bool mCanNotify;
nsCategoryCache<nsINavBookmarkObserver> mCacheObservers;
};
struct nsBookmarksUpdateBatcher

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

@ -53,6 +53,7 @@
#include "nsPlacesTables.h"
#include "nsPlacesIndexes.h"
#include "nsPlacesTriggers.h"
#include "nsPlacesMacros.h"
#include "nsIArray.h"
#include "nsTArray.h"
@ -444,7 +445,9 @@ nsNavHistory::nsNavHistory() : mBatchLevel(0),
mNumVisitsForFrecency(10),
mTagsFolder(-1),
mInPrivateBrowsing(PRIVATEBROWSING_NOTINITED),
mDatabaseStatus(DATABASE_STATUS_OK)
mDatabaseStatus(DATABASE_STATUS_OK),
mCanNotify(true),
mCacheObservers("history-observers")
{
#ifdef LAZY_ADD
mLazyTimerSet = PR_TRUE;
@ -2883,7 +2886,7 @@ nsNavHistory::AddVisit(nsIURI* aURI, PRTime aTime, nsIURI* aReferringURI,
PRUint32 added = 0;
if (!hidden && aTransitionType != TRANSITION_EMBED &&
aTransitionType != TRANSITION_DOWNLOAD) {
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnVisit(aURI, *aVisitID, aTime, aSessionID,
referringVisitID, aTransitionType, &added));
}
@ -4261,7 +4264,7 @@ nsNavHistory::BeginUpdateBatch()
if (mBatchHasTransaction)
mDBConn->BeginTransaction();
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnBeginUpdateBatch())
}
return NS_OK;
@ -4275,7 +4278,8 @@ nsNavHistory::EndUpdateBatch()
if (mBatchHasTransaction)
mDBConn->CommitTransaction();
mBatchHasTransaction = PR_FALSE;
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver, OnEndUpdateBatch())
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnEndUpdateBatch())
}
return NS_OK;
}
@ -4582,15 +4586,16 @@ nsNavHistory::RemovePage(nsIURI *aURI)
NS_ENSURE_ARG(aURI);
// Before we remove, we have to notify our observers!
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
OnBeforeDeleteURI(aURI))
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnBeforeDeleteURI(aURI))
nsIURI** URIs = &aURI;
nsresult rv = RemovePages(URIs, 1, PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
// Notify our observers that the URI has been removed.
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver, OnDeleteURI(aURI))
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
nsINavHistoryObserver, OnDeleteURI(aURI))
return NS_OK;
}
@ -4950,7 +4955,7 @@ nsNavHistory::HidePage(nsIURI *aURI)
// notify observers, finish transaction first
transaction.Commit();
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnPageChanged(aURI,
nsINavHistoryObserver::ATTRIBUTE_HIDDEN,
EmptyString()))
@ -5609,7 +5614,7 @@ NS_IMETHODIMP
nsNavHistory::NotifyOnPageExpired(nsIURI *aURI, PRTime aVisitTime,
PRBool aWholeEntry)
{
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnPageExpired(aURI, aVisitTime, aWholeEntry));
return NS_OK;
}
@ -6858,6 +6863,14 @@ nsNavHistory::BookmarkIdToResultNode(PRInt64 aBookmarkId, nsNavHistoryQueryOptio
return RowToResult(stmt, aOptions, aResult);
}
void
nsNavHistory::SendPageChangedNotification(nsIURI* aURI, PRUint32 aWhat,
const nsAString& aValue)
{
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnPageChanged(aURI, aWhat, aValue));
}
// nsNavHistory::TitleForDomain
//
// This computes the title for a given domain. Normally, this is just the
@ -6987,11 +7000,10 @@ nsNavHistory::SetPageTitleInternal(nsIURI* aURI, const nsAString& aTitle)
NS_ENSURE_SUCCESS(rv, rv);
// observers (have to check first if it's bookmarked)
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mCanNotify, mCacheObservers, mObservers, nsINavHistoryObserver,
OnTitleChanged(aURI, aTitle))
return NS_OK;
}
nsresult

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

@ -82,6 +82,7 @@
#include "nsTArray.h"
#include "nsINavBookmarksService.h"
#include "nsMaybeWeakPtr.h"
#include "nsCategoryCache.h"
#include "nsNavHistoryExpire.h"
#include "nsNavHistoryResult.h"
@ -303,11 +304,7 @@ public:
// used by other places components to send history notifications (for example,
// when the favicon has changed)
void SendPageChangedNotification(nsIURI* aURI, PRUint32 aWhat,
const nsAString& aValue)
{
ENUMERATE_WEAKARRAY(mObservers, nsINavHistoryObserver,
OnPageChanged(aURI, aWhat, aValue));
}
const nsAString& aValue);
// current time optimization
PRTime GetNow();
@ -397,6 +394,12 @@ public:
return NS_OK;
}
/**
* Indicates if it is OK to notify history observers or not.
*
* @returns true if it is OK to notify, false otherwise.
*/
bool canNotify() { return mCanNotify; }
private:
~nsNavHistory();
@ -817,6 +820,10 @@ protected:
PRBool mInPrivateBrowsing;
PRUint16 mDatabaseStatus;
// Used to enable and disable the observer notifications
bool mCanNotify;
nsCategoryCache<nsINavHistoryObserver> mCacheObservers;
};
/**

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

@ -47,6 +47,7 @@
#include "nsNetUtil.h"
#include "nsIAnnotationService.h"
#include "nsPrintfCString.h"
#include "nsPlacesMacros.h"
struct nsNavHistoryExpireRecord {
nsNavHistoryExpireRecord(mozIStorageStatement* statement);
@ -279,7 +280,8 @@ nsNavHistoryExpire::ClearHistory()
// forcibly call the "on idle" timer here to do a little work
// but the rest will happen on idle.
ENUMERATE_WEAKARRAY(mHistory->mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mHistory->canNotify(), mHistory->mCacheObservers,
mHistory->mObservers, nsINavHistoryObserver,
OnClearHistory())
return NS_OK;
@ -384,7 +386,8 @@ nsNavHistoryExpire::ExpireItems(PRUint32 aNumToExpire, PRBool* aKeepGoing)
// FIXME bug 325241 provide a way to observe hidden elements
if (expiredVisits[i].hidden) continue;
ENUMERATE_WEAKARRAY(mHistory->mObservers, nsINavHistoryObserver,
ENUMERATE_OBSERVERS(mHistory->canNotify(), mHistory->mCacheObservers,
mHistory->mObservers, nsINavHistoryObserver,
OnPageExpired(uri, expiredVisits[i].visitDate,
expiredVisits[i].erased));
}

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

@ -103,10 +103,6 @@ function nsPlacesDBFlush()
}
// Register observers
this._bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
this._bs.addObserver(this, false);
this._os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
this._os.addObserver(this, kQuitApplication, false);
@ -140,6 +136,12 @@ function nsPlacesDBFlush()
return this._hsn = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsPIPlacesHistoryListenersNotifier);
});
this.__defineGetter__("_bs", function() {
delete this._bs;
return this._bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
});
}
nsPlacesDBFlush.prototype = {
@ -149,7 +151,6 @@ nsPlacesDBFlush.prototype = {
observe: function DBFlush_observe(aSubject, aTopic, aData)
{
if (aTopic == kQuitApplication) {
this._bs.removeObserver(this);
this._os.removeObserver(this, kQuitApplication);
let (pb2 = this._prefs.QueryInterface(Ci.nsIPrefBranch2)) {
pb2.removeObserver(kSyncPrefName, this);
@ -245,6 +246,24 @@ nsPlacesDBFlush.prototype = {
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(aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) { },
onTitleChanged: function(aURI, aPageTitle) { },
onDeleteURI: function(aURI) { },
onClearHistory: function() { },
onPageChanged: function(aURI, aWhat, aValue) { },
onPageExpired: function(aURI, aVisitTime, aWholeEntry) { },
//////////////////////////////////////////////////////////////////////////////
//// nsITimerCallback
@ -458,13 +477,18 @@ nsPlacesDBFlush.prototype = {
classDescription: "Used to synchronize the temporary and permanent tables of Places",
classID: Components.ID("c1751cfc-e8f1-4ade-b0bb-f74edfb8ef6a"),
contractID: "@mozilla.org/places/sync;1",
_xpcom_categories: [{
category: "profile-after-change",
}],
// Registering in these categories makes us get initialized when either of
// those listeners would be notified.
_xpcom_categories: [
{ category: "bookmark-observers" },
{ category: "history-observers" },
],
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver,
Ci.nsINavBookmarkObserver,
Ci.nsINavHistoryObserver,
Ci.nsITimerCallback,
Ci.mozIStorageStatementCallback,
])

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

@ -0,0 +1,50 @@
/* -*- Mode: C++; tab-width: 8; 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 Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.com> (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 ***** */
#include "prtypes.h"
// Call a method on each observer in a category cache, then call the same
// method on the observer array.
#define ENUMERATE_OBSERVERS(canFire, cache, array, type, method) \
PR_BEGIN_MACRO \
if (canFire) { \
const nsCOMArray<type> &entries = cache.GetEntries(); \
for (PRInt32 idx = 0; idx < entries.Count(); ++idx) \
entries[idx]->method; \
ENUMERATE_WEAKARRAY(array, type, method) \
} \
PR_END_MACRO;

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

@ -139,3 +139,13 @@ function dump_table(aName)
stmt.finalize();
stmt = null;
}
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

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

@ -0,0 +1,65 @@
/* ***** 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
* Mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* 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 ***** */
// put cleanup of the bookmarks test here.
// Run the event loop to be more like the browser, which normally runs the
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
var os = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).
QueryInterface(Ci.nsPIPlacesDatabase);
if (pip.DBConnection.connectionReady) {
pip.commitPendingChanges();
pip.finalizeInternalStatements();
pip.DBConnection.close();
do_check_false(pip.DBConnection.connectionReady);
}

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

@ -94,6 +94,59 @@ function clearDB() {
}
clearDB();
/**
* Dumps the rows of a table out to the console.
*
* @param aName
* The name of the table or view to output.
*/
function dump_table(aName)
{
let db = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsPIPlacesDatabase).
DBConnection;
let stmt = db.createStatement("SELECT * FROM " + aName);
dump("\n*** Printing data from " + aName + ":\n");
let count = 0;
while (stmt.executeStep()) {
let columns = stmt.numEntries;
if (count == 0) {
// print the column names
for (let i = 0; i < columns; i++)
dump(stmt.getColumnName(i) + "\t");
dump("\n");
}
// print the row
for (let i = 0; i < columns; i++) {
switch (stmt.getTypeOfIndex(i)) {
case Ci.mozIStorageValueArray.VALUE_TYPE_NULL:
dump("NULL\t");
break;
case Ci.mozIStorageValueArray.VALUE_TYPE_INTEGER:
dump(stmt.getInt64(i) + "\t");
break;
case Ci.mozIStorageValueArray.VALUE_TYPE_FLOAT:
dump(stmt.getDouble(i) + "\t");
break;
case Ci.mozIStorageValueArray.VALUE_TYPE_TEXT:
dump(stmt.getString(i) + "\t");
break;
}
}
dump("\n");
count++;
}
dump("*** There were a total of " + count + " rows of data.\n\n");
stmt.reset();
stmt.finalize();
stmt = null;
}
/*
* Removes all bookmarks and checks for correct cleanup
*/
@ -126,3 +179,13 @@ function check_no_bookmarks() {
do_check_eq(root.childCount, 0);
root.containerOpen = false;
}
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

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

@ -20,6 +20,7 @@
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -37,5 +38,29 @@
// put cleanup of the bookmarks test here.
// remove bookmarks file
//clearDB();
// Run the event loop to be more like the browser, which normally runs the
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
var os = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).
QueryInterface(Ci.nsPIPlacesDatabase);
if (pip.DBConnection.connectionReady) {
pip.commitPendingChanges();
pip.finalizeInternalStatements();
pip.DBConnection.close();
do_check_false(pip.DBConnection.connectionReady);
}

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

@ -59,24 +59,34 @@ function run_test() {
// test querying for bookmarks in multiple folders
var testFolder1 = bmsvc.createFolder(root, "bug 384228 test folder 1",
bmsvc.DEFAULT_INDEX);
do_check_eq(bmsvc.getItemIndex(testFolder1), 0);
var testFolder2 = bmsvc.createFolder(root, "bug 384228 test folder 2",
bmsvc.DEFAULT_INDEX);
do_check_eq(bmsvc.getItemIndex(testFolder2), 1);
var testFolder3 = bmsvc.createFolder(root, "bug 384228 test folder 3",
bmsvc.DEFAULT_INDEX);
do_check_eq(bmsvc.getItemIndex(testFolder3), 2);
var b1 = bmsvc.insertBookmark(testFolder1, uri("http://foo.tld/"),
bmsvc.DEFAULT_INDEX, "title b1 (folder 1)");
do_check_eq(bmsvc.getItemIndex(b1), 0);
var b2 = bmsvc.insertBookmark(testFolder1, uri("http://foo.tld/"),
bmsvc.DEFAULT_INDEX, "title b2 (folder 1)");
do_check_eq(bmsvc.getItemIndex(b2), 1);
var b3 = bmsvc.insertBookmark(testFolder2, uri("http://foo.tld/"),
bmsvc.DEFAULT_INDEX, "title b3 (folder 2)");
do_check_eq(bmsvc.getItemIndex(b3), 0);
var b4 = bmsvc.insertBookmark(testFolder3, uri("http://foo.tld/"),
bmsvc.DEFAULT_INDEX, "title b4 (folder 3)");
do_check_eq(bmsvc.getItemIndex(b4), 0);
// also test recursive search
var testFolder1_1 = bmsvc.createFolder(testFolder1, "bug 384228 test folder 1.1",
bmsvc.DEFAULT_INDEX);
do_check_eq(bmsvc.getItemIndex(testFolder1_1), 2);
var b5 = bmsvc.insertBookmark(testFolder1_1, uri("http://a1.com/"),
bmsvc.DEFAULT_INDEX, "title b5 (folder 1.1)");
do_check_eq(bmsvc.getItemIndex(b5), 0);
var options = histsvc.getNewQueryOptions();
var query = histsvc.getNewQuery();
query.searchTerms = "title";
@ -94,4 +104,6 @@ function run_test() {
do_check_eq(rootNode.getChild(1).itemId, b2);
do_check_eq(rootNode.getChild(2).itemId, b3);
do_check_eq(rootNode.getChild(3).itemId, b5);
rootNode.containerOpen = false;
}

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

@ -121,7 +121,11 @@ function run_test() {
var sql = "UPDATE moz_bookmarks SET fk = 1337 WHERE id = ?1";
var stmt = mDBConn.createStatement(sql);
stmt.bindUTF8StringParameter(0, aTest._itemId);
stmt.execute();
try {
stmt.execute();
} finally {
stmt.finalize();
}
});
// export json to file

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

@ -533,3 +533,13 @@ function dump_table(aName)
stmt.finalize();
stmt = null;
}
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

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

@ -1 +1,62 @@
clearDB();
/* ***** 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
* Mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* 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 ***** */
// put cleanup of the bookmarks test here.
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
var os = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop to be more like the browser, which normally runs the
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).
QueryInterface(Ci.nsPIPlacesDatabase);
if (pip.DBConnection.connectionReady) {
pip.commitPendingChanges();
pip.finalizeInternalStatements();
pip.DBConnection.close();
do_check_false(pip.DBConnection.connectionReady);
}

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

@ -272,6 +272,12 @@ function DBConn()
return dbConn;
}
// profile-after-change doesn't create components in xpcshell, so we have to do
// it ourselves
Cc["@mozilla.org/places/sync;1"].getService(Ci.nsISupports);
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

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

@ -0,0 +1,65 @@
/* ***** 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
* Mozilla.org
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* 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 ***** */
// put cleanup of the bookmarks test here.
// Run the event loop to be more like the browser, which normally runs the
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
var os = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).
QueryInterface(Ci.nsPIPlacesDatabase);
if (pip.DBConnection.connectionReady) {
pip.commitPendingChanges();
pip.finalizeInternalStatements();
pip.DBConnection.close();
do_check_false(pip.DBConnection.connectionReady);
}

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

@ -206,3 +206,13 @@ function finish_test()
os.notifyObservers(null, "quit-application", null);
do_test_finished();
}
/**
* Flushes any events in the event loop of the main thread.
*/
function flush_main_thread_events()
{
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
while (tm.mainThread.hasPendingEvents())
tm.mainThread.processNextEvent(false);
}

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

@ -0,0 +1,97 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places unit test code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.com> (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 ***** */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
const Cc = Components.classes;
const Ci = Components.interfaces;
// Dummy boomark/history observer
function DummyObserver() {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "dummy-observer-created", null);
}
DummyObserver.prototype = {
// history observer
onBeginUpdateBatch: function() {},
onEndUpdateBatch: function() {},
onVisit: function(aURI, aVisitID, aTime, aSessionID, aReferringID, aTransitionType) {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "dummy-observer-visited", null);
},
onTitleChanged: function(aURI, aPageTitle) {},
onDeleteURI: function(aURI) {},
onClearHistory: function() {},
onPageChanged: function(aURI, aWhat, aValue) {},
onPageExpired: function(aURI, aVisitTime, aWholeEntry) {},
// bookmark observer
//onBeginUpdateBatch: function() {},
//onEndUpdateBatch: function() {},
onItemAdded: function(aItemId, aParentId, aIndex) {
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "dummy-observer-item-added", null);
},
onItemChanged: function (aItemId, aProperty, aIsAnnotationProperty, aValue) {},
onBeforeItemRemoved: function() {},
onItemRemoved: function() {},
onItemVisited: function() {},
onItemMoved: function() {},
classDescription: "Dummy observer used to test category observers",
classID: Components.ID("62e221d3-68c3-4e1a-8943-a27beb5005fe"),
contractID: "@mozilla.org/places/test/dummy-observer;1",
// Registering in these categories makes us get initialized when either of
// those listeners would be notified.
_xpcom_categories: [
{ category: "bookmark-observers" },
{ category: "history-observers" }
],
QueryInterface: XPCOMUtils.generateQI([
Ci.nsINavBookmarkObserver,
Ci.nsINavHistoryObserver,
])
};
function NSGetModule(compMgr, fileSpec) {
return XPCOMUtils.generateModule([DummyObserver]);
}

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

@ -20,6 +20,7 @@
*
* Contributor(s):
* Dietrich Ayala <dietrich@mozilla.com>
* Marco Bonardo <mak77@bonardo.net>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
@ -37,5 +38,30 @@
// put cleanup of the bookmarks test here.
// remove bookmarks file
clearDB();
// Run the event loop to be more like the browser, which normally runs the
// event loop long before code like this would run.
// Not doing so could cause us to close the connection before all tasks have
// been completed, and that would crash badly.
flush_main_thread_events();
// XPCShell doesn't dispatch quit-application, to ensure cleanup we have to
// dispatch it after each test run.
var os = Cc['@mozilla.org/observer-service;1'].
getService(Ci.nsIObserverService);
os.notifyObservers(null, "quit-application-granted", null);
os.notifyObservers(null, "quit-application", null);
// Run the event loop, since we enqueue some statement finalization.
flush_main_thread_events();
// try to close the connection so we can remove places.sqlite
var pip = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService).
QueryInterface(Ci.nsPIPlacesDatabase);
if (pip.DBConnection.connectionReady) {
pip.commitPendingChanges();
pip.finalizeInternalStatements();
pip.DBConnection.close();
do_check_false(pip.DBConnection.connectionReady);
}

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

@ -283,6 +283,7 @@ function run_test() {
// undefined), so check if frecency matches. This is okay because we
// can still ensure the correct number of expected frecencies.
let getFrecency = function(aURL) aURL.match(/frecency:(-?\d+)$/)[1];
print("### searchURL: '"+searchURL+"', expectedURL: '"+expectedURL+"'");
do_check_eq(getFrecency(searchURL), getFrecency(expectURL));
}
}

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

@ -79,7 +79,7 @@ function run_test() {
var stmt = mDBConn.createStatement(sql);
stmt.bindUTF8StringParameter(0, keyword);
do_check_false(stmt.executeStep());
stmt.finalize();
// TEST 2
// 1. add 2 bookmarks
@ -106,5 +106,5 @@ function run_test() {
var stmt = mDBConn.createStatement(sql);
stmt.bindUTF8StringParameter(0, keyword);
do_check_true(stmt.executeStep());
stmt.finalize();
}

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

@ -65,6 +65,7 @@ function add_visit(aURI, aVisitDate, aVisitType) {
stmt.bindInt64Parameter(0, visitId);
do_check_true(stmt.executeStep());
var placeId = stmt.getInt64(0);
stmt.finalize();
do_check_true(placeId > 0);
return placeId;
}

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

@ -0,0 +1,81 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places unit test code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.com> (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 ***** */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Get services.
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let gDummyCreated = false;
let gDummyAdded = false;
let observer = {
observe: function(subject, topic, data) {
if (topic == "dummy-observer-created")
gDummyCreated = true;
else if (topic == "dummy-observer-item-added")
gDummyAdded = true;
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
])
};
function verify() {
do_check_true(gDummyCreated);
do_check_true(gDummyAdded);
do_test_finished();
}
// main
function run_test() {
do_load_module("nsDummyObserver.js");
os.addObserver(observer, "dummy-observer-created", true);
os.addObserver(observer, "dummy-observer-item-added", true);
// Add a bookmark
bs.insertBookmark(bs.unfiledBookmarksFolder, uri("http://typed.mozilla.org"),
bs.DEFAULT_INDEX, "bookmark");
do_test_pending();
do_timeout(1000, "verify();");
}

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

@ -198,11 +198,15 @@ function run_test() {
// get direct db connection
var db = histsvc.QueryInterface(Ci.nsPIPlacesDatabase).DBConnection;
var q = "SELECT id FROM moz_bookmarks";
var statement;
try {
var statement = db.createStatement(q);
statement = db.createStatement(q);
} catch(ex) {
do_throw("bookmarks table does not have id field, schema is too old!");
}
finally {
statement.finalize();
}
// bug 394741 - regressed history text searches
add_visit(uri("http://mozilla.com"));

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

@ -0,0 +1,81 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Places unit test code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Finkle <mfinkle@mozilla.com> (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 ***** */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
// Get services.
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
let os = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
let gDummyCreated = false;
let gDummyVisited = false;
let observer = {
observe: function(subject, topic, data) {
if (topic == "dummy-observer-created")
gDummyCreated = true;
else if (topic == "dummy-observer-visited")
gDummyVisited = true;
},
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIObserver,
Ci.nsISupportsWeakReference,
])
};
function verify() {
do_check_true(gDummyCreated);
do_check_true(gDummyVisited);
do_test_finished();
}
// main
function run_test() {
do_load_module("nsDummyObserver.js");
os.addObserver(observer, "dummy-observer-created", true);
os.addObserver(observer, "dummy-observer-visited", true);
// Add a visit
hs.addVisit(uri("http://typed.mozilla.org"), Date.now(), null,
hs.TRANSITION_TYPED, false, 0);
do_test_pending();
do_timeout(1000, "verify();");
}

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

@ -71,9 +71,9 @@ function run_test() {
deleteMork();
_("Now that places has migrated, check that it calculated frecencies");
places.DBConnection.createStatement(
"SELECT COUNT(*) FROM moz_places_view WHERE frecency < 0").
executeAsync({
var stmt = places.DBConnection.createStatement(
"SELECT COUNT(*) FROM moz_places_view WHERE frecency < 0");
stmt.executeAsync({
handleResult: function(results) {
_("Should always get a result from COUNT(*)");
let row = results.getNextRow();
@ -85,6 +85,7 @@ function run_test() {
handleCompletion: do_test_finished,
handleError: do_throw,
});
stmt.finalize();
break;
}
},