OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #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 Loading... | |
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 Loading... | |
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, these were not |
622 // See needs_version_17_migration() decl for more. In this case, we want | 615 // really used for much, therefore the feature has been removed as of M36. |
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 Loading... | |
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 M36, we no longer retain expired records in an archived database, |
809 // the date of the added visit. | 785 // so forget about old visits. |
810 URLDatabase* url_database = NULL; | 786 if (IsExpiredVisitTime(i->last_visit())) |
811 VisitDatabase* visit_database = NULL; | 787 continue; |
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 | 788 |
822 URLRow existing_url; | 789 URLRow existing_url; |
823 URLID url_id = url_database->GetRowForURL(i->url(), &existing_url); | 790 URLID url_id = db_->GetRowForURL(i->url(), &existing_url); |
824 if (!url_id) { | 791 if (!url_id) { |
825 // Add the page if it doesn't exist. | 792 // Add the page if it doesn't exist. |
826 url_id = url_database->AddURL(*i); | 793 url_id = db_->AddURL(*i); |
827 if (!url_id) { | 794 if (!url_id) { |
828 NOTREACHED() << "Could not add row to DB"; | 795 NOTREACHED() << "Could not add row to DB"; |
829 return; | 796 return; |
830 } | 797 } |
831 | 798 |
832 if (i->typed_count() > 0) { | 799 if (i->typed_count() > 0) { |
833 // Collect expired URLs that belong to |archived_db_| separately; we | 800 modified->changed_urls.push_back(*i); |
834 // want to fire NOTIFICATION_HISTORY_URLS_MODIFIED only for changes that | 801 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 } | 802 } |
844 } | 803 } |
845 | 804 |
846 // Sync code manages the visits itself. | 805 // Sync code manages the visits itself. |
847 if (visit_source != SOURCE_SYNCED) { | 806 if (visit_source != SOURCE_SYNCED) { |
848 // Make up a visit to correspond to the last visit to the page. | 807 // Make up a visit to correspond to the last visit to the page. |
849 VisitRow visit_info(url_id, i->last_visit(), 0, | 808 VisitRow visit_info(url_id, i->last_visit(), 0, |
850 content::PageTransitionFromInt( | 809 content::PageTransitionFromInt( |
851 content::PAGE_TRANSITION_LINK | | 810 content::PAGE_TRANSITION_LINK | |
852 content::PAGE_TRANSITION_CHAIN_START | | 811 content::PAGE_TRANSITION_CHAIN_START | |
853 content::PAGE_TRANSITION_CHAIN_END), 0); | 812 content::PAGE_TRANSITION_CHAIN_END), 0); |
854 if (!visit_database->AddVisit(&visit_info, visit_source)) { | 813 if (!db_->AddVisit(&visit_info, visit_source)) { |
855 NOTREACHED() << "Adding visit failed."; | 814 NOTREACHED() << "Adding visit failed."; |
856 return; | 815 return; |
857 } | 816 } |
858 NotifyVisitObservers(visit_info); | 817 NotifyVisitObservers(visit_info); |
859 | 818 |
860 if (visit_info.visit_time < first_recorded_time_) | 819 if (visit_info.visit_time < first_recorded_time_) |
861 first_recorded_time_ = visit_info.visit_time; | 820 first_recorded_time_ = visit_info.visit_time; |
862 } | 821 } |
863 } | 822 } |
864 | 823 |
865 if (typed_url_syncable_service_.get()) { | 824 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); | 825 typed_url_syncable_service_->OnUrlsModified(&modified->changed_urls); |
869 } | |
870 | 826 |
871 // Broadcast a notification for typed URLs that have been modified. This | 827 // 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. | 828 // will be picked up by the in-memory URL database on the main thread. |
873 // | 829 // |
874 // TODO(brettw) bug 1140015: Add an "add page" notification so the history | 830 // TODO(brettw) bug 1140015: Add an "add page" notification so the history |
875 // views can keep in sync. | 831 // views can keep in sync. |
876 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, | 832 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, |
877 modified.PassAs<HistoryDetails>()); | 833 modified.PassAs<HistoryDetails>()); |
878 | 834 |
879 ScheduleCommit(); | 835 ScheduleCommit(); |
880 } | 836 } |
881 | 837 |
882 bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { | 838 bool HistoryBackend::IsExpiredVisitTime(const base::Time& time) { |
883 return time < expirer_.GetCurrentArchiveTime(); | 839 return time < expirer_.GetCurrentExpirationTime(); |
884 } | 840 } |
885 | 841 |
886 void HistoryBackend::SetPageTitle(const GURL& url, | 842 void HistoryBackend::SetPageTitle(const GURL& url, |
887 const base::string16& title) { | 843 const base::string16& title) { |
888 if (!db_) | 844 if (!db_) |
889 return; | 845 return; |
890 | 846 |
891 // Search for recent redirects which should get the same title. We make a | 847 // 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 | 848 // dummy list containing the exact URL visited if there are no redirects so |
893 // the processing below can be the same. | 849 // the processing below can be the same. |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1119 new KeywordSearchUpdatedDetails(url, keyword_id, term))); | 1075 new KeywordSearchUpdatedDetails(url, keyword_id, term))); |
1120 ScheduleCommit(); | 1076 ScheduleCommit(); |
1121 } | 1077 } |
1122 | 1078 |
1123 void HistoryBackend::DeleteAllSearchTermsForKeyword( | 1079 void HistoryBackend::DeleteAllSearchTermsForKeyword( |
1124 TemplateURLID keyword_id) { | 1080 TemplateURLID keyword_id) { |
1125 if (!db_) | 1081 if (!db_) |
1126 return; | 1082 return; |
1127 | 1083 |
1128 db_->DeleteAllSearchTermsForKeyword(keyword_id); | 1084 db_->DeleteAllSearchTermsForKeyword(keyword_id); |
1129 // TODO(sky): bug 1168470. Need to move from archive dbs too. | |
1130 ScheduleCommit(); | 1085 ScheduleCommit(); |
1131 } | 1086 } |
1132 | 1087 |
1133 void HistoryBackend::GetMostRecentKeywordSearchTerms( | 1088 void HistoryBackend::GetMostRecentKeywordSearchTerms( |
1134 scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, | 1089 scoped_refptr<GetMostRecentKeywordSearchTermsRequest> request, |
1135 TemplateURLID keyword_id, | 1090 TemplateURLID keyword_id, |
1136 const base::string16& prefix, | 1091 const base::string16& prefix, |
1137 int max_count) { | 1092 int max_count) { |
1138 if (request->canceled()) | 1093 if (request->canceled()) |
1139 return; | 1094 return; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1244 const base::string16& text_query, | 1199 const base::string16& text_query, |
1245 const QueryOptions& options) { | 1200 const QueryOptions& options) { |
1246 if (request->canceled()) | 1201 if (request->canceled()) |
1247 return; | 1202 return; |
1248 | 1203 |
1249 TimeTicks beginning_time = TimeTicks::Now(); | 1204 TimeTicks beginning_time = TimeTicks::Now(); |
1250 | 1205 |
1251 if (db_) { | 1206 if (db_) { |
1252 if (text_query.empty()) { | 1207 if (text_query.empty()) { |
1253 // Basic history query for the main database. | 1208 // Basic history query for the main database. |
1254 QueryHistoryBasic(db_.get(), db_.get(), options, &request->value); | 1209 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 { | 1210 } else { |
1264 // Text history query. | 1211 // Text history query. |
1265 QueryHistoryText(db_.get(), db_.get(), text_query, options, | 1212 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 } | 1213 } |
1273 } | 1214 } |
1274 | 1215 |
1275 request->ForwardResult(request->handle(), &request->value); | 1216 request->ForwardResult(request->handle(), &request->value); |
1276 | 1217 |
1277 UMA_HISTOGRAM_TIMES("History.QueryHistory", | 1218 UMA_HISTOGRAM_TIMES("History.QueryHistory", |
1278 TimeTicks::Now() - beginning_time); | 1219 TimeTicks::Now() - beginning_time); |
1279 } | 1220 } |
1280 | 1221 |
1281 // Basic time-based querying of history. | 1222 // Basic time-based querying of history. |
1282 void HistoryBackend::QueryHistoryBasic(URLDatabase* url_db, | 1223 void HistoryBackend::QueryHistoryBasic(const QueryOptions& options, |
1283 VisitDatabase* visit_db, | |
1284 const QueryOptions& options, | |
1285 QueryResults* result) { | 1224 QueryResults* result) { |
1286 // First get all visits. | 1225 // First get all visits. |
1287 VisitVector visits; | 1226 VisitVector visits; |
1288 bool has_more_results = visit_db->GetVisibleVisitsInRange(options, &visits); | 1227 bool has_more_results = db_->GetVisibleVisitsInRange(options, &visits); |
1289 DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); | 1228 DCHECK(static_cast<int>(visits.size()) <= options.EffectiveMaxCount()); |
1290 | 1229 |
1291 // Now add them and the URL rows to the results. | 1230 // Now add them and the URL rows to the results. |
1292 URLResult url_result; | 1231 URLResult url_result; |
1293 for (size_t i = 0; i < visits.size(); i++) { | 1232 for (size_t i = 0; i < visits.size(); i++) { |
1294 const VisitRow visit = visits[i]; | 1233 const VisitRow visit = visits[i]; |
1295 | 1234 |
1296 // Add a result row for this visit, get the URL info from the DB. | 1235 // Add a result row for this visit, get the URL info from the DB. |
1297 if (!url_db->GetURLRow(visit.url_id, &url_result)) { | 1236 if (!db_->GetURLRow(visit.url_id, &url_result)) { |
1298 VLOG(0) << "Failed to get id " << visit.url_id | 1237 VLOG(0) << "Failed to get id " << visit.url_id |
1299 << " from history.urls."; | 1238 << " from history.urls."; |
1300 continue; // DB out of sync and URL doesn't exist, try to recover. | 1239 continue; // DB out of sync and URL doesn't exist, try to recover. |
1301 } | 1240 } |
1302 | 1241 |
1303 if (!url_result.url().is_valid()) { | 1242 if (!url_result.url().is_valid()) { |
1304 VLOG(0) << "Got invalid URL from history.urls with id " | 1243 VLOG(0) << "Got invalid URL from history.urls with id " |
1305 << visit.url_id << ": " | 1244 << visit.url_id << ": " |
1306 << url_result.url().possibly_invalid_spec(); | 1245 << url_result.url().possibly_invalid_spec(); |
1307 continue; // Don't report invalid URLs in case of corruption. | 1246 continue; // Don't report invalid URLs in case of corruption. |
1308 } | 1247 } |
1309 | 1248 |
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()) { | |
engedy
2014/04/16 18:08:10
Note: I think this should have been a non-equality
| |
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); | 1249 url_result.set_visit_time(visit.visit_time); |
1321 | 1250 |
1322 // Set whether the visit was blocked for a managed user by looking at the | 1251 // Set whether the visit was blocked for a managed user by looking at the |
1323 // transition type. | 1252 // transition type. |
1324 url_result.set_blocked_visit( | 1253 url_result.set_blocked_visit( |
1325 (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); | 1254 (visit.transition & content::PAGE_TRANSITION_BLOCKED) != 0); |
1326 | 1255 |
1327 // We don't set any of the query-specific parts of the URLResult, since | 1256 // We don't set any of the query-specific parts of the URLResult, since |
1328 // snippets and stuff don't apply to basic querying. | 1257 // snippets and stuff don't apply to basic querying. |
1329 result->AppendURLBySwapping(&url_result); | 1258 result->AppendURLBySwapping(&url_result); |
1330 } | 1259 } |
1331 | 1260 |
1332 if (!has_more_results && options.begin_time <= first_recorded_time_) | 1261 if (!has_more_results && options.begin_time <= first_recorded_time_) |
1333 result->set_reached_beginning(true); | 1262 result->set_reached_beginning(true); |
1334 } | 1263 } |
1335 | 1264 |
1336 // Text-based querying of history. | 1265 // Text-based querying of history. |
1337 void HistoryBackend::QueryHistoryText(URLDatabase* url_db, | 1266 void HistoryBackend::QueryHistoryText(const base::string16& text_query, |
1338 VisitDatabase* visit_db, | |
1339 const base::string16& text_query, | |
1340 const QueryOptions& options, | 1267 const QueryOptions& options, |
1341 QueryResults* result) { | 1268 QueryResults* result) { |
1342 URLRows text_matches; | 1269 URLRows text_matches; |
1343 url_db->GetTextMatches(text_query, &text_matches); | 1270 db_->GetTextMatches(text_query, &text_matches); |
1344 | 1271 |
1345 std::vector<URLResult> matching_visits; | 1272 std::vector<URLResult> matching_visits; |
1346 VisitVector visits; // Declare outside loop to prevent re-construction. | 1273 VisitVector visits; // Declare outside loop to prevent re-construction. |
1347 for (size_t i = 0; i < text_matches.size(); i++) { | 1274 for (size_t i = 0; i < text_matches.size(); i++) { |
1348 const URLRow& text_match = text_matches[i]; | 1275 const URLRow& text_match = text_matches[i]; |
1349 // Get all visits for given URL match. | 1276 // Get all visits for given URL match. |
1350 visit_db->GetVisibleVisitsForURL(text_match.id(), options, &visits); | 1277 db_->GetVisibleVisitsForURL(text_match.id(), options, &visits); |
1351 for (size_t j = 0; j < visits.size(); j++) { | 1278 for (size_t j = 0; j < visits.size(); j++) { |
1352 URLResult url_result(text_match); | 1279 URLResult url_result(text_match); |
1353 url_result.set_visit_time(visits[j].visit_time); | 1280 url_result.set_visit_time(visits[j].visit_time); |
1354 matching_visits.push_back(url_result); | 1281 matching_visits.push_back(url_result); |
1355 } | 1282 } |
1356 } | 1283 } |
1357 | 1284 |
1358 std::sort(matching_visits.begin(), matching_visits.end(), | 1285 std::sort(matching_visits.begin(), matching_visits.end(), |
1359 URLResult::CompareVisitTime); | 1286 URLResult::CompareVisitTime); |
1360 | 1287 |
(...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2464 db_->CommitTransaction(); | 2391 db_->CommitTransaction(); |
2465 DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; | 2392 DCHECK(db_->transaction_nesting() == 0) << "Somebody left a transaction open"; |
2466 db_->BeginTransaction(); | 2393 db_->BeginTransaction(); |
2467 | 2394 |
2468 if (thumbnail_db_) { | 2395 if (thumbnail_db_) { |
2469 thumbnail_db_->CommitTransaction(); | 2396 thumbnail_db_->CommitTransaction(); |
2470 DCHECK(thumbnail_db_->transaction_nesting() == 0) << | 2397 DCHECK(thumbnail_db_->transaction_nesting() == 0) << |
2471 "Somebody left a transaction open"; | 2398 "Somebody left a transaction open"; |
2472 thumbnail_db_->BeginTransaction(); | 2399 thumbnail_db_->BeginTransaction(); |
2473 } | 2400 } |
2474 | |
2475 if (archived_db_) { | |
2476 archived_db_->CommitTransaction(); | |
2477 archived_db_->BeginTransaction(); | |
2478 } | |
2479 } | 2401 } |
2480 | 2402 |
2481 void HistoryBackend::ScheduleCommit() { | 2403 void HistoryBackend::ScheduleCommit() { |
2482 if (scheduled_commit_.get()) | 2404 if (scheduled_commit_.get()) |
2483 return; | 2405 return; |
2484 scheduled_commit_ = new CommitLaterTask(this); | 2406 scheduled_commit_ = new CommitLaterTask(this); |
2485 base::MessageLoop::current()->PostDelayedTask( | 2407 base::MessageLoop::current()->PostDelayedTask( |
2486 FROM_HERE, | 2408 FROM_HERE, |
2487 base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), | 2409 base::Bind(&CommitLaterTask::RunCommit, scheduled_commit_.get()), |
2488 base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); | 2410 base::TimeDelta::FromSeconds(kCommitIntervalSeconds)); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2595 << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); | 2517 << times.begin()->ToJsTime() << " v.s. " << begin_time.ToJsTime(); |
2596 DCHECK(*times.rbegin() < end_time) | 2518 DCHECK(*times.rbegin() < end_time) |
2597 << "Max time is after end time: " | 2519 << "Max time is after end time: " |
2598 << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); | 2520 << times.rbegin()->ToJsTime() << " v.s. " << end_time.ToJsTime(); |
2599 | 2521 |
2600 history::QueryOptions options; | 2522 history::QueryOptions options; |
2601 options.begin_time = begin_time; | 2523 options.begin_time = begin_time; |
2602 options.end_time = end_time; | 2524 options.end_time = end_time; |
2603 options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; | 2525 options.duplicate_policy = QueryOptions::KEEP_ALL_DUPLICATES; |
2604 QueryResults results; | 2526 QueryResults results; |
2605 QueryHistoryBasic(db_.get(), db_.get(), options, &results); | 2527 QueryHistoryBasic(options, &results); |
2606 | 2528 |
2607 // 1st pass: find URLs that are visited at one of |times|. | 2529 // 1st pass: find URLs that are visited at one of |times|. |
2608 std::set<GURL> urls; | 2530 std::set<GURL> urls; |
2609 for (size_t i = 0; i < results.size(); ++i) { | 2531 for (size_t i = 0; i < results.size(); ++i) { |
2610 if (times.count(results[i].visit_time()) > 0) | 2532 if (times.count(results[i].visit_time()) > 0) |
2611 urls.insert(results[i].url()); | 2533 urls.insert(results[i].url()); |
2612 } | 2534 } |
2613 if (urls.empty()) | 2535 if (urls.empty()) |
2614 return; | 2536 return; |
2615 | 2537 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2700 bool success = db_->Raze(); | 2622 bool success = db_->Raze(); |
2701 UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); | 2623 UMA_HISTOGRAM_BOOLEAN("History.KillHistoryDatabaseResult", success); |
2702 | 2624 |
2703 #if defined(OS_ANDROID) | 2625 #if defined(OS_ANDROID) |
2704 // Release AndroidProviderBackend before other objects. | 2626 // Release AndroidProviderBackend before other objects. |
2705 android_provider_backend_.reset(); | 2627 android_provider_backend_.reset(); |
2706 #endif | 2628 #endif |
2707 | 2629 |
2708 // The expirer keeps tabs on the active databases. Tell it about the | 2630 // The expirer keeps tabs on the active databases. Tell it about the |
2709 // databases which will be closed. | 2631 // databases which will be closed. |
2710 expirer_.SetDatabases(NULL, NULL, NULL); | 2632 expirer_.SetDatabases(NULL, NULL); |
2711 | 2633 |
2712 // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). | 2634 // Reopen a new transaction for |db_| for the sake of CloseAllDatabases(). |
2713 db_->BeginTransaction(); | 2635 db_->BeginTransaction(); |
2714 CloseAllDatabases(); | 2636 CloseAllDatabases(); |
2715 } | 2637 } |
2716 | 2638 |
2717 void HistoryBackend::ProcessDBTask( | 2639 void HistoryBackend::ProcessDBTask( |
2718 scoped_refptr<HistoryDBTaskRequest> request) { | 2640 scoped_refptr<HistoryDBTaskRequest> request) { |
2719 DCHECK(request.get()); | 2641 DCHECK(request.get()); |
2720 if (request->canceled()) | 2642 if (request->canceled()) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2789 // history, we should delete as much as we can. | 2711 // history, we should delete as much as we can. |
2790 } | 2712 } |
2791 | 2713 |
2792 // ClearAllMainHistory will change the IDs of the URLs in kept_urls. | 2714 // ClearAllMainHistory will change the IDs of the URLs in kept_urls. |
2793 // Therefore, we clear the list afterwards to make sure nobody uses this | 2715 // Therefore, we clear the list afterwards to make sure nobody uses this |
2794 // invalid data. | 2716 // invalid data. |
2795 if (!ClearAllMainHistory(kept_urls)) | 2717 if (!ClearAllMainHistory(kept_urls)) |
2796 LOG(ERROR) << "Main history could not be cleared"; | 2718 LOG(ERROR) << "Main history could not be cleared"; |
2797 kept_urls.clear(); | 2719 kept_urls.clear(); |
2798 | 2720 |
2799 // Delete archived history. | |
2800 if (archived_db_) { | |
2801 // Close the database and delete the file. | |
2802 archived_db_.reset(); | |
2803 base::FilePath archived_file_name = GetArchivedFileName(); | |
2804 sql::Connection::Delete(archived_file_name); | |
2805 | |
2806 // Now re-initialize the database (which may fail). | |
2807 archived_db_.reset(new ArchivedDatabase()); | |
2808 if (!archived_db_->Init(archived_file_name)) { | |
2809 LOG(WARNING) << "Could not initialize the archived database."; | |
2810 archived_db_.reset(); | |
2811 } else { | |
2812 // Open our long-running transaction on this database. | |
2813 archived_db_->BeginTransaction(); | |
2814 } | |
2815 } | |
2816 | |
2817 db_->GetStartDate(&first_recorded_time_); | 2721 db_->GetStartDate(&first_recorded_time_); |
2818 | 2722 |
2819 // Send out the notification that history is cleared. The in-memory database | 2723 // Send out the notification that history is cleared. The in-memory database |
2820 // will pick this up and clear itself. | 2724 // will pick this up and clear itself. |
2821 scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); | 2725 scoped_ptr<URLsDeletedDetails> details(new URLsDeletedDetails); |
2822 details->all_history = true; | 2726 details->all_history = true; |
2823 NotifySyncURLsDeleted(true, false, NULL); | 2727 NotifySyncURLsDeleted(true, false, NULL); |
2824 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, | 2728 BroadcastNotifications(chrome::NOTIFICATION_HISTORY_URLS_DELETED, |
2825 details.PassAs<HistoryDetails>()); | 2729 details.PassAs<HistoryDetails>()); |
2826 } | 2730 } |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2937 int rank = kPageVisitStatsMaxTopSites; | 2841 int rank = kPageVisitStatsMaxTopSites; |
2938 std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); | 2842 std::map<GURL, int>::const_iterator it = most_visited_urls_map_.find(url); |
2939 if (it != most_visited_urls_map_.end()) | 2843 if (it != most_visited_urls_map_.end()) |
2940 rank = (*it).second; | 2844 rank = (*it).second; |
2941 UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", | 2845 UMA_HISTOGRAM_ENUMERATION("History.TopSitesVisitsByRank", |
2942 rank, kPageVisitStatsMaxTopSites + 1); | 2846 rank, kPageVisitStatsMaxTopSites + 1); |
2943 } | 2847 } |
2944 #endif | 2848 #endif |
2945 | 2849 |
2946 } // namespace history | 2850 } // namespace history |
OLD | NEW |