activity_log_policy.cc revision 3551c9c881056c480085172ff9840cab31610854
1// Copyright 2013 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/extensions/activity_log/activity_log_policy.h"
6
7#include <stdint.h>
8
9#include "base/files/file_path.h"
10#include "base/json/json_string_value_serializer.h"
11#include "base/logging.h"
12#include "base/strings/stringprintf.h"
13#include "base/time/clock.h"
14#include "base/time/time.h"
15#include "chrome/browser/extensions/activity_log/activity_action_constants.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/common/extensions/extension.h"
18#include "content/public/browser/browser_thread.h"
19#include "url/gurl.h"
20
21using content::BrowserThread;
22
23namespace constants = activity_log_constants;
24
25namespace {
26// Obsolete database tables: these should be dropped from the database if
27// found.
28const char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked",
29                                 "activitylog_urls"};
30}  // namespace
31
32namespace extensions {
33
34ActivityLogPolicy::ActivityLogPolicy(Profile* profile) {}
35
36ActivityLogPolicy::~ActivityLogPolicy() {}
37
38void ActivityLogPolicy::SetClockForTesting(scoped_ptr<base::Clock> clock) {
39  testing_clock_.reset(clock.release());
40}
41
42base::Time ActivityLogPolicy::Now() const {
43  if (testing_clock_)
44    return testing_clock_->Now();
45  else
46    return base::Time::Now();
47}
48
49ActivityLogDatabasePolicy::ActivityLogDatabasePolicy(
50    Profile* profile,
51    const base::FilePath& database_name)
52    : ActivityLogPolicy(profile) {
53  CHECK(profile);
54  base::FilePath profile_base_path = profile->GetPath();
55  db_ = new ActivityDatabase(this);
56  base::FilePath database_path = profile_base_path.Append(database_name);
57  ScheduleAndForget(db_, &ActivityDatabase::Init, database_path);
58}
59
60void ActivityLogDatabasePolicy::Flush() {
61  ScheduleAndForget(activity_database(),
62                    &ActivityDatabase::AdviseFlush,
63                    ActivityDatabase::kFlushImmediately);
64}
65
66sql::Connection* ActivityLogDatabasePolicy::GetDatabaseConnection() const {
67  return db_->GetSqlConnection();
68}
69
70// static
71std::string ActivityLogPolicy::Util::Serialize(const base::Value* value) {
72  std::string value_as_text;
73  if (!value) {
74    value_as_text = "";
75  } else {
76    JSONStringValueSerializer serializer(&value_as_text);
77    serializer.SerializeAndOmitBinaryValues(*value);
78  }
79  return value_as_text;
80}
81
82// static
83void ActivityLogPolicy::Util::StripPrivacySensitiveFields(
84    scoped_refptr<Action> action) {
85  // Clear incognito URLs/titles.
86  if (action->page_incognito()) {
87    action->set_page_url(GURL());
88    action->set_page_title("");
89  }
90  if (action->arg_incognito()) {
91    action->set_arg_url(GURL());
92  }
93
94  // Strip query parameters, username/password, etc., from URLs.
95  if (action->page_url().is_valid() || action->arg_url().is_valid()) {
96    url_canon::Replacements<char> url_sanitizer;
97    url_sanitizer.ClearUsername();
98    url_sanitizer.ClearPassword();
99    url_sanitizer.ClearQuery();
100    url_sanitizer.ClearRef();
101
102    if (action->page_url().is_valid())
103      action->set_page_url(action->page_url().ReplaceComponents(url_sanitizer));
104    if (action->arg_url().is_valid())
105      action->set_arg_url(action->arg_url().ReplaceComponents(url_sanitizer));
106  }
107
108  // Clear WebRequest details; only keep a record of which types of
109  // modifications were performed.
110  if (action->action_type() == Action::ACTION_WEB_REQUEST) {
111    DictionaryValue* details = NULL;
112    if (action->mutable_other()->GetDictionary(constants::kActionWebRequest,
113                                               &details)) {
114      DictionaryValue::Iterator details_iterator(*details);
115      while (!details_iterator.IsAtEnd()) {
116        details->SetBoolean(details_iterator.key(), true);
117        details_iterator.Advance();
118      }
119    }
120  }
121}
122
123// static
124void ActivityLogPolicy::Util::StripArguments(
125    const std::set<std::string>& api_whitelist,
126    scoped_refptr<Action> action) {
127  if (action->action_type() != Action::ACTION_API_CALL &&
128      action->action_type() != Action::ACTION_API_EVENT &&
129      action->action_type() != Action::UNUSED_ACTION_API_BLOCKED)
130    return;
131
132  if (api_whitelist.find(action->api_name()) == api_whitelist.end())
133    action->set_args(scoped_ptr<ListValue>());
134}
135
136// static
137base::Time ActivityLogPolicy::Util::AddDays(const base::Time& base_date,
138                                            int days) {
139  // To allow for time zone changes, add an additional partial day then round
140  // down to midnight.
141  return (base_date + base::TimeDelta::FromDays(days) +
142          base::TimeDelta::FromHours(4)).LocalMidnight();
143}
144
145// static
146void ActivityLogPolicy::Util::ComputeDatabaseTimeBounds(const base::Time& now,
147                                                        int days_ago,
148                                                        int64* early_bound,
149                                                        int64* late_bound) {
150  base::Time morning_midnight = now.LocalMidnight();
151  if (days_ago == 0) {
152      *early_bound = morning_midnight.ToInternalValue();
153      *late_bound = base::Time::Max().ToInternalValue();
154  } else {
155      base::Time early_time = Util::AddDays(morning_midnight, -days_ago);
156      base::Time late_time = Util::AddDays(early_time, 1);
157      *early_bound = early_time.ToInternalValue();
158      *late_bound = late_time.ToInternalValue();
159  }
160}
161
162// static
163bool ActivityLogPolicy::Util::DropObsoleteTables(sql::Connection* db) {
164  for (size_t i = 0; i < arraysize(kObsoleteTables); i++) {
165    const char* table_name = kObsoleteTables[i];
166    if (db->DoesTableExist(table_name)) {
167      std::string drop_statement =
168          base::StringPrintf("DROP TABLE %s", table_name);
169      if (!db->Execute(drop_statement.c_str())) {
170        return false;
171      }
172    }
173  }
174  return true;
175}
176
177}  // namespace extensions
178