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