|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #ifndef mozilla_places_History_h_ |
|
8 #define mozilla_places_History_h_ |
|
9 |
|
10 #include "mozilla/IHistory.h" |
|
11 #include "mozilla/MemoryReporting.h" |
|
12 #include "mozilla/Mutex.h" |
|
13 #include "mozIAsyncHistory.h" |
|
14 #include "nsIDownloadHistory.h" |
|
15 #include "Database.h" |
|
16 |
|
17 #include "mozilla/dom/Link.h" |
|
18 #include "nsTHashtable.h" |
|
19 #include "nsString.h" |
|
20 #include "nsURIHashKey.h" |
|
21 #include "nsTObserverArray.h" |
|
22 #include "nsDeque.h" |
|
23 #include "nsIMemoryReporter.h" |
|
24 #include "nsIObserver.h" |
|
25 #include "mozIStorageConnection.h" |
|
26 |
|
27 namespace mozilla { |
|
28 namespace places { |
|
29 |
|
30 struct VisitData; |
|
31 |
|
32 #define NS_HISTORYSERVICE_CID \ |
|
33 {0x0937a705, 0x91a6, 0x417a, {0x82, 0x92, 0xb2, 0x2e, 0xb1, 0x0d, 0xa8, 0x6c}} |
|
34 |
|
35 // Max size of History::mRecentlyVisitedURIs |
|
36 #define RECENTLY_VISITED_URI_SIZE 8 |
|
37 |
|
38 class History : public IHistory |
|
39 , public nsIDownloadHistory |
|
40 , public mozIAsyncHistory |
|
41 , public nsIObserver |
|
42 , public nsIMemoryReporter |
|
43 { |
|
44 public: |
|
45 NS_DECL_THREADSAFE_ISUPPORTS |
|
46 NS_DECL_IHISTORY |
|
47 NS_DECL_NSIDOWNLOADHISTORY |
|
48 NS_DECL_MOZIASYNCHISTORY |
|
49 NS_DECL_NSIOBSERVER |
|
50 NS_DECL_NSIMEMORYREPORTER |
|
51 |
|
52 History(); |
|
53 |
|
54 /** |
|
55 * Obtains the statement to use to check if a URI is visited or not. |
|
56 */ |
|
57 mozIStorageAsyncStatement* GetIsVisitedStatement(); |
|
58 |
|
59 /** |
|
60 * Adds an entry in moz_places with the data in aVisitData. |
|
61 * |
|
62 * @param aVisitData |
|
63 * The visit data to use to populate a new row in moz_places. |
|
64 */ |
|
65 nsresult InsertPlace(const VisitData& aVisitData); |
|
66 |
|
67 /** |
|
68 * Updates an entry in moz_places with the data in aVisitData. |
|
69 * |
|
70 * @param aVisitData |
|
71 * The visit data to use to update the existing row in moz_places. |
|
72 */ |
|
73 nsresult UpdatePlace(const VisitData& aVisitData); |
|
74 |
|
75 /** |
|
76 * Loads information about the page into _place from moz_places. |
|
77 * |
|
78 * @param _place |
|
79 * The VisitData for the place we need to know information about. |
|
80 * @param [out] _exists |
|
81 * Whether or the page was recorded in moz_places, false otherwise. |
|
82 */ |
|
83 nsresult FetchPageInfo(VisitData& _place, bool* _exists); |
|
84 |
|
85 /** |
|
86 * Get the number of bytes of memory this History object is using, |
|
87 * including sizeof(*this)) |
|
88 */ |
|
89 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); |
|
90 |
|
91 /** |
|
92 * Obtains a pointer to this service. |
|
93 */ |
|
94 static History* GetService(); |
|
95 |
|
96 /** |
|
97 * Obtains a pointer that has had AddRef called on it. Used by the service |
|
98 * manager only. |
|
99 */ |
|
100 static History* GetSingleton(); |
|
101 |
|
102 template<int N> |
|
103 already_AddRefed<mozIStorageStatement> |
|
104 GetStatement(const char (&aQuery)[N]) |
|
105 { |
|
106 mozIStorageConnection* dbConn = GetDBConn(); |
|
107 NS_ENSURE_TRUE(dbConn, nullptr); |
|
108 return mDB->GetStatement(aQuery); |
|
109 } |
|
110 |
|
111 already_AddRefed<mozIStorageStatement> |
|
112 GetStatement(const nsACString& aQuery) |
|
113 { |
|
114 mozIStorageConnection* dbConn = GetDBConn(); |
|
115 NS_ENSURE_TRUE(dbConn, nullptr); |
|
116 return mDB->GetStatement(aQuery); |
|
117 } |
|
118 |
|
119 bool IsShuttingDown() const { |
|
120 return mShuttingDown; |
|
121 } |
|
122 Mutex& GetShutdownMutex() { |
|
123 return mShutdownMutex; |
|
124 } |
|
125 |
|
126 /** |
|
127 * Helper function to append a new URI to mRecentlyVisitedURIs. See |
|
128 * mRecentlyVisitedURIs. |
|
129 */ |
|
130 void AppendToRecentlyVisitedURIs(nsIURI* aURI); |
|
131 |
|
132 private: |
|
133 virtual ~History(); |
|
134 |
|
135 void InitMemoryReporter(); |
|
136 |
|
137 /** |
|
138 * Obtains a read-write database connection. |
|
139 */ |
|
140 mozIStorageConnection* GetDBConn(); |
|
141 |
|
142 /** |
|
143 * The database handle. This is initialized lazily by the first call to |
|
144 * GetDBConn(), so never use it directly, or, if you really need, always |
|
145 * invoke GetDBConn() before. |
|
146 */ |
|
147 nsRefPtr<mozilla::places::Database> mDB; |
|
148 |
|
149 /** |
|
150 * A read-only database connection used for checking if a URI is visited. |
|
151 * |
|
152 * @note this should only be accessed by GetIsVisistedStatement and Shutdown. |
|
153 */ |
|
154 nsCOMPtr<mozIStorageConnection> mReadOnlyDBConn; |
|
155 |
|
156 /** |
|
157 * An asynchronous statement to query if a URI is visited or not. |
|
158 * |
|
159 * @note this should only be accessed by GetIsVisistedStatement and Shutdown. |
|
160 */ |
|
161 nsCOMPtr<mozIStorageAsyncStatement> mIsVisitedStatement; |
|
162 |
|
163 /** |
|
164 * Remove any memory references to tasks and do not take on any more. |
|
165 */ |
|
166 void Shutdown(); |
|
167 |
|
168 static History* gService; |
|
169 |
|
170 // Ensures new tasks aren't started on destruction. |
|
171 bool mShuttingDown; |
|
172 // This mutex guards mShuttingDown. Code running in other threads that might |
|
173 // schedule tasks that use the database should grab it and check the value of |
|
174 // mShuttingDown. If we are already shutting down, the code must gracefully |
|
175 // avoid using the db. If we are not, the lock will prevent shutdown from |
|
176 // starting in an unexpected moment. |
|
177 Mutex mShutdownMutex; |
|
178 |
|
179 typedef nsTObserverArray<mozilla::dom::Link* > ObserverArray; |
|
180 |
|
181 class KeyClass : public nsURIHashKey |
|
182 { |
|
183 public: |
|
184 KeyClass(const nsIURI* aURI) |
|
185 : nsURIHashKey(aURI) |
|
186 { |
|
187 } |
|
188 KeyClass(const KeyClass& aOther) |
|
189 : nsURIHashKey(aOther) |
|
190 { |
|
191 NS_NOTREACHED("Do not call me!"); |
|
192 } |
|
193 ObserverArray array; |
|
194 }; |
|
195 |
|
196 /** |
|
197 * Helper function for nsTHashtable::SizeOfExcludingThis call in |
|
198 * SizeOfIncludingThis(). |
|
199 */ |
|
200 static size_t SizeOfEntryExcludingThis(KeyClass* aEntry, |
|
201 mozilla::MallocSizeOf aMallocSizeOf, |
|
202 void*); |
|
203 |
|
204 nsTHashtable<KeyClass> mObservers; |
|
205 |
|
206 /** |
|
207 * mRecentlyVisitedURIs remembers URIs which are recently added to the DB, |
|
208 * to avoid saving these locations repeatedly in a short period. |
|
209 */ |
|
210 typedef nsAutoTArray<nsCOMPtr<nsIURI>, RECENTLY_VISITED_URI_SIZE> |
|
211 RecentlyVisitedArray; |
|
212 RecentlyVisitedArray mRecentlyVisitedURIs; |
|
213 RecentlyVisitedArray::index_type mRecentlyVisitedURIsNextIndex; |
|
214 |
|
215 bool IsRecentlyVisitedURI(nsIURI* aURI); |
|
216 }; |
|
217 |
|
218 } // namespace places |
|
219 } // namespace mozilla |
|
220 |
|
221 #endif // mozilla_places_History_h_ |