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

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

Powered by Google App Engine
This is Rietveld 408576698