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