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

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

Issue 8511055: Remove old history UI, and replace with history2. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Suppress bidichecker test failure. Created 9 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
« no previous file with comments | « chrome/browser/ui/webui/history2_ui.h ('k') | chrome/browser/ui/webui/history_ui.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/webui/history2_ui.h"
6
7 #include <set>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/callback_old.h"
12 #include "base/i18n/time_formatting.h"
13 #include "base/memory/singleton.h"
14 #include "base/message_loop.h"
15 #include "base/string16.h"
16 #include "base/string_number_conversions.h"
17 #include "base/string_piece.h"
18 #include "base/threading/thread.h"
19 #include "base/time.h"
20 #include "base/utf_string_conversions.h"
21 #include "base/values.h"
22 #include "chrome/browser/bookmarks/bookmark_model.h"
23 #include "chrome/browser/history/history_notifications.h"
24 #include "chrome/browser/history/history_types.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_list.h"
28 #include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
29 #include "chrome/browser/ui/webui/favicon_source.h"
30 #include "chrome/common/chrome_notification_types.h"
31 #include "chrome/common/time_format.h"
32 #include "chrome/common/url_constants.h"
33 #include "content/browser/tab_contents/tab_contents.h"
34 #include "content/browser/tab_contents/tab_contents_delegate.h"
35 #include "content/browser/user_metrics.h"
36 #include "content/public/browser/notification_details.h"
37 #include "content/public/browser/notification_source.h"
38 #include "grit/browser_resources.h"
39 #include "grit/chromium_strings.h"
40 #include "grit/generated_resources.h"
41 #include "grit/locale_settings.h"
42 #include "grit/theme_resources.h"
43 #include "grit/theme_resources_standard.h"
44 #include "net/base/escape.h"
45 #include "ui/base/l10n/l10n_util.h"
46 #include "ui/base/resource/resource_bundle.h"
47
48 // Maximum number of search results to return in a given search. We should
49 // eventually remove this.
50 static const int kMaxSearchResults = 100;
51
52 namespace {
53
54 ChromeWebUIDataSource* CreateHistory2UIHTMLSource() {
55 ChromeWebUIDataSource* source =
56 new ChromeWebUIDataSource(chrome::kChromeUIHistory2Host);
57
58 source->AddLocalizedString("loading", IDS_HISTORY_LOADING);
59 source->AddLocalizedString("title", IDS_HISTORY_TITLE);
60 source->AddLocalizedString("newest", IDS_HISTORY_NEWEST);
61 source->AddLocalizedString("newer", IDS_HISTORY_NEWER);
62 source->AddLocalizedString("older", IDS_HISTORY_OLDER);
63 source->AddLocalizedString("searchresultsfor", IDS_HISTORY_SEARCHRESULTSFOR);
64 source->AddLocalizedString("history", IDS_HISTORY_BROWSERESULTS);
65 source->AddLocalizedString("cont", IDS_HISTORY_CONTINUED);
66 source->AddLocalizedString("searchbutton", IDS_HISTORY_SEARCH_BUTTON);
67 source->AddLocalizedString("noresults", IDS_HISTORY_NO_RESULTS);
68 source->AddLocalizedString("noitems", IDS_HISTORY_NO_ITEMS);
69 source->AddLocalizedString("edithistory", IDS_HISTORY_START_EDITING_HISTORY);
70 source->AddLocalizedString("doneediting", IDS_HISTORY_STOP_EDITING_HISTORY);
71 source->AddLocalizedString("removeselected",
72 IDS_HISTORY_REMOVE_SELECTED_ITEMS);
73 source->AddLocalizedString("clearallhistory",
74 IDS_HISTORY_OPEN_CLEAR_BROWSING_DATA_DIALOG);
75 source->AddLocalizedString("deletewarning",
76 IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING);
77 source->AddLocalizedString("actionMenuDescription",
78 IDS_HISTORY_ACTION_MENU_DESCRIPTION);
79 source->AddLocalizedString("removeFromHistory", IDS_HISTORY_REMOVE_PAGE);
80 source->AddLocalizedString("moreFromSite", IDS_HISTORY_MORE_FROM_SITE);
81 source->set_json_path("strings.js");
82 source->add_resource_path("history2.js", IDR_HISTORY2_JS);
83 source->set_default_resource(IDR_HISTORY2_HTML);
84 return source;
85 };
86
87 } // namespace
88
89 ////////////////////////////////////////////////////////////////////////////////
90 //
91 // HistoryHandler
92 //
93 ////////////////////////////////////////////////////////////////////////////////
94 BrowsingHistoryHandler2::BrowsingHistoryHandler2()
95 : search_text_() {
96 }
97
98 BrowsingHistoryHandler2::~BrowsingHistoryHandler2() {
99 cancelable_search_consumer_.CancelAllRequests();
100 cancelable_delete_consumer_.CancelAllRequests();
101 }
102
103 WebUIMessageHandler* BrowsingHistoryHandler2::Attach(WebUI* web_ui) {
104 // Create our favicon data source.
105 Profile* profile = Profile::FromWebUI(web_ui);
106 profile->GetChromeURLDataManager()->AddDataSource(
107 new FaviconSource(profile, FaviconSource::FAVICON));
108
109 // Get notifications when history is cleared.
110 registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED,
111 content::Source<Profile>(profile->GetOriginalProfile()));
112 return WebUIMessageHandler::Attach(web_ui);
113 }
114
115 void BrowsingHistoryHandler2::RegisterMessages() {
116 web_ui_->RegisterMessageCallback("getHistory",
117 base::Bind(&BrowsingHistoryHandler2::HandleGetHistory,
118 base::Unretained(this)));
119 web_ui_->RegisterMessageCallback("searchHistory",
120 base::Bind(&BrowsingHistoryHandler2::HandleSearchHistory,
121 base::Unretained(this)));
122 web_ui_->RegisterMessageCallback("removeURLsOnOneDay",
123 base::Bind(&BrowsingHistoryHandler2::HandleRemoveURLsOnOneDay,
124 base::Unretained(this)));
125 web_ui_->RegisterMessageCallback("clearBrowsingData",
126 base::Bind(&BrowsingHistoryHandler2::HandleClearBrowsingData,
127 base::Unretained(this)));
128 }
129
130 void BrowsingHistoryHandler2::HandleGetHistory(const ListValue* args) {
131 // Anything in-flight is invalid.
132 cancelable_search_consumer_.CancelAllRequests();
133
134 // Get arguments (if any).
135 int day = 0;
136 ExtractIntegerValue(args, &day);
137
138 // Set our query options.
139 history::QueryOptions options;
140 options.begin_time = base::Time::Now().LocalMidnight();
141 options.begin_time -= base::TimeDelta::FromDays(day);
142 options.end_time = base::Time::Now().LocalMidnight();
143 options.end_time -= base::TimeDelta::FromDays(day - 1);
144
145 // Need to remember the query string for our results.
146 search_text_ = string16();
147
148 HistoryService* hs =
149 Profile::FromWebUI(web_ui_)->GetHistoryService(Profile::EXPLICIT_ACCESS);
150 hs->QueryHistory(search_text_,
151 options,
152 &cancelable_search_consumer_,
153 base::Bind(&BrowsingHistoryHandler2::QueryComplete,
154 base::Unretained(this)));
155 }
156
157 void BrowsingHistoryHandler2::HandleSearchHistory(const ListValue* args) {
158 // Anything in-flight is invalid.
159 cancelable_search_consumer_.CancelAllRequests();
160
161 // Get arguments (if any).
162 int month = 0;
163 string16 query;
164 ExtractSearchHistoryArguments(args, &month, &query);
165
166 // Set the query ranges for the given month.
167 history::QueryOptions options = CreateMonthQueryOptions(month);
168
169 // When searching, limit the number of results returned.
170 options.max_count = kMaxSearchResults;
171
172 // Need to remember the query string for our results.
173 search_text_ = query;
174 HistoryService* hs =
175 Profile::FromWebUI(web_ui_)->GetHistoryService(Profile::EXPLICIT_ACCESS);
176 hs->QueryHistory(search_text_,
177 options,
178 &cancelable_search_consumer_,
179 base::Bind(&BrowsingHistoryHandler2::QueryComplete,
180 base::Unretained(this)));
181 }
182
183 void BrowsingHistoryHandler2::HandleRemoveURLsOnOneDay(const ListValue* args) {
184 if (cancelable_delete_consumer_.HasPendingRequests()) {
185 web_ui_->CallJavascriptFunction("deleteFailed");
186 return;
187 }
188
189 // Get day to delete data from.
190 int visit_time = 0;
191 if (!ExtractIntegerValue(args, &visit_time)) {
192 LOG(ERROR) << "Unable to extract integer argument.";
193 web_ui_->CallJavascriptFunction("deleteFailed");
194 return;
195 }
196 base::Time::Exploded exploded;
197 base::Time::FromTimeT(
198 static_cast<time_t>(visit_time)).LocalExplode(&exploded);
199 exploded.hour = exploded.minute = exploded.second = exploded.millisecond = 0;
200 base::Time begin_time = base::Time::FromLocalExploded(exploded);
201 base::Time end_time = begin_time + base::TimeDelta::FromDays(1);
202
203 // Get URLs.
204 DCHECK(urls_to_be_deleted_.empty());
205 for (ListValue::const_iterator v = args->begin() + 1;
206 v != args->end(); ++v) {
207 if ((*v)->GetType() != Value::TYPE_STRING)
208 continue;
209 const StringValue* string_value = static_cast<const StringValue*>(*v);
210 string16 string16_value;
211 if (!string_value->GetAsString(&string16_value))
212 continue;
213
214 urls_to_be_deleted_.insert(GURL(string16_value));
215 }
216
217 HistoryService* hs =
218 Profile::FromWebUI(web_ui_)->GetHistoryService(Profile::EXPLICIT_ACCESS);
219 hs->ExpireHistoryBetween(
220 urls_to_be_deleted_, begin_time, end_time, &cancelable_delete_consumer_,
221 base::Bind(&BrowsingHistoryHandler2::RemoveComplete,
222 base::Unretained(this)));
223 }
224
225 void BrowsingHistoryHandler2::HandleClearBrowsingData(const ListValue* args) {
226 // TODO(beng): This is an improper direct dependency on Browser. Route this
227 // through some sort of delegate.
228 Profile* profile = Profile::FromWebUI(web_ui_);
229 Browser* browser = BrowserList::FindBrowserWithProfile(profile);
230 if (browser)
231 browser->OpenClearBrowsingDataDialog();
232 }
233
234 void BrowsingHistoryHandler2::QueryComplete(
235 HistoryService::Handle request_handle,
236 history::QueryResults* results) {
237
238 ListValue results_value;
239 base::Time midnight_today = base::Time::Now().LocalMidnight();
240
241 for (size_t i = 0; i < results->size(); ++i) {
242 history::URLResult const &page = (*results)[i];
243 DictionaryValue* page_value = new DictionaryValue();
244 SetURLAndTitle(page_value, page.title(), page.url());
245
246 // Need to pass the time in epoch time (fastest JS conversion).
247 page_value->SetInteger("time",
248 static_cast<int>(page.visit_time().ToTimeT()));
249
250 // Until we get some JS i18n infrastructure, we also need to
251 // pass the dates in as strings. This could use some
252 // optimization.
253
254 // Only pass in the strings we need (search results need a shortdate
255 // and snippet, browse results need day and time information).
256 if (search_text_.empty()) {
257 // Figure out the relative date string.
258 string16 date_str = TimeFormat::RelativeDate(page.visit_time(),
259 &midnight_today);
260 if (date_str.empty()) {
261 date_str = base::TimeFormatFriendlyDate(page.visit_time());
262 } else {
263 date_str = l10n_util::GetStringFUTF16(
264 IDS_HISTORY_DATE_WITH_RELATIVE_TIME,
265 date_str,
266 base::TimeFormatFriendlyDate(page.visit_time()));
267 }
268 page_value->SetString("dateRelativeDay", date_str);
269 page_value->SetString("dateTimeOfDay",
270 base::TimeFormatTimeOfDay(page.visit_time()));
271 } else {
272 page_value->SetString("dateShort",
273 base::TimeFormatShortDate(page.visit_time()));
274 page_value->SetString("snippet", page.snippet().text());
275 }
276 Profile* profile = Profile::FromWebUI(web_ui_);
277 page_value->SetBoolean("starred",
278 profile->GetBookmarkModel()->IsBookmarked(page.url()));
279 results_value.Append(page_value);
280 }
281
282 DictionaryValue info_value;
283 info_value.SetString("term", search_text_);
284 info_value.SetBoolean("finished", results->reached_beginning());
285
286 web_ui_->CallJavascriptFunction("historyResult", info_value, results_value);
287 }
288
289 void BrowsingHistoryHandler2::RemoveComplete() {
290 urls_to_be_deleted_.clear();
291
292 // Notify the page that the deletion request succeeded.
293 web_ui_->CallJavascriptFunction("deleteComplete");
294 }
295
296 void BrowsingHistoryHandler2::ExtractSearchHistoryArguments(
297 const ListValue* args,
298 int* month,
299 string16* query) {
300 *month = 0;
301 Value* list_member;
302
303 // Get search string.
304 if (args->Get(0, &list_member) &&
305 list_member->GetType() == Value::TYPE_STRING) {
306 const StringValue* string_value =
307 static_cast<const StringValue*>(list_member);
308 string_value->GetAsString(query);
309 }
310
311 // Get search month.
312 if (args->Get(1, &list_member) &&
313 list_member->GetType() == Value::TYPE_STRING) {
314 const StringValue* string_value =
315 static_cast<const StringValue*>(list_member);
316 string16 string16_value;
317 if (string_value->GetAsString(&string16_value))
318 base::StringToInt(string16_value, month);
319 }
320 }
321
322 history::QueryOptions BrowsingHistoryHandler2::CreateMonthQueryOptions(
323 int month) {
324 history::QueryOptions options;
325
326 // Configure the begin point of the search to the start of the
327 // current month.
328 base::Time::Exploded exploded;
329 base::Time::Now().LocalMidnight().LocalExplode(&exploded);
330 exploded.day_of_month = 1;
331
332 if (month == 0) {
333 options.begin_time = base::Time::FromLocalExploded(exploded);
334
335 // Set the end time of this first search to null (which will
336 // show results from the future, should the user's clock have
337 // been set incorrectly).
338 options.end_time = base::Time();
339 } else {
340 // Set the end-time of this search to the end of the month that is
341 // |depth| months before the search end point. The end time is not
342 // inclusive, so we should feel free to set it to midnight on the
343 // first day of the following month.
344 exploded.month -= month - 1;
345 while (exploded.month < 1) {
346 exploded.month += 12;
347 exploded.year--;
348 }
349 options.end_time = base::Time::FromLocalExploded(exploded);
350
351 // Set the begin-time of the search to the start of the month
352 // that is |depth| months prior to search_start_.
353 if (exploded.month > 1) {
354 exploded.month--;
355 } else {
356 exploded.month = 12;
357 exploded.year--;
358 }
359 options.begin_time = base::Time::FromLocalExploded(exploded);
360 }
361
362 return options;
363 }
364
365 void BrowsingHistoryHandler2::Observe(
366 int type,
367 const content::NotificationSource& source,
368 const content::NotificationDetails& details) {
369 if (type != chrome::NOTIFICATION_HISTORY_URLS_DELETED) {
370 NOTREACHED();
371 return;
372 }
373 history::URLsDeletedDetails* deletedDetails =
374 content::Details<history::URLsDeletedDetails>(details).ptr();
375 if (deletedDetails->urls != urls_to_be_deleted_) {
376 // Notify the page that someone else deleted from the history.
377 web_ui_->CallJavascriptFunction("historyDeleted");
378 }
379 }
380
381 ////////////////////////////////////////////////////////////////////////////////
382 //
383 // HistoryUIContents
384 //
385 ////////////////////////////////////////////////////////////////////////////////
386
387 HistoryUI2::HistoryUI2(TabContents* contents) : ChromeWebUI(contents) {
388 AddMessageHandler((new BrowsingHistoryHandler2())->Attach(this));
389
390 // Set up the chrome://history2/ source.
391 Profile* profile = Profile::FromBrowserContext(contents->browser_context());
392 profile->GetChromeURLDataManager()->AddDataSource(
393 CreateHistory2UIHTMLSource());
394 }
395
396 // static
397 const GURL HistoryUI2::GetHistoryURLWithSearchText(const string16& text) {
398 return GURL(std::string(chrome::kChromeUIHistory2URL) + "#q=" +
399 net::EscapeQueryParamValue(UTF16ToUTF8(text), true));
400 }
401
402 // static
403 RefCountedMemory* HistoryUI2::GetFaviconResourceBytes() {
404 return ResourceBundle::GetSharedInstance().
405 LoadDataResourceBytes(IDR_HISTORY_FAVICON);
406 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/webui/history2_ui.h ('k') | chrome/browser/ui/webui/history_ui.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698