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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 | 116 |
117 queued_actions_.clear(); | 117 queued_actions_.clear(); |
118 return true; | 118 return true; |
119 } | 119 } |
120 | 120 |
121 scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadFilteredData( | 121 scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadFilteredData( |
122 const std::string& extension_id, | 122 const std::string& extension_id, |
123 const Action::ActionType type, | 123 const Action::ActionType type, |
124 const std::string& api_name, | 124 const std::string& api_name, |
125 const std::string& page_url, | 125 const std::string& page_url, |
126 const std::string& arg_url) { | 126 const std::string& arg_url, |
| 127 const int days_ago) { |
127 // Ensure data is flushed to the database first so that we query over all | 128 // Ensure data is flushed to the database first so that we query over all |
128 // data. | 129 // data. |
129 activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately); | 130 activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately); |
130 scoped_ptr<Action::ActionVector> actions(new Action::ActionVector()); | 131 scoped_ptr<Action::ActionVector> actions(new Action::ActionVector()); |
131 | 132 |
132 sql::Connection* db = GetDatabaseConnection(); | 133 sql::Connection* db = GetDatabaseConnection(); |
133 if (!db) { | 134 if (!db) { |
134 return actions.Pass(); | 135 return actions.Pass(); |
135 } | 136 } |
136 | 137 |
(...skipping 12 matching lines...) Expand all Loading... |
149 where_str += where_next + "action_type=?"; | 150 where_str += where_next + "action_type=?"; |
150 where_next = " AND "; | 151 where_next = " AND "; |
151 } | 152 } |
152 if (!page_url.empty()) { | 153 if (!page_url.empty()) { |
153 where_str += where_next + "page_url LIKE ?"; | 154 where_str += where_next + "page_url LIKE ?"; |
154 where_next = " AND "; | 155 where_next = " AND "; |
155 } | 156 } |
156 if (!arg_url.empty()) { | 157 if (!arg_url.empty()) { |
157 where_str += where_next + "arg_url LIKE ?"; | 158 where_str += where_next + "arg_url LIKE ?"; |
158 } | 159 } |
| 160 if (days_ago >= 0) |
| 161 where_str += where_next + "time BETWEEN ? AND ?"; |
159 std::string query_str = base::StringPrintf( | 162 std::string query_str = base::StringPrintf( |
160 "SELECT extension_id,time,action_type,api_name,args,page_url,page_title," | 163 "SELECT extension_id,time,action_type,api_name,args,page_url,page_title," |
161 "arg_url,other FROM %s WHERE %s ORDER BY time DESC", | 164 "arg_url,other FROM %s WHERE %s ORDER BY time DESC", |
162 kTableName, | 165 kTableName, |
163 where_str.c_str()); | 166 where_str.c_str()); |
164 sql::Statement query(db->GetUniqueStatement(query_str.c_str())); | 167 sql::Statement query(db->GetUniqueStatement(query_str.c_str())); |
165 int i = -1; | 168 int i = -1; |
166 if (!extension_id.empty()) | 169 if (!extension_id.empty()) |
167 query.BindString(++i, extension_id); | 170 query.BindString(++i, extension_id); |
168 if (!api_name.empty()) | 171 if (!api_name.empty()) |
169 query.BindString(++i, api_name); | 172 query.BindString(++i, api_name); |
170 if (type != Action::ACTION_ANY) | 173 if (type != Action::ACTION_ANY) |
171 query.BindInt(++i, static_cast<int>(type)); | 174 query.BindInt(++i, static_cast<int>(type)); |
172 if (!page_url.empty()) | 175 if (!page_url.empty()) |
173 query.BindString(++i, page_url + "%"); | 176 query.BindString(++i, page_url + "%"); |
174 if (!arg_url.empty()) | 177 if (!arg_url.empty()) |
175 query.BindString(++i, arg_url + "%"); | 178 query.BindString(++i, arg_url + "%"); |
| 179 if (days_ago >= 0) { |
| 180 int64 early_bound; |
| 181 int64 late_bound; |
| 182 Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound); |
| 183 query.BindInt64(++i, early_bound); |
| 184 query.BindInt64(++i, late_bound); |
| 185 } |
176 | 186 |
177 // Execute the query and get results. | 187 // Execute the query and get results. |
178 while (query.is_valid() && query.Step()) { | 188 while (query.is_valid() && query.Step()) { |
179 scoped_refptr<Action> action = | 189 scoped_refptr<Action> action = |
180 new Action(query.ColumnString(0), | 190 new Action(query.ColumnString(0), |
181 base::Time::FromInternalValue(query.ColumnInt64(1)), | 191 base::Time::FromInternalValue(query.ColumnInt64(1)), |
182 static_cast<Action::ActionType>(query.ColumnInt(2)), | 192 static_cast<Action::ActionType>(query.ColumnInt(2)), |
183 query.ColumnString(3)); | 193 query.ColumnString(3)); |
184 | 194 |
185 if (query.ColumnType(4) != sql::COLUMN_TYPE_NULL) { | 195 if (query.ColumnType(4) != sql::COLUMN_TYPE_NULL) { |
(...skipping 16 matching lines...) Expand all Loading... |
202 action->set_other(make_scoped_ptr( | 212 action->set_other(make_scoped_ptr( |
203 static_cast<DictionaryValue*>(parsed_value.release()))); | 213 static_cast<DictionaryValue*>(parsed_value.release()))); |
204 } | 214 } |
205 } | 215 } |
206 actions->push_back(action); | 216 actions->push_back(action); |
207 } | 217 } |
208 | 218 |
209 return actions.Pass(); | 219 return actions.Pass(); |
210 } | 220 } |
211 | 221 |
212 scoped_ptr<Action::ActionVector> FullStreamUIPolicy::DoReadData( | |
213 const std::string& extension_id, | |
214 const int days_ago) { | |
215 // Ensure data is flushed to the database first so that we query over all | |
216 // data. | |
217 activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately); | |
218 | |
219 DCHECK_GE(days_ago, 0); | |
220 scoped_ptr<Action::ActionVector> actions(new Action::ActionVector()); | |
221 | |
222 sql::Connection* db = GetDatabaseConnection(); | |
223 if (!db) { | |
224 return actions.Pass(); | |
225 } | |
226 | |
227 int64 early_bound; | |
228 int64 late_bound; | |
229 Util::ComputeDatabaseTimeBounds(Now(), days_ago, &early_bound, &late_bound); | |
230 std::string query_str = base::StringPrintf( | |
231 "SELECT time, action_type, api_name, args, page_url, page_title, " | |
232 "arg_url, other " | |
233 "FROM %s WHERE extension_id=? AND time>? AND time<=? " | |
234 "ORDER BY time DESC", | |
235 kTableName); | |
236 sql::Statement query(db->GetCachedStatement(SQL_FROM_HERE, | |
237 query_str.c_str())); | |
238 query.BindString(0, extension_id); | |
239 query.BindInt64(1, early_bound); | |
240 query.BindInt64(2, late_bound); | |
241 while (query.is_valid() && query.Step()) { | |
242 scoped_refptr<Action> action = | |
243 new Action(extension_id, | |
244 base::Time::FromInternalValue(query.ColumnInt64(0)), | |
245 static_cast<Action::ActionType>(query.ColumnInt(1)), | |
246 query.ColumnString(2)); | |
247 | |
248 if (query.ColumnType(3) != sql::COLUMN_TYPE_NULL) { | |
249 scoped_ptr<Value> parsed_value( | |
250 base::JSONReader::Read(query.ColumnString(3))); | |
251 if (parsed_value && parsed_value->IsType(Value::TYPE_LIST)) { | |
252 action->set_args( | |
253 make_scoped_ptr(static_cast<ListValue*>(parsed_value.release()))); | |
254 } else { | |
255 LOG(WARNING) << "Unable to parse args: '" << query.ColumnString(3) | |
256 << "'"; | |
257 } | |
258 } | |
259 | |
260 action->ParsePageUrl(query.ColumnString(4)); | |
261 action->set_page_title(query.ColumnString(5)); | |
262 action->ParseArgUrl(query.ColumnString(6)); | |
263 | |
264 if (query.ColumnType(7) != sql::COLUMN_TYPE_NULL) { | |
265 scoped_ptr<Value> parsed_value( | |
266 base::JSONReader::Read(query.ColumnString(7))); | |
267 if (parsed_value && parsed_value->IsType(Value::TYPE_DICTIONARY)) { | |
268 action->set_other(make_scoped_ptr( | |
269 static_cast<DictionaryValue*>(parsed_value.release()))); | |
270 } else { | |
271 LOG(WARNING) << "Unable to parse other: '" << query.ColumnString(7) | |
272 << "'"; | |
273 } | |
274 } | |
275 | |
276 actions->push_back(action); | |
277 } | |
278 return actions.Pass(); | |
279 } | |
280 | |
281 void FullStreamUIPolicy::DoRemoveURLs(const std::vector<GURL>& restrict_urls) { | 222 void FullStreamUIPolicy::DoRemoveURLs(const std::vector<GURL>& restrict_urls) { |
282 sql::Connection* db = GetDatabaseConnection(); | 223 sql::Connection* db = GetDatabaseConnection(); |
283 if (!db) { | 224 if (!db) { |
284 LOG(ERROR) << "Unable to connect to database"; | 225 LOG(ERROR) << "Unable to connect to database"; |
285 return; | 226 return; |
286 } | 227 } |
287 | 228 |
288 // Make sure any queued in memory are sent to the database before cleaning. | 229 // Make sure any queued in memory are sent to the database before cleaning. |
289 activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately); | 230 activity_database()->AdviseFlush(ActivityDatabase::kFlushImmediately); |
290 | 231 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 void FullStreamUIPolicy::OnDatabaseClose() { | 288 void FullStreamUIPolicy::OnDatabaseClose() { |
348 delete this; | 289 delete this; |
349 } | 290 } |
350 | 291 |
351 void FullStreamUIPolicy::Close() { | 292 void FullStreamUIPolicy::Close() { |
352 // The policy object should have never been created if there's no DB thread. | 293 // The policy object should have never been created if there's no DB thread. |
353 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::DB)); | 294 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::DB)); |
354 ScheduleAndForget(activity_database(), &ActivityDatabase::Close); | 295 ScheduleAndForget(activity_database(), &ActivityDatabase::Close); |
355 } | 296 } |
356 | 297 |
357 // Get data as a set of key-value pairs. The keys are policy-specific. | |
358 void FullStreamUIPolicy::ReadData( | |
359 const std::string& extension_id, | |
360 const int day, | |
361 const Callback<void(scoped_ptr<Action::ActionVector>)>& callback) { | |
362 BrowserThread::PostTaskAndReplyWithResult( | |
363 BrowserThread::DB, | |
364 FROM_HERE, | |
365 base::Bind(&FullStreamUIPolicy::DoReadData, | |
366 base::Unretained(this), | |
367 extension_id, | |
368 day), | |
369 callback); | |
370 } | |
371 | |
372 void FullStreamUIPolicy::ReadFilteredData( | 298 void FullStreamUIPolicy::ReadFilteredData( |
373 const std::string& extension_id, | 299 const std::string& extension_id, |
374 const Action::ActionType type, | 300 const Action::ActionType type, |
375 const std::string& api_name, | 301 const std::string& api_name, |
376 const std::string& page_url, | 302 const std::string& page_url, |
377 const std::string& arg_url, | 303 const std::string& arg_url, |
| 304 const int days_ago, |
378 const base::Callback | 305 const base::Callback |
379 <void(scoped_ptr<Action::ActionVector>)>& callback) { | 306 <void(scoped_ptr<Action::ActionVector>)>& callback) { |
380 BrowserThread::PostTaskAndReplyWithResult( | 307 BrowserThread::PostTaskAndReplyWithResult( |
381 BrowserThread::DB, | 308 BrowserThread::DB, |
382 FROM_HERE, | 309 FROM_HERE, |
383 base::Bind(&FullStreamUIPolicy::DoReadFilteredData, | 310 base::Bind(&FullStreamUIPolicy::DoReadFilteredData, |
384 base::Unretained(this), | 311 base::Unretained(this), |
385 extension_id, | 312 extension_id, |
386 type, | 313 type, |
387 api_name, | 314 api_name, |
388 page_url, | 315 page_url, |
389 arg_url), | 316 arg_url, |
| 317 days_ago), |
390 callback); | 318 callback); |
391 } | 319 } |
392 | 320 |
393 void FullStreamUIPolicy::RemoveURLs(const std::vector<GURL>& restrict_urls) { | 321 void FullStreamUIPolicy::RemoveURLs(const std::vector<GURL>& restrict_urls) { |
394 ScheduleAndForget(this, &FullStreamUIPolicy::DoRemoveURLs, restrict_urls); | 322 ScheduleAndForget(this, &FullStreamUIPolicy::DoRemoveURLs, restrict_urls); |
395 } | 323 } |
396 | 324 |
397 scoped_refptr<Action> FullStreamUIPolicy::ProcessArguments( | 325 scoped_refptr<Action> FullStreamUIPolicy::ProcessArguments( |
398 scoped_refptr<Action> action) const { | 326 scoped_refptr<Action> action) const { |
399 return action; | 327 return action; |
400 } | 328 } |
401 | 329 |
402 void FullStreamUIPolicy::ProcessAction(scoped_refptr<Action> action) { | 330 void FullStreamUIPolicy::ProcessAction(scoped_refptr<Action> action) { |
403 // TODO(mvrable): Right now this argument stripping updates the Action object | 331 // TODO(mvrable): Right now this argument stripping updates the Action object |
404 // in place, which isn't good if there are other users of the object. When | 332 // in place, which isn't good if there are other users of the object. When |
405 // database writing is moved to policy class, the modifications should be | 333 // database writing is moved to policy class, the modifications should be |
406 // made locally. | 334 // made locally. |
407 action = ProcessArguments(action); | 335 action = ProcessArguments(action); |
408 ScheduleAndForget(this, &FullStreamUIPolicy::QueueAction, action); | 336 ScheduleAndForget(this, &FullStreamUIPolicy::QueueAction, action); |
409 } | 337 } |
410 | 338 |
411 void FullStreamUIPolicy::QueueAction(scoped_refptr<Action> action) { | 339 void FullStreamUIPolicy::QueueAction(scoped_refptr<Action> action) { |
412 if (activity_database()->is_db_valid()) { | 340 if (activity_database()->is_db_valid()) { |
413 queued_actions_.push_back(action); | 341 queued_actions_.push_back(action); |
414 activity_database()->AdviseFlush(queued_actions_.size()); | 342 activity_database()->AdviseFlush(queued_actions_.size()); |
415 } | 343 } |
416 } | 344 } |
417 | 345 |
418 } // namespace extensions | 346 } // namespace extensions |
OLD | NEW |