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