1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef nsNavBookmarks_h_ 7 #define nsNavBookmarks_h_ 8 9 #include "nsINavBookmarksService.h" 10 #include "nsNavHistory.h" 11 #include "nsToolkitCompsCID.h" 12 #include "nsCategoryCache.h" 13 #include "nsTHashtable.h" 14 #include "nsWeakReference.h" 15 #include "mozilla/Attributes.h" 16 #include "prtime.h" 17 18 class nsNavBookmarks; 19 20 namespace mozilla { 21 namespace places { 22 23 enum BookmarkStatementId { 24 DB_FIND_REDIRECTED_BOOKMARK = 0, 25 DB_GET_BOOKMARKS_FOR_URI 26 }; 27 28 struct BookmarkData { 29 int64_t id = -1; 30 nsCString url; 31 nsCString title; 32 int32_t position = -1; 33 int64_t placeId = -1; 34 int64_t parentId = -1; 35 int64_t grandParentId = -1; 36 int32_t type = 0; 37 int32_t syncStatus = nsINavBookmarksService::SYNC_STATUS_UNKNOWN; 38 nsCString serviceCID; 39 PRTime dateAdded = 0; 40 PRTime lastModified = 0; 41 nsCString guid; 42 nsCString parentGuid; 43 }; 44 45 struct ItemVisitData { 46 BookmarkData bookmark; 47 int64_t visitId; 48 uint32_t transitionType; 49 PRTime time; 50 }; 51 52 struct ItemChangeData { 53 BookmarkData bookmark; 54 bool isAnnotation = false; 55 bool updateLastModified = false; 56 uint16_t source = nsINavBookmarksService::SOURCE_DEFAULT; 57 nsCString property; 58 nsCString newValue; 59 nsCString oldValue; 60 }; 61 62 struct TombstoneData { 63 nsCString guid; 64 PRTime dateRemoved; 65 }; 66 67 typedef void (nsNavBookmarks::*ItemVisitMethod)(const ItemVisitData&); 68 typedef void (nsNavBookmarks::*ItemChangeMethod)(const ItemChangeData&); 69 70 enum BookmarkDate { LAST_MODIFIED }; 71 72 } // namespace places 73 } // namespace mozilla 74 75 class nsNavBookmarks final : public nsINavBookmarksService, 76 public nsINavHistoryObserver, 77 public nsIObserver, 78 public nsSupportsWeakReference { 79 public: 80 NS_DECL_ISUPPORTS 81 NS_DECL_NSINAVBOOKMARKSSERVICE 82 NS_DECL_NSINAVHISTORYOBSERVER 83 NS_DECL_NSIOBSERVER 84 85 nsNavBookmarks(); 86 87 /** 88 * Obtains the service's object. 89 */ 90 static already_AddRefed<nsNavBookmarks> GetSingleton(); 91 92 /** 93 * Initializes the service's object. This should only be called once. 94 */ 95 nsresult Init(); 96 GetBookmarksService()97 static nsNavBookmarks* GetBookmarksService() { 98 if (!gBookmarksService) { 99 nsCOMPtr<nsINavBookmarksService> serv = 100 do_GetService(NS_NAVBOOKMARKSSERVICE_CONTRACTID); 101 NS_ENSURE_TRUE(serv, nullptr); 102 NS_ASSERTION(gBookmarksService, 103 "Should have static instance pointer now"); 104 } 105 return gBookmarksService; 106 } 107 108 typedef mozilla::places::BookmarkData BookmarkData; 109 typedef mozilla::places::ItemVisitData ItemVisitData; 110 typedef mozilla::places::ItemChangeData ItemChangeData; 111 typedef mozilla::places::BookmarkStatementId BookmarkStatementId; 112 113 nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime, 114 int64_t aSessionId, int64_t aReferringId, 115 uint32_t aTransitionType, const nsACString& aGUID, 116 bool aHidden, uint32_t aVisitCount, uint32_t aTyped, 117 const nsAString& aLastKnownTitle); 118 119 nsresult ResultNodeForContainer(int64_t aID, 120 nsNavHistoryQueryOptions* aOptions, 121 nsNavHistoryResultNode** aNode); 122 123 // Find all the children of a folder, using the given query and options. 124 // For each child, a ResultNode is created and added to |children|. 125 // The results are ordered by folder position. 126 nsresult QueryFolderChildren(int64_t aFolderId, 127 nsNavHistoryQueryOptions* aOptions, 128 nsCOMArray<nsNavHistoryResultNode>* children); 129 130 /** 131 * Turns aRow into a node and appends it to aChildren if it is appropriate to 132 * do so. 133 * 134 * @param aRow 135 * A Storage statement (in the case of synchronous execution) or row of 136 * a result set (in the case of asynchronous execution). 137 * @param aOptions 138 * The options of the parent folder node. These are the options used 139 * to fill the parent node. 140 * @param aChildren 141 * The children of the parent folder node. 142 * @param aCurrentIndex 143 * The index of aRow within the results. When called on the first row, 144 * this should be set to -1. 145 */ 146 nsresult ProcessFolderNodeRow(mozIStorageValueArray* aRow, 147 nsNavHistoryQueryOptions* aOptions, 148 nsCOMArray<nsNavHistoryResultNode>* aChildren, 149 int32_t& aCurrentIndex); 150 151 /** 152 * The async version of QueryFolderChildren. 153 * 154 * @param aNode 155 * The folder node that will receive the children. 156 * @param _pendingStmt 157 * The Storage pending statement that will be used to control async 158 * execution. 159 */ 160 nsresult QueryFolderChildrenAsync(nsNavHistoryFolderResultNode* aNode, 161 mozIStoragePendingStatement** _pendingStmt); 162 163 /** 164 * Fetches information about the specified id from the database. 165 * 166 * @param aItemId 167 * Id of the item to fetch information for. 168 * @param aBookmark 169 * BookmarkData to store the information. 170 */ 171 nsresult FetchItemInfo(int64_t aItemId, BookmarkData& _bookmark); 172 173 /** 174 * Notifies that a bookmark has been visited. 175 * 176 * @param aItemId 177 * The visited item id. 178 * @param aData 179 * Details about the new visit. 180 */ 181 void NotifyItemVisited(const ItemVisitData& aData); 182 183 /** 184 * Notifies that a bookmark has changed. 185 * 186 * @param aItemId 187 * The changed item id. 188 * @param aData 189 * Details about the change. 190 */ 191 void NotifyItemChanged(const ItemChangeData& aData); 192 193 /** 194 * Recursively builds an array of descendant folders inside a given folder. 195 * 196 * @param aFolderId 197 * The folder to fetch descendants from. 198 * @param aDescendantFoldersArray 199 * Output array to put descendant folders id. 200 */ 201 nsresult GetDescendantFolders(int64_t aFolderId, 202 nsTArray<int64_t>& aDescendantFoldersArray); 203 204 static const int32_t kGetChildrenIndex_Guid; 205 static const int32_t kGetChildrenIndex_Position; 206 static const int32_t kGetChildrenIndex_Type; 207 static const int32_t kGetChildrenIndex_PlaceID; 208 static const int32_t kGetChildrenIndex_SyncStatus; 209 210 static mozilla::Atomic<int64_t> sLastInsertedItemId; 211 static void StoreLastInsertedId(const nsACString& aTable, 212 const int64_t aLastInsertedId); 213 214 private: 215 static nsNavBookmarks* gBookmarksService; 216 217 ~nsNavBookmarks(); 218 219 /** 220 * Checks whether or not aFolderId points to a live bookmark. 221 * 222 * @param aFolderId 223 * the item-id of the folder to check. 224 * @return true if aFolderId points to live bookmarks, false otherwise. 225 */ 226 bool IsLivemark(int64_t aFolderId); 227 228 /** 229 * Locates the root items in the bookmarks folder hierarchy assigning folder 230 * ids to the root properties that are exposed through the service interface. 231 */ 232 nsresult EnsureRoots(); 233 234 nsresult AdjustIndices(int64_t aFolder, int32_t aStartIndex, 235 int32_t aEndIndex, int32_t aDelta); 236 237 nsresult AdjustSeparatorsSyncCounter(int64_t aFolderId, int32_t aStartIndex, 238 int64_t aSyncChangeDelta); 239 240 /** 241 * Fetches properties of a folder. 242 * 243 * @param aFolderId 244 * Folder to count children for. 245 * @param _folderCount 246 * Number of children in the folder. 247 * @param _guid 248 * Unique id of the folder. 249 * @param _parentId 250 * Id of the parent of the folder. 251 * 252 * @throws If folder does not exist. 253 */ 254 nsresult FetchFolderInfo(int64_t aFolderId, int32_t* _folderCount, 255 nsACString& _guid, int64_t* _parentId); 256 257 nsresult AddSyncChangesForBookmarksWithURL(const nsACString& aURL, 258 int64_t aSyncChangeDelta); 259 260 // Bumps the change counter for all bookmarks with |aURI|. This is used to 261 // update tagged bookmarks when adding or changing a tag entry. 262 nsresult AddSyncChangesForBookmarksWithURI(nsIURI* aURI, 263 int64_t aSyncChangeDelta); 264 265 // Bumps the change counter for all bookmarked URLs within |aFolderId|. This 266 // is used to update tagged bookmarks when changing or removing a tag folder. 267 nsresult AddSyncChangesForBookmarksInFolder(int64_t aFolderId, 268 int64_t aSyncChangeDelta); 269 270 // Inserts a tombstone for a removed synced item. 271 nsresult InsertTombstone(const BookmarkData& aBookmark); 272 273 // Inserts tombstones for removed synced items. 274 nsresult InsertTombstones(const nsTArray<TombstoneData>& aTombstones); 275 276 // Removes a stale synced bookmark tombstone. 277 nsresult RemoveTombstone(const nsACString& aGUID); 278 279 nsresult SetItemTitleInternal(BookmarkData& aBookmark, 280 const nsACString& aTitle, 281 int64_t aSyncChangeDelta); 282 283 /** 284 * This is an handle to the Places database. 285 */ 286 RefPtr<mozilla::places::Database> mDB; 287 288 nsMaybeWeakPtrArray<nsINavBookmarkObserver> mObservers; 289 TagsRootId()290 int64_t TagsRootId() { 291 nsresult rv = EnsureRoots(); 292 NS_ENSURE_SUCCESS(rv, -1); 293 return mTagsRoot; 294 } 295 296 // These are lazy loaded, so never access them directly, always use the 297 // XPIDL getters or TagsRootId(). 298 int64_t mRoot; 299 int64_t mMenuRoot; 300 int64_t mTagsRoot; 301 int64_t mUnfiledRoot; 302 int64_t mToolbarRoot; 303 int64_t mMobileRoot; 304 IsRoot(int64_t aFolderId)305 inline bool IsRoot(int64_t aFolderId) { 306 return aFolderId == mRoot || aFolderId == mMenuRoot || 307 aFolderId == mTagsRoot || aFolderId == mUnfiledRoot || 308 aFolderId == mToolbarRoot || aFolderId == mMobileRoot; 309 } 310 311 nsresult SetItemDateInternal(enum mozilla::places::BookmarkDate aDateType, 312 int64_t aSyncChangeDelta, int64_t aItemId, 313 PRTime aValue); 314 315 nsresult RemoveFolderChildren(int64_t aFolderId, uint16_t aSource); 316 317 // Recursive method to build an array of folder's children 318 nsresult GetDescendantChildren(int64_t aFolderId, 319 const nsACString& aFolderGuid, 320 int64_t aGrandParentId, 321 nsTArray<BookmarkData>& aFolderChildrenArray); 322 323 enum ItemType { 324 BOOKMARK = TYPE_BOOKMARK, 325 FOLDER = TYPE_FOLDER, 326 SEPARATOR = TYPE_SEPARATOR, 327 }; 328 329 /** 330 * Helper to insert a bookmark in the database. 331 * 332 * @param aItemId 333 * The itemId to insert, pass -1 to generate a new one. 334 * @param aPlaceId 335 * The placeId to which this bookmark refers to, pass nullptr for 336 * items that don't refer to an URI (eg. folders, separators, ...). 337 * @param aItemType 338 * The type of the new bookmark, see TYPE_* constants. 339 * @param aParentId 340 * The itemId of the parent folder. 341 * @param aIndex 342 * The position inside the parent folder. 343 * @param aTitle 344 * The title for the new bookmark. 345 * Pass a void string to set a NULL title. 346 * @param aDateAdded 347 * The date for the insertion. 348 * @param [optional] aLastModified 349 * The last modified date for the insertion. 350 * It defaults to aDateAdded. 351 * 352 * @return The new item id that has been inserted. 353 * 354 * @note This will also update last modified date of the parent folder. 355 */ 356 nsresult InsertBookmarkInDB(int64_t aPlaceId, enum ItemType aItemType, 357 int64_t aParentId, int32_t aIndex, 358 const nsACString& aTitle, PRTime aDateAdded, 359 PRTime aLastModified, 360 const nsACString& aParentGuid, 361 int64_t aGrandParentId, nsIURI* aURI, 362 uint16_t aSource, int64_t* _itemId, 363 nsACString& _guid); 364 365 nsresult GetBookmarksForURI(nsIURI* aURI, nsTArray<BookmarkData>& _bookmarks); 366 367 // Used to enable and disable the observer notifications. 368 bool mCanNotify; 369 370 // Tracks whether we are in batch mode. 371 // Note: this is only tracking bookmarks batches, not history ones. 372 bool mBatching; 373 }; 374 375 #endif // nsNavBookmarks_h_ 376