Bug 360134: Add GUIDs to items so they can be uniquely identified across profiles (for sync purposes). r=mano

This commit is contained in:
thunder%mozilla.com 2007-07-26 03:54:00 +00:00
Родитель 6ddd341252
Коммит 6bff8dbaa0
4 изменённых файлов: 189 добавлений и 2 удалений

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

@ -161,7 +161,7 @@ interface nsINavBookmarkObserver : nsISupports
* folders. A URI in history can be contained in one or more such folders. * folders. A URI in history can be contained in one or more such folders.
*/ */
[scriptable, uuid(c3307160-525d-4d3c-9d75-b4f13a9ca05d)] [scriptable, uuid(630dcd21-402c-44cd-8336-78bff3efc5f3)]
interface nsINavBookmarksService : nsISupports interface nsINavBookmarksService : nsISupports
{ {
/** /**
@ -327,6 +327,35 @@ interface nsINavBookmarksService : nsISupports
*/ */
void removeChildAt(in long long aFolder, in long aIndex); void removeChildAt(in long long aFolder, in long aIndex);
/**
* Get a globally unique identifier for an item, meant to be used in
* sync scenarios. Even if their contents are exactly the same
* (including an item in a different profile with the same ItemId),
* the GUID would be different.
* @param aItemId
* The ID of the item to get the GUID for
* @returns The GUID string
*/
AString getItemGUID(in long long aItemId);
/**
* Set a globally unique identifier. This can be useful when a sync
* algorithm deems two independently created items (on different
* profiles) to be the same item.
* @param aItemId
* The id of the item to set the GUID of
* @returns The GUID string
*/
void setItemGUID(in long long aItemId, in AString aGUID);
/**
* Get the ID of the item with the given GUID.
* @param aGUID
* The GUID string of the item to search for
* @returns The item ID, or -1 if not found
*/
long long getItemIdForGUID(in AString aGUID);
/** /**
* Set the title for an item. * Set the title for an item.
* @param aItemId * @param aItemId

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

@ -48,6 +48,9 @@
#include "nsAnnotationService.h" #include "nsAnnotationService.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsAutoLock.h" #include "nsAutoLock.h"
#include "nsIUUIDGenerator.h"
#include "prmem.h"
#include "prprf.h"
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ID = 0; const PRInt32 nsNavBookmarks::kFindBookmarksIndex_ID = 0;
const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Type = 1; const PRInt32 nsNavBookmarks::kFindBookmarksIndex_Type = 1;
@ -76,10 +79,11 @@ nsNavBookmarks* nsNavBookmarks::sInstance = nsnull;
#define BOOKMARKS_ANNO_PREFIX "bookmarks/" #define BOOKMARKS_ANNO_PREFIX "bookmarks/"
#define BOOKMARKS_TOOLBAR_FOLDER_ANNO NS_LITERAL_CSTRING(BOOKMARKS_ANNO_PREFIX "toolbarFolder") #define BOOKMARKS_TOOLBAR_FOLDER_ANNO NS_LITERAL_CSTRING(BOOKMARKS_ANNO_PREFIX "toolbarFolder")
#define GUID_ANNO NS_LITERAL_CSTRING("placesInternal/GUID")
nsNavBookmarks::nsNavBookmarks() nsNavBookmarks::nsNavBookmarks()
: mRoot(0), mBookmarksRoot(0), mTagRoot(0), mToolbarFolder(0), mBatchLevel(0), : mRoot(0), mBookmarksRoot(0), mTagRoot(0), mToolbarFolder(0), mBatchLevel(0),
mBatchHasTransaction(PR_FALSE), mLock(nsnull) mItemCount(0), mBatchHasTransaction(PR_FALSE), mLock(nsnull)
{ {
NS_ASSERTION(!sInstance, "Multiple nsNavBookmarks instances!"); NS_ASSERTION(!sInstance, "Multiple nsNavBookmarks instances!");
sInstance = this; sInstance = this;
@ -185,6 +189,13 @@ nsNavBookmarks::Init()
getter_AddRefs(mDBGetItemProperties)); getter_AddRefs(mDBGetItemProperties));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT item_id FROM moz_items_annos "
"WHERE content = ?1 "
"LIMIT 1"),
getter_AddRefs(mDBGetItemIdForGUID));
NS_ENSURE_SUCCESS(rv, rv);
// mDBGetRedirectDestinations // mDBGetRedirectDestinations
// input = page ID, time threshold; output = unique ID input has redirected to // input = page ID, time threshold; output = unique ID input has redirected to
rv = dbConn->CreateStatement(NS_LITERAL_CSTRING( rv = dbConn->CreateStatement(NS_LITERAL_CSTRING(
@ -228,6 +239,17 @@ nsNavBookmarks::Init()
getter_AddRefs(mDBGetURIForKeyword)); getter_AddRefs(mDBGetURIForKeyword));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
// generate a new GUID base for this session
nsCOMPtr<nsIUUIDGenerator> uuidgen = do_GetService("@mozilla.org/uuid-generator;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsID GUID;
rv = uuidgen->GenerateUUIDInPlace(&GUID);
NS_ENSURE_SUCCESS(rv, rv);
char* GUIDChars = GUID.ToString();
NS_ENSURE_TRUE(GUIDChars, NS_ERROR_OUT_OF_MEMORY);
mGUIDBase.Assign(NS_ConvertASCIItoUTF16(GUIDChars));
PR_Free(GUIDChars);
rv = InitRoots(); rv = InitRoots();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -1697,6 +1719,56 @@ nsNavBookmarks::GetItemLastModified(PRInt64 aItemId, PRTime *aLastModified)
return mDBGetItemProperties->GetInt64(kGetItemPropertiesIndex_LastModified, aLastModified); return mDBGetItemProperties->GetInt64(kGetItemPropertiesIndex_LastModified, aLastModified);
} }
NS_IMETHODIMP
nsNavBookmarks::GetItemGUID(PRInt64 aItemId, nsAString &aGUID)
{
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = annosvc->GetItemAnnotationString(aItemId, GUID_ANNO, aGUID);
if (NS_SUCCEEDED(rv) || rv != NS_ERROR_NOT_AVAILABLE)
return rv;
nsAutoString tmp;
tmp.Assign(mGUIDBase);
tmp.AppendInt(mItemCount++);
aGUID.Assign(tmp);
return SetItemGUID(aItemId, aGUID);
}
NS_IMETHODIMP
nsNavBookmarks::SetItemGUID(PRInt64 aItemId, const nsAString &aGUID)
{
PRInt64 checkId;
GetItemIdForGUID(aGUID, &checkId);
if (checkId != -1)
return NS_ERROR_INVALID_ARG; // invalid GUID, already exists
nsAnnotationService* annosvc = nsAnnotationService::GetAnnotationService();
NS_ENSURE_TRUE(annosvc, NS_ERROR_OUT_OF_MEMORY);
return annosvc->SetItemAnnotationString(aItemId, GUID_ANNO, aGUID, 0,
nsIAnnotationService::EXPIRE_NEVER);
}
NS_IMETHODIMP
nsNavBookmarks::GetItemIdForGUID(const nsAString &aGUID, PRInt64 *aItemId)
{
mozStorageStatementScoper scoper(mDBGetItemIdForGUID);
nsresult rv = mDBGetItemIdForGUID->BindStringParameter(0, aGUID);
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasMore = PR_FALSE;
rv = mDBGetItemIdForGUID->ExecuteStep(&hasMore);
if (NS_FAILED(rv) || ! hasMore) {
*aItemId = -1;
return NS_OK; // not found: return -1
}
// found, get the itemId
return mDBGetItemIdForGUID->GetInt64(0, aItemId);
}
NS_IMETHODIMP NS_IMETHODIMP
nsNavBookmarks::SetItemTitle(PRInt64 aItemId, const nsAString &aTitle) nsNavBookmarks::SetItemTitle(PRInt64 aItemId, const nsAString &aTitle)
{ {

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

@ -138,6 +138,9 @@ private:
mozIStorageConnection* DBConn() { return History()->GetStorageConnection(); } mozIStorageConnection* DBConn() { return History()->GetStorageConnection(); }
nsString mGUIDBase;
PRInt32 mItemCount;
nsMaybeWeakPtrArray<nsINavBookmarkObserver> mObservers; nsMaybeWeakPtrArray<nsINavBookmarkObserver> mObservers;
PRInt64 mRoot; PRInt64 mRoot;
PRInt64 mBookmarksRoot; PRInt64 mBookmarksRoot;
@ -201,6 +204,8 @@ private:
static const PRInt32 kGetItemPropertiesIndex_DateAdded; static const PRInt32 kGetItemPropertiesIndex_DateAdded;
static const PRInt32 kGetItemPropertiesIndex_LastModified; static const PRInt32 kGetItemPropertiesIndex_LastModified;
nsCOMPtr<mozIStorageStatement> mDBGetItemIdForGUID;
nsCOMPtr<mozIStorageStatement> mDBGetRedirectDestinations; nsCOMPtr<mozIStorageStatement> mDBGetRedirectDestinations;
// keywords // keywords

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

@ -0,0 +1,81 @@
/* -*- 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 Bug 360134 (item guids) unit test code.
*
* The Initial Developer of the Original Code is Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dan Mills <thunder@mozilla.com>
*
* 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 ***** */
// Get bookmark service
try {
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
} catch(ex) {
do_throw("Could not get nav-bookmarks-service\n");
}
// main
function run_test() {
var URI = uri("http://foo.tld.com/");
var folderId = bmsvc.createFolder(bmsvc.placesRoot, "test folder",
bmsvc.DEFAULT_INDEX);
var bookmarkId = bmsvc.insertBookmark(folderId, URI, bmsvc.DEFAULT_INDEX, "a title");
var separatorId = bmsvc.insertSeparator(folderId, bmsvc.DEFAULT_INDEX);
// get & uniqueness
do_check_eq(bmsvc.getItemGUID(bookmarkId), bmsvc.getItemGUID(bookmarkId));
do_check_neq(bmsvc.getItemGUID(folderId), bmsvc.getItemGUID(bookmarkId));
do_check_neq(bmsvc.getItemGUID(folderId), "");
do_check_neq(bmsvc.getItemGUID(separatorId), bmsvc.getItemGUID(bookmarkId));
do_check_neq(bmsvc.getItemGUID(separatorId), "");
// set
bmsvc.setItemGUID(bookmarkId, "asdf123");
do_check_eq(bmsvc.getItemGUID(bookmarkId), "asdf123");
bmsvc.setItemGUID(folderId, "123asdf");
do_check_eq(bmsvc.getItemGUID(folderId), "123asdf");
try {
bmsvc.setItemGUID(bookmarkId, "123asdf"); // should fail
} catch (e) {
do_check_eq(e.result, Cr.NS_ERROR_ILLEGAL_VALUE);
}
// GUID -> itemId
do_check_eq(bmsvc.getItemIdForGUID("asdf123"), bookmarkId);
do_check_eq(bmsvc.getItemIdForGUID("123asdf"), folderId);
}