Bug 822710 (part 1) - Implement a new getAnnotationsHavingName method.

r=Mano sr=gavin
This commit is contained in:
Marco Bonardo 2012-12-21 15:19:04 +01:00
parent 66912dba05
commit ec97496687
4 changed files with 298 additions and 2 deletions

View File

@ -23,6 +23,7 @@
#include "nsNetCID.h" #include "nsNetCID.h"
using namespace mozilla; using namespace mozilla;
using namespace mozilla::places;
#define ENSURE_ANNO_TYPE(_type, _statement) \ #define ENSURE_ANNO_TYPE(_type, _statement) \
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
@ -47,7 +48,64 @@ const int32_t nsAnnotationService::kAnnoIndex_Type = 7;
const int32_t nsAnnotationService::kAnnoIndex_DateAdded = 8; const int32_t nsAnnotationService::kAnnoIndex_DateAdded = 8;
const int32_t nsAnnotationService::kAnnoIndex_LastModified = 9; const int32_t nsAnnotationService::kAnnoIndex_LastModified = 9;
using namespace mozilla::places; namespace mozilla {
namespace places {
////////////////////////////////////////////////////////////////////////////////
//// AnnotatedResult
AnnotatedResult::AnnotatedResult(const nsCString& aGUID,
nsIURI* aURI,
int64_t aItemId,
const nsACString& aAnnotationName,
nsIVariant* aAnnotationValue)
: mGUID(aGUID)
, mURI(aURI)
, mItemId(aItemId)
, mAnnotationName(aAnnotationName)
, mAnnotationValue(aAnnotationValue)
{
}
NS_IMETHODIMP
AnnotatedResult::GetGuid(nsACString& _guid)
{
_guid = mGUID;
return NS_OK;
}
NS_IMETHODIMP
AnnotatedResult::GetUri(nsIURI** _uri)
{
NS_IF_ADDREF(*_uri = mURI);
return NS_OK;
}
NS_IMETHODIMP
AnnotatedResult::GetItemId(int64_t* _itemId)
{
*_itemId = mItemId;
return NS_OK;
}
NS_IMETHODIMP
AnnotatedResult::GetAnnotationName(nsACString& _annotationName)
{
_annotationName = mAnnotationName;
return NS_OK;
}
NS_IMETHODIMP
AnnotatedResult::GetAnnotationValue(nsIVariant** _annotationValue)
{
NS_IF_ADDREF(*_annotationValue = mAnnotationValue);
return NS_OK;
}
NS_IMPL_ISUPPORTS1(AnnotatedResult, mozIAnnotatedResult)
} // namespace places
} // namespace mozilla
PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsAnnotationService, gAnnotationService) PLACES_FACTORY_SINGLETON_IMPLEMENTATION(nsAnnotationService, gAnnotationService)
@ -1163,6 +1221,111 @@ nsAnnotationService::GetItemsWithAnnotation(const nsACString& aName,
} }
NS_IMETHODIMP
nsAnnotationService::GetAnnotationsWithName(const nsACString& aName,
uint32_t* _count,
mozIAnnotatedResult*** _annotations)
{
NS_ENSURE_ARG(!aName.IsEmpty());
NS_ENSURE_ARG_POINTER(_annotations);
*_count = 0;
*_annotations = nullptr;
nsCOMArray<mozIAnnotatedResult> annotations;
nsCOMPtr<mozIStorageStatement> stmt = mDB->GetStatement(
"SELECT h.guid, h.url, -1, a.type, a.content "
"FROM moz_anno_attributes n "
"JOIN moz_annos a ON n.id = a.anno_attribute_id "
"JOIN moz_places h ON h.id = a.place_id "
"WHERE n.name = :anno_name "
"UNION ALL "
"SELECT b.guid, h.url, b.id, a.type, a.content "
"FROM moz_anno_attributes n "
"JOIN moz_items_annos a ON n.id = a.anno_attribute_id "
"JOIN moz_bookmarks b ON b.id = a.item_id "
"LEFT JOIN moz_places h ON h.id = b.fk "
"WHERE n.name = :anno_name "
);
NS_ENSURE_STATE(stmt);
mozStorageStatementScoper scoper(stmt);
nsresult rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("anno_name"),
aName);
NS_ENSURE_SUCCESS(rv, rv);
bool hasMore = false;
while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&hasMore)) && hasMore) {
nsAutoCString guid;
rv = stmt->GetUTF8String(0, guid);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIURI> uri;
bool uriIsNull = false;
rv = stmt->GetIsNull(1, &uriIsNull);
NS_ENSURE_SUCCESS(rv, rv);
if (!uriIsNull) {
nsAutoCString url;
rv = stmt->GetUTF8String(1, url);
NS_ENSURE_SUCCESS(rv, rv);
rv = NS_NewURI(getter_AddRefs(uri), url);
NS_ENSURE_SUCCESS(rv, rv);
}
int64_t itemId = stmt->AsInt64(2);
int32_t type = stmt->AsInt32(3);
nsCOMPtr<nsIWritableVariant> variant = new nsVariant();
switch (type) {
case nsIAnnotationService::TYPE_INT32: {
rv = variant->SetAsInt32(stmt->AsInt32(4));
break;
}
case nsIAnnotationService::TYPE_INT64: {
rv = variant->SetAsInt64(stmt->AsInt64(4));
break;
}
case nsIAnnotationService::TYPE_DOUBLE: {
rv = variant->SetAsDouble(stmt->AsDouble(4));
break;
}
case nsIAnnotationService::TYPE_STRING: {
nsAutoString valueString;
rv = stmt->GetString(4, valueString);
NS_ENSURE_SUCCESS(rv, rv);
rv = variant->SetAsAString(valueString);
break;
}
default:
MOZ_ASSERT("Unsupported annotation type");
// Move to the next result.
continue;
}
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIAnnotatedResult> anno = new AnnotatedResult(guid, uri, itemId,
aName, variant);
NS_ENSURE_TRUE(annotations.AppendObject(anno), NS_ERROR_OUT_OF_MEMORY);
}
// Convert to raw array.
if (annotations.Count() == 0)
return NS_OK;
*_annotations = static_cast<mozIAnnotatedResult**>
(nsMemory::Alloc(annotations.Count() * sizeof(mozIAnnotatedResult*)));
NS_ENSURE_TRUE(*_annotations, NS_ERROR_OUT_OF_MEMORY);
*_count = annotations.Count();
for (uint32_t i = 0; i < *_count; ++i) {
NS_ADDREF((*_annotations)[i] = annotations[i]);
}
return NS_OK;
}
nsresult nsresult
nsAnnotationService::GetItemsWithAnnotationTArray(const nsACString& aName, nsAnnotationService::GetItemsWithAnnotationTArray(const nsACString& aName,
nsTArray<int64_t>* _results) nsTArray<int64_t>* _results)

