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 |