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