 Chromium Code Reviews
 Chromium Code Reviews Issue 21646004:
  Compressed activity log database storage  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@refactor-cleanups
    
  
    Issue 21646004:
  Compressed activity log database storage  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@refactor-cleanups| 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 |