Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(287)

Side by Side Diff: extensions/browser/extension_function_dispatcher.cc

Issue 2166523003: Add ref count to service workers for extension API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address comments from falken@ Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/macros.h" 13 #include "base/macros.h"
14 #include "base/memory/ref_counted.h" 14 #include "base/memory/ref_counted.h"
15 #include "base/metrics/histogram_macros.h" 15 #include "base/metrics/histogram_macros.h"
16 #include "base/metrics/sparse_histogram.h" 16 #include "base/metrics/sparse_histogram.h"
17 #include "base/process/process.h" 17 #include "base/process/process.h"
18 #include "base/profiler/scoped_profile.h" 18 #include "base/profiler/scoped_profile.h"
19 #include "base/scoped_observer.h" 19 #include "base/scoped_observer.h"
20 #include "base/values.h" 20 #include "base/values.h"
21 #include "build/build_config.h" 21 #include "build/build_config.h"
22 #include "content/common/service_worker/service_worker_types.h"
22 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/render_frame_host.h" 24 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/render_process_host.h" 25 #include "content/public/browser/render_process_host.h"
25 #include "content/public/browser/render_process_host_observer.h" 26 #include "content/public/browser/render_process_host_observer.h"
26 #include "content/public/browser/render_view_host.h" 27 #include "content/public/browser/render_view_host.h"
28 #include "content/public/browser/service_worker_context.h"
27 #include "content/public/browser/user_metrics.h" 29 #include "content/public/browser/user_metrics.h"
28 #include "content/public/browser/web_contents.h" 30 #include "content/public/browser/web_contents.h"
29 #include "content/public/browser/web_contents_observer.h" 31 #include "content/public/browser/web_contents_observer.h"
30 #include "content/public/common/result_codes.h" 32 #include "content/public/common/result_codes.h"
31 #include "extensions/browser/api_activity_monitor.h" 33 #include "extensions/browser/api_activity_monitor.h"
32 #include "extensions/browser/extension_function_registry.h" 34 #include "extensions/browser/extension_function_registry.h"
33 #include "extensions/browser/extension_registry.h" 35 #include "extensions/browser/extension_registry.h"
34 #include "extensions/browser/extension_system.h" 36 #include "extensions/browser/extension_system.h"
37 #include "extensions/browser/extension_util.h"
35 #include "extensions/browser/extensions_browser_client.h" 38 #include "extensions/browser/extensions_browser_client.h"
36 #include "extensions/browser/io_thread_extension_message_filter.h" 39 #include "extensions/browser/io_thread_extension_message_filter.h"
37 #include "extensions/browser/process_manager.h" 40 #include "extensions/browser/process_manager.h"
38 #include "extensions/browser/process_map.h" 41 #include "extensions/browser/process_map.h"
39 #include "extensions/browser/quota_service.h" 42 #include "extensions/browser/quota_service.h"
40 #include "extensions/common/extension_api.h" 43 #include "extensions/common/extension_api.h"
41 #include "extensions/common/extension_messages.h" 44 #include "extensions/common/extension_messages.h"
42 #include "extensions/common/extension_set.h" 45 #include "extensions/common/extension_set.h"
43 #include "extensions/common/extensions_client.h" 46 #include "extensions/common/extensions_client.h"
44 #include "ipc/ipc_message.h" 47 #include "ipc/ipc_message.h"
45 #include "ipc/ipc_message_macros.h" 48 #include "ipc/ipc_message_macros.h"
46 49
47 using content::BrowserThread; 50 using content::BrowserThread;
48 using content::RenderViewHost; 51 using content::RenderViewHost;
49 52
50 namespace extensions { 53 namespace extensions {
51 namespace { 54 namespace {
52 55
53 // Notifies the ApiActivityMonitor that an extension API function has been 56 // Notifies the ApiActivityMonitor that an extension API function has been
54 // called. May be called from any thread. 57 // called. May be called from any thread.
55 void NotifyApiFunctionCalled(const std::string& extension_id, 58 void NotifyApiFunctionCalled(const std::string& extension_id,
56 const std::string& api_name, 59 const std::string& api_name,
57 const base::ListValue& args, 60 const base::ListValue& args,
58 content::BrowserContext* browser_context) { 61 content::BrowserContext* browser_context) {
59 activity_monitor::OnApiFunctionCalled(browser_context, extension_id, api_name, 62 activity_monitor::OnApiFunctionCalled(browser_context, extension_id, api_name,
60 args); 63 args);
61 } 64 }
62 65
66 bool IsRequestFromServiceWorker(
67 const ExtensionHostMsg_Request_Params& request_params) {
68 return content::kInvalidServiceWorkerVersionId !=
Devlin 2016/10/05 17:02:25 nit: prefer inverting these
lazyboy 2016/10/06 01:02:06 Done.
69 request_params.service_worker_version_id;
70 }
71
63 // Separate copy of ExtensionAPI used for IO thread extension functions. We need 72 // Separate copy of ExtensionAPI used for IO thread extension functions. We need
64 // this because ExtensionAPI has mutable data. It should be possible to remove 73 // this because ExtensionAPI has mutable data. It should be possible to remove
65 // this once all the extension APIs are updated to the feature system. 74 // this once all the extension APIs are updated to the feature system.
66 struct Static { 75 struct Static {
67 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} 76 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {}
68 std::unique_ptr<ExtensionAPI> api; 77 std::unique_ptr<ExtensionAPI> api;
69 }; 78 };
70 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; 79 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
71 80
72 // Kills the specified process because it sends us a malformed message. 81 // Kills the specified process because it sends us a malformed message.
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 UIThreadWorkerResponseCallbackWrapper> 279 UIThreadWorkerResponseCallbackWrapper>
271 observer_; 280 observer_;
272 const int render_process_id_; 281 const int render_process_id_;
273 const int worker_thread_id_; 282 const int worker_thread_id_;
274 base::WeakPtrFactory<UIThreadWorkerResponseCallbackWrapper> weak_ptr_factory_; 283 base::WeakPtrFactory<UIThreadWorkerResponseCallbackWrapper> weak_ptr_factory_;
275 284
276 DISALLOW_COPY_AND_ASSIGN(UIThreadWorkerResponseCallbackWrapper); 285 DISALLOW_COPY_AND_ASSIGN(UIThreadWorkerResponseCallbackWrapper);
277 }; 286 };
278 287
279 struct ExtensionFunctionDispatcher::WorkerResponseCallbackMapKey { 288 struct ExtensionFunctionDispatcher::WorkerResponseCallbackMapKey {
280 WorkerResponseCallbackMapKey(int render_process_id, int embedded_worker_id) 289 WorkerResponseCallbackMapKey(int render_process_id,
290 int64_t service_worker_version_id)
281 : render_process_id(render_process_id), 291 : render_process_id(render_process_id),
282 embedded_worker_id(embedded_worker_id) {} 292 service_worker_version_id(service_worker_version_id) {}
283 293
284 bool operator<(const WorkerResponseCallbackMapKey& other) const { 294 bool operator<(const WorkerResponseCallbackMapKey& other) const {
285 return std::tie(render_process_id, embedded_worker_id) < 295 return std::tie(render_process_id, service_worker_version_id) <
286 std::tie(other.render_process_id, other.embedded_worker_id); 296 std::tie(other.render_process_id, other.service_worker_version_id);
287 } 297 }
288 298
289 int render_process_id; 299 int render_process_id;
290 int embedded_worker_id; 300 int64_t service_worker_version_id;
291 }; 301 };
292 302
293 WindowController* 303 WindowController*
294 ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController() const { 304 ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController() const {
295 return nullptr; 305 return nullptr;
296 } 306 }
297 307
298 content::WebContents* 308 content::WebContents*
299 ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const { 309 ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const {
300 return nullptr; 310 return nullptr;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 ui_thread_response_callback_wrappers_[render_frame_host] = 421 ui_thread_response_callback_wrappers_[render_frame_host] =
412 callback_wrapper; 422 callback_wrapper;
413 } else { 423 } else {
414 callback_wrapper = iter->second; 424 callback_wrapper = iter->second;
415 } 425 }
416 DispatchWithCallbackInternal( 426 DispatchWithCallbackInternal(
417 params, render_frame_host, render_process_id, 427 params, render_frame_host, render_process_id,
418 callback_wrapper->CreateCallback(params.request_id)); 428 callback_wrapper->CreateCallback(params.request_id));
419 } else { 429 } else {
420 // Extension API from Service Worker. 430 // Extension API from Service Worker.
421 DCHECK_GE(params.embedded_worker_id, 0); 431 DCHECK_NE(params.service_worker_version_id,
432 content::kInvalidServiceWorkerVersionId);
Devlin 2016/10/05 17:02:25 nit: invert
lazyboy 2016/10/06 01:02:06 Done.
422 WorkerResponseCallbackMapKey key(render_process_id, 433 WorkerResponseCallbackMapKey key(render_process_id,
423 params.embedded_worker_id); 434 params.service_worker_version_id);
424 UIThreadWorkerResponseCallbackWrapperMap::const_iterator iter = 435 UIThreadWorkerResponseCallbackWrapperMap::const_iterator iter =
425 ui_thread_response_callback_wrappers_for_worker_.find(key); 436 ui_thread_response_callback_wrappers_for_worker_.find(key);
426 UIThreadWorkerResponseCallbackWrapper* callback_wrapper = nullptr; 437 UIThreadWorkerResponseCallbackWrapper* callback_wrapper = nullptr;
427 if (iter == ui_thread_response_callback_wrappers_for_worker_.end()) { 438 if (iter == ui_thread_response_callback_wrappers_for_worker_.end()) {
428 callback_wrapper = new UIThreadWorkerResponseCallbackWrapper( 439 callback_wrapper = new UIThreadWorkerResponseCallbackWrapper(
429 AsWeakPtr(), render_process_id, params.worker_thread_id); 440 AsWeakPtr(), render_process_id, params.worker_thread_id);
430 ui_thread_response_callback_wrappers_for_worker_[key] = 441 ui_thread_response_callback_wrappers_for_worker_[key] =
431 base::WrapUnique(callback_wrapper); 442 base::WrapUnique(callback_wrapper);
432 } else { 443 } else {
433 callback_wrapper = iter->second.get(); 444 callback_wrapper = iter->second.get();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 ExtensionAPI::GetSharedInstance(), browser_context_, callback)); 476 ExtensionAPI::GetSharedInstance(), browser_context_, callback));
466 if (!function.get()) 477 if (!function.get())
467 return; 478 return;
468 479
469 UIThreadExtensionFunction* function_ui = 480 UIThreadExtensionFunction* function_ui =
470 function->AsUIThreadExtensionFunction(); 481 function->AsUIThreadExtensionFunction();
471 if (!function_ui) { 482 if (!function_ui) {
472 NOTREACHED(); 483 NOTREACHED();
473 return; 484 return;
474 } 485 }
475 if (params.embedded_worker_id != -1) { 486 if (IsRequestFromServiceWorker(params)) {
476 function_ui->set_is_from_service_worker(true); 487 function_ui->set_service_worker_version_id(
488 params.service_worker_version_id);
477 } else { 489 } else {
478 function_ui->SetRenderFrameHost(render_frame_host); 490 function_ui->SetRenderFrameHost(render_frame_host);
479 } 491 }
480 function_ui->set_dispatcher(AsWeakPtr()); 492 function_ui->set_dispatcher(AsWeakPtr());
481 function_ui->set_browser_context(browser_context_); 493 function_ui->set_browser_context(browser_context_);
482 if (extension && 494 if (extension &&
483 ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito( 495 ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
484 extension, browser_context_)) { 496 extension, browser_context_)) {
485 function->set_include_incognito(true); 497 function->set_include_incognito(true);
486 } 498 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 function->OnQuotaExceeded(violation_error); 541 function->OnQuotaExceeded(violation_error);
530 } 542 }
531 543
532 // Note: do not access |this| after this point. We may have been deleted 544 // Note: do not access |this| after this point. We may have been deleted
533 // if function->Run() ended up closing the tab that owns us. 545 // if function->Run() ended up closing the tab that owns us.
534 546
535 // Check if extension was uninstalled by management.uninstall. 547 // Check if extension was uninstalled by management.uninstall.
536 if (!registry->enabled_extensions().GetByID(params.extension_id)) 548 if (!registry->enabled_extensions().GetByID(params.extension_id))
537 return; 549 return;
538 550
539 // We only adjust the keepalive count for UIThreadExtensionFunction for 551 if (IsRequestFromServiceWorker(params)) {
Devlin 2016/10/05 17:02:25 Similar comment to line 583: if (!IsRequestFromSW(
lazyboy 2016/10/06 01:02:06 Done.
540 // now, largely for simplicity's sake. This is OK because currently, only 552 // Incrementing ref count of service worker extension API is done separately
541 // the webRequest API uses IOThreadExtensionFunction, and that API is not 553 // on IO thread via IPC.
542 // compatible with lazy background pages. 554 } else {
543 // TODO(lazyboy): API functions from extension Service Worker will incorrectly 555 // We only adjust the keepalive count for UIThreadExtensionFunction for
544 // change keepalive count below. 556 // now, largely for simplicity's sake. This is OK because currently, only
545 process_manager->IncrementLazyKeepaliveCount(extension); 557 // the webRequest API uses IOThreadExtensionFunction, and that API is not
558 // compatible with lazy background pages.
559
560 // Increment ref count for non-service worker extension API.
561 process_manager->IncrementLazyKeepaliveCount(function->extension());
562 }
546 } 563 }
547 564
548 void ExtensionFunctionDispatcher::RemoveWorkerCallbacksForProcess( 565 void ExtensionFunctionDispatcher::RemoveWorkerCallbacksForProcess(
549 int render_process_id) { 566 int render_process_id) {
550 UIThreadWorkerResponseCallbackWrapperMap& map = 567 UIThreadWorkerResponseCallbackWrapperMap& map =
551 ui_thread_response_callback_wrappers_for_worker_; 568 ui_thread_response_callback_wrappers_for_worker_;
552 for (UIThreadWorkerResponseCallbackWrapperMap::iterator it = map.begin(); 569 for (UIThreadWorkerResponseCallbackWrapperMap::iterator it = map.begin();
553 it != map.end();) { 570 it != map.end();) {
554 if (it->first.render_process_id == render_process_id) { 571 if (it->first.render_process_id == render_process_id) {
555 it = map.erase(it); 572 it = map.erase(it);
556 continue; 573 continue;
557 } 574 }
558 ++it; 575 ++it;
559 } 576 }
560 } 577 }
561 578
562 void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted( 579 void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted(
563 const Extension* extension) { 580 const Extension* extension,
564 // TODO(lazyboy): API functions from extension Service Worker will incorrectly 581 int64_t service_worker_version_id) {
Devlin 2016/10/05 17:02:25 Perhaps just pass in bool is_from_service_worker,
lazyboy 2016/10/06 01:02:06 Done.
565 // change keepalive count below.
566 if (extension) { 582 if (extension) {
567 ProcessManager::Get(browser_context_) 583 if (service_worker_version_id == content::kInvalidServiceWorkerVersionId) {
Devlin 2016/10/05 17:02:25 I think this is cleaner as: if (extension && !is_f
lazyboy 2016/10/06 01:02:06 Done.
568 ->DecrementLazyKeepaliveCount(extension); 584 // Decrement ref count for non-service worker extension API.
585 ProcessManager::Get(browser_context_)
586 ->DecrementLazyKeepaliveCount(extension);
587 } else {
588 // Decrement ref count for service worker extension API is done separately
589 // on IO thread directly via IPC.
590 }
569 } 591 }
570 } 592 }
571 593
572 WindowController* 594 WindowController*
573 ExtensionFunctionDispatcher::GetExtensionWindowController() const { 595 ExtensionFunctionDispatcher::GetExtensionWindowController() const {
574 return delegate_ ? delegate_->GetExtensionWindowController() : nullptr; 596 return delegate_ ? delegate_->GetExtensionWindowController() : nullptr;
575 } 597 }
576 598
577 content::WebContents* 599 content::WebContents*
578 ExtensionFunctionDispatcher::GetAssociatedWebContents() const { 600 ExtensionFunctionDispatcher::GetAssociatedWebContents() const {
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
634 // static 656 // static
635 void ExtensionFunctionDispatcher::SendAccessDenied( 657 void ExtensionFunctionDispatcher::SendAccessDenied(
636 const ExtensionFunction::ResponseCallback& callback, 658 const ExtensionFunction::ResponseCallback& callback,
637 functions::HistogramValue histogram_value) { 659 functions::HistogramValue histogram_value) {
638 base::ListValue empty_list; 660 base::ListValue empty_list;
639 callback.Run(ExtensionFunction::FAILED, empty_list, 661 callback.Run(ExtensionFunction::FAILED, empty_list,
640 "Access to extension API denied.", histogram_value); 662 "Access to extension API denied.", histogram_value);
641 } 663 }
642 664
643 } // namespace extensions 665 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698