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 /**
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.
10  */
11 
12 #ifndef nsNavHistoryResult_h_
13 #define nsNavHistoryResult_h_
14 
15 #include "nsTArray.h"
16 #include "nsInterfaceHashtable.h"
17 #include "nsDataHashtable.h"
18 #include "nsCycleCollectionParticipant.h"
19 #include "mozilla/storage.h"
20 #include "Helpers.h"
21 
22 class nsNavHistory;
23 class nsNavHistoryQuery;
24 class nsNavHistoryQueryOptions;
25 
26 class nsNavHistoryContainerResultNode;
27 class nsNavHistoryFolderResultNode;
28 class nsNavHistoryQueryResultNode;
29 
30 /**
31  * hashkey wrapper using int64_t KeyType
32  *
33  * @see nsTHashtable::EntryType for specification
34  *
35  * This just truncates the 64-bit int to a 32-bit one for using a hash number.
36  * It is used for bookmark folder IDs, which should be way less than 2^32.
37  */
38 class nsTrimInt64HashKey : public PLDHashEntryHdr {
39  public:
40   typedef const int64_t& KeyType;
41   typedef const int64_t* KeyTypePointer;
42 
nsTrimInt64HashKey(KeyTypePointer aKey)43   explicit nsTrimInt64HashKey(KeyTypePointer aKey) : mValue(*aKey) {}
nsTrimInt64HashKey(const nsTrimInt64HashKey & toCopy)44   nsTrimInt64HashKey(const nsTrimInt64HashKey& toCopy)
45       : mValue(toCopy.mValue) {}
~nsTrimInt64HashKey()46   ~nsTrimInt64HashKey() {}
47 
GetKey()48   KeyType GetKey() const { return mValue; }
KeyEquals(KeyTypePointer aKey)49   bool KeyEquals(KeyTypePointer aKey) const { return *aKey == mValue; }
50 
KeyToPointer(KeyType aKey)51   static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
HashKey(KeyTypePointer aKey)52   static PLDHashNumber HashKey(KeyTypePointer aKey) {
53     return static_cast<uint32_t>((*aKey) & UINT32_MAX);
54   }
55   enum { ALLOW_MEMMOVE = true };
56 
57  private:
58   const int64_t mValue;
59 };
60 
61 // Declare methods for implementing nsINavBookmarkObserver
62 // and nsINavHistoryObserver (some methods, such as BeginUpdateBatch overlap)
63 #define NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE(...)                    \
64   NS_DECL_NSINAVBOOKMARKOBSERVER                                       \
65   NS_IMETHOD OnTitleChanged(nsIURI* aURI, const nsAString& aPageTitle, \
66                             const nsACString& aGUID) __VA_ARGS__;      \
67   NS_IMETHOD OnFrecencyChanged(nsIURI* aURI, int32_t aNewFrecency,     \
68                                const nsACString& aGUID, bool aHidden,  \
69                                PRTime aLastVisitDate) __VA_ARGS__;     \
70   NS_IMETHOD OnManyFrecenciesChanged() __VA_ARGS__;                    \
71   NS_IMETHOD OnDeleteURI(nsIURI* aURI, const nsACString& aGUID,        \
72                          uint16_t aReason) __VA_ARGS__;                \
73   NS_IMETHOD OnClearHistory() __VA_ARGS__;                             \
74   NS_IMETHOD OnPageChanged(nsIURI* aURI, uint32_t aChangedAttribute,   \
75                            const nsAString& aNewValue,                 \
76                            const nsACString& aGUID) __VA_ARGS__;       \
77   NS_IMETHOD OnDeleteVisits(nsIURI* aURI, PRTime aVisitTime,           \
78                             const nsACString& aGUID, uint16_t aReason, \
79                             uint32_t aTransitionType) __VA_ARGS__;
80 
81 // The internal version is used by query nodes.
82 #define NS_DECL_BOOKMARK_HISTORY_OBSERVER_INTERNAL \
83   NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE()
84 
85 // The external version is used by results.
86 #define NS_DECL_BOOKMARK_HISTORY_OBSERVER_EXTERNAL(...) \
87   NS_DECL_BOOKMARK_HISTORY_OBSERVER_BASE(__VA_ARGS__)
88 
89 // nsNavHistoryResult
90 //
91 //    nsNavHistory creates this object and fills in mChildren (by getting
92 //    it through GetTopLevel()). Then FilledAllResults() is called to finish
93 //    object initialization.
94 
95 #define NS_NAVHISTORYRESULT_IID                      \
96   {                                                  \
97     0x455d1d40, 0x1b9b, 0x40e6, {                    \
98       0xa6, 0x41, 0x8b, 0xb7, 0xe8, 0x82, 0x23, 0x87 \
99     }                                                \
100   }
101 
102 class nsNavHistoryResult final : public nsSupportsWeakReference,
103                                  public nsINavHistoryResult,
104                                  public nsINavBookmarkObserver,
105                                  public nsINavHistoryObserver {
106  public:
107   static nsresult NewHistoryResult(nsINavHistoryQuery** aQueries,
108                                    uint32_t aQueryCount,
109                                    nsNavHistoryQueryOptions* aOptions,
110                                    nsNavHistoryContainerResultNode* aRoot,
111                                    bool aBatchInProgress,
112                                    nsNavHistoryResult** result);
113 
114   NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULT_IID)
115 
116   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
117   NS_DECL_NSINAVHISTORYRESULT
118   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsNavHistoryResult,
119                                            nsINavHistoryResult)
120   NS_DECL_BOOKMARK_HISTORY_OBSERVER_EXTERNAL(override)
121   NS_IMETHOD OnVisits(nsIVisitData** aVisits, uint32_t aVisitsCount) override;
122 
123   void AddHistoryObserver(nsNavHistoryQueryResultNode* aNode);
124   void AddBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode,
125                                  int64_t aFolder);
126   void AddAllBookmarksObserver(nsNavHistoryQueryResultNode* aNode);
127   void AddMobilePrefsObserver(nsNavHistoryQueryResultNode* aNode);
128   void RemoveHistoryObserver(nsNavHistoryQueryResultNode* aNode);
129   void RemoveBookmarkFolderObserver(nsNavHistoryFolderResultNode* aNode,
130                                     int64_t aFolder);
131   void RemoveAllBookmarksObserver(nsNavHistoryQueryResultNode* aNode);
132   void RemoveMobilePrefsObserver(nsNavHistoryQueryResultNode* aNode);
133   void StopObserving();
134 
135   nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
136                    uint32_t aTransitionType, const nsACString& aGUID,
137                    bool aHidden, uint32_t aVisitCount,
138                    const nsAString& aLastKnownTitle);
139 
140  public:
141   // two-stage init, use NewHistoryResult to construct
142   explicit nsNavHistoryResult(nsNavHistoryContainerResultNode* mRoot);
143   nsresult Init(nsINavHistoryQuery** aQueries, uint32_t aQueryCount,
144                 nsNavHistoryQueryOptions* aOptions);
145 
146   RefPtr<nsNavHistoryContainerResultNode> mRootNode;
147 
148   nsCOMArray<nsINavHistoryQuery> mQueries;
149   nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
150 
151   // One of nsNavHistoryQueryOptions.SORY_BY_* This is initialized to
152   // mOptions.sortingMode, but may be overridden if the user clicks on one of
153   // the columns.
154   uint16_t mSortingMode;
155   // If root node is closed and we try to apply a sortingMode, it would not
156   // work.  So we will apply it when the node will be reopened and populated.
157   // This var states the fact we need to apply sortingMode in such a situation.
158   bool mNeedsToApplySortingMode;
159 
160   // The sorting annotation to be used for in SORT_BY_ANNOTATION_* modes
161   nsCString mSortingAnnotation;
162 
163   // node observers
164   bool mIsHistoryObserver;
165   bool mIsBookmarkFolderObserver;
166   bool mIsAllBookmarksObserver;
167   bool mIsMobilePrefObserver;
168 
169   typedef nsTArray<RefPtr<nsNavHistoryQueryResultNode> > QueryObserverList;
170   QueryObserverList mHistoryObservers;
171   QueryObserverList mAllBookmarksObservers;
172   QueryObserverList mMobilePrefObservers;
173 
174   typedef nsTArray<RefPtr<nsNavHistoryFolderResultNode> > FolderObserverList;
175   nsDataHashtable<nsTrimInt64HashKey, FolderObserverList*>
176       mBookmarkFolderObservers;
177   FolderObserverList* BookmarkFolderObserversForId(int64_t aFolderId,
178                                                    bool aCreate);
179 
180   typedef nsTArray<RefPtr<nsNavHistoryContainerResultNode> >
181       ContainerObserverList;
182 
183   void RecursiveExpandCollapse(nsNavHistoryContainerResultNode* aContainer,
184                                bool aExpand);
185 
186   void InvalidateTree();
187 
188   bool mBatchInProgress;
189 
190   nsMaybeWeakPtrArray<nsINavHistoryResultObserver> mObservers;
191   bool mSuppressNotifications;
192 
193   ContainerObserverList mRefreshParticipants;
194   void requestRefresh(nsNavHistoryContainerResultNode* aContainer);
195 
196   void OnMobilePrefChanged();
197 
198   static void OnMobilePrefChangedCallback(const char* prefName, void* closure);
199 
200  protected:
201   virtual ~nsNavHistoryResult();
202 };
203 
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult,NS_NAVHISTORYRESULT_IID)204 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResult, NS_NAVHISTORYRESULT_IID)
205 
206 // nsNavHistoryResultNode
207 //
208 //    This is the base class for every node in a result set. The result itself
209 //    is a node (nsNavHistoryResult inherits from this), as well as every
210 //    leaf and branch on the tree.
211 
212 #define NS_NAVHISTORYRESULTNODE_IID                  \
213   {                                                  \
214     0x54b61d38, 0x57c1, 0x11da, {                    \
215       0x95, 0xb8, 0x00, 0x13, 0x21, 0xc9, 0xf6, 0x9e \
216     }                                                \
217   }
218 
219 // These are all the simple getters, they can be used for the result node
220 // implementation and all subclasses. More complex are GetIcon, GetParent
221 // (which depends on the definition of container result node), and GetUri
222 // (which is overridded for lazy construction for some containers).
223 #define NS_IMPLEMENT_SIMPLE_RESULTNODE                         \
224   NS_IMETHOD GetTitle(nsACString& aTitle) override {           \
225     aTitle = mTitle;                                           \
226     return NS_OK;                                              \
227   }                                                            \
228   NS_IMETHOD GetAccessCount(uint32_t* aAccessCount) override { \
229     *aAccessCount = mAccessCount;                              \
230     return NS_OK;                                              \
231   }                                                            \
232   NS_IMETHOD GetTime(PRTime* aTime) override {                 \
233     *aTime = mTime;                                            \
234     return NS_OK;                                              \
235   }                                                            \
236   NS_IMETHOD GetIndentLevel(int32_t* aIndentLevel) override {  \
237     *aIndentLevel = mIndentLevel;                              \
238     return NS_OK;                                              \
239   }                                                            \
240   NS_IMETHOD GetBookmarkIndex(int32_t* aIndex) override {      \
241     *aIndex = mBookmarkIndex;                                  \
242     return NS_OK;                                              \
243   }                                                            \
244   NS_IMETHOD GetDateAdded(PRTime* aDateAdded) override {       \
245     *aDateAdded = mDateAdded;                                  \
246     return NS_OK;                                              \
247   }                                                            \
248   NS_IMETHOD GetLastModified(PRTime* aLastModified) override { \
249     *aLastModified = mLastModified;                            \
250     return NS_OK;                                              \
251   }                                                            \
252   NS_IMETHOD GetItemId(int64_t* aId) override {                \
253     *aId = mItemId;                                            \
254     return NS_OK;                                              \
255   }
256 
257 // This is used by the base classes instead of
258 // NS_FORWARD_NSINAVHISTORYRESULTNODE(nsNavHistoryResultNode) because they
259 // need to redefine GetType and GetUri rather than forwarding them. This
260 // implements all the simple getters instead of forwarding because they are so
261 // short and we can save a virtual function call.
262 //
263 // (GetUri is redefined only by QueryResultNode and FolderResultNode because
264 // the queries might not necessarily be parsed. The rest just return the node's
265 // buffer.)
266 #define NS_FORWARD_COMMON_RESULTNODE_TO_BASE                                  \
267   NS_IMPLEMENT_SIMPLE_RESULTNODE                                              \
268   NS_IMETHOD GetIcon(nsACString& aIcon) override {                            \
269     return nsNavHistoryResultNode::GetIcon(aIcon);                            \
270   }                                                                           \
271   NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) override { \
272     return nsNavHistoryResultNode::GetParent(aParent);                        \
273   }                                                                           \
274   NS_IMETHOD GetParentResult(nsINavHistoryResult** aResult) override {        \
275     return nsNavHistoryResultNode::GetParentResult(aResult);                  \
276   }                                                                           \
277   NS_IMETHOD GetTags(nsAString& aTags) override {                             \
278     return nsNavHistoryResultNode::GetTags(aTags);                            \
279   }                                                                           \
280   NS_IMETHOD GetPageGuid(nsACString& aPageGuid) override {                    \
281     return nsNavHistoryResultNode::GetPageGuid(aPageGuid);                    \
282   }                                                                           \
283   NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) override {            \
284     return nsNavHistoryResultNode::GetBookmarkGuid(aBookmarkGuid);            \
285   }                                                                           \
286   NS_IMETHOD GetVisitId(int64_t* aVisitId) override {                         \
287     return nsNavHistoryResultNode::GetVisitId(aVisitId);                      \
288   }                                                                           \
289   NS_IMETHOD GetFromVisitId(int64_t* aFromVisitId) override {                 \
290     return nsNavHistoryResultNode::GetFromVisitId(aFromVisitId);              \
291   }                                                                           \
292   NS_IMETHOD GetVisitType(uint32_t* aVisitType) override {                    \
293     return nsNavHistoryResultNode::GetVisitType(aVisitType);                  \
294   }
295 
296 class nsNavHistoryResultNode : public nsINavHistoryResultNode {
297  public:
298   nsNavHistoryResultNode(const nsACString& aURI, const nsACString& aTitle,
299                          uint32_t aAccessCount, PRTime aTime);
300 
301   NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYRESULTNODE_IID)
302 
303   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
304   NS_DECL_CYCLE_COLLECTION_CLASS(nsNavHistoryResultNode)
305 
306   NS_IMPLEMENT_SIMPLE_RESULTNODE
307   NS_IMETHOD GetIcon(nsACString& aIcon) override;
308   NS_IMETHOD GetParent(nsINavHistoryContainerResultNode** aParent) override;
309   NS_IMETHOD GetParentResult(nsINavHistoryResult** aResult) override;
310   NS_IMETHOD GetType(uint32_t* type) override {
311     *type = nsNavHistoryResultNode::RESULT_TYPE_URI;
312     return NS_OK;
313   }
314   NS_IMETHOD GetUri(nsACString& aURI) override {
315     aURI = mURI;
316     return NS_OK;
317   }
318   NS_IMETHOD GetTags(nsAString& aTags) override;
319   NS_IMETHOD GetPageGuid(nsACString& aPageGuid) override;
320   NS_IMETHOD GetBookmarkGuid(nsACString& aBookmarkGuid) override;
321   NS_IMETHOD GetVisitId(int64_t* aVisitId) override;
322   NS_IMETHOD GetFromVisitId(int64_t* aFromVisitId) override;
323   NS_IMETHOD GetVisitType(uint32_t* aVisitType) override;
324 
325   virtual void OnRemoving();
326 
327   // Called from result's onItemChanged, see also bookmark observer declaration
328   // in nsNavHistoryFolderResultNode
329   NS_IMETHOD OnItemChanged(int64_t aItemId, const nsACString& aProperty,
330                            bool aIsAnnotationProperty, const nsACString& aValue,
331                            PRTime aNewLastModified, uint16_t aItemType,
332                            int64_t aParentId, const nsACString& aGUID,
333                            const nsACString& aParentGUID,
334                            const nsACString& aOldValue, uint16_t aSource);
335 
336   virtual nsresult OnMobilePrefChanged(bool newValue) { return NS_OK; };
337 
338  protected:
339   virtual ~nsNavHistoryResultNode() {}
340 
341  public:
342   nsNavHistoryResult* GetResult();
343 
344   // These functions test the type. We don't use a virtual function since that
345   // would take a vtable slot for every one of (potentially very many) nodes.
346   // Note that GetType() already has a vtable slot because its on the iface.
347   bool IsTypeContainer(uint32_t type) {
348     return type == nsINavHistoryResultNode::RESULT_TYPE_QUERY ||
349            type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
350            type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
351   }
352   bool IsContainer() {
353     uint32_t type;
354     GetType(&type);
355     return IsTypeContainer(type);
356   }
357   static bool IsTypeURI(uint32_t type) {
358     return type == nsINavHistoryResultNode::RESULT_TYPE_URI;
359   }
360   bool IsURI() {
361     uint32_t type;
362     GetType(&type);
363     return IsTypeURI(type);
364   }
365   static bool IsTypeFolder(uint32_t type) {
366     return type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER ||
367            type == nsINavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
368   }
369   bool IsFolder() {
370     uint32_t type;
371     GetType(&type);
372     return IsTypeFolder(type);
373   }
374   static bool IsTypeQuery(uint32_t type) {
375     return type == nsINavHistoryResultNode::RESULT_TYPE_QUERY;
376   }
377   bool IsQuery() {
378     uint32_t type;
379     GetType(&type);
380     return IsTypeQuery(type);
381   }
382   bool IsSeparator() {
383     uint32_t type;
384     GetType(&type);
385     return type == nsINavHistoryResultNode::RESULT_TYPE_SEPARATOR;
386   }
387   nsNavHistoryContainerResultNode* GetAsContainer() {
388     NS_ASSERTION(IsContainer(), "Not a container");
389     return reinterpret_cast<nsNavHistoryContainerResultNode*>(this);
390   }
391   nsNavHistoryFolderResultNode* GetAsFolder() {
392     NS_ASSERTION(IsFolder(), "Not a folder");
393     return reinterpret_cast<nsNavHistoryFolderResultNode*>(this);
394   }
395   nsNavHistoryQueryResultNode* GetAsQuery() {
396     NS_ASSERTION(IsQuery(), "Not a query");
397     return reinterpret_cast<nsNavHistoryQueryResultNode*>(this);
398   }
399 
400   RefPtr<nsNavHistoryContainerResultNode> mParent;
401   nsCString mURI;  // not necessarily valid for containers, call GetUri
402   nsCString mTitle;
403   nsString mTags;
404   bool mAreTagsSorted;
405   uint32_t mAccessCount;
406   int64_t mTime;
407   int32_t mBookmarkIndex;
408   int64_t mItemId;
409   int64_t mFolderId;
410   int64_t mVisitId;
411   int64_t mFromVisitId;
412   PRTime mDateAdded;
413   PRTime mLastModified;
414 
415   // The indent level of this node. The root node will have a value of -1.  The
416   // root's children will have a value of 0, and so on.
417   int32_t mIndentLevel;
418 
419   // Frecency of the page.  Valid only for URI nodes.
420   int32_t mFrecency;
421 
422   // Hidden status of the page.  Valid only for URI nodes.
423   bool mHidden;
424 
425   // Transition type used when this node represents a single visit.
426   uint32_t mTransitionType;
427 
428   // Unique Id of the page.
429   nsCString mPageGuid;
430 
431   // Unique Id of the bookmark.
432   nsCString mBookmarkGuid;
433 };
434 
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode,NS_NAVHISTORYRESULTNODE_IID)435 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryResultNode,
436                               NS_NAVHISTORYRESULTNODE_IID)
437 
438 // nsNavHistoryContainerResultNode
439 //
440 //    This is the base class for all nodes that can have children. It is
441 //    overridden for nodes that are dynamically populated such as queries and
442 //    folders. It is used directly for simple containers such as host groups
443 //    in history views.
444 
445 // derived classes each provide their own implementation of has children and
446 // forward the rest to us using this macro
447 #define NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN                           \
448   NS_IMETHOD GetState(uint16_t* _state) override {                            \
449     return nsNavHistoryContainerResultNode::GetState(_state);                 \
450   }                                                                           \
451   NS_IMETHOD GetContainerOpen(bool* aContainerOpen) override {                \
452     return nsNavHistoryContainerResultNode::GetContainerOpen(aContainerOpen); \
453   }                                                                           \
454   NS_IMETHOD SetContainerOpen(bool aContainerOpen) override {                 \
455     return nsNavHistoryContainerResultNode::SetContainerOpen(aContainerOpen); \
456   }                                                                           \
457   NS_IMETHOD GetChildCount(uint32_t* aChildCount) override {                  \
458     return nsNavHistoryContainerResultNode::GetChildCount(aChildCount);       \
459   }                                                                           \
460   NS_IMETHOD GetChild(uint32_t index, nsINavHistoryResultNode** _retval)      \
461       override {                                                              \
462     return nsNavHistoryContainerResultNode::GetChild(index, _retval);         \
463   }                                                                           \
464   NS_IMETHOD GetChildIndex(nsINavHistoryResultNode* aNode, uint32_t* _retval) \
465       override {                                                              \
466     return nsNavHistoryContainerResultNode::GetChildIndex(aNode, _retval);    \
467   }
468 
469 #define NS_NAVHISTORYCONTAINERRESULTNODE_IID         \
470   {                                                  \
471     0x6e3bf8d3, 0x22aa, 0x4065, {                    \
472       0x86, 0xbc, 0x37, 0x46, 0xb5, 0xb3, 0x2c, 0xe8 \
473     }                                                \
474   }
475 
476 class nsNavHistoryContainerResultNode
477     : public nsNavHistoryResultNode,
478       public nsINavHistoryContainerResultNode {
479  public:
480   nsNavHistoryContainerResultNode(const nsACString& aURI,
481                                   const nsACString& aTitle,
482                                   uint32_t aContainerType,
483                                   nsNavHistoryQueryOptions* aOptions);
484   nsNavHistoryContainerResultNode(const nsACString& aURI,
485                                   const nsACString& aTitle, PRTime aTime,
486                                   uint32_t aContainerType,
487                                   nsNavHistoryQueryOptions* aOptions);
488 
489   virtual nsresult Refresh();
490 
491   NS_DECLARE_STATIC_IID_ACCESSOR(NS_NAVHISTORYCONTAINERRESULTNODE_IID)
492 
493   NS_DECL_ISUPPORTS_INHERITED
494   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsNavHistoryContainerResultNode,
495                                            nsNavHistoryResultNode)
496   NS_FORWARD_COMMON_RESULTNODE_TO_BASE
497   NS_IMETHOD GetType(uint32_t* type) override {
498     *type = mContainerType;
499     return NS_OK;
500   }
501   NS_IMETHOD GetUri(nsACString& aURI) override {
502     aURI = mURI;
503     return NS_OK;
504   }
505   NS_DECL_NSINAVHISTORYCONTAINERRESULTNODE
506 
507  public:
508   virtual void OnRemoving() override;
509 
510   bool AreChildrenVisible();
511 
512   // Overridded by descendents to populate.
513   virtual nsresult OpenContainer();
514   nsresult CloseContainer(bool aSuppressNotifications = false);
515 
516   virtual nsresult OpenContainerAsync();
517 
518   // This points to the result that owns this container. All containers have
519   // their result pointer set so we can quickly get to the result without having
520   // to walk the tree. Yet, this also saves us from storing a million pointers
521   // for every leaf node to the result.
522   RefPtr<nsNavHistoryResult> mResult;
523 
524   // For example, RESULT_TYPE_QUERY. Query and Folder results override GetType
525   // so this is not used, but is still kept in sync.
526   uint32_t mContainerType;
527 
528   // When there are children, this stores the open state in the tree
529   // this is set to the default in the constructor.
530   bool mExpanded;
531 
532   // Filled in by the result type generator in nsNavHistory.
533   nsCOMArray<nsNavHistoryResultNode> mChildren;
534 
535   // mOriginalOptions is the options object used to _define_ this specific
536   // container node. It may differ from mOptions, that is the options used
537   // to _fill_ this container node, because mOptions may be modified by
538   // the direct parent of this container node, see SetAsParentOfNode. For
539   // example, if the parent has excludeItems, options will have it too, even if
540   // originally this object was not defined with that option.
541   nsCOMPtr<nsNavHistoryQueryOptions> mOriginalOptions;
542   nsCOMPtr<nsNavHistoryQueryOptions> mOptions;
543 
544   void FillStats();
545   // Sets this container as parent of aNode, propagating the appropriate
546   // options.
547   void SetAsParentOfNode(nsNavHistoryResultNode* aNode);
548   nsresult ReverseUpdateStats(int32_t aAccessCountChange);
549 
550   // Sorting methods.
551   typedef nsCOMArray<nsNavHistoryResultNode>::nsCOMArrayComparatorFunc
552       SortComparator;
553   virtual uint16_t GetSortType();
554   virtual void GetSortingAnnotation(nsACString& aSortingAnnotation);
555 
556   static SortComparator GetSortingComparator(uint16_t aSortType);
557   virtual void RecursiveSort(const char* aData, SortComparator aComparator);
558   uint32_t FindInsertionPoint(nsNavHistoryResultNode* aNode,
559                               SortComparator aComparator, const char* aData,
560                               bool* aItemExists);
561   bool DoesChildNeedResorting(uint32_t aIndex, SortComparator aComparator,
562                               const char* aData);
563 
564   static int32_t SortComparison_StringLess(const nsAString& a,
565                                            const nsAString& b);
566 
567   static int32_t SortComparison_Bookmark(nsNavHistoryResultNode* a,
568                                          nsNavHistoryResultNode* b,
569                                          void* closure);
570   static int32_t SortComparison_TitleLess(nsNavHistoryResultNode* a,
571                                           nsNavHistoryResultNode* b,
572                                           void* closure);
573   static int32_t SortComparison_TitleGreater(nsNavHistoryResultNode* a,
574                                              nsNavHistoryResultNode* b,
575                                              void* closure);
576   static int32_t SortComparison_DateLess(nsNavHistoryResultNode* a,
577                                          nsNavHistoryResultNode* b,
578                                          void* closure);
579   static int32_t SortComparison_DateGreater(nsNavHistoryResultNode* a,
580                                             nsNavHistoryResultNode* b,
581                                             void* closure);
582   static int32_t SortComparison_URILess(nsNavHistoryResultNode* a,
583                                         nsNavHistoryResultNode* b,
584                                         void* closure);
585   static int32_t SortComparison_URIGreater(nsNavHistoryResultNode* a,
586                                            nsNavHistoryResultNode* b,
587                                            void* closure);
588   static int32_t SortComparison_VisitCountLess(nsNavHistoryResultNode* a,
589                                                nsNavHistoryResultNode* b,
590                                                void* closure);
591   static int32_t SortComparison_VisitCountGreater(nsNavHistoryResultNode* a,
592                                                   nsNavHistoryResultNode* b,
593                                                   void* closure);
594   static int32_t SortComparison_AnnotationLess(nsNavHistoryResultNode* a,
595                                                nsNavHistoryResultNode* b,
596                                                void* closure);
597   static int32_t SortComparison_AnnotationGreater(nsNavHistoryResultNode* a,
598                                                   nsNavHistoryResultNode* b,
599                                                   void* closure);
600   static int32_t SortComparison_DateAddedLess(nsNavHistoryResultNode* a,
601                                               nsNavHistoryResultNode* b,
602                                               void* closure);
603   static int32_t SortComparison_DateAddedGreater(nsNavHistoryResultNode* a,
604                                                  nsNavHistoryResultNode* b,
605                                                  void* closure);
606   static int32_t SortComparison_LastModifiedLess(nsNavHistoryResultNode* a,
607                                                  nsNavHistoryResultNode* b,
608                                                  void* closure);
609   static int32_t SortComparison_LastModifiedGreater(nsNavHistoryResultNode* a,
610                                                     nsNavHistoryResultNode* b,
611                                                     void* closure);
612   static int32_t SortComparison_TagsLess(nsNavHistoryResultNode* a,
613                                          nsNavHistoryResultNode* b,
614                                          void* closure);
615   static int32_t SortComparison_TagsGreater(nsNavHistoryResultNode* a,
616                                             nsNavHistoryResultNode* b,
617                                             void* closure);
618   static int32_t SortComparison_FrecencyLess(nsNavHistoryResultNode* a,
619                                              nsNavHistoryResultNode* b,
620                                              void* closure);
621   static int32_t SortComparison_FrecencyGreater(nsNavHistoryResultNode* a,
622                                                 nsNavHistoryResultNode* b,
623                                                 void* closure);
624 
625   // finding children: THESE DO NOT ADDREF
626   nsNavHistoryResultNode* FindChildURI(const nsACString& aSpec,
627                                        uint32_t* aNodeIndex);
628   // returns the index of the given node, -1 if not found
629   int32_t FindChild(nsNavHistoryResultNode* aNode) {
630     return mChildren.IndexOf(aNode);
631   }
632 
633   nsNavHistoryResultNode* FindChildByGuid(const nsACString& guid,
634                                           int32_t* nodeIndex);
635 
636   nsresult InsertChildAt(nsNavHistoryResultNode* aNode, int32_t aIndex);
637   nsresult InsertSortedChild(nsNavHistoryResultNode* aNode,
638                              bool aIgnoreDuplicates = false);
639   bool EnsureItemPosition(uint32_t aIndex);
640 
641   nsresult RemoveChildAt(int32_t aIndex);
642 
643   void RecursiveFindURIs(bool aOnlyOne,
644                          nsNavHistoryContainerResultNode* aContainer,
645                          const nsCString& aSpec,
646                          nsCOMArray<nsNavHistoryResultNode>* aMatches);
647   bool UpdateURIs(bool aRecursive, bool aOnlyOne, bool aUpdateSort,
648                   const nsCString& aSpec,
649                   nsresult (*aCallback)(nsNavHistoryResultNode*, const void*,
650                                         const nsNavHistoryResult*),
651                   const void* aClosure);
652   nsresult ChangeTitles(nsIURI* aURI, const nsACString& aNewTitle,
653                         bool aRecursive, bool aOnlyOne);
654 
655  protected:
656   virtual ~nsNavHistoryContainerResultNode();
657 
658   enum AsyncCanceledState { NOT_CANCELED, CANCELED, CANCELED_RESTART_NEEDED };
659 
660   void CancelAsyncOpen(bool aRestart);
661   nsresult NotifyOnStateChange(uint16_t aOldState);
662 
663   nsCOMPtr<mozIStoragePendingStatement> mAsyncPendingStmt;
664   AsyncCanceledState mAsyncCanceledState;
665 };
666 
NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryContainerResultNode,NS_NAVHISTORYCONTAINERRESULTNODE_IID)667 NS_DEFINE_STATIC_IID_ACCESSOR(nsNavHistoryContainerResultNode,
668                               NS_NAVHISTORYCONTAINERRESULTNODE_IID)
669 
670 // nsNavHistoryQueryResultNode
671 //
672 //    Overridden container type for complex queries over history and/or
673 //    bookmarks. This keeps itself in sync by listening to history and
674 //    bookmark notifications.
675 
676 class nsNavHistoryQueryResultNode final
677     : public nsNavHistoryContainerResultNode,
678       public nsINavHistoryQueryResultNode,
679       public nsINavBookmarkObserver {
680  public:
681   nsNavHistoryQueryResultNode(const nsACString& aTitle,
682                               const nsACString& aQueryURI);
683   nsNavHistoryQueryResultNode(const nsACString& aTitle,
684                               const nsCOMArray<nsNavHistoryQuery>& aQueries,
685                               nsNavHistoryQueryOptions* aOptions);
686   nsNavHistoryQueryResultNode(const nsACString& aTitle, PRTime aTime,
687                               const nsCOMArray<nsNavHistoryQuery>& aQueries,
688                               nsNavHistoryQueryOptions* aOptions);
689 
690   NS_DECL_ISUPPORTS_INHERITED
691   NS_FORWARD_COMMON_RESULTNODE_TO_BASE
692   NS_IMETHOD GetType(uint32_t* type) override {
693     *type = nsNavHistoryResultNode::RESULT_TYPE_QUERY;
694     return NS_OK;
695   }
696   NS_IMETHOD GetUri(nsACString& aURI) override;  // does special lazy creation
697   NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
698   NS_IMETHOD GetHasChildren(bool* aHasChildren) override;
699   NS_DECL_NSINAVHISTORYQUERYRESULTNODE
700 
701   virtual nsresult OnMobilePrefChanged(bool newValue) override;
702 
703   bool CanExpand();
704   bool IsContainersQuery();
705 
706   virtual nsresult OpenContainer() override;
707 
708   NS_DECL_BOOKMARK_HISTORY_OBSERVER_INTERNAL
709 
710   // The internal version has an output aAdded parameter, it is incremented by
711   // query nodes when the visited uri belongs to them. If no such query exists,
712   // the history result creates a new query node dynamically.
713   nsresult OnVisit(nsIURI* aURI, int64_t aVisitId, PRTime aTime,
714                    uint32_t aTransitionType, bool aHidden, uint32_t* aAdded);
715   virtual void OnRemoving() override;
716 
717  public:
718   // this constructs lazily mURI from mQueries and mOptions, call
719   // VerifyQueriesSerialized either this or mQueries/mOptions should be valid
720   nsresult VerifyQueriesSerialized();
721 
722   // these may be constructed lazily from mURI, call VerifyQueriesParsed
723   // either this or mURI should be valid
724   nsCOMArray<nsNavHistoryQuery> mQueries;
725   uint32_t mLiveUpdate;  // one of QUERYUPDATE_* in nsNavHistory.h
726   bool mHasSearchTerms;
727   nsresult VerifyQueriesParsed();
728 
729   // safe options getter, ensures queries are parsed
730   nsNavHistoryQueryOptions* Options();
731 
732   // this indicates whether the query contents are valid, they don't go away
733   // after the container is closed until a notification comes in
734   bool mContentsValid;
735 
736   nsresult FillChildren();
737   void ClearChildren(bool unregister);
738   nsresult Refresh() override;
739 
740   virtual uint16_t GetSortType() override;
741   virtual void GetSortingAnnotation(nsACString& aSortingAnnotation) override;
742   virtual void RecursiveSort(const char* aData,
743                              SortComparator aComparator) override;
744 
745   nsresult NotifyIfTagsChanged(nsIURI* aURI);
746 
747   uint32_t mBatchChanges;
748 
749   // Tracks transition type filters shared by all mQueries.
750   nsTArray<uint32_t> mTransitions;
751 
752  protected:
753   virtual ~nsNavHistoryQueryResultNode();
754 };
755 
756 // nsNavHistoryFolderResultNode
757 //
758 //    Overridden container type for bookmark folders. It will keep the contents
759 //    of the folder in sync with the bookmark service.
760 
761 class nsNavHistoryFolderResultNode final
762     : public nsNavHistoryContainerResultNode,
763       public nsINavHistoryQueryResultNode,
764       public nsINavBookmarkObserver,
765       public mozilla::places::WeakAsyncStatementCallback {
766  public:
767   nsNavHistoryFolderResultNode(const nsACString& aTitle,
768                                nsNavHistoryQueryOptions* options,
769                                int64_t aFolderId);
770 
771   NS_DECL_ISUPPORTS_INHERITED
772   NS_FORWARD_COMMON_RESULTNODE_TO_BASE
GetType(uint32_t * type)773   NS_IMETHOD GetType(uint32_t* type) override {
774     if (mTargetFolderItemId != mItemId) {
775       *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER_SHORTCUT;
776     } else {
777       *type = nsNavHistoryResultNode::RESULT_TYPE_FOLDER;
778     }
779     return NS_OK;
780   }
781   NS_IMETHOD GetUri(nsACString& aURI) override;
782   NS_FORWARD_CONTAINERNODE_EXCEPT_HASCHILDREN
783   NS_IMETHOD GetHasChildren(bool* aHasChildren) override;
784   NS_DECL_NSINAVHISTORYQUERYRESULTNODE
785 
786   virtual nsresult OpenContainer() override;
787 
788   virtual nsresult OpenContainerAsync() override;
789   NS_DECL_ASYNCSTATEMENTCALLBACK
790 
791   // This object implements a bookmark observer interface. This is called from
792   // the result's actual observer and it knows all observers are
793   // FolderResultNodes
794   NS_DECL_NSINAVBOOKMARKOBSERVER
795 
796   virtual void OnRemoving() override;
797 
798   // this indicates whether the folder contents are valid, they don't go away
799   // after the container is closed until a notification comes in
800   bool mContentsValid;
801 
802   // If the node is generated from a place:folder=X query, this is the target
803   // folder id and GUID.  For regular folder nodes, they are set to the same
804   // values as mItemId and mBookmarkGuid. For more complex queries, they are set
805   // to -1/an empty string.
806   int64_t mTargetFolderItemId;
807   nsCString mTargetFolderGuid;
808 
809   nsresult FillChildren();
810   void ClearChildren(bool aUnregister);
811   nsresult Refresh() override;
812 
813   bool StartIncrementalUpdate();
814   void ReindexRange(int32_t aStartIndex, int32_t aEndIndex, int32_t aDelta);
815 
816   nsNavHistoryResultNode* FindChildById(int64_t aItemId, uint32_t* aNodeIndex);
817 
818  protected:
819   virtual ~nsNavHistoryFolderResultNode();
820 
821  private:
822   nsresult OnChildrenFilled();
823   void EnsureRegisteredAsFolderObserver();
824   nsresult FillChildrenAsync();
825 
826   bool mIsRegisteredFolderObserver;
827   int32_t mAsyncBookmarkIndex;
828 };
829 
830 // nsNavHistorySeparatorResultNode
831 //
832 // Separator result nodes do not hold any data.
833 class nsNavHistorySeparatorResultNode : public nsNavHistoryResultNode {
834  public:
835   nsNavHistorySeparatorResultNode();
836 
GetType(uint32_t * type)837   NS_IMETHOD GetType(uint32_t* type) override {
838     *type = nsNavHistoryResultNode::RESULT_TYPE_SEPARATOR;
839     return NS_OK;
840   }
841 };
842 
843 #endif  // nsNavHistoryResult_h_
844