forked from mirrors/gecko-dev
		
	Bug 822710 (part 1) - Implement a new getAnnotationsHavingName method.
r=Mano sr=gavin
This commit is contained in:
		
							parent
							
								
									2995d3615f
								
							
						
					
					
						commit
						17cc116f68
					
				
					 4 changed files with 298 additions and 2 deletions
				
			
		|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | @ -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(); | ||||||
|  | }); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Marco Bonardo
						Marco Bonardo