| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/extension_function_dispatcher.h" | 5 #include "extensions/browser/extension_function_dispatcher.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/json/json_string_value_serializer.h" | 10 #include "base/json/json_string_value_serializer.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 using content::BrowserThread; | 47 using content::BrowserThread; |
| 48 using content::RenderViewHost; | 48 using content::RenderViewHost; |
| 49 | 49 |
| 50 namespace extensions { | 50 namespace extensions { |
| 51 namespace { | 51 namespace { |
| 52 | 52 |
| 53 // Notifies the ApiActivityMonitor that an extension API function has been | 53 // Notifies the ApiActivityMonitor that an extension API function has been |
| 54 // called. May be called from any thread. | 54 // called. May be called from any thread. |
| 55 void NotifyApiFunctionCalled(const std::string& extension_id, | 55 void NotifyApiFunctionCalled(const std::string& extension_id, |
| 56 const std::string& api_name, | 56 const std::string& api_name, |
| 57 std::unique_ptr<base::ListValue> args, | 57 const base::ListValue& args, |
| 58 content::BrowserContext* browser_context) { | 58 content::BrowserContext* browser_context) { |
| 59 // The ApiActivityMonitor can only be accessed from the main (UI) thread. If | 59 activity_monitor::OnApiFunctionCalled(browser_context, extension_id, api_name, |
| 60 // we're running on the wrong thread, re-dispatch from the main thread. | 60 args); |
| 61 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 62 BrowserThread::PostTask(BrowserThread::UI, | |
| 63 FROM_HERE, | |
| 64 base::Bind(&NotifyApiFunctionCalled, | |
| 65 extension_id, | |
| 66 api_name, | |
| 67 base::Passed(&args), | |
| 68 browser_context)); | |
| 69 return; | |
| 70 } | |
| 71 // The BrowserContext may become invalid after the task above is posted. | |
| 72 if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context)) | |
| 73 return; | |
| 74 | |
| 75 ApiActivityMonitor* monitor = | |
| 76 ExtensionsBrowserClient::Get()->GetApiActivityMonitor(browser_context); | |
| 77 if (monitor) | |
| 78 monitor->OnApiFunctionCalled(extension_id, api_name, std::move(args)); | |
| 79 } | 61 } |
| 80 | 62 |
| 81 // Separate copy of ExtensionAPI used for IO thread extension functions. We need | 63 // Separate copy of ExtensionAPI used for IO thread extension functions. We need |
| 82 // this because ExtensionAPI has mutable data. It should be possible to remove | 64 // this because ExtensionAPI has mutable data. It should be possible to remove |
| 83 // this once all the extension APIs are updated to the feature system. | 65 // this once all the extension APIs are updated to the feature system. |
| 84 struct Static { | 66 struct Static { |
| 85 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} | 67 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} |
| 86 std::unique_ptr<ExtensionAPI> api; | 68 std::unique_ptr<ExtensionAPI> api; |
| 87 }; | 69 }; |
| 88 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; | 70 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 function->RunWithValidation()->Execute(); | 359 function->RunWithValidation()->Execute(); |
| 378 return; | 360 return; |
| 379 } | 361 } |
| 380 | 362 |
| 381 QuotaService* quota = extension_info_map->GetQuotaService(); | 363 QuotaService* quota = extension_info_map->GetQuotaService(); |
| 382 std::string violation_error = quota->Assess(extension->id(), | 364 std::string violation_error = quota->Assess(extension->id(), |
| 383 function.get(), | 365 function.get(), |
| 384 ¶ms.arguments, | 366 ¶ms.arguments, |
| 385 base::TimeTicks::Now()); | 367 base::TimeTicks::Now()); |
| 386 if (violation_error.empty()) { | 368 if (violation_error.empty()) { |
| 387 std::unique_ptr<base::ListValue> args(params.arguments.DeepCopy()); | 369 NotifyApiFunctionCalled(extension->id(), params.name, params.arguments, |
| 388 NotifyApiFunctionCalled(extension->id(), params.name, std::move(args), | |
| 389 static_cast<content::BrowserContext*>(profile_id)); | 370 static_cast<content::BrowserContext*>(profile_id)); |
| 390 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", | 371 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", |
| 391 function->histogram_value()); | 372 function->histogram_value()); |
| 392 tracked_objects::ScopedProfile scoped_profile( | 373 tracked_objects::ScopedProfile scoped_profile( |
| 393 FROM_HERE_WITH_EXPLICIT_FUNCTION(function->name()), | 374 FROM_HERE_WITH_EXPLICIT_FUNCTION(function->name()), |
| 394 tracked_objects::ScopedProfile::ENABLED); | 375 tracked_objects::ScopedProfile::ENABLED); |
| 395 base::ElapsedTimer timer; | 376 base::ElapsedTimer timer; |
| 396 function->RunWithValidation()->Execute(); | 377 function->RunWithValidation()->Execute(); |
| 397 // TODO(devlin): Once we have a baseline metric for how long functions take, | 378 // TODO(devlin): Once we have a baseline metric for how long functions take, |
| 398 // we can create a handful of buckets and record the function name so that | 379 // we can create a handful of buckets and record the function name so that |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 ProcessManager* process_manager = ProcessManager::Get(browser_context_); | 499 ProcessManager* process_manager = ProcessManager::Get(browser_context_); |
| 519 | 500 |
| 520 ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_); | 501 ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_); |
| 521 QuotaService* quota = extension_system->quota_service(); | 502 QuotaService* quota = extension_system->quota_service(); |
| 522 std::string violation_error = quota->Assess(extension->id(), | 503 std::string violation_error = quota->Assess(extension->id(), |
| 523 function.get(), | 504 function.get(), |
| 524 ¶ms.arguments, | 505 ¶ms.arguments, |
| 525 base::TimeTicks::Now()); | 506 base::TimeTicks::Now()); |
| 526 | 507 |
| 527 if (violation_error.empty()) { | 508 if (violation_error.empty()) { |
| 528 std::unique_ptr<base::ListValue> args(params.arguments.DeepCopy()); | |
| 529 | |
| 530 // See crbug.com/39178. | 509 // See crbug.com/39178. |
| 531 ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler(); | 510 ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler(); |
| 532 NotifyApiFunctionCalled(extension->id(), params.name, std::move(args), | 511 NotifyApiFunctionCalled(extension->id(), params.name, params.arguments, |
| 533 browser_context_); | 512 browser_context_); |
| 534 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", | 513 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", |
| 535 function->histogram_value()); | 514 function->histogram_value()); |
| 536 tracked_objects::ScopedProfile scoped_profile( | 515 tracked_objects::ScopedProfile scoped_profile( |
| 537 FROM_HERE_WITH_EXPLICIT_FUNCTION(function->name()), | 516 FROM_HERE_WITH_EXPLICIT_FUNCTION(function->name()), |
| 538 tracked_objects::ScopedProfile::ENABLED); | 517 tracked_objects::ScopedProfile::ENABLED); |
| 539 base::ElapsedTimer timer; | 518 base::ElapsedTimer timer; |
| 540 function->RunWithValidation()->Execute(); | 519 function->RunWithValidation()->Execute(); |
| 541 // TODO(devlin): Once we have a baseline metric for how long functions take, | 520 // TODO(devlin): Once we have a baseline metric for how long functions take, |
| 542 // we can create a handful of buckets and record the function name so that | 521 // we can create a handful of buckets and record the function name so that |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 // static | 634 // static |
| 656 void ExtensionFunctionDispatcher::SendAccessDenied( | 635 void ExtensionFunctionDispatcher::SendAccessDenied( |
| 657 const ExtensionFunction::ResponseCallback& callback, | 636 const ExtensionFunction::ResponseCallback& callback, |
| 658 functions::HistogramValue histogram_value) { | 637 functions::HistogramValue histogram_value) { |
| 659 base::ListValue empty_list; | 638 base::ListValue empty_list; |
| 660 callback.Run(ExtensionFunction::FAILED, empty_list, | 639 callback.Run(ExtensionFunction::FAILED, empty_list, |
| 661 "Access to extension API denied.", histogram_value); | 640 "Access to extension API denied.", histogram_value); |
| 662 } | 641 } |
| 663 | 642 |
| 664 } // namespace extensions | 643 } // namespace extensions |
| OLD | NEW |