Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/ui/webui/browsing_history_handler.h" | 5 #include "chrome/browser/ui/webui/browsing_history_handler.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/bind_helpers.h" | 13 #include "base/bind_helpers.h" |
| 14 #include "base/i18n/rtl.h" | 14 #include "base/i18n/rtl.h" |
| 15 #include "base/i18n/time_formatting.h" | 15 #include "base/i18n/time_formatting.h" |
| 16 #include "base/logging.h" | |
|
tsergeant
2016/09/06 23:28:25
Nit: Can this be removed?
Dan Beam
2016/09/06 23:30:22
it could but this file uses LOG() stuff
| |
| 16 #include "base/metrics/histogram_macros.h" | 17 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/strings/string16.h" | 18 #include "base/strings/string16.h" |
| 18 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/time/time.h" | 21 #include "base/time/time.h" |
| 21 #include "base/values.h" | 22 #include "base/values.h" |
| 22 #include "chrome/browser/banners/app_banner_settings_helper.h" | 23 #include "chrome/browser/banners/app_banner_settings_helper.h" |
| 23 #include "chrome/browser/bookmarks/bookmark_model_factory.h" | 24 #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| 24 #include "chrome/browser/engagement/site_engagement_service.h" | 25 #include "chrome/browser/engagement/site_engagement_service.h" |
| 25 #include "chrome/browser/favicon/fallback_icon_service_factory.h" | 26 #include "chrome/browser/favicon/fallback_icon_service_factory.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" | 69 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" |
| 69 #include "chrome/browser/supervised_user/supervised_user_service.h" | 70 #include "chrome/browser/supervised_user/supervised_user_service.h" |
| 70 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" | 71 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" |
| 71 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" | 72 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" |
| 72 #endif | 73 #endif |
| 73 | 74 |
| 74 #if BUILDFLAG(ANDROID_JAVA_UI) | 75 #if BUILDFLAG(ANDROID_JAVA_UI) |
| 75 #include "chrome/browser/android/chrome_application.h" | 76 #include "chrome/browser/android/chrome_application.h" |
| 76 #endif | 77 #endif |
| 77 | 78 |
| 79 #if !defined(OS_ANDROID) | |
| 80 #include "chrome/browser/ui/webui/md_history_ui.h" | |
| 81 #endif | |
| 82 | |
| 78 // The amount of time to wait for a response from the WebHistoryService. | 83 // The amount of time to wait for a response from the WebHistoryService. |
| 79 static const int kWebHistoryTimeoutSeconds = 3; | 84 static const int kWebHistoryTimeoutSeconds = 3; |
| 80 | 85 |
| 86 // Number of chars to truncate titles when making them "short". | |
| 87 static const size_t kShortTitleLength = 300; | |
| 88 | |
| 81 using bookmarks::BookmarkModel; | 89 using bookmarks::BookmarkModel; |
| 82 | 90 |
| 83 namespace { | 91 namespace { |
| 84 | 92 |
| 85 // Buckets for UMA histograms. | 93 // Buckets for UMA histograms. |
| 86 enum WebHistoryQueryBuckets { | 94 enum WebHistoryQueryBuckets { |
| 87 WEB_HISTORY_QUERY_FAILED = 0, | 95 WEB_HISTORY_QUERY_FAILED = 0, |
| 88 WEB_HISTORY_QUERY_SUCCEEDED, | 96 WEB_HISTORY_QUERY_SUCCEEDED, |
| 89 WEB_HISTORY_QUERY_TIMED_OUT, | 97 WEB_HISTORY_QUERY_TIMED_OUT, |
| 90 NUM_WEB_HISTORY_QUERY_BUCKETS | 98 NUM_WEB_HISTORY_QUERY_BUCKETS |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 : entry_type(EMPTY_ENTRY), is_search_result(false), blocked_visit(false) { | 195 : entry_type(EMPTY_ENTRY), is_search_result(false), blocked_visit(false) { |
| 188 } | 196 } |
| 189 | 197 |
| 190 BrowsingHistoryHandler::HistoryEntry::HistoryEntry(const HistoryEntry& other) = | 198 BrowsingHistoryHandler::HistoryEntry::HistoryEntry(const HistoryEntry& other) = |
| 191 default; | 199 default; |
| 192 | 200 |
| 193 BrowsingHistoryHandler::HistoryEntry::~HistoryEntry() { | 201 BrowsingHistoryHandler::HistoryEntry::~HistoryEntry() { |
| 194 } | 202 } |
| 195 | 203 |
| 196 void BrowsingHistoryHandler::HistoryEntry::SetUrlAndTitle( | 204 void BrowsingHistoryHandler::HistoryEntry::SetUrlAndTitle( |
| 197 base::DictionaryValue* result) const { | 205 base::DictionaryValue* result, |
| 206 bool limit_title_length) const { | |
| 198 result->SetString("url", url.spec()); | 207 result->SetString("url", url.spec()); |
| 199 | 208 |
| 200 bool using_url_as_the_title = false; | 209 bool using_url_as_the_title = false; |
| 201 base::string16 title_to_set(title); | 210 base::string16 title_to_set(title); |
| 202 if (title.empty()) { | 211 if (title.empty()) { |
| 203 using_url_as_the_title = true; | 212 using_url_as_the_title = true; |
| 204 title_to_set = base::UTF8ToUTF16(url.spec()); | 213 title_to_set = base::UTF8ToUTF16(url.spec()); |
| 205 } | 214 } |
| 206 | 215 |
| 207 // Since the title can contain BiDi text, we need to mark the text as either | 216 // Since the title can contain BiDi text, we need to mark the text as either |
| 208 // RTL or LTR, depending on the characters in the string. If we use the URL | 217 // RTL or LTR, depending on the characters in the string. If we use the URL |
| 209 // as the title, we mark the title as LTR since URLs are always treated as | 218 // as the title, we mark the title as LTR since URLs are always treated as |
| 210 // left to right strings. | 219 // left to right strings. |
| 211 if (base::i18n::IsRTL()) { | 220 if (base::i18n::IsRTL()) { |
| 212 if (using_url_as_the_title) | 221 if (using_url_as_the_title) |
| 213 base::i18n::WrapStringWithLTRFormatting(&title_to_set); | 222 base::i18n::WrapStringWithLTRFormatting(&title_to_set); |
| 214 else | 223 else |
| 215 base::i18n::AdjustStringForLocaleDirection(&title_to_set); | 224 base::i18n::AdjustStringForLocaleDirection(&title_to_set); |
| 216 } | 225 } |
| 217 result->SetString("title", title_to_set); | 226 |
| 227 result->SetString("title", | |
| 228 limit_title_length ? title_to_set.substr(0, kShortTitleLength) | |
| 229 : title_to_set); | |
| 218 } | 230 } |
| 219 | 231 |
| 220 std::unique_ptr<base::DictionaryValue> | 232 std::unique_ptr<base::DictionaryValue> |
| 221 BrowsingHistoryHandler::HistoryEntry::ToValue( | 233 BrowsingHistoryHandler::HistoryEntry::ToValue( |
| 222 BookmarkModel* bookmark_model, | 234 BookmarkModel* bookmark_model, |
| 223 SupervisedUserService* supervised_user_service, | 235 SupervisedUserService* supervised_user_service, |
| 224 const ProfileSyncService* sync_service) const { | 236 const ProfileSyncService* sync_service, |
| 237 bool limit_title_length) const { | |
| 225 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); | 238 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); |
| 226 SetUrlAndTitle(result.get()); | 239 SetUrlAndTitle(result.get(), limit_title_length); |
| 227 | 240 |
| 228 base::string16 domain = url_formatter::IDNToUnicode(url.host()); | 241 base::string16 domain = url_formatter::IDNToUnicode(url.host()); |
| 229 // When the domain is empty, use the scheme instead. This allows for a | 242 // When the domain is empty, use the scheme instead. This allows for a |
| 230 // sensible treatment of e.g. file: URLs when group by domain is on. | 243 // sensible treatment of e.g. file: URLs when group by domain is on. |
| 231 if (domain.empty()) | 244 if (domain.empty()) |
| 232 domain = base::UTF8ToUTF16(url.scheme() + ":"); | 245 domain = base::UTF8ToUTF16(url.scheme() + ":"); |
| 233 | 246 |
| 234 // The items which are to be written into result are also described in | 247 // The items which are to be written into result are also described in |
| 235 // chrome/browser/resources/history/history.js in @typedef for | 248 // chrome/browser/resources/history/history.js in @typedef for |
| 236 // HistoryEntry. Please update it whenever you add or remove | 249 // HistoryEntry. Please update it whenever you add or remove |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 | 704 |
| 692 if (entry->entry_type != it->entry_type) { | 705 if (entry->entry_type != it->entry_type) { |
| 693 entry->entry_type = | 706 entry->entry_type = |
| 694 BrowsingHistoryHandler::HistoryEntry::COMBINED_ENTRY; | 707 BrowsingHistoryHandler::HistoryEntry::COMBINED_ENTRY; |
| 695 } | 708 } |
| 696 } | 709 } |
| 697 } | 710 } |
| 698 results->swap(new_results); | 711 results->swap(new_results); |
| 699 } | 712 } |
| 700 | 713 |
| 714 void BrowsingHistoryHandler::QueryComplete( | |
| 715 const base::string16& search_text, | |
| 716 const history::QueryOptions& options, | |
| 717 history::QueryResults* results) { | |
| 718 DCHECK_EQ(0U, query_results_.size()); | |
| 719 query_results_.reserve(results->size()); | |
| 720 | |
| 721 for (size_t i = 0; i < results->size(); ++i) { | |
| 722 history::URLResult const &page = (*results)[i]; | |
| 723 // TODO(dubroy): Use sane time (crbug.com/146090) here when it's ready. | |
| 724 query_results_.push_back( | |
| 725 HistoryEntry( | |
| 726 HistoryEntry::LOCAL_ENTRY, | |
| 727 page.url(), | |
| 728 page.title(), | |
| 729 page.visit_time(), | |
| 730 std::string(), | |
| 731 !search_text.empty(), | |
| 732 page.snippet().text(), | |
| 733 page.blocked_visit())); | |
| 734 } | |
| 735 | |
| 736 // The items which are to be written into results_info_value_ are also | |
| 737 // described in chrome/browser/resources/history/history.js in @typedef for | |
| 738 // HistoryQuery. Please update it whenever you add or remove any keys in | |
| 739 // results_info_value_. | |
| 740 results_info_value_.SetString("term", search_text); | |
| 741 results_info_value_.SetBoolean("finished", results->reached_beginning()); | |
| 742 | |
| 743 // Add the specific dates that were searched to display them. | |
| 744 // TODO(sergiu): Put today if the start is in the future. | |
| 745 results_info_value_.SetString("queryStartTime", | |
| 746 GetRelativeDateLocalized(options.begin_time)); | |
| 747 if (!options.end_time.is_null()) { | |
| 748 results_info_value_.SetString("queryEndTime", | |
| 749 GetRelativeDateLocalized(options.end_time - | |
| 750 base::TimeDelta::FromDays(1))); | |
| 751 } else { | |
| 752 results_info_value_.SetString("queryEndTime", | |
| 753 GetRelativeDateLocalized(base::Time::Now())); | |
| 754 } | |
| 755 if (!web_history_timer_.IsRunning()) | |
| 756 ReturnResultsToFrontEnd(); | |
| 757 } | |
| 758 | |
| 701 void BrowsingHistoryHandler::ReturnResultsToFrontEnd() { | 759 void BrowsingHistoryHandler::ReturnResultsToFrontEnd() { |
| 702 Profile* profile = Profile::FromWebUI(web_ui()); | 760 Profile* profile = Profile::FromWebUI(web_ui()); |
| 703 BookmarkModel* bookmark_model = | 761 BookmarkModel* bookmark_model = |
| 704 BookmarkModelFactory::GetForBrowserContext(profile); | 762 BookmarkModelFactory::GetForBrowserContext(profile); |
| 705 SupervisedUserService* supervised_user_service = NULL; | 763 SupervisedUserService* supervised_user_service = NULL; |
| 706 #if defined(ENABLE_SUPERVISED_USERS) | 764 #if defined(ENABLE_SUPERVISED_USERS) |
| 707 if (profile->IsSupervised()) | 765 if (profile->IsSupervised()) |
| 708 supervised_user_service = | 766 supervised_user_service = |
| 709 SupervisedUserServiceFactory::GetForProfile(profile); | 767 SupervisedUserServiceFactory::GetForProfile(profile); |
| 710 #endif | 768 #endif |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 723 if (local_result_count) { | 781 if (local_result_count) { |
| 724 // In the best case, we expect that all local results are duplicated on | 782 // In the best case, we expect that all local results are duplicated on |
| 725 // the server. Keep track of how many are missing. | 783 // the server. Keep track of how many are missing. |
| 726 int missing_count = std::count_if( | 784 int missing_count = std::count_if( |
| 727 query_results_.begin(), query_results_.end(), IsLocalOnlyResult); | 785 query_results_.begin(), query_results_.end(), IsLocalOnlyResult); |
| 728 UMA_HISTOGRAM_PERCENTAGE("WebHistory.LocalResultMissingOnServer", | 786 UMA_HISTOGRAM_PERCENTAGE("WebHistory.LocalResultMissingOnServer", |
| 729 missing_count * 100.0 / local_result_count); | 787 missing_count * 100.0 / local_result_count); |
| 730 } | 788 } |
| 731 } | 789 } |
| 732 | 790 |
| 791 bool is_md = false; | |
| 792 #if !defined(OS_ANDROID) | |
| 793 is_md = MdHistoryUI::IsEnabled(profile); | |
| 794 #endif | |
| 795 | |
| 733 // Convert the result vector into a ListValue. | 796 // Convert the result vector into a ListValue. |
| 734 base::ListValue results_value; | 797 base::ListValue results_value; |
| 735 for (std::vector<BrowsingHistoryHandler::HistoryEntry>::iterator it = | 798 for (std::vector<BrowsingHistoryHandler::HistoryEntry>::iterator it = |
| 736 query_results_.begin(); it != query_results_.end(); ++it) { | 799 query_results_.begin(); it != query_results_.end(); ++it) { |
| 737 std::unique_ptr<base::Value> value( | 800 std::unique_ptr<base::Value> value(it->ToValue( |
| 738 it->ToValue(bookmark_model, supervised_user_service, sync_service)); | 801 bookmark_model, supervised_user_service, sync_service, is_md)); |
| 739 results_value.Append(std::move(value)); | 802 results_value.Append(std::move(value)); |
| 740 } | 803 } |
| 741 | 804 |
| 742 web_ui()->CallJavascriptFunctionUnsafe("historyResult", results_info_value_, | 805 web_ui()->CallJavascriptFunctionUnsafe("historyResult", results_info_value_, |
| 743 results_value); | 806 results_value); |
| 744 web_ui()->CallJavascriptFunctionUnsafe( | 807 web_ui()->CallJavascriptFunctionUnsafe( |
| 745 "showNotification", base::FundamentalValue(has_synced_results_), | 808 "showNotification", base::FundamentalValue(has_synced_results_), |
| 746 base::FundamentalValue(has_other_forms_of_browsing_history_)); | 809 base::FundamentalValue(has_other_forms_of_browsing_history_)); |
| 747 results_info_value_.Clear(); | 810 results_info_value_.Clear(); |
| 748 query_results_.clear(); | 811 query_results_.clear(); |
| 749 web_history_query_results_.clear(); | 812 web_history_query_results_.clear(); |
| 750 } | 813 } |
| 751 | 814 |
| 752 void BrowsingHistoryHandler::QueryComplete( | |
| 753 const base::string16& search_text, | |
| 754 const history::QueryOptions& options, | |
| 755 history::QueryResults* results) { | |
| 756 DCHECK_EQ(0U, query_results_.size()); | |
| 757 query_results_.reserve(results->size()); | |
| 758 | |
| 759 for (size_t i = 0; i < results->size(); ++i) { | |
| 760 history::URLResult const &page = (*results)[i]; | |
| 761 // TODO(dubroy): Use sane time (crbug.com/146090) here when it's ready. | |
| 762 query_results_.push_back( | |
| 763 HistoryEntry( | |
| 764 HistoryEntry::LOCAL_ENTRY, | |
| 765 page.url(), | |
| 766 page.title(), | |
| 767 page.visit_time(), | |
| 768 std::string(), | |
| 769 !search_text.empty(), | |
| 770 page.snippet().text(), | |
| 771 page.blocked_visit())); | |
| 772 } | |
| 773 | |
| 774 // The items which are to be written into results_info_value_ are also | |
| 775 // described in chrome/browser/resources/history/history.js in @typedef for | |
| 776 // HistoryQuery. Please update it whenever you add or remove any keys in | |
| 777 // results_info_value_. | |
| 778 results_info_value_.SetString("term", search_text); | |
| 779 results_info_value_.SetBoolean("finished", results->reached_beginning()); | |
| 780 | |
| 781 // Add the specific dates that were searched to display them. | |
| 782 // TODO(sergiu): Put today if the start is in the future. | |
| 783 results_info_value_.SetString("queryStartTime", | |
| 784 GetRelativeDateLocalized(options.begin_time)); | |
| 785 if (!options.end_time.is_null()) { | |
| 786 results_info_value_.SetString("queryEndTime", | |
| 787 GetRelativeDateLocalized(options.end_time - | |
| 788 base::TimeDelta::FromDays(1))); | |
| 789 } else { | |
| 790 results_info_value_.SetString("queryEndTime", | |
| 791 GetRelativeDateLocalized(base::Time::Now())); | |
| 792 } | |
| 793 if (!web_history_timer_.IsRunning()) | |
| 794 ReturnResultsToFrontEnd(); | |
| 795 } | |
| 796 | |
| 797 void BrowsingHistoryHandler::WebHistoryQueryComplete( | 815 void BrowsingHistoryHandler::WebHistoryQueryComplete( |
| 798 const base::string16& search_text, | 816 const base::string16& search_text, |
| 799 const history::QueryOptions& options, | 817 const history::QueryOptions& options, |
| 800 base::TimeTicks start_time, | 818 base::TimeTicks start_time, |
| 801 history::WebHistoryService::Request* request, | 819 history::WebHistoryService::Request* request, |
| 802 const base::DictionaryValue* results_value) { | 820 const base::DictionaryValue* results_value) { |
| 803 base::TimeDelta delta = base::TimeTicks::Now() - start_time; | 821 base::TimeDelta delta = base::TimeTicks::Now() - start_time; |
| 804 UMA_HISTOGRAM_TIMES("WebHistory.ResponseTime", delta); | 822 UMA_HISTOGRAM_TIMES("WebHistory.ResponseTime", delta); |
| 805 | 823 |
| 806 // If the response came in too late, do nothing. | 824 // If the response came in too late, do nothing. |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 986 bool expired, | 1004 bool expired, |
| 987 const history::URLRows& deleted_rows, | 1005 const history::URLRows& deleted_rows, |
| 988 const std::set<GURL>& favicon_urls) { | 1006 const std::set<GURL>& favicon_urls) { |
| 989 if (all_history || DeletionsDiffer(deleted_rows, urls_to_be_deleted_)) | 1007 if (all_history || DeletionsDiffer(deleted_rows, urls_to_be_deleted_)) |
| 990 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted"); | 1008 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted"); |
| 991 } | 1009 } |
| 992 | 1010 |
| 993 void BrowsingHistoryHandler::OnWebHistoryDeleted() { | 1011 void BrowsingHistoryHandler::OnWebHistoryDeleted() { |
| 994 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted"); | 1012 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted"); |
| 995 } | 1013 } |
| OLD | NEW |