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

Side by Side Diff: chrome/browser/history/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/history_backend.h" 5 #include "chrome/browser/history/history_backend.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 #include <list> 9 #include <list>
10 #include <map> 10 #include <map>
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
46 #include "url/gurl.h" 46 #include "url/gurl.h"
47 47
48 #if defined(OS_ANDROID) 48 #if defined(OS_ANDROID)
49 #include "chrome/browser/history/android/android_provider_backend.h" 49 #include "chrome/browser/history/android/android_provider_backend.h"
50 #endif 50 #endif
51 51
52 using base::Time; 52 using base::Time;
53 using base::TimeDelta; 53 using base::TimeDelta;
54 using base::TimeTicks; 54 using base::TimeTicks;
55 55
56 /* The HistoryBackend consists of a number of components: 56 /* The HistoryBackend consists of two components:
57 57
58 HistoryDatabase (stores past 3 months of history) 58 HistoryDatabase (stores past 3 months of history)
59 URLDatabase (stores a list of URLs) 59 URLDatabase (stores a list of URLs)
60 DownloadDatabase (stores a list of downloads) 60 DownloadDatabase (stores a list of downloads)
61 VisitDatabase (stores a list of visits for the URLs) 61 VisitDatabase (stores a list of visits for the URLs)
62 VisitSegmentDatabase (stores groups of URLs for the most visited view). 62 VisitSegmentDatabase (stores groups of URLs for the most visited view).
63 63
64 ArchivedDatabase (stores history older than 3 months) 64 ExpireHistoryBackend (manages deleting things older than 3 months)
65 URLDatabase (stores a list of URLs)
66 DownloadDatabase (stores a list of downloads)
67 VisitDatabase (stores a list of visits for the URLs)
68
69 (this does not store visit segments as they expire after 3 mos.)
70
71 ExpireHistoryBackend (manages moving things from HistoryDatabase to
72 the ArchivedDatabase and deleting)
73 */ 65 */
74 66
75 namespace history { 67 namespace history {
76 68
77 // How long we keep segment data for in days. Currently 3 months. 69 // How long we keep segment data for in days. Currently 3 months.
78 // This value needs to be greater or equal to 70 // This value needs to be greater or equal to
79 // MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct 71 // MostVisitedModel::kMostVisitedScope but we don't want to introduce a direct
80 // dependency between MostVisitedModel and the history backend. 72 // dependency between MostVisitedModel and the history backend.
81 const int kSegmentDataRetention = 90; 73 const int kSegmentDataRetention = 90;
82 74
83 // How long we'll wait to do a commit, so that things are batched together. 75 // How long we'll wait to do a commit, so that things are batched together.
84 const int kCommitIntervalSeconds = 10; 76 const int kCommitIntervalSeconds = 10;
85 77
86 // The amount of time before we re-fetch the favicon. 78 // The amount of time before we re-fetch the favicon.
87 const int kFaviconRefetchDays = 7; 79 const int kFaviconRefetchDays = 7;
88 80
89 // The maximum number of items we'll allow in the redirect list before 81 // The maximum number of items we'll allow in the redirect list before
90 // deleting some. 82 // deleting some.
91 const int kMaxRedirectCount = 32; 83 const int kMaxRedirectCount = 32;
92 84
93 // The number of days old a history entry can be before it is considered "old" 85 // The number of days old a history entry can be before it is considered "old"
94 // and is archived. 86 // and is deleted.
95 const int kArchiveDaysThreshold = 90; 87 const int kExpireDaysThreshold = 90;
96 88
97 #if defined(OS_ANDROID) 89 #if defined(OS_ANDROID)
98 // The maximum number of top sites to track when recording top page visit stats. 90 // The maximum number of top sites to track when recording top page visit stats.
99 const size_t kPageVisitStatsMaxTopSites = 50; 91 const size_t kPageVisitStatsMaxTopSites = 50;
100 #endif 92 #endif
101 93
102 // Converts from PageUsageData to MostVisitedURL. |redirects| is a 94 // Converts from PageUsageData to MostVisitedURL. |redirects| is a
103 // list of redirects for this URL. Empty list means no redirects. 95 // list of redirects for this URL. Empty list means no redirects.
104 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data, 96 MostVisitedURL MakeMostVisitedURL(const PageUsageData& page_data,
105 const RedirectList& redirects) { 97 const RedirectList& redirects) {
(...skipping 504 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 if (thumbnail_db_->Init(thumbnail_name) != sql::INIT_OK) { 602 if (thumbnail_db_->Init(thumbnail_name) != sql::INIT_OK) {
611 // Unlike the main database, we don't error out when the database is too 603 // Unlike the main database, we don't error out when the database is too
612 // new because this error is much less severe. Generally, this shouldn't 604 // new because this error is much less severe. Generally, this shouldn't
613 // happen since the thumbnail and main database versions should be in sync. 605 // happen since the thumbnail and main database versions should be in sync.
614 // We'll just continue without thumbnails & favicons in this case or any 606 // We'll just continue without thumbnails & favicons in this case or any
615 // other error. 607 // other error.
616 LOG(WARNING) << "Could not initialize the thumbnail database."; 608 LOG(WARNING) << "Could not initialize the thumbnail database.";
617 thumbnail_db_.reset(); 609 thumbnail_db_.reset();
618 } 610 }
619 611
620 // Archived database. 612 // Nuke any files corresponding to the legacy Archived History Database, which
621 if (db_->needs_version_17_migration()) { 613 // previously retained expired (> 3 months old) history entries, but, in the
622 // See needs_version_17_migration() decl for more. In this case, we want 614 // end, was not used for much, and consequently has been removed as of M37.
623 // to delete the archived database and need to do so before we try to 615 // TODO(engedy): Remove this code after the end of 2014.
624 // open the file. We can ignore any error (maybe the file doesn't exist). 616 sql::Connection::Delete(archived_name);
625 sql::Connection::Delete(archived_name);
626 }
627 archived_db_.reset(new ArchivedDatabase());
628 if (!archived_db_->Init(archived_name)) {
629 LOG(WARNING) << "Could not initialize the archived database.";
630 archived_db_.reset();
631 }
632 617
633 // Generate the history and thumbnail database metrics only after performing 618 // Generate the history and thumbnail database metrics only after performing
634 // any migration work. 619 // any migration work.
635 if (base::RandInt(1, 100) == 50) { 620 if (base::RandInt(1, 100) == 50) {
636 // Only do this computation sometimes since it can be expensive. 621 // Only do this computation sometimes since it can be expensive.
637 db_->ComputeDatabaseMetrics(history_name); 622 db_->ComputeDatabaseMetrics(history_name);
638 if (thumbnail_db_) 623 if (thumbnail_db_)
639 thumbnail_db_->ComputeDatabaseMetrics(); 624 thumbnail_db_->ComputeDatabaseMetrics();
640 } 625 }
641 626
642 // Tell the expiration module about all the nice databases we made. This must 627 expirer_.SetDatabases(db_.get(), thumbnail_db_.get());
643 // happen before db_->Init() is called since the callback ForceArchiveHistory
644 // may need to expire stuff.
645 //
646 // *sigh*, this can all be cleaned up when that migration code is removed.
647 // The main DB initialization should intuitively be first (not that it
648 // actually matters) and the expirer should be set last.
649 expirer_.SetDatabases(db_.get(), archived_db_.get(), thumbnail_db_.get());
650 628
651 // Open the long-running transaction. 629 // Open the long-running transaction.
652 db_->BeginTransaction(); 630 db_->BeginTransaction();
653 if (thumbnail_db_) 631 if (thumbnail_db_)
654 thumbnail_db_->BeginTransaction(); 632 thumbnail_db_->BeginTransaction();
655 if (archived_db_)
656 archived_db_->BeginTransaction();
657 633
658 // Get the first item in our database. 634 // Get the first item in our database.
659 db_->GetStartDate(&first_recorded_time_); 635 db_->GetStartDate(&first_recorded_time_);
660 636
661 // Start expiring old stuff. 637 // Start expiring old stuff.
662 expirer_.StartArchivingOldStuff(TimeDelta::FromDays(kArchiveDaysThreshold)); 638 expirer_.StartExpiringOldStuff(TimeDelta::FromDays(kExpireDaysThreshold));
663 639
664 #if defined(OS_ANDROID) 640 #if defined(OS_ANDROID)
665 if (thumbnail_db_) { 641 if (thumbnail_db_) {
666 android_provider_backend_.reset( 642 android_provider_backend_.reset(
667 new AndroidProviderBackend(GetAndroidCacheFileName(), 643 new AndroidProviderBackend(GetAndroidCacheFileName(),
668 db_.get(), 644 db_.get(),
669 thumbnail_db_.get(), 645 thumbnail_db_.get(),
670 history_client_, 646 history_client_,
671 delegate_.get())); 647 delegate_.get()));
672 } 648 }
673 #endif 649 #endif
674 650
675 HISTOGRAM_TIMES("History.InitTime", 651 HISTOGRAM_TIMES("History.InitTime",
676 TimeTicks::Now() - beginning_time); 652 TimeTicks::Now() - beginning_time);
677 } 653 }
678 654
679 void HistoryBackend::OnMemoryPressure( 655 void HistoryBackend::OnMemoryPressure(
680 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 656 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
681 bool trim_aggressively = memory_pressure_level == 657 bool trim_aggressively = memory_pressure_level ==
682 base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL; 658 base::MemoryPressureListener::MEMORY_PRESSURE_CRITICAL;
683 if (db_) 659 if (db_)
684 db_->TrimMemory(trim_aggressively); 660 db_->TrimMemory(trim_aggressively);
685 if (thumbnail_db_) 661 if (thumbnail_db_)
686 thumbnail_db_->TrimMemory(trim_aggressively); 662 thumbnail_db_->TrimMemory(trim_aggressively);
687 if (archived_db_)
688 archived_db_->TrimMemory(trim_aggressively);
689 } 663 }
690 664
691 void HistoryBackend::CloseAllDatabases() { 665 void HistoryBackend::CloseAllDatabases() {
692 if (db_) { 666 if (db_) {
693 // Commit the long-running transaction. 667 // Commit the long-running transaction.
694 db_->CommitTransaction(); 668 db_->CommitTransaction();
695 db_.reset(); 669 db_.reset();
696 // Forget the first recorded time since the database is closed. 670 // Forget the first recorded time since the database is closed.
697 first_recorded_time_ = base::Time(); 671 first_recorded_time_ = base::Time();
698 } 672 }
699 if (thumbnail_db_) { 673 if (thumbnail_db_) {
700 thumbnail_db_->CommitTransaction(); 674 thumbnail_db_->CommitTransaction();
701 thumbnail_db_.reset(); 675 thumbnail_db_.reset();
702 } 676 }
703 if (archived_db_) {
704 archived_db_->CommitTransaction();
705 archived_db_.reset();
706 }
707 } 677 }
708 678
709 std::pair<URLID, VisitID> HistoryBackend::AddPageVisit( 679 std::pair<URLID, VisitID> HistoryBackend::AddPageVisit(
710 const GURL& url, 680 const GURL& url,
711 Time time, 681 Time time,
712 VisitID referring_visit, 682 VisitID referring_visit,
713 content::PageTransition transition, 683 content::PageTransition transition,
714 VisitSource visit_source) { 684 VisitSource visit_source) {
715 // Top-level frame navigations are visible, everything else is hidden 685 // Top-level frame navigations are visible, everything else is hidden
716 bool new_hidden = !content::PageTransitionIsMainFrame(transition); 686 bool new_hidden = !content::PageTransitionIsMainFrame(transition);
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 768
799 return std::make_pair(url_id, visit_id); 769 return std::make_pair(url_id, visit_id);
800 } 770 }
801 771
802 void HistoryBackend::AddPagesWithDetails(const URLRows& urls, 772 void HistoryBackend::AddPagesWithDetails(const URLRows& urls,
803 VisitSource visit_source) { 773 VisitSource visit_source) {
804 if (!db_) 774 if (!db_)
805 return; 775 return;
806 776
807 scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails); 777 scoped_ptr<URLsModifiedDetails> modified(new URLsModifiedDetails);
808 scoped_ptr<URLsModifiedDetails> modified_in_archive(new URLsModifiedDetails);
809 for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) { 778 for (URLRows::const_iterator i = urls.begin(); i != urls.end(); ++i) {
810 DCHECK(!i->last_visit().is_null()); 779 DCHECK(!i->last_visit().is_null());
811 780
812 // We will add to either the archived database or the main one depending on 781 // As of M37, we no longer maintain an archived database, ignore old visits.
813 // the date of the added visit. 782 if (IsExpiredVisitTime(i->last_visit()))
814 URLDatabase* url_database = NULL; 783 continue;
815 VisitDatabase* visit_database = NULL;
816 if (IsExpiredVisitTime(i->last_visit())) {
817 if (!archived_db_)
818 return; // No archived database to save it to, just forget this.
819 url_database = archived_db_.get();
820 visit_database = archived_db_.get();
821 } else {
822 url_database = db_.get();
823 visit_database = db_.get();
824 }
825 784
826 URLRow existing_url; 785 URLRow existing_url;
827 URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); 786 URLID url_id = db_->GetRowForURL(i->url(), &existing_url);
828 if (!url_id) { 787 if (!url_id) {
829 // Add the page if it doesn't exist. 788 // Add the page if it doesn't exist.
830 url_id = url_database->AddURL(*i); 789 url_id = db_->AddURL(*i);
831 if (!url_id) { 790 if (!url_id) {
832 NOTREACHED() << "Could not add row to DB"; 791 NOTREACHED() << "Could not add row to DB";
833 return; 792 return;
834 } 793 }
835 794
836 if (i->typed_count() > 0) { 795 if (i->typed_count() > 0) {
837 // Collect expired URLs that belong to |archived_db_| separately; we 796 modified->changed_urls.push_back(*i);
838 // want to fire NOTIFICATION_HISTORY_URLS_MODIFIED only for changes that 797 modified->changed_urls.back().set_id(url_id); // i->id_ is likely 0.
839 // take place in the main |db_|.
840 if (url_database == db_.get()) {
841 modified->changed_urls.push_back(*i);
842 modified->changed_urls.back().set_id(url_id); // i->id_ is likely 0.
843 } else {
844 modified_in_archive->changed_urls.push_back(*i);
845 modified_in_archive->changed_urls.back().set_id(url_id);
846 }
847 } 798 }
848 } 799 }
849 800
850 // Sync code manages the visits itself. 801 // Sync code manages the visits itself.
851 if (visit_source != SOURCE_SYNCED) { 802 if (visit_source != SOURCE_SYNCED) {
852 // Make up a visit to correspond to the last visit to the page. 803 // Make up a visit to correspond to the last visit to the page.
853 VisitRow visit_info(url_id, i->last_visit(), 0, 804 VisitRow visit_info(url_id, i->last_visit(), 0,
854 content::PageTransitionFromInt( 805 content::PageTransitionFromInt(
855 content::PAGE_TRANSITION_LINK | 806 content::PAGE_TRANSITION_LINK |
856 content::PAGE_TRANSITION_CHAIN_START | 807 content::PAGE_TRANSITION_CHAIN_START |
857 content::PAGE_TRANSITION_CHAIN_END), 0); 808 content::PAGE_TRANSITION_CHAIN_END), 0);
858 if (!visit_database->AddVisit(&visit_info, visit_source)) { 809 if (!db_->AddVisit(&visit_info, visit_source)) {
859 NOTREACHED() << "Adding visit failed."; 810 NOTREACHED() << "Adding visit failed.";
860 return; 811 return;
861 } 812 }
862 NotifyVisitObservers(visit_info); 813 NotifyVisitObservers(visit_info);
863 814
864 if (visit_info.visit_time < first_recorded_time_) 815 if (visit_info.visit_time < first_recorded_time_)
865 first_recorded_time_ = visit_info.visit_time; 816 first_recorded_time_ = visit_info.visit_time;
866 } 817 }
867 } 818 }
868 819
869 if (typed_url_syncable_service_.get()) { 820 if (typed_url_syncable_service_.get())
870 typed_url_syncable_service_->OnUrlsModified(
871 &modified_in_archive->changed_urls);
Andrew T Wilson (Slow) 2014/06/05 11:44:44 Hmm, we're no longer notifying the sync subsystem
engedy 2014/06/05 12:17:59 Thanks for looking into this!
872 typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); 821 typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls);
873 }
874 822
875 // Broadcast a notification for typed URLs that have been modified. This 823 // Broadcast a notification for typed URLs that have been modified. This
876 // will be picked up by the in-memory URL database on the main thread. 824 // will be picked up by the in-memory URL database on the main thread.
877 // 825 //
878 // TODO(brettw) bug 1140015: Add an "add page" notification so the history 826 // TODO(brettw) bug 1140015: Add an "add page" notification so the history
879 // views can keep in sync. 827 // views can keep in sync.
880 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, 828 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED,
881 modified.PassAs<HistoryDetails>()); 829 modified.PassAs<HistoryDetails>());
882 830
883 ScheduleCommit(); 831 ScheduleCommit();
884 } 832 }
885 833
886 bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { 834 bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) {
887 return time < expirer_.GetCurrentArchiveTime(); 835 return time < expirer_.GetCurrentExpirationTime();
888 } 836 }
889 837
890 void HistoryBackend::SetPageTitle(const GURL& url, 838 void HistoryBackend::SetPageTitle(const GURL& url,
891 const base::string16& title) { 839 const base::string16& title) {
892 if (!db_) 840 if (!db_)
893 return; 841 return;
894 842
895 // Search for recent redirects which should get the same title. We make a 843 // Search for recent redirects which should get the same title. We make a
896 // dummy list containing the exact URL visited if there are no redirects so 844 // dummy list containing the exact URL visited if there are no redirects so
897 // the processing below can be the same. 845 // the processing below can be the same.
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 new KeywordSearchUpdatedDetails(row, keyword_id, term))); 1071 new KeywordSearchUpdatedDetails(row, keyword_id, term)));
1124 ScheduleCommit(); 1072 ScheduleCommit();
1125 } 1073 }
1126 1074
1127 void HistoryBackend::DeleteAllSearchTermsForKeyword( 1075 void HistoryBackend::DeleteAllSearchTermsForKeyword(
1128 TemplateURLID keyword_id) { 1076 TemplateURLID keyword_id) {
1129 if (!db_) 1077 if (!db_)
1130 return; 1078 return;
1131 1079
1132 db_->DeleteAllSearchTermsForKeyword(keyword_id); 1080 db_->DeleteAllSearchTermsForKeyword(keyword_id);
1133 // TODO(sky): bug 1168470. Need to move from archive dbs too.
1134 ScheduleCommit(); 1081 ScheduleCommit();
1135 } 1082 }
1136 1083
1137 void HistoryBackend::GetMostRecentKeywordSearchTerms( 1084 void HistoryBackend::GetMostRecentKeywordSearchTerms(
1138 scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, 1085 scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request,
1139 TemplateURLID keyword_id, 1086 TemplateURLID keyword_id,
1140 const base::string16& prefix, 1087 const base::string16& prefix,
1141 int max_count) { 1088 int max_count) {
1142 if (request->canceled()) 1089 if (request->canceled())
1143 return; 1090 return;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
1248 const base::string16& text_query, 1195 const base::string16& text_query,
1249 const QueryOptions& options) { 1196 const QueryOptions& options) {
1250 if (request->canceled()) 1197 if (request->canceled())
1251 return; 1198 return;
1252 1199
1253 TimeTicks beginning_time = TimeTicks::Now(); 1200 TimeTicks beginning_time = TimeTicks::Now();
1254 1201
1255 if (db_) { 1202 if (db_) {
1256 if (text_query.empty()) { 1203 if (text_query.empty()) {
1257 // Basic history query for the main database. 1204 // Basic history query for the main database.
1258 QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); 1205 QueryHistoryBasic(options, &request->value);
1259
1260 // Now query the archived database. This is a bit tricky because we don't
1261 // want to query it if the queried time range isn't going to find anything
1262 // in it.
1263 // TODO(brettw) bug 1171036: do blimpie querying for the archived database
1264 // as well.
1265 // if (archived_db_.get() &&
1266 // expirer_.GetCurrentArchiveTime() - TimeDelta::FromDays(7)) {
1267 } else { 1206 } else {
1268 // Text history query. 1207 // Text history query.
1269 QueryHistoryText(db_.get(), db_.get(), text_query, options, 1208 QueryHistoryText(text_query, options, &request->value);
1270 &request->value);
1271 if (archived_db_.get() &&
1272 expirer_.GetCurrentArchiveTime() >= options.begin_time) {
1273 QueryHistoryText(archived_db_.get(), archived_db_.get(), text_query,
1274 options, &request->value);
1275 }
1276 } 1209 }
1277 } 1210 }
1278 1211
1279 request->ForwardResult(request->handle(), &request->value); 1212 request->ForwardResult(request->handle(), &request->value);
1280 1213
1281 UMA_HISTOGRAM_TIMES("History.QueryHistory", 1214 UMA_HISTOGRAM_TIMES("History.QueryHistory",
1282 TimeTicks::Now() - beginning_time); 1215 TimeTicks::Now() - beginning_time);
1283 } 1216 }
1284 1217
1285 // Basic time-based querying of history. 1218 // Basic time-based querying of history.
1286 void HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, 1219 void HistoryBackend::QueryHistoryBasic(const QueryOptions& options,
1287 VisitDatabase* visit_db,
1288 const QueryOptions& options,
1289 QueryResults* result) { 1220 QueryResults* result) {
1290 // First get all visits. 1221 // First get all visits.
1291 VisitVector visits; 1222 VisitVector visits;
1292 bool has_more_results = visit_db->GetVisibleVisitsInRange(options, &visits); 1223 bool has_more_results = db_->GetVisibleVisitsInRange(options, &visits);
1293 DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); 1224 DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount());
1294 1225
1295 // Now add them and the URL rows to the results. 1226 // Now add them and the URL rows to the results.
1296 URLResult url_result; 1227 URLResult url_result;
1297 for (size_t i = 0; i < visits.size(); i++) { 1228 for (size_t i = 0; i < visits.size(); i++) {
1298 const VisitRow visit = visits[i]; 1229 const VisitRow visit = visits[i];
1299 1230
1300 // Add a result row for this visit, get the URL info from the DB. 1231 // Add a result row for this visit, get the URL info from the DB.
1301 if (!url_db->GetURLRow(visit.url_id, &url_result)) { 1232 if (!db_->GetURLRow(visit.url_id, &url_result)) {
1302 VLOG(0) << "Failed to get id " << visit.url_id 1233 VLOG(0) << "Failed to get id " << visit.url_id
1303 << " from history.urls."; 1234 << " from history.urls.";
1304 continue; // DB out of sync and URL doesn't exist, try to recover. 1235 continue; // DB out of sync and URL doesn't exist, try to recover.
1305 } 1236 }
1306 1237
1307 if (!url_result.url().is_valid()) { 1238 if (!url_result.url().is_valid()) {
1308 VLOG(0) << "Got invalid URL from history.urls with id " 1239 VLOG(0) << "Got invalid URL from history.urls with id "
1309 << visit.url_id << ": " 1240 << visit.url_id << ": "
1310 << url_result.url().possibly_invalid_spec(); 1241 << url_result.url().possibly_invalid_spec();
1311 continue; // Don't report invalid URLs in case of corruption. 1242 continue; // Don't report invalid URLs in case of corruption.
1312 } 1243 }
1313 1244
1314 // The archived database may be out of sync with respect to starring,
1315 // titles, last visit date, etc. Therefore, we query the main DB if the
1316 // current URL database is not the main one.
1317 if (url_db == db_.get()) {
1318 // Currently querying the archived DB, update with the main database to
1319 // catch any interesting stuff. This will update it if it exists in the
1320 // main DB, and do nothing otherwise.
1321 db_->GetRowForURL(url_result.url(), &url_result);
1322 }
1323
1324 url_result.set_visit_time(visit.visit_time); 1245 url_result.set_visit_time(visit.visit_time);
1325 1246
1326 // Set whether the visit was blocked for a managed user by looking at the 1247 // Set whether the visit was blocked for a managed user by looking at the
1327 // transition type. 1248 // transition type.
1328 url_result.set_blocked_visit( 1249 url_result.set_blocked_visit(
1329 (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); 1250 (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0);
1330 1251
1331 // We don't set any of the query-specific parts of the URLResult, since 1252 // We don't set any of the query-specific parts of the URLResult, since
1332 // snippets and stuff don't apply to basic querying. 1253 // snippets and stuff don't apply to basic querying.
1333 result->AppendURLBySwapping(&url_result); 1254 result->AppendURLBySwapping(&url_result);
1334 } 1255 }
1335 1256
1336 if (!has_more_results && options.begin_time <= first_recorded_time_) 1257 if (!has_more_results && options.begin_time <= first_recorded_time_)
1337 result->set_reached_beginning(true); 1258 result->set_reached_beginning(true);
1338 } 1259 }
1339 1260
1340 // Text-based querying of history. 1261 // Text-based querying of history.
1341 void HistoryBackend::QueryHistoryText(URLDatabase* url_db, 1262 void HistoryBackend::QueryHistoryText(const base::string16& text_query,
1342 VisitDatabase* visit_db,
1343 const base::string16& text_query,
1344 const QueryOptions& options, 1263 const QueryOptions& options,
1345 QueryResults* result) { 1264 QueryResults* result) {
1346 URLRows text_matches; 1265 URLRows text_matches;
1347 url_db->GetTextMatches(text_query, &text_matches); 1266 db_->GetTextMatches(text_query, &text_matches);
1348 1267
1349 std::vector<URLResult> matching_visits; 1268 std::vector<URLResult> matching_visits;
1350 VisitVector visits; // Declare outside loop to prevent re-construction. 1269 VisitVector visits; // Declare outside loop to prevent re-construction.
1351 for (size_t i = 0; i < text_matches.size(); i++) { 1270 for (size_t i = 0; i < text_matches.size(); i++) {
1352 const URLRow& text_match = text_matches[i]; 1271 const URLRow& text_match = text_matches[i];
1353 // Get all visits for given URL match. 1272 // Get all visits for given URL match.
1354 visit_db->GetVisibleVisitsForURL(text_match.id(), options, &visits); 1273 db_->GetVisibleVisitsForURL(text_match.id(), options, &visits);
1355 for (size_t j = 0; j < visits.size(); j++) { 1274 for (size_t j = 0; j < visits.size(); j++) {
1356 URLResult url_result(text_match); 1275 URLResult url_result(text_match);
1357 url_result.set_visit_time(visits[j].visit_time); 1276 url_result.set_visit_time(visits[j].visit_time);
1358 matching_visits.push_back(url_result); 1277 matching_visits.push_back(url_result);
1359 } 1278 }
1360 } 1279 }
1361 1280
1362 std::sort(matching_visits.begin(), matching_visits.end(), 1281 std::sort(matching_visits.begin(), matching_visits.end(),
1363 URLResult::CompareVisitTime); 1282 URLResult::CompareVisitTime);
1364 1283
(...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after
2474 db_->CommitTransaction(); 2393 db_->CommitTransaction();
2475 DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; 2394 DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open";
2476 db_->BeginTransaction(); 2395 db_->BeginTransaction();
2477 2396
2478 if (thumbnail_db_) { 2397 if (thumbnail_db_) {
2479 thumbnail_db_->CommitTransaction(); 2398 thumbnail_db_->CommitTransaction();
2480 DCHECK(thumbnail_db_->transaction_nesting() == 0) << 2399 DCHECK(thumbnail_db_->transaction_nesting() == 0) <<
2481 "Somebody left a transaction open"; 2400 "Somebody left a transaction open";
2482 thumbnail_db_->BeginTransaction(); 2401 thumbnail_db_->BeginTransaction();
2483 } 2402 }
2484
2485 if (archived_db_) {
2486 archived_db_->CommitTransaction();
2487 archived_db_->BeginTransaction();
2488 }
2489 } 2403 }
2490 2404
2491 void HistoryBackend::ScheduleCommit() { 2405 void HistoryBackend::ScheduleCommit() {
2492 if (scheduled_commit_.get()) 2406 if (scheduled_commit_.get())
2493 return; 2407 return;
2494 scheduled_commit_ = new CommitLaterTask(this); 2408 scheduled_commit_ = new CommitLaterTask(this);
2495 base::MessageLoop::current()->PostDelayedTask( 2409 base::MessageLoop::current()->PostDelayedTask(
2496 FROM_HERE, 2410 FROM_HERE,
2497 base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), 2411 base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()),
2498 base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); 2412 base::TimeDelta::FromSeconds(kCommitIntervalSeconds));
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); 2519 << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime();
2606 DCHECK(*times.rbegin() < end_time) 2520 DCHECK(*times.rbegin() < end_time)
2607 << "Max time is after end time: " 2521 << "Max time is after end time: "
2608 << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); 2522 << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime();
2609 2523
2610 history::QueryOptions options; 2524 history::QueryOptions options;
2611 options.begin_time = begin_time; 2525 options.begin_time = begin_time;
2612 options.end_time = end_time; 2526 options.end_time = end_time;
2613 options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; 2527 options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES;
2614 QueryResults results; 2528 QueryResults results;
2615 QueryHistoryBasic(db_.get(), db_.get(), options, &results); 2529 QueryHistoryBasic(options, &results);
2616 2530
2617 // 1st pass: find URLs that are visited at one of |times|. 2531 // 1st pass: find URLs that are visited at one of |times|.
2618 std::set<GURL> urls; 2532 std::set<GURL> urls;
2619 for (size_t i = 0; i < results.size(); ++i) { 2533 for (size_t i = 0; i < results.size(); ++i) {
2620 if (times.count(results[i].visit_time()) > 0) 2534 if (times.count(results[i].visit_time()) > 0)
2621 urls.insert(results[i].url()); 2535 urls.insert(results[i].url());
2622 } 2536 }
2623 if (urls.empty()) 2537 if (urls.empty())
2624 return; 2538 return;
2625 2539
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
2710 bool success = db_->Raze(); 2624 bool success = db_->Raze();
2711 UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); 2625 UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success);
2712 2626
2713 #if defined(OS_ANDROID) 2627 #if defined(OS_ANDROID)
2714 // Release AndroidProviderBackend before other objects. 2628 // Release AndroidProviderBackend before other objects.
2715 android_provider_backend_.reset(); 2629 android_provider_backend_.reset();
2716 #endif 2630 #endif
2717 2631
2718 // The expirer keeps tabs on the active databases. Tell it about the 2632 // The expirer keeps tabs on the active databases. Tell it about the
2719 // databases which will be closed. 2633 // databases which will be closed.
2720 expirer_.SetDatabases(NULL, NULL, NULL); 2634 expirer_.SetDatabases(NULL, NULL);
2721 2635
2722 // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). 2636 // Reopen a new transaction for |db_| for the sake of CloseAllDatabases().
2723 db_->BeginTransaction(); 2637 db_->BeginTransaction();
2724 CloseAllDatabases(); 2638 CloseAllDatabases();
2725 } 2639 }
2726 2640
2727 void HistoryBackend::ProcessDBTask( 2641 void HistoryBackend::ProcessDBTask(
2728 scoped_refptr<HistoryDBTaskRequest> request) { 2642 scoped_refptr<HistoryDBTaskRequest> request) {
2729 DCHECK(request.get()); 2643 DCHECK(request.get());
2730 if (request->canceled()) 2644 if (request->canceled())
(...skipping 18 matching lines...) Expand all
2749 if (delegate_) 2663 if (delegate_)
2750 delegate_->BroadcastNotifications(type, details.Pass()); 2664 delegate_->BroadcastNotifications(type, details.Pass());
2751 } 2665 }
2752 2666
2753 void HistoryBackend::NotifySyncURLsModified(URLRows* rows) { 2667 void HistoryBackend::NotifySyncURLsModified(URLRows* rows) {
2754 if (typed_url_syncable_service_.get()) 2668 if (typed_url_syncable_service_.get())
2755 typed_url_syncable_service_->OnUrlsModified(rows); 2669 typed_url_syncable_service_->OnUrlsModified(rows);
2756 } 2670 }
2757 2671
2758 void HistoryBackend::NotifySyncURLsDeleted(bool all_history, 2672 void HistoryBackend::NotifySyncURLsDeleted(bool all_history,
2759 bool archived, 2673 bool expired,
2760 URLRows* rows) { 2674 URLRows* rows) {
2761 if (typed_url_syncable_service_.get()) 2675 if (typed_url_syncable_service_.get())
2762 typed_url_syncable_service_->OnUrlsDeleted(all_history, archived, rows); 2676 typed_url_syncable_service_->OnUrlsDeleted(all_history, expired, rows);
2763 } 2677 }
2764 2678
2765 // Deleting -------------------------------------------------------------------- 2679 // Deleting --------------------------------------------------------------------
2766 2680
2767 void HistoryBackend::DeleteAllHistory() { 2681 void HistoryBackend::DeleteAllHistory() {
2768 // Our approach to deleting all history is: 2682 // Our approach to deleting all history is:
2769 // 1. Copy the bookmarks and their dependencies to new tables with temporary 2683 // 1. Copy the bookmarks and their dependencies to new tables with temporary
2770 // names. 2684 // names.
2771 // 2. Delete the original tables. Since tables can not share pages, we know 2685 // 2. Delete the original tables. Since tables can not share pages, we know
2772 // that any data we don't want to keep is now in an unused page. 2686 // that any data we don't want to keep is now in an unused page.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2804 // history, we should delete as much as we can. 2718 // history, we should delete as much as we can.
2805 } 2719 }
2806 2720
2807 // ClearAllMainHistory will change the IDs of the URLs in kept_urls. 2721 // ClearAllMainHistory will change the IDs of the URLs in kept_urls.
2808 // Therefore, we clear the list afterwards to make sure nobody uses this 2722 // Therefore, we clear the list afterwards to make sure nobody uses this
2809 // invalid data. 2723 // invalid data.
2810 if (!ClearAllMainHistory(kept_urls)) 2724 if (!ClearAllMainHistory(kept_urls))
2811 LOG(ERROR) << "Main history could not be cleared"; 2725 LOG(ERROR) << "Main history could not be cleared";
2812 kept_urls.clear(); 2726 kept_urls.clear();
2813 2727
2814 // Delete archived history.
2815 if (archived_db_) {
2816 // Close the database and delete the file.
2817 archived_db_.reset();
2818 base::FilePath archived_file_name = GetArchivedFileName();
2819 sql::Connection::Delete(archived_file_name);
2820
2821 // Now re-initialize the database (which may fail).
2822 archived_db_.reset(new ArchivedDatabase());
2823 if (!archived_db_->Init(archived_file_name)) {
2824 LOG(WARNING) << "Could not initialize the archived database.";
2825 archived_db_.reset();
2826 } else {
2827 // Open our long-running transaction on this database.
2828 archived_db_->BeginTransaction();
2829 }
2830 }
2831
2832 db_->GetStartDate(&first_recorded_time_); 2728 db_->GetStartDate(&first_recorded_time_);
2833 2729
2834 // Send out the notification that history is cleared. The in-memory database 2730 // Send out the notification that history is cleared. The in-memory database
2835 // will pick this up and clear itself. 2731 // will pick this up and clear itself.
2836 scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); 2732 scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails);
2837 details->all_history = true; 2733 details->all_history = true;
2838 NotifySyncURLsDeleted(true, false, NULL); 2734 NotifySyncURLsDeleted(true, false, NULL);
2839 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, 2735 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED,
2840 details.PassAs<HistoryDetails>()); 2736 details.PassAs<HistoryDetails>());
2841 } 2737 }
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
2952 int rank = kPageVisitStatsMaxTopSites; 2848 int rank = kPageVisitStatsMaxTopSites;
2953 std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); 2849 std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url);
2954 if (it != most_visited_urls_map_.end()) 2850 if (it != most_visited_urls_map_.end())
2955 rank = (*it).second; 2851 rank = (*it).second;
2956 UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", 2852 UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank",
2957 rank, kPageVisitStatsMaxTopSites + 1); 2853 rank, kPageVisitStatsMaxTopSites + 1);
2958 } 2854 }
2959 #endif 2855 #endif
2960 2856
2961 } // namespace history 2857 } // namespace history
OLDNEW
« no previous file with comments | « chrome/browser/history/history_backend.h ('k') | chrome/browser/history/history_backend_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698