| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/json/json_string_value_serializer.h" | 8 #include "base/json/json_string_value_serializer.h" |
| 9 #include "base/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/metrics/sparse_histogram.h" | 12 #include "base/metrics/sparse_histogram.h" |
| 13 #include "base/process/process.h" | 13 #include "base/process/process.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "build/build_config.h" | 15 #include "build/build_config.h" |
| 16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 17 #include "content/public/browser/child_process_security_policy.h" | |
| 18 #include "content/public/browser/render_frame_host.h" | 17 #include "content/public/browser/render_frame_host.h" |
| 19 #include "content/public/browser/render_process_host.h" | 18 #include "content/public/browser/render_process_host.h" |
| 20 #include "content/public/browser/render_view_host.h" | 19 #include "content/public/browser/render_view_host.h" |
| 21 #include "content/public/browser/user_metrics.h" | 20 #include "content/public/browser/user_metrics.h" |
| 22 #include "content/public/browser/web_contents.h" | 21 #include "content/public/browser/web_contents.h" |
| 23 #include "content/public/browser/web_contents_observer.h" | 22 #include "content/public/browser/web_contents_observer.h" |
| 24 #include "content/public/common/result_codes.h" | 23 #include "content/public/common/result_codes.h" |
| 25 #include "extensions/browser/api_activity_monitor.h" | 24 #include "extensions/browser/api_activity_monitor.h" |
| 26 #include "extensions/browser/extension_function_registry.h" | 25 #include "extensions/browser/extension_function_registry.h" |
| 27 #include "extensions/browser/extension_message_filter.h" | 26 #include "extensions/browser/extension_message_filter.h" |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 422 const ExtensionHostMsg_Request_Params& params, | 421 const ExtensionHostMsg_Request_Params& params, |
| 423 const ExtensionFunction::ResponseCallback& callback) { | 422 const ExtensionFunction::ResponseCallback& callback) { |
| 424 if (!function->HasPermission()) { | 423 if (!function->HasPermission()) { |
| 425 LOG(ERROR) << "Permission denied for " << params.name; | 424 LOG(ERROR) << "Permission denied for " << params.name; |
| 426 SendAccessDenied(callback); | 425 SendAccessDenied(callback); |
| 427 return false; | 426 return false; |
| 428 } | 427 } |
| 429 return true; | 428 return true; |
| 430 } | 429 } |
| 431 | 430 |
| 432 namespace { | |
| 433 | |
| 434 // Only COMPONENT hosted apps may call extension APIs, and they are limited | |
| 435 // to just the permissions they explicitly request. They should not have access | |
| 436 // to extension APIs like eg chrome.runtime, chrome.windows, etc. that normally | |
| 437 // are available without permission. | |
| 438 // TODO(mpcomplete): move this to ExtensionFunction::HasPermission (or remove | |
| 439 // it altogether). | |
| 440 bool AllowHostedAppAPICall(const Extension& extension, | |
| 441 const GURL& source_url, | |
| 442 const std::string& function_name) { | |
| 443 if (extension.location() != Manifest::COMPONENT) | |
| 444 return false; | |
| 445 | |
| 446 if (!extension.web_extent().MatchesURL(source_url)) | |
| 447 return false; | |
| 448 | |
| 449 // Note: Not BLESSED_WEB_PAGE_CONTEXT here because these component hosted app | |
| 450 // entities have traditionally been treated as blessed extensions, for better | |
| 451 // or worse. | |
| 452 Feature::Availability availability = | |
| 453 ExtensionAPI::GetSharedInstance()->IsAvailable( | |
| 454 function_name, &extension, Feature::BLESSED_EXTENSION_CONTEXT, | |
| 455 source_url); | |
| 456 return availability.is_available(); | |
| 457 } | |
| 458 | |
| 459 } // namespace | |
| 460 | |
| 461 | |
| 462 // static | 431 // static |
| 463 ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction( | 432 ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction( |
| 464 const ExtensionHostMsg_Request_Params& params, | 433 const ExtensionHostMsg_Request_Params& params, |
| 465 const Extension* extension, | 434 const Extension* extension, |
| 466 int requesting_process_id, | 435 int requesting_process_id, |
| 467 const ProcessMap& process_map, | 436 const ProcessMap& process_map, |
| 468 ExtensionAPI* api, | 437 ExtensionAPI* api, |
| 469 void* profile_id, | 438 void* profile_id, |
| 470 const ExtensionFunction::ResponseCallback& callback) { | 439 const ExtensionFunction::ResponseCallback& callback) { |
| 471 const char* disallowed_reason = NULL; | |
| 472 | |
| 473 if (extension) { | |
| 474 // Extension is calling this API. | |
| 475 if (extension->is_hosted_app() && | |
| 476 !AllowHostedAppAPICall(*extension, params.source_url, params.name)) { | |
| 477 // Most hosted apps can't call APIs. | |
| 478 disallowed_reason = "Hosted apps cannot call privileged APIs"; | |
| 479 } else if (!process_map.Contains(extension->id(), requesting_process_id) && | |
| 480 !api->IsAvailableInUntrustedContext(params.name, extension)) { | |
| 481 // Privileged APIs can only be called from the process the extension | |
| 482 // is running in. | |
| 483 disallowed_reason = | |
| 484 "Privileged APIs cannot be called from untrusted processes"; | |
| 485 } | |
| 486 } else if (content::ChildProcessSecurityPolicy::GetInstance() | |
| 487 ->HasWebUIBindings(requesting_process_id)) { | |
| 488 // WebUI is calling this API. | |
| 489 if (!api->IsAvailableToWebUI(params.name, params.source_url)) { | |
| 490 disallowed_reason = "WebUI can only call webui-enabled APIs"; | |
| 491 } | |
| 492 } else { | |
| 493 // Web page is calling this API. However, the APIs that are available to | |
| 494 // web pages (e.g. messaging) don't go through ExtensionFunctionDispatcher, | |
| 495 // so this should be impossible. | |
| 496 NOTREACHED(); | |
| 497 disallowed_reason = "Specified extension does not exist."; | |
| 498 } | |
| 499 | |
| 500 if (disallowed_reason != NULL) { | |
| 501 LOG(ERROR) << "Extension API call disallowed - name:" << params.name | |
| 502 << ", pid:" << requesting_process_id | |
| 503 << ", from URL: " << params.source_url.spec() | |
| 504 << ", reason: " << disallowed_reason; | |
| 505 SendAccessDenied(callback); | |
| 506 return NULL; | |
| 507 } | |
| 508 | |
| 509 ExtensionFunction* function = | 440 ExtensionFunction* function = |
| 510 ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name); | 441 ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name); |
| 511 if (!function) { | 442 if (!function) { |
| 512 LOG(ERROR) << "Unknown Extension API - " << params.name; | 443 LOG(ERROR) << "Unknown Extension API - " << params.name; |
| 513 SendAccessDenied(callback); | 444 SendAccessDenied(callback); |
| 514 return NULL; | 445 return NULL; |
| 515 } | 446 } |
| 516 | 447 |
| 517 function->SetArgs(¶ms.arguments); | 448 function->SetArgs(¶ms.arguments); |
| 518 function->set_source_url(params.source_url); | 449 function->set_source_url(params.source_url); |
| 519 function->set_request_id(params.request_id); | 450 function->set_request_id(params.request_id); |
| 520 function->set_has_callback(params.has_callback); | 451 function->set_has_callback(params.has_callback); |
| 521 function->set_user_gesture(params.user_gesture); | 452 function->set_user_gesture(params.user_gesture); |
| 522 function->set_extension(extension); | 453 function->set_extension(extension); |
| 523 function->set_profile_id(profile_id); | 454 function->set_profile_id(profile_id); |
| 524 function->set_response_callback(callback); | 455 function->set_response_callback(callback); |
| 525 function->set_source_tab_id(params.source_tab_id); | 456 function->set_source_tab_id(params.source_tab_id); |
| 457 function->set_source_context_type( |
| 458 process_map.GuessContextType(extension, requesting_process_id)); |
| 526 | 459 |
| 527 return function; | 460 return function; |
| 528 } | 461 } |
| 529 | 462 |
| 530 // static | 463 // static |
| 531 void ExtensionFunctionDispatcher::SendAccessDenied( | 464 void ExtensionFunctionDispatcher::SendAccessDenied( |
| 532 const ExtensionFunction::ResponseCallback& callback) { | 465 const ExtensionFunction::ResponseCallback& callback) { |
| 533 base::ListValue empty_list; | 466 base::ListValue empty_list; |
| 534 callback.Run(ExtensionFunction::FAILED, empty_list, | 467 callback.Run(ExtensionFunction::FAILED, empty_list, |
| 535 "Access to extension API denied."); | 468 "Access to extension API denied."); |
| 536 } | 469 } |
| 537 | 470 |
| 538 } // namespace extensions | 471 } // namespace extensions |
| OLD | NEW |