| 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/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| 11 #include "base/strings/utf_string_conversions.h" |
| 11 #include "base/threading/thread_checker.h" | 12 #include "base/threading/thread_checker.h" |
| 12 #include "chrome/browser/extensions/activity_log/activity_log.h" | 13 #include "chrome/browser/extensions/activity_log/activity_log.h" |
| 13 #include "chrome/browser/extensions/activity_log/api_actions.h" | |
| 14 #include "chrome/browser/extensions/activity_log/blocked_actions.h" | |
| 15 #include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h" | 14 #include "chrome/browser/extensions/activity_log/stream_noargs_ui_policy.h" |
| 16 #include "chrome/browser/extensions/api/activity_log_private/activity_log_privat
e_api.h" | 15 #include "chrome/browser/extensions/api/activity_log_private/activity_log_privat
e_api.h" |
| 17 #include "chrome/browser/extensions/extension_service.h" | 16 #include "chrome/browser/extensions/extension_service.h" |
| 18 #include "chrome/browser/extensions/extension_system.h" | 17 #include "chrome/browser/extensions/extension_system.h" |
| 19 #include "chrome/browser/extensions/extension_system_factory.h" | 18 #include "chrome/browser/extensions/extension_system_factory.h" |
| 20 #include "chrome/browser/extensions/install_tracker_factory.h" | 19 #include "chrome/browser/extensions/install_tracker_factory.h" |
| 21 #include "chrome/browser/prerender/prerender_manager.h" | 20 #include "chrome/browser/prerender/prerender_manager.h" |
| 22 #include "chrome/browser/prerender/prerender_manager_factory.h" | 21 #include "chrome/browser/prerender/prerender_manager_factory.h" |
| 23 #include "chrome/browser/profiles/incognito_helpers.h" | 22 #include "chrome/browser/profiles/incognito_helpers.h" |
| 24 #include "chrome/common/chrome_constants.h" | 23 #include "chrome/common/chrome_constants.h" |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 } | 245 } |
| 247 | 246 |
| 248 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { | 247 void ActivityLog::AddObserver(ActivityLog::Observer* observer) { |
| 249 observers_->AddObserver(observer); | 248 observers_->AddObserver(observer); |
| 250 } | 249 } |
| 251 | 250 |
| 252 void ActivityLog::RemoveObserver(ActivityLog::Observer* observer) { | 251 void ActivityLog::RemoveObserver(ActivityLog::Observer* observer) { |
| 253 observers_->RemoveObserver(observer); | 252 observers_->RemoveObserver(observer); |
| 254 } | 253 } |
| 255 | 254 |
| 255 void ActivityLog::LogAction(scoped_refptr<Action> action) { |
| 256 if (IsLogEnabled() && |
| 257 !ActivityLogAPI::IsExtensionWhitelisted(action->extension_id())) { |
| 258 if (policy_) |
| 259 policy_->ProcessAction(action); |
| 260 observers_->Notify(&Observer::OnExtensionActivity, action); |
| 261 if (testing_mode_) |
| 262 LOG(INFO) << action->PrintForDebug(); |
| 263 } |
| 264 } |
| 265 |
| 256 void ActivityLog::LogAPIActionInternal(const std::string& extension_id, | 266 void ActivityLog::LogAPIActionInternal(const std::string& extension_id, |
| 257 const std::string& api_call, | 267 const std::string& api_call, |
| 258 base::ListValue* args, | 268 base::ListValue* args, |
| 259 const std::string& extra, | 269 const std::string& extra, |
| 260 const APIAction::Type type) { | 270 const APIAction::Type type) { |
| 261 std::string verb, manager; | 271 std::string verb, manager; |
| 262 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); | 272 bool matches = RE2::FullMatch(api_call, "(.*?)\\.(.*)", &manager, &verb); |
| 263 if (matches) { | 273 if (matches) { |
| 264 if (!args->empty() && manager == "tabs") { | 274 if (!args->empty() && manager == "tabs") { |
| 265 APIAction::LookupTabId(api_call, args, profile_); | 275 APIAction::LookupTabId(api_call, args, profile_); |
| 266 } | 276 } |
| 267 | 277 |
| 268 if (policy_) { | 278 DCHECK((type == APIAction::CALL || type == APIAction::EVENT_CALLBACK) && |
| 269 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); | 279 "Unexpected APIAction call type."); |
| 270 std::string key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_EXTRA); | |
| 271 details->SetString(key, extra); | |
| 272 DCHECK((type == APIAction::CALL || type == APIAction::EVENT_CALLBACK) && | |
| 273 "Unexpected APIAction call type."); | |
| 274 policy_->ProcessAction( | |
| 275 type == APIAction::CALL ? ActivityLogPolicy::ACTION_API : | |
| 276 ActivityLogPolicy::ACTION_EVENT, | |
| 277 extension_id, | |
| 278 api_call, | |
| 279 GURL(), | |
| 280 args, | |
| 281 details.get()); | |
| 282 } | |
| 283 | 280 |
| 284 // TODO(felt) Logging should be done more efficiently, so that it | 281 scoped_refptr<Action> action; |
| 285 // doesn't require construction of the action object. | 282 action = new Action(extension_id, |
| 286 scoped_refptr<APIAction> action = new APIAction( | 283 base::Time::Now(), |
| 287 extension_id, | 284 type == APIAction::CALL ? Action::ACTION_API_CALL |
| 288 base::Time::Now(), | 285 : Action::ACTION_API_EVENT); |
| 289 type, | 286 action->set_api_name(api_call); |
| 290 api_call, | 287 action->set_args(make_scoped_ptr(args->DeepCopy())); |
| 291 MakeArgList(args), | 288 // TODO(mvrable): Factor common key strings out as constants. |
| 292 *args, | 289 if (!extra.empty()) |
| 293 extra); | 290 action->mutable_other()->SetString("extra", extra); |
| 294 | 291 |
| 295 observers_->Notify(&Observer::OnExtensionActivity, action); | 292 LogAction(action); |
| 296 if (testing_mode_) LOG(INFO) << action->PrintForDebug(); | |
| 297 } else { | 293 } else { |
| 298 LOG(ERROR) << "Unknown API call! " << api_call; | 294 LOG(ERROR) << "Unknown API call! " << api_call; |
| 299 } | 295 } |
| 300 } | 296 } |
| 301 | 297 |
| 302 // A wrapper around LogAPIActionInternal, but we know it's an API call. | 298 // A wrapper around LogAPIActionInternal, but we know it's an API call. |
| 303 void ActivityLog::LogAPIAction(const std::string& extension_id, | 299 void ActivityLog::LogAPIAction(const std::string& extension_id, |
| 304 const std::string& api_call, | 300 const std::string& api_call, |
| 305 base::ListValue* args, | 301 base::ListValue* args, |
| 306 const std::string& extra) { | 302 const std::string& extra) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 331 } | 327 } |
| 332 | 328 |
| 333 void ActivityLog::LogBlockedAction(const std::string& extension_id, | 329 void ActivityLog::LogBlockedAction(const std::string& extension_id, |
| 334 const std::string& blocked_call, | 330 const std::string& blocked_call, |
| 335 base::ListValue* args, | 331 base::ListValue* args, |
| 336 BlockedAction::Reason reason, | 332 BlockedAction::Reason reason, |
| 337 const std::string& extra) { | 333 const std::string& extra) { |
| 338 if (!IsLogEnabled() || | 334 if (!IsLogEnabled() || |
| 339 ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return; | 335 ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return; |
| 340 | 336 |
| 341 if (policy_) { | 337 scoped_refptr<Action> action; |
| 342 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); | 338 action = |
| 343 std::string key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_REASON); | 339 new Action(extension_id, base::Time::Now(), Action::ACTION_API_BLOCKED); |
| 344 details->SetInteger(key, static_cast<int>(reason)); | 340 action->set_api_name(blocked_call); |
| 345 key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_EXTRA); | 341 action->set_args(make_scoped_ptr(args->DeepCopy())); |
| 346 details->SetString(key, extra); | 342 // TODO(mvrable): Factor common key strings out as constants. |
| 347 policy_->ProcessAction( | 343 action->mutable_other()->SetInteger("reason", static_cast<int>(reason)); |
| 348 ActivityLogPolicy::ACTION_BLOCKED, | 344 if (!extra.empty()) |
| 349 extension_id, | 345 action->mutable_other()->SetString("extra", extra); |
| 350 blocked_call, | |
| 351 GURL(), | |
| 352 args, | |
| 353 details.get()); | |
| 354 } | |
| 355 | 346 |
| 356 scoped_refptr<BlockedAction> action = new BlockedAction(extension_id, | 347 LogAction(action); |
| 357 base::Time::Now(), | |
| 358 blocked_call, | |
| 359 MakeArgList(args), | |
| 360 reason, | |
| 361 extra); | |
| 362 observers_->Notify(&Observer::OnExtensionActivity, action); | |
| 363 if (testing_mode_) LOG(INFO) << action->PrintForDebug(); | |
| 364 } | 348 } |
| 365 | 349 |
| 366 void ActivityLog::LogDOMAction(const std::string& extension_id, | 350 void ActivityLog::LogDOMAction(const std::string& extension_id, |
| 367 const GURL& url, | 351 const GURL& url, |
| 368 const string16& url_title, | 352 const string16& url_title, |
| 369 const std::string& api_call, | 353 const std::string& api_call, |
| 370 const base::ListValue* args, | 354 const base::ListValue* args, |
| 371 DomActionType::Type call_type, | 355 DomActionType::Type call_type, |
| 372 const std::string& extra) { | 356 const std::string& extra) { |
| 373 if (!IsLogEnabled() || | 357 if (!IsLogEnabled() || |
| 374 ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return; | 358 ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return; |
| 375 if (call_type == DomActionType::METHOD && api_call == "XMLHttpRequest.open") | 359 |
| 360 Action::ActionType action_type = Action::ACTION_DOM_ACCESS; |
| 361 if (call_type == DomActionType::INSERTED) { |
| 362 action_type = Action::ACTION_CONTENT_SCRIPT; |
| 363 } else if (call_type == DomActionType::METHOD && |
| 364 api_call == "XMLHttpRequest.open") { |
| 376 call_type = DomActionType::XHR; | 365 call_type = DomActionType::XHR; |
| 377 | 366 action_type = Action::ACTION_DOM_XHR; |
| 378 if (policy_) { | |
| 379 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); | |
| 380 std::string key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_DOM_ACTION); | |
| 381 details->SetInteger(key, static_cast<int>(call_type)); | |
| 382 key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_URL_TITLE); | |
| 383 details->SetString(key, url_title); | |
| 384 key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_EXTRA); | |
| 385 details->SetString(key, extra); | |
| 386 policy_->ProcessAction( | |
| 387 ActivityLogPolicy::ACTION_DOM, | |
| 388 extension_id, | |
| 389 api_call, | |
| 390 url, | |
| 391 args, | |
| 392 details.get()); | |
| 393 } | 367 } |
| 394 | 368 |
| 369 scoped_refptr<Action> action; |
| 370 action = new Action(extension_id, base::Time::Now(), action_type); |
| 371 action->set_api_name(api_call); |
| 372 if (args) |
| 373 action->set_args(make_scoped_ptr(args->DeepCopy())); |
| 374 action->set_page_url(url); |
| 375 // TODO(mvrable): Factor common key strings out as constants. |
| 376 action->set_page_title(base::UTF16ToUTF8(url_title)); |
| 377 action->mutable_other()->SetInteger("dom_verb", static_cast<int>(call_type)); |
| 378 if (!extra.empty()) |
| 379 action->mutable_other()->SetString("extra", extra); |
| 395 | 380 |
| 396 // TODO(felt) Logging should be done more efficiently, so that it | 381 LogAction(action); |
| 397 // doesn't require construction of the action object. | |
| 398 scoped_refptr<DOMAction> action = new DOMAction( | |
| 399 extension_id, | |
| 400 base::Time::Now(), | |
| 401 call_type, | |
| 402 url, | |
| 403 url_title, | |
| 404 api_call, | |
| 405 MakeArgList(args), | |
| 406 extra); | |
| 407 observers_->Notify(&Observer::OnExtensionActivity, action); | |
| 408 if (testing_mode_) LOG(INFO) << action->PrintForDebug(); | |
| 409 } | 382 } |
| 410 | 383 |
| 411 void ActivityLog::LogWebRequestAction(const std::string& extension_id, | 384 void ActivityLog::LogWebRequestAction(const std::string& extension_id, |
| 412 const GURL& url, | 385 const GURL& url, |
| 413 const std::string& api_call, | 386 const std::string& api_call, |
| 414 scoped_ptr<DictionaryValue> details, | 387 scoped_ptr<DictionaryValue> details, |
| 415 const std::string& extra) { | 388 const std::string& extra) { |
| 416 string16 null_title; | |
| 417 if (!IsLogEnabled() || | 389 if (!IsLogEnabled() || |
| 418 ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return; | 390 ActivityLogAPI::IsExtensionWhitelisted(extension_id)) return; |
| 419 | 391 |
| 420 std::string details_string; | 392 scoped_refptr<Action> action; |
| 421 if (policy_) { | 393 action = |
| 422 scoped_ptr<base::DictionaryValue> details(new DictionaryValue()); | 394 new Action(extension_id, base::Time::Now(), Action::ACTION_WEB_REQUEST); |
| 423 std::string key = policy_->GetKey( | 395 action->set_api_name(api_call); |
| 424 ActivityLogPolicy::PARAM_KEY_DETAILS_STRING); | 396 action->set_page_url(url); |
| 425 details->SetString(key, details_string); | 397 // TODO(mvrable): Factor common key strings out as constants. |
| 426 key = policy_->GetKey(ActivityLogPolicy::PARAM_KEY_EXTRA); | 398 action->mutable_other()->Set("web_request", details.release()); |
| 427 details->SetString(key, extra); | 399 if (!extra.empty()) |
| 428 policy_->ProcessAction( | 400 action->mutable_other()->SetString("extra", extra); |
| 429 ActivityLogPolicy::ACTION_WEB_REQUEST, | |
| 430 extension_id, | |
| 431 api_call, | |
| 432 url, | |
| 433 NULL, | |
| 434 details.get()); | |
| 435 } | |
| 436 | 401 |
| 437 JSONStringValueSerializer serializer(&details_string); | 402 LogAction(action); |
| 438 serializer.SerializeAndOmitBinaryValues(*details); | |
| 439 | |
| 440 // TODO(felt) Logging should be done more efficiently, so that it | |
| 441 // doesn't require construction of the action object. | |
| 442 scoped_refptr<DOMAction> action = new DOMAction( | |
| 443 extension_id, | |
| 444 base::Time::Now(), | |
| 445 DomActionType::WEBREQUEST, | |
| 446 url, | |
| 447 null_title, | |
| 448 api_call, | |
| 449 details_string, | |
| 450 extra); | |
| 451 observers_->Notify(&Observer::OnExtensionActivity, action); | |
| 452 if (testing_mode_) LOG(INFO) << action->PrintForDebug(); | |
| 453 } | 403 } |
| 454 | 404 |
| 455 void ActivityLog::GetActions( | 405 void ActivityLog::GetActions( |
| 456 const std::string& extension_id, | 406 const std::string& extension_id, |
| 457 const int day, | 407 const int day, |
| 458 const base::Callback | 408 const base::Callback |
| 459 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { | 409 <void(scoped_ptr<std::vector<scoped_refptr<Action> > >)>& callback) { |
| 460 if (policy_) { | 410 if (policy_) { |
| 461 policy_->ReadData(extension_id, day, callback); | 411 policy_->ReadData(extension_id, day, callback); |
| 462 } | 412 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 506 web_contents->GetTitle(), | 456 web_contents->GetTitle(), |
| 507 std::string(), // no api call here | 457 std::string(), // no api call here |
| 508 script_names.get(), | 458 script_names.get(), |
| 509 DomActionType::INSERTED, | 459 DomActionType::INSERTED, |
| 510 extra); | 460 extra); |
| 511 } | 461 } |
| 512 } | 462 } |
| 513 } | 463 } |
| 514 | 464 |
| 515 } // namespace extensions | 465 } // namespace extensions |
| OLD | NEW |