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) | 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |