17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file.
47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "chrome/browser/extensions/activity_log/activity_log_policy.h"
6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <stdint.h>
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/files/file_path.h"
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/json/json_string_value_serializer.h"
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/logging.h"
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/strings/stringprintf.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/time/clock.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using content::BrowserThread;
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace constants = activity_log_constants;
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace {
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Obsolete database tables: these should be dropped from the database if
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found.
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked",
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                 "activitylog_urls"};
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace extensions {
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochActivityLogPolicy::ActivityLogPolicy(Profile* profile) {}
357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ActivityLogPolicy::~ActivityLogPolicy() {}
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ActivityLogPolicy::SetClockForTesting(scoped_ptr<base::Clock> clock) {
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  testing_clock_.reset(clock.release());
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::Time ActivityLogPolicy::Now() const {
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (testing_clock_)
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return testing_clock_->Now();
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  else
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return base::Time::Now();
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)ActivityLogDatabasePolicy::ActivityLogDatabasePolicy(
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Profile* profile,
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    const base::FilePath& database_name)
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    : ActivityLogPolicy(profile) {
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  CHECK(profile);
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::FilePath profile_base_path = profile->GetPath();
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  db_ = new ActivityDatabase(this);
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  database_path_ = profile_base_path.Append(database_name);
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ActivityLogDatabasePolicy::Init() {
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScheduleAndForget(db_, &ActivityDatabase::Init, database_path_);
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ActivityLogDatabasePolicy::Flush() {
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  ScheduleAndForget(activity_database(),
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    &ActivityDatabase::AdviseFlush,
663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                    ActivityDatabase::kFlushImmediately);
673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)sql::Connection* ActivityLogDatabasePolicy::GetDatabaseConnection() const {
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return db_->GetSqlConnection();
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstd::string ActivityLogPolicy::Util::Serialize(const base::Value* value) {
75ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  std::string value_as_text;
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!value) {
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    value_as_text = "";
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    JSONStringValueSerializer serializer(&value_as_text);
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    serializer.SerializeAndOmitBinaryValues(*value);
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return value_as_text;
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ActivityLogPolicy::Util::StripPrivacySensitiveFields(
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    scoped_refptr<Action> action) {
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Clear incognito URLs/titles.
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (action->page_incognito()) {
90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    action->set_page_url(GURL());
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    action->set_page_title("");
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    action->set_page_incognito(false);
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (action->arg_incognito()) {
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    action->set_arg_url(GURL());
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    action->set_arg_incognito(false);
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Strip query parameters, username/password, etc., from URLs.
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (action->page_url().is_valid() || action->arg_url().is_valid()) {
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    url::Replacements<char> url_sanitizer;
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    url_sanitizer.ClearUsername();
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    url_sanitizer.ClearPassword();
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    url_sanitizer.ClearQuery();
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    url_sanitizer.ClearRef();
106ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
107ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (action->page_url().is_valid())
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      action->set_page_url(action->page_url().ReplaceComponents(url_sanitizer));
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (action->arg_url().is_valid())
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      action->set_arg_url(action->arg_url().ReplaceComponents(url_sanitizer));
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Clear WebRequest details; only keep a record of which types of
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // modifications were performed.
115ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (action->action_type() == Action::ACTION_WEB_REQUEST) {
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    base::DictionaryValue* details = NULL;
117ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
118ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                               &details)) {
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::DictionaryValue::Iterator details_iterator(*details);
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      while (!details_iterator.IsAtEnd()) {
121ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        details->SetBoolean(details_iterator.key(), true);
122ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        details_iterator.Advance();
123ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ActivityLogPolicy::Util::StripArguments(const ApiSet& api_whitelist,
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                             scoped_refptr<Action> action) {
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (api_whitelist.find(
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          std::make_pair(action->action_type(), action->api_name())) ==
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      api_whitelist.end()) {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    action->set_args(scoped_ptr<base::ListValue>());
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbase::Time ActivityLogPolicy::Util::AddDays(const base::Time& base_date,
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                            int days) {
141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // To allow for time zone changes, add an additional partial day then round
142ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // down to midnight.
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return (base_date + base::TimeDelta::FromDays(days) +
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          base::TimeDelta::FromHours(4)).LocalMidnight();
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ActivityLogPolicy::Util::ComputeDatabaseTimeBounds(const base::Time& now,
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                                        int days_ago,
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                                        int64* early_bound,
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                                                        int64* late_bound) {
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::Time morning_midnight = now.LocalMidnight();
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (days_ago == 0) {
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      *early_bound = morning_midnight.ToInternalValue();
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      *late_bound = base::Time::Max().ToInternalValue();
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  } else {
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Time early_time = Util::AddDays(morning_midnight, -days_ago);
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::Time late_time = Util::AddDays(early_time, 1);
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      *early_bound = early_time.ToInternalValue();
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      *late_bound = late_time.ToInternalValue();
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ActivityLogPolicy::Util::DropObsoleteTables(sql::Connection* db) {
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (size_t i = 0; i < arraysize(kObsoleteTables); i++) {
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const char* table_name = kObsoleteTables[i];
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (db->DoesTableExist(table_name)) {
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      std::string drop_statement =
170ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          base::StringPrintf("DROP TABLE %s", table_name);
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      if (!db->Execute(drop_statement.c_str())) {
172ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        return false;
173ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return true;
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
178ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace extensions
180