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

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