Chromium Code Reviews| 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 const char* kPredefinedAllowedSocketOrigins[] = { | 111 const char* kPredefinedAllowedSocketOrigins[] = { |
| 110 "okddffdblfhhnmhodogpojmfkjmhinfp", // Test SSH Client | 112 "okddffdblfhhnmhodogpojmfkjmhinfp", // Test SSH Client |
| 111 "pnhechapfaindjhompbnflcldabbghjo" // HTerm App (SSH Client) | 113 "pnhechapfaindjhompbnflcldabbghjo" // HTerm App (SSH Client) |
| 112 }; | 114 }; |
| 113 | 115 |
| 114 static void AppendParams(const std::vector<string16>& additional_names, | 116 static void AppendParams(const std::vector<string16>& additional_names, |
| 115 const std::vector<string16>& additional_values, | 117 const std::vector<string16>& additional_values, |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 382 // Delay loading plugins if prerendering. | 384 // Delay loading plugins if prerendering. |
| 383 if (prerender::PrerenderHelper::IsPrerendering(render_view)) { | 385 if (prerender::PrerenderHelper::IsPrerendering(render_view)) { |
| 384 placeholder = PluginPlaceholder::CreateBlockedPlugin( | 386 placeholder = PluginPlaceholder::CreateBlockedPlugin( |
| 385 render_view, frame, params, plugin, name, | 387 render_view, frame, params, plugin, name, |
| 386 IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD); | 388 IDR_CLICK_TO_PLAY_PLUGIN_HTML, IDS_PLUGIN_LOAD); |
| 387 placeholder->set_blocked_for_prerendering(true); | 389 placeholder->set_blocked_for_prerendering(true); |
| 388 placeholder->set_allow_loading(true); | 390 placeholder->set_allow_loading(true); |
| 389 break; | 391 break; |
| 390 } | 392 } |
| 391 | 393 |
| 392 // Determine if NaCl is allowed for both the internal plugin and | |
| 393 // any external plugin that handles our MIME type. This is so NaCl | |
| 394 // tests will still pass. | |
| 395 const char* kNaClMimeType = "application/x-nacl"; | 394 const char* kNaClMimeType = "application/x-nacl"; |
| 396 bool is_nacl_mime_type = actual_mime_type == kNaClMimeType; | 395 bool is_nacl_mime_type = actual_mime_type == kNaClMimeType; |
| 397 bool is_nacl_enabled; | 396 bool is_nacl_unrestricted; |
| 398 if (is_nacl_plugin) { | 397 if (is_nacl_plugin) { |
| 399 is_nacl_enabled = CommandLine::ForCurrentProcess()->HasSwitch( | 398 is_nacl_unrestricted = CommandLine::ForCurrentProcess()->HasSwitch( |
| 400 switches::kEnableNaCl); | 399 switches::kEnableNaCl); |
| 401 } else { | 400 } else { |
| 402 // If this is an external plugin that handles NaCl mime type, | 401 // If this is an external plugin that handles the NaCl mime type, we |
| 403 // we want to allow Native Client, because it's how | 402 // allow Native Client, so Native Client's integration tests work. |
| 404 // NaCl tests for the plugin work. | 403 is_nacl_unrestricted = true; |
| 405 is_nacl_enabled = true; | |
| 406 } | 404 } |
| 407 if (is_nacl_plugin || is_nacl_mime_type) { | 405 if (is_nacl_plugin || is_nacl_mime_type) { |
| 408 if (!IsNaClAllowed(plugin, | 406 GURL manifest_url = is_nacl_mime_type ? |
| 409 url, | 407 url : GetNaClContentHandlerURL(actual_mime_type, plugin); |
| 410 actual_mime_type, | 408 const Extension* extension = |
| 411 is_nacl_mime_type, | 409 extension_dispatcher_->extensions()->GetExtensionOrAppByURL( |
| 412 is_nacl_enabled, | 410 ExtensionURLInfo(manifest_url)); |
| 413 params)) { | 411 bool is_extension_from_webstore = |
| 412 extension && extension->from_webstore(); | |
| 413 // Allow built-in extensions and extensions under development. | |
| 414 bool is_extension_unrestricted = extension && | |
| 415 (extension->location() == Extension::COMPONENT || | |
| 416 extension->location() == Extension::LOAD); | |
| 417 GURL top_url = frame->top()->document().url(); | |
| 418 if (IsNaClAllowed(manifest_url, | |
| 419 top_url, | |
| 420 is_nacl_unrestricted, | |
| 421 is_extension_unrestricted, | |
| 422 is_extension_from_webstore, | |
| 423 params)) { | |
| 424 return render_view->CreatePlugin(frame, plugin, params); | |
| 425 } else { | |
| 414 frame->addMessageToConsole( | 426 frame->addMessageToConsole( |
| 415 WebConsoleMessage( | 427 WebConsoleMessage( |
| 416 WebConsoleMessage::LevelError, | 428 WebConsoleMessage::LevelError, |
| 417 "Only unpacked extensions and apps installed from the " | 429 "Only unpacked extensions and apps installed from the " |
| 418 "Chrome Web Store can load NaCl modules without enabling " | 430 "Chrome Web Store can load NaCl modules without enabling " |
| 419 "Native Client in about:flags.")); | 431 "Native Client in about:flags.")); |
| 420 placeholder = PluginPlaceholder::CreateBlockedPlugin( | 432 placeholder = PluginPlaceholder::CreateBlockedPlugin( |
| 421 render_view, frame, params, plugin, name, | 433 render_view, frame, params, plugin, name, |
| 422 IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED); | 434 IDR_BLOCKED_PLUGIN_HTML, IDS_PLUGIN_BLOCKED); |
| 423 break; | |
| 424 } | 435 } |
| 425 } | 436 } |
| 426 return render_view->CreatePlugin(frame, plugin, params); | 437 break; |
| 427 } | 438 } |
| 428 case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: { | 439 case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: { |
| 429 placeholder = PluginPlaceholder::CreateBlockedPlugin( | 440 placeholder = PluginPlaceholder::CreateBlockedPlugin( |
| 430 render_view, frame, params, plugin, name, | 441 render_view, frame, params, plugin, name, |
| 431 IDR_DISABLED_PLUGIN_HTML, IDS_PLUGIN_DISABLED); | 442 IDR_DISABLED_PLUGIN_HTML, IDS_PLUGIN_DISABLED); |
| 432 break; | 443 break; |
| 433 } | 444 } |
| 434 case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: { | 445 case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: { |
| 435 #if defined(ENABLE_PLUGIN_INSTALLATION) | 446 #if defined(ENABLE_PLUGIN_INSTALLATION) |
| 436 placeholder = PluginPlaceholder::CreateBlockedPlugin( | 447 placeholder = PluginPlaceholder::CreateBlockedPlugin( |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 477 RenderThread::Get()->RecordUserMetrics("Plugin_Blocked"); | 488 RenderThread::Get()->RecordUserMetrics("Plugin_Blocked"); |
| 478 observer->DidBlockContentType(content_type, group->identifier()); | 489 observer->DidBlockContentType(content_type, group->identifier()); |
| 479 break; | 490 break; |
| 480 } | 491 } |
| 481 } | 492 } |
| 482 } | 493 } |
| 483 placeholder->SetStatus(status); | 494 placeholder->SetStatus(status); |
| 484 return placeholder->plugin(); | 495 return placeholder->plugin(); |
| 485 } | 496 } |
| 486 | 497 |
| 498 // For NaCl content handling plugins, the NaCl manifest is stored in an | |
| 499 // additonal 'nacl' param associated with the MIME type. | |
| 500 GURL ChromeContentRendererClient::GetNaClContentHandlerURL( | |
|
Mihai Parparita -not on Chrome
2012/02/17 01:19:13
Nit: static functions usually have a "// static" c
bbudge
2012/02/17 19:25:04
Done.
| |
| 501 const std::string& actual_mime_type, | |
| 502 const webkit::WebPluginInfo& plugin) { | |
| 503 // Look for the manifest URL among the MIME type's additonal parameters. | |
| 504 const char* kNaClPluginManifestAttribute = "nacl"; | |
| 505 string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute); | |
| 506 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { | |
| 507 if (plugin.mime_types[i].mime_type == actual_mime_type) { | |
| 508 const WebPluginMimeType& content_type = plugin.mime_types[i]; | |
| 509 for (size_t i = 0; i < content_type.additional_param_names.size(); ++i) { | |
| 510 if (content_type.additional_param_names[i] == nacl_attr) | |
| 511 return GURL(content_type.additional_param_values[i]); | |
| 512 } | |
| 513 break; | |
| 514 } | |
| 515 } | |
| 516 return GURL(); | |
| 517 } | |
| 518 | |
| 487 bool ChromeContentRendererClient::IsNaClAllowed( | 519 bool ChromeContentRendererClient::IsNaClAllowed( |
| 488 const webkit::WebPluginInfo& plugin, | 520 const GURL& manifest_url, |
| 489 const GURL& url, | 521 const GURL& top_url, |
| 490 const std::string& actual_mime_type, | 522 bool is_nacl_unrestricted, |
| 491 bool is_nacl_mime_type, | 523 bool is_extension_unrestricted, |
| 492 bool enable_nacl, | 524 bool is_extension_from_webstore, |
| 493 WebKit::WebPluginParams& params) { | 525 WebPluginParams& params) { |
| 494 GURL manifest_url; | 526 // Temporarily allow these URLs to run NaCl apps. We should remove this |
| 495 if (is_nacl_mime_type) { | 527 // code when PNaCl ships. |
| 496 manifest_url = url; // Normal embedded NaCl plugin. | 528 bool is_whitelisted_url = |
| 497 } else { | 529 ((top_url.SchemeIs("http") || top_url.SchemeIs("https")) && |
| 498 // This is a content type handling NaCl plugin; look for the .nexe URL | 530 (top_url.host() == "plus.google.com" || |
| 499 // among the MIME type's additonal parameters. | 531 top_url.host() == "plus.sandbox.google.com") && |
| 500 const char* kNaClPluginManifestAttribute = "nacl"; | 532 top_url.path().find("/games") == 0); |
| 501 string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute); | 533 |
| 502 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { | 534 // Allow Chrome Web Store extensions, built-in extensions, extensions |
| 503 if (plugin.mime_types[i].mime_type == actual_mime_type) { | 535 // under development, invocations from whitelisted URLs, and all invocations |
| 504 const webkit::WebPluginMimeType& content_type = | 536 // if --enable-nacl is set. |
| 505 plugin.mime_types[i]; | 537 bool is_nacl_allowed = |
| 506 for (size_t i = 0; | 538 is_extension_from_webstore || |
| 507 i < content_type.additional_param_names.size(); ++i) { | 539 is_extension_unrestricted || |
| 508 if (content_type.additional_param_names[i] == nacl_attr) { | 540 is_whitelisted_url || |
| 509 manifest_url = GURL(content_type.additional_param_values[i]); | 541 is_nacl_unrestricted; |
| 510 break; | 542 if (is_nacl_allowed) { |
| 511 } | 543 bool app_can_use_dev_interfaces = |
| 512 } | 544 // NaCl PDF viewer extension |
| 513 break; | 545 (is_extension_from_webstore && |
| 546 manifest_url.SchemeIs("chrome-extension") && | |
| 547 manifest_url.host() == "acadkphlmlegjaadjagenfimbpphcgnh"); | |
| 548 // Make sure that PPAPI 'dev' interfaces aren't available for production | |
| 549 // apps unless they're whitelisted. | |
| 550 WebString dev_attribute = WebString::fromUTF8("@dev"); | |
| 551 if ((!is_whitelisted_url && !is_extension_from_webstore) || | |
| 552 app_can_use_dev_interfaces) { | |
| 553 // Add the special '@dev' attribute. | |
| 554 std::vector<string16> param_names; | |
| 555 std::vector<string16> param_values; | |
| 556 param_names.push_back(dev_attribute); | |
| 557 param_values.push_back(WebString()); | |
| 558 AppendParams( | |
| 559 param_names, | |
| 560 param_values, | |
| 561 ¶ms.attributeNames, | |
| 562 ¶ms.attributeValues); | |
| 563 } else { | |
| 564 // If the params somehow contain '@dev', remove it. | |
| 565 size_t attribute_count = params.attributeNames.size(); | |
| 566 for (size_t i = 0; i < attribute_count; ++i) { | |
| 567 if (params.attributeNames[i].equals(dev_attribute)) | |
| 568 params.attributeNames[i] = WebString(); | |
| 514 } | 569 } |
| 515 } | 570 } |
| 516 } | 571 } |
| 517 | 572 return is_nacl_allowed; |
| 518 // Determine if the manifest URL is part of an extension. | |
| 519 const Extension* extension = | |
| 520 extension_dispatcher_->extensions()->GetExtensionOrAppByURL( | |
| 521 ExtensionURLInfo(manifest_url)); | |
| 522 // Only component, unpacked, and Chrome Web Store extensions are allowed. | |
| 523 bool allowed_extension = extension && | |
| 524 (extension->from_webstore() || | |
| 525 extension->location() == Extension::COMPONENT || | |
| 526 extension->location() == Extension::LOAD); | |
| 527 | |
| 528 // Block any other use of NaCl plugin, unless --enable-nacl is set. | |
| 529 if (!allowed_extension && !enable_nacl) | |
| 530 return false; | |
| 531 | |
| 532 // Allow dev interfaces for non-extension apps. | |
| 533 bool allow_dev_interfaces = true; | |
| 534 if (allowed_extension) { | |
| 535 // Allow dev interfaces for component and unpacked extensions. | |
| 536 if (extension->location() != Extension::COMPONENT && | |
| 537 extension->location() != Extension::LOAD) { | |
| 538 // Whitelist all other allowed extensions. | |
| 539 allow_dev_interfaces = | |
| 540 // PDF Viewer plugin | |
| 541 (manifest_url.scheme() == "chrome-extension" && | |
| 542 manifest_url.host() == "acadkphlmlegjaadjagenfimbpphcgnh"); | |
| 543 } | |
| 544 } | |
| 545 | |
| 546 WebString dev_attribute = WebString::fromUTF8("@dev"); | |
| 547 if (allow_dev_interfaces) { | |
| 548 std::vector<string16> param_names; | |
| 549 std::vector<string16> param_values; | |
| 550 param_names.push_back(dev_attribute); | |
| 551 param_values.push_back(WebString()); | |
| 552 AppendParams( | |
| 553 param_names, | |
| 554 param_values, | |
| 555 ¶ms.attributeNames, | |
| 556 ¶ms.attributeValues); | |
| 557 } else { | |
| 558 // If the params somehow contain this special attribute, remove it. | |
| 559 size_t attribute_count = params.attributeNames.size(); | |
| 560 for (size_t i = 0; i < attribute_count; ++i) { | |
| 561 if (params.attributeNames[i].equals(dev_attribute)) | |
| 562 params.attributeNames[i] = WebString(); | |
| 563 } | |
| 564 } | |
| 565 | |
| 566 return true; | |
| 567 } | 573 } |
| 568 | 574 |
| 569 bool ChromeContentRendererClient::HasErrorPage(int http_status_code, | 575 bool ChromeContentRendererClient::HasErrorPage(int http_status_code, |
| 570 std::string* error_domain) { | 576 std::string* error_domain) { |
| 571 // Use an internal error page, if we have one for the status code. | 577 // Use an internal error page, if we have one for the status code. |
| 572 if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, | 578 if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, |
| 573 http_status_code)) { | 579 http_status_code)) { |
| 574 return false; | 580 return false; |
| 575 } | 581 } |
| 576 | 582 |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 860 webkit::ppapi::PpapiInterfaceFactoryManager* factory_manager) { | 866 webkit::ppapi::PpapiInterfaceFactoryManager* factory_manager) { |
| 861 factory_manager->RegisterFactory(ChromePPAPIInterfaceFactory); | 867 factory_manager->RegisterFactory(ChromePPAPIInterfaceFactory); |
| 862 } | 868 } |
| 863 | 869 |
| 864 bool ChromeContentRendererClient::AllowSocketAPI(const GURL& url) { | 870 bool ChromeContentRendererClient::AllowSocketAPI(const GURL& url) { |
| 865 return allowed_socket_origins_.find(url.host()) != | 871 return allowed_socket_origins_.find(url.host()) != |
| 866 allowed_socket_origins_.end(); | 872 allowed_socket_origins_.end(); |
| 867 } | 873 } |
| 868 | 874 |
| 869 } // namespace chrome | 875 } // namespace chrome |
| OLD | NEW |