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

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

Powered by Google App Engine
This is Rietveld 408576698