Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" | 5 #include "chrome/browser/extensions/activity_log/fullstream_ui_policy.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 using base::Callback; | 26 using base::Callback; |
| 27 using base::FilePath; | 27 using base::FilePath; |
| 28 using base::Time; | 28 using base::Time; |
| 29 using base::Unretained; | 29 using base::Unretained; |
| 30 using content::BrowserThread; | 30 using content::BrowserThread; |
| 31 | 31 |
| 32 namespace constants = activity_log_constants; | 32 namespace constants = activity_log_constants; |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 // Key strings for passing parameters to the ProcessAction member function. | |
| 37 const char kKeyReason[] = "fsuip.reason"; | |
| 38 const char kKeyDomainAction[] = "fsuip.domact"; | |
| 39 const char kKeyURLTitle[] = "fsuip.urltitle"; | |
| 40 const char kKeyDetailsString[] = "fsuip.details"; | |
| 41 | |
| 42 // Obsolete database tables: these should be dropped from the database if | |
| 43 // found. | |
| 44 const char* kObsoleteTables[] = {"activitylog_apis", "activitylog_blocked", | |
| 45 "activitylog_urls"}; | |
| 46 | |
| 47 std::string Serialize(const base::Value* value) { | 36 std::string Serialize(const base::Value* value) { |
| 48 std::string value_as_text; | 37 std::string value_as_text; |
| 49 if (!value) { | 38 if (!value) { |
| 50 value_as_text = "null"; | 39 value_as_text = "null"; |
| 51 } else { | 40 } else { |
| 52 JSONStringValueSerializer serializer(&value_as_text); | 41 JSONStringValueSerializer serializer(&value_as_text); |
| 53 serializer.SerializeAndOmitBinaryValues(*value); | 42 serializer.SerializeAndOmitBinaryValues(*value); |
| 54 } | 43 } |
| 55 return value_as_text; | 44 return value_as_text; |
| 56 } | 45 } |
| 57 | 46 |
| 58 } // namespace | 47 } // namespace |
| 59 | 48 |
| 60 namespace extensions { | 49 namespace extensions { |
| 61 | 50 |
| 62 const char* FullStreamUIPolicy::kTableName = "activitylog_full"; | 51 const char* FullStreamUIPolicy::kTableName = "activitylog_full"; |
| 63 const char* FullStreamUIPolicy::kTableContentFields[] = { | 52 const char* FullStreamUIPolicy::kTableContentFields[] = { |
| 64 "extension_id", "time", "action_type", "api_name", "args", "page_url", | 53 "extension_id", "time", "action_type", "api_name", "args", "page_url", |
| 65 "page_title", "arg_url", "other" | 54 "page_title", "arg_url", "other" |
| 66 }; | 55 }; |
| 67 const char* FullStreamUIPolicy::kTableFieldTypes[] = { | 56 const char* FullStreamUIPolicy::kTableFieldTypes[] = { |
| 68 "LONGVARCHAR NOT NULL", "INTEGER", "INTEGER", "LONGVARCHAR", "LONGVARCHAR", | 57 "LONGVARCHAR NOT NULL", "INTEGER", "INTEGER", "LONGVARCHAR", "LONGVARCHAR", |
| 69 "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR" | 58 "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR", "LONGVARCHAR" |
| 70 }; | 59 }; |
| 71 const int FullStreamUIPolicy::kTableFieldCount = arraysize(kTableContentFields); | 60 const int FullStreamUIPolicy::kTableFieldCount = |
| 61 arraysize(FullStreamUIPolicy::kTableContentFields); | |
| 72 | 62 |
| 73 FullStreamUIPolicy::FullStreamUIPolicy(Profile* profile) | 63 FullStreamUIPolicy::FullStreamUIPolicy(Profile* profile) |
| 74 : ActivityLogDatabasePolicy( | 64 : ActivityLogDatabasePolicy( |
| 75 profile, | 65 profile, |
| 76 FilePath(chrome::kExtensionActivityLogFilename)) {} | 66 FilePath(chrome::kExtensionActivityLogFilename)) {} |
| 77 | 67 |
| 78 FullStreamUIPolicy::~FullStreamUIPolicy() {} | 68 FullStreamUIPolicy::~FullStreamUIPolicy() {} |
| 79 | 69 |
| 80 bool FullStreamUIPolicy::InitDatabase(sql::Connection* db) { | 70 bool FullStreamUIPolicy::InitDatabase(sql::Connection* db) { |
| 81 // Drop old database tables. | 71 if (!Util::DropObsoleteTables(db)) |
| 82 for (size_t i = 0; i < arraysize(kObsoleteTables); i++) { | 72 return false; |
| 83 const char* table_name = kObsoleteTables[i]; | |
| 84 if (db->DoesTableExist(table_name)) { | |
| 85 std::string drop_statement = | |
| 86 base::StringPrintf("DROP TABLE %s", table_name); | |
| 87 if (!db->Execute(drop_statement.c_str())) { | |
| 88 return false; | |
| 89 } | |
| 90 } | |
| 91 } | |
| 92 | 73 |
| 93 // Create the unified activity log entry table. | 74 // Create the unified activity log entry table. |
| 94 return ActivityDatabase::InitializeTable(db, | 75 return ActivityDatabase::InitializeTable(db, |
| 95 kTableName, | 76 kTableName, |
| 96 kTableContentFields, | 77 kTableContentFields, |
| 97 kTableFieldTypes, | 78 kTableFieldTypes, |
| 98 arraysize(kTableContentFields)); | 79 arraysize(kTableContentFields)); |
| 99 } | 80 } |
| 100 | 81 |
| 101 bool FullStreamUIPolicy::FlushDatabase(sql::Connection* db) { | 82 bool FullStreamUIPolicy::FlushDatabase(sql::Connection* db) { |
| 102 if (queued_actions_.empty()) | 83 if (queued_actions_.empty()) |
| 103 return true; | 84 return true; |
| 104 | 85 |
| 105 sql::Transaction transaction(db); | 86 sql::Transaction transaction(db); |
| 106 if (!transaction.Begin()) | 87 if (!transaction.Begin()) |
| 107 return false; | 88 return false; |
| 108 | 89 |
| 109 std::string sql_str = | 90 std::string sql_str = |
| 110 "INSERT INTO " + std::string(FullStreamUIPolicy::kTableName) + | 91 "INSERT INTO " + std::string(FullStreamUIPolicy::kTableName) + |
| 111 " (extension_id, time, action_type, api_name, args, " | 92 " (extension_id, time, action_type, api_name, args, " |
| 112 "page_url, page_title, arg_url, other) VALUES (?,?,?,?,?,?,?,?,?)"; | 93 "page_url, page_title, arg_url, other) VALUES (?,?,?,?,?,?,?,?,?)"; |
| 113 sql::Statement statement(db->GetCachedStatement( | 94 sql::Statement statement(db->GetCachedStatement( |
| 114 sql::StatementID(SQL_FROM_HERE), sql_str.c_str())); | 95 sql::StatementID(SQL_FROM_HERE), sql_str.c_str())); |
| 115 | 96 |
| 116 url_canon::Replacements<char> url_sanitizer; | |
| 117 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
| 118 switches::kEnableExtensionActivityLogTesting)) { | |
| 119 url_sanitizer.ClearQuery(); | |
| 120 url_sanitizer.ClearRef(); | |
| 121 } | |
| 122 | |
| 123 Action::ActionVector::size_type i; | 97 Action::ActionVector::size_type i; |
| 124 for (i = 0; i != queued_actions_.size(); ++i) { | 98 for (i = 0; i != queued_actions_.size(); ++i) { |
| 125 const Action& action = *queued_actions_[i]; | 99 const Action& action = *queued_actions_[i]; |
| 126 statement.Reset(true); | 100 statement.Reset(true); |
| 127 statement.BindString(0, action.extension_id()); | 101 statement.BindString(0, action.extension_id()); |
| 128 statement.BindInt64(1, action.time().ToInternalValue()); | 102 statement.BindInt64(1, action.time().ToInternalValue()); |
| 129 statement.BindInt(2, static_cast<int>(action.action_type())); | 103 statement.BindInt(2, static_cast<int>(action.action_type())); |
| 130 statement.BindString(3, action.api_name()); | 104 statement.BindString(3, action.api_name()); |
| 131 if (action.args()) { | 105 if (action.args()) { |
| 132 statement.BindString(4, Serialize(action.args())); | 106 statement.BindString(4, Serialize(action.args())); |
| 133 } | 107 } |
| 134 if (action.page_url().is_valid()) { | 108 if (action.page_url().is_valid()) { |
| 135 if (action.page_incognito()) { | 109 if (action.page_incognito()) { |
| 136 statement.BindString(5, constants::kIncognitoUrl); | 110 statement.BindString(5, constants::kIncognitoUrl); |
| 137 } else { | 111 } else { |
| 138 statement.BindString( | 112 statement.BindString(5, action.page_url().spec()); |
| 139 5, action.page_url().ReplaceComponents(url_sanitizer).spec()); | |
| 140 } | 113 } |
| 141 } | 114 } |
| 142 if (!action.page_title().empty() && !action.page_incognito()) { | 115 if (!action.page_title().empty() && !action.page_incognito()) { |
| 143 statement.BindString(6, action.page_title()); | 116 statement.BindString(6, action.page_title()); |
| 144 } | 117 } |
| 145 if (action.arg_url().is_valid()) { | 118 if (action.arg_url().is_valid()) { |
| 146 if (action.arg_incognito()) { | 119 if (action.arg_incognito()) { |
| 147 statement.BindString(7, constants::kIncognitoUrl); | 120 statement.BindString(7, constants::kIncognitoUrl); |
|
felt
2013/08/07 01:09:42
Probably should have caught this before. Why are w
mvrable
2013/08/07 17:01:19
Looks like I forgot to update this code. The inte
felt
2013/08/08 02:08:50
Hmm. It seems like doing "<incognito>url" is overl
| |
| 148 } else { | 121 } else { |
| 149 statement.BindString( | 122 statement.BindString(7, action.arg_url().spec()); |
| 150 7, action.arg_url().ReplaceComponents(url_sanitizer).spec()); | |
| 151 } | 123 } |
| 152 } | 124 } |
| 153 if (action.other()) { | 125 if (action.other()) { |
| 154 statement.BindString(8, Serialize(action.other())); | 126 statement.BindString(8, Serialize(action.other())); |
| 155 } | 127 } |
| 156 | 128 |
| 157 if (!statement.Run()) { | 129 if (!statement.Run()) { |
| 158 LOG(ERROR) << "Activity log database I/O failed: " << sql_str; | 130 LOG(ERROR) << "Activity log database I/O failed: " << sql_str; |
| 159 return false; | 131 return false; |
| 160 } | 132 } |
| 161 } | 133 } |
| 162 | 134 |
| 163 if (!transaction.Commit()) | 135 if (!transaction.Commit()) |
| 164 return false; | 136 return false; |
| 165 | 137 |
| 166 queued_actions_.clear(); | 138 queued_actions_.clear(); |
| 167 return true; | 139 return true; |
| 168 } | 140 } |
| 169 | 141 |
| 170 scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadData( | 142 scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadData( |
| 171 const std::string& extension_id, | 143 const std::string& extension_id, |
| 172 const int days_ago) { | 144 const int days_ago) { |
| 145 // Ensure data is flushed to the database first so that we query over all | |
| 146 // data. | |
| 147 activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately); | |
| 148 | |
| 173 DCHECK_GE(days_ago, 0); | 149 DCHECK_GE(days_ago, 0); |
| 174 scoped_ptr<Action::ActionVector> actions(new Action::ActionVector()); | 150 scoped_ptr<Action::ActionVector> actions(new Action::ActionVector()); |
| 175 | 151 |
| 176 sql::Connection* db = GetDatabaseConnection(); | 152 sql::Connection* db = GetDatabaseConnection(); |
| 177 if (!db) { | 153 if (!db) { |
| 178 return actions.Pass(); | 154 return actions.Pass(); |
| 179 } | 155 } |
| 180 | 156 |
| 181 // Compute the time bounds for that day. | 157 int64 early_bound; |
| 182 base::Time morning_midnight = Now().LocalMidnight(); | 158 int64 late_bound; |
| 183 int64 early_bound = 0; | 159 Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound); |
| 184 int64 late_bound = 0; | |
| 185 if (days_ago == 0) { | |
| 186 early_bound = morning_midnight.ToInternalValue(); | |
| 187 late_bound = base::Time::Max().ToInternalValue(); | |
| 188 } else { | |
| 189 base::Time early_time = morning_midnight - | |
| 190 base::TimeDelta::FromDays(days_ago); | |
| 191 base::Time late_time = morning_midnight - | |
| 192 base::TimeDelta::FromDays(days_ago-1); | |
| 193 early_bound = early_time.ToInternalValue(); | |
| 194 late_bound = late_time.ToInternalValue(); | |
| 195 } | |
| 196 std::string query_str = base::StringPrintf( | 160 std::string query_str = base::StringPrintf( |
| 197 "SELECT time, action_type, api_name, args, page_url, page_title, " | 161 "SELECT time, action_type, api_name, args, page_url, page_title, " |
| 198 "arg_url, other " | 162 "arg_url, other " |
| 199 "FROM %s WHERE extension_id=? AND time>? AND time<=? " | 163 "FROM %s WHERE extension_id=? AND time>? AND time<=? " |
| 200 "ORDER BY time DESC", | 164 "ORDER BY time DESC", |
| 201 kTableName); | 165 kTableName); |
| 202 sql::Statement query(db->GetCachedStatement(SQL_FROM_HERE, | 166 sql::Statement query(db->GetCachedStatement(SQL_FROM_HERE, |
| 203 query_str.c_str())); | 167 query_str.c_str())); |
| 204 query.BindString(0, extension_id); | 168 query.BindString(0, extension_id); |
| 205 query.BindInt64(1, early_bound); | 169 query.BindInt64(1, early_bound); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 BrowserThread::PostTaskAndReplyWithResult( | 234 BrowserThread::PostTaskAndReplyWithResult( |
| 271 BrowserThread::DB, | 235 BrowserThread::DB, |
| 272 FROM_HERE, | 236 FROM_HERE, |
| 273 base::Bind(&FullStreamUIPolicy::DoReadData, | 237 base::Bind(&FullStreamUIPolicy::DoReadData, |
| 274 base::Unretained(this), | 238 base::Unretained(this), |
| 275 extension_id, | 239 extension_id, |
| 276 day), | 240 day), |
| 277 callback); | 241 callback); |
| 278 } | 242 } |
| 279 | 243 |
| 280 std::string FullStreamUIPolicy::GetKey(ActivityLogPolicy::KeyType key_ty) const | |
|
felt
2013/08/07 01:09:42
where did this go?
mvrable
2013/08/07 17:01:19
This code isn't being used any longer. The consta
felt
2013/08/08 02:08:50
Ahhh OK, right, I couldn't find them in this CL be
| |
| 281 { | |
| 282 switch (key_ty) { | |
| 283 case PARAM_KEY_REASON: | |
| 284 return std::string(kKeyReason); | |
| 285 case PARAM_KEY_DOM_ACTION: | |
| 286 return std::string(kKeyDomainAction); | |
| 287 case PARAM_KEY_URL_TITLE: | |
| 288 return std::string(kKeyURLTitle); | |
| 289 case PARAM_KEY_DETAILS_STRING: | |
| 290 return std::string(kKeyDetailsString); | |
| 291 default: | |
| 292 return std::string(); | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 scoped_refptr<Action> FullStreamUIPolicy::ProcessArguments( | 244 scoped_refptr<Action> FullStreamUIPolicy::ProcessArguments( |
| 297 scoped_refptr<Action> action) const { | 245 scoped_refptr<Action> action) const { |
| 298 return action; | 246 return action; |
| 299 } | 247 } |
| 300 | 248 |
| 301 void FullStreamUIPolicy::ProcessAction(scoped_refptr<Action> action) { | 249 void FullStreamUIPolicy::ProcessAction(scoped_refptr<Action> action) { |
| 302 // TODO(mvrable): Right now this argument stripping updates the Action object | 250 // TODO(mvrable): Right now this argument stripping updates the Action object |
| 303 // in place, which isn't good if there are other users of the object. When | 251 // in place, which isn't good if there are other users of the object. When |
| 304 // database writing is moved to policy class, the modifications should be | 252 // database writing is moved to policy class, the modifications should be |
| 305 // made locally. | 253 // made locally. |
| 306 action = ProcessArguments(action); | 254 action = ProcessArguments(action); |
| 307 ScheduleAndForget(this, &FullStreamUIPolicy::QueueAction, action); | 255 ScheduleAndForget(this, &FullStreamUIPolicy::QueueAction, action); |
| 308 } | 256 } |
| 309 | 257 |
| 310 void FullStreamUIPolicy::QueueAction(scoped_refptr<Action> action) { | 258 void FullStreamUIPolicy::QueueAction(scoped_refptr<Action> action) { |
| 311 if (activity_database()->is_db_valid()) { | 259 if (activity_database()->is_db_valid()) { |
| 312 queued_actions_.push_back(action); | 260 queued_actions_.push_back(action); |
| 313 activity_database()->NotifyAction(); | 261 activity_database()->AdviseFlush(queued_actions_.size()); |
| 314 } | 262 } |
| 315 } | 263 } |
| 316 | 264 |
| 317 } // namespace extensions | 265 } // namespace extensions |
| OLD | NEW |