1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian 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
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_history_api.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/callback.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_writer.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/values.h"
13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "chrome/browser/extensions/extension_event_router.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_history_api_constants.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/history/history_types.h"
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_type.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace keys = extension_history_api_constants;
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace {
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochdouble MilliSecondsFromTime(const base::Time& time) {
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return 1000 * time.ToDoubleT();
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetHistoryItemDictionary(const history::URLRow& row,
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              DictionaryValue* value) {
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  value->SetString(keys::kIdKey, base::Int64ToString(row.id()));
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  value->SetString(keys::kUrlKey, row.url().spec());
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  value->SetString(keys::kTitleKey, row.title());
3472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  value->SetDouble(keys::kLastVisitdKey,
3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                   MilliSecondsFromTime(row.last_visit()));
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  value->SetInteger(keys::kTypedCountKey, row.typed_count());
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  value->SetInteger(keys::kVisitCountKey, row.visit_count());
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddHistoryNode(const history::URLRow& row, ListValue* list) {
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* dict = new DictionaryValue();
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetHistoryItemDictionary(row, dict);
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  list->Append(dict);
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetVisitInfoDictionary(const history::VisitRow& row,
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            DictionaryValue* value) {
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  value->SetString(keys::kIdKey, base::Int64ToString(row.url_id));
493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  value->SetString(keys::kVisitId, base::Int64ToString(row.visit_id));
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  value->SetDouble(keys::kVisitTime, MilliSecondsFromTime(row.visit_time));
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  value->SetString(keys::kReferringVisitId,
523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                   base::Int64ToString(row.referring_visit));
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const char* trans = PageTransition::CoreTransitionString(row.transition);
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(trans) << "Invalid transition.";
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  value->SetString(keys::kTransition, trans);
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid AddVisitNode(const history::VisitRow& row, ListValue* list) {
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* dict = new DictionaryValue();
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetVisitInfoDictionary(row, dict);
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  list->Append(dict);
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochExtensionHistoryEventRouter* ExtensionHistoryEventRouter::GetInstance() {
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return Singleton<ExtensionHistoryEventRouter>::get();
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionHistoryEventRouter::ObserveProfile(Profile* profile) {
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationSource source = Source<Profile>(profile);
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (profiles_.find(source.map_key()) == profiles_.end())
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    profiles_[source.map_key()] = profile;
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (registrar_.IsEmpty()) {
77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    registrar_.Add(this,
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationType::HISTORY_URL_VISITED,
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationService::AllSources());
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    registrar_.Add(this,
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationType::HISTORY_URLS_DELETED,
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationService::AllSources());
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
86731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionHistoryEventRouter::ExtensionHistoryEventRouter() {}
87731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
88731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickExtensionHistoryEventRouter::~ExtensionHistoryEventRouter() {}
89731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionHistoryEventRouter::Observe(NotificationType type,
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const NotificationSource& source,
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                          const NotificationDetails& details) {
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ProfileMap::iterator it = profiles_.find(source.map_key());
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (it != profiles_.end()) {
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile = it->second;
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (type.value) {
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case NotificationType::HISTORY_URL_VISITED:
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        HistoryUrlVisited(
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            profile,
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            Details<const history::URLVisitedDetails>(details).ptr());
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case NotificationType::HISTORY_URLS_DELETED:
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        HistoryUrlsRemoved(
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            profile,
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            Details<const history::URLsDeletedDetails>(details).ptr());
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED();
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionHistoryEventRouter::HistoryUrlVisited(
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile,
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const history::URLVisitedDetails* details) {
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue args;
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* dict = new DictionaryValue();
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GetHistoryItemDictionary(details->row, dict);
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  args.Append(dict);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json_args;
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json_args);
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DispatchEvent(profile, keys::kOnVisited, json_args);
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionHistoryEventRouter::HistoryUrlsRemoved(
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Profile* profile,
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const history::URLsDeletedDetails* details) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue args;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* dict = new DictionaryValue();
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dict->SetBoolean(keys::kAllHistoryKey, details->all_history);
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue* urls = new ListValue();
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (std::set<GURL>::const_iterator iterator = details->urls.begin();
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      iterator != details->urls.end();
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++iterator) {
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    urls->Append(new StringValue(iterator->spec()));
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  dict->Set(keys::kUrlsKey, urls);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  args.Append(dict);
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string json_args;
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::JSONWriter::Write(&args, false, &json_args);
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DispatchEvent(profile, keys::kOnVisitRemoved, json_args);
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ExtensionHistoryEventRouter::DispatchEvent(Profile* profile,
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                const char* event_name,
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                const std::string& json_args) {
149731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (profile && profile->GetExtensionEventRouter()) {
150731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    profile->GetExtensionEventRouter()->DispatchEventToRenderers(
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        event_name, json_args, profile, GURL());
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryFunction::Run() {
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!RunImpl()) {
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    SendResponse(false);
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryFunction::GetUrlFromValue(Value* value, GURL* url) {
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::string url_string;
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!value->GetAsString(&url_string)) {
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bad_message_ = true;
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL temp_url(url_string);
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!temp_url.is_valid()) {
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    error_ = keys::kInvalidUrlError;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  url->Swap(&temp_url);
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryFunction::GetTimeFromValue(Value* value, base::Time* time) {
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double ms_from_epoch = 0.0;
17972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!value->GetAsDouble(&ms_from_epoch)) {
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int ms_from_epoch_as_int = 0;
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!value->GetAsInteger(&ms_from_epoch_as_int))
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return false;
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ms_from_epoch = static_cast<double>(ms_from_epoch_as_int);
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The history service has seconds resolution, while javascript Date() has
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // milliseconds resolution.
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  double seconds_from_epoch = ms_from_epoch / 1000.0;
1883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // Time::FromDoubleT converts double time 0 to empty Time object. So we need
1893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // to do special handling here.
1903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  *time = (seconds_from_epoch == 0) ?
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::Time::UnixEpoch() : base::Time::FromDoubleT(seconds_from_epoch);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHistoryFunctionWithCallback::HistoryFunctionWithCallback() {
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHistoryFunctionWithCallback::~HistoryFunctionWithCallback() {
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HistoryFunctionWithCallback::RunImpl() {
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddRef();  // Balanced in SendAysncRepose() and below.
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool retval = RunAsyncImpl();
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (false == retval)
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Release();
206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return retval;
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryFunctionWithCallback::SendAsyncResponse() {
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  MessageLoop::current()->PostTask(
211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      FROM_HERE,
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewRunnableMethod(
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          this,
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          &HistoryFunctionWithCallback::SendResponseToCallback));
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HistoryFunctionWithCallback::SendResponseToCallback() {
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendResponse(true);
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Release();  // Balanced in RunImpl().
220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool GetVisitsHistoryFunction::RunAsyncImpl() {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* json;
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Value* value;
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kUrlKey, &value));
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url;
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetUrlFromValue(value, &url))
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs = profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->QueryURL(url,
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               true,  // Retrieve full history of a URL.
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               &cancelable_consumer_,
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               NewCallback(this, &GetVisitsHistoryFunction::QueryComplete));
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetVisitsHistoryFunction::QueryComplete(
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HistoryService::Handle request_service,
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    bool success,
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const history::URLRow* url_row,
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    history::VisitVector* visits) {
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue* list = new ListValue();
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (visits && !visits->empty()) {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (history::VisitVector::iterator iterator = visits->begin();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         iterator != visits->end();
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         ++iterator) {
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddVisitNode(*iterator, list);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result_.reset(list);
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendAsyncResponse();
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SearchHistoryFunction::RunAsyncImpl() {
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* json;
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Initialize the HistoryQuery
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  string16 search_text;
2653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  EXTENSION_FUNCTION_VALIDATE(json->GetString(keys::kTextKey, &search_text));
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  history::QueryOptions options;
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.SetRecentDayRange(1);
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  options.max_count = 100;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (json->HasKey(keys::kStartTimeKey)) {  // Optional.
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Value* value;
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kStartTimeKey, &value));
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXTENSION_FUNCTION_VALIDATE(GetTimeFromValue(value, &options.begin_time));
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (json->HasKey(keys::kEndTimeKey)) {  // Optional.
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    Value* value;
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kEndTimeKey, &value));
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXTENSION_FUNCTION_VALIDATE(GetTimeFromValue(value, &options.end_time));
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (json->HasKey(keys::kMaxResultsKey)) {  // Optional.
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    EXTENSION_FUNCTION_VALIDATE(json->GetInteger(keys::kMaxResultsKey,
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                                 &options.max_count));
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs = profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->QueryHistory(search_text, options, &cancelable_consumer_,
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NewCallback(this, &SearchHistoryFunction::SearchComplete));
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SearchHistoryFunction::SearchComplete(
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HistoryService::Handle request_handle,
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    history::QueryResults* results) {
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ListValue* list = new ListValue();
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (results && !results->empty()) {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (history::QueryResults::URLResultVector::const_iterator iterator =
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch            results->begin();
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         iterator != results->end();
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        ++iterator) {
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddHistoryNode(**iterator, list);
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  result_.reset(list);
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendAsyncResponse();
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool AddUrlHistoryFunction::RunImpl() {
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* json;
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Value* value;
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kUrlKey, &value));
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url;
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetUrlFromValue(value, &url))
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs = profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  hs->AddPage(url, history::SOURCE_EXTENSION);
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendResponse(true);
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DeleteUrlHistoryFunction::RunImpl() {
328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* json;
329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Value* value;
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kUrlKey, &value));
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GURL url;
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!GetUrlFromValue(value, &url))
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return false;
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs = profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->DeleteURL(url);
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendResponse(true);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DeleteRangeHistoryFunction::RunAsyncImpl() {
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DictionaryValue* json;
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &json));
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Value* value = NULL;
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kStartTimeKey, &value));
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time begin_time;
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(GetTimeFromValue(value, &begin_time));
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(json->Get(keys::kEndTimeKey, &value));
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  base::Time end_time;
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  EXTENSION_FUNCTION_VALIDATE(GetTimeFromValue(value, &end_time));
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<GURL> restrict_urls;
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs = profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->ExpireHistoryBetween(
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      restrict_urls,
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      begin_time,
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      end_time,
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &cancelable_consumer_,
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &DeleteRangeHistoryFunction::DeleteComplete));
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DeleteRangeHistoryFunction::DeleteComplete() {
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendAsyncResponse();
372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool DeleteAllHistoryFunction::RunAsyncImpl() {
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  std::set<GURL> restrict_urls;
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  HistoryService* hs = profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  hs->ExpireHistoryBetween(
378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      restrict_urls,
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      base::Time::UnixEpoch(),     // From the beginning of the epoch.
380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      base::Time::Now(),           // To the current time.
381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      &cancelable_consumer_,
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NewCallback(this, &DeleteAllHistoryFunction::DeleteComplete));
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return true;
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid DeleteAllHistoryFunction::DeleteComplete() {
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SendAsyncResponse();
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
390