Bug 1900094 - Add telemetry for impressions missing due to domain-to-categories map...
[gecko.git] / toolkit / components / places / nsNavHistoryResult.h
bloba61bc8db2402ea8801ca5875926e9c743b076e37
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/. */
6 /**
7 * The definitions of objects that make up a history query result set. This file
8 * should only be included by nsNavHistory.h, include that if you want these
9 * classes.
12 #ifndef nsNavHistoryResult_h_
13 #define nsNavHistoryResult_h_
15 #include "INativePlacesEventCallback.h"
16 #include "nsCOMArray.h"
17 #include "nsTArray.h"
18 #include "nsMaybeWeakPtr.h"
19 #include "nsInterfaceHashtable.h"
20 #include "nsINavHistoryService.h"
21 #include "nsTHashMap.h"
22 #include "nsCycleCollectionParticipant.h"
23 #include "mozIStoragePendingStatement.h"
24 #include "Helpers.h"
26 class nsNavHistory;
27 class nsNavHistoryQuery;
28 class nsNavHistoryQueryOptions;
30 class nsNavHistoryContainerResultNode;
31 class nsNavHistoryFolderResultNode;
32 class nsNavHistoryQueryResultNode;
34 /**
35 * hashkey wrapper using int64_t KeyType
37 * @see nsTHashtable::EntryType for specification
39 * This just truncates the 64-bit int to a 32-bit one for using a hash number.
40 * It is used for bookmark folder IDs, which should be way less than 2^32.
42 class nsTrimInt64HashKey : public PLDHashEntryHdr {
43 public:
44 using KeyType = const int64_t&;
45 using KeyTypePointer = const int64_t*;
47 explicit nsTrimInt64HashKey(KeyTypePointer aKey) : mValue(*aKey) {}
48 nsTrimInt64HashKey(const nsTrimInt64HashKey& toCopy)
49 : mValue(toCopy.mValue) {}
50 ~nsTrimInt64HashKey() = default;
52 KeyType GetKey() const { return mValue; }
53 bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
55 static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
56 static PLDHashNumber HashKey(KeyTypePointer aKey) {
57 return static_cast<uint32_t>((*aKey) & UINT32_MAX);
59 enum { ALLOW_MEMMOVE = true };
61 private:
62 const int64_t mValue;
65 // nsNavHistoryResult
67 // nsNavHistory creates this object and fills in mChildren (by getting
68 // it through GetTopLevel()). Then FilledAllResults() is called to finish
69 // object initialization.
71 #define NS_NAVHISTORYRESULT_IID \
72 { \
73 0x455d1d40, 0x1b9b, 0x40e6, { \
74 0xa6, 0x41, 0x8b, 0xb7, 0xe8, 0x82, 0x23, 0x87 \
75 } \
78 class nsNavHistoryResult final
79 : public nsSupportsWeakReference,
80 public nsINavHistoryResult,
81 public mozilla::places::INativePlacesEventCallback {
82 public:
83 NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID)
85 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
86 NS_DECL_NSINAVHISTORYRESULT
87 NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNavHistoryResult,
88 nsINavHistoryResult)
90 void AddHistoryObserver(nsNavHistoryQueryResultNode* aNode);
91 void AddBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode,
92 const nsACString& aFolderGUID);
93 void AddAllBookmarksObserver(nsNavHistoryQueryResultNode* aNode);
94 void AddMobilePrefsObserver(nsNavHistoryQueryResultNode* aNode);
95 void RemoveHistoryObserver(nsNavHistoryQueryResultNode* aNode);
96 void RemoveBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode,
97 const nsACString& aFolderGUID);
98 void RemoveAllBookmarksObserver(nsNavHistoryQueryResultNode* aNode);
99 void RemoveMobilePrefsObserver(nsNavHistoryQueryResultNode* aNode);
100 void StopObserving();
101 void EnsureIsObservingBookmarks();
103 nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
104 uint32_t aTransitionType, const nsACString& aGUID,
105 bool aHidden, uint32_t aVisitCount,
106 const nsAString& aLastKnownTitle, int64_t aFrecency);
108 void OnIconChanged(nsIURI* aURI, nsIURI* aFaviconURI,
109 const nsACString& aGUID);
111 explicit nsNavHistoryResult(nsNavHistoryContainerResultNode* aRoot,
112 const RefPtr<nsNavHistoryQuery>& aQuery,
113 const RefPtr<nsNavHistoryQueryOptions>& aOptions);
115 RefPtr<nsNavHistoryContainerResultNode> mRootNode;
117 RefPtr<nsNavHistoryQuery> mQuery;
118 RefPtr<nsNavHistoryQueryOptions> mOptions;
120 // One of nsNavHistoryQueryOptions.SORY_BY_* This is initialized to
121 // mOptions.sortingMode, but may be overridden if the user clicks on one of
122 // the columns.
123 uint16_t mSortingMode;
124 // If root node is closed and we try to apply a sortingMode, it would not
125 // work. So we will apply it when the node will be reopened and populated.
126 // This var states the fact we need to apply sortingMode in such a situation.
127 bool mNeedsToApplySortingMode;
129 // node observers
130 bool mIsHistoryObserver;
131 bool mIsBookmarksObserver;
132 bool mIsMobilePrefObserver;
134 using QueryObserverList = nsTArray<RefPtr<nsNavHistoryQueryResultNode>>;
135 QueryObserverList mHistoryObservers;
136 QueryObserverList mAllBookmarksObservers;
137 QueryObserverList mMobilePrefObservers;
139 using FolderObserverList = nsTArray<RefPtr<nsNavHistoryFolderResultNode>>;
140 nsTHashMap<nsCStringHashKey, FolderObserverList*> mBookmarkFolderObservers;
141 FolderObserverList* BookmarkFolderObserversForGUID(
142 const nsACString& aFolderGUID, bool aCreate);
144 using ContainerObserverList =
145 nsTArray<RefPtr<nsNavHistoryContainerResultNode>>;
147 void RecursiveExpandCollapse(nsNavHistoryContainerResultNode* aContainer,
148 bool aExpand);
150 void InvalidateTree();
152 nsMaybeWeakPtrArray<nsINavHistoryResultObserver> mObservers;
153 bool mSuppressNotifications;
155 // Tracks whether observers for history details were added.
156 bool mIsHistoryDetailsObserver;
157 // Tracks whether any result observer is interested in history details
158 // updates.
159 bool mObserversWantHistoryDetails;
161 * Updates mObserversWantHistoryDetails when observers are added/removed.
162 * @returns Whether we started observing for history changes.
164 bool UpdateHistoryDetailsObservers();
165 // Whether NodeHistoryDetailsChanged can be skipped.
166 bool CanSkipHistoryDetailsNotifications() const;
168 ContainerObserverList mRefreshParticipants;
169 void requestRefresh(nsNavHistoryContainerResultNode* aContainer);
171 void HandlePlacesEvent(const PlacesEventSequence& aEvents) override;
173 // Optimisation: refreshing containers is much faster than incremental
174 // updates when handling multiple Page_removed events.
175 bool IsBulkPageRemovedEvent(const PlacesEventSequence& aEvents);
177 void OnMobilePrefChanged();
179 bool IsBatching() const { return mBatchInProgress > 0; };
181 static void OnMobilePrefChangedCallback(const char* prefName, void* self);
183 protected:
184 virtual ~nsNavHistoryResult();
186 private:
187 // Number of batch processes currently running. IsBatching() returns true if
188 // this value is greater than or equal to 1. Also, when this value changes to
189 // 1 from 0, batching() in nsINavHistoryResultObserver is called with
190 // parameter as true, when changes to 0, that means finishing all batch
191 // processes, batching() is called with false.
192 uint32_t mBatchInProgress;
194 // Stop all observers upon unlinking.
195 void StopObservingOnUnlink();
198 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
200 // nsNavHistoryResultNode
202 // This is the base class for every node in a result set. The result itself
203 // is a node (nsNavHistoryResult inherits from this), as well as every
204 // leaf and branch on the tree.
206 #define NS_NAVHISTORYRESULTNODE_IID \
208 0x54b61d38, 0x57c1, 0x11da, { \
209 0x95, 0xb8, 0x00, 0x13, 0x21, 0xc9, 0xf6, 0x9e \
213 // These are all the simple getters, they can be used for the result node
214 // implementation and all subclasses. More complex are GetIcon, GetParent
215 // (which depends on the definition of container result node), and GetUri
216 // (which is overridded for lazy construction for some containers).
217 #define NS_IMPLEMENT_SIMPLE_RESULTNODE \
218 NS_IMETHOD GetTitle(nsACString& aTitle) override { \
219 aTitle = mTitle; \
220 return NS_OK; \
222 NS_IMETHOD GetAccessCount(uint32_t* aAccessCount) override { \
223 *aAccessCount = mAccessCount; \
224 return NS_OK; \
226 NS_IMETHOD GetTime(PRTime* aTime) override { \
227 *aTime = mTime; \
228 return NS_OK; \
230 NS_IMETHOD GetIndentLevel(int32_t* aIndentLevel) override { \
231 *aIndentLevel = mIndentLevel; \
232 return NS_OK; \
234 NS_IMETHOD GetBookmarkIndex(int32_t* aIndex) override { \
235 *aIndex = mBookmarkIndex; \
236 return NS_OK; \
238 NS_IMETHOD GetDateAdded(PRTime* aDateAdded) override { \
239 *aDateAdded = mDateAdded; \
240 return NS_OK; \
242 NS_IMETHOD GetLastModified(PRTime* aLastModified) override { \
243 *aLastModified = mLastModified; \
244 return NS_OK; \
246 NS_IMETHOD GetItemId(int64_t* aId) override { \
247 *aId = mItemId; \
248 return NS_OK; \
251 // This is used by the base classes instead of
252 // NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryResultNode) because they
253 // need to redefine GetType and GetUri rather than forwarding them. This
254 // implements all the simple getters instead of forwarding because they are so
255 // short and we can save a virtual function call.
257 // (GetUri is redefined only by QueryResultNode and FolderResultNode because
258 // the query might not necessarily be parsed. The rest just return the node's
259 // buffer.)
260 #define NS_FORWARD_COMMON_RESULTNODE_TO_BASE \
261 NS_IMPLEMENT_SIMPLE_RESULTNODE \
262 NS_IMETHOD GetIcon(nsACString& aIcon) override { \
263 return nsNavHistoryResultNode::GetIcon(aIcon); \
265 NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) override { \
266 return nsNavHistoryResultNode::GetParent(aParent); \
268 NS_IMETHOD GetParentResult(nsINavHistoryResult** aResult) override { \
269 return nsNavHistoryResultNode::GetParentResult(aResult); \
271 NS_IMETHOD GetTags(nsAString& aTags) override { \
272 return nsNavHistoryResultNode::GetTags(aTags); \
274 NS_IMETHOD GetPageGuid(nsACString& aPageGuid) override { \
275 return nsNavHistoryResultNode::GetPageGuid(aPageGuid); \
277 NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) override { \
278 return nsNavHistoryResultNode::GetBookmarkGuid(aBookmarkGuid); \
280 NS_IMETHOD GetVisitId(int64_t* aVisitId) override { \
281 return nsNavHistoryResultNode::GetVisitId(aVisitId); \
283 NS_IMETHOD GetVisitType(uint32_t* aVisitType) override { \
284 return nsNavHistoryResultNode::GetVisitType(aVisitType); \
287 class nsNavHistoryResultNode : public nsINavHistoryResultNode {
288 public:
289 nsNavHistoryResultNode(const nsACString& aURI, const nsACString& aTitle,
290 uint32_t aAccessCount, PRTime aTime);
292 NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULTNODE_IID)
294 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
295 NS_DECL_CYCLE_COLLECTION_CLASS(nsNavHistoryResultNode)
297 NS_IMPLEMENT_SIMPLE_RESULTNODE
298 NS_IMETHOD GetIcon(nsACString& aIcon) override;
299 NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) override;
300 NS_IMETHOD GetParentResult(nsINavHistoryResult** aResult) override;
301 NS_IMETHOD GetType(uint32_t* type) override {
302 *type = nsNavHistoryResultNode::RESULT_TYPE_URI;
303 return NS_OK;
305 NS_IMETHOD GetUri(nsACString& aURI) override {
306 aURI = mURI;
307 return NS_OK;
309 NS_IMETHOD GetTags(nsAString& aTags) override;
310 NS_IMETHOD GetPageGuid(nsACString& aPageGuid) override;
311 NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) override;
312 NS_IMETHOD GetVisitId(int64_t* aVisitId) override;
313 NS_IMETHOD GetVisitType(uint32_t* aVisitType) override;
315 virtual void OnRemoving();
317 nsresult OnItemKeywordChanged(int64_t aItemId, const nsACString& aKeyword);
318 nsresult OnItemTagsChanged(int64_t aItemId, const nsAString& aURL,
319 const nsAString& aTags);
320 nsresult OnItemTimeChanged(int64_t aItemId, const nsACString& aGUID,
321 PRTime aDateAdded, PRTime aLastModified);
322 nsresult OnItemTitleChanged(int64_t aItemId, const nsACString& aGUID,
323 const nsACString& aTitle, PRTime aLastModified);
324 nsresult OnItemUrlChanged(int64_t aItemId, const nsACString& aGUID,
325 const nsACString& aURL, PRTime aLastModified);
327 virtual nsresult OnMobilePrefChanged(bool newValue) { return NS_OK; };
329 nsresult OnVisitsRemoved();
331 protected:
332 virtual ~nsNavHistoryResultNode() = default;
334 public:
335 nsNavHistoryResult* GetResult();
336 void SetTags(const nsAString& aTags);
338 bool IsContainer() {
339 uint32_t type;
340 GetType(&type);
341 return type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
342 type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
343 type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
346 bool IsURI() {
347 uint32_t type;
348 GetType(&type);
349 return type == nsINavHistoryResultNode::RESULT_TYPE_URI;
352 bool IsFolderOrShortcut() {
353 uint32_t type;
354 GetType(&type);
355 return type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
356 type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
359 bool IsQuery() {
360 uint32_t type;
361 GetType(&type);
362 return type == nsINavHistoryResultNode::RESULT_TYPE_QUERY;
365 bool IsSeparator() {
366 uint32_t type;
367 GetType(&type);
368 return type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR;
371 nsNavHistoryContainerResultNode* GetAsContainer() {
372 NS_ASSERTION(IsContainer(), "Not a container");
373 return reinterpret_cast<nsNavHistoryContainerResultNode*>(this);
375 nsNavHistoryFolderResultNode* GetAsFolder() {
376 NS_ASSERTION(IsFolderOrShortcut(), "Not a folder");
377 return reinterpret_cast<nsNavHistoryFolderResultNode*>(this);
379 nsNavHistoryQueryResultNode* GetAsQuery() {
380 NS_ASSERTION(IsQuery(), "Not a query");
381 return reinterpret_cast<nsNavHistoryQueryResultNode*>(this);
384 RefPtr<nsNavHistoryContainerResultNode> mParent;
385 nsCString mURI; // not necessarily valid for containers, call GetUri
386 nsCString mTitle;
387 nsString mTags;
388 uint32_t mAccessCount;
389 int64_t mTime;
390 int32_t mBookmarkIndex;
391 int64_t mItemId;
392 int64_t mVisitId;
393 PRTime mDateAdded;
394 PRTime mLastModified;
396 // The indent level of this node. The root node will have a value of -1. The
397 // root's children will have a value of 0, and so on.
398 int32_t mIndentLevel;
400 // Frecency of the page. Valid only for URI nodes.
401 int64_t mFrecency;
403 // Hidden status of the page. Valid only for URI nodes.
404 bool mHidden;
406 // Transition type used when this node represents a single visit.
407 uint32_t mTransitionType;
409 // Unique Id of the page.
410 nsCString mPageGuid;
412 // Unique Id of the bookmark.
413 nsCString mBookmarkGuid;
416 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode,
417 NS_NAVHISTORYRESULTNODE_IID)
419 // nsNavHistoryContainerResultNode
421 // This is the base class for all nodes that can have children. It is
422 // overridden for nodes that are dynamically populated such as queries and
423 // folders. It is used directly for simple containers such as host groups
424 // in history views.
426 // derived classes each provide their own implementation of has children and
427 // forward the rest to us using this macro
428 #define NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN \
429 NS_IMETHOD GetState(uint16_t* _state) override { \
430 return nsNavHistoryContainerResultNode::GetState(_state); \
432 NS_IMETHOD GetContainerOpen(bool* aContainerOpen) override { \
433 return nsNavHistoryContainerResultNode::GetContainerOpen(aContainerOpen); \
435 NS_IMETHOD SetContainerOpen(bool aContainerOpen) override { \
436 return nsNavHistoryContainerResultNode::SetContainerOpen(aContainerOpen); \
438 NS_IMETHOD GetChildCount(uint32_t* aChildCount) override { \
439 return nsNavHistoryContainerResultNode::GetChildCount(aChildCount); \
441 NS_IMETHOD GetChild(uint32_t index, nsINavHistoryResultNode** _retval) \
442 override { \
443 return nsNavHistoryContainerResultNode::GetChild(index, _retval); \
445 NS_IMETHOD GetChildIndex(nsINavHistoryResultNode* aNode, uint32_t* _retval) \
446 override { \
447 return nsNavHistoryContainerResultNode::GetChildIndex(aNode, _retval); \
450 #define NS_NAVHISTORYCONTAINERRESULTNODE_IID \
452 0x6e3bf8d3, 0x22aa, 0x4065, { \
453 0x86, 0xbc, 0x37, 0x46, 0xb5, 0xb3, 0x2c, 0xe8 \
457 class nsNavHistoryContainerResultNode
458 : public nsNavHistoryResultNode,
459 public nsINavHistoryContainerResultNode {
460 public:
461 nsNavHistoryContainerResultNode(const nsACString& aURI,
462 const nsACString& aTitle, PRTime aTime,
463 uint32_t aContainerType,
464 nsNavHistoryQueryOptions* aOptions);
466 virtual nsresult Refresh();
468 NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYCONTAINERRESULTNODE_IID)
470 NS_DECL_ISUPPORTS_INHERITED
471 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsNavHistoryContainerResultNode,
472 nsNavHistoryResultNode)
473 NS_FORWARD_COMMON_RESULTNODE_TO_BASE
474 NS_IMETHOD GetType(uint32_t* type) override {
475 *type = mContainerType;
476 return NS_OK;
478 NS_IMETHOD GetUri(nsACString& aURI) override {
479 aURI = mURI;
480 return NS_OK;
482 NS_DECL_NSINAVHISTORYCONTAINERRESULTNODE
484 public:
485 virtual void OnRemoving() override;
487 nsresult OnVisitsRemoved(nsIURI* aURI);
489 bool AreChildrenVisible();
491 // Overridded by descendents to populate.
492 virtual nsresult OpenContainer();
493 nsresult CloseContainer(bool aSuppressNotifications = false);
495 virtual nsresult OpenContainerAsync();
497 // This points to the result that owns this container. All containers have
498 // their result pointer set so we can quickly get to the result without having
499 // to walk the tree. Yet, this also saves us from storing a million pointers
500 // for every leaf node to the result.
501 RefPtr<nsNavHistoryResult> mResult;
503 // For example, RESULT_TYPE_QUERY. Query and Folder results override GetType
504 // so this is not used, but is still kept in sync.
505 uint32_t mContainerType;
507 // When there are children, this stores the open state in the tree
508 // this is set to the default in the constructor.
509 bool mExpanded;
511 // Filled in by the result type generator in nsNavHistory.
512 nsCOMArray<nsNavHistoryResultNode> mChildren;
514 // mOriginalOptions is the options object used to _define_ this specific
515 // container node. It may differ from mOptions, that is the options used
516 // to _fill_ this container node, because mOptions may be modified by
517 // the direct parent of this container node, see SetAsParentOfNode. For
518 // example, if the parent has excludeItems, options will have it too, even if
519 // originally this object was not defined with that option.
520 RefPtr<nsNavHistoryQueryOptions> mOriginalOptions;
521 RefPtr<nsNavHistoryQueryOptions> mOptions;
523 void FillStats();
524 // Sets this container as parent of aNode, propagating the appropriate
525 // options.
526 void SetAsParentOfNode(nsNavHistoryResultNode* aNode);
528 // Sorting methods.
529 using SortComparator = nsCOMArray<nsNavHistoryResultNode>::TComparatorFunc;
530 virtual uint16_t GetSortType();
532 static SortComparator GetSortingComparator(uint16_t aSortType);
533 virtual void RecursiveSort(SortComparator aComparator);
534 int32_t FindInsertionPoint(nsNavHistoryResultNode* aNode,
535 SortComparator aComparator, bool* aItemExists);
536 bool DoesChildNeedResorting(int32_t aIndex, SortComparator aComparator);
538 static int32_t SortComparison_StringLess(const nsAString& a,
539 const nsAString& b);
541 static int32_t SortComparison_Bookmark(nsNavHistoryResultNode* a,
542 nsNavHistoryResultNode* b);
543 static int32_t SortComparison_TitleLess(nsNavHistoryResultNode* a,
544 nsNavHistoryResultNode* b);
545 static int32_t SortComparison_TitleGreater(nsNavHistoryResultNode* a,
546 nsNavHistoryResultNode* b);
547 static int32_t SortComparison_DateLess(nsNavHistoryResultNode* a,
548 nsNavHistoryResultNode* b);
549 static int32_t SortComparison_DateGreater(nsNavHistoryResultNode* a,
550 nsNavHistoryResultNode* b);
551 static int32_t SortComparison_URILess(nsNavHistoryResultNode* a,
552 nsNavHistoryResultNode* b);
553 static int32_t SortComparison_URIGreater(nsNavHistoryResultNode* a,
554 nsNavHistoryResultNode* b);
555 static int32_t SortComparison_VisitCountLess(nsNavHistoryResultNode* a,
556 nsNavHistoryResultNode* b);
557 static int32_t SortComparison_VisitCountGreater(nsNavHistoryResultNode* a,
558 nsNavHistoryResultNode* b);
559 static int32_t SortComparison_DateAddedLess(nsNavHistoryResultNode* a,
560 nsNavHistoryResultNode* b);
561 static int32_t SortComparison_DateAddedGreater(nsNavHistoryResultNode* a,
562 nsNavHistoryResultNode* b);
563 static int32_t SortComparison_LastModifiedLess(nsNavHistoryResultNode* a,
564 nsNavHistoryResultNode* b);
565 static int32_t SortComparison_LastModifiedGreater(nsNavHistoryResultNode* a,
566 nsNavHistoryResultNode* b);
567 static int32_t SortComparison_TagsLess(nsNavHistoryResultNode* a,
568 nsNavHistoryResultNode* b);
569 static int32_t SortComparison_TagsGreater(nsNavHistoryResultNode* a,
570 nsNavHistoryResultNode* b);
571 static int32_t SortComparison_FrecencyLess(nsNavHistoryResultNode* a,
572 nsNavHistoryResultNode* b);
573 static int32_t SortComparison_FrecencyGreater(nsNavHistoryResultNode* a,
574 nsNavHistoryResultNode* b);
576 // finding children: THESE DO NOT ADDREF
577 nsNavHistoryResultNode* FindChildByURI(const nsACString& aSpec,
578 uint32_t* aNodeIndex);
579 void FindChildrenByURI(const nsCString& aSpec,
580 nsCOMArray<nsNavHistoryResultNode>* aMatches);
581 // returns the index of the given node, -1 if not found
582 int32_t FindChild(nsNavHistoryResultNode* aNode) {
583 return mChildren.IndexOf(aNode);
586 nsNavHistoryResultNode* FindChildByGuid(const nsACString& guid,
587 int32_t* nodeIndex);
589 nsNavHistoryResultNode* FindChildById(int64_t aItemId, int32_t* aNodeIndex);
591 nsresult InsertChildAt(nsNavHistoryResultNode* aNode, int32_t aIndex);
592 nsresult InsertSortedChild(nsNavHistoryResultNode* aNode,
593 bool aIgnoreDuplicates = false);
594 bool EnsureItemPosition(int32_t aIndex);
596 nsresult RemoveChildAt(int32_t aIndex);
598 void RecursiveFindURIs(bool aOnlyOne,
599 nsNavHistoryContainerResultNode* aContainer,
600 const nsCString& aSpec,
601 nsCOMArray<nsNavHistoryResultNode>* aMatches);
602 bool UpdateURIs(bool aRecursive, bool aOnlyOne, bool aUpdateSort,
603 const nsCString& aSpec,
604 nsresult (*aCallback)(nsNavHistoryResultNode*, const void*,
605 const nsNavHistoryResult*),
606 const void* aClosure);
607 nsresult ChangeTitles(nsIURI* aURI, const nsACString& aNewTitle,
608 bool aRecursive, bool aOnlyOne);
610 protected:
611 virtual ~nsNavHistoryContainerResultNode();
613 enum AsyncCanceledState { NOT_CANCELED, CANCELED, CANCELED_RESTART_NEEDED };
615 void CancelAsyncOpen(bool aRestart);
616 nsresult NotifyOnStateChange(uint16_t aOldState);
618 nsCOMPtr<mozIStoragePendingStatement> mAsyncPendingStmt;
619 AsyncCanceledState mAsyncCanceledState;
622 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryContainerResultNode,
623 NS_NAVHISTORYCONTAINERRESULTNODE_IID)
625 // nsNavHistoryQueryResultNode
627 // Overridden container type for complex queries over history and/or
628 // bookmarks. This keeps itself in sync by listening to history and
629 // bookmark notifications.
631 class nsNavHistoryQueryResultNode final
632 : public nsNavHistoryContainerResultNode,
633 public nsINavHistoryQueryResultNode {
634 public:
635 nsNavHistoryQueryResultNode(const nsACString& aTitle, PRTime aTime,
636 const nsACString& aQueryURI,
637 const RefPtr<nsNavHistoryQuery>& aQuery,
638 const RefPtr<nsNavHistoryQueryOptions>& aOptions);
640 NS_DECL_ISUPPORTS_INHERITED
641 NS_FORWARD_COMMON_RESULTNODE_TO_BASE
642 NS_IMETHOD GetType(uint32_t* type) override {
643 *type = nsNavHistoryResultNode::RESULT_TYPE_QUERY;
644 return NS_OK;
646 NS_IMETHOD GetUri(nsACString& aURI) override; // does special lazy creation
647 NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
648 NS_IMETHOD GetHasChildren(bool* aHasChildren) override;
649 NS_DECL_NSINAVHISTORYQUERYRESULTNODE
651 virtual nsresult OnMobilePrefChanged(bool newValue) override;
653 bool CanExpand();
654 bool IsContainersQuery();
656 virtual nsresult OpenContainer() override;
658 nsresult OnItemAdded(int64_t aItemId, int64_t aParentId, int32_t aIndex,
659 uint16_t aItemType, nsIURI* aURI, PRTime aDateAdded,
660 const nsACString& aGUID, const nsACString& aParentGUID,
661 uint16_t aSource);
662 nsresult OnItemRemoved(int64_t aItemId, int64_t aParentFolder, int32_t aIndex,
663 uint16_t aItemType, nsIURI* aURI,
664 const nsACString& aGUID, const nsACString& aParentGUID,
665 uint16_t aSource);
666 nsresult OnItemMoved(int64_t aFolder, int32_t aOldIndex, int32_t aNewIndex,
667 uint16_t aItemType, const nsACString& aGUID,
668 const nsACString& aOldParentGUID,
669 const nsACString& aNewParentGUID, uint16_t aSource,
670 const nsACString& aURI);
671 nsresult OnItemTagsChanged(int64_t aItemId, const nsAString& aURL,
672 const nsAString& aTags);
673 nsresult OnItemTimeChanged(int64_t aItemId, const nsACString& aGUID,
674 PRTime aDateAdded, PRTime aLastModified);
675 nsresult OnItemTitleChanged(int64_t aItemId, const nsACString& aGUID,
676 const nsACString& aTitle, PRTime aLastModified);
677 nsresult OnItemUrlChanged(int64_t aItemId, const nsACString& aGUID,
678 const nsACString& aURL, PRTime aLastModified);
680 // The internal version has an output aAdded parameter, it is incremented by
681 // query nodes when the visited uri belongs to them. If no such query exists,
682 // the history result creates a new query node dynamically.
683 nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
684 uint32_t aTransitionType, const nsACString& aGUID,
685 bool aHidden, uint32_t aVisitCount,
686 const nsAString& aLastKnownTitle, int64_t aFrecency,
687 uint32_t* aAdded);
688 nsresult OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle,
689 const nsACString& aGUID);
690 nsresult OnClearHistory();
691 nsresult OnPageRemovedFromStore(nsIURI* aURI, const nsACString& aGUID,
692 uint16_t aReason);
693 nsresult OnPageRemovedVisits(nsIURI* aURI, bool aPartialRemoval,
694 const nsACString& aGUID, uint16_t aReason,
695 uint32_t aTransitionType);
697 virtual void OnRemoving() override;
699 nsresult OnBeginUpdateBatch();
700 nsresult OnEndUpdateBatch();
702 public:
703 RefPtr<nsNavHistoryQuery> mQuery;
704 bool mHasSearchTerms;
705 uint32_t mLiveUpdate; // one of QUERYUPDATE_* in nsNavHistory.h
707 // safe options getter, ensures query is parsed
708 nsNavHistoryQueryOptions* Options();
710 // this indicates whether the query contents are valid, they don't go away
711 // after the container is closed until a notification comes in
712 bool mContentsValid;
714 nsresult FillChildren();
715 void ClearChildren(bool unregister);
716 nsresult Refresh() override;
718 virtual uint16_t GetSortType() override;
719 virtual void RecursiveSort(SortComparator aComparator) override;
721 uint32_t mBatchChanges;
723 // Tracks transition type filters.
724 nsTArray<uint32_t> mTransitions;
726 protected:
727 virtual ~nsNavHistoryQueryResultNode();
730 // nsNavHistoryFolderResultNode
732 // Overridden container type for bookmark folders. It will keep the contents
733 // of the folder in sync with the bookmark service.
735 class nsNavHistoryFolderResultNode final
736 : public nsNavHistoryContainerResultNode,
737 public nsINavHistoryQueryResultNode,
738 public mozilla::places::WeakAsyncStatementCallback {
739 public:
740 nsNavHistoryFolderResultNode(int64_t aItemId, const nsACString& aBookmarkGuid,
741 int64_t aTargetFolderItemId,
742 const nsACString& aTargetFolderGuid,
743 const nsACString& aTitle,
744 nsNavHistoryQueryOptions* aOptions);
746 NS_DECL_ISUPPORTS_INHERITED
747 NS_FORWARD_COMMON_RESULTNODE_TO_BASE
748 NS_IMETHOD GetType(uint32_t* type) override {
749 if (mTargetFolderItemId != mItemId) {
750 *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
751 } else {
752 *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER;
754 return NS_OK;
756 NS_IMETHOD GetUri(nsACString& aURI) override;
757 NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
758 NS_IMETHOD GetHasChildren(bool* aHasChildren) override;
759 NS_DECL_NSINAVHISTORYQUERYRESULTNODE
761 virtual nsresult OpenContainer() override;
763 virtual nsresult OpenContainerAsync() override;
764 NS_DECL_ASYNCSTATEMENTCALLBACK
766 nsresult OnItemAdded(int64_t aItemId, int64_t aParentFolder, int32_t aIndex,
767 uint16_t aItemType, nsIURI* aURI, PRTime aDateAdded,
768 const nsACString& aGUID, const nsACString& aParentGUID,
769 uint16_t aSource, const nsACString& aTitle,
770 const nsAString& aTags, int64_t aFrecency, bool aHidden,
771 uint32_t aVisitCount, PRTime aLastVisitDate,
772 int64_t aTargetFolderItemId,
773 const nsACString& aTargetFolderGuid,
774 const nsACString& aTargetFolderTitle);
775 nsresult OnItemRemoved(int64_t aItemId, int64_t aParentFolder, int32_t aIndex,
776 uint16_t aItemType, nsIURI* aURI,
777 const nsACString& aGUID, const nsACString& aParentGUID,
778 uint16_t aSource);
779 nsresult OnItemMoved(int64_t aItemId, int32_t aOldIndex, int32_t aNewIndex,
780 uint16_t aItemType, const nsACString& aGUID,
781 const nsACString& aOldParentGUID,
782 const nsACString& aNewParentGUID, uint16_t aSource,
783 const nsACString& aURI, const nsACString& aTitle,
784 const nsAString& aTags, int64_t aFrecency, bool aHidden,
785 uint32_t aVisitCount, PRTime aLastVisitDate,
786 PRTime aDateAdded);
787 nsresult OnItemVisited(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
788 int64_t aFrecency);
790 virtual void OnRemoving() override;
792 // this indicates whether the folder contents are valid, they don't go away
793 // after the container is closed until a notification comes in
794 bool mContentsValid;
796 // If the node is generated from a place:folder=X query, this is the target
797 // folder id and GUID. For regular folder nodes, they are set to the same
798 // values as mItemId and mBookmarkGuid. For more complex queries, they are set
799 // to -1/an empty string.
800 int64_t mTargetFolderItemId;
801 nsCString mTargetFolderGuid;
803 nsresult FillChildren();
804 void ClearChildren(bool aUnregister);
805 nsresult Refresh() override;
807 bool StartIncrementalUpdate();
808 void ReindexRange(int32_t aStartIndex, int32_t aEndIndex, int32_t aDelta);
810 nsresult OnBeginUpdateBatch();
811 nsresult OnEndUpdateBatch();
813 protected:
814 virtual ~nsNavHistoryFolderResultNode();
816 private:
817 nsresult OnChildrenFilled();
818 void EnsureRegisteredAsFolderObserver();
819 nsresult FillChildrenAsync();
821 bool mIsRegisteredFolderObserver;
822 int32_t mAsyncBookmarkIndex;
825 // nsNavHistorySeparatorResultNode
827 // Separator result nodes do not hold any data.
828 class nsNavHistorySeparatorResultNode : public nsNavHistoryResultNode {
829 public:
830 nsNavHistorySeparatorResultNode();
832 NS_IMETHOD GetType(uint32_t* type) override {
833 *type = nsNavHistoryResultNode::RESULT_TYPE_SEPARATOR;
834 return NS_OK;
838 #endif // nsNavHistoryResult_h_