| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/renderer/chrome_content_renderer_client.h" | 5 #include "chrome/renderer/chrome_content_renderer_client.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 using WebKit::WebSecurityPolicy; | 96 using WebKit::WebSecurityPolicy; |
| 97 using WebKit::WebString; | 97 using WebKit::WebString; |
| 98 using WebKit::WebURL; | 98 using WebKit::WebURL; |
| 99 using WebKit::WebURLError; | 99 using WebKit::WebURLError; |
| 100 using WebKit::WebURLRequest; | 100 using WebKit::WebURLRequest; |
| 101 using WebKit::WebURLResponse; | 101 using WebKit::WebURLResponse; |
| 102 using WebKit::WebVector; | 102 using WebKit::WebVector; |
| 103 using autofill::AutofillAgent; | 103 using autofill::AutofillAgent; |
| 104 using autofill::PasswordAutofillManager; | 104 using autofill::PasswordAutofillManager; |
| 105 using content::RenderThread; | 105 using content::RenderThread; |
| 106 using webkit::WebPluginInfo; |
| 107 using webkit::WebPluginMimeType; |
| 106 | 108 |
| 107 namespace { | 109 namespace { |
| 108 | 110 |
| 109 static void AppendParams(const std::vector<string16>& additional_names, | 111 static void AppendParams(const std::vector<string16>& additional_names, |
| 110 const std::vector<string16>& additional_values, | 112 const std::vector<string16>& additional_values, |
| 111 WebVector<WebString>* existing_names, | 113 WebVector<WebString>* existing_names, |
| 112 WebVector<WebString>* existing_values) { | 114 WebVector<WebString>* existing_values) { |
| 113 DCHECK(additional_names.size() == additional_values.size()); | 115 DCHECK(additional_names.size() == additional_values.size()); |
| 114 DCHECK(existing_names->size() == existing_values->size()); | 116 DCHECK(existing_names->size() == existing_values->size()); |
| 115 | 117 |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 // Delay loading plugins if prerendering. | 367 // Delay loading plugins if prerendering. |
| 366 if (prerender::PrerenderHelper::IsPrerendering(render_view)) { | 368 if (prerender::PrerenderHelper::IsPrerendering(render_view)) { |
| 367 placeholder = PluginPlaceholder::CreateBlockedPlugin( | 369 placeholder = PluginPlaceholder::CreateBlockedPlugin( |
| 368 render_view, frame, params, plugin, name, | 370 render_view, frame, params, plugin, name, |
| 369 IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD); | 371 IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD); |
| 370 placeholder->set_blocked_for_prerendering(true); | 372 placeholder->set_blocked_for_prerendering(true); |
| 371 placeholder->set_allow_loading(true); | 373 placeholder->set_allow_loading(true); |
| 372 break; | 374 break; |
| 373 } | 375 } |
| 374 | 376 |
| 375 // Determine if NaCl is allowed for both the internal plugin and | |
| 376 // any external plugin that handles our MIME type. This is so NaCl | |
| 377 // tests will still pass. | |
| 378 const char* kNaClMimeType = "application/x-nacl"; | 377 const char* kNaClMimeType = "application/x-nacl"; |
| 379 bool is_nacl_mime_type = actual_mime_type == kNaClMimeType; | 378 bool is_nacl_mime_type = actual_mime_type == kNaClMimeType; |
| 380 bool is_nacl_enabled; | 379 bool is_nacl_unrestricted; |
| 381 if (is_nacl_plugin) { | 380 if (is_nacl_plugin) { |
| 382 is_nacl_enabled = CommandLine::ForCurrentProcess()->HasSwitch( | 381 is_nacl_unrestricted = CommandLine::ForCurrentProcess()->HasSwitch( |
| 383 switches::kEnableNaCl); | 382 switches::kEnableNaCl); |
| 384 } else { | 383 } else { |
| 385 // If this is an external plugin that handles NaCl mime type, | 384 // If this is an external plugin that handles the NaCl mime type, we |
| 386 // we want to allow Native Client, because it's how | 385 // allow Native Client, so Native Client's integration tests work. |
| 387 // NaCl tests for the plugin work. | 386 is_nacl_unrestricted = true; |
| 388 is_nacl_enabled = true; | |
| 389 } | 387 } |
| 390 if (is_nacl_plugin || is_nacl_mime_type) { | 388 if (is_nacl_plugin || is_nacl_mime_type) { |
| 391 if (!IsNaClAllowed(plugin, | 389 GURL manifest_url = is_nacl_mime_type ? |
| 392 url, | 390 url : GetNaClContentHandlerURL(actual_mime_type, plugin); |
| 393 actual_mime_type, | 391 const Extension* extension = |
| 394 is_nacl_mime_type, | 392 extension_dispatcher_->extensions()->GetExtensionOrAppByURL( |
| 395 is_nacl_enabled, | 393 ExtensionURLInfo(manifest_url)); |
| 396 params)) { | 394 bool is_extension_from_webstore = |
| 395 extension && extension->from_webstore(); |
| 396 // Allow built-in extensions and extensions under development. |
| 397 bool is_extension_unrestricted = extension && |
| 398 (extension->location() == Extension::COMPONENT || |
| 399 extension->location() == Extension::LOAD); |
| 400 GURL top_url = frame->top()->document().url(); |
| 401 if (!IsNaClAllowed(manifest_url, |
| 402 top_url, |
| 403 is_nacl_unrestricted, |
| 404 is_extension_unrestricted, |
| 405 is_extension_from_webstore, |
| 406 ¶ms)) { |
| 397 frame->addMessageToConsole( | 407 frame->addMessageToConsole( |
| 398 WebConsoleMessage( | 408 WebConsoleMessage( |
| 399 WebConsoleMessage::LevelError, | 409 WebConsoleMessage::LevelError, |
| 400 "Only unpacked extensions and apps installed from the " | 410 "Only unpacked extensions and apps installed from the " |
| 401 "Chrome Web Store can load NaCl modules without enabling " | 411 "Chrome Web Store can load NaCl modules without enabling " |
| 402 "Native Client in about:flags.")); | 412 "Native Client in about:flags.")); |
| 403 placeholder = PluginPlaceholder::CreateBlockedPlugin( | 413 placeholder = PluginPlaceholder::CreateBlockedPlugin( |
| 404 render_view, frame, params, plugin, name, | 414 render_view, frame, params, plugin, name, |
| 405 IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED); | 415 IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED); |
| 406 break; | 416 break; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 RenderThread::Get()->RecordUserMetrics("Plugin_Blocked"); | 470 RenderThread::Get()->RecordUserMetrics("Plugin_Blocked"); |
| 461 observer->DidBlockContentType(content_type, group->identifier()); | 471 observer->DidBlockContentType(content_type, group->identifier()); |
| 462 break; | 472 break; |
| 463 } | 473 } |
| 464 } | 474 } |
| 465 } | 475 } |
| 466 placeholder->SetStatus(status); | 476 placeholder->SetStatus(status); |
| 467 return placeholder->plugin(); | 477 return placeholder->plugin(); |
| 468 } | 478 } |
| 469 | 479 |
| 480 // For NaCl content handling plugins, the NaCl manifest is stored in an |
| 481 // additonal 'nacl' param associated with the MIME type. |
| 482 // static |
| 483 GURL ChromeContentRendererClient::GetNaClContentHandlerURL( |
| 484 const std::string& actual_mime_type, |
| 485 const webkit::WebPluginInfo& plugin) { |
| 486 // Look for the manifest URL among the MIME type's additonal parameters. |
| 487 const char* kNaClPluginManifestAttribute = "nacl"; |
| 488 string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute); |
| 489 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { |
| 490 if (plugin.mime_types[i].mime_type == actual_mime_type) { |
| 491 const WebPluginMimeType& content_type = plugin.mime_types[i]; |
| 492 for (size_t i = 0; i < content_type.additional_param_names.size(); ++i) { |
| 493 if (content_type.additional_param_names[i] == nacl_attr) |
| 494 return GURL(content_type.additional_param_values[i]); |
| 495 } |
| 496 break; |
| 497 } |
| 498 } |
| 499 return GURL(); |
| 500 } |
| 501 |
| 502 // static |
| 470 bool ChromeContentRendererClient::IsNaClAllowed( | 503 bool ChromeContentRendererClient::IsNaClAllowed( |
| 471 const webkit::WebPluginInfo& plugin, | 504 const GURL& manifest_url, |
| 472 const GURL& url, | 505 const GURL& top_url, |
| 473 const std::string& actual_mime_type, | 506 bool is_nacl_unrestricted, |
| 474 bool is_nacl_mime_type, | 507 bool is_extension_unrestricted, |
| 475 bool enable_nacl, | 508 bool is_extension_from_webstore, |
| 476 WebKit::WebPluginParams& params) { | 509 WebPluginParams* params) { |
| 477 GURL manifest_url; | 510 // Temporarily allow these URLs to run NaCl apps. We should remove this |
| 478 if (is_nacl_mime_type) { | 511 // code when PNaCl ships. |
| 479 manifest_url = url; // Normal embedded NaCl plugin. | 512 bool is_whitelisted_url = |
| 480 } else { | 513 ((top_url.SchemeIs("http") || top_url.SchemeIs("https")) && |
| 481 // This is a content type handling NaCl plugin; look for the .nexe URL | 514 (top_url.host() == "plus.google.com" || |
| 482 // among the MIME type's additonal parameters. | 515 top_url.host() == "plus.sandbox.google.com") && |
| 483 const char* kNaClPluginManifestAttribute = "nacl"; | 516 top_url.path().find("/games") == 0); |
| 484 string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute); | 517 |
| 485 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { | 518 // Allow Chrome Web Store extensions, built-in extensions, extensions |
| 486 if (plugin.mime_types[i].mime_type == actual_mime_type) { | 519 // under development, invocations from whitelisted URLs, and all invocations |
| 487 const webkit::WebPluginMimeType& content_type = | 520 // if --enable-nacl is set. |
| 488 plugin.mime_types[i]; | 521 bool is_nacl_allowed = |
| 489 for (size_t i = 0; | 522 is_extension_from_webstore || |
| 490 i < content_type.additional_param_names.size(); ++i) { | 523 is_extension_unrestricted || |
| 491 if (content_type.additional_param_names[i] == nacl_attr) { | 524 is_whitelisted_url || |
| 492 manifest_url = GURL(content_type.additional_param_values[i]); | 525 is_nacl_unrestricted; |
| 493 break; | 526 if (is_nacl_allowed) { |
| 494 } | 527 bool app_can_use_dev_interfaces = |
| 495 } | 528 // NaCl PDF viewer extension |
| 496 break; | 529 (is_extension_from_webstore && |
| 530 manifest_url.SchemeIs("chrome-extension") && |
| 531 manifest_url.host() == "acadkphlmlegjaadjagenfimbpphcgnh"); |
| 532 // Make sure that PPAPI 'dev' interfaces aren't available for production |
| 533 // apps unless they're whitelisted. |
| 534 WebString dev_attribute = WebString::fromUTF8("@dev"); |
| 535 if ((!is_whitelisted_url && !is_extension_from_webstore) || |
| 536 app_can_use_dev_interfaces) { |
| 537 // Add the special '@dev' attribute. |
| 538 std::vector<string16> param_names; |
| 539 std::vector<string16> param_values; |
| 540 param_names.push_back(dev_attribute); |
| 541 param_values.push_back(WebString()); |
| 542 AppendParams( |
| 543 param_names, |
| 544 param_values, |
| 545 ¶ms->attributeNames, |
| 546 ¶ms->attributeValues); |
| 547 } else { |
| 548 // If the params somehow contain '@dev', remove it. |
| 549 size_t attribute_count = params->attributeNames.size(); |
| 550 for (size_t i = 0; i < attribute_count; ++i) { |
| 551 if (params->attributeNames[i].equals(dev_attribute)) |
| 552 params->attributeNames[i] = WebString(); |
| 497 } | 553 } |
| 498 } | 554 } |
| 499 } | 555 } |
| 500 | 556 return is_nacl_allowed; |
| 501 // Determine if the manifest URL is part of an extension. | |
| 502 const Extension* extension = | |
| 503 extension_dispatcher_->extensions()->GetExtensionOrAppByURL( | |
| 504 ExtensionURLInfo(manifest_url)); | |
| 505 // Only component, unpacked, and Chrome Web Store extensions are allowed. | |
| 506 bool allowed_extension = extension && | |
| 507 (extension->from_webstore() || | |
| 508 extension->location() == Extension::COMPONENT || | |
| 509 extension->location() == Extension::LOAD); | |
| 510 | |
| 511 // Block any other use of NaCl plugin, unless --enable-nacl is set. | |
| 512 if (!allowed_extension && !enable_nacl) | |
| 513 return false; | |
| 514 | |
| 515 // Allow dev interfaces for non-extension apps. | |
| 516 bool allow_dev_interfaces = true; | |
| 517 if (allowed_extension) { | |
| 518 // Allow dev interfaces for component and unpacked extensions. | |
| 519 if (extension->location() != Extension::COMPONENT && | |
| 520 extension->location() != Extension::LOAD) { | |
| 521 // Whitelist all other allowed extensions. | |
| 522 allow_dev_interfaces = | |
| 523 // PDF Viewer plugin | |
| 524 (manifest_url.scheme() == "chrome-extension" && | |
| 525 manifest_url.host() == "acadkphlmlegjaadjagenfimbpphcgnh"); | |
| 526 } | |
| 527 } | |
| 528 | |
| 529 WebString dev_attribute = WebString::fromUTF8("@dev"); | |
| 530 if (allow_dev_interfaces) { | |
| 531 std::vector<string16> param_names; | |
| 532 std::vector<string16> param_values; | |
| 533 param_names.push_back(dev_attribute); | |
| 534 param_values.push_back(WebString()); | |
| 535 AppendParams( | |
| 536 param_names, | |
| 537 param_values, | |
| 538 ¶ms.attributeNames, | |
| 539 ¶ms.attributeValues); | |
| 540 } else { | |
| 541 // If the params somehow contain this special attribute, remove it. | |
| 542 size_t attribute_count = params.attributeNames.size(); | |
| 543 for (size_t i = 0; i < attribute_count; ++i) { | |
| 544 if (params.attributeNames[i].equals(dev_attribute)) | |
| 545 params.attributeNames[i] = WebString(); | |
| 546 } | |
| 547 } | |
| 548 | |
| 549 return true; | |
| 550 } | 557 } |
| 551 | 558 |
| 552 bool ChromeContentRendererClient::HasErrorPage(int http_status_code, | 559 bool ChromeContentRendererClient::HasErrorPage(int http_status_code, |
| 553 std::string* error_domain) { | 560 std::string* error_domain) { |
| 554 // Use an internal error page, if we have one for the status code. | 561 // Use an internal error page, if we have one for the status code. |
| 555 if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, | 562 if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, |
| 556 http_status_code)) { | 563 http_status_code)) { |
| 557 return false; | 564 return false; |
| 558 } | 565 } |
| 559 | 566 |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 bool ChromeContentRendererClient::IsOtherExtensionWithWebRequestInstalled() { | 845 bool ChromeContentRendererClient::IsOtherExtensionWithWebRequestInstalled() { |
| 839 return extension_dispatcher_->IsOtherExtensionWithWebRequestInstalled(); | 846 return extension_dispatcher_->IsOtherExtensionWithWebRequestInstalled(); |
| 840 } | 847 } |
| 841 | 848 |
| 842 void ChromeContentRendererClient::RegisterPPAPIInterfaceFactories( | 849 void ChromeContentRendererClient::RegisterPPAPIInterfaceFactories( |
| 843 webkit::ppapi::PpapiInterfaceFactoryManager* factory_manager) { | 850 webkit::ppapi::PpapiInterfaceFactoryManager* factory_manager) { |
| 844 factory_manager->RegisterFactory(ChromePPAPIInterfaceFactory); | 851 factory_manager->RegisterFactory(ChromePPAPIInterfaceFactory); |
| 845 } | 852 } |
| 846 | 853 |
| 847 } // namespace chrome | 854 } // namespace chrome |
| OLD | NEW |