View File

@ -17,6 +17,30 @@
#include "nsString.h" #include "nsString.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
namespace mozilla {
namespace places {
class AnnotatedResult MOZ_FINAL : public mozIAnnotatedResult
{
public:
NS_DECL_ISUPPORTS
NS_DECL_MOZIANNOTATEDRESULT
AnnotatedResult(const nsCString& aGUID, nsIURI* aURI, int64_t aItemd,
const nsACString& aAnnotationName,
nsIVariant* aAnnotationValue);
private:
const nsCString mGUID;
nsCOMPtr<nsIURI> mURI;
const int64_t mItemId;
const nsCString mAnnotationName;
nsCOMPtr<nsIVariant> mAnnotationValue;
};
} // namespace places
} // namespace mozilla
class nsAnnotationService MOZ_FINAL : public nsIAnnotationService class nsAnnotationService MOZ_FINAL : public nsIAnnotationService
, public nsIObserver , public nsIObserver
, public nsSupportsWeakReference , public nsSupportsWeakReference

View File

@ -7,6 +7,7 @@
interface nsIURI; interface nsIURI;
interface nsIVariant; interface nsIVariant;
interface mozIAnnotatedResult;
[scriptable, uuid(63fe98e0-6889-4c2c-ac9f-703e4bc25027)] [scriptable, uuid(63fe98e0-6889-4c2c-ac9f-703e4bc25027)]
interface nsIAnnotationObserver : nsISupports interface nsIAnnotationObserver : nsISupports
@ -31,7 +32,7 @@ interface nsIAnnotationObserver : nsISupports
in AUTF8String aName); in AUTF8String aName);
}; };
[scriptable, uuid(ba249b58-346f-42a9-a393-203ae34ec6c4)] [scriptable, uuid(c7f425cc-a063-49ef-9f4c-b08eb2f1730a)]
interface nsIAnnotationService : nsISupports interface nsIAnnotationService : nsISupports
{ {
/** /**
@ -324,6 +325,19 @@ interface nsIAnnotationService : nsISupports
[optional] out unsigned long resultCount, [optional] out unsigned long resultCount,
[retval, array, size_is(resultCount)] out long long results); [retval, array, size_is(resultCount)] out long long results);
/**
* Returns a list of mozIAnnotation(s), having a given annotation name.
*
* @param name
* The annotation to search for.
* @return list of mozIAnnotation objects.
* @note binary annotations are not supported and thus skipped.
*/
void getAnnotationsWithName(
in AUTF8String name,
[optional] out unsigned long count,
[retval, array, size_is(count)] out mozIAnnotatedResult results);
/** /**
* Get the names of all annotations for this URI. * Get the names of all annotations for this URI.
* *
@ -402,3 +416,44 @@ interface nsIAnnotationService : nsISupports
nsIURI getAnnotationURI(in nsIURI aURI, nsIURI getAnnotationURI(in nsIURI aURI,
in AUTF8String aName); in AUTF8String aName);
}; };
/**
* Represents a place annotated with a given annotation. If a place has
* multiple annotations, it can be represented by multiple
* mozIAnnotatedResult(s).
*/
[scriptable, uuid(81fd0188-db6a-492e-80b6-f6414913b396)]
interface mozIAnnotatedResult : nsISupports
{
/**
* The globally unique identifier of the place with this annotation.
*
* @note if itemId is valid this is the guid of the bookmark, otherwise
* of the page.
*/
readonly attribute AUTF8String guid;
/**
* The URI of the place with this annotation, if available, null otherwise.
*/
readonly attribute nsIURI uri;
/**
* The bookmark id of the place with this annotation, if available,
* -1 otherwise.
*
* @note if itemId is -1, it doesn't mean the page is not bookmarked, just
* that this annotation is relative to the page, not to the bookmark.
*/
readonly attribute long long itemId;
/**
* Name of the annotation.
*/
readonly attribute AUTF8String annotationName;
/**
* Value of the annotation.
*/
readonly attribute nsIVariant annotationValue;
};

View File

@ -357,3 +357,57 @@ add_task(function test_execute()
annosvc.removeObserver(annoObserver); annosvc.removeObserver(annoObserver);
}); });
add_test(function test_getAnnotationsHavingName() {
let uri = NetUtil.newURI("http://cat.mozilla.org");
let id = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.unfiledBookmarksFolderId, uri,
PlacesUtils.bookmarks.DEFAULT_INDEX, "cat");
let fid = PlacesUtils.bookmarks.createFolder(
PlacesUtils.unfiledBookmarksFolderId, "pillow",
PlacesUtils.bookmarks.DEFAULT_INDEX);
const ANNOS = {
"int": 7,
"double": 7.7,
"string": "seven"
};
for (let name in ANNOS) {
PlacesUtils.annotations.setPageAnnotation(
uri, name, ANNOS[name], 0,
PlacesUtils.annotations.EXPIRE_SESSION);
PlacesUtils.annotations.setItemAnnotation(
id, name, ANNOS[name], 0,
PlacesUtils.annotations.EXPIRE_SESSION);
PlacesUtils.annotations.setItemAnnotation(
fid, name, ANNOS[name], 0,
PlacesUtils.annotations.EXPIRE_SESSION);
}
for (let name in ANNOS) {
let results = PlacesUtils.annotations.getAnnotationsWithName(name);
do_check_eq(results.length, 3);
for (let result of results) {
do_check_eq(result.annotationName, name);
do_check_eq(result.annotationValue, ANNOS[name]);
if (result.uri)
do_check_true(result.uri.equals(uri));
else
do_check_true(result.itemId > 0);
if (result.itemId != -1) {
if (result.uri)
do_check_eq(result.itemId, id);
else
do_check_eq(result.itemId, fid);
do_check_guid_for_bookmark(result.itemId, result.guid);
}
else {
do_check_guid_for_uri(result.uri, result.guid);
}
}
}
run_next_test();
});