зеркало из https://github.com/mozilla/gecko-dev.git
Bug 542943 - Get rid of bookmarksHash, r=dietrich
This commit is contained in:
Родитель
1dc1d82e84
Коммит
a91d58bd5e
|
@ -499,6 +499,9 @@ interface nsINavBookmarksService : nsISupports
|
|||
* in this case "mozilla.org".
|
||||
*
|
||||
* If there is no bookmarked page found, it will return NULL.
|
||||
*
|
||||
* @note The function will only return bookmarks in the first 3 levels of
|
||||
* redirection (1 -> 2 -> 3 -> aURI).
|
||||
*/
|
||||
nsIURI getBookmarkedURIFor(in nsIURI aURI);
|
||||
|
||||
|
|
|
@ -286,52 +286,6 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
|||
"WHERE content = ?1 "
|
||||
"LIMIT 1"));
|
||||
|
||||
// input = page ID, time threshold; output = unique ID input has redirected to
|
||||
RETURN_IF_STMT(mDBGetRedirectDestinations, NS_LITERAL_CSTRING(
|
||||
"SELECT DISTINCT dest_v.place_id "
|
||||
"FROM moz_historyvisits_temp source_v "
|
||||
"JOIN moz_historyvisits_temp dest_v ON dest_v.from_visit = source_v.id "
|
||||
"WHERE source_v.place_id = ?1 "
|
||||
"AND source_v.visit_date >= ?2 "
|
||||
"AND dest_v.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") "
|
||||
"UNION "
|
||||
"SELECT DISTINCT dest_v.place_id "
|
||||
"FROM moz_historyvisits_temp source_v "
|
||||
"JOIN moz_historyvisits dest_v ON dest_v.from_visit = source_v.id "
|
||||
"WHERE source_v.place_id = ?1 "
|
||||
"AND source_v.visit_date >= ?2 "
|
||||
"AND dest_v.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") "
|
||||
"UNION "
|
||||
"SELECT DISTINCT dest_v.place_id "
|
||||
"FROM moz_historyvisits source_v "
|
||||
"JOIN moz_historyvisits_temp dest_v ON dest_v.from_visit = source_v.id "
|
||||
"WHERE source_v.place_id = ?1 "
|
||||
"AND source_v.visit_date >= ?2 "
|
||||
"AND dest_v.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") "
|
||||
"UNION "
|
||||
"SELECT DISTINCT dest_v.place_id "
|
||||
"FROM moz_historyvisits source_v "
|
||||
"JOIN moz_historyvisits dest_v ON dest_v.from_visit = source_v.id "
|
||||
"WHERE source_v.place_id = ?1 "
|
||||
"AND source_v.visit_date >= ?2 "
|
||||
"AND dest_v.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") "));
|
||||
|
||||
RETURN_IF_STMT(mDBInsertBookmark, NS_LITERAL_CSTRING(
|
||||
"INSERT INTO moz_bookmarks "
|
||||
"(id, fk, type, parent, position, title, folder_type, "
|
||||
|
@ -341,9 +295,17 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
|||
// Just select position since it's just an int32 and may be faster.
|
||||
// We don't actually care about the data, just whether there is any.
|
||||
RETURN_IF_STMT(mDBIsBookmarkedInDatabase, NS_LITERAL_CSTRING(
|
||||
"SELECT position FROM moz_bookmarks WHERE fk = ?1 AND type = ?2"));
|
||||
"SELECT 1 FROM moz_bookmarks WHERE fk = ?1"));
|
||||
|
||||
// Checks to make sure a place_id is a bookmark, and isn't a livemark.
|
||||
RETURN_IF_STMT(mDBIsURIBookmarkedInDatabase, NS_LITERAL_CSTRING(
|
||||
"SELECT 1 FROM moz_bookmarks WHERE fk = ("
|
||||
"SELECT id FROM moz_places_temp WHERE url = ?1 "
|
||||
"UNION ALL "
|
||||
"SELECT id FROM moz_places WHERE url = ?1 "
|
||||
"LIMIT 1"
|
||||
")"));
|
||||
|
||||
// Checks to make sure a place id is a bookmark, and isn't a livemark.
|
||||
RETURN_IF_STMT(mDBIsRealBookmark, NS_LITERAL_CSTRING(
|
||||
"SELECT id "
|
||||
"FROM moz_bookmarks "
|
||||
|
@ -429,6 +391,85 @@ nsNavBookmarks::GetStatement(const nsCOMPtr<mozIStorageStatement>& aStmt)
|
|||
RETURN_IF_STMT(mDBChangeBookmarkURI, NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_bookmarks SET fk = ?1, lastModified = ?2 WHERE id = ?3 "));
|
||||
|
||||
// The next query finds the bookmarked ancestors in a redirects chain.
|
||||
// It won't go further than 3 levels of redirects (a->b->c->your_place_id).
|
||||
// To make this path 100% correct (up to any level) we would need either:
|
||||
// - A separate hash, build through recursive querying of the database.
|
||||
// This solution was previously implemented, but it had a negative effect
|
||||
// on startup since at each startup we have to recursively query the
|
||||
// database to rebuild a hash that is always the same across sessions.
|
||||
// It must be updated at each visit and bookmarks change too. The code to
|
||||
// manage it is complex and prone to errors, sometimes causing incorrect
|
||||
// data fetches (for example wrong favicon for a redirected bookmark).
|
||||
// - A better way to track redirects for a visit.
|
||||
// We would need a separate table to track redirects, in the table we would
|
||||
// have visit_id, redirect_session. To get all sources for
|
||||
// a visit then we could just join this table and get all visit_id that
|
||||
// are in the same redirect_session as our visit. This has the drawback
|
||||
// that we can't ensure data integrity in the downgrade -> upgrade path,
|
||||
// since an old version would not update the table on new visits.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#define COALESCE_PLACEID \
|
||||
"COALESCE(greatgrandparent.place_id, grandparent.place_id, parent.place_id) "
|
||||
|
||||
nsCString redirectsFragment =
|
||||
nsPrintfCString(3, "%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY);
|
||||
|
||||
RETURN_IF_STMT(mDBFindRedirectedBookmark, NS_LITERAL_CSTRING(
|
||||
"SELECT IFNULL( "
|
||||
"(SELECT url FROM moz_places_temp WHERE id = ?1), "
|
||||
"(SELECT url FROM moz_places WHERE id = ?1) "
|
||||
") "
|
||||
"FROM moz_bookmarks b "
|
||||
"WHERE b.fk = ?1 "
|
||||
"UNION ALL " // Not directly bookmarked.
|
||||
"SELECT IFNULL( "
|
||||
"(SELECT url FROM moz_places_temp WHERE id = " COALESCE_PLACEID "), "
|
||||
"(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 = ?1 "
|
||||
"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 "
|
||||
"LEFT JOIN moz_historyvisits grandparent ON parent.from_visit = grandparent.id "
|
||||
"AND parent.visit_type IN (") + redirectsFragment + NS_LITERAL_CSTRING(") "
|
||||
"LEFT JOIN moz_historyvisits 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 = ?1 "
|
||||
"LIMIT 1 " // Stop at the first result.
|
||||
));
|
||||
#undef COALESCE_PLACEID
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
|
@ -444,7 +485,6 @@ nsNavBookmarks::FinalizeStatements() {
|
|||
mDBGetChildAt,
|
||||
mDBGetItemProperties,
|
||||
mDBGetItemIdForGUID,
|
||||
mDBGetRedirectDestinations,
|
||||
mDBInsertBookmark,
|
||||
mDBIsBookmarkedInDatabase,
|
||||
mDBIsRealBookmark,
|
||||
|
@ -461,6 +501,8 @@ nsNavBookmarks::FinalizeStatements() {
|
|||
mDBMoveItem,
|
||||
mDBSetItemTitle,
|
||||
mDBChangeBookmarkURI,
|
||||
mDBIsURIBookmarkedInDatabase,
|
||||
mDBFindRedirectedBookmark,
|
||||
};
|
||||
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) {
|
||||
|
@ -678,271 +720,24 @@ nsNavBookmarks::CreateRoot(mozIStorageStatement* aGetRootStatement,
|
|||
}
|
||||
|
||||
|
||||
// nsNavBookmarks::GetBookmarksHash
|
||||
//
|
||||
// Getter and lazy initializer of the bookmarks redirect hash.
|
||||
// See FillBookmarksHash for more information.
|
||||
|
||||
nsDataHashtable<nsTrimInt64HashKey, PRInt64>*
|
||||
nsNavBookmarks::GetBookmarksHash()
|
||||
{
|
||||
if (!mBookmarksHash.IsInitialized()) {
|
||||
nsresult rv = FillBookmarksHash();
|
||||
NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "FillBookmarksHash() failed!");
|
||||
}
|
||||
|
||||
return &mBookmarksHash;
|
||||
}
|
||||
|
||||
|
||||
// nsNavBookmarks::FillBookmarksHash
|
||||
//
|
||||
// This initializes the bookmarks hashtable that tells us which bookmark
|
||||
// a given URI redirects to. This hashtable includes all URIs that
|
||||
// redirect to bookmarks.
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::FillBookmarksHash()
|
||||
{
|
||||
PRBool hasMore;
|
||||
|
||||
// first init the hashtable
|
||||
NS_ENSURE_TRUE(mBookmarksHash.Init(1024), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// first populate the hashtable with all bookmarks
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT b.fk "
|
||||
"FROM moz_bookmarks b "
|
||||
"WHERE b.type = ?1 "
|
||||
"AND b.fk NOTNULL"),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt32Parameter(0, TYPE_BOOKMARK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
while (NS_SUCCEEDED(statement->ExecuteStep(&hasMore)) && hasMore) {
|
||||
PRInt64 pageID;
|
||||
rv = statement->GetInt64(0, &pageID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(mBookmarksHash.Put(pageID, pageID), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
// Find all pages h2 that have been redirected to from a bookmarked URI:
|
||||
// bookmarked -> url (h1) url (h2)
|
||||
// | ^
|
||||
// . |
|
||||
// visit (v1) -> destination visit (v2)
|
||||
// This should catch most redirects, which are only one level. More levels of
|
||||
// redirection will be handled separately.
|
||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
"SELECT v1.place_id, v2.place_id "
|
||||
"FROM moz_bookmarks b "
|
||||
"LEFT JOIN moz_historyvisits_temp v1 on b.fk = v1.place_id "
|
||||
"LEFT JOIN moz_historyvisits v2 on v2.from_visit = v1.id "
|
||||
"WHERE b.fk IS NOT NULL AND b.type = ?1 "
|
||||
"AND v2.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") GROUP BY v2.place_id "
|
||||
"UNION "
|
||||
"SELECT v1.place_id, v2.place_id "
|
||||
"FROM moz_bookmarks b "
|
||||
"LEFT JOIN moz_historyvisits v1 on b.fk = v1.place_id "
|
||||
"LEFT JOIN moz_historyvisits_temp v2 on v2.from_visit = v1.id "
|
||||
"WHERE b.fk IS NOT NULL AND b.type = ?1 "
|
||||
"AND v2.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") GROUP BY v2.place_id "
|
||||
"UNION "
|
||||
"SELECT v1.place_id, v2.place_id "
|
||||
"FROM moz_bookmarks b "
|
||||
"LEFT JOIN moz_historyvisits v1 on b.fk = v1.place_id "
|
||||
"LEFT JOIN moz_historyvisits v2 on v2.from_visit = v1.id "
|
||||
"WHERE b.fk IS NOT NULL AND b.type = ?1 "
|
||||
"AND v2.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") GROUP BY v2.place_id "
|
||||
"UNION "
|
||||
"SELECT v1.place_id, v2.place_id "
|
||||
"FROM moz_bookmarks b "
|
||||
"LEFT JOIN moz_historyvisits_temp v1 on b.fk = v1.place_id "
|
||||
"LEFT JOIN moz_historyvisits_temp v2 on v2.from_visit = v1.id "
|
||||
"WHERE b.fk IS NOT NULL AND b.type = ?1 "
|
||||
"AND v2.visit_type IN (") +
|
||||
nsPrintfCString("%d,%d",
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_PERMANENT,
|
||||
nsINavHistoryService::TRANSITION_REDIRECT_TEMPORARY) +
|
||||
NS_LITERAL_CSTRING(") GROUP BY v2.place_id "),
|
||||
getter_AddRefs(statement));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->BindInt32Parameter(0, TYPE_BOOKMARK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
while (NS_SUCCEEDED(statement->ExecuteStep(&hasMore)) && hasMore) {
|
||||
PRInt64 fromId, toId;
|
||||
rv = statement->GetInt64(0, &fromId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = statement->GetInt64(1, &toId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(mBookmarksHash.Put(toId, fromId), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// handle redirects deeper than one level
|
||||
rv = RecursiveAddBookmarkHash(fromId, toId, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavBookmarks::AddBookmarkToHash
|
||||
//
|
||||
// Given a bookmark that was potentially added, this goes through all
|
||||
// redirects that this page may have resulted in and adds them to our hash.
|
||||
// Note that this takes the ID of the URL in the history system, which we
|
||||
// generally have when calling this function and which makes it faster.
|
||||
//
|
||||
// For better performance, this call should be in a DB transaction.
|
||||
//
|
||||
// @see RecursiveAddBookmarkHash
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::AddBookmarkToHash(PRInt64 aPlaceId, PRTime aMinTime)
|
||||
{
|
||||
if (!GetBookmarksHash()->Put(aPlaceId, aPlaceId))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
nsresult rv = RecursiveAddBookmarkHash(aPlaceId, aPlaceId, aMinTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavBookmkars::RecursiveAddBookmarkHash
|
||||
//
|
||||
// Used to add a new level of redirect information to the bookmark hash.
|
||||
// Given a source bookmark 'aBookmark' and 'aCurrentSource' that has already
|
||||
// been added to the hashtable, this will add all redirect destinations of
|
||||
// 'aCurrentSource'. Will call itself recursively to walk down the chain.
|
||||
//
|
||||
// 'aMinTime' is the minimum time to consider visits from. Visits previous
|
||||
// to this will not be considered. This allows the search to be much more
|
||||
// efficient if you know something happened recently. Use 0 for the min time
|
||||
// to search all history for redirects.
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::RecursiveAddBookmarkHash(PRInt64 aPlaceID,
|
||||
PRInt64 aCurrentSource,
|
||||
PRTime aMinTime)
|
||||
{
|
||||
nsresult rv;
|
||||
nsTArray<PRInt64> found;
|
||||
|
||||
// scope for the DB statement. The statement must be reset by the time we
|
||||
// recursively call ourselves again, because our recursive call will use the
|
||||
// same statement.
|
||||
{
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBGetRedirectDestinations);
|
||||
rv = stmt->BindInt64Parameter(0, aCurrentSource);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt64Parameter(1, aMinTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasMore;
|
||||
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) {
|
||||
// add this newly found redirect destination to the hashtable
|
||||
PRInt64 curID;
|
||||
rv = stmt->GetInt64(0, &curID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// It is very important we ignore anything already in our hashtable. It
|
||||
// is actually pretty common to get loops of redirects. For example,
|
||||
// a restricted page will redirect you to a login page, which will
|
||||
// redirect you to the restricted page again with the proper cookie.
|
||||
PRInt64 alreadyExistingOne;
|
||||
if (GetBookmarksHash()->Get(curID, &alreadyExistingOne))
|
||||
continue;
|
||||
|
||||
if (!GetBookmarksHash()->Put(curID, aPlaceID))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// save for recursion later
|
||||
found.AppendElement(curID);
|
||||
}
|
||||
}
|
||||
|
||||
// recurse on each found item now that we're done with the statement
|
||||
for (PRUint32 i = 0; i < found.Length(); i ++) {
|
||||
rv = RecursiveAddBookmarkHash(aPlaceID, found[i], aMinTime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// nsNavBookmarks::UpdateBookmarkHashOnRemove
|
||||
//
|
||||
// Call this when a bookmark is removed. It will see if the bookmark still
|
||||
// exists anywhere in the system, and, if not, remove all references to it
|
||||
// in the bookmark hashtable.
|
||||
//
|
||||
// The callback takes a pointer to what bookmark is being removed (as
|
||||
// an Int64 history page ID) as the userArg and removes all redirect
|
||||
// destinations that reference it.
|
||||
|
||||
static PLDHashOperator
|
||||
RemoveBookmarkHashCallback(nsTrimInt64HashKey::KeyType aKey,
|
||||
PRInt64& aPlaceId, void* aUserArg)
|
||||
{
|
||||
const PRInt64* removeThisOne = reinterpret_cast<const PRInt64*>(aUserArg);
|
||||
if (aPlaceId == *removeThisOne)
|
||||
return PL_DHASH_REMOVE;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
nsresult
|
||||
nsNavBookmarks::UpdateBookmarkHashOnRemove(PRInt64 aPlaceId)
|
||||
{
|
||||
// note we have to use the DB version here since the hashtable may be
|
||||
// out-of-date
|
||||
PRBool inDB;
|
||||
nsresult rv = IsBookmarkedInDatabase(aPlaceId, &inDB);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!inDB) {
|
||||
// Bookmark does not exist anymore, remove it from hashtable
|
||||
GetBookmarksHash()->Enumerate(RemoveBookmarkHashCallback,
|
||||
reinterpret_cast<void*>(&aPlaceId));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsNavBookmarks::IsRealBookmark(PRInt64 aPlaceId)
|
||||
{
|
||||
// Fast path is to check the hash table first. If it is in the hash table,
|
||||
// then verify that it is a real bookmark.
|
||||
PRInt64 bookmarkId;
|
||||
PRBool isBookmark = GetBookmarksHash()->Get(aPlaceId, &bookmarkId);
|
||||
if (isBookmark) {
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBIsRealBookmark);
|
||||
nsresult rv = stmt->BindInt64Parameter(0, aPlaceId);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Binding failed");
|
||||
rv = stmt->BindInt32Parameter(1, TYPE_BOOKMARK);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Binding failed");
|
||||
rv = stmt->BindUTF8StringParameter(2, NS_LITERAL_CSTRING(LMANNO_FEEDURI));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Binding failed");
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBIsRealBookmark);
|
||||
nsresult rv = stmt->BindInt64Parameter(0, aPlaceId);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Binding failed");
|
||||
rv = stmt->BindInt32Parameter(1, TYPE_BOOKMARK);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Binding failed");
|
||||
rv = stmt->BindUTF8StringParameter(2, NS_LITERAL_CSTRING(LMANNO_FEEDURI));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Binding failed");
|
||||
|
||||
// If we get any rows, then there exists at least one bookmark corresponding
|
||||
// to aPlaceId that is not a livemark item.
|
||||
rv = stmt->ExecuteStep(&isBookmark);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "ExecuteStep failed");
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return isBookmark;
|
||||
}
|
||||
// If we get any rows, then there exists at least one bookmark corresponding
|
||||
// to aPlaceId that is not a livemark item.
|
||||
PRBool isBookmark;
|
||||
rv = stmt->ExecuteStep(&isBookmark);
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "ExecuteStep failed");
|
||||
if (NS_SUCCEEDED(rv))
|
||||
return isBookmark;
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -951,7 +746,6 @@ nsNavBookmarks::IsRealBookmark(PRInt64 aPlaceId)
|
|||
// nsNavBookmarks::IsBookmarkedInDatabase
|
||||
//
|
||||
// This checks to see if the specified place_id is actually bookmarked.
|
||||
// This does not check for redirects in the hashtable.
|
||||
|
||||
nsresult
|
||||
nsNavBookmarks::IsBookmarkedInDatabase(PRInt64 aPlaceId,
|
||||
|
@ -960,8 +754,6 @@ nsNavBookmarks::IsBookmarkedInDatabase(PRInt64 aPlaceId,
|
|||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBIsBookmarkedInDatabase);
|
||||
nsresult rv = stmt->BindInt64Parameter(0, aPlaceId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32Parameter(1, TYPE_BOOKMARK);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->ExecuteStep(aIsBookmarked);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return NS_OK;
|
||||
|
@ -1202,9 +994,6 @@ nsNavBookmarks::InsertBookmark(PRInt64 aFolder,
|
|||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AddBookmarkToHash(childID, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NOTIFY_OBSERVERS(mCanNotify, mCacheObservers, mObservers,
|
||||
nsINavBookmarkObserver,
|
||||
OnItemAdded(*aNewBookmarkId, aFolder, index, TYPE_BOOKMARK));
|
||||
|
@ -1310,9 +1099,6 @@ nsNavBookmarks::RemoveItem(PRInt64 aItemId)
|
|||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = UpdateBookmarkHashOnRemove(placeId);
|
||||
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;
|
||||
|
@ -1881,7 +1667,6 @@ nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolderId)
|
|||
folderChildrenInfo child = folderChildrenArray[i];
|
||||
if (child.itemType == TYPE_BOOKMARK) {
|
||||
PRInt64 placeId = child.placeId;
|
||||
UpdateBookmarkHashOnRemove(placeId);
|
||||
|
||||
// UpdateFrecency needs to know whether placeId is still bookmarked.
|
||||
// Although we removed a child of aFolderId that bookmarked it, it may
|
||||
|
@ -2618,36 +2403,11 @@ nsNavBookmarks::IsBookmarked(nsIURI* aURI, PRBool* aBookmarked)
|
|||
NS_ENSURE_ARG(aURI);
|
||||
NS_ENSURE_ARG_POINTER(aBookmarked);
|
||||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// convert the URL to an ID
|
||||
PRInt64 urlID;
|
||||
nsresult rv = history->GetUrlIdFor(aURI, &urlID, PR_FALSE);
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBIsURIBookmarkedInDatabase);
|
||||
nsresult rv = BindStatementURI(stmt, 0, aURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->ExecuteStep(aBookmarked);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!urlID) {
|
||||
// never seen this before, not even in history
|
||||
*aBookmarked = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt64 bookmarkedID;
|
||||
PRBool foundOne = GetBookmarksHash()->Get(urlID, &bookmarkedID);
|
||||
|
||||
// IsBookmarked only tests if this exact URI is bookmarked, so we need to
|
||||
// check that the destination matches
|
||||
if (foundOne)
|
||||
*aBookmarked = (urlID == bookmarkedID);
|
||||
else
|
||||
*aBookmarked = PR_FALSE;
|
||||
|
||||
#ifdef DEBUG
|
||||
// sanity check for the bookmark hashtable
|
||||
PRBool realBookmarked;
|
||||
rv = IsBookmarkedInDatabase(urlID, &realBookmarked);
|
||||
NS_ASSERTION(realBookmarked == *aBookmarked,
|
||||
"Bookmark hash table out-of-sync with the database");
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -2663,33 +2423,32 @@ nsNavBookmarks::GetBookmarkedURIFor(nsIURI* aURI, nsIURI** _retval)
|
|||
|
||||
nsNavHistory* history = nsNavHistory::GetHistoryService();
|
||||
NS_ENSURE_TRUE(history, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// convert the URL to an ID
|
||||
PRInt64 urlID;
|
||||
nsresult rv = history->GetUrlIdFor(aURI, &urlID, PR_FALSE);
|
||||
PRInt64 placeId;
|
||||
nsresult rv = history->GetUrlIdFor(aURI, &placeId, PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!urlID) {
|
||||
// never seen this before, not even in history, leave result NULL
|
||||
if (!placeId) {
|
||||
// This URI is unknown, just return null.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt64 bookmarkID;
|
||||
if (GetBookmarksHash()->Get(urlID, &bookmarkID)) {
|
||||
// found one, convert ID back to URL. This statement is NOT refcounted
|
||||
mozIStorageStatement* statement = history->DBGetIdPageInfo();
|
||||
NS_ENSURE_STATE(statement);
|
||||
mozStorageStatementScoper scoper(statement);
|
||||
|
||||
rv = statement->BindInt64Parameter(0, bookmarkID);
|
||||
// Check if a bookmark exists in the redirects chain for this URI.
|
||||
// The query will also check if the page is directly bookmarked, and return
|
||||
// the first found bookmark in case. The check is directly on moz_bookmarks
|
||||
// without special filtering.
|
||||
DECLARE_AND_ASSIGN_SCOPED_LAZY_STMT(stmt, mDBFindRedirectedBookmark);
|
||||
rv = stmt->BindInt64Parameter(0, placeId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRBool hasBookmarkedOrigin;
|
||||
if (NS_SUCCEEDED(stmt->ExecuteStep(&hasBookmarkedOrigin)) &&
|
||||
hasBookmarkedOrigin) {
|
||||
nsCAutoString spec;
|
||||
rv = stmt->GetUTF8String(0, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = NS_NewURI(_retval, spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool hasMore;
|
||||
if (NS_SUCCEEDED(statement->ExecuteStep(&hasMore)) && hasMore) {
|
||||
nsCAutoString spec;
|
||||
statement->GetUTF8String(nsNavHistory::kGetInfoIndex_URL, spec);
|
||||
return NS_NewURI(_retval, spec);
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no bookmarked origin, we will just return null.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2734,14 +2493,6 @@ nsNavBookmarks::ChangeBookmarkURI(PRInt64 aBookmarkId, nsIURI* aNewURI)
|
|||
rv = transaction.Commit();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add new URI to bookmark hash.
|
||||
rv = AddBookmarkToHash(placeId, 0);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Remove old URI from bookmark hash.
|
||||
rv = UpdateBookmarkHashOnRemove(oldPlaceId);
|
||||
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.
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include "nsIAnnotationService.h"
|
||||
#include "nsITransaction.h"
|
||||
#include "nsNavHistory.h"
|
||||
#include "nsNavHistoryResult.h" // need for Int64 hashtable
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "nsCategoryCache.h"
|
||||
|
||||
|
@ -87,8 +86,6 @@ public:
|
|||
return gBookmarksService;
|
||||
}
|
||||
|
||||
nsresult AddBookmarkToHash(PRInt64 aBookmarkId, PRTime aMinTime);
|
||||
|
||||
nsresult ResultNodeForContainer(PRInt64 aID,
|
||||
nsNavHistoryQueryOptions* aOptions,
|
||||
nsNavHistoryResultNode** aNode);
|
||||
|
@ -187,16 +184,6 @@ private:
|
|||
// be committed when our batch level reaches 0 again.
|
||||
PRBool mBatchHasTransaction;
|
||||
|
||||
// This stores a mapping from all pages reachable by redirects from bookmarked
|
||||
// pages to the bookmarked page. Used by GetBookmarkedURIFor.
|
||||
nsDataHashtable<nsTrimInt64HashKey, PRInt64> mBookmarksHash;
|
||||
nsDataHashtable<nsTrimInt64HashKey, PRInt64>* GetBookmarksHash();
|
||||
nsresult FillBookmarksHash();
|
||||
nsresult RecursiveAddBookmarkHash(PRInt64 aBookmarkId,
|
||||
PRInt64 aCurrentSource,
|
||||
PRTime aMinTime);
|
||||
nsresult UpdateBookmarkHashOnRemove(PRInt64 aPlaceId);
|
||||
|
||||
nsresult GetParentAndIndexOfFolder(PRInt64 aFolder,
|
||||
PRInt64* aParent,
|
||||
PRInt32* aIndex);
|
||||
|
@ -281,6 +268,7 @@ private:
|
|||
nsresult GetBookmarkIdsForURITArray(nsIURI* aURI,
|
||||
nsTArray<PRInt64>& aResult);
|
||||
|
||||
PRInt64 RecursiveFindRedirectedBookmark(PRInt64 aPlaceId);
|
||||
|
||||
/**
|
||||
* You should always use this getter and never use directly the nsCOMPtr.
|
||||
|
@ -330,8 +318,8 @@ private:
|
|||
nsCOMPtr<mozIStorageStatement> mDBGetItemIndex;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetChildAt;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetItemIdForGUID;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetRedirectDestinations;
|
||||
nsCOMPtr<mozIStorageStatement> mDBIsBookmarkedInDatabase;
|
||||
nsCOMPtr<mozIStorageStatement> mDBIsURIBookmarkedInDatabase;
|
||||
nsCOMPtr<mozIStorageStatement> mDBIsRealBookmark;
|
||||
nsCOMPtr<mozIStorageStatement> mDBGetLastBookmarkID;
|
||||
nsCOMPtr<mozIStorageStatement> mDBSetItemDateAdded;
|
||||
|
@ -346,6 +334,7 @@ private:
|
|||
nsCOMPtr<mozIStorageStatement> mDBMoveItem;
|
||||
nsCOMPtr<mozIStorageStatement> mDBSetItemTitle;
|
||||
nsCOMPtr<mozIStorageStatement> mDBChangeBookmarkURI;
|
||||
nsCOMPtr<mozIStorageStatement> mDBFindRedirectedBookmark;
|
||||
|
||||
class RemoveFolderTransaction : public nsITransaction {
|
||||
public:
|
||||
|
|
|
@ -91,10 +91,6 @@ using namespace mozilla::places;
|
|||
// This is 15 minutes m s/m us/s
|
||||
#define RECENT_EVENT_THRESHOLD ((PRInt64)15 * 60 * PR_USEC_PER_SEC)
|
||||
|
||||
// Microseconds ago to look for redirects when updating bookmarks. Used to
|
||||
// compute the threshold for nsNavBookmarks::AddBookmarkToHash
|
||||
#define BOOKMARK_REDIRECT_TIME_THRESHOLD ((PRInt64)2 * 60 * PR_USEC_PER_SEC)
|
||||
|
||||
// The maximum number of things that we will store in the recent events list
|
||||
// before calling ExpireNonrecentEvents. This number should be big enough so it
|
||||
// is very difficult to get that many unconsumed events (for example, typed but
|
||||
|
@ -3858,7 +3854,7 @@ PlacesSQLQueryBuilder::OrderBy()
|
|||
switch(mSortingMode)
|
||||
{
|
||||
case nsINavHistoryQueryOptions::SORT_BY_NONE:
|
||||
// If this is an URI query the sorting could change based on the
|
||||
// If this is a URI query the sorting could change based on the
|
||||
// sync status of disk and temp tables, we must ensure sorting does not
|
||||
// change between queries.
|
||||
if (mResultType == nsINavHistoryQueryOptions::RESULTS_AS_URI) {
|
||||
|
@ -5038,7 +5034,7 @@ nsNavHistory::MarkPageAsFollowedLink(nsIURI *aURI)
|
|||
|
||||
// nsNavHistory::SetCharsetForURI
|
||||
//
|
||||
// Sets the character-set for an URI.
|
||||
// Sets the character-set for a URI.
|
||||
// If aCharset is empty remove character-set annotation for aURI.
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -5075,7 +5071,7 @@ nsNavHistory::SetCharsetForURI(nsIURI* aURI,
|
|||
|
||||
// nsNavHistory::GetCharsetForURI
|
||||
//
|
||||
// Get the last saved character-set for an URI.
|
||||
// Get the last saved character-set for a URI.
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNavHistory::GetCharsetForURI(nsIURI* aURI,
|
||||
|
@ -5160,27 +5156,9 @@ nsNavHistory::AddURIInternal(nsIURI* aURI, PRTime aTime, PRBool aRedirect,
|
|||
PRInt64 visitID = 0;
|
||||
PRInt64 sessionID = 0;
|
||||
nsresult rv = AddVisitChain(aURI, aTime, aToplevel, aRedirect, aReferrer,
|
||||
&visitID, &sessionID, &redirectBookmark);
|
||||
&visitID, &sessionID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The bookmark cache of redirects may be out-of-date with this addition, so
|
||||
// we need to update it. The issue here is if they bookmark "mozilla.org" by
|
||||
// typing it in without ever having visited "www.mozilla.org". They will then
|
||||
// get redirected to the latter, and we need to add mozilla.org ->
|
||||
// www.mozilla.org to the bookmark hashtable.
|
||||
//
|
||||
// AddVisitChain will put the spec of a bookmarked URI if it encounters one
|
||||
// into bookmarkURI. If this is non-empty, we know that something has happened
|
||||
// with a bookmark and we should probably go update it.
|
||||
if (redirectBookmark) {
|
||||
nsNavBookmarks *bookmarkService = nsNavBookmarks::GetBookmarksService();
|
||||
if (bookmarkService) {
|
||||
PRTime now = GetNow();
|
||||
bookmarkService->AddBookmarkToHash(redirectBookmark,
|
||||
now - BOOKMARK_REDIRECT_TIME_THRESHOLD);
|
||||
}
|
||||
}
|
||||
|
||||
return transaction.Commit();
|
||||
}
|
||||
|
||||
|
@ -5198,12 +5176,6 @@ nsNavHistory::AddURIInternal(nsIURI* aURI, PRTime aTime, PRBool aRedirect,
|
|||
// save them in mRecentRedirects. This function will add all of them for a
|
||||
// given destination page when that page is actually visited.)
|
||||
// See GetRedirectFor for more information about how redirects work.
|
||||
//
|
||||
// aRedirectBookmark should be empty when this function is first called. If
|
||||
// there are any redirects that are bookmarks the specs will be placed in
|
||||
// this buffer. The caller can then determine if any bookmarked items were
|
||||
// visited so it knows whether to update the bookmark service's redirect
|
||||
// hashtable.
|
||||
|
||||
nsresult
|
||||
nsNavHistory::AddVisitChain(nsIURI* aURI,
|
||||
|
@ -5212,8 +5184,7 @@ nsNavHistory::AddVisitChain(nsIURI* aURI,
|
|||
PRBool aIsRedirect,
|
||||
nsIURI* aReferrerURI,
|
||||
PRInt64* aVisitID,
|
||||
PRInt64* aSessionID,
|
||||
PRInt64* aRedirectBookmark)
|
||||
PRInt64* aSessionID)
|
||||
{
|
||||
// This is the address that will be saved to from_visit column, will be
|
||||
// overwritten later if needed.
|
||||
|
@ -5247,15 +5218,6 @@ nsNavHistory::AddVisitChain(nsIURI* aURI,
|
|||
redirectIsSame)
|
||||
return NS_OK;
|
||||
|
||||
// remember if any redirect sources were bookmarked
|
||||
nsNavBookmarks *bookmarkService = nsNavBookmarks::GetBookmarksService();
|
||||
PRBool isBookmarked;
|
||||
if (bookmarkService &&
|
||||
NS_SUCCEEDED(bookmarkService->IsBookmarked(redirectSourceURI, &isBookmarked))
|
||||
&& isBookmarked) {
|
||||
GetUrlIdFor(redirectSourceURI, aRedirectBookmark, PR_FALSE);
|
||||
}
|
||||
|
||||
// Recusively call addVisitChain to walk up the chain till the first
|
||||
// not-redirected URI.
|
||||
// Ensure that the sources have a visit time smaller than aTime, otherwise
|
||||
|
@ -5266,8 +5228,7 @@ nsNavHistory::AddVisitChain(nsIURI* aURI,
|
|||
PR_TRUE, // Is a redirect.
|
||||
aReferrerURI, // This one is the originating source.
|
||||
&sourceVisitId, // Get back the visit id of the source.
|
||||
aSessionID,
|
||||
aRedirectBookmark);
|
||||
aSessionID);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// All the visits for preceding pages in the redirects chain have been
|
||||
|
|
|
@ -488,7 +488,7 @@ protected:
|
|||
nsresult AddVisitChain(nsIURI* aURI, PRTime aTime,
|
||||
PRBool aToplevel, PRBool aRedirect,
|
||||
nsIURI* aReferrer, PRInt64* aVisitID,
|
||||
PRInt64* aSessionID, PRInt64* aRedirectBookmark);
|
||||
PRInt64* aSessionID);
|
||||
nsresult InternalAddNewPage(nsIURI* aURI, const nsAString& aTitle,
|
||||
PRBool aHidden, PRBool aTyped,
|
||||
PRInt32 aVisitCount, PRBool aCalculateFrecency,
|
||||
|
|
|
@ -155,6 +155,32 @@ function check_no_bookmarks() {
|
|||
root.containerOpen = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function gets current database connection, if the connection has been closed
|
||||
* it will try to reconnect to the places.sqlite database.
|
||||
*/
|
||||
function DBConn()
|
||||
{
|
||||
let db = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsPIPlacesDatabase).
|
||||
DBConnection;
|
||||
if (db.connectionReady)
|
||||
return db;
|
||||
|
||||
// open a new connection if needed
|
||||
let file = dirSvc.get('ProfD', Ci.nsIFile);
|
||||
file.append("places.sqlite");
|
||||
let storageService = Cc["@mozilla.org/storage/service;1"].
|
||||
getService(Ci.mozIStorageService);
|
||||
|
||||
try {
|
||||
return dbConn = storageService.openDatabase(file);
|
||||
}
|
||||
catch(ex) {}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes any events in the event loop of the main thread.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,132 @@
|
|||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Places unit test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Marco Bonardo <mak77bonardo.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 ***** */
|
||||
|
||||
/**
|
||||
* Test bookmarksService.getBookmarkedURIFor(aURI);
|
||||
*/
|
||||
|
||||
let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
|
||||
getService(Ci.nsINavHistoryService);
|
||||
let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
|
||||
getService(Ci.nsINavBookmarksService);
|
||||
|
||||
/**
|
||||
* Adds a fake redirect between two visits.
|
||||
*/
|
||||
function addFakeRedirect(aSourceVisitId, aDestVisitId, aRedirectType) {
|
||||
let dbConn = DBConn();
|
||||
let stmt = dbConn.createStatement(
|
||||
"UPDATE moz_historyvisits " +
|
||||
"SET from_visit = :source, visit_type = :type " +
|
||||
"WHERE id = :dest");
|
||||
stmt.params.source = aSourceVisitId;
|
||||
stmt.params.dest = aDestVisitId;
|
||||
stmt.params.type = aRedirectType;
|
||||
try {
|
||||
stmt.executeStep();
|
||||
}
|
||||
finally {
|
||||
stmt.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let now = Date.now() * 1000;
|
||||
const sourceURI = uri("http://test.mozilla.org/");
|
||||
// Add a visit and a bookmark.
|
||||
let sourceVisitId = hs.addVisit(sourceURI,
|
||||
now,
|
||||
null,
|
||||
hs.TRANSITION_TYPED,
|
||||
false,
|
||||
0);
|
||||
do_check_eq(bs.getBookmarkedURIFor(sourceURI), null);
|
||||
|
||||
let sourceItemId = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
sourceURI,
|
||||
bs.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
|
||||
// Add a redirected visit.
|
||||
const permaURI = uri("http://perma.mozilla.org/");
|
||||
hs.addVisit(permaURI,
|
||||
now++,
|
||||
sourceURI,
|
||||
hs.TRANSITION_REDIRECT_PERMANENT,
|
||||
true,
|
||||
0);
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(permaURI).equals(sourceURI));
|
||||
// Add a bookmark to the destination.
|
||||
let permaItemId = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
permaURI,
|
||||
bs.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(permaURI).equals(permaURI));
|
||||
// Now remove the bookmark on the destination.
|
||||
bs.removeItem(permaItemId);
|
||||
// We should see the source as bookmark.
|
||||
do_check_true(bs.getBookmarkedURIFor(permaURI).equals(sourceURI));
|
||||
|
||||
// Add another redirected visit.
|
||||
const tempURI = uri("http://perma.mozilla.org/");
|
||||
hs.addVisit(tempURI,
|
||||
now++,
|
||||
permaURI,
|
||||
hs.TRANSITION_REDIRECT_TEMPORARY,
|
||||
true,
|
||||
0);
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(tempURI).equals(sourceURI));
|
||||
// Add a bookmark to the destination.
|
||||
let tempItemId = bs.insertBookmark(bs.unfiledBookmarksFolder,
|
||||
tempURI,
|
||||
bs.DEFAULT_INDEX,
|
||||
"bookmark");
|
||||
do_check_true(bs.getBookmarkedURIFor(sourceURI).equals(sourceURI));
|
||||
do_check_true(bs.getBookmarkedURIFor(tempURI).equals(tempURI));
|
||||
// Now remove the bookmark on the destination.
|
||||
bs.removeItem(tempItemId);
|
||||
// We should see the source as bookmark.
|
||||
do_check_true(bs.getBookmarkedURIFor(tempURI).equals(sourceURI));
|
||||
// Remove the source bookmark as well.
|
||||
bs.removeItem(sourceItemId);
|
||||
do_check_eq(bs.getBookmarkedURIFor(tempURI), null);
|
||||
}
|
Загрузка…
Ссылка в новой задаче