Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(672)

Side by Side Diff: chrome/browser/history/expire_history_backend.cc

Issue 235863023: Eliminate the archived history database and clean up related code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 #include "chrome/browser/history/expire_history_backend.h" 5 #include "chrome/browser/history/expire_history_backend.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <limits> 9 #include <limits>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/file_util.h" 13 #include "base/file_util.h"
14 #include "base/files/file_enumerator.h" 14 #include "base/files/file_enumerator.h"
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/message_loop/message_loop.h" 16 #include "base/message_loop/message_loop.h"
17 #include "chrome/browser/bookmarks/bookmark_service.h" 17 #include "chrome/browser/bookmarks/bookmark_service.h"
18 #include "chrome/browser/chrome_notification_types.h" 18 #include "chrome/browser/chrome_notification_types.h"
19 #include "chrome/browser/history/archived_database.h"
20 #include "chrome/browser/history/history_database.h" 19 #include "chrome/browser/history/history_database.h"
21 #include "chrome/browser/history/history_notifications.h" 20 #include "chrome/browser/history/history_notifications.h"
22 #include "chrome/browser/history/thumbnail_database.h" 21 #include "chrome/browser/history/thumbnail_database.h"
23 22
24 using base::Time; 23 using base::Time;
25 using base::TimeDelta; 24 using base::TimeDelta;
26 25
27 namespace history { 26 namespace history {
28 27
29 namespace { 28 namespace {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 content::PAGE_TRANSITION_AUTO_SUBFRAME, 86 content::PAGE_TRANSITION_AUTO_SUBFRAME,
88 visits); 87 visits);
89 bool more = static_cast<int>(visits->size()) == max_visits; 88 bool more = static_cast<int>(visits->size()) == max_visits;
90 if (!more) 89 if (!more)
91 db->UpdateEarlyExpirationThreshold(early_end_time); 90 db->UpdateEarlyExpirationThreshold(early_end_time);
92 91
93 return more; 92 return more;
94 } 93 }
95 }; 94 };
96 95
97 // Returns true if this visit is worth archiving. Otherwise, this visit is not
98 // worth saving (for example, subframe navigations and redirects) and we can
99 // just delete it when it gets old.
100 bool ShouldArchiveVisit(const VisitRow& visit) {
101 int no_qualifier = content::PageTransitionStripQualifier(visit.transition);
102
103 // These types of transitions are always "important" and the user will want
104 // to see them.
105 if (no_qualifier == content::PAGE_TRANSITION_TYPED ||
106 no_qualifier == content::PAGE_TRANSITION_AUTO_BOOKMARK ||
107 no_qualifier == content::PAGE_TRANSITION_AUTO_TOPLEVEL)
108 return true;
109
110 // Only archive these "less important" transitions when they were the final
111 // navigation and not part of a redirect chain.
112 if ((no_qualifier == content::PAGE_TRANSITION_LINK ||
113 no_qualifier == content::PAGE_TRANSITION_FORM_SUBMIT ||
114 no_qualifier == content::PAGE_TRANSITION_KEYWORD ||
115 no_qualifier == content::PAGE_TRANSITION_GENERATED) &&
116 visit.transition & content::PAGE_TRANSITION_CHAIN_END)
117 return true;
118
119 // The transition types we ignore are AUTO_SUBFRAME and MANUAL_SUBFRAME.
120 return false;
121 }
122
123 // The number of visits we will expire very time we check for old items. This 96 // The number of visits we will expire very time we check for old items. This
124 // Prevents us from doing too much work any given time. 97 // Prevents us from doing too much work any given time.
125 const int kNumExpirePerIteration = 32; 98 const int kNumExpirePerIteration = 32;
126 99
127 // The number of seconds between checking for items that should be expired when 100 // The number of seconds between checking for items that should be expired when
128 // we think there might be more items to expire. This timeout is used when the 101 // we think there might be more items to expire. This timeout is used when the
129 // last expiration found at least kNumExpirePerIteration and we want to check 102 // last expiration found at least kNumExpirePerIteration and we want to check
130 // again "soon." 103 // again "soon."
131 const int kExpirationDelaySec = 30; 104 const int kExpirationDelaySec = 30;
132 105
(...skipping 29 matching lines...) Expand all
162 // The list of all favicon urls that were actually deleted from the thumbnail 135 // The list of all favicon urls that were actually deleted from the thumbnail
163 // db. 136 // db.
164 std::set<GURL> expired_favicons; 137 std::set<GURL> expired_favicons;
165 }; 138 };
166 139
167 ExpireHistoryBackend::ExpireHistoryBackend( 140 ExpireHistoryBackend::ExpireHistoryBackend(
168 BroadcastNotificationDelegate* delegate, 141 BroadcastNotificationDelegate* delegate,
169 BookmarkService* bookmark_service) 142 BookmarkService* bookmark_service)
170 : delegate_(delegate), 143 : delegate_(delegate),
171 main_db_(NULL), 144 main_db_(NULL),
172 archived_db_(NULL),
173 thumb_db_(NULL), 145 thumb_db_(NULL),
174 weak_factory_(this), 146 weak_factory_(this),
175 bookmark_service_(bookmark_service) { 147 bookmark_service_(bookmark_service) {
176 } 148 }
177 149
178 ExpireHistoryBackend::~ExpireHistoryBackend() { 150 ExpireHistoryBackend::~ExpireHistoryBackend() {
179 } 151 }
180 152
181 void ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db, 153 void ExpireHistoryBackend::SetDatabases(HistoryDatabase* main_db,
182 ArchivedDatabase* archived_db,
183 ThumbnailDatabase* thumb_db) { 154 ThumbnailDatabase* thumb_db) {
184 main_db_ = main_db; 155 main_db_ = main_db;
185 archived_db_ = archived_db;
186 thumb_db_ = thumb_db; 156 thumb_db_ = thumb_db;
187 } 157 }
188 158
189 void ExpireHistoryBackend::DeleteURL(const GURL& url) { 159 void ExpireHistoryBackend::DeleteURL(const GURL& url) {
190 DeleteURLs(std::vector<GURL>(1, url)); 160 DeleteURLs(std::vector<GURL>(1, url));
191 } 161 }
192 162
193 void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) { 163 void ExpireHistoryBackend::DeleteURLs(const std::vector<GURL>& urls) {
194 if (!main_db_) 164 if (!main_db_)
195 return; 165 return;
196 166
197 DeleteDependencies dependencies; 167 DeleteDependencies dependencies;
198 for (std::vector<GURL>::const_iterator url = urls.begin(); url != urls.end(); 168 for (std::vector<GURL>::const_iterator url = urls.begin(); url != urls.end();
199 ++url) { 169 ++url) {
200 URLRow url_row; 170 URLRow url_row;
201 if (!main_db_->GetRowForURL(*url, &url_row)) 171 if (!main_db_->GetRowForURL(*url, &url_row))
202 continue; // Nothing to delete. 172 continue; // Nothing to delete.
203 173
204 // Collect all the visits and delete them. Note that we don't give 174 // Collect all the visits and delete them. Note that we don't give
205 // up if there are no visits, since the URL could still have an 175 // up if there are no visits, since the URL could still have an
206 // entry that we should delete. TODO(brettw): bug 1171148: We 176 // entry that we should delete.
207 // should also delete from the archived DB.
208 VisitVector visits; 177 VisitVector visits;
209 main_db_->GetVisitsForURL(url_row.id(), &visits); 178 main_db_->GetVisitsForURL(url_row.id(), &visits);
210 179
211 DeleteVisitRelatedInfo(visits, &dependencies); 180 DeleteVisitRelatedInfo(visits, &dependencies);
212 181
213 // We skip ExpireURLsForVisits (since we are deleting from the 182 // We skip ExpireURLsForVisits (since we are deleting from the
214 // URL, and not starting with visits in a given time range). We 183 // URL, and not starting with visits in a given time range). We
215 // therefore need to call the deletion and favicon update 184 // therefore need to call the deletion and favicon update
216 // functions manually. 185 // functions manually.
217 186
218 BookmarkService* bookmark_service = GetBookmarkService(); 187 BookmarkService* bookmark_service = GetBookmarkService();
219 bool is_bookmarked = 188 bool is_bookmarked =
220 (bookmark_service && bookmark_service->IsBookmarked(*url)); 189 (bookmark_service && bookmark_service->IsBookmarked(*url));
221 190
222 DeleteOneURL(url_row, is_bookmarked, &dependencies); 191 DeleteOneURL(url_row, is_bookmarked, &dependencies);
223 } 192 }
224 193
225 DeleteFaviconsIfPossible(dependencies.affected_favicons, 194 DeleteFaviconsIfPossible(dependencies.affected_favicons,
226 &dependencies.expired_favicons); 195 &dependencies.expired_favicons);
227 196
228 BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED); 197 BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED);
229 } 198 }
230 199
231 void ExpireHistoryBackend::ExpireHistoryBetween( 200 void ExpireHistoryBackend::ExpireHistoryBetween(
232 const std::set<GURL>& restrict_urls, Time begin_time, Time end_time) { 201 const std::set<GURL>& restrict_urls, Time begin_time, Time end_time) {
233 if (!main_db_) 202 if (!main_db_)
234 return; 203 return;
235 204
236 // Find the affected visits and delete them. 205 // Find the affected visits and delete them.
237 // TODO(brettw): bug 1171164: We should query the archived database here, too.
238 VisitVector visits; 206 VisitVector visits;
239 main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits); 207 main_db_->GetAllVisitsInRange(begin_time, end_time, 0, &visits);
240 if (!restrict_urls.empty()) { 208 if (!restrict_urls.empty()) {
241 std::set<URLID> url_ids; 209 std::set<URLID> url_ids;
242 for (std::set<GURL>::const_iterator url = restrict_urls.begin(); 210 for (std::set<GURL>::const_iterator url = restrict_urls.begin();
243 url != restrict_urls.end(); ++url) 211 url != restrict_urls.end(); ++url)
244 url_ids.insert(main_db_->GetRowForURL(*url, NULL)); 212 url_ids.insert(main_db_->GetRowForURL(*url, NULL));
245 VisitVector all_visits; 213 VisitVector all_visits;
246 all_visits.swap(visits); 214 all_visits.swap(visits);
247 for (VisitVector::iterator visit = all_visits.begin(); 215 for (VisitVector::iterator visit = all_visits.begin();
(...skipping 12 matching lines...) Expand all
260 // it. 228 // it.
261 DCHECK( 229 DCHECK(
262 std::adjacent_find( 230 std::adjacent_find(
263 times.begin(), times.end(), std::less_equal<base::Time>()) == 231 times.begin(), times.end(), std::less_equal<base::Time>()) ==
264 times.end()); 232 times.end());
265 233
266 if (!main_db_) 234 if (!main_db_)
267 return; 235 return;
268 236
269 // Find the affected visits and delete them. 237 // Find the affected visits and delete them.
270 // TODO(brettw): bug 1171164: We should query the archived database here, too.
271 VisitVector visits; 238 VisitVector visits;
272 main_db_->GetVisitsForTimes(times, &visits); 239 main_db_->GetVisitsForTimes(times, &visits);
273 ExpireVisits(visits); 240 ExpireVisits(visits);
274 } 241 }
275 242
276 void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) { 243 void ExpireHistoryBackend::ExpireVisits(const VisitVector& visits) {
277 if (visits.empty()) 244 if (visits.empty())
278 return; 245 return;
279 246
280 DeleteDependencies dependencies; 247 DeleteDependencies dependencies;
281 DeleteVisitRelatedInfo(visits, &dependencies); 248 DeleteVisitRelatedInfo(visits, &dependencies);
282 249
283 // Delete or update the URLs affected. We want to update the visit counts 250 // Delete or update the URLs affected. We want to update the visit counts
284 // since this is called by the user who wants to delete their recent history, 251 // since this is called by the user who wants to delete their recent history,
285 // and we don't want to leave any evidence. 252 // and we don't want to leave any evidence.
286 ExpireURLsForVisits(visits, &dependencies); 253 ExpireURLsForVisits(visits, &dependencies);
287 DeleteFaviconsIfPossible(dependencies.affected_favicons, 254 DeleteFaviconsIfPossible(dependencies.affected_favicons,
288 &dependencies.expired_favicons); 255 &dependencies.expired_favicons);
289 256
290 // An is_null begin time means that all history should be deleted. 257 // An is_null begin time means that all history should be deleted.
291 BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED); 258 BroadcastDeleteNotifications(&dependencies, DELETION_USER_INITIATED);
292 259
293 // Pick up any bits possibly left over. 260 // Pick up any bits possibly left over.
294 ParanoidExpireHistory(); 261 ParanoidExpireHistory();
295 } 262 }
296 263
297 void ExpireHistoryBackend::ArchiveHistoryBefore(Time end_time) { 264 void ExpireHistoryBackend::ExpireHistoryBefore(Time end_time) {
298 if (!main_db_) 265 if (!main_db_)
299 return; 266 return;
300 267
301 // Archive as much history as possible before the given date. 268 // Expire all history before the given date.
302 ArchiveSomeOldHistory(end_time, GetAllVisitsReader(), 269 ExpireSomeOldHistory(end_time, GetAllVisitsReader(),
303 std::numeric_limits<int>::max()); 270 std::numeric_limits<int>::max());
304 ParanoidExpireHistory(); 271 ParanoidExpireHistory();
305 } 272 }
306 273
307 void ExpireHistoryBackend::InitWorkQueue() { 274 void ExpireHistoryBackend::InitWorkQueue() {
308 DCHECK(work_queue_.empty()) << "queue has to be empty prior to init"; 275 DCHECK(work_queue_.empty()) << "queue has to be empty prior to init";
309 276
310 for (size_t i = 0; i < readers_.size(); i++) 277 for (size_t i = 0; i < readers_.size(); i++)
311 work_queue_.push(readers_[i]); 278 work_queue_.push(readers_[i]);
312 } 279 }
313 280
314 const ExpiringVisitsReader* ExpireHistoryBackend::GetAllVisitsReader() { 281 const ExpiringVisitsReader* ExpireHistoryBackend::GetAllVisitsReader() {
315 if (!all_visits_reader_) 282 if (!all_visits_reader_)
316 all_visits_reader_.reset(new AllVisitsReader()); 283 all_visits_reader_.reset(new AllVisitsReader());
317 return all_visits_reader_.get(); 284 return all_visits_reader_.get();
318 } 285 }
319 286
320 const ExpiringVisitsReader* 287 const ExpiringVisitsReader*
321 ExpireHistoryBackend::GetAutoSubframeVisitsReader() { 288 ExpireHistoryBackend::GetAutoSubframeVisitsReader() {
322 if (!auto_subframe_visits_reader_) 289 if (!auto_subframe_visits_reader_)
323 auto_subframe_visits_reader_.reset(new AutoSubframeVisitsReader()); 290 auto_subframe_visits_reader_.reset(new AutoSubframeVisitsReader());
324 return auto_subframe_visits_reader_.get(); 291 return auto_subframe_visits_reader_.get();
325 } 292 }
326 293
327 void ExpireHistoryBackend::StartArchivingOldStuff( 294 void ExpireHistoryBackend::StartExpiringOldStuff(
328 TimeDelta expiration_threshold) { 295 TimeDelta expiration_threshold) {
329 expiration_threshold_ = expiration_threshold; 296 expiration_threshold_ = expiration_threshold;
330 297
331 // Remove all readers, just in case this was method was called before. 298 // Remove all readers, just in case this was method was called before.
332 readers_.clear(); 299 readers_.clear();
333 // For now, we explicitly add all known readers. If we come up with more 300 // For now, we explicitly add all known readers. If we come up with more
334 // reader types (in case we want to expire different types of visits in 301 // reader types (in case we want to expire different types of visits in
335 // different ways), we can make it be populated by creator/owner of 302 // different ways), we can make it be populated by creator/owner of
336 // ExpireHistoryBackend. 303 // ExpireHistoryBackend.
337 readers_.push_back(GetAllVisitsReader()); 304 readers_.push_back(GetAllVisitsReader());
338 readers_.push_back(GetAutoSubframeVisitsReader()); 305 readers_.push_back(GetAutoSubframeVisitsReader());
339 306
340 // Initialize the queue with all tasks for the first set of iterations. 307 // Initialize the queue with all tasks for the first set of iterations.
341 InitWorkQueue(); 308 InitWorkQueue();
342 ScheduleArchive(); 309 ScheduleExpire();
343 } 310 }
344 311
345 void ExpireHistoryBackend::DeleteFaviconsIfPossible( 312 void ExpireHistoryBackend::DeleteFaviconsIfPossible(
346 const std::set<chrome::FaviconID>& favicon_set, 313 const std::set<chrome::FaviconID>& favicon_set,
347 std::set<GURL>* expired_favicons) { 314 std::set<GURL>* expired_favicons) {
348 if (!thumb_db_) 315 if (!thumb_db_)
349 return; 316 return;
350 317
351 for (std::set<chrome::FaviconID>::const_iterator i = favicon_set.begin(); 318 for (std::set<chrome::FaviconID>::const_iterator i = favicon_set.begin();
352 i != favicon_set.end(); ++i) { 319 i != favicon_set.end(); ++i) {
(...skipping 12 matching lines...) Expand all
365 332
366 void ExpireHistoryBackend::BroadcastDeleteNotifications( 333 void ExpireHistoryBackend::BroadcastDeleteNotifications(
367 DeleteDependencies* dependencies, DeletionType type) { 334 DeleteDependencies* dependencies, DeletionType type) {
368 if (!dependencies->deleted_urls.empty()) { 335 if (!dependencies->deleted_urls.empty()) {
369 // Broadcast the URL deleted notification. Note that we also broadcast when 336 // Broadcast the URL deleted notification. Note that we also broadcast when
370 // we were requested to delete everything even if that was a NOP, since 337 // we were requested to delete everything even if that was a NOP, since
371 // some components care to know when history is deleted (it's up to them to 338 // some components care to know when history is deleted (it's up to them to
372 // determine if they care whether anything was deleted). 339 // determine if they care whether anything was deleted).
373 scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); 340 scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails);
374 details->all_history = false; 341 details->all_history = false;
375 details->archived = (type == DELETION_ARCHIVED); 342 details->expired = (type == DELETION_EXPIRED);
376 details->rows = dependencies->deleted_urls; 343 details->rows = dependencies->deleted_urls;
377 details->favicon_urls = dependencies->expired_favicons; 344 details->favicon_urls = dependencies->expired_favicons;
378 delegate_->NotifySyncURLsDeleted(false, details->archived, &details->rows); 345 delegate_->NotifySyncURLsDeleted(false, details->expired, &details->rows);
379 delegate_->BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, 346 delegate_->BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
380 details.PassAs<HistoryDetails>()); 347 details.PassAs<HistoryDetails>());
381 } 348 }
382 } 349 }
383 350
384 void ExpireHistoryBackend::DeleteVisitRelatedInfo( 351 void ExpireHistoryBackend::DeleteVisitRelatedInfo(
385 const VisitVector& visits, 352 const VisitVector& visits,
386 DeleteDependencies* dependencies) { 353 DeleteDependencies* dependencies) {
387 for (size_t i = 0; i < visits.size(); i++) { 354 for (size_t i = 0; i < visits.size(); i++) {
388 // Delete the visit itself. 355 // Delete the visit itself.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 } 387 }
421 // Delete the mapping entries for the url. 388 // Delete the mapping entries for the url.
422 thumb_db_->DeleteIconMappings(url_row.url()); 389 thumb_db_->DeleteIconMappings(url_row.url());
423 } 390 }
424 } 391 }
425 // Last, delete the URL entry. 392 // Last, delete the URL entry.
426 main_db_->DeleteURLRow(url_row.id()); 393 main_db_->DeleteURLRow(url_row.id());
427 } 394 }
428 } 395 }
429 396
430 URLID ExpireHistoryBackend::ArchiveOneURL(const URLRow& url_row) {
431 if (!archived_db_)
432 return 0;
433
434 // See if this URL is present in the archived database already. Note that
435 // we must look up by ID since the URL ID will be different.
436 URLRow archived_row;
437 if (archived_db_->GetRowForURL(url_row.url(), &archived_row)) {
438 // TODO(sky): bug 1168470, need to archive past search terms.
439 // TODO(brettw): should be copy the visit counts over? This will mean that
440 // the main DB's visit counts are only for the last 3 months rather than
441 // accumulative.
442 archived_row.set_last_visit(url_row.last_visit());
443 archived_db_->UpdateURLRow(archived_row.id(), archived_row);
444 return archived_row.id();
445 }
446
447 // This row is not in the archived DB, add it.
448 return archived_db_->AddURL(url_row);
449 }
450
451 namespace { 397 namespace {
452 398
453 struct ChangedURL { 399 struct ChangedURL {
454 ChangedURL() : visit_count(0), typed_count(0) {} 400 ChangedURL() : visit_count(0), typed_count(0) {}
455 int visit_count; 401 int visit_count;
456 int typed_count; 402 int typed_count;
457 }; 403 };
458 404
459 } // namespace 405 } // namespace
460 406
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 std::max(0, url_row.visit_count() - i->second.visit_count)); 457 std::max(0, url_row.visit_count() - i->second.visit_count));
512 url_row.set_typed_count( 458 url_row.set_typed_count(
513 std::max(0, url_row.typed_count() - i->second.typed_count)); 459 std::max(0, url_row.typed_count() - i->second.typed_count));
514 460
515 // Update the db with the new details. 461 // Update the db with the new details.
516 main_db_->UpdateURLRow(url_row.id(), url_row); 462 main_db_->UpdateURLRow(url_row.id(), url_row);
517 } 463 }
518 } 464 }
519 } 465 }
520 466
521 void ExpireHistoryBackend::ArchiveURLsAndVisits( 467 void ExpireHistoryBackend::ScheduleExpire() {
522 const VisitVector& visits,
523 DeleteDependencies* dependencies) {
524 if (!archived_db_ || !main_db_)
525 return;
526
527 // Make sure all unique URL rows are added to the dependency list and the
528 // archived database. We will also keep the mapping between the main DB URLID
529 // and the archived one.
530 std::map<URLID, URLID> main_id_to_archived_id;
531 for (size_t i = 0; i < visits.size(); i++) {
532 std::map<URLID, URLRow>::const_iterator found =
533 dependencies->affected_urls.find(visits[i].url_id);
534 if (found == dependencies->affected_urls.end()) {
535 // Unique URL encountered, archive it.
536 URLRow row; // Row in the main DB.
537 URLID archived_id; // ID in the archived DB.
538 if (!main_db_->GetURLRow(visits[i].url_id, &row) ||
539 !(archived_id = ArchiveOneURL(row))) {
540 // Failure archiving, skip this one.
541 continue;
542 }
543
544 // Only add URL to the dependency list once we know we successfully
545 // archived it.
546 main_id_to_archived_id[row.id()] = archived_id;
547 dependencies->affected_urls[row.id()] = row;
548 }
549 }
550
551 // Retrieve the sources for all the archived visits before archiving.
552 // The returned visit_sources vector should contain the source for each visit
553 // from visits at the same index.
554 VisitSourceMap visit_sources;
555 main_db_->GetVisitsSource(visits, &visit_sources);
556
557 // Now archive the visits since we know the URL ID to make them reference.
558 // The source visit list should still reference the visits in the main DB, but
559 // we will update it to reflect only the visits that were successfully
560 // archived.
561 for (size_t i = 0; i < visits.size(); i++) {
562 // Construct the visit that we will add to the archived database. We do
563 // not store referring visits since we delete many of the visits when
564 // archiving.
565 VisitRow cur_visit(visits[i]);
566 cur_visit.url_id = main_id_to_archived_id[cur_visit.url_id];
567 cur_visit.referring_visit = 0;
568 VisitSourceMap::iterator iter = visit_sources.find(visits[i].visit_id);
569 archived_db_->AddVisit(
570 &cur_visit,
571 iter == visit_sources.end() ? SOURCE_BROWSED : iter->second);
572 // Ignore failures, we will delete it from the main DB no matter what.
573 }
574 }
575
576 void ExpireHistoryBackend::ScheduleArchive() {
577 TimeDelta delay; 468 TimeDelta delay;
578 if (work_queue_.empty()) { 469 if (work_queue_.empty()) {
579 // If work queue is empty, reset the work queue to contain all tasks and 470 // If work queue is empty, reset the work queue to contain all tasks and
580 // schedule next iteration after a longer delay. 471 // schedule next iteration after a longer delay.
581 InitWorkQueue(); 472 InitWorkQueue();
582 delay = TimeDelta::FromMinutes(kExpirationEmptyDelayMin); 473 delay = TimeDelta::FromMinutes(kExpirationEmptyDelayMin);
583 } else { 474 } else {
584 delay = TimeDelta::FromSeconds(kExpirationDelaySec); 475 delay = TimeDelta::FromSeconds(kExpirationDelaySec);
585 } 476 }
586 477
587 base::MessageLoop::current()->PostDelayedTask( 478 base::MessageLoop::current()->PostDelayedTask(
588 FROM_HERE, 479 FROM_HERE,
589 base::Bind(&ExpireHistoryBackend::DoArchiveIteration, 480 base::Bind(&ExpireHistoryBackend::DoExpireIteration,
590 weak_factory_.GetWeakPtr()), 481 weak_factory_.GetWeakPtr()),
591 delay); 482 delay);
592 } 483 }
593 484
594 void ExpireHistoryBackend::DoArchiveIteration() { 485 void ExpireHistoryBackend::DoExpireIteration() {
595 DCHECK(!work_queue_.empty()) << "queue has to be non-empty"; 486 DCHECK(!work_queue_.empty()) << "queue has to be non-empty";
596 487
597 const ExpiringVisitsReader* reader = work_queue_.front(); 488 const ExpiringVisitsReader* reader = work_queue_.front();
598 bool more_to_expire = ArchiveSomeOldHistory(GetCurrentArchiveTime(), reader, 489 bool more_to_expire = ExpireSomeOldHistory(GetCurrentExpirationTime(), reader,
599 kNumExpirePerIteration); 490 kNumExpirePerIteration);
600 491
601 work_queue_.pop(); 492 work_queue_.pop();
602 // If there are more items to expire, add the reader back to the queue, thus 493 // If there are more items to expire, add the reader back to the queue, thus
603 // creating a new task for future iterations. 494 // creating a new task for future iterations.
604 if (more_to_expire) 495 if (more_to_expire)
605 work_queue_.push(reader); 496 work_queue_.push(reader);
606 497
607 ScheduleArchive(); 498 ScheduleExpire();
608 } 499 }
609 500
610 bool ExpireHistoryBackend::ArchiveSomeOldHistory( 501 bool ExpireHistoryBackend::ExpireSomeOldHistory(
611 base::Time end_time, 502 base::Time end_time,
612 const ExpiringVisitsReader* reader, 503 const ExpiringVisitsReader* reader,
613 int max_visits) { 504 int max_visits) {
614 if (!main_db_) 505 if (!main_db_)
615 return false; 506 return false;
616 507
617 // Add an extra time unit to given end time, because 508 // Add an extra time unit to given end time, because
618 // GetAllVisitsInRange, et al. queries' end value is non-inclusive. 509 // GetAllVisitsInRange, et al. queries' end value is non-inclusive.
619 Time effective_end_time = 510 Time effective_end_time =
620 Time::FromInternalValue(end_time.ToInternalValue() + 1); 511 Time::FromInternalValue(end_time.ToInternalValue() + 1);
621 512
622 VisitVector affected_visits; 513 VisitVector visits_to_delete;
623 bool more_to_expire = reader->Read(effective_end_time, main_db_, 514 bool more_to_expire = reader->Read(effective_end_time, main_db_,
624 &affected_visits, max_visits); 515 &visits_to_delete, max_visits);
625 516
626 // Some visits we'll delete while others we'll archive. 517 DeleteDependencies dependencies;
627 VisitVector deleted_visits, archived_visits; 518 DeleteVisitRelatedInfo(visits_to_delete, &dependencies);
628 for (size_t i = 0; i < affected_visits.size(); i++) { 519 ExpireURLsForVisits(visits_to_delete, &dependencies);
629 if (ShouldArchiveVisit(affected_visits[i])) 520 DeleteFaviconsIfPossible(dependencies.affected_favicons,
630 archived_visits.push_back(affected_visits[i]); 521 &dependencies.expired_favicons);
631 else
632 deleted_visits.push_back(affected_visits[i]);
633 }
634 522
635 // Do the actual archiving. 523 BroadcastDeleteNotifications(&dependencies, DELETION_EXPIRED);
636 DeleteDependencies archived_dependencies;
637 ArchiveURLsAndVisits(archived_visits, &archived_dependencies);
638 DeleteVisitRelatedInfo(archived_visits, &archived_dependencies);
639
640 DeleteDependencies deleted_dependencies;
641 DeleteVisitRelatedInfo(deleted_visits, &deleted_dependencies);
642
643 // This will remove or archive all the affected URLs. Must do the deleting
644 // cleanup before archiving so the delete dependencies structure references
645 // only those URLs that were actually deleted instead of having some visits
646 // archived and then the rest deleted.
647 ExpireURLsForVisits(deleted_visits, &deleted_dependencies);
648 ExpireURLsForVisits(archived_visits, &archived_dependencies);
649
650 // Create a union of all affected favicons (we don't store favicons for
651 // archived URLs) and delete them.
652 std::set<chrome::FaviconID> affected_favicons(
653 archived_dependencies.affected_favicons);
654 for (std::set<chrome::FaviconID>::const_iterator i =
655 deleted_dependencies.affected_favicons.begin();
656 i != deleted_dependencies.affected_favicons.end(); ++i) {
657 affected_favicons.insert(*i);
658 }
659 DeleteFaviconsIfPossible(affected_favicons,
660 &deleted_dependencies.expired_favicons);
661
662 // Send notifications for the stuff that was deleted. These won't normally be
663 // in history views since they were subframes, but they will be in the visited
664 // link system, which needs to be updated now. This function is smart enough
665 // to not do anything if nothing was deleted.
666 BroadcastDeleteNotifications(&deleted_dependencies, DELETION_ARCHIVED);
667 524
668 return more_to_expire; 525 return more_to_expire;
669 } 526 }
670 527
671 void ExpireHistoryBackend::ParanoidExpireHistory() { 528 void ExpireHistoryBackend::ParanoidExpireHistory() {
672 // TODO(brettw): Bug 1067331: write this to clean up any errors. 529 // TODO(brettw): Bug 1067331: write this to clean up any errors.
673 } 530 }
674 531
675 BookmarkService* ExpireHistoryBackend::GetBookmarkService() { 532 BookmarkService* ExpireHistoryBackend::GetBookmarkService() {
676 // We use the bookmark service to determine if a URL is bookmarked. The 533 // We use the bookmark service to determine if a URL is bookmarked. The
677 // bookmark service is loaded on a separate thread and may not be done by the 534 // bookmark service is loaded on a separate thread and may not be done by the
678 // time we get here. We therefor block until the bookmarks have finished 535 // time we get here. We therefor block until the bookmarks have finished
679 // loading. 536 // loading.
680 if (bookmark_service_) 537 if (bookmark_service_)
681 bookmark_service_->BlockTillLoaded(); 538 bookmark_service_->BlockTillLoaded();
682 return bookmark_service_; 539 return bookmark_service_;
683 } 540 }
684 541
685 } // namespace history 542 } // namespace history
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698