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