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

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

Issue 7024056: Handle extension webrequest API on the IO thread. This speeds up blocking event (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review Created 9 years, 6 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 | Annotate | Revision Log
OLDNEW
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 "chrome/browser/extensions/extension_function_dispatcher.h" 5 #include "chrome/browser/extensions/extension_function_dispatcher.h"
6 6
7 #include <map> 7 #include <map>
8 8
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/memory/singleton.h" 10 #include "base/memory/singleton.h"
(...skipping 28 matching lines...) Expand all
39 #include "chrome/browser/extensions/extension_tabs_module.h" 39 #include "chrome/browser/extensions/extension_tabs_module.h"
40 #include "chrome/browser/extensions/extension_test_api.h" 40 #include "chrome/browser/extensions/extension_test_api.h"
41 #include "chrome/browser/extensions/extension_tts_api.h" 41 #include "chrome/browser/extensions/extension_tts_api.h"
42 #include "chrome/browser/extensions/extension_web_socket_proxy_private_api.h" 42 #include "chrome/browser/extensions/extension_web_socket_proxy_private_api.h"
43 #include "chrome/browser/extensions/extension_web_ui.h" 43 #include "chrome/browser/extensions/extension_web_ui.h"
44 #include "chrome/browser/extensions/extension_webrequest_api.h" 44 #include "chrome/browser/extensions/extension_webrequest_api.h"
45 #include "chrome/browser/extensions/extension_webstore_private_api.h" 45 #include "chrome/browser/extensions/extension_webstore_private_api.h"
46 #include "chrome/browser/extensions/extensions_quota_service.h" 46 #include "chrome/browser/extensions/extensions_quota_service.h"
47 #include "chrome/browser/external_protocol/external_protocol_handler.h" 47 #include "chrome/browser/external_protocol/external_protocol_handler.h"
48 #include "chrome/browser/profiles/profile.h" 48 #include "chrome/browser/profiles/profile.h"
49 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
49 #include "chrome/browser/ui/browser_list.h" 50 #include "chrome/browser/ui/browser_list.h"
50 #include "chrome/browser/ui/browser_window.h" 51 #include "chrome/browser/ui/browser_window.h"
51 #include "chrome/common/extensions/extension_messages.h" 52 #include "chrome/common/extensions/extension_messages.h"
52 #include "chrome/common/url_constants.h" 53 #include "chrome/common/url_constants.h"
53 #include "content/browser/child_process_security_policy.h" 54 #include "content/browser/child_process_security_policy.h"
54 #include "content/browser/renderer_host/render_process_host.h" 55 #include "content/browser/renderer_host/render_process_host.h"
55 #include "content/browser/renderer_host/render_view_host.h" 56 #include "content/browser/renderer_host/render_view_host.h"
56 #include "ipc/ipc_message.h" 57 #include "ipc/ipc_message.h"
57 #include "ipc/ipc_message_macros.h" 58 #include "ipc/ipc_message_macros.h"
58 #include "third_party/skia/include/core/SkBitmap.h" 59 #include "third_party/skia/include/core/SkBitmap.h"
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 405
405 bool ExtensionFunctionDispatcher::OverrideFunction( 406 bool ExtensionFunctionDispatcher::OverrideFunction(
406 const std::string& name, ExtensionFunctionFactory factory) { 407 const std::string& name, ExtensionFunctionFactory factory) {
407 return FactoryRegistry::GetInstance()->OverrideFunction(name, factory); 408 return FactoryRegistry::GetInstance()->OverrideFunction(name, factory);
408 } 409 }
409 410
410 void ExtensionFunctionDispatcher::ResetFunctions() { 411 void ExtensionFunctionDispatcher::ResetFunctions() {
411 FactoryRegistry::GetInstance()->ResetFunctions(); 412 FactoryRegistry::GetInstance()->ResetFunctions();
412 } 413 }
413 414
415 // static
416 void ExtensionFunctionDispatcher::DispatchOnIOThread(
417 const ExtensionInfoMap* extension_info_map,
418 ProfileId profile_id,
419 int render_process_id,
420 base::WeakPtr<ChromeRenderMessageFilter> ipc_sender,
421 int routing_id,
422 const ExtensionHostMsg_Request_Params& params) {
423 const Extension* extension =
424 extension_info_map->extensions().GetByURL(params.source_url);
425
426 scoped_refptr<ExtensionFunction> function(
427 CreateExtensionFunction(params, extension, profile_id, render_process_id,
428 ipc_sender, routing_id));
429 if (!function)
430 return;
431
432 IOThreadExtensionFunction* function_io =
433 function->AsIOThreadExtensionFunction();
434 if (!function_io) {
435 NOTREACHED();
436 return;
437 }
438 function_io->set_ipc_sender(ipc_sender, routing_id);
439 function_io->set_extension_info_map(extension_info_map);
440 function->set_include_incognito(
441 extension_info_map->IsIncognitoEnabled(extension->id()));
442 function->Run();
443 }
444
414 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile, 445 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(Profile* profile,
415 Delegate* delegate) 446 Delegate* delegate)
416 : profile_(profile), 447 : profile_(profile),
417 delegate_(delegate) { 448 delegate_(delegate) {
418 } 449 }
419 450
420 ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { 451 ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
421 } 452 }
422 453
423 Browser* ExtensionFunctionDispatcher::GetCurrentBrowser( 454 Browser* ExtensionFunctionDispatcher::GetCurrentBrowser(
(...skipping 17 matching lines...) Expand all
441 // before the browser is sufficiently initialized to return here. 472 // before the browser is sufficiently initialized to return here.
442 // A similar situation may arise during shutdown. 473 // A similar situation may arise during shutdown.
443 // TODO(rafaelw): Delay creation of background_page until the browser 474 // TODO(rafaelw): Delay creation of background_page until the browser
444 // is available. http://code.google.com/p/chromium/issues/detail?id=13284 475 // is available. http://code.google.com/p/chromium/issues/detail?id=13284
445 return browser; 476 return browser;
446 } 477 }
447 478
448 void ExtensionFunctionDispatcher::Dispatch( 479 void ExtensionFunctionDispatcher::Dispatch(
449 const ExtensionHostMsg_Request_Params& params, 480 const ExtensionHostMsg_Request_Params& params,
450 RenderViewHost* render_view_host) { 481 RenderViewHost* render_view_host) {
451 // TODO(aa): It would be cool to use ExtensionProcessManager to track which
452 // processes are extension processes rather than ChildProcessSecurityPolicy.
453 // EPM has richer information: it not only knows which processes contain
454 // at least one extension, but it knows which extensions are inside and what
455 // permissions the have. So we would be able to enforce permissions more
456 // granularly.
457 if (!ChildProcessSecurityPolicy::GetInstance()->HasExtensionBindings(
458 render_view_host->process()->id())) {
459 // TODO(aa): Allow content scripts access to low-threat extension APIs.
460 // See: crbug.com/80308.
461 LOG(ERROR) << "Extension API called from non-extension process.";
462 SendAccessDenied(render_view_host, params.request_id);
463 return;
464 }
465
466 ExtensionService* service = profile()->GetExtensionService(); 482 ExtensionService* service = profile()->GetExtensionService();
467 if (!service) 483 if (!service)
468 return; 484 return;
469 485
470 if (!service->ExtensionBindingsAllowed(params.source_url)) { 486 if (!service->ExtensionBindingsAllowed(params.source_url)) {
471 LOG(ERROR) << "Extension bindings not allowed for URL: " 487 LOG(ERROR) << "Extension bindings not allowed for URL: "
472 << params.source_url.spec(); 488 << params.source_url.spec();
473 SendAccessDenied(render_view_host, params.request_id); 489 SendAccessDenied(render_view_host, render_view_host->routing_id(),
490 params.request_id);
474 return; 491 return;
475 } 492 }
476 493
477 // TODO(aa): When we allow content scripts to call extension APIs, we will 494 // TODO(aa): When we allow content scripts to call extension APIs, we will
478 // have to pass the extension ID explicitly here, not use the source URL. 495 // have to pass the extension ID explicitly here, not use the source URL.
479 const Extension* extension = service->GetExtensionByURL(params.source_url); 496 const Extension* extension = service->GetExtensionByURL(params.source_url);
480 if (!extension) 497 if (!extension)
481 extension = service->GetExtensionByWebExtent(params.source_url); 498 extension = service->GetExtensionByWebExtent(params.source_url);
482 if (!extension) { 499
483 LOG(ERROR) << "Extension does not exist for URL: " 500 scoped_refptr<ExtensionFunction> function(CreateExtensionFunction(
484 << params.source_url.spec(); 501 params, extension, profile_->GetRuntimeId(),
485 SendAccessDenied(render_view_host, params.request_id); 502 render_view_host->process()->id(),
503 render_view_host, render_view_host->routing_id()));
504 if (!function)
486 return; 505 return;
487 }
488 506
489 if (!extension->HasApiPermission(params.name)) {
490 LOG(ERROR) << "Extension " << extension->id() << " does not have "
491 << "permission to function: " << params.name;
492 SendAccessDenied(render_view_host, params.request_id);
493 return;
494 }
495
496 scoped_refptr<ExtensionFunction> function(
497 FactoryRegistry::GetInstance()->NewFunction(params.name));
498 UIThreadExtensionFunction* function_ui = 507 UIThreadExtensionFunction* function_ui =
499 function->AsUIThreadExtensionFunction(); 508 function->AsUIThreadExtensionFunction();
500 if (!function_ui) { 509 if (!function_ui) {
501 NOTREACHED(); 510 NOTREACHED();
502 return; 511 return;
503 } 512 }
504 function_ui->SetRenderViewHost(render_view_host); 513 function_ui->SetRenderViewHost(render_view_host);
505 function_ui->set_dispatcher(AsWeakPtr()); 514 function_ui->set_dispatcher(AsWeakPtr());
506 function_ui->set_profile(profile_); 515 function_ui->set_profile(profile_);
507
508 function->set_profile_id(profile_->GetRuntimeId());
509 function->set_extension(extension);
510 function->SetArgs(&params.arguments);
511 function->set_source_url(params.source_url);
512 function->set_request_id(params.request_id);
513 function->set_has_callback(params.has_callback);
514 function->set_user_gesture(params.user_gesture);
515 function->set_include_incognito(service->CanCrossIncognito(extension)); 516 function->set_include_incognito(service->CanCrossIncognito(extension));
516 517
517 ExtensionsQuotaService* quota = service->quota_service(); 518 ExtensionsQuotaService* quota = service->quota_service();
518 if (quota->Assess(extension->id(), function, &params.arguments, 519 if (quota->Assess(extension->id(), function, &params.arguments,
519 base::TimeTicks::Now())) { 520 base::TimeTicks::Now())) {
520 // See crbug.com/39178. 521 // See crbug.com/39178.
521 ExternalProtocolHandler::PermitLaunchUrl(); 522 ExternalProtocolHandler::PermitLaunchUrl();
522 523
523 function->Run(); 524 function->Run();
524 } else { 525 } else {
525 render_view_host->Send(new ExtensionMsg_Response( 526 render_view_host->Send(new ExtensionMsg_Response(
526 render_view_host->routing_id(), function->request_id(), false, 527 render_view_host->routing_id(), function->request_id(), false,
527 std::string(), QuotaLimitHeuristic::kGenericOverQuotaError)); 528 std::string(), QuotaLimitHeuristic::kGenericOverQuotaError));
528 } 529 }
529 } 530 }
530 531
532 // static
533 ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
534 const ExtensionHostMsg_Request_Params& params,
535 const Extension* extension,
536 ProfileId profile_id,
537 int render_process_id,
538 IPC::Message::Sender* ipc_sender,
539 int routing_id) {
540 // TODO(aa): It would be cool to use ExtensionProcessManager to track which
541 // processes are extension processes rather than ChildProcessSecurityPolicy.
542 // EPM has richer information: it not only knows which processes contain
543 // at least one extension, but it knows which extensions are inside and what
544 // permissions the have. So we would be able to enforce permissions more
545 // granularly.
546 if (!ChildProcessSecurityPolicy::GetInstance()->HasExtensionBindings(
547 render_process_id)) {
548 // TODO(aa): Allow content scripts access to low-threat extension APIs.
549 // See: crbug.com/80308.
550 LOG(ERROR) << "Extension API called from non-extension process.";
551 SendAccessDenied(ipc_sender, routing_id, params.request_id);
552 return NULL;
553 }
554
555 if (!extension) {
556 LOG(ERROR) << "Extension does not exist for URL: "
557 << params.source_url.spec();
558 SendAccessDenied(ipc_sender, routing_id, params.request_id);
559 return NULL;
560 }
561
562 if (!extension->HasApiPermission(params.name)) {
563 LOG(ERROR) << "Extension " << extension->id() << " does not have "
564 << "permission to function: " << params.name;
565 SendAccessDenied(ipc_sender, routing_id, params.request_id);
566 return NULL;
567 }
568
569 ExtensionFunction* function =
570 FactoryRegistry::GetInstance()->NewFunction(params.name);
571 function->SetArgs(&params.arguments);
572 function->set_source_url(params.source_url);
573 function->set_request_id(params.request_id);
574 function->set_has_callback(params.has_callback);
575 function->set_user_gesture(params.user_gesture);
576 function->set_extension(extension);
577 function->set_profile_id(profile_id);
578 return function;
579 }
580
581 // static
531 void ExtensionFunctionDispatcher::SendAccessDenied( 582 void ExtensionFunctionDispatcher::SendAccessDenied(
532 RenderViewHost* render_view_host, int request_id) { 583 IPC::Message::Sender* ipc_sender, int routing_id, int request_id) {
533 render_view_host->Send(new ExtensionMsg_Response( 584 ipc_sender->Send(new ExtensionMsg_Response(
534 render_view_host->routing_id(), request_id, false, std::string(), 585 routing_id, request_id, false, std::string(),
535 "Access to extension API denied.")); 586 "Access to extension API denied."));
536 } 587 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_function_dispatcher.h ('k') | chrome/browser/extensions/extension_info_map.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698