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 60sql::Connection* ActivityLogDatabasePolicy::GetDatabaseConnection() const { 61 return db_->GetSqlConnection(); 62} 63 64// static 65std::string ActivityLogPolicy::Util::Serialize(const base::Value* value) { 66 std::string value_as_text; 67 if (!value) { 68 value_as_text = ""; 69 } else { 70 JSONStringValueSerializer serializer(&value_as_text); 71 serializer.SerializeAndOmitBinaryValues(*value); 72 } 73 return value_as_text; 74} 75 76// static 77void ActivityLogPolicy::Util::StripPrivacySensitiveFields( 78 scoped_refptr<Action> action) { 79 // Clear incognito URLs/titles. 80 if (action->page_incognito()) { 81 action->set_page_url(GURL()); 82 action->set_page_title(""); 83 } 84 if (action->arg_incognito()) { 85 action->set_arg_url(GURL()); 86 } 87 88 // Strip query parameters, username/password, etc., from URLs. 89 if (action->page_url().is_valid() || action->arg_url().is_valid()) { 90 url_canon::Replacements<char> url_sanitizer; 91 url_sanitizer.ClearUsername(); 92 url_sanitizer.ClearPassword(); 93 url_sanitizer.ClearQuery(); 94 url_sanitizer.ClearRef(); 95 96 if (action->page_url().is_valid()) 97 action->set_page_url(action->page_url().ReplaceComponents(url_sanitizer)); 98 if (action->arg_url().is_valid()) 99 action->set_arg_url(action->arg_url().ReplaceComponents(url_sanitizer)); 100 } 101 102 // Clear WebRequest details; only keep a record of which types of 103 // modifications were performed. 104 if (action->action_type() == Action::ACTION_WEB_REQUEST) { 105 DictionaryValue* details = NULL; 106 if (action->mutable_other()->GetDictionary(constants::kActionWebRequest, 107 &details)) { 108 DictionaryValue::Iterator details_iterator(*details); 109 while (!details_iterator.IsAtEnd()) { 110 details->SetBoolean(details_iterator.key(), true); 111 details_iterator.Advance(); 112 } 113 } 114 } 115} 116 117// static 118void ActivityLogPolicy::Util::StripArguments( 119 const std::set<std::string>& api_whitelist, 120 scoped_refptr<Action> action) { 121 if (action->action_type() != Action::ACTION_API_CALL && 122 action->action_type() != Action::ACTION_API_EVENT && 123 action->action_type() != Action::ACTION_API_BLOCKED) 124 return; 125 126 if (api_whitelist.find(action->api_name()) == api_whitelist.end()) 127 action->set_args(scoped_ptr<ListValue>()); 128} 129 130// static 131base::Time ActivityLogPolicy::Util::AddDays(const base::Time& base_date, 132 int days) { 133 // To allow for time zone changes, add an additional partial day then round 134 // down to midnight. 135 return (base_date + base::TimeDelta::FromDays(days) + 136 base::TimeDelta::FromHours(4)).LocalMidnight(); 137} 138 139// static 140void ActivityLogPolicy::Util::ComputeDatabaseTimeBounds(const base::Time& now, 141 int days_ago, 142 int64* early_bound, 143 int64* late_bound) { 144 base::Time morning_midnight = now.LocalMidnight(); 145 if (days_ago == 0) { 146 *early_bound = morning_midnight.ToInternalValue(); 147 *late_bound = base::Time::Max().ToInternalValue(); 148 } else { 149 base::Time early_time = Util::AddDays(morning_midnight, -days_ago); 150 base::Time late_time = Util::AddDays(early_time, 1); 151 *early_bound = early_time.ToInternalValue(); 152 *late_bound = late_time.ToInternalValue(); 153 } 154} 155 156// static 157bool ActivityLogPolicy::Util::DropObsoleteTables(sql::Connection* db) { 158 for (size_t i = 0; i < arraysize(kObsoleteTables); i++) { 159 const char* table_name = kObsoleteTables[i]; 160 if (db->DoesTableExist(table_name)) { 161 std::string drop_statement = 162 base::StringPrintf("DROP TABLE %s", table_name); 163 if (!db->Execute(drop_statement.c_str())) { 164 return false; 165 } 166 } 167 } 168 return true; 169} 170 171} // namespace extensions 172