172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/history_ui.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <algorithm>
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <set>
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/i18n/time_formatting.h"
12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/singleton.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string16.h"
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_piece.h"
173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h"
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/time.h"
193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/bookmarks/bookmark_model.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_types.h"
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/metrics/user_metrics.h"
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser_list.h"
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/ui/webui/favicon_source.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/jstemplate_builder.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/time_format.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h"
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h"
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_delegate.h"
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/browser_resources.h"
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/chromium_strings.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/locale_settings.h"
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/theme_resources.h"
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "net/base/escape.h"
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h"
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Maximum number of search results to return in a given search. We should
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// eventually remove this.
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kMaxSearchResults = 100;
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HistoryHTMLSource
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHistoryUIHTMLSource::HistoryUIHTMLSource()
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : DataSource(chrome::kChromeUIHistoryHost, MessageLoop::current()) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryUIHTMLSource::StartDataRequest(const std::string& path,
58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                           bool is_incognito,
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                           int request_id) {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue localized_strings;
613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("loading",
623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_LOADING));
633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("title",
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_TITLE));
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("loading",
663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_LOADING));
673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("newest",
683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_NEWEST));
693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("newer",
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_NEWER));
713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("older",
723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_OLDER));
733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("searchresultsfor",
743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_SEARCHRESULTSFOR));
753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("history",
763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_BROWSERESULTS));
773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("cont",
783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_CONTINUED));
793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("searchbutton",
803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_SEARCH_BUTTON));
813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("noresults",
823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_NO_RESULTS));
833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("noitems",
843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_NO_ITEMS));
853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("edithistory",
863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_START_EDITING_HISTORY));
873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("doneediting",
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_STOP_EDITING_HISTORY));
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("removeselected",
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_REMOVE_SELECTED_ITEMS));
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("clearallhistory",
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_OPEN_CLEAR_BROWSING_DATA_DIALOG));
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  localized_strings.SetString("deletewarning",
943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      l10n_util::GetStringUTF16(IDS_HISTORY_DELETE_PRIOR_VISITS_WARNING));
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SetFontAndTextDirection(&localized_strings);
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static const base::StringPiece history_html(
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ResourceBundle::GetSharedInstance().GetRawDataResource(
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          IDR_HISTORY_HTML));
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const std::string full_html = jstemplate_builder::GetI18nTemplateHtml(
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      history_html, &localized_strings);
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  html_bytes->data.resize(full_html.size());
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::copy(full_html.begin(), full_html.end(), html_bytes->data.begin());
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendResponse(request_id, html_bytes);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstd::string HistoryUIHTMLSource::GetMimeType(const std::string&) const {
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return "text/html";
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HistoryHandler
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowsingHistoryHandler::BrowsingHistoryHandler()
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : search_text_() {
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowsingHistoryHandler::~BrowsingHistoryHandler() {
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cancelable_search_consumer_.CancelAllRequests();
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cancelable_delete_consumer_.CancelAllRequests();
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenWebUIMessageHandler* BrowsingHistoryHandler::Attach(WebUI* web_ui) {
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Create our favicon data source.
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Profile* profile = web_ui->GetProfile();
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  profile->GetChromeURLDataManager()->AddDataSource(
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      new FaviconSource(profile));
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return WebUIMessageHandler::Attach(web_ui);
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowsingHistoryHandler::RegisterMessages() {
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("getHistory",
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::HandleGetHistory));
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("searchHistory",
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::HandleSearchHistory));
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("removeURLsOnOneDay",
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::HandleRemoveURLsOnOneDay));
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  web_ui_->RegisterMessageCallback("clearBrowsingData",
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::HandleClearBrowsingData));
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowsingHistoryHandler::HandleGetHistory(const ListValue* args) {
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Anything in-flight is invalid.
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cancelable_search_consumer_.CancelAllRequests();
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get arguments (if any).
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int day = 0;
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ExtractIntegerValue(args, &day);
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set our query options.
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history::QueryOptions options;
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time = base::Time::Now().LocalMidnight();
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.begin_time -= base::TimeDelta::FromDays(day);
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time = base::Time::Now().LocalMidnight();
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.end_time -= base::TimeDelta::FromDays(day - 1);
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Need to remember the query string for our results.
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  search_text_ = string16();
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs =
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->QueryHistory(search_text_,
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      options,
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &cancelable_search_consumer_,
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::QueryComplete));
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowsingHistoryHandler::HandleSearchHistory(const ListValue* args) {
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Anything in-flight is invalid.
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  cancelable_search_consumer_.CancelAllRequests();
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get arguments (if any).
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int month = 0;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 query;
1823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ExtractSearchHistoryArguments(args, &month, &query);
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set the query ranges for the given month.
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history::QueryOptions options = CreateMonthQueryOptions(month);
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // When searching, limit the number of results returned.
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.max_count = kMaxSearchResults;
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Need to remember the query string for our results.
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  search_text_ = query;
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs =
19372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->QueryHistory(search_text_,
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      options,
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &cancelable_search_consumer_,
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::QueryComplete));
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowsingHistoryHandler::HandleRemoveURLsOnOneDay(const ListValue* args) {
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancelable_delete_consumer_.HasPendingRequests()) {
202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    web_ui_->CallJavascriptFunction("deleteFailed");
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get day to delete data from.
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int visit_time = 0;
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  ExtractIntegerValue(args, &visit_time);
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time::Exploded exploded;
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time::FromTimeT(
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      static_cast<time_t>(visit_time)).LocalExplode(&exploded);
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.hour = exploded.minute = exploded.second = exploded.millisecond = 0;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time begin_time = base::Time::FromLocalExploded(exploded);
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time end_time = begin_time + base::TimeDelta::FromDays(1);
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Get URLs.
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<GURL> urls;
2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  for (ListValue::const_iterator v = args->begin() + 1;
2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick       v != args->end(); ++v) {
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((*v)->GetType() != Value::TYPE_STRING)
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const StringValue* string_value = static_cast<const StringValue*>(*v);
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    string16 string16_value;
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!string_value->GetAsString(&string16_value))
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    urls.insert(GURL(string16_value));
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs =
23072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      web_ui_->GetProfile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->ExpireHistoryBetween(
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      urls, begin_time, end_time, &cancelable_delete_consumer_,
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &BrowsingHistoryHandler::RemoveComplete));
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowsingHistoryHandler::HandleClearBrowsingData(const ListValue* args) {
2373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(beng): This is an improper direct dependency on Browser. Route this
2383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // through some sort of delegate.
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Browser* browser = BrowserList::FindBrowserWithProfile(web_ui_->GetProfile());
2403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (browser)
2413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    browser->OpenClearBrowsingDataDialog();
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowsingHistoryHandler::QueryComplete(
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HistoryService::Handle request_handle,
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    history::QueryResults* results) {
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue results_value;
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time midnight_today = base::Time::Now().LocalMidnight();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (size_t i = 0; i < results->size(); ++i) {
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    history::URLResult const &page = (*results)[i];
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DictionaryValue* page_value = new DictionaryValue();
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SetURLAndTitle(page_value, page.title(), page.url());
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Need to pass the time in epoch time (fastest JS conversion).
2573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    page_value->SetInteger("time",
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        static_cast<int>(page.visit_time().ToTimeT()));
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Until we get some JS i18n infrastructure, we also need to
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // pass the dates in as strings. This could use some
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // optimization.
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Only pass in the strings we need (search results need a shortdate
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // and snippet, browse results need day and time information).
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (search_text_.empty()) {
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Figure out the relative date string.
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      string16 date_str = TimeFormat::RelativeDate(page.visit_time(),
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                                   &midnight_today);
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (date_str.empty()) {
27121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        date_str = base::TimeFormatFriendlyDate(page.visit_time());
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        date_str = l10n_util::GetStringFUTF16(
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            IDS_HISTORY_DATE_WITH_RELATIVE_TIME,
2753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick            date_str,
27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            base::TimeFormatFriendlyDate(page.visit_time()));
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
2783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      page_value->SetString("dateRelativeDay", date_str);
2793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      page_value->SetString("dateTimeOfDay",
28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          base::TimeFormatTimeOfDay(page.visit_time()));
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
2823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      page_value->SetString("dateShort",
28321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          base::TimeFormatShortDate(page.visit_time()));
2843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      page_value->SetString("snippet", page.snippet().text());
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    page_value->SetBoolean("starred",
28772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        web_ui_->GetProfile()->GetBookmarkModel()->IsBookmarked(page.url()));
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    results_value.Append(page_value);
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue info_value;
2923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  info_value.SetString("term", search_text_);
2933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  info_value.SetBoolean("finished", results->reached_beginning());
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction("historyResult", info_value, results_value);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowsingHistoryHandler::RemoveComplete() {
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Some Visits were deleted from history. Reload the list.
300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  web_ui_->CallJavascriptFunction("deleteComplete");
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid BrowsingHistoryHandler::ExtractSearchHistoryArguments(
3043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      const ListValue* args,
3053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      int* month,
3063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      string16* query) {
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CHECK(args->GetSize() == 2);
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  query->clear();
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CHECK(args->GetString(0, query));
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  string16 string16_value;
3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  CHECK(args->GetString(1, &string16_value));
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  *month = 0;
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  base::StringToInt(string16_value, month);
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochhistory::QueryOptions BrowsingHistoryHandler::CreateMonthQueryOptions(
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int month) {
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history::QueryOptions options;
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Configure the begin point of the search to the start of the
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // current month.
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time::Exploded exploded;
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time::Now().LocalMidnight().LocalExplode(&exploded);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  exploded.day_of_month = 1;
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (month == 0) {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    options.begin_time = base::Time::FromLocalExploded(exploded);
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Set the end time of this first search to null (which will
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // show results from the future, should the user's clock have
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // been set incorrectly).
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    options.end_time = base::Time();
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Set the end-time of this search to the end of the month that is
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // |depth| months before the search end point. The end time is not
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // inclusive, so we should feel free to set it to midnight on the
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // first day of the following month.
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    exploded.month -= month - 1;
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    while (exploded.month < 1) {
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exploded.month += 12;
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exploded.year--;
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    options.end_time = base::Time::FromLocalExploded(exploded);
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Set the begin-time of the search to the start of the month
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // that is |depth| months prior to search_start_.
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (exploded.month > 1) {
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exploded.month--;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exploded.month = 12;
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      exploded.year--;
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    options.begin_time = base::Time::FromLocalExploded(exploded);
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return options;
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// HistoryUIContents
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////////////
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenHistoryUI::HistoryUI(TabContents* contents) : WebUI(contents) {
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddMessageHandler((new BrowsingHistoryHandler())->Attach(this));
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryUIHTMLSource* html_source = new HistoryUIHTMLSource();
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Set up the chrome://history/ source.
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  contents->profile()->GetChromeURLDataManager()->AddDataSource(html_source);
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst GURL HistoryUI::GetHistoryURLWithSearchText(const string16& text) {
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return GURL(std::string(chrome::kChromeUIHistoryURL) + "#q=" +
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch              EscapeQueryParamValue(UTF16ToUTF8(text), true));
379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochRefCountedMemory* HistoryUI::GetFaviconResourceBytes() {
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return ResourceBundle::GetSharedInstance().
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LoadDataResourceBytes(IDR_HISTORY_FAVICON);
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
386