/src/mozilla-central/toolkit/components/places/History.h
Line | Count | Source (jump to first uncovered line) |
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/Move.h" |
13 | | #include "mozilla/Mutex.h" |
14 | | #include "mozIAsyncHistory.h" |
15 | | #include "Database.h" |
16 | | |
17 | | #include "mozilla/dom/Link.h" |
18 | | #include "mozilla/ipc/URIParams.h" |
19 | | #include "nsTHashtable.h" |
20 | | #include "nsString.h" |
21 | | #include "nsURIHashKey.h" |
22 | | #include "nsTObserverArray.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 | | class ConcurrentStatementsHolder; |
32 | | |
33 | | #define NS_HISTORYSERVICE_CID \ |
34 | | {0x0937a705, 0x91a6, 0x417a, {0x82, 0x92, 0xb2, 0x2e, 0xb1, 0x0d, 0xa8, 0x6c}} |
35 | | |
36 | | // Initial size of mRecentlyVisitedURIs. |
37 | | #define RECENTLY_VISITED_URIS_SIZE 64 |
38 | | // Microseconds after which a visit can be expired from mRecentlyVisitedURIs. |
39 | | // When an URI is reloaded we only take into account the first visit to it, and |
40 | | // ignore any subsequent visits, if they happen before this time has elapsed. |
41 | | // A commonly found case is to reload a page every 5 minutes, so we pick a time |
42 | | // larger than that. |
43 | 0 | #define RECENTLY_VISITED_URIS_MAX_AGE 6 * 60 * PR_USEC_PER_SEC |
44 | | // When notifying the main thread after inserting visits, we chunk the visits |
45 | | // into medium-sized groups so that we can amortize the cost of the runnable |
46 | | // without janking the main thread by expecting it to process hundreds at once. |
47 | 0 | #define NOTIFY_VISITS_CHUNK_SIZE 100 |
48 | | |
49 | | class History final : public IHistory |
50 | | , public mozIAsyncHistory |
51 | | , public nsIObserver |
52 | | , public nsIMemoryReporter |
53 | | { |
54 | | public: |
55 | | NS_DECL_THREADSAFE_ISUPPORTS |
56 | | NS_DECL_IHISTORY |
57 | | NS_DECL_MOZIASYNCHISTORY |
58 | | NS_DECL_NSIOBSERVER |
59 | | NS_DECL_NSIMEMORYREPORTER |
60 | | |
61 | | History(); |
62 | | |
63 | | /** |
64 | | * Obtains the statement to use to check if a URI is visited or not. |
65 | | */ |
66 | | nsresult GetIsVisitedStatement(mozIStorageCompletionCallback* aCallback); |
67 | | |
68 | | /** |
69 | | * Adds an entry in moz_places with the data in aVisitData. |
70 | | * |
71 | | * @param aVisitData |
72 | | * The visit data to use to populate a new row in moz_places. |
73 | | * @param aShouldNotifyFrecencyChanged |
74 | | * Whether to dispatch OnFrecencyChanged notifications. |
75 | | * Defaults to true. Set to false if you (the caller) are |
76 | | * doing many inserts and will dispatch your own |
77 | | * OnManyFrecenciesChanged notification. |
78 | | */ |
79 | | nsresult InsertPlace(VisitData& aVisitData, |
80 | | bool aShouldNotifyFrecencyChanged = true); |
81 | | |
82 | | /** |
83 | | * Updates an entry in moz_places with the data in aVisitData. |
84 | | * |
85 | | * @param aVisitData |
86 | | * The visit data to use to update the existing row in moz_places. |
87 | | */ |
88 | | nsresult UpdatePlace(const VisitData& aVisitData); |
89 | | |
90 | | /** |
91 | | * Loads information about the page into _place from moz_places. |
92 | | * |
93 | | * @param _place |
94 | | * The VisitData for the place we need to know information about. |
95 | | * @param [out] _exists |
96 | | * Whether or the page was recorded in moz_places, false otherwise. |
97 | | */ |
98 | | nsresult FetchPageInfo(VisitData& _place, bool* _exists); |
99 | | |
100 | | /** |
101 | | * Get the number of bytes of memory this History object is using, |
102 | | * including sizeof(*this)) |
103 | | */ |
104 | | size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); |
105 | | |
106 | | /** |
107 | | * Obtains a pointer to this service. |
108 | | */ |
109 | | static History* GetService(); |
110 | | |
111 | | /** |
112 | | * Used by the service manager only. |
113 | | */ |
114 | | static already_AddRefed<History> GetSingleton(); |
115 | | |
116 | | template<int N> |
117 | | already_AddRefed<mozIStorageStatement> |
118 | | GetStatement(const char (&aQuery)[N]) |
119 | 0 | { |
120 | 0 | // May be invoked on both threads. |
121 | 0 | const mozIStorageConnection* dbConn = GetConstDBConn(); |
122 | 0 | NS_ENSURE_TRUE(dbConn, nullptr); |
123 | 0 | return mDB->GetStatement(aQuery); |
124 | 0 | } Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<147>(char const (&) [147]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<146>(char const (&) [146]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<93>(char const (&) [93]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<71>(char const (&) [71]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<63>(char const (&) [63]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<168>(char const (&) [168]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<90>(char const (&) [90]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<106>(char const (&) [106]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<260>(char const (&) [260]) Unexecuted instantiation: already_AddRefed<mozIStorageStatement> mozilla::places::History::GetStatement<225>(char const (&) [225]) |
125 | | |
126 | | already_AddRefed<mozIStorageStatement> |
127 | | GetStatement(const nsACString& aQuery) |
128 | 0 | { |
129 | 0 | // May be invoked on both threads. |
130 | 0 | const mozIStorageConnection* dbConn = GetConstDBConn(); |
131 | 0 | NS_ENSURE_TRUE(dbConn, nullptr); |
132 | 0 | return mDB->GetStatement(aQuery); |
133 | 0 | } |
134 | | |
135 | 0 | bool IsShuttingDown() const { |
136 | 0 | return mShuttingDown; |
137 | 0 | } |
138 | 0 | Mutex& GetShutdownMutex() { |
139 | 0 | return mShutdownMutex; |
140 | 0 | } |
141 | | |
142 | | /** |
143 | | * Helper function to append a new URI to mRecentlyVisitedURIs. See |
144 | | * mRecentlyVisitedURIs. |
145 | | */ |
146 | | void AppendToRecentlyVisitedURIs(nsIURI* aURI); |
147 | | |
148 | | void NotifyVisitedParent(const nsTArray<mozilla::ipc::URIParams>& aURIs); |
149 | | private: |
150 | | virtual ~History(); |
151 | | |
152 | | void InitMemoryReporter(); |
153 | | |
154 | | /** |
155 | | * Obtains a read-write database connection, initializing the connection |
156 | | * if needed. Must be invoked on the main thread. |
157 | | */ |
158 | | mozIStorageConnection* GetDBConn(); |
159 | | |
160 | | /** |
161 | | * Obtains a read-write database connection, but won't try to initialize it. |
162 | | * May be invoked on both threads, but first one must invoke GetDBConn() on |
163 | | * the main-thread at least once. |
164 | | */ |
165 | | const mozIStorageConnection* GetConstDBConn(); |
166 | | |
167 | | /** |
168 | | * Mark all links for the given URI in the given document as visited. Used |
169 | | * within NotifyVisited. |
170 | | */ |
171 | | void NotifyVisitedForDocument(nsIURI* aURI, nsIDocument* aDocument); |
172 | | |
173 | | /** |
174 | | * Dispatch a runnable for the document passed in which will call |
175 | | * NotifyVisitedForDocument with the correct URI and Document. |
176 | | */ |
177 | | void DispatchNotifyVisited(nsIURI* aURI, nsIDocument* aDocument); |
178 | | |
179 | | /** |
180 | | * The database handle. This is initialized lazily by the first call to |
181 | | * GetDBConn(), so never use it directly, or, if you really need, always |
182 | | * invoke GetDBConn() before. |
183 | | */ |
184 | | RefPtr<mozilla::places::Database> mDB; |
185 | | |
186 | | RefPtr<ConcurrentStatementsHolder> mConcurrentStatementsHolder; |
187 | | |
188 | | /** |
189 | | * Remove any memory references to tasks and do not take on any more. |
190 | | */ |
191 | | void Shutdown(); |
192 | | |
193 | | static History* gService; |
194 | | |
195 | | // Ensures new tasks aren't started on destruction. |
196 | | bool mShuttingDown; |
197 | | // This mutex guards mShuttingDown. Code running in other threads that might |
198 | | // schedule tasks that use the database should grab it and check the value of |
199 | | // mShuttingDown. If we are already shutting down, the code must gracefully |
200 | | // avoid using the db. If we are not, the lock will prevent shutdown from |
201 | | // starting in an unexpected moment. |
202 | | Mutex mShutdownMutex; |
203 | | |
204 | | typedef nsTObserverArray<mozilla::dom::Link* > ObserverArray; |
205 | | |
206 | | class KeyClass : public nsURIHashKey |
207 | | { |
208 | | public: |
209 | | explicit KeyClass(const nsIURI* aURI) |
210 | | : nsURIHashKey(aURI) |
211 | 0 | { |
212 | 0 | } |
213 | | KeyClass(KeyClass&& aOther) |
214 | | : nsURIHashKey(std::move(aOther)) |
215 | | , array(std::move(aOther.array)) |
216 | | , mVisited(std::move(aOther.mVisited)) |
217 | | { |
218 | | MOZ_ASSERT_UNREACHABLE("Do not call me!"); |
219 | | } |
220 | | size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const |
221 | 0 | { |
222 | 0 | return array.ShallowSizeOfExcludingThis(aMallocSizeOf); |
223 | 0 | } |
224 | | ObserverArray array; |
225 | | bool mVisited = false; |
226 | | }; |
227 | | |
228 | | nsTHashtable<KeyClass> mObservers; |
229 | | |
230 | | /** |
231 | | * mRecentlyVisitedURIs remembers URIs which have been recently added to |
232 | | * history, to avoid saving these locations repeatedly in a short period. |
233 | | */ |
234 | | class RecentURIKey : public nsURIHashKey |
235 | | { |
236 | | public: |
237 | | explicit RecentURIKey(const nsIURI* aURI) : nsURIHashKey(aURI) |
238 | 0 | { |
239 | 0 | } |
240 | | RecentURIKey(RecentURIKey&& aOther) : nsURIHashKey(std::move(aOther)) |
241 | | { |
242 | | MOZ_ASSERT_UNREACHABLE("Do not call me!"); |
243 | | } |
244 | | MOZ_INIT_OUTSIDE_CTOR PRTime time; |
245 | | }; |
246 | | nsTHashtable<RecentURIKey> mRecentlyVisitedURIs; |
247 | | /** |
248 | | * Whether aURI has been visited "recently". |
249 | | * See RECENTLY_VISITED_URIS_MAX_AGE. |
250 | | */ |
251 | | bool IsRecentlyVisitedURI(nsIURI* aURI); |
252 | | }; |
253 | | |
254 | | } // namespace places |
255 | | } // namespace mozilla |
256 | | |
257 | | #endif // mozilla_places_History_h_ |