| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 <set> | 5 #include <set> |
| 6 #include <vector> | 6 #include <vector> |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/json/json_string_value_serializer.h" | 8 #include "base/json/json_string_value_serializer.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 } | 193 } |
| 194 | 194 |
| 195 // static | 195 // static |
| 196 ActivityLog* ActivityLog::GetInstance(Profile* profile) { | 196 ActivityLog* ActivityLog::GetInstance(Profile* profile) { |
| 197 return ActivityLogFactory::GetForProfile(profile); | 197 return ActivityLogFactory::GetForProfile(profile); |
| 198 } | 198 } |
| 199 | 199 |
| 200 void ActivityLog::AddObserver(const Extension* extension, | 200 void ActivityLog::AddObserver(const Extension* extension, |
| 201 ActivityLog::Observer* observer) { | 201 ActivityLog::Observer* observer) { |
| 202 if (!IsLogEnabled()) return; | 202 if (!IsLogEnabled()) return; |
| 203 if (observers_.count(extension) == 0) | 203 // TODO(felt) Re-implement Observer notification HERE for the API. |
| 204 observers_[extension] = new ObserverListThreadSafe<Observer>; | |
| 205 observers_[extension]->AddObserver(observer); | |
| 206 } | 204 } |
| 207 | 205 |
| 208 void ActivityLog::RemoveObserver(const Extension* extension, | 206 void ActivityLog::RemoveObserver(const Extension* extension, |
| 209 ActivityLog::Observer* observer) { | 207 ActivityLog::Observer* observer) { |
| 210 if (observers_.count(extension) == 1) | 208 // TODO(felt) Re-implement Observer notification HERE for the API. |
| 211 observers_[extension]->RemoveObserver(observer); | |
| 212 } | 209 } |
| 213 | 210 |
| 214 void ActivityLog::LogAPIActionInternal(const Extension* extension, | 211 void ActivityLog::LogAPIActionInternal(const std::string& extension_id, |
| 215 const std::string& api_call, | 212 const std::string& api_call, |
| 216 ListValue* args, | 213 ListValue* args, |
| 217 const std::string& extra, | 214 const std::string& extra, |
| 218 const APIAction::Type type) { | 215 const APIAction::Type type) { |
| 219 std::string verb, manager; | 216 std::string verb, manager; |
| 220 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); | 217 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); |
| 221 if (matches) { | 218 if (matches) { |
| 222 if (!args->empty() && manager == "tabs") { | 219 if (!args->empty() && manager == "tabs") { |
| 223 APIAction::LookupTabId(api_call, args, profile_); | 220 APIAction::LookupTabId(api_call, args, profile_); |
| 224 } | 221 } |
| 225 scoped_refptr<APIAction> action = new APIAction( | 222 scoped_refptr<APIAction> action = new APIAction( |
| 226 extension->id(), | 223 extension_id, |
| 227 base::Time::Now(), | 224 base::Time::Now(), |
| 228 type, | 225 type, |
| 229 api_call, | 226 api_call, |
| 230 MakeArgList(args), | 227 MakeArgList(args), |
| 231 extra); | 228 extra); |
| 232 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 229 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
| 233 | 230 // TODO(felt) Re-implement Observer notification HERE for the API. |
| 234 // Display the action. | |
| 235 ObserverMap::const_iterator iter = observers_.find(extension); | |
| 236 if (iter != observers_.end()) { | |
| 237 if (type == APIAction::CALL) { | |
| 238 iter->second->Notify(&Observer::OnExtensionActivity, | |
| 239 extension, | |
| 240 ActivityLog::ACTIVITY_EXTENSION_API_CALL, | |
| 241 MakeCallSignature(api_call, args)); | |
| 242 } else if (type == APIAction::EVENT_CALLBACK) { | |
| 243 iter->second->Notify(&Observer::OnExtensionActivity, | |
| 244 extension, | |
| 245 ActivityLog::ACTIVITY_EVENT_DISPATCH, | |
| 246 MakeCallSignature(api_call, args)); | |
| 247 } | |
| 248 } | |
| 249 if (log_activity_to_stdout_) | 231 if (log_activity_to_stdout_) |
| 250 LOG(INFO) << action->PrintForDebug(); | 232 LOG(INFO) << action->PrintForDebug(); |
| 251 } else { | 233 } else { |
| 252 LOG(ERROR) << "Unknown API call! " << api_call; | 234 LOG(ERROR) << "Unknown API call! " << api_call; |
| 253 } | 235 } |
| 254 } | 236 } |
| 255 | 237 |
| 256 // A wrapper around LogAPIActionInternal, but we know it's an API call. | 238 // A wrapper around LogAPIActionInternal, but we know it's an API call. |
| 257 void ActivityLog::LogAPIAction(const Extension* extension, | 239 void ActivityLog::LogAPIAction(const std::string& extension_id, |
| 258 const std::string& api_call, | 240 const std::string& api_call, |
| 259 ListValue* args, | 241 ListValue* args, |
| 260 const std::string& extra) { | 242 const std::string& extra) { |
| 261 if (!IsLogEnabled()) return; | 243 if (!IsLogEnabled()) return; |
| 262 if (!testing_mode_ && | 244 if (!testing_mode_ && |
| 263 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) | 245 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) |
| 264 args->Clear(); | 246 args->Clear(); |
| 265 LogAPIActionInternal(extension, | 247 LogAPIActionInternal(extension_id, |
| 266 api_call, | 248 api_call, |
| 267 args, | 249 args, |
| 268 extra, | 250 extra, |
| 269 APIAction::CALL); | 251 APIAction::CALL); |
| 270 } | 252 } |
| 271 | 253 |
| 272 // A wrapper around LogAPIActionInternal, but we know it's actually an event | 254 // A wrapper around LogAPIActionInternal, but we know it's actually an event |
| 273 // being fired and triggering extension code. Having the two separate methods | 255 // being fired and triggering extension code. Having the two separate methods |
| 274 // (LogAPIAction vs LogEventAction) lets us hide how we actually choose to | 256 // (LogAPIAction vs LogEventAction) lets us hide how we actually choose to |
| 275 // handle them. Right now they're being handled almost the same. | 257 // handle them. Right now they're being handled almost the same. |
| 276 void ActivityLog::LogEventAction(const Extension* extension, | 258 void ActivityLog::LogEventAction(const std::string& extension_id, |
| 277 const std::string& api_call, | 259 const std::string& api_call, |
| 278 ListValue* args, | 260 ListValue* args, |
| 279 const std::string& extra) { | 261 const std::string& extra) { |
| 280 if (!IsLogEnabled()) return; | 262 if (!IsLogEnabled()) return; |
| 281 if (!testing_mode_ && | 263 if (!testing_mode_ && |
| 282 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) | 264 arg_whitelist_api_.find(api_call) == arg_whitelist_api_.end()) |
| 283 args->Clear(); | 265 args->Clear(); |
| 284 LogAPIActionInternal(extension, | 266 LogAPIActionInternal(extension_id, |
| 285 api_call, | 267 api_call, |
| 286 args, | 268 args, |
| 287 extra, | 269 extra, |
| 288 APIAction::EVENT_CALLBACK); | 270 APIAction::EVENT_CALLBACK); |
| 289 } | 271 } |
| 290 | 272 |
| 291 void ActivityLog::LogBlockedAction(const Extension* extension, | 273 void ActivityLog::LogBlockedAction(const std::string& extension_id, |
| 292 const std::string& blocked_call, | 274 const std::string& blocked_call, |
| 293 ListValue* args, | 275 ListValue* args, |
| 294 BlockedAction::Reason reason, | 276 BlockedAction::Reason reason, |
| 295 const std::string& extra) { | 277 const std::string& extra) { |
| 296 if (!IsLogEnabled()) return; | 278 if (!IsLogEnabled()) return; |
| 297 if (!testing_mode_ && | 279 if (!testing_mode_ && |
| 298 arg_whitelist_api_.find(blocked_call) == arg_whitelist_api_.end()) | 280 arg_whitelist_api_.find(blocked_call) == arg_whitelist_api_.end()) |
| 299 args->Clear(); | 281 args->Clear(); |
| 300 scoped_refptr<BlockedAction> action = new BlockedAction(extension->id(), | 282 scoped_refptr<BlockedAction> action = new BlockedAction(extension_id, |
| 301 base::Time::Now(), | 283 base::Time::Now(), |
| 302 blocked_call, | 284 blocked_call, |
| 303 MakeArgList(args), | 285 MakeArgList(args), |
| 304 reason, | 286 reason, |
| 305 extra); | 287 extra); |
| 306 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 288 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
| 307 // Display the action. | 289 // TODO(felt) Re-implement Observer notification HERE for the API. |
| 308 ObserverMap::const_iterator iter = observers_.find(extension); | |
| 309 if (iter != observers_.end()) { | |
| 310 std::string blocked_str = MakeCallSignature(blocked_call, args); | |
| 311 iter->second->Notify(&Observer::OnExtensionActivity, | |
| 312 extension, | |
| 313 ActivityLog::ACTIVITY_EXTENSION_API_BLOCK, | |
| 314 blocked_str); | |
| 315 } | |
| 316 if (log_activity_to_stdout_) | 290 if (log_activity_to_stdout_) |
| 317 LOG(INFO) << action->PrintForDebug(); | 291 LOG(INFO) << action->PrintForDebug(); |
| 318 } | 292 } |
| 319 | 293 |
| 320 void ActivityLog::LogDOMActionInternal(const Extension* extension, | 294 void ActivityLog::LogDOMActionInternal(const std::string& extension_id, |
| 321 const GURL& url, | 295 const GURL& url, |
| 322 const string16& url_title, | 296 const string16& url_title, |
| 323 const std::string& api_call, | 297 const std::string& api_call, |
| 324 const ListValue* args, | 298 const ListValue* args, |
| 325 const std::string& extra, | 299 const std::string& extra, |
| 326 DOMAction::DOMActionType verb) { | 300 DOMAction::DOMActionType verb) { |
| 327 scoped_refptr<DOMAction> action = new DOMAction( | 301 scoped_refptr<DOMAction> action = new DOMAction( |
| 328 extension->id(), | 302 extension_id, |
| 329 base::Time::Now(), | 303 base::Time::Now(), |
| 330 verb, | 304 verb, |
| 331 url, | 305 url, |
| 332 url_title, | 306 url_title, |
| 333 api_call, | 307 api_call, |
| 334 MakeArgList(args), | 308 MakeArgList(args), |
| 335 extra); | 309 extra); |
| 336 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 310 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
| 337 | 311 // TODO(felt) Re-implement Observer notification HERE for the API. |
| 338 // Display the action. | |
| 339 ObserverMap::const_iterator iter = observers_.find(extension); | |
| 340 if (iter != observers_.end()) { | |
| 341 // TODO(felt): This is a kludge, planning to update this when new | |
| 342 // UI is in place. | |
| 343 if (verb == DOMAction::INSERTED) { | |
| 344 iter->second->Notify(&Observer::OnExtensionActivity, | |
| 345 extension, | |
| 346 ActivityLog::ACTIVITY_CONTENT_SCRIPT, | |
| 347 action->PrintForDebug()); | |
| 348 } else { | |
| 349 iter->second->Notify(&Observer::OnExtensionActivity, | |
| 350 extension, | |
| 351 ActivityLog::ACTIVITY_CONTENT_SCRIPT, | |
| 352 MakeCallSignature(api_call, args)); | |
| 353 } | |
| 354 } | |
| 355 if (log_activity_to_stdout_) | 312 if (log_activity_to_stdout_) |
| 356 LOG(INFO) << action->PrintForDebug(); | 313 LOG(INFO) << action->PrintForDebug(); |
| 357 } | 314 } |
| 358 | 315 |
| 359 void ActivityLog::LogDOMAction(const Extension* extension, | 316 void ActivityLog::LogDOMAction(const std::string& extension_id, |
| 360 const GURL& url, | 317 const GURL& url, |
| 361 const string16& url_title, | 318 const string16& url_title, |
| 362 const std::string& api_call, | 319 const std::string& api_call, |
| 363 const ListValue* args, | 320 const ListValue* args, |
| 364 const std::string& extra) { | 321 const std::string& extra) { |
| 365 if (!IsLogEnabled()) return; | 322 if (!IsLogEnabled()) return; |
| 366 DOMAction::DOMActionType action = DOMAction::MODIFIED; | 323 DOMAction::DOMActionType action = DOMAction::MODIFIED; |
| 367 if (extra == "Getter") { | 324 if (extra == "Getter") { |
| 368 action = DOMAction::GETTER; | 325 action = DOMAction::GETTER; |
| 369 } else if (extra == "Setter") { | 326 } else if (extra == "Setter") { |
| 370 action = DOMAction::SETTER; | 327 action = DOMAction::SETTER; |
| 371 } else if (api_call == "XMLHttpRequest.open") { | 328 } else if (api_call == "XMLHttpRequest.open") { |
| 372 // Has to come before the Method check because XHR is also a Method. | 329 // Has to come before the Method check because XHR is also a Method. |
| 373 action = DOMAction::XHR; | 330 action = DOMAction::XHR; |
| 374 } else if (extra == "Method") { | 331 } else if (extra == "Method") { |
| 375 action = DOMAction::METHOD; | 332 action = DOMAction::METHOD; |
| 376 } | 333 } |
| 377 LogDOMActionInternal(extension, | 334 LogDOMActionInternal(extension_id, |
| 378 url, | 335 url, |
| 379 url_title, | 336 url_title, |
| 380 api_call, | 337 api_call, |
| 381 args, | 338 args, |
| 382 extra, | 339 extra, |
| 383 action); | 340 action); |
| 384 } | 341 } |
| 385 | 342 |
| 386 void ActivityLog::LogWebRequestAction(const Extension* extension, | 343 void ActivityLog::LogWebRequestAction(const std::string& extension_id, |
| 387 const GURL& url, | 344 const GURL& url, |
| 388 const std::string& api_call, | 345 const std::string& api_call, |
| 389 scoped_ptr<DictionaryValue> details, | 346 scoped_ptr<DictionaryValue> details, |
| 390 const std::string& extra) { | 347 const std::string& extra) { |
| 391 string16 null_title; | 348 string16 null_title; |
| 392 if (!IsLogEnabled()) return; | 349 if (!IsLogEnabled()) return; |
| 393 | 350 |
| 394 // Strip details of the web request modifications (for privacy reasons), | 351 // Strip details of the web request modifications (for privacy reasons), |
| 395 // unless testing is enabled. | 352 // unless testing is enabled. |
| 396 if (!testing_mode_) { | 353 if (!testing_mode_) { |
| 397 DictionaryValue::Iterator details_iterator(*details); | 354 DictionaryValue::Iterator details_iterator(*details); |
| 398 while (!details_iterator.IsAtEnd()) { | 355 while (!details_iterator.IsAtEnd()) { |
| 399 details->SetBoolean(details_iterator.key(), true); | 356 details->SetBoolean(details_iterator.key(), true); |
| 400 details_iterator.Advance(); | 357 details_iterator.Advance(); |
| 401 } | 358 } |
| 402 } | 359 } |
| 403 std::string details_string; | 360 std::string details_string; |
| 404 JSONStringValueSerializer serializer(&details_string); | 361 JSONStringValueSerializer serializer(&details_string); |
| 405 serializer.SerializeAndOmitBinaryValues(*details); | 362 serializer.SerializeAndOmitBinaryValues(*details); |
| 406 | 363 |
| 407 scoped_refptr<DOMAction> action = new DOMAction( | 364 scoped_refptr<DOMAction> action = new DOMAction( |
| 408 extension->id(), | 365 extension_id, |
| 409 base::Time::Now(), | 366 base::Time::Now(), |
| 410 DOMAction::WEBREQUEST, | 367 DOMAction::WEBREQUEST, |
| 411 url, | 368 url, |
| 412 null_title, | 369 null_title, |
| 413 api_call, | 370 api_call, |
| 414 details_string, | 371 details_string, |
| 415 extra); | 372 extra); |
| 416 ScheduleAndForget(&ActivityDatabase::RecordAction, action); | 373 ScheduleAndForget(&ActivityDatabase::RecordAction, action); |
| 417 | 374 // TODO(felt) Re-implement Observer notification HERE for the API. |
| 418 // Display the action. | |
| 419 ObserverMap::const_iterator iter = observers_.find(extension); | |
| 420 if (iter != observers_.end()) { | |
| 421 iter->second->Notify(&Observer::OnExtensionActivity, | |
| 422 extension, | |
| 423 ActivityLog::ACTIVITY_CONTENT_SCRIPT, | |
| 424 action->PrintForDebug()); | |
| 425 } | |
| 426 if (log_activity_to_stdout_) | 375 if (log_activity_to_stdout_) |
| 427 LOG(INFO) << action->PrintForDebug(); | 376 LOG(INFO) << action->PrintForDebug(); |
| 428 } | 377 } |
| 429 | 378 |
| 430 void ActivityLog::GetActions( | 379 void ActivityLog::GetActions( |
| 431 const std::string& extension_id, | 380 const std::string& extension_id, |
| 432 const int day, | 381 const int day, |
| 433 const base::Callback | 382 const base::Callback |
| 434 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { | 383 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { |
| 435 BrowserThread::PostTaskAndReplyWithResult( | 384 BrowserThread::PostTaskAndReplyWithResult( |
| (...skipping 30 matching lines...) Expand all Loading... |
| 466 if (!it->second.empty()) { | 415 if (!it->second.empty()) { |
| 467 std::string ext_scripts_str; | 416 std::string ext_scripts_str; |
| 468 for (std::set<std::string>::const_iterator it2 = it->second.begin(); | 417 for (std::set<std::string>::const_iterator it2 = it->second.begin(); |
| 469 it2 != it->second.end(); | 418 it2 != it->second.end(); |
| 470 ++it2) { | 419 ++it2) { |
| 471 ext_scripts_str += *it2; | 420 ext_scripts_str += *it2; |
| 472 ext_scripts_str += " "; | 421 ext_scripts_str += " "; |
| 473 } | 422 } |
| 474 scoped_ptr<ListValue> script_names(new ListValue()); | 423 scoped_ptr<ListValue> script_names(new ListValue()); |
| 475 script_names->Set(0, new StringValue(ext_scripts_str)); | 424 script_names->Set(0, new StringValue(ext_scripts_str)); |
| 476 LogDOMActionInternal(extension, | 425 LogDOMActionInternal(extension->id(), |
| 477 on_url, | 426 on_url, |
| 478 web_contents->GetTitle(), | 427 web_contents->GetTitle(), |
| 479 std::string(), // no api call here | 428 std::string(), // no api call here |
| 480 script_names.get(), | 429 script_names.get(), |
| 481 std::string(), // no extras either | 430 std::string(), // no extras either |
| 482 DOMAction::INSERTED); | 431 DOMAction::INSERTED); |
| 483 } | 432 } |
| 484 } | 433 } |
| 485 } | 434 } |
| 486 | 435 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 499 return "content_script"; | 448 return "content_script"; |
| 500 case ActivityLog::ACTIVITY_EVENT_DISPATCH: | 449 case ActivityLog::ACTIVITY_EVENT_DISPATCH: |
| 501 return "event_dispatch"; | 450 return "event_dispatch"; |
| 502 default: | 451 default: |
| 503 NOTREACHED(); | 452 NOTREACHED(); |
| 504 return ""; | 453 return ""; |
| 505 } | 454 } |
| 506 } | 455 } |
| 507 | 456 |
| 508 } // namespace extensions | 457 } // namespace extensions |
| OLD | NEW |