OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ | 5 #ifndef CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ |
6 #define CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ | 6 #define CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ |
7 | 7 |
8 #include <queue> | 8 #include <queue> |
9 #include <set> | 9 #include <set> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/gtest_prod_util.h" | 13 #include "base/gtest_prod_util.h" |
14 #include "base/memory/scoped_ptr.h" | 14 #include "base/memory/scoped_ptr.h" |
15 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
17 #include "chrome/browser/history/history_types.h" | 17 #include "chrome/browser/history/history_types.h" |
18 | 18 |
19 class GURL; | 19 class GURL; |
20 class TestingProfile; | 20 class TestingProfile; |
21 | 21 |
22 namespace history { | 22 namespace history { |
23 | 23 |
24 class ArchivedDatabase; | |
25 class HistoryClient; | 24 class HistoryClient; |
26 class HistoryDatabase; | 25 class HistoryDatabase; |
27 struct HistoryDetails; | 26 struct HistoryDetails; |
28 class ThumbnailDatabase; | 27 class ThumbnailDatabase; |
29 | 28 |
30 // Delegate used to broadcast notifications to the main thread. | 29 // Delegate used to broadcast notifications to the main thread. |
31 class BroadcastNotificationDelegate { | 30 class BroadcastNotificationDelegate { |
32 public: | 31 public: |
33 // Schedules a broadcast of the given notification on the application main | 32 // Schedules a broadcast of the given notification on the application main |
34 // thread. | 33 // thread. |
35 virtual void BroadcastNotifications(int type, | 34 virtual void BroadcastNotifications(int type, |
36 scoped_ptr<HistoryDetails> details) = 0; | 35 scoped_ptr<HistoryDetails> details) = 0; |
37 | 36 |
38 // Tells typed url sync code to handle URL modifications or deletions. | 37 // Tells typed url sync code to handle URL modifications or deletions. |
39 virtual void NotifySyncURLsModified(URLRows* rows) = 0; | 38 virtual void NotifySyncURLsModified(URLRows* rows) = 0; |
40 virtual void NotifySyncURLsDeleted(bool all_history, | 39 virtual void NotifySyncURLsDeleted(bool all_history, |
41 bool archived, | 40 bool expired, |
42 URLRows* rows) = 0; | 41 URLRows* rows) = 0; |
43 | 42 |
44 protected: | 43 protected: |
45 virtual ~BroadcastNotificationDelegate() {} | 44 virtual ~BroadcastNotificationDelegate() {} |
46 }; | 45 }; |
47 | 46 |
48 // Encapsulates visit expiration criteria and type of visits to expire. | 47 // Encapsulates visit expiration criteria and type of visits to expire. |
49 class ExpiringVisitsReader { | 48 class ExpiringVisitsReader { |
50 public: | 49 public: |
51 virtual ~ExpiringVisitsReader() {} | 50 virtual ~ExpiringVisitsReader() {} |
52 // Populates |visits| from |db|, using provided |end_time| and |max_visits| | 51 // Populates |visits| from |db|, using provided |end_time| and |max_visits| |
53 // cap. | 52 // cap. |
54 virtual bool Read(base::Time end_time, HistoryDatabase* db, | 53 virtual bool Read(base::Time end_time, HistoryDatabase* db, |
55 VisitVector* visits, int max_visits) const = 0; | 54 VisitVector* visits, int max_visits) const = 0; |
56 }; | 55 }; |
57 | 56 |
58 typedef std::vector<const ExpiringVisitsReader*> ExpiringVisitsReaders; | 57 typedef std::vector<const ExpiringVisitsReader*> ExpiringVisitsReaders; |
59 | 58 |
60 // Helper component to HistoryBackend that manages expiration and deleting of | 59 // Helper component to HistoryBackend that manages expiration and deleting of |
61 // history, as well as moving data from the main database to the archived | 60 // history. |
62 // database as it gets old. | |
63 // | 61 // |
64 // It will automatically start periodically archiving old history once you call | 62 // It will automatically start periodically expiring old history once you call |
65 // StartArchivingOldStuff(). | 63 // StartExpiringOldStuff(). |
66 class ExpireHistoryBackend { | 64 class ExpireHistoryBackend { |
67 public: | 65 public: |
68 // The delegate pointer must be non-NULL. We will NOT take ownership of it. | 66 // The delegate pointer must be non-NULL. We will NOT take ownership of it. |
69 // HistoryClient may be NULL. The HistoryClient is used when expiring URLS so | 67 // HistoryClient may be NULL. The HistoryClient is used when expiring URLS so |
70 // that we don't remove any URLs or favicons that are bookmarked (visits are | 68 // that we don't remove any URLs or favicons that are bookmarked (visits are |
71 // removed though). | 69 // removed though). |
72 ExpireHistoryBackend(BroadcastNotificationDelegate* delegate, | 70 ExpireHistoryBackend(BroadcastNotificationDelegate* delegate, |
73 HistoryClient* history_client); | 71 HistoryClient* history_client); |
74 ~ExpireHistoryBackend(); | 72 ~ExpireHistoryBackend(); |
75 | 73 |
76 // Completes initialization by setting the databases that this class will use. | 74 // Completes initialization by setting the databases that this class will use. |
77 void SetDatabases(HistoryDatabase* main_db, | 75 void SetDatabases(HistoryDatabase* main_db, |
78 ArchivedDatabase* archived_db, | |
79 ThumbnailDatabase* thumb_db); | 76 ThumbnailDatabase* thumb_db); |
80 | 77 |
81 // Begins periodic expiration of history older than the given threshold. This | 78 // Begins periodic expiration of history older than the given threshold. This |
82 // will continue until the object is deleted. | 79 // will continue until the object is deleted. |
83 void StartArchivingOldStuff(base::TimeDelta expiration_threshold); | 80 void StartExpiringOldStuff(base::TimeDelta expiration_threshold); |
84 | 81 |
85 // Deletes everything associated with a URL. | 82 // Deletes everything associated with a URL. |
86 void DeleteURL(const GURL& url); | 83 void DeleteURL(const GURL& url); |
87 | 84 |
88 // Deletes everything associated with each URL in the list. | 85 // Deletes everything associated with each URL in the list. |
89 void DeleteURLs(const std::vector<GURL>& url); | 86 void DeleteURLs(const std::vector<GURL>& url); |
90 | 87 |
91 // Removes all visits to restrict_urls (or all URLs if empty) in the given | 88 // Removes all visits to restrict_urls (or all URLs if empty) in the given |
92 // time range, updating the URLs accordingly. | 89 // time range, updating the URLs accordingly. |
93 void ExpireHistoryBetween(const std::set<GURL>& restrict_urls, | 90 void ExpireHistoryBetween(const std::set<GURL>& restrict_urls, |
94 base::Time begin_time, base::Time end_time); | 91 base::Time begin_time, base::Time end_time); |
95 | 92 |
96 // Removes all visits to all URLs with the given times, updating the | 93 // Removes all visits to all URLs with the given times, updating the |
97 // URLs accordingly. |times| must be in reverse chronological order | 94 // URLs accordingly. |times| must be in reverse chronological order |
98 // and not contain any duplicates. | 95 // and not contain any duplicates. |
99 void ExpireHistoryForTimes(const std::vector<base::Time>& times); | 96 void ExpireHistoryForTimes(const std::vector<base::Time>& times); |
100 | 97 |
101 // Removes the given list of visits, updating the URLs accordingly (similar to | 98 // Removes the given list of visits, updating the URLs accordingly (similar to |
102 // ExpireHistoryBetween(), but affecting a specific set of visits). | 99 // ExpireHistoryBetween(), but affecting a specific set of visits). |
103 void ExpireVisits(const VisitVector& visits); | 100 void ExpireVisits(const VisitVector& visits); |
104 | 101 |
105 // Archives all visits before and including the given time, updating the URLs | 102 // Expires all visits before and including the given time, updating the URLs |
106 // accordingly. This function is intended for migrating old databases | 103 // accordingly. Currently only used for testing. |
107 // (which encompased all time) to the tiered structure and testing, and | 104 void ExpireHistoryBefore(base::Time end_time); |
108 // probably isn't useful for anything else. | |
109 void ArchiveHistoryBefore(base::Time end_time); | |
110 | 105 |
111 // Returns the current time that we are archiving stuff to. This will return | 106 // Returns the current cut-off time before which we will start expiring stuff. |
112 // the threshold in absolute time rather than a delta, so the caller should | 107 // Note that this as an absolute time rather than a delta, so the caller |
113 // not save it. | 108 // should not save it. |
114 base::Time GetCurrentArchiveTime() const { | 109 base::Time GetCurrentExpirationTime() const { |
115 return base::Time::Now() - expiration_threshold_; | 110 return base::Time::Now() - expiration_threshold_; |
116 } | 111 } |
117 | 112 |
118 private: | 113 private: |
119 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, DeleteFaviconsIfPossible); | 114 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, DeleteFaviconsIfPossible); |
120 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ArchiveSomeOldHistory); | 115 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpireSomeOldHistory); |
121 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpiringVisitsReader); | 116 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpiringVisitsReader); |
122 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ArchiveSomeOldHistoryWithSource); | 117 FRIEND_TEST_ALL_PREFIXES(ExpireHistoryTest, ExpireSomeOldHistoryWithSource); |
123 friend class ::TestingProfile; | 118 friend class ::TestingProfile; |
124 | 119 |
125 struct DeleteEffects { | 120 struct DeleteEffects { |
126 DeleteEffects(); | 121 DeleteEffects(); |
127 ~DeleteEffects(); | 122 ~DeleteEffects(); |
128 | 123 |
129 // The time range affected. These can be is_null() to be unbounded in one | 124 // The time range affected. These can be is_null() to be unbounded in one |
130 // or both directions. | 125 // or both directions. |
131 base::Time begin_time, end_time; | 126 base::Time begin_time, end_time; |
132 | 127 |
(...skipping 14 matching lines...) Expand all Loading... |
147 // All favicon urls that were actually deleted from the thumbnail db. | 142 // All favicon urls that were actually deleted from the thumbnail db. |
148 std::set<GURL> deleted_favicons; | 143 std::set<GURL> deleted_favicons; |
149 }; | 144 }; |
150 | 145 |
151 // Deletes the visit-related stuff for all the visits in the given list, and | 146 // Deletes the visit-related stuff for all the visits in the given list, and |
152 // adds the rows for unique URLs affected to the affected_urls list in | 147 // adds the rows for unique URLs affected to the affected_urls list in |
153 // the dependencies structure. | 148 // the dependencies structure. |
154 void DeleteVisitRelatedInfo(const VisitVector& visits, | 149 void DeleteVisitRelatedInfo(const VisitVector& visits, |
155 DeleteEffects* effects); | 150 DeleteEffects* effects); |
156 | 151 |
157 // Moves the given visits from the main database to the archived one. | |
158 void ArchiveVisits(const VisitVector& visits); | |
159 | |
160 // Finds or deletes dependency information for the given URL. Information that | 152 // Finds or deletes dependency information for the given URL. Information that |
161 // is specific to this URL (URL row, thumbnails, etc.) is deleted. | 153 // is specific to this URL (URL row, thumbnails, etc.) is deleted. |
162 // | 154 // |
163 // This does not affect the visits! This is used for expiration as well as | 155 // This does not affect the visits! This is used for expiration as well as |
164 // deleting from the UI, and they handle visits differently. | 156 // deleting from the UI, and they handle visits differently. |
165 // | 157 // |
166 // Other information will be collected and returned in the output containers. | 158 // Other information will be collected and returned in the output containers. |
167 // This includes some of the things deleted that are needed elsewhere, plus | 159 // This includes some of the things deleted that are needed elsewhere, plus |
168 // some things like favicons that could be shared by many URLs, and need to | 160 // some things like favicons that could be shared by many URLs, and need to |
169 // be checked for deletion (this allows us to delete many URLs with only one | 161 // be checked for deletion (this allows us to delete many URLs with only one |
170 // check for shared information at the end). | 162 // check for shared information at the end). |
171 // | 163 // |
172 // Assumes the main_db_ is non-NULL. | 164 // Assumes the main_db_ is non-NULL. |
173 // | 165 // |
174 // NOTE: If the url is bookmarked only the segments and text db are updated, | 166 // NOTE: If the url is bookmarked only the segments and text db are updated, |
175 // everything else is unchanged. This is done so that bookmarks retain their | 167 // everything else is unchanged. This is done so that bookmarks retain their |
176 // favicons and thumbnails. | 168 // favicons and thumbnails. |
177 void DeleteOneURL(const URLRow& url_row, | 169 void DeleteOneURL(const URLRow& url_row, |
178 bool is_bookmarked, | 170 bool is_bookmarked, |
179 DeleteEffects* effects); | 171 DeleteEffects* effects); |
180 | 172 |
181 // Adds or merges the given URL row with the archived database, returning the | |
182 // ID of the URL in the archived database, or 0 on failure. The main (source) | |
183 // database will not be affected (the URL will have to be deleted later). | |
184 // | |
185 // Assumes the archived database is not NULL. | |
186 URLID ArchiveOneURL(const URLRow& url_row); | |
187 | |
188 // Deletes all the URLs in the given vector and handles their dependencies. | 173 // Deletes all the URLs in the given vector and handles their dependencies. |
189 // This will delete starred URLs | 174 // This will delete starred URLs |
190 void DeleteURLs(const URLRows& urls, DeleteEffects* effects); | 175 void DeleteURLs(const URLRows& urls, DeleteEffects* effects); |
191 | 176 |
192 // Expiration involves removing visits, then propagating the visits out from | 177 // Expiration involves removing visits, then propagating the visits out from |
193 // there and delete any orphaned URLs. These will be added to the deleted URLs | 178 // there and delete any orphaned URLs. These will be added to the deleted URLs |
194 // field of the dependencies and DeleteOneURL will handle deleting out from | 179 // field of the dependencies and DeleteOneURL will handle deleting out from |
195 // there. This function does not handle favicons. | 180 // there. This function does not handle favicons. |
196 // | 181 // |
197 // When a URL is not deleted and |archive| is not set, the last visit time and | 182 // When a URL is not deleted, the last visit time and the visit and typed |
198 // the visit and typed counts will be updated (we want to clear these when a | 183 // counts will be updated. |
199 // user is deleting history manually, but not when we're normally expiring old | |
200 // things from history). | |
201 // | 184 // |
202 // The visits in the given vector should have already been deleted from the | 185 // The visits in the given vector should have already been deleted from the |
203 // database, and the list of affected URLs already be filled into | 186 // database, and the list of affected URLs already be filled into |
204 // |depenencies->affected_urls|. | 187 // |depenencies->affected_urls|. |
205 // | 188 // |
206 // Starred URLs will not be deleted. The information in the dependencies that | 189 // Starred URLs will not be deleted. The information in the dependencies that |
207 // DeleteOneURL fills in will be updated, and this function will also delete | 190 // DeleteOneURL fills in will be updated, and this function will also delete |
208 // any now-unused favicons. | 191 // any now-unused favicons. |
209 void ExpireURLsForVisits(const VisitVector& visits, DeleteEffects* effects); | 192 void ExpireURLsForVisits(const VisitVector& visits, DeleteEffects* effects); |
210 | 193 |
211 // Creates entries in the archived database for the unique URLs referenced | 194 // Deletes the favicons listed in |effects->affected_favicons| if they are |
212 // by the given visits. It will then add versions of the visits to that | 195 // unsued. Fails silently (we don't care about favicons so much, so don't want |
213 // database. The source database WILL NOT BE MODIFIED. The source URLs and | 196 // to stop everything if it fails). Fills |expired_favicons| with the set of |
214 // visits will have to be deleted in another pass. | 197 // favicon urls that no longer have associated visits and were therefore |
215 void ArchiveURLsAndVisits(const VisitVector& visits); | 198 // expired. |
216 | |
217 // Deletes the favicons listed in effects->affected_favicons if unused. | |
218 // Fills effects->deleted_favicons with the set of favicon urls that were | |
219 // actually deleted. | |
220 void DeleteFaviconsIfPossible(DeleteEffects* effects); | 199 void DeleteFaviconsIfPossible(DeleteEffects* effects); |
221 | 200 |
222 // Enum representing what type of action resulted in the history DB deletion. | 201 // Enum representing what type of action resulted in the history DB deletion. |
223 enum DeletionType { | 202 enum DeletionType { |
224 // User initiated the deletion from the History UI. | 203 // User initiated the deletion from the History UI. |
225 DELETION_USER_INITIATED, | 204 DELETION_USER_INITIATED, |
226 // History data was automatically archived due to being more than 90 days | 205 // History data was automatically expired due to being more than 90 days |
227 // old. | 206 // old. |
228 DELETION_ARCHIVED | 207 DELETION_EXPIRED |
229 }; | 208 }; |
230 | 209 |
231 // Broadcasts URL modified and deleted notifications. | 210 // Broadcasts URL modified and deleted notifications. |
232 void BroadcastNotifications(DeleteEffects* effects, DeletionType type); | 211 void BroadcastNotifications(DeleteEffects* effects, DeletionType type); |
233 | 212 |
234 // Schedules a call to DoArchiveIteration. | 213 // Schedules a call to DoExpireIteration. |
235 void ScheduleArchive(); | 214 void ScheduleExpire(); |
236 | 215 |
237 // Calls ArchiveSomeOldHistory to expire some amount of old history, according | 216 // Calls ExpireSomeOldHistory to expire some amount of old history, according |
238 // to the items in work queue, and schedules another call to happen in the | 217 // to the items in work queue, and schedules another call to happen in the |
239 // future. | 218 // future. |
240 void DoArchiveIteration(); | 219 void DoExpireIteration(); |
241 | 220 |
242 // Tries to expire the oldest |max_visits| visits from history that are older | 221 // Tries to expire the oldest |max_visits| visits from history that are older |
243 // than |time_threshold|. The return value indicates if we think there might | 222 // than |time_threshold|. The return value indicates if we think there might |
244 // be more history to expire with the current time threshold (it does not | 223 // be more history to expire with the current time threshold (it does not |
245 // indicate success or failure). | 224 // indicate success or failure). |
246 bool ArchiveSomeOldHistory(base::Time end_time, | 225 bool ExpireSomeOldHistory(base::Time end_time, |
247 const ExpiringVisitsReader* reader, | 226 const ExpiringVisitsReader* reader, |
248 int max_visits); | 227 int max_visits); |
249 | 228 |
250 // Tries to detect possible bad history or inconsistencies in the database | 229 // Tries to detect possible bad history or inconsistencies in the database |
251 // and deletes items. For example, URLs with no visits. | 230 // and deletes items. For example, URLs with no visits. |
252 void ParanoidExpireHistory(); | 231 void ParanoidExpireHistory(); |
253 | 232 |
254 // Returns the HistoryClient, blocking until the bookmarks are loaded. This | 233 // Returns the HistoryClient, blocking until the bookmarks are loaded. This |
255 // may return NULL during testing. | 234 // may return NULL during testing. |
256 HistoryClient* GetHistoryClient(); | 235 HistoryClient* GetHistoryClient(); |
257 | 236 |
258 // Initializes periodic expiration work queue by populating it with with tasks | 237 // Initializes periodic expiration work queue by populating it with with tasks |
259 // for all known readers. | 238 // for all known readers. |
260 void InitWorkQueue(); | 239 void InitWorkQueue(); |
261 | 240 |
262 // Returns the reader for all visits. This method is only used by the unit | 241 // Returns the reader for all visits. This method is only used by the unit |
263 // tests. | 242 // tests. |
264 const ExpiringVisitsReader* GetAllVisitsReader(); | 243 const ExpiringVisitsReader* GetAllVisitsReader(); |
265 | 244 |
266 // Returns the reader for AUTO_SUBFRAME visits. This method is only used by | 245 // Returns the reader for AUTO_SUBFRAME visits. This method is only used by |
267 // the unit tests. | 246 // the unit tests. |
268 const ExpiringVisitsReader* GetAutoSubframeVisitsReader(); | 247 const ExpiringVisitsReader* GetAutoSubframeVisitsReader(); |
269 | 248 |
270 // Non-owning pointer to the notification delegate (guaranteed non-NULL). | 249 // Non-owning pointer to the notification delegate (guaranteed non-NULL). |
271 BroadcastNotificationDelegate* delegate_; | 250 BroadcastNotificationDelegate* delegate_; |
272 | 251 |
273 // Non-owning pointers to the databases we deal with (MAY BE NULL). | 252 // Non-owning pointers to the databases we deal with (MAY BE NULL). |
274 HistoryDatabase* main_db_; // Main history database. | 253 HistoryDatabase* main_db_; // Main history database. |
275 ArchivedDatabase* archived_db_; // Old history. | |
276 ThumbnailDatabase* thumb_db_; // Thumbnails and favicons. | 254 ThumbnailDatabase* thumb_db_; // Thumbnails and favicons. |
277 | 255 |
278 // Used to generate runnable methods to do timers on this class. They will be | 256 // Used to generate runnable methods to do timers on this class. They will be |
279 // automatically canceled when this class is deleted. | 257 // automatically canceled when this class is deleted. |
280 base::WeakPtrFactory<ExpireHistoryBackend> weak_factory_; | 258 base::WeakPtrFactory<ExpireHistoryBackend> weak_factory_; |
281 | 259 |
282 // The threshold for "old" history where we will automatically expire it to | 260 // The threshold for "old" history where we will automatically delete it. |
283 // the archived database. | |
284 base::TimeDelta expiration_threshold_; | 261 base::TimeDelta expiration_threshold_; |
285 | 262 |
286 // List of all distinct types of readers. This list is used to populate the | 263 // List of all distinct types of readers. This list is used to populate the |
287 // work queue. | 264 // work queue. |
288 ExpiringVisitsReaders readers_; | 265 ExpiringVisitsReaders readers_; |
289 | 266 |
290 // Work queue for periodic expiration tasks, used by DoArchiveIteration() to | 267 // Work queue for periodic expiration tasks, used by DoExpireIteration() to |
291 // determine what to do at an iteration, as well as populate it for future | 268 // determine what to do at an iteration, as well as populate it for future |
292 // iterations. | 269 // iterations. |
293 std::queue<const ExpiringVisitsReader*> work_queue_; | 270 std::queue<const ExpiringVisitsReader*> work_queue_; |
294 | 271 |
295 // Readers for various types of visits. | 272 // Readers for various types of visits. |
296 // TODO(dglazkov): If you are adding another one, please consider reorganizing | 273 // TODO(dglazkov): If you are adding another one, please consider reorganizing |
297 // into a map. | 274 // into a map. |
298 scoped_ptr<ExpiringVisitsReader> all_visits_reader_; | 275 scoped_ptr<ExpiringVisitsReader> all_visits_reader_; |
299 scoped_ptr<ExpiringVisitsReader> auto_subframe_visits_reader_; | 276 scoped_ptr<ExpiringVisitsReader> auto_subframe_visits_reader_; |
300 | 277 |
301 // The HistoryClient; may be NULL. | 278 // The HistoryClient; may be NULL. |
302 // | 279 // |
303 // Use GetHistoryClient to access this, which makes sure the bookmarks are | 280 // Use GetHistoryClient to access this, which makes sure the bookmarks are |
304 // loaded before returning. | 281 // loaded before returning. |
305 HistoryClient* history_client_; | 282 HistoryClient* history_client_; |
306 | 283 |
307 DISALLOW_COPY_AND_ASSIGN(ExpireHistoryBackend); | 284 DISALLOW_COPY_AND_ASSIGN(ExpireHistoryBackend); |
308 }; | 285 }; |
309 | 286 |
310 } // namespace history | 287 } // namespace history |
311 | 288 |
312 #endif // CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ | 289 #endif // CHROME_BROWSER_HISTORY_EXPIRE_HISTORY_BACKEND_H_ |
OLD | NEW |