From e1220c43899834eff6af2ac839ea3d408554d780 Mon Sep 17 00:00:00 2001 From: "benjamin%smedbergs.us" Date: Tue, 18 Jul 2006 14:48:53 +0000 Subject: [PATCH] 324958 - folder undo delete back to previous folder id. Implement folder removal transaction in bookmarks service itself, using private methods to restore folders back to previous ids. Adjust fe to use new api. r=brettw (C++), annie.sullivan (JS) Original committer: beng%bengoodger.com Original revision: 1.56 Original date: 2006/03/25 00:46:09 --- .../components/places/src/nsNavBookmarks.cpp | 130 +++++++++++++----- 1 file changed, 99 insertions(+), 31 deletions(-) diff --git a/toolkit/components/places/src/nsNavBookmarks.cpp b/toolkit/components/places/src/nsNavBookmarks.cpp index 0d840fed7125..aaed471cb372 100644 --- a/toolkit/components/places/src/nsNavBookmarks.cpp +++ b/toolkit/components/places/src/nsNavBookmarks.cpp @@ -282,7 +282,10 @@ nsNavBookmarks::InitTables(mozIStorageConnection* aDBConn) // new primary key is unique, reducing the chance that stale references to // bookmark folders will reference a random folder. This slows down inserts // a little bit, which is why we don't always use it, but bookmark folders - // are not created very often. + // are not created very often. + // NOTE: The folder undo code depends on the autoincrement behavior because + // it must be able to undo deleting of a folder back to the old folder ID, + // which we assume has not been taken by something else. rv = aDBConn->TableExists(NS_LITERAL_CSTRING("moz_bookmarks_folders"), &exists); NS_ENSURE_SUCCESS(rv, rv); if (! exists) { @@ -962,6 +965,22 @@ nsNavBookmarks::ReplaceItem(PRInt64 aFolder, nsIURI *aItem, nsIURI *aNewItem) NS_IMETHODIMP nsNavBookmarks::CreateFolder(PRInt64 aParent, const nsAString &aName, PRInt32 aIndex, PRInt64 *aNewFolder) +{ + return CreateFolderWithID(-1, aParent, aName, aIndex, aNewFolder); +} + +NS_IMETHODIMP +nsNavBookmarks::CreateContainer(PRInt64 aParent, const nsAString &aName, + PRInt32 aIndex, const nsAString &aType, + PRInt64 *aNewFolder) +{ + return CreateContainerWithID(-1, aParent, aName, aIndex, aType, aNewFolder); +} + +nsresult +nsNavBookmarks::CreateFolderWithID(PRInt64 aFolder, PRInt64 aParent, + const nsAString& aName, PRInt32 aIndex, + PRInt64* aNewFolder) { mozIStorageConnection *dbConn = DBConn(); mozStorageTransaction transaction(dbConn, PR_FALSE); @@ -973,13 +992,24 @@ nsNavBookmarks::CreateFolder(PRInt64 aParent, const nsAString &aName, { nsCOMPtr statement; - rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks_folders (name, type) VALUES (?1, null)"), - getter_AddRefs(statement)); - NS_ENSURE_SUCCESS(rv, rv); + if (aFolder == -1) { + rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks_folders (name, type) VALUES (?1, null)"), + getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); - rv = statement->BindStringParameter(0, aName); - NS_ENSURE_SUCCESS(rv, rv); + rv = statement->BindStringParameter(0, aName); + NS_ENSURE_SUCCESS(rv, rv); + } + else { + rv = dbConn->CreateStatement(NS_LITERAL_CSTRING("INSERT INTO moz_bookmarks_folders (id, name, type) VALUES (?1, ?2, null)"), + getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); + rv = statement->BindInt64Parameter(0, aFolder); + NS_ENSURE_SUCCESS(rv, rv); + rv = statement->BindStringParameter(1, aName); + NS_ENSURE_SUCCESS(rv, rv); + } rv = statement->Execute(); NS_ENSURE_SUCCESS(rv, rv); } @@ -1009,13 +1039,13 @@ nsNavBookmarks::CreateFolder(PRInt64 aParent, const nsAString &aName, return NS_OK; } -NS_IMETHODIMP -nsNavBookmarks::CreateContainer(PRInt64 aParent, const nsAString &aName, - PRInt32 aIndex, const nsAString &aType, - PRInt64 *aNewFolder) +nsresult +nsNavBookmarks::CreateContainerWithID(PRInt64 aFolder, PRInt64 aParent, + const nsAString &aName, PRInt32 aIndex, + const nsAString &aType, PRInt64 *aNewFolder) { // Containers are wrappers around read-only folders, with a specific type. - nsresult rv = CreateFolder(aParent, aName, aIndex, aNewFolder); + nsresult rv = CreateFolderWithID(aFolder, aParent, aName, aIndex, aNewFolder); NS_ENSURE_SUCCESS(rv, rv); // Set the type. @@ -1035,7 +1065,6 @@ nsNavBookmarks::CreateContainer(PRInt64 aParent, const nsAString &aName, return NS_OK; } - NS_IMETHODIMP nsNavBookmarks::InsertSeparator(PRInt64 aParent, PRInt32 aIndex) { @@ -1165,6 +1194,31 @@ nsNavBookmarks::RemoveChildAt(PRInt64 aParent, PRInt32 aIndex) return NS_OK; } +nsresult +nsNavBookmarks::GetParentAndIndexOfFolder(PRInt64 aFolder, PRInt64* aParent, + PRInt32* aIndex) +{ + nsCAutoString buffer; + buffer.AssignLiteral("SELECT parent, position FROM moz_bookmarks WHERE folder_child = "); + buffer.AppendInt(aFolder); + + nsCOMPtr statement; + nsresult rv = DBConn()->CreateStatement(buffer, getter_AddRefs(statement)); + NS_ENSURE_SUCCESS(rv, rv); + + PRBool results; + rv = statement->ExecuteStep(&results); + NS_ENSURE_SUCCESS(rv, rv); + if (!results) { + return NS_ERROR_INVALID_ARG; // folder is not in the hierarchy + } + + *aParent = statement->AsInt64(0); + *aIndex = statement->AsInt32(1); + + return NS_OK; +} + NS_IMETHODIMP nsNavBookmarks::RemoveFolder(PRInt64 aFolder) { @@ -1186,32 +1240,16 @@ nsNavBookmarks::RemoveFolder(PRInt64 aFolder) mozIStorageConnection *dbConn = DBConn(); mozStorageTransaction transaction(dbConn, PR_FALSE); - nsCAutoString buffer; - buffer.AssignLiteral("SELECT parent, position FROM moz_bookmarks WHERE folder_child = "); - buffer.AppendInt(aFolder); - PRInt64 parent; PRInt32 index; - { - nsCOMPtr statement; - rv = dbConn->CreateStatement(buffer, getter_AddRefs(statement)); - NS_ENSURE_SUCCESS(rv, rv); - - PRBool results; - rv = statement->ExecuteStep(&results); - NS_ENSURE_SUCCESS(rv, rv); - if (!results) { - return NS_ERROR_INVALID_ARG; // folder is not in the hierarchy - } - - parent = statement->AsInt64(0); - index = statement->AsInt32(1); - } + rv = GetParentAndIndexOfFolder(aFolder, &parent, &index); + NS_ENSURE_SUCCESS(rv, rv); // Remove all of the folder's children RemoveFolderChildren(aFolder); // Remove the folder from its parent + nsCAutoString buffer; buffer.AssignLiteral("DELETE FROM moz_bookmarks WHERE folder_child = "); buffer.AppendInt(aFolder); rv = dbConn->ExecuteSimpleSQL(buffer); @@ -1235,6 +1273,36 @@ nsNavBookmarks::RemoveFolder(PRInt64 aFolder) return NS_OK; } +NS_IMPL_ISUPPORTS1(nsNavBookmarks::RemoveFolderTransaction, nsITransaction) + +NS_IMETHODIMP +nsNavBookmarks::GetRemoveFolderTransaction(PRInt64 aFolder, nsITransaction** aResult) +{ + // Create and initialize a RemoveFolderTransaction object that can be used to + // recreate the folder safely later. + + nsAutoString title; + nsresult rv = GetFolderTitle(aFolder, title); + NS_ENSURE_SUCCESS(rv, rv); + + PRInt64 parent; + PRInt32 index; + rv = GetParentAndIndexOfFolder(aFolder, &parent, &index); + NS_ENSURE_SUCCESS(rv, rv); + + nsCAutoString type; + rv = GetFolderType(aFolder, type); + NS_ENSURE_SUCCESS(rv, rv); + + RemoveFolderTransaction* rft = + new RemoveFolderTransaction(aFolder, parent, title, index, type); + if (!rft) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(*aResult = rft); + return NS_OK; +} + NS_IMETHODIMP nsNavBookmarks::RemoveFolderChildren(PRInt64 aFolder)