зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1555412 - Remove all the bookmark annotations but the last used one. r=Standard8
Differential Revision: https://phabricator.services.mozilla.com/D33044 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
68f8760568
Коммит
9793f55d17
|
@ -101,16 +101,6 @@
|
|||
// How much time Sqlite can wait before returning a SQLITE_BUSY error.
|
||||
#define DATABASE_BUSY_TIMEOUT_MS 100
|
||||
|
||||
// Old Sync GUID annotation.
|
||||
#define SYNCGUID_ANNO NS_LITERAL_CSTRING("sync/guid")
|
||||
|
||||
// Places string bundle, contains internationalized bookmark root names.
|
||||
#define PLACES_BUNDLE "chrome://places/locale/places.properties"
|
||||
|
||||
// This is no longer used & obsolete except for during migration.
|
||||
// Note: it may still be found in older places databases.
|
||||
#define MOBILE_ROOT_ANNO "mobile/bookmarksRoot"
|
||||
|
||||
// This annotation is no longer used & is obsolete, but here for migration.
|
||||
#define LAST_USED_ANNO \
|
||||
NS_LITERAL_CSTRING("bookmarkPropertiesDialog/folderLastUsed")
|
||||
|
@ -123,6 +113,9 @@
|
|||
// sets the title to the localized version when it creates the left pane query.
|
||||
#define MOBILE_ROOT_TITLE "mobile"
|
||||
|
||||
// Legacy item annotation used by the old Sync engine.
|
||||
#define SYNC_PARENT_ANNO "sync/parent"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -1138,51 +1131,13 @@ nsresult Database::InitSchema(bool* aDatabaseMigrated) {
|
|||
if (currentSchemaVersion < DATABASE_SCHEMA_VERSION) {
|
||||
*aDatabaseMigrated = true;
|
||||
|
||||
if (currentSchemaVersion < 30) {
|
||||
// These are versions older than Firefox 45 that are not supported
|
||||
if (currentSchemaVersion < 35) {
|
||||
// These are versions older than Firefox 52 ESR that are not supported
|
||||
// anymore. In this case it's safer to just replace the database.
|
||||
// Note that Firefox 45 is the ESR release before the latest one (52),
|
||||
// and Firefox 48 is a watershed release, so any version older than 48
|
||||
// will first have to go through it.
|
||||
return NS_ERROR_FILE_CORRUPTED;
|
||||
}
|
||||
|
||||
// Firefox 45 ESR uses schema version 30.
|
||||
|
||||
if (currentSchemaVersion < 31) {
|
||||
rv = MigrateV31Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 48 uses schema version 31.
|
||||
|
||||
if (currentSchemaVersion < 32) {
|
||||
rv = MigrateV32Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 49 uses schema version 32.
|
||||
|
||||
if (currentSchemaVersion < 33) {
|
||||
rv = MigrateV33Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 50 uses schema version 33.
|
||||
|
||||
if (currentSchemaVersion < 34) {
|
||||
rv = MigrateV34Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 51 uses schema version 34.
|
||||
|
||||
if (currentSchemaVersion < 35) {
|
||||
rv = MigrateV35Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 52 uses schema version 35.
|
||||
// Firefox 52 ESR uses schema version 35.
|
||||
|
||||
if (currentSchemaVersion < 36) {
|
||||
rv = MigrateV36Up();
|
||||
|
@ -1208,7 +1163,7 @@ nsresult Database::InitSchema(bool* aDatabaseMigrated) {
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 57 uses schema version 39.
|
||||
// Firefox 57 uses schema version 39. - This is a watershed version.
|
||||
|
||||
if (currentSchemaVersion < 40) {
|
||||
rv = MigrateV40Up();
|
||||
|
@ -1232,7 +1187,7 @@ nsresult Database::InitSchema(bool* aDatabaseMigrated) {
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 60 uses schema version 43.
|
||||
// Firefox 60 uses schema version 43. - This is an ESR.
|
||||
|
||||
if (currentSchemaVersion < 44) {
|
||||
rv = MigrateV44Up();
|
||||
|
@ -1283,6 +1238,13 @@ nsresult Database::InitSchema(bool* aDatabaseMigrated) {
|
|||
|
||||
// Firefox 62 uses schema version 52.
|
||||
|
||||
if (currentSchemaVersion < 53) {
|
||||
rv = MigrateV53Up();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Firefox 69 uses schema version 53
|
||||
|
||||
// Schema Upgrades must add migration code here.
|
||||
// >>> IMPORTANT! <<<
|
||||
// NEVER MIX UP SYNC AND ASYNC EXECUTION IN MIGRATORS, YOU MAY LOCK THE
|
||||
|
@ -1694,247 +1656,6 @@ nsresult Database::InitTempEntities() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV31Up() {
|
||||
nsresult rv = mMainConn->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("DROP TABLE IF EXISTS moz_bookmarks_roots"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV32Up() {
|
||||
// Remove some old and no more used Places preferences that may be confusing
|
||||
// for the user.
|
||||
mozilla::Unused << Preferences::ClearUser(
|
||||
"places.history.expiration.transient_optimal_database_size");
|
||||
mozilla::Unused << Preferences::ClearUser("places.last_vacuum");
|
||||
mozilla::Unused << Preferences::ClearUser("browser.history_expire_sites");
|
||||
mozilla::Unused << Preferences::ClearUser(
|
||||
"browser.history_expire_days.mirror");
|
||||
mozilla::Unused << Preferences::ClearUser("browser.history_expire_days_min");
|
||||
|
||||
// For performance reasons we want to remove too long urls from history.
|
||||
// We cannot use the moz_places triggers here, cause they are defined only
|
||||
// after the schema migration. Thus we need to collect the hosts that need to
|
||||
// be updated first.
|
||||
nsresult rv = mMainConn->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("CREATE TEMP TABLE moz_migrate_v32_temp ("
|
||||
"host TEXT PRIMARY KEY "
|
||||
") WITHOUT ROWID "));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("INSERT OR IGNORE INTO moz_migrate_v32_temp (host) "
|
||||
"SELECT fixup_url(get_unreversed_host(rev_host)) "
|
||||
"FROM moz_places WHERE LENGTH(url) > :maxlen AND "
|
||||
"foreign_count = 0"),
|
||||
getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("maxlen"), MaxUrlLength());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// Now remove the pages with a long url.
|
||||
{
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("DELETE FROM moz_places WHERE LENGTH(url) > :maxlen "
|
||||
"AND foreign_count = 0"),
|
||||
getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("maxlen"), MaxUrlLength());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Expire orphan visits and update moz_hosts.
|
||||
// These may be a bit more expensive and are not critical for the DB
|
||||
// functionality, so we execute them asynchronously.
|
||||
nsCOMPtr<mozIStorageAsyncStatement> expireOrphansStmt;
|
||||
rv = mMainConn->CreateAsyncStatement(
|
||||
NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_historyvisits "
|
||||
"WHERE NOT EXISTS (SELECT 1 FROM moz_places WHERE id = place_id)"),
|
||||
getter_AddRefs(expireOrphansStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<mozIStorageAsyncStatement> deleteHostsStmt;
|
||||
rv = mMainConn->CreateAsyncStatement(
|
||||
NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_hosts "
|
||||
"WHERE host IN (SELECT host FROM moz_migrate_v32_temp) "
|
||||
"AND NOT EXISTS("
|
||||
"SELECT 1 FROM moz_places "
|
||||
"WHERE rev_host = get_unreversed_host(host || '.') || '.' "
|
||||
"OR rev_host = get_unreversed_host(host || '.') || '.www.' "
|
||||
"); "),
|
||||
getter_AddRefs(deleteHostsStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#define HOST_TO_REVHOST_PREDICATE \
|
||||
"rev_host = get_unreversed_host(host || '.') || '.' " \
|
||||
"OR rev_host = get_unreversed_host(host || '.') || '.www.'"
|
||||
#define HOSTS_PREFIX_PRIORITY_FRAGMENT \
|
||||
"SELECT CASE " \
|
||||
"WHEN ( " \
|
||||
"SELECT round(avg(substr(url,1,12) = 'https://www.')) FROM moz_places h " \
|
||||
"WHERE (" HOST_TO_REVHOST_PREDICATE \
|
||||
") AND +h.typed = 1 " \
|
||||
") THEN 'https://www.' " \
|
||||
"WHEN ( " \
|
||||
"SELECT round(avg(substr(url,1,8) = 'https://')) FROM moz_places h " \
|
||||
"WHERE (" HOST_TO_REVHOST_PREDICATE \
|
||||
") AND +h.typed = 1 " \
|
||||
") THEN 'https://' " \
|
||||
"WHEN 1 = ( " \
|
||||
"SELECT min(substr(url,1,4) = 'ftp:') FROM moz_places h " \
|
||||
"WHERE (" HOST_TO_REVHOST_PREDICATE \
|
||||
") AND +h.typed = 1 " \
|
||||
") THEN 'ftp://' " \
|
||||
"WHEN ( " \
|
||||
"SELECT round(avg(substr(url,1,11) = 'http://www.')) FROM moz_places h " \
|
||||
"WHERE (" HOST_TO_REVHOST_PREDICATE \
|
||||
") AND +h.typed = 1 " \
|
||||
") THEN 'www.' " \
|
||||
"END "
|
||||
|
||||
nsCOMPtr<mozIStorageAsyncStatement> updateHostsStmt;
|
||||
rv = mMainConn->CreateAsyncStatement(
|
||||
NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_hosts "
|
||||
"SET prefix = (" HOSTS_PREFIX_PRIORITY_FRAGMENT ") "
|
||||
"WHERE host IN (SELECT host FROM moz_migrate_v32_temp) "),
|
||||
getter_AddRefs(updateHostsStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#undef HOST_TO_REVHOST_PREDICATE
|
||||
#undef HOSTS_PREFIX_PRIORITY_FRAGMENT
|
||||
|
||||
nsCOMPtr<mozIStorageAsyncStatement> dropTableStmt;
|
||||
rv = mMainConn->CreateAsyncStatement(
|
||||
NS_LITERAL_CSTRING("DROP TABLE IF EXISTS moz_migrate_v32_temp"),
|
||||
getter_AddRefs(dropTableStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsTArray<RefPtr<mozIStorageBaseStatement>> stmts = {
|
||||
expireOrphansStmt.forget(),
|
||||
deleteHostsStmt.forget(),
|
||||
updateHostsStmt.forget(),
|
||||
dropTableStmt.forget(),
|
||||
};
|
||||
nsCOMPtr<mozIStoragePendingStatement> ps;
|
||||
rv = mMainConn->ExecuteAsync(stmts, nullptr, getter_AddRefs(ps));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV33Up() {
|
||||
nsresult rv = mMainConn->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("DROP INDEX IF EXISTS moz_places_url_uniqueindex"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Add an url_hash column to moz_places.
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT url_hash FROM moz_places"),
|
||||
getter_AddRefs(stmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
rv = mMainConn->ExecuteSimpleSQL(
|
||||
NS_LITERAL_CSTRING("ALTER TABLE moz_places ADD COLUMN url_hash INTEGER "
|
||||
"DEFAULT 0 NOT NULL"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"UPDATE moz_places SET url_hash = hash(url) WHERE url_hash = 0"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Create an index on url_hash.
|
||||
rv = mMainConn->ExecuteSimpleSQL(CREATE_IDX_MOZ_PLACES_URL_HASH);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV34Up() {
|
||||
nsresult rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_keywords WHERE id IN ( "
|
||||
"SELECT id FROM moz_keywords k "
|
||||
"WHERE NOT EXISTS (SELECT 1 FROM moz_places h WHERE k.place_id = h.id) "
|
||||
")"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV35Up() {
|
||||
int64_t mobileRootId = CreateMobileRoot();
|
||||
if (mobileRootId <= 0) {
|
||||
// Either the schema is broken or there isn't any root. The latter can
|
||||
// happen if a consumer, for example Thunderbird, never used bookmarks.
|
||||
// If there are no roots, this migration should not run.
|
||||
nsCOMPtr<mozIStorageStatement> checkRootsStmt;
|
||||
nsresult rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT id FROM moz_bookmarks WHERE parent = 0"),
|
||||
getter_AddRefs(checkRootsStmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
bool hasResult = false;
|
||||
rv = checkRootsStmt->ExecuteStep(&hasResult);
|
||||
if (NS_SUCCEEDED(rv) && !hasResult) {
|
||||
return NS_OK;
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// At this point, we should have no more than two folders with the mobile
|
||||
// bookmarks anno: the new root, and the old folder if one exists. If, for
|
||||
// some reason, we have multiple folders with the anno, we append their
|
||||
// children to the new root.
|
||||
nsTArray<int64_t> folderIds;
|
||||
nsresult rv =
|
||||
GetItemsWithAnno(NS_LITERAL_CSTRING(MOBILE_ROOT_ANNO),
|
||||
nsINavBookmarksService::TYPE_FOLDER, folderIds);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (uint32_t i = 0; i < folderIds.Length(); ++i) {
|
||||
if (folderIds[i] == mobileRootId) {
|
||||
// Ignore the new mobile root. We'll remove this anno from the root in
|
||||
// bug 1306445.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Append the folder's children to the new root.
|
||||
nsCOMPtr<mozIStorageStatement> moveStmt;
|
||||
rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("UPDATE moz_bookmarks "
|
||||
"SET parent = :root_id, "
|
||||
"position = position + IFNULL("
|
||||
"(SELECT MAX(position) + 1 FROM moz_bookmarks "
|
||||
"WHERE parent = :root_id), 0)"
|
||||
"WHERE parent = :folder_id"),
|
||||
getter_AddRefs(moveStmt));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = moveStmt->BindInt64ByName(NS_LITERAL_CSTRING("root_id"), mobileRootId);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = moveStmt->BindInt64ByName(NS_LITERAL_CSTRING("folder_id"),
|
||||
folderIds[i]);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = moveStmt->Execute();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Delete the old folder.
|
||||
rv = DeleteBookmarkItem(folderIds[i]);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV36Up() {
|
||||
// Add sync status and change counter tracking columns for bookmarks.
|
||||
nsCOMPtr<mozIStorageStatement> syncStatusStmt;
|
||||
|
@ -2688,6 +2409,44 @@ nsresult Database::MigrateV52Up() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::MigrateV53Up() {
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
nsresult rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("SELECT 1 FROM moz_items_annos"),
|
||||
getter_AddRefs(stmt));
|
||||
if (NS_FAILED(rv)) {
|
||||
// Likely we removed the table.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove all item annotations but SYNC_PARENT_ANNO.
|
||||
rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_items_annos "
|
||||
"WHERE anno_attribute_id NOT IN ( "
|
||||
" SELECT id FROM moz_anno_attributes WHERE name = :anno_name "
|
||||
") "),
|
||||
getter_AddRefs(stmt));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"),
|
||||
NS_LITERAL_CSTRING(SYNC_PARENT_ANNO));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->Execute();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mMainConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_anno_attributes WHERE id IN ( "
|
||||
" SELECT id FROM moz_anno_attributes "
|
||||
" EXCEPT "
|
||||
" SELECT DISTINCT anno_attribute_id FROM moz_annos "
|
||||
" EXCEPT "
|
||||
" SELECT DISTINCT anno_attribute_id FROM moz_items_annos "
|
||||
")"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::ConvertOldStyleQuery(nsCString& aURL) {
|
||||
AutoTArray<QueryKeyValuePair, 8> tokens;
|
||||
nsresult rv = TokenizeQueryString(aURL, &tokens);
|
||||
|
@ -2765,67 +2524,6 @@ nsresult Database::ConvertOldStyleQuery(nsCString& aURL) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::GetItemsWithAnno(const nsACString& aAnnoName,
|
||||
int32_t aItemType,
|
||||
nsTArray<int64_t>& aItemIds) {
|
||||
nsCOMPtr<mozIStorageStatement> stmt;
|
||||
nsresult rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING(
|
||||
"SELECT b.id FROM moz_items_annos a "
|
||||
"JOIN moz_anno_attributes n ON n.id = a.anno_attribute_id "
|
||||
"JOIN moz_bookmarks b ON b.id = a.item_id "
|
||||
"WHERE n.name = :anno_name AND "
|
||||
"b.type = :item_type"),
|
||||
getter_AddRefs(stmt));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"), aAnnoName);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = stmt->BindInt64ByName(NS_LITERAL_CSTRING("item_type"), aItemType);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
bool hasMore = false;
|
||||
while (NS_SUCCEEDED(stmt->ExecuteStep(&hasMore)) && hasMore) {
|
||||
int64_t itemId;
|
||||
rv = stmt->GetInt64(0, &itemId);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
aItemIds.AppendElement(itemId);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult Database::DeleteBookmarkItem(int32_t aItemId) {
|
||||
// Delete the old bookmark.
|
||||
nsCOMPtr<mozIStorageStatement> deleteStmt;
|
||||
nsresult rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING("DELETE FROM moz_bookmarks WHERE id = :item_id"),
|
||||
getter_AddRefs(deleteStmt));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = deleteStmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = deleteStmt->Execute();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Clean up orphan annotations.
|
||||
nsCOMPtr<mozIStorageStatement> removeAnnosStmt;
|
||||
rv = mMainConn->CreateStatement(
|
||||
NS_LITERAL_CSTRING(
|
||||
"DELETE FROM moz_items_annos WHERE item_id = :item_id"),
|
||||
getter_AddRefs(removeAnnosStmt));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = removeAnnosStmt->BindInt64ByName(NS_LITERAL_CSTRING("item_id"), aItemId);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = removeAnnosStmt->Execute();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int64_t Database::CreateMobileRoot() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
// This is the schema version. Update it at any schema change and add a
|
||||
// corresponding migrateVxx method below.
|
||||
#define DATABASE_SCHEMA_VERSION 52
|
||||
#define DATABASE_SCHEMA_VERSION 53
|
||||
|
||||
// Fired after Places inited.
|
||||
#define TOPIC_PLACES_INIT_COMPLETE "places-init-complete"
|
||||
|
@ -319,11 +319,6 @@ class Database final : public nsIObserver, public nsSupportsWeakReference {
|
|||
/**
|
||||
* Helpers used by schema upgrades.
|
||||
*/
|
||||
nsresult MigrateV31Up();
|
||||
nsresult MigrateV32Up();
|
||||
nsresult MigrateV33Up();
|
||||
nsresult MigrateV34Up();
|
||||
nsresult MigrateV35Up();
|
||||
nsresult MigrateV36Up();
|
||||
nsresult MigrateV37Up();
|
||||
nsresult MigrateV38Up();
|
||||
|
@ -341,6 +336,7 @@ class Database final : public nsIObserver, public nsSupportsWeakReference {
|
|||
nsresult MigrateV50Up();
|
||||
nsresult MigrateV51Up();
|
||||
nsresult MigrateV52Up();
|
||||
nsresult MigrateV53Up();
|
||||
|
||||
void MigrateV52OriginFrecencies();
|
||||
|
||||
|
@ -350,9 +346,6 @@ class Database final : public nsIObserver, public nsSupportsWeakReference {
|
|||
|
||||
int64_t CreateMobileRoot();
|
||||
nsresult ConvertOldStyleQuery(nsCString& aURL);
|
||||
nsresult GetItemsWithAnno(const nsACString& aAnnoName, int32_t aItemType,
|
||||
nsTArray<int64_t>& aItemIds);
|
||||
nsresult DeleteBookmarkItem(int32_t aItemId);
|
||||
|
||||
private:
|
||||
~Database();
|
||||
|
|
|
@ -49,10 +49,6 @@ int64_t NS_NavBookmarksTotalSyncChanges() {
|
|||
|
||||
PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsNavBookmarks, gBookmarksService)
|
||||
|
||||
#define BOOKMARKS_ANNO_PREFIX "bookmarks/"
|
||||
#define BOOKMARKS_TOOLBAR_FOLDER_ANNO \
|
||||
NS_LITERAL_CSTRING(BOOKMARKS_ANNO_PREFIX "toolbarFolder")
|
||||
#define SYNC_PARENT_ANNO "sync/parent"
|
||||
#define SQLITE_MAX_VARIABLE_NUMBER 999
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -15,8 +15,8 @@ var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
|
||||
// Put any other stuff relative to this test folder below.
|
||||
|
||||
const CURRENT_SCHEMA_VERSION = 52;
|
||||
const FIRST_UPGRADABLE_SCHEMA_VERSION = 30;
|
||||
const CURRENT_SCHEMA_VERSION = 53;
|
||||
const FIRST_UPGRADABLE_SCHEMA_VERSION = 35;
|
||||
|
||||
async function assertAnnotationsRemoved(db, expectedAnnos) {
|
||||
for (let anno of expectedAnnos) {
|
||||
|
|
Двоичные данные
toolkit/components/places/tests/migration/places_v31.sqlite
Двоичные данные
toolkit/components/places/tests/migration/places_v31.sqlite
Двоичный файл не отображается.
Двоичные данные
toolkit/components/places/tests/migration/places_v34.sqlite
Двоичные данные
toolkit/components/places/tests/migration/places_v34.sqlite
Двоичный файл не отображается.
|
@ -1,46 +0,0 @@
|
|||
// Add pages.
|
||||
let shorturl = "http://example.com/" + "a".repeat(1981);
|
||||
let longurl = "http://example.com/" + "a".repeat(1982);
|
||||
let bmurl = "http://example.com/" + "a".repeat(1983);
|
||||
|
||||
add_task(async function setup() {
|
||||
await setupPlacesDatabase("places_v31.sqlite");
|
||||
// Setup database contents to be migrated.
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, DB_FILENAME);
|
||||
let db = await Sqlite.openConnection({ path });
|
||||
|
||||
await db.execute(`INSERT INTO moz_places (url, guid, foreign_count)
|
||||
VALUES (:shorturl, "test1_______", 0)
|
||||
, (:longurl, "test2_______", 0)
|
||||
, (:bmurl, "test3_______", 1)
|
||||
`, { shorturl, longurl, bmurl });
|
||||
// Add visits.
|
||||
await db.execute(`INSERT INTO moz_historyvisits (place_id)
|
||||
VALUES ((SELECT id FROM moz_places WHERE url = :shorturl))
|
||||
, ((SELECT id FROM moz_places WHERE url = :longurl))
|
||||
`, { shorturl, longurl });
|
||||
await db.close();
|
||||
});
|
||||
|
||||
add_task(async function database_is_valid() {
|
||||
Assert.equal(PlacesUtils.history.databaseStatus,
|
||||
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
|
||||
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
Assert.equal((await db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
|
||||
});
|
||||
|
||||
add_task(async function test_longurls() {
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
let rows = await db.execute(`SELECT 1 FROM moz_places where url = :longurl`,
|
||||
{ longurl });
|
||||
Assert.equal(rows.length, 0, "Long url should have been removed");
|
||||
rows = await db.execute(`SELECT 1 FROM moz_places where url = :shorturl`,
|
||||
{ shorturl });
|
||||
Assert.equal(rows.length, 1, "Short url should have been retained");
|
||||
rows = await db.execute(`SELECT 1 FROM moz_places where url = :bmurl`,
|
||||
{ bmurl });
|
||||
Assert.equal(rows.length, 1, "Bookmarked url should have been retained");
|
||||
rows = await db.execute(`SELECT count(*) FROM moz_historyvisits`);
|
||||
Assert.equal(rows.length, 1, "Orphan visists should have been removed");
|
||||
});
|
|
@ -1,134 +0,0 @@
|
|||
Cu.importGlobalProperties(["crypto"]);
|
||||
|
||||
const { TYPE_BOOKMARK, TYPE_FOLDER } = Ci.nsINavBookmarksService;
|
||||
const { EXPIRE_NEVER, TYPE_INT32 } = Ci.nsIAnnotationService;
|
||||
|
||||
function makeGuid() {
|
||||
return ChromeUtils.base64URLEncode(crypto.getRandomValues(new Uint8Array(9)), {
|
||||
pad: false,
|
||||
});
|
||||
}
|
||||
|
||||
// These queries are more or less copied directly from Bookmarks.jsm, but
|
||||
// operate on the old, pre-migration DB. We can't use any of the Places SQL
|
||||
// functions yet, because those are only registered for the main connection.
|
||||
async function insertItem(db, info) {
|
||||
let [parentInfo] = await db.execute(`
|
||||
SELECT b.id, (SELECT count(*) FROM moz_bookmarks
|
||||
WHERE parent = b.id) AS childCount
|
||||
FROM moz_bookmarks b
|
||||
WHERE b.guid = :parentGuid`,
|
||||
{ parentGuid: info.parentGuid });
|
||||
|
||||
let guid = makeGuid();
|
||||
await db.execute(`
|
||||
INSERT INTO moz_bookmarks (fk, type, parent, position, guid)
|
||||
VALUES ((SELECT id FROM moz_places WHERE url = :url),
|
||||
:type, :parent, :position, :guid)`,
|
||||
{ url: info.url || "nonexistent", type: info.type, guid,
|
||||
// Just append items.
|
||||
position: parentInfo.getResultByName("childCount"),
|
||||
parent: parentInfo.getResultByName("id") });
|
||||
|
||||
let id = (await db.execute(`
|
||||
SELECT id FROM moz_bookmarks WHERE guid = :guid LIMIT 1`,
|
||||
{ guid }))[0].getResultByName("id");
|
||||
|
||||
return { id, guid };
|
||||
}
|
||||
|
||||
function insertBookmark(db, info) {
|
||||
return db.executeTransaction(async function() {
|
||||
if (info.type == TYPE_BOOKMARK) {
|
||||
// We don't have access to the hash function here, so we omit the
|
||||
// `url_hash` column. These will be fixed up automatically during
|
||||
// migration.
|
||||
let url = new URL(info.url);
|
||||
let placeGuid = makeGuid();
|
||||
await db.execute(`
|
||||
INSERT INTO moz_places (url, rev_host, hidden, frecency, guid)
|
||||
VALUES (:url, :rev_host, 0, -1, :guid)`,
|
||||
{ url: url.href, guid: placeGuid,
|
||||
rev_host: PlacesUtils.getReversedHost(url) });
|
||||
}
|
||||
return insertItem(db, info);
|
||||
});
|
||||
}
|
||||
|
||||
async function insertAnno(db, itemId, name, value) {
|
||||
await db.execute(`INSERT OR IGNORE INTO moz_anno_attributes (name)
|
||||
VALUES (:name)`, { name });
|
||||
await db.execute(`
|
||||
INSERT INTO moz_items_annos
|
||||
(item_id, anno_attribute_id, content, flags,
|
||||
expiration, type, dateAdded, lastModified)
|
||||
VALUES (:itemId,
|
||||
(SELECT id FROM moz_anno_attributes
|
||||
WHERE name = :name),
|
||||
1, 0, :expiration, :type, 0, 0)
|
||||
`, { itemId, name, expiration: EXPIRE_NEVER, type: TYPE_INT32 });
|
||||
}
|
||||
|
||||
function insertMobileFolder(db) {
|
||||
return db.executeTransaction(async function() {
|
||||
let item = await insertItem(db, {
|
||||
type: TYPE_FOLDER,
|
||||
parentGuid: "root________",
|
||||
});
|
||||
await insertAnno(db, item.id, "mobile/bookmarksRoot", 1);
|
||||
return item;
|
||||
});
|
||||
}
|
||||
|
||||
var mobileId, mobileGuid, fxGuid;
|
||||
var dupeMobileId, dupeMobileGuid, tbGuid;
|
||||
|
||||
add_task(async function setup() {
|
||||
await setupPlacesDatabase("places_v34.sqlite");
|
||||
// Setup database contents to be migrated.
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, DB_FILENAME);
|
||||
let db = await Sqlite.openConnection({ path });
|
||||
|
||||
info("Create mobile folder with bookmarks");
|
||||
({ id: mobileId, guid: mobileGuid } = await insertMobileFolder(db));
|
||||
({ guid: fxGuid } = await insertBookmark(db, {
|
||||
type: TYPE_BOOKMARK,
|
||||
url: "http://getfirefox.com",
|
||||
parentGuid: mobileGuid,
|
||||
}));
|
||||
|
||||
// We should only have one mobile folder, but, in case an old version of Sync
|
||||
// did the wrong thing and created multiple mobile folders, we should merge
|
||||
// their contents into the new mobile root.
|
||||
info("Create second mobile folder with different bookmarks");
|
||||
({ id: dupeMobileId, guid: dupeMobileGuid } = await insertMobileFolder(db));
|
||||
({ guid: tbGuid } = await insertBookmark(db, {
|
||||
type: TYPE_BOOKMARK,
|
||||
url: "http://getthunderbird.com",
|
||||
parentGuid: dupeMobileGuid,
|
||||
}));
|
||||
|
||||
await db.close();
|
||||
});
|
||||
|
||||
add_task(async function database_is_valid() {
|
||||
// Accessing the database for the first time triggers migration.
|
||||
Assert.equal(PlacesUtils.history.databaseStatus,
|
||||
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
|
||||
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
Assert.equal((await db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
|
||||
});
|
||||
|
||||
add_task(async function test_mobile_root() {
|
||||
let fxBmk = await PlacesUtils.bookmarks.fetch(fxGuid);
|
||||
equal(fxBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
|
||||
"Firefox bookmark should be moved to new mobile root");
|
||||
equal(fxBmk.index, 0, "Firefox bookmark should be first child of new root");
|
||||
|
||||
let tbBmk = await PlacesUtils.bookmarks.fetch(tbGuid);
|
||||
equal(tbBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
|
||||
"Thunderbird bookmark should be moved to new mobile root");
|
||||
equal(tbBmk.index, 1,
|
||||
"Thunderbird bookmark should be second child of new root");
|
||||
});
|
|
@ -1,21 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
add_task(async function setup() {
|
||||
await setupPlacesDatabase("places_v34.sqlite");
|
||||
// Setup database contents to be migrated.
|
||||
let path = OS.Path.join(OS.Constants.Path.profileDir, DB_FILENAME);
|
||||
let db = await Sqlite.openConnection({ path });
|
||||
// Remove all the roots.
|
||||
await db.execute("DELETE FROM moz_bookmarks");
|
||||
await db.close();
|
||||
});
|
||||
|
||||
add_task(async function database_is_valid() {
|
||||
// Accessing the database for the first time triggers migration.
|
||||
Assert.equal(PlacesUtils.history.databaseStatus,
|
||||
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
|
||||
|
||||
let db = await PlacesUtils.promiseDBConnection();
|
||||
Assert.equal((await db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
|
||||
});
|
|
@ -4,8 +4,6 @@ head = head_migration.js
|
|||
support-files =
|
||||
favicons_v41.sqlite
|
||||
places_outdated.sqlite
|
||||
places_v31.sqlite
|
||||
places_v34.sqlite
|
||||
places_v35.sqlite
|
||||
places_v36.sqlite
|
||||
places_v38.sqlite
|
||||
|
@ -14,9 +12,6 @@ support-files =
|
|||
|
||||
[test_current_from_downgraded.js]
|
||||
[test_current_from_outdated.js]
|
||||
[test_current_from_v31.js]
|
||||
[test_current_from_v34.js]
|
||||
[test_current_from_v34_no_roots.js]
|
||||
[test_current_from_v35.js]
|
||||
[test_current_from_v36.js]
|
||||
[test_current_from_v38.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче