Line data Source code
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 : 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 : #define RECENTLY_VISITED_URIS_MAX_AGE 6 * 60 * PR_USEC_PER_SEC
44 :
45 : class History final : public IHistory
46 : , public nsIDownloadHistory
47 : , public mozIAsyncHistory
48 : , public nsIObserver
49 : , public nsIMemoryReporter
50 : {
51 : public:
52 : NS_DECL_THREADSAFE_ISUPPORTS
53 : NS_DECL_IHISTORY
54 : NS_DECL_NSIDOWNLOADHISTORY
55 : NS_DECL_MOZIASYNCHISTORY
56 : NS_DECL_NSIOBSERVER
57 : NS_DECL_NSIMEMORYREPORTER
58 :
59 : History();
60 :
61 : /**
62 : * Obtains the statement to use to check if a URI is visited or not.
63 : */
64 : nsresult GetIsVisitedStatement(mozIStorageCompletionCallback* aCallback);
65 :
66 : /**
67 : * Adds an entry in moz_places with the data in aVisitData.
68 : *
69 : * @param aVisitData
70 : * The visit data to use to populate a new row in moz_places.
71 : * @param aShouldNotifyFrecencyChanged
72 : * Whether to dispatch OnFrecencyChanged notifications.
73 : * Defaults to true. Set to false if you (the caller) are
74 : * doing many inserts and will dispatch your own
75 : * OnManyFrecenciesChanged notification.
76 : */
77 : nsresult InsertPlace(VisitData& aVisitData,
78 : bool aShouldNotifyFrecencyChanged = true);
79 :
80 : /**
81 : * Updates an entry in moz_places with the data in aVisitData.
82 : *
83 : * @param aVisitData
84 : * The visit data to use to update the existing row in moz_places.
85 : */
86 : nsresult UpdatePlace(const VisitData& aVisitData);
87 :
88 : /**
89 : * Loads information about the page into _place from moz_places.
90 : *
91 : * @param _place
92 : * The VisitData for the place we need to know information about.
93 : * @param [out] _exists
94 : * Whether or the page was recorded in moz_places, false otherwise.
95 : */
96 : nsresult FetchPageInfo(VisitData& _place, bool* _exists);
97 :
98 : /**
99 : * Get the number of bytes of memory this History object is using,
100 : * including sizeof(*this))
101 : */
102 : size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
103 :
104 : /**
105 : * Obtains a pointer to this service.
106 : */
107 : static History* GetService();
108 :
109 : /**
110 : * Obtains a pointer that has had AddRef called on it. Used by the service
111 : * manager only.
112 : */
113 : static History* GetSingleton();
114 :
115 : template<int N>
116 : already_AddRefed<mozIStorageStatement>
117 5 : GetStatement(const char (&aQuery)[N])
118 : {
119 : // May be invoked on both threads.
120 5 : const mozIStorageConnection* dbConn = GetConstDBConn();
121 5 : NS_ENSURE_TRUE(dbConn, nullptr);
122 5 : return mDB->GetStatement(aQuery);
123 : }
124 :
125 : already_AddRefed<mozIStorageStatement>
126 0 : GetStatement(const nsACString& aQuery)
127 : {
128 : // May be invoked on both threads.
129 0 : const mozIStorageConnection* dbConn = GetConstDBConn();
130 0 : NS_ENSURE_TRUE(dbConn, nullptr);
131 0 : return mDB->GetStatement(aQuery);
132 : }
133 :
134 2 : bool IsShuttingDown() const {
135 2 : return mShuttingDown;
136 : }
137 1 : Mutex& GetShutdownMutex() {
138 1 : return mShutdownMutex;
139 : }
140 :
141 : /**
142 : * Helper function to append a new URI to mRecentlyVisitedURIs. See
143 : * mRecentlyVisitedURIs.
144 : */
145 : void AppendToRecentlyVisitedURIs(nsIURI* aURI);
146 :
147 : private:
148 : virtual ~History();
149 :
150 : void InitMemoryReporter();
151 :
152 : /**
153 : * Obtains a read-write database connection, initializing the connection
154 : * if needed. Must be invoked on the main thread.
155 : */
156 : mozIStorageConnection* GetDBConn();
157 :
158 : /**
159 : * Obtains a read-write database connection, but won't try to initialize it.
160 : * May be invoked on both threads, but first one must invoke GetDBConn() on
161 : * the main-thread at least once.
162 : */
163 : const mozIStorageConnection* GetConstDBConn();
164 :
165 : /**
166 : * The database handle. This is initialized lazily by the first call to
167 : * GetDBConn(), so never use it directly, or, if you really need, always
168 : * invoke GetDBConn() before.
169 : */
170 : RefPtr<mozilla::places::Database> mDB;
171 :
172 : RefPtr<ConcurrentStatementsHolder> mConcurrentStatementsHolder;
173 :
174 : /**
175 : * Remove any memory references to tasks and do not take on any more.
176 : */
177 : void Shutdown();
178 :
179 : static History* gService;
180 :
181 : // Ensures new tasks aren't started on destruction.
182 : bool mShuttingDown;
183 : // This mutex guards mShuttingDown. Code running in other threads that might
184 : // schedule tasks that use the database should grab it and check the value of
185 : // mShuttingDown. If we are already shutting down, the code must gracefully
186 : // avoid using the db. If we are not, the lock will prevent shutdown from
187 : // starting in an unexpected moment.
188 : Mutex mShutdownMutex;
189 :
190 : typedef nsTObserverArray<mozilla::dom::Link* > ObserverArray;
191 :
192 0 : class KeyClass : public nsURIHashKey
193 : {
194 : public:
195 0 : explicit KeyClass(const nsIURI* aURI)
196 0 : : nsURIHashKey(aURI)
197 : {
198 0 : }
199 : KeyClass(const KeyClass& aOther)
200 : : nsURIHashKey(aOther)
201 : {
202 : NS_NOTREACHED("Do not call me!");
203 : }
204 0 : size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
205 : {
206 0 : return array.ShallowSizeOfExcludingThis(aMallocSizeOf);
207 : }
208 : ObserverArray array;
209 : };
210 :
211 : nsTHashtable<KeyClass> mObservers;
212 :
213 : /**
214 : * mRecentlyVisitedURIs remembers URIs which have been recently added to
215 : * history, to avoid saving these locations repeatedly in a short period.
216 : */
217 0 : class RecentURIKey : public nsURIHashKey
218 : {
219 : public:
220 1 : explicit RecentURIKey(const nsIURI* aURI) : nsURIHashKey(aURI)
221 : {
222 1 : }
223 : RecentURIKey(const RecentURIKey& aOther) : nsURIHashKey(aOther)
224 : {
225 : NS_NOTREACHED("Do not call me!");
226 : }
227 : MOZ_INIT_OUTSIDE_CTOR PRTime time;
228 : };
229 : nsTHashtable<RecentURIKey> mRecentlyVisitedURIs;
230 : /**
231 : * Whether aURI has been visited "recently".
232 : * See RECENTLY_VISITED_URIS_MAX_AGE.
233 : */
234 : bool IsRecentlyVisitedURI(nsIURI* aURI);
235 : };
236 :
237 : } // namespace places
238 : } // namespace mozilla
239 :
240 : #endif // mozilla_places_History_h_
|