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

Side by Side Diff: chrome/browser/ui/webui/browsing_history_handler.cc

Issue 2450453002: Refactor BrowsingHistoryHandler, create BrowsingHistoryService (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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" 16 #include "base/logging.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/strings/string16.h" 17 #include "base/strings/string16.h"
19 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
21 #include "base/time/time.h" 20 #include "base/time/time.h"
22 #include "base/values.h" 21 #include "base/values.h"
23 #include "chrome/browser/banners/app_banner_settings_helper.h"
24 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 22 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
25 #include "chrome/browser/engagement/site_engagement_service.h"
26 #include "chrome/browser/favicon/fallback_icon_service_factory.h" 23 #include "chrome/browser/favicon/fallback_icon_service_factory.h"
27 #include "chrome/browser/favicon/large_icon_service_factory.h" 24 #include "chrome/browser/favicon/large_icon_service_factory.h"
28 #include "chrome/browser/history/history_service_factory.h"
29 #include "chrome/browser/history/history_utils.h"
30 #include "chrome/browser/history/web_history_service_factory.h"
31 #include "chrome/browser/profiles/profile.h" 25 #include "chrome/browser/profiles/profile.h"
32 #include "chrome/browser/sync/profile_sync_service_factory.h" 26 #include "chrome/browser/sync/profile_sync_service_factory.h"
33 #include "chrome/browser/ui/browser_finder.h" 27 #include "chrome/browser/ui/browser_finder.h"
34 #include "chrome/browser/ui/chrome_pages.h" 28 #include "chrome/browser/ui/chrome_pages.h"
35 #include "chrome/browser/ui/webui/favicon_source.h" 29 #include "chrome/browser/ui/webui/favicon_source.h"
36 #include "chrome/browser/ui/webui/large_icon_source.h" 30 #include "chrome/browser/ui/webui/large_icon_source.h"
37 #include "chrome/common/features.h" 31 #include "chrome/common/features.h"
38 #include "chrome/common/pref_names.h"
39 #include "components/bookmarks/browser/bookmark_model.h" 32 #include "components/bookmarks/browser/bookmark_model.h"
40 #include "components/bookmarks/browser/bookmark_utils.h" 33 #include "components/bookmarks/browser/bookmark_utils.h"
41 #include "components/browser_sync/profile_sync_service.h" 34 #include "components/browser_sync/profile_sync_service.h"
42 #include "components/browsing_data/core/history_notice_utils.h"
43 #include "components/favicon/core/fallback_icon_service.h" 35 #include "components/favicon/core/fallback_icon_service.h"
44 #include "components/favicon/core/fallback_url_util.h" 36 #include "components/favicon/core/fallback_url_util.h"
45 #include "components/favicon/core/large_icon_service.h" 37 #include "components/favicon/core/large_icon_service.h"
46 #include "components/history/core/browser/history_service.h"
47 #include "components/history/core/browser/history_types.h"
48 #include "components/history/core/browser/web_history_service.h"
49 #include "components/keyed_service/core/service_access_type.h"
50 #include "components/prefs/pref_service.h"
51 #include "components/query_parser/snippet.h" 38 #include "components/query_parser/snippet.h"
52 #include "components/strings/grit/components_strings.h" 39 #include "components/strings/grit/components_strings.h"
53 #include "components/sync/device_info/device_info.h" 40 #include "components/sync/device_info/device_info.h"
54 #include "components/sync/device_info/device_info_tracker.h" 41 #include "components/sync/device_info/device_info_tracker.h"
55 #include "components/sync/driver/sync_service_observer.h"
56 #include "components/sync/protocol/history_delete_directive_specifics.pb.h"
57 #include "components/sync/protocol/sync_enums.pb.h"
58 #include "components/url_formatter/url_formatter.h" 42 #include "components/url_formatter/url_formatter.h"
59 #include "content/public/browser/url_data_source.h" 43 #include "content/public/browser/url_data_source.h"
60 #include "content/public/browser/web_ui.h" 44 #include "content/public/browser/web_ui.h"
61 #include "ui/base/l10n/l10n_util.h" 45 #include "ui/base/l10n/l10n_util.h"
62 #include "ui/base/l10n/time_format.h" 46 #include "ui/base/l10n/time_format.h"
63 47
64 #if defined(ENABLE_EXTENSIONS)
65 #include "chrome/browser/extensions/activity_log/activity_log.h"
66 #endif
67
68 #if defined(ENABLE_SUPERVISED_USERS) 48 #if defined(ENABLE_SUPERVISED_USERS)
69 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" 49 #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h"
70 #include "chrome/browser/supervised_user/supervised_user_service.h" 50 #include "chrome/browser/supervised_user/supervised_user_service.h"
71 #include "chrome/browser/supervised_user/supervised_user_service_factory.h" 51 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
72 #include "chrome/browser/supervised_user/supervised_user_url_filter.h" 52 #include "chrome/browser/supervised_user/supervised_user_url_filter.h"
73 #endif 53 #endif
74 54
75 #if BUILDFLAG(ANDROID_JAVA_UI) 55 #if BUILDFLAG(ANDROID_JAVA_UI)
76 #include "chrome/browser/android/chrome_application.h" 56 #include "chrome/browser/android/chrome_application.h"
77 #endif 57 #endif
78 58
79 #if !defined(OS_ANDROID) 59 #if !defined(OS_ANDROID)
80 #include "chrome/browser/ui/webui/md_history_ui.h" 60 #include "chrome/browser/ui/webui/md_history_ui.h"
81 #endif 61 #endif
82 62
83 // The amount of time to wait for a response from the WebHistoryService.
84 static const int kWebHistoryTimeoutSeconds = 3;
85
86 // Number of chars to truncate titles when making them "short". 63 // Number of chars to truncate titles when making them "short".
87 static const size_t kShortTitleLength = 300; 64 static const size_t kShortTitleLength = 300;
88 65
89 using bookmarks::BookmarkModel; 66 using bookmarks::BookmarkModel;
90 67
91 namespace { 68 namespace {
92 69
93 // Buckets for UMA histograms.
94 enum WebHistoryQueryBuckets {
95 WEB_HISTORY_QUERY_FAILED = 0,
96 WEB_HISTORY_QUERY_SUCCEEDED,
97 WEB_HISTORY_QUERY_TIMED_OUT,
98 NUM_WEB_HISTORY_QUERY_BUCKETS
99 };
100
101 // Identifiers for the type of device from which a history entry originated. 70 // Identifiers for the type of device from which a history entry originated.
102 static const char kDeviceTypeLaptop[] = "laptop"; 71 static const char kDeviceTypeLaptop[] = "laptop";
103 static const char kDeviceTypePhone[] = "phone"; 72 static const char kDeviceTypePhone[] = "phone";
104 static const char kDeviceTypeTablet[] = "tablet"; 73 static const char kDeviceTypeTablet[] = "tablet";
105 74
106 // Returns a localized version of |visit_time| including a relative 75 // Returns a localized version of |visit_time| including a relative
107 // indicator (e.g. today, yesterday). 76 // indicator (e.g. today, yesterday).
108 base::string16 GetRelativeDateLocalized(const base::Time& visit_time) { 77 base::string16 GetRelativeDateLocalized(const base::Time& visit_time) {
109 base::Time midnight = base::Time::Now().LocalMidnight(); 78 base::Time midnight = base::Time::Now().LocalMidnight();
110 base::string16 date_str = ui::TimeFormat::RelativeDate(visit_time, &midnight); 79 base::string16 date_str = ui::TimeFormat::RelativeDate(visit_time, &midnight);
(...skipping 10 matching lines...) Expand all
121 90
122 // Sets the correct year when substracting months from a date. 91 // Sets the correct year when substracting months from a date.
123 void NormalizeMonths(base::Time::Exploded* exploded) { 92 void NormalizeMonths(base::Time::Exploded* exploded) {
124 // Decrease a year at a time until we have a proper date. 93 // Decrease a year at a time until we have a proper date.
125 while (exploded->month < 1) { 94 while (exploded->month < 1) {
126 exploded->month += 12; 95 exploded->month += 12;
127 exploded->year--; 96 exploded->year--;
128 } 97 }
129 } 98 }
130 99
131 // Returns true if |entry| represents a local visit that had no corresponding
132 // visit on the server.
133 bool IsLocalOnlyResult(const BrowsingHistoryHandler::HistoryEntry& entry) {
134 return entry.entry_type == BrowsingHistoryHandler::HistoryEntry::LOCAL_ENTRY;
135 }
136
137 // Gets the name and type of a device for the given sync client ID. 100 // Gets the name and type of a device for the given sync client ID.
138 // |name| and |type| are out parameters. 101 // |name| and |type| are out parameters.
139 void GetDeviceNameAndType(const browser_sync::ProfileSyncService* sync_service, 102 void GetDeviceNameAndType(const browser_sync::ProfileSyncService* sync_service,
140 const std::string& client_id, 103 const std::string& client_id,
141 std::string* name, 104 std::string* name,
142 std::string* type) { 105 std::string* type) {
143 // DeviceInfoTracker must be syncing in order for remote history entries to 106 // DeviceInfoTracker must be syncing in order for remote history entries to
144 // be available. 107 // be available.
145 DCHECK(sync_service); 108 DCHECK(sync_service);
146 DCHECK(sync_service->GetDeviceInfoTracker()); 109 DCHECK(sync_service->GetDeviceInfoTracker());
(...skipping 12 matching lines...) Expand all
159 break; 122 break;
160 default: 123 default:
161 *type = kDeviceTypeLaptop; 124 *type = kDeviceTypeLaptop;
162 } 125 }
163 return; 126 return;
164 } 127 }
165 128
166 *name = l10n_util::GetStringUTF8(IDS_HISTORY_UNKNOWN_DEVICE); 129 *name = l10n_util::GetStringUTF8(IDS_HISTORY_UNKNOWN_DEVICE);
167 *type = kDeviceTypeLaptop; 130 *type = kDeviceTypeLaptop;
168 } 131 }
169 132 // Formats |entry|'s URL and title and adds them to |result|.
170 void RecordMetricsForNoticeAboutOtherFormsOfBrowsingHistory(bool shown) { 133 void SetHistoryEntryUrlAndTitle(HistoryUiService::HistoryEntry* entry,
171 UMA_HISTOGRAM_BOOLEAN( 134 base::DictionaryValue* result,
172 "History.ShownHeaderAboutOtherFormsOfBrowsingHistory", 135 bool limit_title_length) {
173 shown); 136 result->SetString("url", entry->url.spec());
174 }
175
176 } // namespace
177
178 BrowsingHistoryHandler::HistoryEntry::HistoryEntry(
179 BrowsingHistoryHandler::HistoryEntry::EntryType entry_type,
180 const GURL& url, const base::string16& title, base::Time time,
181 const std::string& client_id, bool is_search_result,
182 const base::string16& snippet, bool blocked_visit) {
183 this->entry_type = entry_type;
184 this->url = url;
185 this->title = title;
186 this->time = time;
187 this->client_id = client_id;
188 all_timestamps.insert(time.ToInternalValue());
189 this->is_search_result = is_search_result;
190 this->snippet = snippet;
191 this->blocked_visit = blocked_visit;
192 }
193
194 BrowsingHistoryHandler::HistoryEntry::HistoryEntry()
195 : entry_type(EMPTY_ENTRY), is_search_result(false), blocked_visit(false) {
196 }
197
198 BrowsingHistoryHandler::HistoryEntry::HistoryEntry(const HistoryEntry& other) =
199 default;
200
201 BrowsingHistoryHandler::HistoryEntry::~HistoryEntry() {
202 }
203
204 void BrowsingHistoryHandler::HistoryEntry::SetUrlAndTitle(
205 base::DictionaryValue* result,
206 bool limit_title_length) const {
207 result->SetString("url", url.spec());
208 137
209 bool using_url_as_the_title = false; 138 bool using_url_as_the_title = false;
210 base::string16 title_to_set(title); 139 base::string16 title_to_set(entry->title);
211 if (title.empty()) { 140 if (entry->title.empty()) {
212 using_url_as_the_title = true; 141 using_url_as_the_title = true;
213 title_to_set = base::UTF8ToUTF16(url.spec()); 142 title_to_set = base::UTF8ToUTF16(entry->url.spec());
214 } 143 }
215 144
216 // Since the title can contain BiDi text, we need to mark the text as either 145 // Since the title can contain BiDi text, we need to mark the text as either
217 // RTL or LTR, depending on the characters in the string. If we use the URL 146 // RTL or LTR, depending on the characters in the string. If we use the URL
218 // as the title, we mark the title as LTR since URLs are always treated as 147 // as the title, we mark the title as LTR since URLs are always treated as
219 // left to right strings. 148 // left to right strings.
220 if (base::i18n::IsRTL()) { 149 if (base::i18n::IsRTL()) {
221 if (using_url_as_the_title) 150 if (using_url_as_the_title)
222 base::i18n::WrapStringWithLTRFormatting(&title_to_set); 151 base::i18n::WrapStringWithLTRFormatting(&title_to_set);
223 else 152 else
224 base::i18n::AdjustStringForLocaleDirection(&title_to_set); 153 base::i18n::AdjustStringForLocaleDirection(&title_to_set);
225 } 154 }
226 155
227 result->SetString("title", 156 result->SetString("title",
228 limit_title_length ? title_to_set.substr(0, kShortTitleLength) 157 limit_title_length ? title_to_set.substr(0, kShortTitleLength)
229 : title_to_set); 158 : title_to_set);
230 } 159 }
231 160
232 std::unique_ptr<base::DictionaryValue> 161 // Converts |entry| to a DictionaryValue to be owned by the caller.
233 BrowsingHistoryHandler::HistoryEntry::ToValue( 162 std::unique_ptr<base::DictionaryValue> HistoryEntryToValue(
163 HistoryUiService::HistoryEntry* entry,
234 BookmarkModel* bookmark_model, 164 BookmarkModel* bookmark_model,
235 SupervisedUserService* supervised_user_service, 165 SupervisedUserService* supervised_user_service,
236 const browser_sync::ProfileSyncService* sync_service, 166 const browser_sync::ProfileSyncService* sync_service,
237 bool limit_title_length) const { 167 bool limit_title_length) {
238 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 168 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
239 SetUrlAndTitle(result.get(), limit_title_length); 169 SetHistoryEntryUrlAndTitle(entry, result.get(), limit_title_length);
240 170
241 base::string16 domain = url_formatter::IDNToUnicode(url.host()); 171 base::string16 domain = url_formatter::IDNToUnicode(entry->url.host());
242 // When the domain is empty, use the scheme instead. This allows for a 172 // When the domain is empty, use the scheme instead. This allows for a
243 // sensible treatment of e.g. file: URLs when group by domain is on. 173 // sensible treatment of e.g. file: URLs when group by domain is on.
244 if (domain.empty()) 174 if (domain.empty())
245 domain = base::UTF8ToUTF16(url.scheme() + ":"); 175 domain = base::UTF8ToUTF16(entry->url.scheme() + ":");
246 176
247 // The items which are to be written into result are also described in 177 // The items which are to be written into result are also described in
248 // chrome/browser/resources/history/history.js in @typedef for 178 // chrome/browser/resources/history/history.js in @typedef for
249 // HistoryEntry. Please update it whenever you add or remove 179 // HistoryEntry. Please update it whenever you add or remove
250 // any keys in result. 180 // any keys in result.
251 result->SetString("domain", domain); 181 result->SetString("domain", domain);
252 182
253 result->SetString("fallbackFaviconText", 183 result->SetString(
254 base::UTF16ToASCII(favicon::GetFallbackIconText(url))); 184 "fallbackFaviconText",
185 base::UTF16ToASCII(favicon::GetFallbackIconText(entry->url)));
255 186
256 result->SetDouble("time", time.ToJsTime()); 187 result->SetDouble("time", entry->time.ToJsTime());
257 188
258 // Pass the timestamps in a list. 189 // Pass the timestamps in a list.
259 std::unique_ptr<base::ListValue> timestamps(new base::ListValue); 190 std::unique_ptr<base::ListValue> timestamps(new base::ListValue);
260 for (std::set<int64_t>::const_iterator it = all_timestamps.begin(); 191 for (std::set<int64_t>::const_iterator it = entry->all_timestamps.begin();
261 it != all_timestamps.end(); ++it) { 192 it != entry->all_timestamps.end(); ++it) {
262 timestamps->AppendDouble(base::Time::FromInternalValue(*it).ToJsTime()); 193 timestamps->AppendDouble(base::Time::FromInternalValue(*it).ToJsTime());
263 } 194 }
264 result->Set("allTimestamps", timestamps.release()); 195 result->Set("allTimestamps", timestamps.release());
265 196
266 // Always pass the short date since it is needed both in the search and in 197 // Always pass the short date since it is needed both in the search and in
267 // the monthly view. 198 // the monthly view.
268 result->SetString("dateShort", base::TimeFormatShortDate(time)); 199 result->SetString("dateShort", base::TimeFormatShortDate(entry->time));
269 200
270 base::string16 snippet_string; 201 base::string16 snippet_string;
271 base::string16 date_relative_day; 202 base::string16 date_relative_day;
272 base::string16 date_time_of_day; 203 base::string16 date_time_of_day;
273 bool is_blocked_visit = false; 204 bool is_blocked_visit = false;
274 int host_filtering_behavior = -1; 205 int host_filtering_behavior = -1;
275 206
276 // Only pass in the strings we need (search results need a shortdate 207 // Only pass in the strings we need (search results need a shortdate
277 // and snippet, browse results need day and time information). Makes sure that 208 // and snippet, browse results need day and time information). Makes sure that
278 // values of result are never undefined 209 // values of result are never undefined
279 if (is_search_result) { 210 if (entry->is_search_result) {
280 snippet_string = snippet; 211 snippet_string = entry->snippet;
281 } else { 212 } else {
282 base::Time midnight = base::Time::Now().LocalMidnight(); 213 base::Time midnight = base::Time::Now().LocalMidnight();
283 base::string16 date_str = ui::TimeFormat::RelativeDate(time, &midnight); 214 base::string16 date_str = ui::TimeFormat::RelativeDate(entry->time,
215 &midnight);
284 if (date_str.empty()) { 216 if (date_str.empty()) {
285 date_str = base::TimeFormatFriendlyDate(time); 217 date_str = base::TimeFormatFriendlyDate(entry->time);
286 } else { 218 } else {
287 date_str = l10n_util::GetStringFUTF16( 219 date_str = l10n_util::GetStringFUTF16(
288 IDS_HISTORY_DATE_WITH_RELATIVE_TIME, 220 IDS_HISTORY_DATE_WITH_RELATIVE_TIME,
289 date_str, 221 date_str,
290 base::TimeFormatFriendlyDate(time)); 222 base::TimeFormatFriendlyDate(entry->time));
291 } 223 }
292 date_relative_day = date_str; 224 date_relative_day = date_str;
293 date_time_of_day = base::TimeFormatTimeOfDay(time); 225 date_time_of_day = base::TimeFormatTimeOfDay(entry->time);
294 } 226 }
295 227
296 std::string device_name; 228 std::string device_name;
297 std::string device_type; 229 std::string device_type;
298 if (!client_id.empty()) 230 if (!entry->client_id.empty())
299 GetDeviceNameAndType(sync_service, client_id, &device_name, &device_type); 231 GetDeviceNameAndType(sync_service, entry->client_id, &device_name,
232 &device_type);
300 result->SetString("deviceName", device_name); 233 result->SetString("deviceName", device_name);
301 result->SetString("deviceType", device_type); 234 result->SetString("deviceType", device_type);
302 235
303 #if defined(ENABLE_SUPERVISED_USERS) 236 #if defined(ENABLE_SUPERVISED_USERS)
304 if (supervised_user_service) { 237 if (supervised_user_service) {
305 const SupervisedUserURLFilter* url_filter = 238 const SupervisedUserURLFilter* url_filter =
306 supervised_user_service->GetURLFilterForUIThread(); 239 supervised_user_service->GetURLFilterForUIThread();
307 int filtering_behavior = 240 int filtering_behavior =
308 url_filter->GetFilteringBehaviorForURL(url.GetWithEmptyPath()); 241 url_filter->GetFilteringBehaviorForURL(entry->url.GetWithEmptyPath());
309 is_blocked_visit = blocked_visit; 242 is_blocked_visit = entry->blocked_visit;
310 host_filtering_behavior = filtering_behavior; 243 host_filtering_behavior = filtering_behavior;
311 } 244 }
312 #endif 245 #endif
313 246
314 result->SetString("dateTimeOfDay", date_time_of_day); 247 result->SetString("dateTimeOfDay", date_time_of_day);
315 result->SetString("dateRelativeDay", date_relative_day); 248 result->SetString("dateRelativeDay", date_relative_day);
316 result->SetString("snippet", snippet_string); 249 result->SetString("snippet", snippet_string);
317 result->SetBoolean("starred", bookmark_model->IsBookmarked(url)); 250 result->SetBoolean("starred", bookmark_model->IsBookmarked(entry->url));
318 result->SetInteger("hostFilteringBehavior", host_filtering_behavior); 251 result->SetInteger("hostFilteringBehavior", host_filtering_behavior);
319 result->SetBoolean("blockedVisit", is_blocked_visit); 252 result->SetBoolean("blockedVisit", is_blocked_visit);
320 253
321 return result; 254 return result;
322 } 255 }
323 256
324 bool BrowsingHistoryHandler::HistoryEntry::SortByTimeDescending( 257 } // namespace
325 const BrowsingHistoryHandler::HistoryEntry& entry1,
326 const BrowsingHistoryHandler::HistoryEntry& entry2) {
327 return entry1.time > entry2.time;
328 }
329 258
330 BrowsingHistoryHandler::BrowsingHistoryHandler() 259 BrowsingHistoryHandler::BrowsingHistoryHandler()
331 : has_pending_delete_request_(false), 260 : history_ui_service_(nullptr) {}
332 history_service_observer_(this),
333 web_history_service_observer_(this),
334 sync_service_observer_(this),
335 has_synced_results_(false),
336 has_other_forms_of_browsing_history_(false),
337 weak_factory_(this) {}
338 261
339 BrowsingHistoryHandler::~BrowsingHistoryHandler() { 262 BrowsingHistoryHandler::~BrowsingHistoryHandler() {
340 query_task_tracker_.TryCancelAll();
341 web_history_request_.reset();
342 } 263 }
343 264
344 void BrowsingHistoryHandler::RegisterMessages() { 265 void BrowsingHistoryHandler::RegisterMessages() {
266 history_ui_service_ =
267 std::unique_ptr<HistoryUiService>(
268 new HistoryUiService(Profile::FromWebUI(web_ui()), this));
Dan Beam 2016/11/03 03:56:34 nit: base::MakeUnique
Theresa 2016/11/03 18:09:07 Done.
269
345 // Create our favicon data source. 270 // Create our favicon data source.
346 Profile* profile = Profile::FromWebUI(web_ui()); 271 Profile* profile = Profile::FromWebUI(web_ui());
347 272
348 #if defined(OS_ANDROID) 273 #if defined(OS_ANDROID)
349 favicon::FallbackIconService* fallback_icon_service = 274 favicon::FallbackIconService* fallback_icon_service =
350 FallbackIconServiceFactory::GetForBrowserContext(profile); 275 FallbackIconServiceFactory::GetForBrowserContext(profile);
351 favicon::LargeIconService* large_icon_service = 276 favicon::LargeIconService* large_icon_service =
352 LargeIconServiceFactory::GetForBrowserContext(profile); 277 LargeIconServiceFactory::GetForBrowserContext(profile);
353 content::URLDataSource::Add( 278 content::URLDataSource::Add(
354 profile, new LargeIconSource(fallback_icon_service, large_icon_service)); 279 profile, new LargeIconSource(fallback_icon_service, large_icon_service));
355 #else 280 #else
356 content::URLDataSource::Add( 281 content::URLDataSource::Add(
357 profile, new FaviconSource(profile, FaviconSource::ANY)); 282 profile, new FaviconSource(profile, FaviconSource::ANY));
358 #endif 283 #endif
359 284
360 // Get notifications when history is cleared.
361 history::HistoryService* local_history = HistoryServiceFactory::GetForProfile(
362 profile, ServiceAccessType::EXPLICIT_ACCESS);
363 if (local_history)
364 history_service_observer_.Add(local_history);
365
366 // Get notifications when web history is deleted.
367 history::WebHistoryService* web_history =
368 WebHistoryServiceFactory::GetForProfile(profile);
369 if (web_history) {
370 web_history_service_observer_.Add(web_history);
371 } else {
372 // If |web_history| is not available, it means that the history sync is
373 // disabled. Observe |sync_service| so that we can attach the listener
374 // in case it gets enabled later.
375 browser_sync::ProfileSyncService* sync_service =
376 ProfileSyncServiceFactory::GetForProfile(profile);
377 if (sync_service)
378 sync_service_observer_.Add(sync_service);
379 }
380
381 web_ui()->RegisterMessageCallback("queryHistory", 285 web_ui()->RegisterMessageCallback("queryHistory",
382 base::Bind(&BrowsingHistoryHandler::HandleQueryHistory, 286 base::Bind(&BrowsingHistoryHandler::HandleQueryHistory,
383 base::Unretained(this))); 287 base::Unretained(this)));
384 web_ui()->RegisterMessageCallback("removeVisits", 288 web_ui()->RegisterMessageCallback("removeVisits",
385 base::Bind(&BrowsingHistoryHandler::HandleRemoveVisits, 289 base::Bind(&BrowsingHistoryHandler::HandleRemoveVisits,
386 base::Unretained(this))); 290 base::Unretained(this)));
387 web_ui()->RegisterMessageCallback("clearBrowsingData", 291 web_ui()->RegisterMessageCallback("clearBrowsingData",
388 base::Bind(&BrowsingHistoryHandler::HandleClearBrowsingData, 292 base::Bind(&BrowsingHistoryHandler::HandleClearBrowsingData,
389 base::Unretained(this))); 293 base::Unretained(this)));
390 web_ui()->RegisterMessageCallback("removeBookmark", 294 web_ui()->RegisterMessageCallback("removeBookmark",
391 base::Bind(&BrowsingHistoryHandler::HandleRemoveBookmark, 295 base::Bind(&BrowsingHistoryHandler::HandleRemoveBookmark,
392 base::Unretained(this))); 296 base::Unretained(this)));
393 } 297 }
394 298
395 bool BrowsingHistoryHandler::ExtractIntegerValueAtIndex( 299 bool BrowsingHistoryHandler::ExtractIntegerValueAtIndex(
396 const base::ListValue* value, 300 const base::ListValue* value,
397 int index, 301 int index,
398 int* out_int) { 302 int* out_int) {
399 double double_value; 303 double double_value;
400 if (value->GetDouble(index, &double_value)) { 304 if (value->GetDouble(index, &double_value)) {
401 *out_int = static_cast<int>(double_value); 305 *out_int = static_cast<int>(double_value);
402 return true; 306 return true;
403 } 307 }
404 NOTREACHED(); 308 NOTREACHED();
405 return false; 309 return false;
406 } 310 }
407 311
408 void BrowsingHistoryHandler::OnStateChanged() {
409 // If the history sync was enabled, start observing WebHistoryService.
410 // This method should not be called after we already added the observer.
411 history::WebHistoryService* web_history =
412 WebHistoryServiceFactory::GetForProfile(Profile::FromWebUI(web_ui()));
413 if (web_history) {
414 DCHECK(!web_history_service_observer_.IsObserving(web_history));
415 web_history_service_observer_.Add(web_history);
416 sync_service_observer_.RemoveAll();
417 }
418 }
419
420 void BrowsingHistoryHandler::WebHistoryTimeout() {
421 has_synced_results_ = false;
422 // TODO(dubroy): Communicate the failure to the front end.
423 if (!query_task_tracker_.HasTrackedTasks())
424 ReturnResultsToFrontEnd();
425
426 UMA_HISTOGRAM_ENUMERATION(
427 "WebHistory.QueryCompletion",
428 WEB_HISTORY_QUERY_TIMED_OUT, NUM_WEB_HISTORY_QUERY_BUCKETS);
429 }
430
431 void BrowsingHistoryHandler::QueryHistory(
432 const base::string16& search_text,
433 const history::QueryOptions& options) {
434 Profile* profile = Profile::FromWebUI(web_ui());
435
436 // Anything in-flight is invalid.
437 query_task_tracker_.TryCancelAll();
438 web_history_request_.reset();
439
440 query_results_.clear();
441 results_info_value_.Clear();
442
443 history::HistoryService* hs = HistoryServiceFactory::GetForProfile(
444 profile, ServiceAccessType::EXPLICIT_ACCESS);
445 hs->QueryHistory(search_text,
446 options,
447 base::Bind(&BrowsingHistoryHandler::QueryComplete,
448 base::Unretained(this),
449 search_text,
450 options),
451 &query_task_tracker_);
452
453 history::WebHistoryService* web_history =
454 WebHistoryServiceFactory::GetForProfile(profile);
455
456 // Set this to false until the results actually arrive.
457 results_info_value_.SetBoolean("hasSyncedResults", false);
458
459 if (web_history) {
460 web_history_query_results_.clear();
461 web_history_request_ = web_history->QueryHistory(
462 search_text,
463 options,
464 base::Bind(&BrowsingHistoryHandler::WebHistoryQueryComplete,
465 base::Unretained(this),
466 search_text, options,
467 base::TimeTicks::Now()));
468 // Start a timer so we know when to give up.
469 web_history_timer_.Start(
470 FROM_HERE, base::TimeDelta::FromSeconds(kWebHistoryTimeoutSeconds),
471 this, &BrowsingHistoryHandler::WebHistoryTimeout);
472
473 // Test the existence of other forms of browsing history.
474 browsing_data::ShouldShowNoticeAboutOtherFormsOfBrowsingHistory(
475 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile),
476 web_history,
477 base::Bind(
478 &BrowsingHistoryHandler::OtherFormsOfBrowsingHistoryQueryComplete,
479 weak_factory_.GetWeakPtr()));
480 } else {
481 // The notice could not have been shown, because there is no web history.
482 RecordMetricsForNoticeAboutOtherFormsOfBrowsingHistory(false);
483 has_synced_results_ = false;
484 has_other_forms_of_browsing_history_ = false;
485 }
486 }
487
488 void BrowsingHistoryHandler::HandleQueryHistory(const base::ListValue* args) { 312 void BrowsingHistoryHandler::HandleQueryHistory(const base::ListValue* args) {
489 history::QueryOptions options; 313 history::QueryOptions options;
490 314
491 // Parse the arguments from JavaScript. There are five required arguments: 315 // Parse the arguments from JavaScript. There are five required arguments:
492 // - the text to search for (may be empty) 316 // - the text to search for (may be empty)
493 // - the offset from which the search should start (in multiples of week or 317 // - the offset from which the search should start (in multiples of week or
494 // month, set by the next argument). 318 // month, set by the next argument).
495 // - the range (BrowsingHistoryHandler::Range) Enum value that sets the range 319 // - the range (BrowsingHistoryHandler::Range) Enum value that sets the range
496 // of the query. 320 // of the query.
497 // - the end time for the query. Only results older than this time will be 321 // - the end time for the query. Only results older than this time will be
(...skipping 24 matching lines...) Expand all
522 } 346 }
523 if (end_time) 347 if (end_time)
524 options.end_time = base::Time::FromJsTime(end_time); 348 options.end_time = base::Time::FromJsTime(end_time);
525 349
526 if (!ExtractIntegerValueAtIndex(args, 4, &options.max_count)) { 350 if (!ExtractIntegerValueAtIndex(args, 4, &options.max_count)) {
527 NOTREACHED() << "Failed to convert argument 4."; 351 NOTREACHED() << "Failed to convert argument 4.";
528 return; 352 return;
529 } 353 }
530 354
531 options.duplicate_policy = history::QueryOptions::REMOVE_DUPLICATES_PER_DAY; 355 options.duplicate_policy = history::QueryOptions::REMOVE_DUPLICATES_PER_DAY;
532 QueryHistory(search_text, options); 356 history_ui_service_->QueryHistory(search_text, options);
533 } 357 }
534 358
535 void BrowsingHistoryHandler::HandleRemoveVisits(const base::ListValue* args) { 359 void BrowsingHistoryHandler::HandleRemoveVisits(const base::ListValue* args) {
536 Profile* profile = Profile::FromWebUI(web_ui()); 360 std::vector<std::unique_ptr<HistoryUiService::HistoryEntry>> items_to_remove;
537 // TODO(davidben): history.js is not aware of this failure and will still 361 items_to_remove.reserve(args->GetSize());
538 // override |deleteCompleteCallback_|.
539 if (delete_task_tracker_.HasTrackedTasks() ||
540 has_pending_delete_request_ ||
541 !profile->GetPrefs()->GetBoolean(prefs::kAllowDeletingBrowserHistory)) {
542 web_ui()->CallJavascriptFunctionUnsafe("deleteFailed");
543 return;
544 }
545
546 history::HistoryService* history_service =
547 HistoryServiceFactory::GetForProfile(profile,
548 ServiceAccessType::EXPLICIT_ACCESS);
549 history::WebHistoryService* web_history =
550 WebHistoryServiceFactory::GetForProfile(profile);
551
552 base::Time now = base::Time::Now();
553 std::vector<history::ExpireHistoryArgs> expire_list;
554 expire_list.reserve(args->GetSize());
555
556 DCHECK(urls_to_be_deleted_.empty());
557 for (base::ListValue::const_iterator it = args->begin(); 362 for (base::ListValue::const_iterator it = args->begin();
558 it != args->end(); ++it) { 363 it != args->end(); ++it) {
559 base::DictionaryValue* deletion = NULL; 364 base::DictionaryValue* deletion = NULL;
560 base::string16 url; 365 base::string16 url;
561 base::ListValue* timestamps = NULL; 366 base::ListValue* timestamps = NULL;
562 367
563 // Each argument is a dictionary with properties "url" and "timestamps". 368 // Each argument is a dictionary with properties "url" and "timestamps".
564 if (!((*it)->GetAsDictionary(&deletion) && 369 if (!((*it)->GetAsDictionary(&deletion) &&
565 deletion->GetString("url", &url) && 370 deletion->GetString("url", &url) &&
566 deletion->GetList("timestamps", &timestamps))) { 371 deletion->GetList("timestamps", &timestamps))) {
567 NOTREACHED() << "Unable to extract arguments"; 372 NOTREACHED() << "Unable to extract arguments";
568 return; 373 return;
569 } 374 }
570 DCHECK(timestamps->GetSize() > 0); 375 DCHECK(timestamps->GetSize() > 0);
376 std::unique_ptr<HistoryUiService::HistoryEntry> entry(
377 new HistoryUiService::HistoryEntry());
571 378
572 // In order to ensure that visits will be deleted from the server and other 379 entry->url = GURL(url);
573 // clients (even if they are offline), create a sync delete directive for
574 // each visit to be deleted.
575 sync_pb::HistoryDeleteDirectiveSpecifics delete_directive;
576 sync_pb::GlobalIdDirective* global_id_directive =
577 delete_directive.mutable_global_id_directive();
578 380
579 double timestamp; 381 double timestamp;
580 history::ExpireHistoryArgs* expire_args = NULL;
581 for (base::ListValue::const_iterator ts_iterator = timestamps->begin(); 382 for (base::ListValue::const_iterator ts_iterator = timestamps->begin();
582 ts_iterator != timestamps->end(); ++ts_iterator) { 383 ts_iterator != timestamps->end(); ++ts_iterator) {
583 if (!(*ts_iterator)->GetAsDouble(&timestamp)) { 384 if (!(*ts_iterator)->GetAsDouble(&timestamp)) {
584 NOTREACHED() << "Unable to extract visit timestamp."; 385 NOTREACHED() << "Unable to extract visit timestamp.";
585 continue; 386 continue;
586 } 387 }
388
587 base::Time visit_time = base::Time::FromJsTime(timestamp); 389 base::Time visit_time = base::Time::FromJsTime(timestamp);
588 if (!expire_args) { 390 entry->all_timestamps.insert(visit_time.ToInternalValue());
589 GURL gurl(url);
590 expire_list.resize(expire_list.size() + 1);
591 expire_args = &expire_list.back();
592 expire_args->SetTimeRangeForOneDay(visit_time);
593 expire_args->urls.insert(gurl);
594 urls_to_be_deleted_.insert(gurl);
595 }
596 // The local visit time is treated as a global ID for the visit.
597 global_id_directive->add_global_id(visit_time.ToInternalValue());
598 } 391 }
599 392
600 // Set the start and end time in microseconds since the Unix epoch. 393 items_to_remove.push_back(std::move(entry));
601 global_id_directive->set_start_time_usec(
602 (expire_args->begin_time - base::Time::UnixEpoch()).InMicroseconds());
603
604 // Delete directives shouldn't have an end time in the future.
605 // TODO(dubroy): Use sane time (crbug.com/146090) here when it's ready.
606 base::Time end_time = std::min(expire_args->end_time, now);
607
608 // -1 because end time in delete directives is inclusive.
609 global_id_directive->set_end_time_usec(
610 (end_time - base::Time::UnixEpoch()).InMicroseconds() - 1);
611
612 // TODO(dubroy): Figure out the proper way to handle an error here.
613 if (web_history)
614 history_service->ProcessLocalDeleteDirective(delete_directive);
615 } 394 }
616 395
617 history_service->ExpireHistory( 396 history_ui_service_->RemoveVisits(&items_to_remove);
618 expire_list, 397 items_to_remove.clear();
619 base::Bind(&BrowsingHistoryHandler::RemoveComplete,
620 base::Unretained(this)),
621 &delete_task_tracker_);
622
623 if (web_history) {
624 has_pending_delete_request_ = true;
625 web_history->ExpireHistory(
626 expire_list,
627 base::Bind(&BrowsingHistoryHandler::RemoveWebHistoryComplete,
628 weak_factory_.GetWeakPtr()));
629 }
630
631 #if defined(ENABLE_EXTENSIONS)
632 // If the profile has activity logging enabled also clean up any URLs from
633 // the extension activity log. The extension activity log contains URLS
634 // which websites an extension has activity on so it will indirectly
635 // contain websites that a user has visited.
636 extensions::ActivityLog* activity_log =
637 extensions::ActivityLog::GetInstance(profile);
638 for (std::vector<history::ExpireHistoryArgs>::const_iterator it =
639 expire_list.begin(); it != expire_list.end(); ++it) {
640 activity_log->RemoveURLs(it->urls);
641 }
642 #endif
643
644 for (const history::ExpireHistoryArgs& expire_entry : expire_list)
645 AppBannerSettingsHelper::ClearHistoryForURLs(profile, expire_entry.urls);
646 } 398 }
647 399
648 void BrowsingHistoryHandler::HandleClearBrowsingData( 400 void BrowsingHistoryHandler::HandleClearBrowsingData(
649 const base::ListValue* args) { 401 const base::ListValue* args) {
650 #if BUILDFLAG(ANDROID_JAVA_UI) 402 #if BUILDFLAG(ANDROID_JAVA_UI)
651 chrome::android::ChromeApplication::OpenClearBrowsingData( 403 chrome::android::ChromeApplication::OpenClearBrowsingData(
652 web_ui()->GetWebContents()); 404 web_ui()->GetWebContents());
653 #else 405 #else
654 // TODO(beng): This is an improper direct dependency on Browser. Route this 406 // TODO(beng): This is an improper direct dependency on Browser. Route this
655 // through some sort of delegate. 407 // through some sort of delegate.
656 Browser* browser = chrome::FindBrowserWithWebContents( 408 Browser* browser = chrome::FindBrowserWithWebContents(
657 web_ui()->GetWebContents()); 409 web_ui()->GetWebContents());
658 chrome::ShowClearBrowsingDataDialog(browser); 410 chrome::ShowClearBrowsingDataDialog(browser);
659 #endif 411 #endif
660 } 412 }
661 413
662 void BrowsingHistoryHandler::HandleRemoveBookmark(const base::ListValue* args) { 414 void BrowsingHistoryHandler::HandleRemoveBookmark(const base::ListValue* args) {
663 base::string16 url = ExtractStringValue(args); 415 base::string16 url = ExtractStringValue(args);
664 Profile* profile = Profile::FromWebUI(web_ui()); 416 Profile* profile = Profile::FromWebUI(web_ui());
665 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile); 417 BookmarkModel* model = BookmarkModelFactory::GetForBrowserContext(profile);
666 bookmarks::RemoveAllBookmarks(model, GURL(url)); 418 bookmarks::RemoveAllBookmarks(model, GURL(url));
667 } 419 }
668 420
669 // static
670 void BrowsingHistoryHandler::MergeDuplicateResults(
671 std::vector<BrowsingHistoryHandler::HistoryEntry>* results) {
672 std::vector<BrowsingHistoryHandler::HistoryEntry> new_results;
673 // Pre-reserve the size of the new vector. Since we're working with pointers
674 // later on not doing this could lead to the vector being resized and to
675 // pointers to invalid locations.
676 new_results.reserve(results->size());
677 // Maps a URL to the most recent entry on a particular day.
678 std::map<GURL, BrowsingHistoryHandler::HistoryEntry*> current_day_entries;
679
680 // Keeps track of the day that |current_day_urls| is holding the URLs for,
681 // in order to handle removing per-day duplicates.
682 base::Time current_day_midnight;
683
684 std::sort(
685 results->begin(), results->end(), HistoryEntry::SortByTimeDescending);
686
687 for (std::vector<BrowsingHistoryHandler::HistoryEntry>::const_iterator it =
688 results->begin(); it != results->end(); ++it) {
689 // Reset the list of found URLs when a visit from a new day is encountered.
690 if (current_day_midnight != it->time.LocalMidnight()) {
691 current_day_entries.clear();
692 current_day_midnight = it->time.LocalMidnight();
693 }
694
695 // Keep this visit if it's the first visit to this URL on the current day.
696 if (current_day_entries.count(it->url) == 0) {
697 new_results.push_back(*it);
698 current_day_entries[it->url] = &new_results.back();
699 } else {
700 // Keep track of the timestamps of all visits to the URL on the same day.
701 BrowsingHistoryHandler::HistoryEntry* entry =
702 current_day_entries[it->url];
703 entry->all_timestamps.insert(
704 it->all_timestamps.begin(), it->all_timestamps.end());
705
706 if (entry->entry_type != it->entry_type) {
707 entry->entry_type =
708 BrowsingHistoryHandler::HistoryEntry::COMBINED_ENTRY;
709 }
710 }
711 }
712 results->swap(new_results);
713 }
714
715 void BrowsingHistoryHandler::QueryComplete(
716 const base::string16& search_text,
717 const history::QueryOptions& options,
718 history::QueryResults* results) {
719 DCHECK_EQ(0U, query_results_.size());
720 query_results_.reserve(results->size());
721
722 for (size_t i = 0; i < results->size(); ++i) {
723 history::URLResult const &page = (*results)[i];
724 // TODO(dubroy): Use sane time (crbug.com/146090) here when it's ready.
725 query_results_.push_back(
726 HistoryEntry(
727 HistoryEntry::LOCAL_ENTRY,
728 page.url(),
729 page.title(),
730 page.visit_time(),
731 std::string(),
732 !search_text.empty(),
733 page.snippet().text(),
734 page.blocked_visit()));
735 }
736
737 // The items which are to be written into results_info_value_ are also
738 // described in chrome/browser/resources/history/history.js in @typedef for
739 // HistoryQuery. Please update it whenever you add or remove any keys in
740 // results_info_value_.
741 results_info_value_.SetString("term", search_text);
742 results_info_value_.SetBoolean("finished", results->reached_beginning());
743
744 // Add the specific dates that were searched to display them.
745 // TODO(sergiu): Put today if the start is in the future.
746 results_info_value_.SetString("queryStartTime",
747 GetRelativeDateLocalized(options.begin_time));
748 if (!options.end_time.is_null()) {
749 results_info_value_.SetString("queryEndTime",
750 GetRelativeDateLocalized(options.end_time -
751 base::TimeDelta::FromDays(1)));
752 } else {
753 results_info_value_.SetString("queryEndTime",
754 GetRelativeDateLocalized(base::Time::Now()));
755 }
756 if (!web_history_timer_.IsRunning())
757 ReturnResultsToFrontEnd();
758 }
759
760 void BrowsingHistoryHandler::ReturnResultsToFrontEnd() {
761 Profile* profile = Profile::FromWebUI(web_ui());
762 BookmarkModel* bookmark_model =
763 BookmarkModelFactory::GetForBrowserContext(profile);
764 SupervisedUserService* supervised_user_service = NULL;
765 #if defined(ENABLE_SUPERVISED_USERS)
766 if (profile->IsSupervised())
767 supervised_user_service =
768 SupervisedUserServiceFactory::GetForProfile(profile);
769 #endif
770 browser_sync::ProfileSyncService* sync_service =
771 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
772
773 // Combine the local and remote results into |query_results_|, and remove
774 // any duplicates.
775 if (!web_history_query_results_.empty()) {
776 int local_result_count = query_results_.size();
777 query_results_.insert(query_results_.end(),
778 web_history_query_results_.begin(),
779 web_history_query_results_.end());
780 MergeDuplicateResults(&query_results_);
781
782 if (local_result_count) {
783 // In the best case, we expect that all local results are duplicated on
784 // the server. Keep track of how many are missing.
785 int missing_count = std::count_if(
786 query_results_.begin(), query_results_.end(), IsLocalOnlyResult);
787 UMA_HISTOGRAM_PERCENTAGE("WebHistory.LocalResultMissingOnServer",
788 missing_count * 100.0 / local_result_count);
789 }
790 }
791
792 bool is_md = false;
793 #if !defined(OS_ANDROID)
794 is_md = MdHistoryUI::IsEnabled(profile);
795 #endif
796
797 // Convert the result vector into a ListValue.
798 base::ListValue results_value;
799 for (std::vector<BrowsingHistoryHandler::HistoryEntry>::iterator it =
800 query_results_.begin(); it != query_results_.end(); ++it) {
801 std::unique_ptr<base::Value> value(it->ToValue(
802 bookmark_model, supervised_user_service, sync_service, is_md));
803 results_value.Append(std::move(value));
804 }
805
806 web_ui()->CallJavascriptFunctionUnsafe("historyResult", results_info_value_,
807 results_value);
808 web_ui()->CallJavascriptFunctionUnsafe(
809 "showNotification", base::FundamentalValue(has_synced_results_),
810 base::FundamentalValue(has_other_forms_of_browsing_history_));
811 results_info_value_.Clear();
812 query_results_.clear();
813 web_history_query_results_.clear();
814 }
815
816 void BrowsingHistoryHandler::WebHistoryQueryComplete(
817 const base::string16& search_text,
818 const history::QueryOptions& options,
819 base::TimeTicks start_time,
820 history::WebHistoryService::Request* request,
821 const base::DictionaryValue* results_value) {
822 base::TimeDelta delta = base::TimeTicks::Now() - start_time;
823 UMA_HISTOGRAM_TIMES("WebHistory.ResponseTime", delta);
824
825 // If the response came in too late, do nothing.
826 // TODO(dubroy): Maybe show a banner, and prompt the user to reload?
827 if (!web_history_timer_.IsRunning())
828 return;
829 web_history_timer_.Stop();
830
831 UMA_HISTOGRAM_ENUMERATION(
832 "WebHistory.QueryCompletion",
833 results_value ? WEB_HISTORY_QUERY_SUCCEEDED : WEB_HISTORY_QUERY_FAILED,
834 NUM_WEB_HISTORY_QUERY_BUCKETS);
835
836 DCHECK_EQ(0U, web_history_query_results_.size());
837 const base::ListValue* events = NULL;
838 if (results_value && results_value->GetList("event", &events)) {
839 web_history_query_results_.reserve(events->GetSize());
840 for (unsigned int i = 0; i < events->GetSize(); ++i) {
841 const base::DictionaryValue* event = NULL;
842 const base::DictionaryValue* result = NULL;
843 const base::ListValue* results = NULL;
844 const base::ListValue* ids = NULL;
845 base::string16 url;
846 base::string16 title;
847 base::Time visit_time;
848
849 if (!(events->GetDictionary(i, &event) &&
850 event->GetList("result", &results) &&
851 results->GetDictionary(0, &result) &&
852 result->GetString("url", &url) &&
853 result->GetList("id", &ids) &&
854 ids->GetSize() > 0)) {
855 LOG(WARNING) << "Improperly formed JSON response from history server.";
856 continue;
857 }
858
859 // Ignore any URLs that should not be shown in the history page.
860 GURL gurl(url);
861 if (!CanAddURLToHistory(gurl))
862 continue;
863
864 // Title is optional, so the return value is ignored here.
865 result->GetString("title", &title);
866
867 // Extract the timestamps of all the visits to this URL.
868 // They are referred to as "IDs" by the server.
869 for (int j = 0; j < static_cast<int>(ids->GetSize()); ++j) {
870 const base::DictionaryValue* id = NULL;
871 std::string timestamp_string;
872 int64_t timestamp_usec = 0;
873
874 if (!ids->GetDictionary(j, &id) ||
875 !id->GetString("timestamp_usec", &timestamp_string) ||
876 !base::StringToInt64(timestamp_string, &timestamp_usec)) {
877 NOTREACHED() << "Unable to extract timestamp.";
878 continue;
879 }
880 // The timestamp on the server is a Unix time.
881 base::Time time = base::Time::UnixEpoch() +
882 base::TimeDelta::FromMicroseconds(timestamp_usec);
883
884 // Get the ID of the client that this visit came from.
885 std::string client_id;
886 id->GetString("client_id", &client_id);
887
888 web_history_query_results_.push_back(
889 HistoryEntry(
890 HistoryEntry::REMOTE_ENTRY,
891 gurl,
892 title,
893 time,
894 client_id,
895 !search_text.empty(),
896 base::string16(),
897 /* blocked_visit */ false));
898 }
899 }
900 }
901 has_synced_results_ = results_value != nullptr;
902 results_info_value_.SetBoolean("hasSyncedResults", has_synced_results_);
903 if (!query_task_tracker_.HasTrackedTasks())
904 ReturnResultsToFrontEnd();
905 }
906
907 void BrowsingHistoryHandler::OtherFormsOfBrowsingHistoryQueryComplete(
908 bool found_other_forms_of_browsing_history) {
909 has_other_forms_of_browsing_history_ = found_other_forms_of_browsing_history;
910
911 RecordMetricsForNoticeAboutOtherFormsOfBrowsingHistory(
912 has_other_forms_of_browsing_history_);
913
914 web_ui()->CallJavascriptFunctionUnsafe(
915 "showNotification", base::FundamentalValue(has_synced_results_),
916 base::FundamentalValue(has_other_forms_of_browsing_history_));
917 }
918
919 void BrowsingHistoryHandler::RemoveComplete() {
920 urls_to_be_deleted_.clear();
921
922 // Notify the page that the deletion request is complete, but only if a web
923 // history delete request is not still pending.
924 if (!has_pending_delete_request_)
925 web_ui()->CallJavascriptFunctionUnsafe("deleteComplete");
926 }
927
928 void BrowsingHistoryHandler::RemoveWebHistoryComplete(bool success) {
929 has_pending_delete_request_ = false;
930 // TODO(dubroy): Should we handle failure somehow? Delete directives will
931 // ensure that the visits are eventually deleted, so maybe it's not necessary.
932 if (!delete_task_tracker_.HasTrackedTasks())
933 RemoveComplete();
934 }
935
936 void BrowsingHistoryHandler::SetQueryTimeInWeeks( 421 void BrowsingHistoryHandler::SetQueryTimeInWeeks(
937 int offset, history::QueryOptions* options) { 422 int offset, history::QueryOptions* options) {
938 // LocalMidnight returns the beginning of the current day so get the 423 // LocalMidnight returns the beginning of the current day so get the
939 // beginning of the next one. 424 // beginning of the next one.
940 base::Time midnight = base::Time::Now().LocalMidnight() + 425 base::Time midnight = base::Time::Now().LocalMidnight() +
941 base::TimeDelta::FromDays(1); 426 base::TimeDelta::FromDays(1);
942 options->end_time = midnight - 427 options->end_time = midnight -
943 base::TimeDelta::FromDays(7 * offset); 428 base::TimeDelta::FromDays(7 * offset);
944 options->begin_time = midnight - 429 options->begin_time = midnight -
945 base::TimeDelta::FromDays(7 * (offset + 1)); 430 base::TimeDelta::FromDays(7 * (offset + 1));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
979 exploded.month -= 1; 464 exploded.month -= 1;
980 // Set the correct year 465 // Set the correct year
981 NormalizeMonths(&exploded); 466 NormalizeMonths(&exploded);
982 if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) { 467 if (!base::Time::FromLocalExploded(exploded, &options->begin_time)) {
983 // TODO(maksims): implement errors handling here. 468 // TODO(maksims): implement errors handling here.
984 NOTIMPLEMENTED(); 469 NOTIMPLEMENTED();
985 } 470 }
986 } 471 }
987 } 472 }
988 473
989 // Helper function for Observe that determines if there are any differences 474 void BrowsingHistoryHandler::OnQueryComplete(
990 // between the URLs noticed for deletion and the ones we are expecting. 475 std::vector<HistoryUiService::HistoryEntry>* results,
991 static bool DeletionsDiffer(const history::URLRows& deleted_rows, 476 HistoryUiService::QueryResultsInfo* query_results_info) {
992 const std::set<GURL>& urls_to_be_deleted) { 477 Profile* profile = Profile::FromWebUI(web_ui());
Theresa 2016/10/24 15:40:29 This logic used to be in BrowsingHistoryHandler::R
993 if (deleted_rows.size() != urls_to_be_deleted.size()) 478 BookmarkModel* bookmark_model =
994 return true; 479 BookmarkModelFactory::GetForBrowserContext(profile);
995 for (const auto& i : deleted_rows) { 480 SupervisedUserService* supervised_user_service = NULL;
996 if (urls_to_be_deleted.find(i.url()) == urls_to_be_deleted.end()) 481 #if defined(ENABLE_SUPERVISED_USERS)
997 return true; 482 if (profile->IsSupervised())
483 supervised_user_service =
484 SupervisedUserServiceFactory::GetForProfile(profile);
485 #endif
486 browser_sync::ProfileSyncService* sync_service =
487 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
488
489 bool is_md = false;
490 #if !defined(OS_ANDROID)
491 is_md = MdHistoryUI::IsEnabled(profile);
492 #endif
493
494 // Convert the result vector into a ListValue.
495 base::ListValue results_value;
496 for (std::vector<HistoryUiService::HistoryEntry>::iterator it =
497 results->begin(); it != results->end(); ++it) {
498 std::unique_ptr<base::Value> value(HistoryEntryToValue(&(*it),
499 bookmark_model, supervised_user_service, sync_service, is_md));
500 results_value.Append(std::move(value));
998 } 501 }
999 return false; 502
503 base::DictionaryValue results_info;
504 // The items which are to be written into results_info_value_ are also
505 // described in chrome/browser/resources/history/history.js in @typedef for
506 // HistoryQuery. Please update it whenever you add or remove any keys in
507 // results_info_value_.
508 results_info.SetString("term", query_results_info->search_text);
509 results_info.SetBoolean("finished", query_results_info->reached_beginning);
510 results_info.SetBoolean("hasSyncedResults",
511 query_results_info->has_synced_results);
512
513 // Add the specific dates that were searched to display them.
514 // TODO(sergiu): Put today if the start is in the future.
515 results_info.SetString(
516 "queryStartTime",
517 GetRelativeDateLocalized(query_results_info->start_time));
518 results_info.SetString(
519 "queryEndTime",
520 GetRelativeDateLocalized(query_results_info->end_time));
521
522 web_ui()->CallJavascriptFunctionUnsafe("historyResult", results_info,
523 results_value);
1000 } 524 }
1001 525
1002 void BrowsingHistoryHandler::OnURLsDeleted( 526 void BrowsingHistoryHandler::OnRemoveVisitsComplete() {
1003 history::HistoryService* history_service, 527 web_ui()->CallJavascriptFunctionUnsafe("deleteComplete");
1004 bool all_history,
1005 bool expired,
1006 const history::URLRows& deleted_rows,
1007 const std::set<GURL>& favicon_urls) {
1008 if (all_history || DeletionsDiffer(deleted_rows, urls_to_be_deleted_))
1009 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted");
1010 } 528 }
1011 529
1012 void BrowsingHistoryHandler::OnWebHistoryDeleted() { 530 void BrowsingHistoryHandler::OnRemoveVisitsFailed() {
531 web_ui()->CallJavascriptFunctionUnsafe("deleteFailed");
532 }
533
534 void BrowsingHistoryHandler::HistoryDeleted() {
1013 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted"); 535 web_ui()->CallJavascriptFunctionUnsafe("historyDeleted");
1014 } 536 }
537
538 void BrowsingHistoryHandler::HasOtherFormsOfBrowsingHistory(
539 bool has_other_forms,
540 bool has_synced_results) {
541 web_ui()->CallJavascriptFunctionUnsafe(
542 "showNotification", base::FundamentalValue(has_synced_results),
543 base::FundamentalValue(has_other_forms));
544 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698