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 3 // found in the LICENSE file. 4 5 #include "chrome/renderer/chrome_content_renderer_client.h" 6 7 #include "base/command_line.h" 8 #include "base/debug/crash_logging.h" 9 #include "base/logging.h" 10 #include "base/metrics/field_trial.h" 11 #include "base/metrics/histogram.h" 12 #include "base/metrics/user_metrics_action.h" 13 #include "base/path_service.h" 14 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_util.h" 16 #include "base/strings/utf_string_conversions.h" 17 #include "base/values.h" 18 #include "chrome/common/chrome_paths.h" 19 #include "chrome/common/chrome_switches.h" 20 #include "chrome/common/chrome_version_info.h" 21 #include "chrome/common/crash_keys.h" 22 #include "chrome/common/extensions/chrome_extensions_client.h" 23 #include "chrome/common/extensions/extension_constants.h" 24 #include "chrome/common/extensions/extension_process_policy.h" 25 #include "chrome/common/localized_error.h" 26 #include "chrome/common/pepper_permission_util.h" 27 #include "chrome/common/render_messages.h" 28 #include "chrome/common/url_constants.h" 29 #include "chrome/grit/generated_resources.h" 30 #include "chrome/grit/locale_settings.h" 31 #include "chrome/grit/renderer_resources.h" 32 #include "chrome/renderer/benchmarking_extension.h" 33 #include "chrome/renderer/chrome_render_frame_observer.h" 34 #include "chrome/renderer/chrome_render_process_observer.h" 35 #include "chrome/renderer/chrome_render_view_observer.h" 36 #include "chrome/renderer/content_settings_observer.h" 37 #include "chrome/renderer/external_extension.h" 38 #include "chrome/renderer/loadtimes_extension_bindings.h" 39 #include "chrome/renderer/media/cast_ipc_dispatcher.h" 40 #include "chrome/renderer/media/chrome_key_systems.h" 41 #include "chrome/renderer/net/net_error_helper.h" 42 #include "chrome/renderer/net/prescient_networking_dispatcher.h" 43 #include "chrome/renderer/net/renderer_net_predictor.h" 44 #include "chrome/renderer/net_benchmarking_extension.h" 45 #include "chrome/renderer/page_load_histograms.h" 46 #include "chrome/renderer/pepper/pepper_helper.h" 47 #include "chrome/renderer/playback_extension.h" 48 #include "chrome/renderer/plugins/chrome_plugin_placeholder.h" 49 #include "chrome/renderer/plugins/plugin_uma.h" 50 #include "chrome/renderer/prefetch_helper.h" 51 #include "chrome/renderer/prerender/prerender_dispatcher.h" 52 #include "chrome/renderer/prerender/prerender_helper.h" 53 #include "chrome/renderer/prerender/prerender_media_load_deferrer.h" 54 #include "chrome/renderer/prerender/prerenderer_client.h" 55 #include "chrome/renderer/principals_extension_bindings.h" 56 #include "chrome/renderer/printing/print_web_view_helper.h" 57 #include "chrome/renderer/safe_browsing/malware_dom_details.h" 58 #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h" 59 #include "chrome/renderer/searchbox/search_bouncer.h" 60 #include "chrome/renderer/searchbox/searchbox.h" 61 #include "chrome/renderer/searchbox/searchbox_extension.h" 62 #include "chrome/renderer/tts_dispatcher.h" 63 #include "chrome/renderer/worker_permission_client_proxy.h" 64 #include "components/autofill/content/renderer/autofill_agent.h" 65 #include "components/autofill/content/renderer/password_autofill_agent.h" 66 #include "components/autofill/content/renderer/password_generation_agent.h" 67 #include "components/content_settings/core/common/content_settings_pattern.h" 68 #include "components/dom_distiller/core/url_constants.h" 69 #include "components/nacl/renderer/ppb_nacl_private_impl.h" 70 #include "components/password_manager/content/renderer/credential_manager_client.h" 71 #include "components/pdf/renderer/ppb_pdf_impl.h" 72 #include "components/plugins/renderer/mobile_youtube_plugin.h" 73 #include "components/signin/core/common/profile_management_switches.h" 74 #include "components/visitedlink/renderer/visitedlink_slave.h" 75 #include "components/web_cache/renderer/web_cache_render_process_observer.h" 76 #include "content/public/common/content_constants.h" 77 #include "content/public/renderer/render_frame.h" 78 #include "content/public/renderer/render_thread.h" 79 #include "content/public/renderer/render_view.h" 80 #include "content/public/renderer/render_view_visitor.h" 81 #include "extensions/common/constants.h" 82 #include "extensions/common/extension.h" 83 #include "extensions/common/extension_set.h" 84 #include "extensions/common/extension_urls.h" 85 #include "extensions/common/switches.h" 86 #include "ipc/ipc_sync_channel.h" 87 #include "net/base/net_errors.h" 88 #include "ppapi/c/private/ppb_nacl_private.h" 89 #include "ppapi/c/private/ppb_pdf.h" 90 #include "ppapi/shared_impl/ppapi_switches.h" 91 #include "third_party/WebKit/public/platform/WebURL.h" 92 #include "third_party/WebKit/public/platform/WebURLError.h" 93 #include "third_party/WebKit/public/platform/WebURLRequest.h" 94 #include "third_party/WebKit/public/web/WebCache.h" 95 #include "third_party/WebKit/public/web/WebDataSource.h" 96 #include "third_party/WebKit/public/web/WebDocument.h" 97 #include "third_party/WebKit/public/web/WebElement.h" 98 #include "third_party/WebKit/public/web/WebLocalFrame.h" 99 #include "third_party/WebKit/public/web/WebPluginContainer.h" 100 #include "third_party/WebKit/public/web/WebPluginParams.h" 101 #include "third_party/WebKit/public/web/WebSecurityOrigin.h" 102 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" 103 #include "ui/base/l10n/l10n_util.h" 104 #include "ui/base/layout.h" 105 #include "ui/base/resource/resource_bundle.h" 106 #include "ui/base/webui/jstemplate_builder.h" 107 #include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR. 108 109 #if !defined(DISABLE_NACL) 110 #include "components/nacl/common/nacl_constants.h" 111 #include "components/nacl/renderer/nacl_helper.h" 112 #endif 113 114 #if defined(ENABLE_EXTENSIONS) 115 #include "chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h" 116 #include "chrome/renderer/extensions/chrome_extensions_renderer_client.h" 117 #include "chrome/renderer/extensions/extension_frame_helper.h" 118 #include "chrome/renderer/extensions/renderer_permissions_policy_delegate.h" 119 #include "chrome/renderer/extensions/resource_request_policy.h" 120 #include "extensions/renderer/dispatcher.h" 121 #include "extensions/renderer/extension_helper.h" 122 #include "extensions/renderer/extensions_render_frame_observer.h" 123 #include "extensions/renderer/guest_view/guest_view_container.h" 124 #include "extensions/renderer/script_context.h" 125 #endif 126 127 #if defined(ENABLE_FULL_PRINTING) 128 #include "chrome/renderer/pepper/chrome_pdf_print_client.h" 129 #endif 130 131 #if defined(ENABLE_SPELLCHECK) 132 #include "chrome/renderer/spellchecker/spellcheck.h" 133 #include "chrome/renderer/spellchecker/spellcheck_provider.h" 134 #endif 135 136 #if defined(ENABLE_WEBRTC) 137 #include "chrome/renderer/media/webrtc_logging_message_filter.h" 138 #endif 139 140 #if defined(OS_WIN) 141 #include "chrome_elf/blacklist/blacklist.h" 142 #endif 143 144 using autofill::AutofillAgent; 145 using autofill::PasswordAutofillAgent; 146 using autofill::PasswordGenerationAgent; 147 using base::ASCIIToUTF16; 148 using base::UserMetricsAction; 149 using content::RenderThread; 150 using content::WebPluginInfo; 151 using extensions::Extension; 152 using blink::WebCache; 153 using blink::WebConsoleMessage; 154 using blink::WebDataSource; 155 using blink::WebDocument; 156 using blink::WebFrame; 157 using blink::WebLocalFrame; 158 using blink::WebPlugin; 159 using blink::WebPluginParams; 160 using blink::WebSecurityOrigin; 161 using blink::WebSecurityPolicy; 162 using blink::WebString; 163 using blink::WebURL; 164 using blink::WebURLError; 165 using blink::WebURLRequest; 166 using blink::WebURLResponse; 167 using blink::WebVector; 168 169 namespace { 170 171 ChromeContentRendererClient* g_current_client; 172 173 #if defined(ENABLE_PLUGINS) 174 const char* const kPredefinedAllowedCompositorOrigins[] = { 175 "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/383937 176 "4EB74897CB187C7633357C2FE832E0AD6A44883A" // see crbug.com/383937 177 }; 178 179 const char* const kPredefinedAllowedVideoDecodeOrigins[] = { 180 "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/383937 181 "4EB74897CB187C7633357C2FE832E0AD6A44883A" // see crbug.com/383937 182 }; 183 #endif 184 185 static void AppendParams(const std::vector<base::string16>& additional_names, 186 const std::vector<base::string16>& additional_values, 187 WebVector<WebString>* existing_names, 188 WebVector<WebString>* existing_values) { 189 DCHECK(additional_names.size() == additional_values.size()); 190 DCHECK(existing_names->size() == existing_values->size()); 191 192 size_t existing_size = existing_names->size(); 193 size_t total_size = existing_size + additional_names.size(); 194 195 WebVector<WebString> names(total_size); 196 WebVector<WebString> values(total_size); 197 198 for (size_t i = 0; i < existing_size; ++i) { 199 names[i] = (*existing_names)[i]; 200 values[i] = (*existing_values)[i]; 201 } 202 203 for (size_t i = 0; i < additional_names.size(); ++i) { 204 names[existing_size + i] = additional_names[i]; 205 values[existing_size + i] = additional_values[i]; 206 } 207 208 existing_names->swap(names); 209 existing_values->swap(values); 210 } 211 212 #if defined(ENABLE_SPELLCHECK) 213 class SpellCheckReplacer : public content::RenderViewVisitor { 214 public: 215 explicit SpellCheckReplacer(SpellCheck* spellcheck) 216 : spellcheck_(spellcheck) {} 217 virtual bool Visit(content::RenderView* render_view) OVERRIDE; 218 219 private: 220 SpellCheck* spellcheck_; // New shared spellcheck for all views. Weak Ptr. 221 DISALLOW_COPY_AND_ASSIGN(SpellCheckReplacer); 222 }; 223 224 bool SpellCheckReplacer::Visit(content::RenderView* render_view) { 225 SpellCheckProvider* provider = SpellCheckProvider::Get(render_view); 226 DCHECK(provider); 227 provider->set_spellcheck(spellcheck_); 228 return true; 229 } 230 #endif 231 232 // For certain sandboxed Pepper plugins, use the JavaScript Content Settings. 233 bool ShouldUseJavaScriptSettingForPlugin(const WebPluginInfo& plugin) { 234 if (plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS && 235 plugin.type != WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS) { 236 return false; 237 } 238 239 #if !defined(DISABLE_NACL) 240 // Treat Native Client invocations like JavaScript. 241 if (plugin.name == ASCIIToUTF16(nacl::kNaClPluginName)) 242 return true; 243 #endif 244 245 #if defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) 246 // Treat CDM invocations like JavaScript. 247 if (plugin.name == ASCIIToUTF16(kWidevineCdmDisplayName)) { 248 DCHECK(plugin.type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS); 249 return true; 250 } 251 #endif // defined(WIDEVINE_CDM_AVAILABLE) && defined(ENABLE_PEPPER_CDMS) 252 253 return false; 254 } 255 256 #if defined(ENABLE_EXTENSIONS) 257 void IsGuestViewApiAvailableToScriptContext( 258 bool* api_is_available, 259 extensions::ScriptContext* context) { 260 if (context->GetAvailability("guestViewInternal").is_available()) { 261 *api_is_available = true; 262 } 263 } 264 #endif 265 266 } // namespace 267 268 ChromeContentRendererClient::ChromeContentRendererClient() { 269 g_current_client = this; 270 271 extensions::ExtensionsClient::Set( 272 extensions::ChromeExtensionsClient::GetInstance()); 273 #if defined(ENABLE_EXTENSIONS) 274 extensions::ExtensionsRendererClient::Set( 275 ChromeExtensionsRendererClient::GetInstance()); 276 #endif 277 #if defined(ENABLE_PLUGINS) 278 for (size_t i = 0; i < arraysize(kPredefinedAllowedCompositorOrigins); ++i) 279 allowed_compositor_origins_.insert(kPredefinedAllowedCompositorOrigins[i]); 280 for (size_t i = 0; i < arraysize(kPredefinedAllowedVideoDecodeOrigins); ++i) 281 allowed_video_decode_origins_.insert( 282 kPredefinedAllowedVideoDecodeOrigins[i]); 283 #endif 284 } 285 286 ChromeContentRendererClient::~ChromeContentRendererClient() { 287 g_current_client = NULL; 288 } 289 290 void ChromeContentRendererClient::RenderThreadStarted() { 291 RenderThread* thread = RenderThread::Get(); 292 293 chrome_observer_.reset(new ChromeRenderProcessObserver(this)); 294 web_cache_observer_.reset(new web_cache::WebCacheRenderProcessObserver()); 295 296 #if defined(ENABLE_EXTENSIONS) 297 extension_dispatcher_delegate_.reset( 298 new ChromeExtensionsDispatcherDelegate()); 299 // ChromeRenderViewTest::SetUp() creates its own ExtensionDispatcher and 300 // injects it using SetExtensionDispatcher(). Don't overwrite it. 301 if (!extension_dispatcher_) { 302 extension_dispatcher_.reset( 303 new extensions::Dispatcher(extension_dispatcher_delegate_.get())); 304 } 305 permissions_policy_delegate_.reset( 306 new extensions::RendererPermissionsPolicyDelegate( 307 extension_dispatcher_.get())); 308 #endif 309 310 prescient_networking_dispatcher_.reset(new PrescientNetworkingDispatcher()); 311 net_predictor_.reset(new RendererNetPredictor()); 312 #if defined(ENABLE_SPELLCHECK) 313 // ChromeRenderViewTest::SetUp() creates a Spellcheck and injects it using 314 // SetSpellcheck(). Don't overwrite it. 315 if (!spellcheck_) { 316 spellcheck_.reset(new SpellCheck()); 317 thread->AddObserver(spellcheck_.get()); 318 } 319 #endif 320 visited_link_slave_.reset(new visitedlink::VisitedLinkSlave()); 321 #if defined(FULL_SAFE_BROWSING) 322 phishing_classifier_.reset(safe_browsing::PhishingClassifierFilter::Create()); 323 #endif 324 prerender_dispatcher_.reset(new prerender::PrerenderDispatcher()); 325 #if defined(ENABLE_WEBRTC) 326 webrtc_logging_message_filter_ = new WebRtcLoggingMessageFilter( 327 content::RenderThread::Get()->GetIOMessageLoopProxy()); 328 #endif 329 search_bouncer_.reset(new SearchBouncer()); 330 331 thread->AddObserver(chrome_observer_.get()); 332 thread->AddObserver(web_cache_observer_.get()); 333 #if defined(ENABLE_EXTENSIONS) 334 thread->AddObserver(extension_dispatcher_.get()); 335 #endif 336 #if defined(FULL_SAFE_BROWSING) 337 thread->AddObserver(phishing_classifier_.get()); 338 #endif 339 thread->AddObserver(visited_link_slave_.get()); 340 thread->AddObserver(prerender_dispatcher_.get()); 341 thread->AddObserver(search_bouncer_.get()); 342 343 #if defined(ENABLE_WEBRTC) 344 thread->AddFilter(webrtc_logging_message_filter_.get()); 345 #endif 346 thread->AddFilter(new CastIPCDispatcher( 347 content::RenderThread::Get()->GetIOMessageLoopProxy())); 348 349 thread->RegisterExtension(extensions_v8::ExternalExtension::Get()); 350 thread->RegisterExtension(extensions_v8::LoadTimesExtension::Get()); 351 352 CommandLine* command_line = CommandLine::ForCurrentProcess(); 353 if (command_line->HasSwitch(switches::kEnableBenchmarking)) 354 thread->RegisterExtension(extensions_v8::BenchmarkingExtension::Get()); 355 if (command_line->HasSwitch(switches::kEnableNetBenchmarking)) 356 thread->RegisterExtension(extensions_v8::NetBenchmarkingExtension::Get()); 357 if (command_line->HasSwitch(switches::kInstantProcess)) 358 thread->RegisterExtension(extensions_v8::SearchBoxExtension::Get()); 359 360 if (command_line->HasSwitch(switches::kPlaybackMode) || 361 command_line->HasSwitch(switches::kRecordMode)) { 362 thread->RegisterExtension(extensions_v8::PlaybackExtension::Get()); 363 } 364 365 // TODO(guohui): needs to forward the new-profile-management switch to 366 // renderer processes. 367 if (switches::IsEnableAccountConsistency()) 368 thread->RegisterExtension(extensions_v8::PrincipalsExtension::Get()); 369 370 // chrome:, chrome-search:, chrome-devtools:, and chrome-distiller: pages 371 // should not be accessible by normal content, and should also be unable to 372 // script anything but themselves (to help limit the damage that a corrupt 373 // page could cause). 374 WebString chrome_ui_scheme(ASCIIToUTF16(content::kChromeUIScheme)); 375 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(chrome_ui_scheme); 376 377 WebString chrome_search_scheme(ASCIIToUTF16(chrome::kChromeSearchScheme)); 378 // The Instant process can only display the content but not read it. Other 379 // processes can't display it or read it. 380 if (!command_line->HasSwitch(switches::kInstantProcess)) 381 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(chrome_search_scheme); 382 383 WebString dev_tools_scheme(ASCIIToUTF16(content::kChromeDevToolsScheme)); 384 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(dev_tools_scheme); 385 386 WebString dom_distiller_scheme( 387 ASCIIToUTF16(dom_distiller::kDomDistillerScheme)); 388 // TODO(nyquist): Add test to ensure this happens when the flag is set. 389 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(dom_distiller_scheme); 390 391 #if defined(OS_CHROMEOS) 392 WebString external_file_scheme(ASCIIToUTF16(chrome::kExternalFileScheme)); 393 WebSecurityPolicy::registerURLSchemeAsLocal(external_file_scheme); 394 #endif 395 396 // chrome: and chrome-search: pages should not be accessible by bookmarklets 397 // or javascript: URLs typed in the omnibox. 398 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs( 399 chrome_ui_scheme); 400 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs( 401 chrome_search_scheme); 402 403 // chrome:, chrome-search:, and chrome-extension: resources shouldn't trigger 404 // insecure content warnings. 405 WebSecurityPolicy::registerURLSchemeAsSecure(chrome_ui_scheme); 406 WebSecurityPolicy::registerURLSchemeAsSecure(chrome_search_scheme); 407 408 WebString extension_scheme(ASCIIToUTF16(extensions::kExtensionScheme)); 409 WebSecurityPolicy::registerURLSchemeAsSecure(extension_scheme); 410 411 // chrome-extension: resources should be allowed to receive CORS requests. 412 WebSecurityPolicy::registerURLSchemeAsCORSEnabled(extension_scheme); 413 414 WebString extension_resource_scheme( 415 ASCIIToUTF16(extensions::kExtensionResourceScheme)); 416 WebSecurityPolicy::registerURLSchemeAsSecure(extension_resource_scheme); 417 418 // chrome-extension-resource: resources should be allowed to receive CORS 419 // requests. 420 WebSecurityPolicy::registerURLSchemeAsCORSEnabled(extension_resource_scheme); 421 422 // chrome-extension: resources should bypass Content Security Policy checks 423 // when included in protected resources. 424 WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( 425 extension_scheme); 426 WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( 427 extension_resource_scheme); 428 429 #if defined(OS_WIN) 430 // Report if the renderer process has been patched by chrome_elf. 431 // TODO(csharp): Remove once the renderer is no longer getting 432 // patched this way. 433 if (blacklist::IsBlacklistInitialized()) 434 UMA_HISTOGRAM_BOOLEAN("Blacklist.PatchedInRenderer", true); 435 #endif 436 #if defined(ENABLE_FULL_PRINTING) 437 pdf_print_client_.reset(new ChromePDFPrintClient()); 438 pdf::PPB_PDF_Impl::SetPrintClient(pdf_print_client_.get()); 439 #endif 440 } 441 442 void ChromeContentRendererClient::RenderFrameCreated( 443 content::RenderFrame* render_frame) { 444 new ChromeRenderFrameObserver(render_frame); 445 446 extensions::Dispatcher* ext_dispatcher = NULL; 447 #if defined(ENABLE_EXTENSIONS) 448 ext_dispatcher = extension_dispatcher_.get(); 449 #endif 450 ContentSettingsObserver* content_settings = 451 new ContentSettingsObserver(render_frame, ext_dispatcher); 452 if (chrome_observer_.get()) { 453 content_settings->SetContentSettingRules( 454 chrome_observer_->content_setting_rules()); 455 } 456 457 #if defined(ENABLE_EXTENSIONS) 458 new extensions::ExtensionsRenderFrameObserver(render_frame); 459 new extensions::ExtensionFrameHelper(render_frame, ext_dispatcher); 460 #endif 461 462 #if defined(ENABLE_PLUGINS) 463 new PepperHelper(render_frame); 464 #endif 465 466 #if !defined(DISABLE_NACL) 467 new nacl::NaClHelper(render_frame); 468 #endif 469 470 // TODO(jam): when the frame tree moves into content and parent() works at 471 // RenderFrame construction, simplify this by just checking parent(). 472 if (render_frame->GetRenderView()->GetMainRenderFrame() != render_frame) { 473 // Avoid any race conditions from having the browser tell subframes that 474 // they're prerendering. 475 if (prerender::PrerenderHelper::IsPrerendering( 476 render_frame->GetRenderView()->GetMainRenderFrame())) { 477 new prerender::PrerenderHelper(render_frame); 478 } 479 } 480 481 if (render_frame->GetRenderView()->GetMainRenderFrame() == render_frame) { 482 // Only attach NetErrorHelper to the main frame, since only the main frame 483 // should get error pages. 484 // PrefetchHelper is also needed only for main frames. 485 new NetErrorHelper(render_frame); 486 new prefetch::PrefetchHelper(render_frame); 487 } 488 } 489 490 void ChromeContentRendererClient::RenderViewCreated( 491 content::RenderView* render_view) { 492 #if defined(ENABLE_EXTENSIONS) 493 new extensions::ExtensionHelper(render_view, extension_dispatcher_.get()); 494 extension_dispatcher_->OnRenderViewCreated(render_view); 495 #endif 496 new PageLoadHistograms(render_view); 497 #if defined(ENABLE_PRINTING) 498 new printing::PrintWebViewHelper(render_view); 499 #endif 500 #if defined(ENABLE_SPELLCHECK) 501 new SpellCheckProvider(render_view, spellcheck_.get()); 502 #endif 503 new prerender::PrerendererClient(render_view); 504 #if defined(FULL_SAFE_BROWSING) 505 safe_browsing::MalwareDOMDetails::Create(render_view); 506 #endif 507 508 PasswordGenerationAgent* password_generation_agent = 509 new PasswordGenerationAgent(render_view); 510 PasswordAutofillAgent* password_autofill_agent = 511 new PasswordAutofillAgent(render_view); 512 new AutofillAgent(render_view, 513 password_autofill_agent, 514 password_generation_agent); 515 516 CommandLine* command_line = CommandLine::ForCurrentProcess(); 517 if (command_line->HasSwitch(switches::kInstantProcess)) 518 new SearchBox(render_view); 519 520 new ChromeRenderViewObserver(render_view, web_cache_observer_.get()); 521 522 new password_manager::CredentialManagerClient(render_view); 523 } 524 525 void ChromeContentRendererClient::SetNumberOfViews(int number_of_views) { 526 base::debug::SetCrashKeyValue(crash_keys::kNumberOfViews, 527 base::IntToString(number_of_views)); 528 } 529 530 SkBitmap* ChromeContentRendererClient::GetSadPluginBitmap() { 531 return const_cast<SkBitmap*>(ResourceBundle::GetSharedInstance(). 532 GetImageNamed(IDR_SAD_PLUGIN).ToSkBitmap()); 533 } 534 535 SkBitmap* ChromeContentRendererClient::GetSadWebViewBitmap() { 536 return const_cast<SkBitmap*>(ResourceBundle::GetSharedInstance(). 537 GetImageNamed(IDR_SAD_WEBVIEW).ToSkBitmap()); 538 } 539 540 #if defined(ENABLE_EXTENSIONS) 541 const Extension* ChromeContentRendererClient::GetExtensionByOrigin( 542 const WebSecurityOrigin& origin) const { 543 if (!EqualsASCII(origin.protocol(), extensions::kExtensionScheme)) 544 return NULL; 545 546 const std::string extension_id = origin.host().utf8().data(); 547 return extension_dispatcher_->extensions()->GetByID(extension_id); 548 } 549 #endif 550 551 bool ChromeContentRendererClient::OverrideCreatePlugin( 552 content::RenderFrame* render_frame, 553 WebLocalFrame* frame, 554 const WebPluginParams& params, 555 WebPlugin** plugin) { 556 std::string orig_mime_type = params.mimeType.utf8(); 557 #if defined(ENABLE_EXTENSIONS) 558 if (orig_mime_type == content::kBrowserPluginMimeType) { 559 bool guest_view_api_available = false; 560 extension_dispatcher_->script_context_set().ForEach( 561 render_frame->GetRenderView(), 562 base::Bind(&IsGuestViewApiAvailableToScriptContext, 563 &guest_view_api_available)); 564 if (guest_view_api_available) 565 return false; 566 } 567 #endif 568 569 ChromeViewHostMsg_GetPluginInfo_Output output; 570 #if defined(ENABLE_PLUGINS) 571 render_frame->Send(new ChromeViewHostMsg_GetPluginInfo( 572 render_frame->GetRoutingID(), GURL(params.url), 573 frame->top()->document().url(), orig_mime_type, &output)); 574 575 if (output.plugin.type == content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) 576 return false; 577 #else 578 output.status.value = ChromeViewHostMsg_GetPluginInfo_Status::kNotFound; 579 #endif 580 *plugin = CreatePlugin(render_frame, frame, params, output); 581 return true; 582 } 583 584 WebPlugin* ChromeContentRendererClient::CreatePluginReplacement( 585 content::RenderFrame* render_frame, 586 const base::FilePath& plugin_path) { 587 ChromePluginPlaceholder* placeholder = 588 ChromePluginPlaceholder::CreateErrorPlugin(render_frame, plugin_path); 589 return placeholder->plugin(); 590 } 591 592 void ChromeContentRendererClient::DeferMediaLoad( 593 content::RenderFrame* render_frame, 594 const base::Closure& closure) { 595 #if defined(OS_ANDROID) 596 // Chromium for Android doesn't support prerender yet. 597 closure.Run(); 598 return; 599 #else 600 if (!prerender::PrerenderHelper::IsPrerendering(render_frame)) { 601 closure.Run(); 602 return; 603 } 604 605 // Lifetime is tied to |render_frame| via content::RenderFrameObserver. 606 new prerender::PrerenderMediaLoadDeferrer(render_frame, closure); 607 #endif 608 } 609 610 WebPlugin* ChromeContentRendererClient::CreatePlugin( 611 content::RenderFrame* render_frame, 612 WebLocalFrame* frame, 613 const WebPluginParams& original_params, 614 const ChromeViewHostMsg_GetPluginInfo_Output& output) { 615 const ChromeViewHostMsg_GetPluginInfo_Status& status = output.status; 616 const WebPluginInfo& plugin = output.plugin; 617 const std::string& actual_mime_type = output.actual_mime_type; 618 const base::string16& group_name = output.group_name; 619 const std::string& identifier = output.group_identifier; 620 ChromeViewHostMsg_GetPluginInfo_Status::Value status_value = status.value; 621 GURL url(original_params.url); 622 std::string orig_mime_type = original_params.mimeType.utf8(); 623 ChromePluginPlaceholder* placeholder = NULL; 624 625 // If the browser plugin is to be enabled, this should be handled by the 626 // renderer, so the code won't reach here due to the early exit in 627 // OverrideCreatePlugin. 628 if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kNotFound || 629 orig_mime_type == content::kBrowserPluginMimeType) { 630 #if defined(OS_ANDROID) 631 if (plugins::MobileYouTubePlugin::IsYouTubeURL(url, orig_mime_type)) { 632 base::StringPiece template_html( 633 ResourceBundle::GetSharedInstance().GetRawDataResource( 634 IDR_MOBILE_YOUTUBE_PLUGIN_HTML)); 635 return (new plugins::MobileYouTubePlugin( 636 render_frame, 637 frame, 638 original_params, 639 template_html, 640 GURL(ChromePluginPlaceholder::kPluginPlaceholderDataURL))) 641 ->plugin(); 642 } 643 #endif 644 PluginUMAReporter::GetInstance()->ReportPluginMissing(orig_mime_type, url); 645 placeholder = ChromePluginPlaceholder::CreateMissingPlugin( 646 render_frame, frame, original_params); 647 } else { 648 // TODO(bauerb): This should be in content/. 649 WebPluginParams params(original_params); 650 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { 651 if (plugin.mime_types[i].mime_type == actual_mime_type) { 652 AppendParams(plugin.mime_types[i].additional_param_names, 653 plugin.mime_types[i].additional_param_values, 654 ¶ms.attributeNames, 655 ¶ms.attributeValues); 656 break; 657 } 658 } 659 if (params.mimeType.isNull() && (actual_mime_type.size() > 0)) { 660 // Webkit might say that mime type is null while we already know the 661 // actual mime type via ChromeViewHostMsg_GetPluginInfo. In that case 662 // we should use what we know since WebpluginDelegateProxy does some 663 // specific initializations based on this information. 664 params.mimeType = WebString::fromUTF8(actual_mime_type.c_str()); 665 } 666 667 ContentSettingsObserver* observer = 668 ContentSettingsObserver::Get(render_frame); 669 670 const ContentSettingsType content_type = 671 ShouldUseJavaScriptSettingForPlugin(plugin) ? 672 CONTENT_SETTINGS_TYPE_JAVASCRIPT : 673 CONTENT_SETTINGS_TYPE_PLUGINS; 674 675 if ((status_value == 676 ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized || 677 status_value == ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay || 678 status_value == ChromeViewHostMsg_GetPluginInfo_Status::kBlocked) && 679 observer->IsPluginTemporarilyAllowed(identifier)) { 680 status_value = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; 681 } 682 683 // Allow full-page plug-ins for click-to-play. 684 if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay && 685 !frame->parent() && 686 !frame->opener() && 687 frame->document().isPluginDocument()) { 688 status_value = ChromeViewHostMsg_GetPluginInfo_Status::kAllowed; 689 } 690 691 #if defined(OS_WIN) 692 // In Windows we need to check if we can load NPAPI plugins. 693 // For example, if the render view is in the Ash desktop, we should not. 694 if (status_value == ChromeViewHostMsg_GetPluginInfo_Status::kAllowed && 695 plugin.type == content::WebPluginInfo::PLUGIN_TYPE_NPAPI) { 696 if (observer->AreNPAPIPluginsBlocked()) 697 status_value = 698 ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported; 699 } 700 #endif 701 702 switch (status_value) { 703 case ChromeViewHostMsg_GetPluginInfo_Status::kNotFound: { 704 NOTREACHED(); 705 break; 706 } 707 case ChromeViewHostMsg_GetPluginInfo_Status::kAllowed: { 708 #if !defined(DISABLE_NACL) 709 const bool is_nacl_plugin = 710 plugin.name == ASCIIToUTF16(nacl::kNaClPluginName); 711 const bool is_nacl_mime_type = 712 actual_mime_type == nacl::kNaClPluginMimeType; 713 const bool is_pnacl_mime_type = 714 actual_mime_type == nacl::kPnaclPluginMimeType; 715 if (is_nacl_plugin || is_nacl_mime_type || is_pnacl_mime_type) { 716 bool is_nacl_unrestricted = false; 717 if (is_nacl_mime_type) { 718 is_nacl_unrestricted = 719 CommandLine::ForCurrentProcess()->HasSwitch( 720 switches::kEnableNaCl); 721 } else if (is_pnacl_mime_type) { 722 is_nacl_unrestricted = true; 723 } 724 GURL manifest_url; 725 GURL app_url; 726 if (is_nacl_mime_type || is_pnacl_mime_type) { 727 // Normal NaCl/PNaCl embed. The app URL is the page URL. 728 manifest_url = url; 729 app_url = frame->top()->document().url(); 730 } else { 731 // NaCl is being invoked as a content handler. Look up the NaCl 732 // module using the MIME type. The app URL is the manifest URL. 733 manifest_url = GetNaClContentHandlerURL(actual_mime_type, plugin); 734 app_url = manifest_url; 735 } 736 const Extension* extension = 737 g_current_client->extension_dispatcher_->extensions()-> 738 GetExtensionOrAppByURL(manifest_url); 739 if (!IsNaClAllowed(manifest_url, 740 app_url, 741 is_nacl_unrestricted, 742 extension, 743 ¶ms)) { 744 WebString error_message; 745 if (is_nacl_mime_type) { 746 error_message = 747 "Only unpacked extensions and apps installed from the Chrome " 748 "Web Store can load NaCl modules without enabling Native " 749 "Client in about:flags."; 750 } else if (is_pnacl_mime_type) { 751 error_message = 752 "Portable Native Client must not be disabled in about:flags."; 753 } 754 frame->addMessageToConsole( 755 WebConsoleMessage(WebConsoleMessage::LevelError, 756 error_message)); 757 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 758 render_frame, 759 frame, 760 params, 761 plugin, 762 identifier, 763 group_name, 764 IDR_BLOCKED_PLUGIN_HTML, 765 #if defined(OS_CHROMEOS) 766 l10n_util::GetStringUTF16(IDS_NACL_PLUGIN_BLOCKED)); 767 #else 768 l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); 769 #endif 770 break; 771 } 772 } 773 #endif // !defined(DISABLE_NACL) 774 775 // Delay loading plugins if prerendering. 776 // TODO(mmenke): In the case of prerendering, feed into 777 // ChromeContentRendererClient::CreatePlugin instead, to 778 // reduce the chance of future regressions. 779 if (prerender::PrerenderHelper::IsPrerendering(render_frame)) { 780 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 781 render_frame, 782 frame, 783 params, 784 plugin, 785 identifier, 786 group_name, 787 IDR_CLICK_TO_PLAY_PLUGIN_HTML, 788 l10n_util::GetStringFUTF16(IDS_PLUGIN_LOAD, group_name)); 789 placeholder->set_blocked_for_prerendering(true); 790 placeholder->set_allow_loading(true); 791 break; 792 } 793 794 return render_frame->CreatePlugin(frame, plugin, params); 795 } 796 case ChromeViewHostMsg_GetPluginInfo_Status::kNPAPINotSupported: { 797 RenderThread::Get()->RecordAction( 798 UserMetricsAction("Plugin_NPAPINotSupported")); 799 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 800 render_frame, 801 frame, 802 params, 803 plugin, 804 identifier, 805 group_name, 806 IDR_BLOCKED_PLUGIN_HTML, 807 l10n_util::GetStringUTF16(IDS_PLUGIN_NOT_SUPPORTED_METRO)); 808 render_frame->Send(new ChromeViewHostMsg_NPAPINotSupported( 809 render_frame->GetRoutingID(), identifier)); 810 break; 811 } 812 case ChromeViewHostMsg_GetPluginInfo_Status::kDisabled: { 813 PluginUMAReporter::GetInstance()->ReportPluginDisabled(orig_mime_type, 814 url); 815 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 816 render_frame, 817 frame, 818 params, 819 plugin, 820 identifier, 821 group_name, 822 IDR_DISABLED_PLUGIN_HTML, 823 l10n_util::GetStringFUTF16(IDS_PLUGIN_DISABLED, group_name)); 824 break; 825 } 826 case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedBlocked: { 827 #if defined(ENABLE_PLUGIN_INSTALLATION) 828 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 829 render_frame, 830 frame, 831 params, 832 plugin, 833 identifier, 834 group_name, 835 IDR_BLOCKED_PLUGIN_HTML, 836 l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name)); 837 placeholder->set_allow_loading(true); 838 render_frame->Send(new ChromeViewHostMsg_BlockedOutdatedPlugin( 839 render_frame->GetRoutingID(), placeholder->CreateRoutingId(), 840 identifier)); 841 #else 842 NOTREACHED(); 843 #endif 844 break; 845 } 846 case ChromeViewHostMsg_GetPluginInfo_Status::kOutdatedDisallowed: { 847 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 848 render_frame, 849 frame, 850 params, 851 plugin, 852 identifier, 853 group_name, 854 IDR_BLOCKED_PLUGIN_HTML, 855 l10n_util::GetStringFUTF16(IDS_PLUGIN_OUTDATED, group_name)); 856 break; 857 } 858 case ChromeViewHostMsg_GetPluginInfo_Status::kUnauthorized: { 859 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 860 render_frame, 861 frame, 862 params, 863 plugin, 864 identifier, 865 group_name, 866 IDR_BLOCKED_PLUGIN_HTML, 867 l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, group_name)); 868 placeholder->set_allow_loading(true); 869 // Check to see if old infobar should be displayed. 870 std::string trial_group = 871 base::FieldTrialList::FindFullName("UnauthorizedPluginInfoBar"); 872 if (plugin.type != content::WebPluginInfo::PLUGIN_TYPE_NPAPI || 873 trial_group == "Enabled") { 874 render_frame->Send(new ChromeViewHostMsg_BlockedUnauthorizedPlugin( 875 render_frame->GetRoutingID(), 876 group_name, 877 identifier)); 878 } else { 879 // Send IPC for showing blocked plugins page action. 880 observer->DidBlockContentType(content_type); 881 } 882 break; 883 } 884 case ChromeViewHostMsg_GetPluginInfo_Status::kClickToPlay: { 885 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 886 render_frame, 887 frame, 888 params, 889 plugin, 890 identifier, 891 group_name, 892 IDR_CLICK_TO_PLAY_PLUGIN_HTML, 893 l10n_util::GetStringFUTF16(IDS_PLUGIN_LOAD, group_name)); 894 placeholder->set_allow_loading(true); 895 RenderThread::Get()->RecordAction( 896 UserMetricsAction("Plugin_ClickToPlay")); 897 observer->DidBlockContentType(content_type); 898 break; 899 } 900 case ChromeViewHostMsg_GetPluginInfo_Status::kBlocked: { 901 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 902 render_frame, 903 frame, 904 params, 905 plugin, 906 identifier, 907 group_name, 908 IDR_BLOCKED_PLUGIN_HTML, 909 l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); 910 placeholder->set_allow_loading(true); 911 RenderThread::Get()->RecordAction(UserMetricsAction("Plugin_Blocked")); 912 observer->DidBlockContentType(content_type); 913 break; 914 } 915 case ChromeViewHostMsg_GetPluginInfo_Status::kBlockedByPolicy: { 916 placeholder = ChromePluginPlaceholder::CreateBlockedPlugin( 917 render_frame, 918 frame, 919 params, 920 plugin, 921 identifier, 922 group_name, 923 IDR_BLOCKED_PLUGIN_HTML, 924 l10n_util::GetStringFUTF16(IDS_PLUGIN_BLOCKED, group_name)); 925 placeholder->set_allow_loading(false); 926 RenderThread::Get()->RecordAction( 927 UserMetricsAction("Plugin_BlockedByPolicy")); 928 observer->DidBlockContentType(content_type); 929 break; 930 } 931 } 932 } 933 placeholder->SetStatus(status); 934 return placeholder->plugin(); 935 } 936 937 // For NaCl content handling plugins, the NaCl manifest is stored in an 938 // additonal 'nacl' param associated with the MIME type. 939 // static 940 GURL ChromeContentRendererClient::GetNaClContentHandlerURL( 941 const std::string& actual_mime_type, 942 const content::WebPluginInfo& plugin) { 943 // Look for the manifest URL among the MIME type's additonal parameters. 944 const char* kNaClPluginManifestAttribute = "nacl"; 945 base::string16 nacl_attr = ASCIIToUTF16(kNaClPluginManifestAttribute); 946 for (size_t i = 0; i < plugin.mime_types.size(); ++i) { 947 if (plugin.mime_types[i].mime_type == actual_mime_type) { 948 const content::WebPluginMimeType& content_type = plugin.mime_types[i]; 949 for (size_t i = 0; i < content_type.additional_param_names.size(); ++i) { 950 if (content_type.additional_param_names[i] == nacl_attr) 951 return GURL(content_type.additional_param_values[i]); 952 } 953 break; 954 } 955 } 956 return GURL(); 957 } 958 959 // static 960 bool ChromeContentRendererClient::IsNaClAllowed( 961 const GURL& manifest_url, 962 const GURL& app_url, 963 bool is_nacl_unrestricted, 964 const Extension* extension, 965 WebPluginParams* params) { 966 // Temporarily allow these whitelisted apps and WebUIs to use NaCl. 967 std::string app_url_host = app_url.host(); 968 std::string manifest_url_path = manifest_url.path(); 969 970 bool is_whitelisted_web_ui = 971 app_url.spec() == chrome::kChromeUIAppListStartPageURL; 972 973 bool is_photo_app = 974 // Whitelisted apps must be served over https. 975 app_url.SchemeIs("https") && 976 manifest_url.SchemeIs("https") && 977 (EndsWith(app_url_host, "plus.google.com", false) || 978 EndsWith(app_url_host, "plus.sandbox.google.com", false)) && 979 manifest_url.DomainIs("ssl.gstatic.com") && 980 (manifest_url_path.find("s2/oz/nacl/") == 1 || 981 manifest_url_path.find("photos/nacl/") == 1); 982 983 std::string manifest_fs_host; 984 if (manifest_url.SchemeIsFileSystem() && manifest_url.inner_url()) { 985 manifest_fs_host = manifest_url.inner_url()->host(); 986 } 987 bool is_hangouts_app = 988 // Whitelisted apps must be served over secure scheme. 989 app_url.SchemeIs("https") && 990 manifest_url.SchemeIsSecure() && 991 manifest_url.SchemeIsFileSystem() && 992 (EndsWith(app_url_host, "talkgadget.google.com", false) || 993 EndsWith(app_url_host, "plus.google.com", false) || 994 EndsWith(app_url_host, "plus.sandbox.google.com", false)) && 995 // The manifest must be loaded from the host's FileSystem. 996 (manifest_fs_host == app_url_host); 997 998 bool is_whitelisted_app = is_photo_app || is_hangouts_app; 999 1000 bool is_extension_from_webstore = extension && 1001 extension->from_webstore(); 1002 1003 bool is_invoked_by_hosted_app = extension && 1004 extension->is_hosted_app() && 1005 extension->web_extent().MatchesURL(app_url); 1006 1007 // Allow built-in extensions and extensions under development. 1008 bool is_extension_unrestricted = extension && 1009 (extension->location() == extensions::Manifest::COMPONENT || 1010 extensions::Manifest::IsUnpackedLocation(extension->location())); 1011 1012 bool is_invoked_by_extension = app_url.SchemeIs("chrome-extension"); 1013 1014 // The NaCl PDF viewer is always allowed and can use 'Dev' interfaces. 1015 bool is_nacl_pdf_viewer = 1016 (is_extension_from_webstore && 1017 manifest_url.SchemeIs("chrome-extension") && 1018 manifest_url.host() == "acadkphlmlegjaadjagenfimbpphcgnh"); 1019 1020 // Allow Chrome Web Store extensions, built-in extensions and extensions 1021 // under development if the invocation comes from a URL with an extension 1022 // scheme. Also allow invocations if they are from whitelisted URLs or 1023 // if --enable-nacl is set. 1024 bool is_nacl_allowed = is_nacl_unrestricted || 1025 is_whitelisted_web_ui || 1026 is_whitelisted_app || 1027 is_nacl_pdf_viewer || 1028 is_invoked_by_hosted_app || 1029 (is_invoked_by_extension && 1030 (is_extension_from_webstore || 1031 is_extension_unrestricted)); 1032 if (is_nacl_allowed) { 1033 bool app_can_use_dev_interfaces = is_nacl_pdf_viewer; 1034 // Make sure that PPAPI 'dev' interfaces aren't available for production 1035 // apps unless they're whitelisted. 1036 WebString dev_attribute = WebString::fromUTF8("@dev"); 1037 if ((!is_whitelisted_app && !is_extension_from_webstore) || 1038 app_can_use_dev_interfaces) { 1039 // Add the special '@dev' attribute. 1040 std::vector<base::string16> param_names; 1041 std::vector<base::string16> param_values; 1042 param_names.push_back(dev_attribute); 1043 param_values.push_back(WebString()); 1044 AppendParams( 1045 param_names, 1046 param_values, 1047 ¶ms->attributeNames, 1048 ¶ms->attributeValues); 1049 } else { 1050 // If the params somehow contain '@dev', remove it. 1051 size_t attribute_count = params->attributeNames.size(); 1052 for (size_t i = 0; i < attribute_count; ++i) { 1053 if (params->attributeNames[i].equals(dev_attribute)) 1054 params->attributeNames[i] = WebString(); 1055 } 1056 } 1057 } 1058 return is_nacl_allowed; 1059 } 1060 1061 bool ChromeContentRendererClient::HasErrorPage(int http_status_code, 1062 std::string* error_domain) { 1063 // Use an internal error page, if we have one for the status code. 1064 if (!LocalizedError::HasStrings(LocalizedError::kHttpErrorDomain, 1065 http_status_code)) { 1066 return false; 1067 } 1068 1069 *error_domain = LocalizedError::kHttpErrorDomain; 1070 return true; 1071 } 1072 1073 bool ChromeContentRendererClient::ShouldSuppressErrorPage( 1074 content::RenderFrame* render_frame, 1075 const GURL& url) { 1076 // Unit tests for ChromeContentRendererClient pass a NULL RenderFrame here. 1077 // Unfortunately it's very difficult to construct a mock RenderView, so skip 1078 // this functionality in this case. 1079 if (render_frame) { 1080 content::RenderView* render_view = render_frame->GetRenderView(); 1081 content::RenderFrame* main_render_frame = render_view->GetMainRenderFrame(); 1082 blink::WebFrame* web_frame = render_frame->GetWebFrame(); 1083 NetErrorHelper* net_error_helper = NetErrorHelper::Get(main_render_frame); 1084 if (net_error_helper->ShouldSuppressErrorPage(web_frame, url)) 1085 return true; 1086 } 1087 // Do not flash an error page if the Instant new tab page fails to load. 1088 return search_bouncer_.get() && search_bouncer_->IsNewTabPage(url); 1089 } 1090 1091 void ChromeContentRendererClient::GetNavigationErrorStrings( 1092 content::RenderView* render_view, 1093 blink::WebFrame* frame, 1094 const blink::WebURLRequest& failed_request, 1095 const blink::WebURLError& error, 1096 std::string* error_html, 1097 base::string16* error_description) { 1098 const GURL failed_url = error.unreachableURL; 1099 const Extension* extension = NULL; 1100 1101 #if defined(ENABLE_EXTENSIONS) 1102 if (failed_url.is_valid() && 1103 !failed_url.SchemeIs(extensions::kExtensionScheme)) { 1104 extension = extension_dispatcher_->extensions()->GetExtensionOrAppByURL( 1105 failed_url); 1106 } 1107 #endif 1108 1109 bool is_post = EqualsASCII(failed_request.httpMethod(), "POST"); 1110 1111 if (error_html) { 1112 // Use a local error page. 1113 if (extension && !extension->from_bookmark()) { 1114 // TODO(erikkay): Should we use a different template for different 1115 // error messages? 1116 int resource_id = IDR_ERROR_APP_HTML; 1117 const base::StringPiece template_html( 1118 ResourceBundle::GetSharedInstance().GetRawDataResource( 1119 resource_id)); 1120 if (template_html.empty()) { 1121 NOTREACHED() << "unable to load template. ID: " << resource_id; 1122 } else { 1123 base::DictionaryValue error_strings; 1124 LocalizedError::GetAppErrorStrings(failed_url, extension, 1125 &error_strings); 1126 // "t" is the id of the template's root node. 1127 *error_html = webui::GetTemplatesHtml(template_html, &error_strings, 1128 "t"); 1129 } 1130 } else { 1131 // TODO(ellyjones): change GetNavigationErrorStrings to take a RenderFrame 1132 // instead of a RenderView, then pass that in. 1133 // This is safe for now because we only install the NetErrorHelper on the 1134 // main render frame anyway; see the TODO(ellyjones) in 1135 // RenderFrameCreated. 1136 content::RenderFrame* main_render_frame = 1137 render_view->GetMainRenderFrame(); 1138 NetErrorHelper* helper = NetErrorHelper::Get(main_render_frame); 1139 helper->GetErrorHTML(frame, error, is_post, error_html); 1140 } 1141 } 1142 1143 if (error_description) { 1144 if (!extension) 1145 *error_description = LocalizedError::GetErrorDetails(error, is_post); 1146 } 1147 } 1148 1149 bool ChromeContentRendererClient::RunIdleHandlerWhenWidgetsHidden() { 1150 #if defined(ENABLE_EXTENSIONS) 1151 return !extension_dispatcher_->is_extension_process(); 1152 #else 1153 return true; 1154 #endif 1155 } 1156 1157 bool ChromeContentRendererClient::AllowPopup() { 1158 #if defined(ENABLE_EXTENSIONS) 1159 extensions::ScriptContext* current_context = 1160 extension_dispatcher_->script_context_set().GetCurrent(); 1161 if (!current_context || !current_context->extension()) 1162 return false; 1163 // See http://crbug.com/117446 for the subtlety of this check. 1164 switch (current_context->context_type()) { 1165 case extensions::Feature::UNSPECIFIED_CONTEXT: 1166 case extensions::Feature::WEB_PAGE_CONTEXT: 1167 case extensions::Feature::UNBLESSED_EXTENSION_CONTEXT: 1168 case extensions::Feature::WEBUI_CONTEXT: 1169 return false; 1170 case extensions::Feature::BLESSED_EXTENSION_CONTEXT: 1171 case extensions::Feature::CONTENT_SCRIPT_CONTEXT: 1172 return true; 1173 case extensions::Feature::BLESSED_WEB_PAGE_CONTEXT: 1174 return !current_context->web_frame()->parent(); 1175 } 1176 NOTREACHED(); 1177 #endif 1178 return false; 1179 } 1180 1181 bool ChromeContentRendererClient::ShouldFork(WebFrame* frame, 1182 const GURL& url, 1183 const std::string& http_method, 1184 bool is_initial_navigation, 1185 bool is_server_redirect, 1186 bool* send_referrer) { 1187 DCHECK(!frame->parent()); 1188 1189 // If this is the Instant process, fork all navigations originating from the 1190 // renderer. The destination page will then be bucketed back to this Instant 1191 // process if it is an Instant url, or to another process if not. Conversely, 1192 // fork if this is a non-Instant process navigating to an Instant url, so that 1193 // such navigations can also be bucketed into an Instant renderer. 1194 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInstantProcess) || 1195 (search_bouncer_.get() && search_bouncer_->ShouldFork(url))) { 1196 *send_referrer = true; 1197 return true; 1198 } 1199 1200 // For now, we skip the rest for POST submissions. This is because 1201 // http://crbug.com/101395 is more likely to cause compatibility issues 1202 // with hosted apps and extensions than WebUI pages. We will remove this 1203 // check when cross-process POST submissions are supported. 1204 if (http_method != "GET") 1205 return false; 1206 1207 // If this is the Signin process, fork all navigations originating from the 1208 // renderer. The destination page will then be bucketed back to this Signin 1209 // process if it is a Signin url, or to another process if not. 1210 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSigninProcess)) { 1211 // We never want to allow non-signin pages to fork-on-POST to a 1212 // signin-related action URL. We'll need to handle this carefully once 1213 // http://crbug.com/101395 is fixed. The CHECK ensures we don't forget. 1214 CHECK_NE(http_method, "POST"); 1215 return true; 1216 } 1217 1218 // If |url| matches one of the prerendered URLs, stop this navigation and try 1219 // to swap in the prerendered page on the browser process. If the prerendered 1220 // page no longer exists by the time the OpenURL IPC is handled, a normal 1221 // navigation is attempted. 1222 if (prerender_dispatcher_.get() && 1223 prerender_dispatcher_->IsPrerenderURL(url)) { 1224 *send_referrer = true; 1225 return true; 1226 } 1227 1228 #if defined(ENABLE_EXTENSIONS) 1229 const extensions::ExtensionSet* extensions = 1230 extension_dispatcher_->extensions(); 1231 1232 // Determine if the new URL is an extension (excluding bookmark apps). 1233 const Extension* new_url_extension = extensions::GetNonBookmarkAppExtension( 1234 *extensions, url); 1235 bool is_extension_url = !!new_url_extension; 1236 1237 // If the navigation would cross an app extent boundary, we also need 1238 // to defer to the browser to ensure process isolation. This is not necessary 1239 // for server redirects, which will be transferred to a new process by the 1240 // browser process when they are ready to commit. It is necessary for client 1241 // redirects, which won't be transferred in the same way. 1242 if (!is_server_redirect && 1243 CrossesExtensionExtents(frame, url, *extensions, is_extension_url, 1244 is_initial_navigation)) { 1245 // Include the referrer in this case since we're going from a hosted web 1246 // page. (the packaged case is handled previously by the extension 1247 // navigation test) 1248 *send_referrer = true; 1249 1250 const Extension* extension = 1251 extension_dispatcher_->extensions()->GetExtensionOrAppByURL(url); 1252 if (extension && extension->is_app()) { 1253 UMA_HISTOGRAM_ENUMERATION( 1254 extension->is_platform_app() ? 1255 extension_misc::kPlatformAppLaunchHistogram : 1256 extension_misc::kAppLaunchHistogram, 1257 extension_misc::APP_LAUNCH_CONTENT_NAVIGATION, 1258 extension_misc::APP_LAUNCH_BUCKET_BOUNDARY); 1259 } 1260 return true; 1261 } 1262 1263 // If this is a reload, check whether it has the wrong process type. We 1264 // should send it to the browser if it's an extension URL (e.g., hosted app) 1265 // in a normal process, or if it's a process for an extension that has been 1266 // uninstalled. 1267 if (frame->top()->document().url() == url) { 1268 if (is_extension_url != extension_dispatcher_->is_extension_process()) 1269 return true; 1270 } 1271 #endif // defined(ENABLE_EXTENSIONS) 1272 1273 return false; 1274 } 1275 1276 bool ChromeContentRendererClient::WillSendRequest( 1277 blink::WebFrame* frame, 1278 ui::PageTransition transition_type, 1279 const GURL& url, 1280 const GURL& first_party_for_cookies, 1281 GURL* new_url) { 1282 // Check whether the request should be allowed. If not allowed, we reset the 1283 // URL to something invalid to prevent the request and cause an error. 1284 #if defined(ENABLE_EXTENSIONS) 1285 if (url.SchemeIs(extensions::kExtensionScheme) && 1286 !extensions::ResourceRequestPolicy::CanRequestResource( 1287 url, 1288 frame, 1289 transition_type, 1290 extension_dispatcher_->extensions())) { 1291 *new_url = GURL(chrome::kExtensionInvalidRequestURL); 1292 return true; 1293 } 1294 1295 if (url.SchemeIs(extensions::kExtensionResourceScheme) && 1296 !extensions::ResourceRequestPolicy::CanRequestExtensionResourceScheme( 1297 url, 1298 frame)) { 1299 *new_url = GURL(chrome::kExtensionResourceInvalidRequestURL); 1300 return true; 1301 } 1302 #endif 1303 1304 const content::RenderView* render_view = 1305 content::RenderView::FromWebView(frame->view()); 1306 SearchBox* search_box = SearchBox::Get(render_view); 1307 if (search_box && url.SchemeIs(chrome::kChromeSearchScheme)) { 1308 if (url.host() == chrome::kChromeUIThumbnailHost) 1309 return search_box->GenerateThumbnailURLFromTransientURL(url, new_url); 1310 else if (url.host() == chrome::kChromeUIFaviconHost) 1311 return search_box->GenerateFaviconURLFromTransientURL(url, new_url); 1312 } 1313 1314 return false; 1315 } 1316 1317 void ChromeContentRendererClient::DidCreateScriptContext( 1318 WebFrame* frame, v8::Handle<v8::Context> context, int extension_group, 1319 int world_id) { 1320 #if defined(ENABLE_EXTENSIONS) 1321 extension_dispatcher_->DidCreateScriptContext( 1322 frame, context, extension_group, world_id); 1323 #endif 1324 } 1325 1326 unsigned long long ChromeContentRendererClient::VisitedLinkHash( 1327 const char* canonical_url, size_t length) { 1328 return visited_link_slave_->ComputeURLFingerprint(canonical_url, length); 1329 } 1330 1331 bool ChromeContentRendererClient::IsLinkVisited(unsigned long long link_hash) { 1332 return visited_link_slave_->IsVisited(link_hash); 1333 } 1334 1335 blink::WebPrescientNetworking* 1336 ChromeContentRendererClient::GetPrescientNetworking() { 1337 return prescient_networking_dispatcher_.get(); 1338 } 1339 1340 bool ChromeContentRendererClient::ShouldOverridePageVisibilityState( 1341 const content::RenderFrame* render_frame, 1342 blink::WebPageVisibilityState* override_state) { 1343 if (!prerender::PrerenderHelper::IsPrerendering(render_frame)) 1344 return false; 1345 1346 *override_state = blink::WebPageVisibilityStatePrerender; 1347 return true; 1348 } 1349 1350 #if defined(ENABLE_EXTENSIONS) 1351 void ChromeContentRendererClient::SetExtensionDispatcherForTest( 1352 extensions::Dispatcher* extension_dispatcher) { 1353 extension_dispatcher_.reset(extension_dispatcher); 1354 permissions_policy_delegate_.reset( 1355 new extensions::RendererPermissionsPolicyDelegate( 1356 extension_dispatcher_.get())); 1357 } 1358 1359 extensions::Dispatcher* 1360 ChromeContentRendererClient::GetExtensionDispatcherForTest() { 1361 return extension_dispatcher_.get(); 1362 } 1363 1364 bool ChromeContentRendererClient::CrossesExtensionExtents( 1365 WebFrame* frame, 1366 const GURL& new_url, 1367 const extensions::ExtensionSet& extensions, 1368 bool is_extension_url, 1369 bool is_initial_navigation) { 1370 GURL old_url(frame->top()->document().url()); 1371 1372 // If old_url is still empty and this is an initial navigation, then this is 1373 // a window.open operation. We should look at the opener URL. 1374 if (is_initial_navigation && old_url.is_empty() && frame->opener()) { 1375 // If we're about to open a normal web page from a same-origin opener stuck 1376 // in an extension process, we want to keep it in process to allow the 1377 // opener to script it. 1378 WebDocument opener_document = frame->opener()->document(); 1379 WebSecurityOrigin opener = frame->opener()->document().securityOrigin(); 1380 bool opener_is_extension_url = 1381 !opener.isUnique() && extensions.GetExtensionOrAppByURL( 1382 opener_document.url()) != NULL; 1383 if (!is_extension_url && 1384 !opener_is_extension_url && 1385 extension_dispatcher_->is_extension_process() && 1386 opener.canRequest(WebURL(new_url))) 1387 return false; 1388 1389 // In all other cases, we want to compare against the top frame's URL (as 1390 // opposed to the opener frame's), since that's what determines the type of 1391 // process. This allows iframes outside an app to open a popup in the app. 1392 old_url = frame->top()->opener()->top()->document().url(); 1393 } 1394 1395 // Only consider keeping non-app URLs in an app process if this window 1396 // has an opener (in which case it might be an OAuth popup that tries to 1397 // script an iframe within the app). 1398 bool should_consider_workaround = !!frame->opener(); 1399 1400 return extensions::CrossesExtensionProcessBoundary( 1401 extensions, old_url, new_url, should_consider_workaround); 1402 } 1403 #endif // defined(ENABLE_EXTENSIONS) 1404 1405 #if defined(ENABLE_SPELLCHECK) 1406 void ChromeContentRendererClient::SetSpellcheck(SpellCheck* spellcheck) { 1407 RenderThread* thread = RenderThread::Get(); 1408 if (spellcheck_.get() && thread) 1409 thread->RemoveObserver(spellcheck_.get()); 1410 spellcheck_.reset(spellcheck); 1411 SpellCheckReplacer replacer(spellcheck_.get()); 1412 content::RenderView::ForEach(&replacer); 1413 if (thread) 1414 thread->AddObserver(spellcheck_.get()); 1415 } 1416 #endif 1417 1418 // static 1419 bool ChromeContentRendererClient::WasWebRequestUsedBySomeExtensions() { 1420 #if defined(ENABLE_EXTENSIONS) 1421 return g_current_client->extension_dispatcher_ 1422 ->WasWebRequestUsedBySomeExtensions(); 1423 #else 1424 return false; 1425 #endif 1426 } 1427 1428 const void* ChromeContentRendererClient::CreatePPAPIInterface( 1429 const std::string& interface_name) { 1430 #if defined(ENABLE_PLUGINS) 1431 #if !defined(DISABLE_NACL) 1432 if (interface_name == PPB_NACL_PRIVATE_INTERFACE) 1433 return nacl::GetNaClPrivateInterface(); 1434 #endif // DISABLE_NACL 1435 if (interface_name == PPB_PDF_INTERFACE) 1436 return pdf::PPB_PDF_Impl::GetInterface(); 1437 #endif 1438 return NULL; 1439 } 1440 1441 bool ChromeContentRendererClient::IsExternalPepperPlugin( 1442 const std::string& module_name) { 1443 // TODO(bbudge) remove this when the trusted NaCl plugin has been removed. 1444 // We must defer certain plugin events for NaCl instances since we switch 1445 // from the in-process to the out-of-process proxy after instantiating them. 1446 return module_name == "Native Client"; 1447 } 1448 1449 #if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS) 1450 bool ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted( 1451 const GURL& url, const std::set<std::string>& whitelist) { 1452 const extensions::ExtensionSet* extension_set = 1453 g_current_client->extension_dispatcher_->extensions(); 1454 return chrome::IsExtensionOrSharedModuleWhitelisted(url, extension_set, 1455 whitelist); 1456 } 1457 #endif 1458 1459 blink::WebSpeechSynthesizer* 1460 ChromeContentRendererClient::OverrideSpeechSynthesizer( 1461 blink::WebSpeechSynthesizerClient* client) { 1462 return new TtsDispatcher(client); 1463 } 1464 1465 bool ChromeContentRendererClient::AllowPepperMediaStreamAPI( 1466 const GURL& url) { 1467 #if !defined(OS_ANDROID) 1468 // Allow only the Hangouts app to use the MediaStream APIs. It's OK to check 1469 // the whitelist in the renderer, since we're only preventing access until 1470 // these APIs are public and stable. 1471 std::string url_host = url.host(); 1472 if (url.SchemeIs("https") && 1473 (EndsWith(url_host, "talkgadget.google.com", false) || 1474 EndsWith(url_host, "plus.google.com", false) || 1475 EndsWith(url_host, "plus.sandbox.google.com", false)) && 1476 StartsWithASCII(url.path(), "/hangouts/", false)) { 1477 return true; 1478 } 1479 // Allow access for tests. 1480 if (CommandLine::ForCurrentProcess()->HasSwitch( 1481 switches::kEnablePepperTesting)) { 1482 return true; 1483 } 1484 #endif // !defined(OS_ANDROID) 1485 return false; 1486 } 1487 1488 void ChromeContentRendererClient::AddKeySystems( 1489 std::vector<content::KeySystemInfo>* key_systems) { 1490 AddChromeKeySystems(key_systems); 1491 } 1492 1493 bool ChromeContentRendererClient::ShouldReportDetailedMessageForSource( 1494 const base::string16& source) const { 1495 return extensions::IsSourceFromAnExtension(source); 1496 } 1497 1498 bool ChromeContentRendererClient::ShouldEnableSiteIsolationPolicy() const { 1499 // SiteIsolationPolicy is off by default. We would like to activate cross-site 1500 // document blocking (for UMA data collection) for normal renderer processes 1501 // running a normal web page from the Internet. We only turn on 1502 // SiteIsolationPolicy for a renderer process that does not have the extension 1503 // flag on. 1504 CommandLine* command_line = CommandLine::ForCurrentProcess(); 1505 return !command_line->HasSwitch(extensions::switches::kExtensionProcess); 1506 } 1507 1508 blink::WebWorkerPermissionClientProxy* 1509 ChromeContentRendererClient::CreateWorkerPermissionClientProxy( 1510 content::RenderFrame* render_frame, 1511 blink::WebFrame* frame) { 1512 return new WorkerPermissionClientProxy(render_frame, frame); 1513 } 1514 1515 bool ChromeContentRendererClient::IsPluginAllowedToUseDevChannelAPIs() { 1516 #if defined(ENABLE_PLUGINS) 1517 // Allow access for tests. 1518 if (CommandLine::ForCurrentProcess()->HasSwitch( 1519 switches::kEnablePepperTesting)) { 1520 return true; 1521 } 1522 1523 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 1524 // Allow dev channel APIs to be used on "Canary", "Dev", and "Unknown" 1525 // releases of Chrome. Permitting "Unknown" allows these APIs to be used on 1526 // Chromium builds as well. 1527 return channel <= chrome::VersionInfo::CHANNEL_DEV; 1528 #else 1529 return false; 1530 #endif 1531 } 1532 1533 bool ChromeContentRendererClient::IsPluginAllowedToUseCompositorAPI( 1534 const GURL& url) { 1535 #if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS) 1536 if (CommandLine::ForCurrentProcess()->HasSwitch( 1537 switches::kEnablePepperTesting)) 1538 return true; 1539 if (IsExtensionOrSharedModuleWhitelisted(url, allowed_compositor_origins_)) 1540 return true; 1541 1542 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 1543 return channel <= chrome::VersionInfo::CHANNEL_DEV; 1544 #else 1545 return false; 1546 #endif 1547 } 1548 1549 bool ChromeContentRendererClient::IsPluginAllowedToUseVideoDecodeAPI( 1550 const GURL& url) { 1551 #if defined(ENABLE_PLUGINS) && defined(ENABLE_EXTENSIONS) 1552 if (CommandLine::ForCurrentProcess()->HasSwitch( 1553 switches::kEnablePepperTesting)) 1554 return true; 1555 1556 if (IsExtensionOrSharedModuleWhitelisted(url, allowed_video_decode_origins_)) 1557 return true; 1558 1559 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 1560 return channel <= chrome::VersionInfo::CHANNEL_DEV; 1561 #else 1562 return false; 1563 #endif 1564 } 1565 1566 content::BrowserPluginDelegate* 1567 ChromeContentRendererClient::CreateBrowserPluginDelegate( 1568 content::RenderFrame* render_frame, 1569 const std::string& mime_type) { 1570 #if defined(ENABLE_EXTENSIONS) 1571 return new extensions::GuestViewContainer(render_frame, mime_type); 1572 #else 1573 return NULL; 1574 #endif 1575 } 1576