chrome_content_browser_client.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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/browser/chrome_content_browser_client.h" 6 7#include <set> 8#include <utility> 9#include <vector> 10 11#include "base/bind.h" 12#include "base/command_line.h" 13#include "base/lazy_instance.h" 14#include "base/path_service.h" 15#include "base/prefs/pref_service.h" 16#include "base/strings/string_number_conversions.h" 17#include "base/strings/utf_string_conversions.h" 18#include "base/threading/sequenced_worker_pool.h" 19#include "chrome/app/breakpad_mac.h" 20#include "chrome/browser/app_mode/app_mode_utils.h" 21#include "chrome/browser/browser_about_handler.h" 22#include "chrome/browser/browser_process.h" 23#include "chrome/browser/browser_shutdown.h" 24#include "chrome/browser/browsing_data/browsing_data_helper.h" 25#include "chrome/browser/browsing_data/browsing_data_remover.h" 26#include "chrome/browser/character_encoding.h" 27#include "chrome/browser/chrome_net_benchmarking_message_filter.h" 28#include "chrome/browser/chrome_quota_permission_context.h" 29#include "chrome/browser/content_settings/content_settings_utils.h" 30#include "chrome/browser/content_settings/cookie_settings.h" 31#include "chrome/browser/content_settings/host_content_settings_map.h" 32#include "chrome/browser/content_settings/tab_specific_content_settings.h" 33#include "chrome/browser/defaults.h" 34#include "chrome/browser/download/download_prefs.h" 35#include "chrome/browser/extensions/api/web_request/web_request_api.h" 36#include "chrome/browser/extensions/browser_permissions_policy_delegate.h" 37#include "chrome/browser/extensions/extension_host.h" 38#include "chrome/browser/extensions/extension_info_map.h" 39#include "chrome/browser/extensions/extension_process_manager.h" 40#include "chrome/browser/extensions/extension_service.h" 41#include "chrome/browser/extensions/extension_system.h" 42#include "chrome/browser/extensions/extension_web_ui.h" 43#include "chrome/browser/extensions/extension_webkit_preferences.h" 44#include "chrome/browser/extensions/process_map.h" 45#include "chrome/browser/extensions/suggest_permission_util.h" 46#include "chrome/browser/geolocation/chrome_access_token_store.h" 47#include "chrome/browser/google/google_util.h" 48#include "chrome/browser/guestview/adview/adview_guest.h" 49#include "chrome/browser/guestview/guestview_constants.h" 50#include "chrome/browser/guestview/webview/webview_guest.h" 51#include "chrome/browser/media/media_capture_devices_dispatcher.h" 52#include "chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.h" 53#include "chrome/browser/nacl_host/nacl_host_message_filter.h" 54#include "chrome/browser/nacl_host/nacl_process_host.h" 55#include "chrome/browser/net/chrome_net_log.h" 56#include "chrome/browser/notifications/desktop_notification_service.h" 57#include "chrome/browser/notifications/desktop_notification_service_factory.h" 58#include "chrome/browser/platform_util.h" 59#include "chrome/browser/plugins/plugin_info_message_filter.h" 60#include "chrome/browser/prefs/scoped_user_pref_update.h" 61#include "chrome/browser/prerender/prerender_final_status.h" 62#include "chrome/browser/prerender/prerender_manager.h" 63#include "chrome/browser/prerender/prerender_manager_factory.h" 64#include "chrome/browser/prerender/prerender_message_filter.h" 65#include "chrome/browser/prerender/prerender_tracker.h" 66#include "chrome/browser/printing/printing_message_filter.h" 67#include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h" 68#include "chrome/browser/profiles/profile.h" 69#include "chrome/browser/profiles/profile_io_data.h" 70#include "chrome/browser/profiles/profile_manager.h" 71#include "chrome/browser/renderer_host/chrome_render_message_filter.h" 72#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" 73#include "chrome/browser/search/instant_service.h" 74#include "chrome/browser/search/instant_service_factory.h" 75#include "chrome/browser/search/search.h" 76#include "chrome/browser/search_engines/search_provider_install_state_message_filter.h" 77#include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" 78#include "chrome/browser/speech/tts_message_filter.h" 79#include "chrome/browser/ssl/ssl_add_certificate.h" 80#include "chrome/browser/ssl/ssl_blocking_page.h" 81#include "chrome/browser/ssl/ssl_tab_helper.h" 82#include "chrome/browser/sync_file_system/local/sync_file_system_backend.h" 83#include "chrome/browser/tab_contents/tab_util.h" 84#include "chrome/browser/ui/blocked_content/blocked_window_params.h" 85#include "chrome/browser/ui/blocked_content/popup_blocker_tab_helper.h" 86#include "chrome/browser/ui/chrome_select_file_policy.h" 87#include "chrome/browser/ui/sync/sync_promo_ui.h" 88#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h" 89#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" 90#include "chrome/browser/user_style_sheet_watcher.h" 91#include "chrome/browser/user_style_sheet_watcher_factory.h" 92#include "chrome/browser/validation_message_message_filter.h" 93#include "chrome/common/child_process_logging.h" 94#include "chrome/common/chrome_constants.h" 95#include "chrome/common/chrome_paths.h" 96#include "chrome/common/chrome_switches.h" 97#include "chrome/common/extensions/background_info.h" 98#include "chrome/common/extensions/extension.h" 99#include "chrome/common/extensions/extension_process_policy.h" 100#include "chrome/common/extensions/extension_set.h" 101#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h" 102#include "chrome/common/extensions/manifest_handlers/shared_module_info.h" 103#include "chrome/common/extensions/permissions/permissions_data.h" 104#include "chrome/common/extensions/permissions/socket_permission.h" 105#include "chrome/common/extensions/web_accessible_resources_handler.h" 106#include "chrome/common/logging_chrome.h" 107#include "chrome/common/pepper_permission_util.h" 108#include "chrome/common/pref_names.h" 109#include "chrome/common/render_messages.h" 110#include "chrome/common/url_constants.h" 111#include "chromeos/chromeos_constants.h" 112#include "components/nacl/common/nacl_process_type.h" 113#include "components/user_prefs/pref_registry_syncable.h" 114#include "content/public/browser/browser_child_process_host.h" 115#include "content/public/browser/browser_main_parts.h" 116#include "content/public/browser/browser_ppapi_host.h" 117#include "content/public/browser/browser_thread.h" 118#include "content/public/browser/browser_url_handler.h" 119#include "content/public/browser/child_process_data.h" 120#include "content/public/browser/child_process_security_policy.h" 121#include "content/public/browser/render_process_host.h" 122#include "content/public/browser/render_view_host.h" 123#include "content/public/browser/resource_context.h" 124#include "content/public/browser/site_instance.h" 125#include "content/public/browser/web_contents.h" 126#include "content/public/browser/web_contents_view.h" 127#include "content/public/common/child_process_host.h" 128#include "content/public/common/content_descriptors.h" 129#include "extensions/browser/view_type_utils.h" 130#include "extensions/common/constants.h" 131#include "extensions/common/switches.h" 132#include "grit/generated_resources.h" 133#include "grit/ui_resources.h" 134#include "net/base/escape.h" 135#include "net/base/mime_util.h" 136#include "net/cookies/canonical_cookie.h" 137#include "net/cookies/cookie_options.h" 138#include "net/ssl/ssl_cert_request_info.h" 139#include "ppapi/host/ppapi_host.h" 140#include "ui/base/l10n/l10n_util.h" 141#include "ui/base/resource/resource_bundle.h" 142#include "ui/message_center/message_center_util.h" 143#include "webkit/browser/fileapi/external_mount_points.h" 144#include "webkit/common/webpreferences.h" 145 146#if defined(OS_WIN) 147#include "chrome/browser/chrome_browser_main_win.h" 148#include "sandbox/win/src/sandbox_policy.h" 149#elif defined(OS_MACOSX) 150#include "chrome/browser/chrome_browser_main_mac.h" 151#include "chrome/browser/spellchecker/spellcheck_message_filter_mac.h" 152#elif defined(OS_CHROMEOS) 153#include "chrome/browser/chromeos/chrome_browser_main_chromeos.h" 154#include "chrome/browser/chromeos/drive/file_system_backend_delegate.h" 155#include "chrome/browser/chromeos/fileapi/file_system_backend.h" 156#include "chrome/browser/chromeos/login/startup_utils.h" 157#include "chrome/browser/chromeos/login/user_manager.h" 158#include "chrome/browser/chromeos/system/input_device_settings.h" 159#include "chromeos/chromeos_switches.h" 160#elif defined(OS_LINUX) 161#include "chrome/browser/chrome_browser_main_linux.h" 162#elif defined(OS_ANDROID) 163#include "chrome/browser/android/crash_dump_manager.h" 164#include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h" 165#include "chrome/browser/chrome_browser_main_android.h" 166#include "chrome/browser/media/encrypted_media_message_filter_android.h" 167#include "chrome/common/descriptors_android.h" 168#elif defined(OS_POSIX) 169#include "chrome/browser/chrome_browser_main_posix.h" 170#endif 171 172#if defined(OS_LINUX) || defined(OS_OPENBSD) || defined(OS_ANDROID) 173#include "base/linux_util.h" 174#include "chrome/browser/crash_handler_host_linux.h" 175#endif 176 177#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 178#include "chrome/browser/captive_portal/captive_portal_tab_helper.h" 179#endif 180 181#if defined(OS_ANDROID) 182#include "ui/base/ui_base_paths.h" 183#endif 184 185#if defined(USE_NSS) 186#include "chrome/browser/ui/crypto_module_password_dialog.h" 187#endif 188 189#if !defined(OS_CHROMEOS) 190#include "chrome/browser/signin/signin_manager.h" 191#include "chrome/browser/signin/signin_manager_factory.h" 192#endif 193 194#if !defined(OS_ANDROID) 195#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h" 196#endif 197 198#if defined(ENABLE_WEBRTC) 199#include "chrome/browser/media/webrtc_logging_handler_host.h" 200#endif 201 202#if defined(ENABLE_INPUT_SPEECH) 203#include "chrome/browser/speech/chrome_speech_recognition_manager_delegate_bubble_ui.h" 204#endif 205 206#if defined(FILE_MANAGER_EXTENSION) 207#include "chrome/browser/chromeos/file_manager/app_id.h" 208#endif 209 210#if defined(TOOLKIT_GTK) 211#include "chrome/browser/ui/gtk/chrome_browser_main_extra_parts_gtk.h" 212#endif 213 214#if defined(TOOLKIT_VIEWS) 215#include "chrome/browser/ui/views/chrome_browser_main_extra_parts_views.h" 216#endif 217 218#if defined(USE_ASH) 219#include "chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.h" 220#endif 221 222#if defined(USE_AURA) 223#include "chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.h" 224#endif 225 226#if defined(USE_X11) 227#include "chrome/browser/chrome_browser_main_extra_parts_x11.h" 228#endif 229 230#if defined(ENABLE_SPELLCHECK) 231#include "chrome/browser/spellchecker/spellcheck_message_filter.h" 232#endif 233 234using WebKit::WebWindowFeatures; 235using base::FileDescriptor; 236using content::AccessTokenStore; 237using content::BrowserChildProcessHostIterator; 238using content::BrowserThread; 239using content::BrowserURLHandler; 240using content::ChildProcessSecurityPolicy; 241using content::FileDescriptorInfo; 242using content::QuotaPermissionContext; 243using content::RenderViewHost; 244using content::SiteInstance; 245using content::WebContents; 246using extensions::APIPermission; 247using extensions::Extension; 248using extensions::Manifest; 249using message_center::NotifierId; 250 251namespace { 252 253// Cached version of the locale so we can return the locale on the I/O 254// thread. 255base::LazyInstance<std::string> g_io_thread_application_locale; 256 257#if defined(ENABLE_PLUGINS) 258const char* kPredefinedAllowedSocketOrigins[] = { 259 "okddffdblfhhnmhodogpojmfkjmhinfp", // Test SSH Client 260 "pnhechapfaindjhompbnflcldabbghjo", // HTerm App (SSH Client) 261 "bglhmjfplikpjnfoegeomebmfnkjomhe", // see crbug.com/122126 262 "gbchcmhmhahfdphkhkmpfmihenigjmpp", // Chrome Remote Desktop 263 "kgngmbheleoaphbjbaiobfdepmghbfah", // Pre-release Chrome Remote Desktop 264 "odkaodonbgfohohmklejpjiejmcipmib", // Dogfood Chrome Remote Desktop 265 "ojoimpklfciegopdfgeenehpalipignm", // Chromoting canary 266 "cbkkbcmdlboombapidmoeolnmdacpkch", // see crbug.com/129089 267 "hhnbmknkdabfoieppbbljkhkfjcmcbjh", // see crbug.com/134099 268 "mablfbjkhmhkmefkjjacnbaikjkipphg", // see crbug.com/134099 269 "pdeelgamlgannhelgoegilelnnojegoh", // see crbug.com/134099 270 "cabapfdbkniadpollkckdnedaanlciaj", // see crbug.com/134099 271 "mapljbgnjledlpdmlchihnmeclmefbba", // see crbug.com/134099 272 "ghbfeebgmiidnnmeobbbaiamklmpbpii", // see crbug.com/134099 273 "jdfhpkjeckflbbleddjlpimecpbjdeep", // see crbug.com/142514 274 "iabmpiboiopbgfabjmgeedhcmjenhbla", // see crbug.com/165080 275 "B7CF8A292249681AF81771650BA4CEEAF19A4560", // see crbug.com/165080 276 "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F", // see crbug.com/234789 277 "4EB74897CB187C7633357C2FE832E0AD6A44883A", // see crbug.com/234789 278 "7525AF4F66763A70A883C4700529F647B470E4D2", // see crbug.com/238084 279 "0B549507088E1564D672F7942EB87CA4DAD73972", // see crbug.com/238084 280 "864288364E239573E777D3E0E36864E590E95C74" // see crbug.com/238084 281}; 282#endif 283 284// Returns a copy of the given url with its host set to given host and path set 285// to given path. Other parts of the url will be the same. 286GURL ReplaceURLHostAndPath(const GURL& url, 287 const std::string& host, 288 const std::string& path) { 289 url_canon::Replacements<char> replacements; 290 replacements.SetHost(host.c_str(), 291 url_parse::Component(0, host.length())); 292 replacements.SetPath(path.c_str(), 293 url_parse::Component(0, path.length())); 294 return url.ReplaceComponents(replacements); 295} 296 297// Maps "foo://bar/baz/" to "foo://chrome/bar/baz/". 298GURL AddUberHost(const GURL& url) { 299 const std::string uber_host = chrome::kChromeUIUberHost; 300 const std::string new_path = url.host() + url.path(); 301 302 return ReplaceURLHostAndPath(url, uber_host, new_path); 303} 304 305// If url->host() is "chrome" and url->path() has characters other than the 306// first slash, changes the url from "foo://chrome/bar/" to "foo://bar/" and 307// returns true. Otherwise returns false. 308bool RemoveUberHost(GURL* url) { 309 if (url->host() != chrome::kChromeUIUberHost) 310 return false; 311 312 if (url->path().empty() || url->path() == "/") 313 return false; 314 315 const std::string old_path = url->path(); 316 317 const std::string::size_type separator = old_path.find('/', 1); 318 std::string new_host; 319 std::string new_path; 320 if (separator == std::string::npos) { 321 new_host = old_path.substr(1); 322 } else { 323 new_host = old_path.substr(1, separator - 1); 324 new_path = old_path.substr(separator); 325 } 326 327 // Do not allow URLs with paths empty before the first slash since we can't 328 // have an empty host. (e.g "foo://chrome//") 329 if (new_host.empty()) 330 return false; 331 332 *url = ReplaceURLHostAndPath(*url, new_host, new_path); 333 334 DCHECK(url->is_valid()); 335 336 return true; 337} 338 339// Handles rewriting Web UI URLs. 340bool HandleWebUI(GURL* url, content::BrowserContext* browser_context) { 341 // Do not handle special URLs such as "about:foo" 342 if (!url->host().empty()) { 343 const GURL chrome_url = AddUberHost(*url); 344 345 // Handle valid "chrome://chrome/foo" URLs so the reverse handler will 346 // be called. 347 if (ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL( 348 browser_context, chrome_url)) 349 return true; 350 } 351 352 if (!ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL( 353 browser_context, *url)) 354 return false; 355 356#if defined(OS_CHROMEOS) 357 // Special case : in ChromeOS in Guest mode bookmarks and history are 358 // disabled for security reasons. New tab page explains the reasons, so 359 // we redirect user to new tab page. 360 if (chromeos::UserManager::Get()->IsLoggedInAsGuest()) { 361 if (url->SchemeIs(chrome::kChromeUIScheme) && 362 (url->DomainIs(chrome::kChromeUIBookmarksHost) || 363 url->DomainIs(chrome::kChromeUIHistoryHost))) { 364 // Rewrite with new tab URL 365 *url = GURL(chrome::kChromeUINewTabURL); 366 } 367 } 368#endif 369 370 // Special case the new tab page. In older versions of Chrome, the new tab 371 // page was hosted at chrome-internal:<blah>. This might be in people's saved 372 // sessions or bookmarks, so we say any URL with that scheme triggers the new 373 // tab page. 374 if (url->SchemeIs(chrome::kChromeInternalScheme)) { 375 // Rewrite it with the proper new tab URL. 376 *url = GURL(chrome::kChromeUINewTabURL); 377 } 378 379 return true; 380} 381 382// Reverse URL handler for Web UI. Maps "chrome://chrome/foo/" to 383// "chrome://foo/". 384bool HandleWebUIReverse(GURL* url, content::BrowserContext* browser_context) { 385 if (!url->is_valid() || !url->SchemeIs(chrome::kChromeUIScheme)) 386 return false; 387 388 return RemoveUberHost(url); 389} 390 391// Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions 392// below. Extension, and isolated apps require different privileges to be 393// granted to their RenderProcessHosts. This classification allows us to make 394// sure URLs are served by hosts with the right set of privileges. 395enum RenderProcessHostPrivilege { 396 PRIV_NORMAL, 397 PRIV_HOSTED, 398 PRIV_ISOLATED, 399 PRIV_EXTENSION, 400}; 401 402RenderProcessHostPrivilege GetPrivilegeRequiredByUrl( 403 const GURL& url, 404 ExtensionService* service) { 405 // Default to a normal renderer cause it is lower privileged. This should only 406 // occur if the URL on a site instance is either malformed, or uninitialized. 407 // If it is malformed, then there is no need for better privileges anyways. 408 // If it is uninitialized, but eventually settles on being an a scheme other 409 // than normal webrenderer, the navigation logic will correct us out of band 410 // anyways. 411 if (!url.is_valid()) 412 return PRIV_NORMAL; 413 414 if (url.SchemeIs(extensions::kExtensionScheme)) { 415 const Extension* extension = 416 service->extensions()->GetByID(url.host()); 417 if (extension && 418 extensions::AppIsolationInfo::HasIsolatedStorage(extension)) 419 return PRIV_ISOLATED; 420 if (extension && extension->is_hosted_app()) 421 return PRIV_HOSTED; 422 423 return PRIV_EXTENSION; 424 } 425 426 return PRIV_NORMAL; 427} 428 429RenderProcessHostPrivilege GetProcessPrivilege( 430 content::RenderProcessHost* process_host, 431 extensions::ProcessMap* process_map, 432 ExtensionService* service) { 433 std::set<std::string> extension_ids = 434 process_map->GetExtensionsInProcess(process_host->GetID()); 435 if (extension_ids.empty()) 436 return PRIV_NORMAL; 437 438 for (std::set<std::string>::iterator iter = extension_ids.begin(); 439 iter != extension_ids.end(); ++iter) { 440 const Extension* extension = service->GetExtensionById(*iter, false); 441 if (extension && 442 extensions::AppIsolationInfo::HasIsolatedStorage(extension)) 443 return PRIV_ISOLATED; 444 if (extension && extension->is_hosted_app()) 445 return PRIV_HOSTED; 446 } 447 448 return PRIV_EXTENSION; 449} 450 451bool CertMatchesFilter(const net::X509Certificate& cert, 452 const base::DictionaryValue& filter) { 453 // TODO(markusheintz): This is the minimal required filter implementation. 454 // Implement a better matcher. 455 456 // An empty filter matches any client certificate since no requirements are 457 // specified at all. 458 if (filter.empty()) 459 return true; 460 461 std::string common_name; 462 if (filter.GetString("ISSUER.CN", &common_name) && 463 (cert.issuer().common_name == common_name)) { 464 return true; 465 } 466 return false; 467} 468 469// Fills |map| with the per-script font prefs under path |map_name|. 470void FillFontFamilyMap(const PrefService* prefs, 471 const char* map_name, 472 webkit_glue::ScriptFontFamilyMap* map) { 473 for (size_t i = 0; i < prefs::kWebKitScriptsForFontFamilyMapsLength; ++i) { 474 const char* script = prefs::kWebKitScriptsForFontFamilyMaps[i]; 475 std::string pref_name = base::StringPrintf("%s.%s", map_name, script); 476 std::string font_family = prefs->GetString(pref_name.c_str()); 477 if (!font_family.empty()) 478 (*map)[script] = UTF8ToUTF16(font_family); 479 } 480} 481 482#if defined(OS_POSIX) && !defined(OS_MACOSX) 483int GetCrashSignalFD(const CommandLine& command_line) { 484 if (command_line.HasSwitch(switches::kExtensionProcess)) { 485 ExtensionCrashHandlerHostLinux* crash_handler = 486 ExtensionCrashHandlerHostLinux::GetInstance(); 487 return crash_handler->GetDeathSignalSocket(); 488 } 489 490 std::string process_type = 491 command_line.GetSwitchValueASCII(switches::kProcessType); 492 493 if (process_type == switches::kRendererProcess) 494 return RendererCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 495 496 if (process_type == switches::kPluginProcess) 497 return PluginCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 498 499 if (process_type == switches::kPpapiPluginProcess) 500 return PpapiCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 501 502 if (process_type == switches::kGpuProcess) 503 return GpuCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 504 505 return -1; 506} 507#endif // defined(OS_POSIX) && !defined(OS_MACOSX) 508 509#if !defined(OS_CHROMEOS) 510GURL GetEffectiveURLForSignin(const GURL& url) { 511 CHECK(SigninManager::IsWebBasedSigninFlowURL(url)); 512 513 GURL effective_url(SigninManager::kChromeSigninEffectiveSite); 514 // Copy the path because the argument to SetPathStr must outlive 515 // the Replacements object. 516 const std::string path_copy(url.path()); 517 GURL::Replacements replacements; 518 replacements.SetPathStr(path_copy); 519 effective_url = effective_url.ReplaceComponents(replacements); 520 return effective_url; 521} 522#endif 523 524void SetApplicationLocaleOnIOThread(const std::string& locale) { 525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 526 g_io_thread_application_locale.Get() = locale; 527} 528 529void HandleBlockedPopupOnUIThread(const BlockedWindowParams& params) { 530 WebContents* tab = tab_util::GetWebContentsByID(params.render_process_id(), 531 params.opener_id()); 532 if (!tab) 533 return; 534 535 PopupBlockerTabHelper* popup_helper = 536 PopupBlockerTabHelper::FromWebContents(tab); 537 if (!popup_helper) 538 return; 539 popup_helper->AddBlockedPopup(params); 540} 541 542#if defined(OS_ANDROID) 543void HandleSingleTabModeBlockOnUIThread(const BlockedWindowParams& params) { 544 WebContents* web_contents = 545 tab_util::GetWebContentsByID(params.render_process_id(), 546 params.opener_id()); 547 if (!web_contents) 548 return; 549 550 SingleTabModeTabHelper::FromWebContents(web_contents)->HandleOpenUrl(params); 551} 552#endif // defined(OS_ANDROID) 553 554} // namespace 555 556namespace chrome { 557 558ChromeContentBrowserClient::ChromeContentBrowserClient() { 559#if defined(ENABLE_PLUGINS) 560 for (size_t i = 0; i < arraysize(kPredefinedAllowedSocketOrigins); ++i) 561 allowed_socket_origins_.insert(kPredefinedAllowedSocketOrigins[i]); 562#endif 563 564 permissions_policy_delegate_.reset( 565 new extensions::BrowserPermissionsPolicyDelegate()); 566} 567 568ChromeContentBrowserClient::~ChromeContentBrowserClient() { 569} 570 571// static 572void ChromeContentBrowserClient::RegisterProfilePrefs( 573 user_prefs::PrefRegistrySyncable* registry) { 574 registry->RegisterBooleanPref( 575 prefs::kDisable3DAPIs, 576 false, 577 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 578 registry->RegisterBooleanPref( 579 prefs::kEnableHyperlinkAuditing, 580 true, 581 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 582 registry->RegisterBooleanPref( 583 prefs::kEnableMemoryInfo, 584 false, 585 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 586} 587 588// static 589void ChromeContentBrowserClient::SetApplicationLocale( 590 const std::string& locale) { 591 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 592 593 // This object is guaranteed to outlive all threads so we don't have to 594 // worry about the lack of refcounting and can just post as Unretained. 595 // 596 // The common case is that this function is called early in Chrome startup 597 // before any threads are created (it will also be called later if the user 598 // changes the pref). In this case, there will be no threads created and 599 // posting will fail. When there are no threads, we can just set the string 600 // without worrying about threadsafety. 601 if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 602 base::Bind(&SetApplicationLocaleOnIOThread, locale))) { 603 g_io_thread_application_locale.Get() = locale; 604 } 605} 606 607content::BrowserMainParts* ChromeContentBrowserClient::CreateBrowserMainParts( 608 const content::MainFunctionParams& parameters) { 609 ChromeBrowserMainParts* main_parts; 610 // Construct the Main browser parts based on the OS type. 611#if defined(OS_WIN) 612 main_parts = new ChromeBrowserMainPartsWin(parameters); 613#elif defined(OS_MACOSX) 614 main_parts = new ChromeBrowserMainPartsMac(parameters); 615#elif defined(OS_CHROMEOS) 616 main_parts = new chromeos::ChromeBrowserMainPartsChromeos(parameters); 617#elif defined(OS_LINUX) 618 main_parts = new ChromeBrowserMainPartsLinux(parameters); 619#elif defined(OS_ANDROID) 620 main_parts = new ChromeBrowserMainPartsAndroid(parameters); 621#elif defined(OS_POSIX) 622 main_parts = new ChromeBrowserMainPartsPosix(parameters); 623#else 624 NOTREACHED(); 625 main_parts = new ChromeBrowserMainParts(parameters); 626#endif 627 628 chrome::AddProfilesExtraParts(main_parts); 629 630 // Construct additional browser parts. Stages are called in the order in 631 // which they are added. 632#if defined(TOOLKIT_GTK) 633 main_parts->AddParts(new ChromeBrowserMainExtraPartsGtk()); 634#endif 635 636#if defined(TOOLKIT_VIEWS) 637 main_parts->AddParts(new ChromeBrowserMainExtraPartsViews()); 638#endif 639 640#if defined(USE_ASH) 641 main_parts->AddParts(new ChromeBrowserMainExtraPartsAsh()); 642#endif 643 644#if defined(USE_AURA) 645 main_parts->AddParts(new ChromeBrowserMainExtraPartsAura()); 646#endif 647 648#if defined(USE_X11) 649 main_parts->AddParts(new ChromeBrowserMainExtraPartsX11()); 650#endif 651 652 chrome::AddMetricsExtraParts(main_parts); 653 654 return main_parts; 655} 656 657std::string ChromeContentBrowserClient::GetStoragePartitionIdForSite( 658 content::BrowserContext* browser_context, 659 const GURL& site) { 660 std::string partition_id; 661 662 // The partition ID for webview guest processes is the string value of its 663 // SiteInstance URL - "chrome-guest://app_id/persist?partition". 664 if (site.SchemeIs(chrome::kGuestScheme)) 665 partition_id = site.spec(); 666 667 DCHECK(IsValidStoragePartitionId(browser_context, partition_id)); 668 return partition_id; 669} 670 671bool ChromeContentBrowserClient::IsValidStoragePartitionId( 672 content::BrowserContext* browser_context, 673 const std::string& partition_id) { 674 // The default ID is empty and is always valid. 675 if (partition_id.empty()) 676 return true; 677 678 return GURL(partition_id).is_valid(); 679} 680 681void ChromeContentBrowserClient::GetStoragePartitionConfigForSite( 682 content::BrowserContext* browser_context, 683 const GURL& site, 684 bool can_be_default, 685 std::string* partition_domain, 686 std::string* partition_name, 687 bool* in_memory) { 688 // Default to the browser-wide storage partition and override based on |site| 689 // below. 690 partition_domain->clear(); 691 partition_name->clear(); 692 *in_memory = false; 693 694 // For the webview tag, we create special guest processes, which host the 695 // tag content separately from the main application that embeds the tag. 696 // A webview tag can specify both the partition name and whether the storage 697 // for that partition should be persisted. Each tag gets a SiteInstance with 698 // a specially formatted URL, based on the application it is hosted by and 699 // the partition requested by it. The format for that URL is: 700 // chrome-guest://partition_domain/persist?partition_name 701 if (site.SchemeIs(chrome::kGuestScheme)) { 702 // Since guest URLs are only used for packaged apps, there must be an app 703 // id in the URL. 704 CHECK(site.has_host()); 705 *partition_domain = site.host(); 706 // Since persistence is optional, the path must either be empty or the 707 // literal string. 708 *in_memory = (site.path() != "/persist"); 709 // The partition name is user supplied value, which we have encoded when the 710 // URL was created, so it needs to be decoded. 711 *partition_name = net::UnescapeURLComponent(site.query(), 712 net::UnescapeRule::NORMAL); 713 } else if (site.SchemeIs(extensions::kExtensionScheme)) { 714 // If |can_be_default| is false, the caller is stating that the |site| 715 // should be parsed as if it had isolated storage. In particular it is 716 // important to NOT check ExtensionService for the is_storage_isolated() 717 // attribute because this code path is run during Extension uninstall 718 // to do cleanup after the Extension has already been unloaded from the 719 // ExtensionService. 720 bool is_isolated = !can_be_default; 721 if (can_be_default) { 722 const Extension* extension = NULL; 723 Profile* profile = Profile::FromBrowserContext(browser_context); 724 ExtensionService* extension_service = 725 extensions::ExtensionSystem::Get(profile)->extension_service(); 726 if (extension_service) { 727 extension = 728 extension_service->extensions()->GetExtensionOrAppByURL(site); 729 if (extension && 730 extensions::AppIsolationInfo::HasIsolatedStorage(extension)) { 731 is_isolated = true; 732 } 733 } 734 } 735 736 if (is_isolated) { 737 CHECK(site.has_host()); 738 // For extensions with isolated storage, the the host of the |site| is 739 // the |partition_domain|. The |in_memory| and |partition_name| are only 740 // used in guest schemes so they are cleared here. 741 *partition_domain = site.host(); 742 *in_memory = false; 743 partition_name->clear(); 744 } 745 } 746 747 // Assert that if |can_be_default| is false, the code above must have found a 748 // non-default partition. If this fails, the caller has a serious logic 749 // error about which StoragePartition they expect to be in and it is not 750 // safe to continue. 751 CHECK(can_be_default || !partition_domain->empty()); 752} 753 754content::WebContentsViewDelegate* 755 ChromeContentBrowserClient::GetWebContentsViewDelegate( 756 content::WebContents* web_contents) { 757 return chrome::CreateWebContentsViewDelegate(web_contents); 758} 759 760void ChromeContentBrowserClient::GuestWebContentsCreated( 761 WebContents* guest_web_contents, 762 WebContents* opener_web_contents, 763 content::BrowserPluginGuestDelegate** guest_delegate, 764 scoped_ptr<base::DictionaryValue> extra_params) { 765 if (opener_web_contents) { 766 GuestView* guest = GuestView::FromWebContents(opener_web_contents); 767 if (!guest) { 768 NOTREACHED(); 769 return; 770 } 771 772 // Create a new GuestView of the same type as the opener. 773 *guest_delegate = 774 GuestView::Create(guest_web_contents, guest->GetViewType()); 775 return; 776 } 777 778 if (!extra_params) { 779 NOTREACHED(); 780 return; 781 } 782 std::string api_type; 783 extra_params->GetString(guestview::kParameterApi, &api_type); 784 785 *guest_delegate = 786 GuestView::Create(guest_web_contents, 787 GuestView::GetViewTypeFromString(api_type)); 788} 789 790void ChromeContentBrowserClient::GuestWebContentsAttached( 791 WebContents* guest_web_contents, 792 WebContents* embedder_web_contents, 793 const base::DictionaryValue& extra_params) { 794 Profile* profile = Profile::FromBrowserContext( 795 embedder_web_contents->GetBrowserContext()); 796 ExtensionService* service = 797 extensions::ExtensionSystem::Get(profile)->extension_service(); 798 if (!service) { 799 NOTREACHED(); 800 return; 801 } 802 const GURL& url = embedder_web_contents->GetSiteInstance()->GetSiteURL(); 803 const Extension* extension = 804 service->extensions()->GetExtensionOrAppByURL(url); 805 if (!extension) { 806 // It's ok to return here, since we could be running a browser plugin 807 // outside an extension, and don't need to attach a 808 // BrowserPluginGuestDelegate in that case; 809 // e.g. running with flag --enable-browser-plugin-for-all-view-types. 810 return; 811 } 812 813 GuestView* guest = GuestView::FromWebContents(guest_web_contents); 814 if (!guest) { 815 NOTREACHED(); 816 return; 817 } 818 guest->Attach(embedder_web_contents, extension->id(), extra_params); 819} 820 821void ChromeContentBrowserClient::RenderProcessHostCreated( 822 content::RenderProcessHost* host) { 823 int id = host->GetID(); 824 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 825 net::URLRequestContextGetter* context = 826 profile->GetRequestContextForRenderProcess(id); 827 828 host->GetChannel()->AddFilter(new ChromeRenderMessageFilter( 829 id, profile, context)); 830#if defined(ENABLE_PLUGINS) 831 host->GetChannel()->AddFilter(new PluginInfoMessageFilter(id, profile)); 832#endif 833#if defined(ENABLE_PRINTING) 834 host->GetChannel()->AddFilter(new PrintingMessageFilter(id, profile)); 835#endif 836 host->GetChannel()->AddFilter( 837 new SearchProviderInstallStateMessageFilter(id, profile)); 838#if defined(ENABLE_SPELLCHECK) 839 host->GetChannel()->AddFilter(new SpellCheckMessageFilter(id)); 840#endif 841#if defined(OS_MACOSX) 842 host->GetChannel()->AddFilter(new SpellCheckMessageFilterMac(id)); 843#endif 844 host->GetChannel()->AddFilter(new ChromeNetBenchmarkingMessageFilter( 845 id, profile, context)); 846 host->GetChannel()->AddFilter( 847 new prerender::PrerenderMessageFilter(id, profile)); 848 host->GetChannel()->AddFilter(new ValidationMessageMessageFilter(id)); 849 host->GetChannel()->AddFilter(new TtsMessageFilter(id, profile)); 850#if defined(ENABLE_WEBRTC) 851 host->GetChannel()->AddFilter(new WebRtcLoggingHandlerHost()); 852#endif 853#if !defined(DISABLE_NACL) 854 ExtensionInfoMap* extension_info_map = 855 extensions::ExtensionSystem::Get(profile)->info_map(); 856 host->GetChannel()->AddFilter(new NaClHostMessageFilter( 857 id, profile->IsOffTheRecord(), 858 profile->GetPath(), extension_info_map, 859 context)); 860#endif 861#if defined(OS_ANDROID) 862 host->GetChannel()->AddFilter(new EncryptedMediaMessageFilterAndroid()); 863#endif 864 865 host->Send(new ChromeViewMsg_SetIsIncognitoProcess( 866 profile->IsOffTheRecord())); 867 868 SendExtensionWebRequestStatusToHost(host); 869 870 RendererContentSettingRules rules; 871 GetRendererContentSettingRules(profile->GetHostContentSettingsMap(), &rules); 872 host->Send(new ChromeViewMsg_SetContentSettingRules(rules)); 873} 874 875GURL ChromeContentBrowserClient::GetEffectiveURL( 876 content::BrowserContext* browser_context, const GURL& url) { 877 Profile* profile = Profile::FromBrowserContext(browser_context); 878 if (!profile) 879 return url; 880 881 // If the input |url| should be assigned to the Instant renderer, make its 882 // effective URL distinct from other URLs on the search provider's domain. 883 if (chrome::ShouldAssignURLToInstantRenderer(url, profile)) 884 return chrome::GetEffectiveURLForInstant(url, profile); 885 886#if !defined(OS_CHROMEOS) 887 // If the input |url| should be assigned to the Signin renderer, make its 888 // effective URL distinct from other URLs on the signin service's domain. 889 // Note that the signin renderer will be allowed to sign the user in to 890 // Chrome. 891 if (SigninManager::IsWebBasedSigninFlowURL(url)) 892 return GetEffectiveURLForSignin(url); 893#endif 894 895 // If the input |url| is part of an installed app, the effective URL is an 896 // extension URL with the ID of that extension as the host. This has the 897 // effect of grouping apps together in a common SiteInstance. 898 ExtensionService* extension_service = 899 extensions::ExtensionSystem::Get(profile)->extension_service(); 900 if (!extension_service) 901 return url; 902 903 const Extension* extension = extension_service->extensions()-> 904 GetHostedAppByURL(url); 905 if (!extension) 906 return url; 907 908 // Bookmark apps do not use the hosted app process model, and should be 909 // treated as normal URLs. 910 if (extension->from_bookmark()) 911 return url; 912 913 // If the URL is part of an extension's web extent, convert it to an 914 // extension URL. 915 return extension->GetResourceURL(url.path()); 916} 917 918bool ChromeContentBrowserClient::ShouldUseProcessPerSite( 919 content::BrowserContext* browser_context, const GURL& effective_url) { 920 // Non-extension, non-Instant URLs should generally use 921 // process-per-site-instance. Because we expect to use the effective URL, 922 // URLs for hosted apps (apart from bookmark apps) should have an extension 923 // scheme by now. 924 925 Profile* profile = Profile::FromBrowserContext(browser_context); 926 if (!profile) 927 return false; 928 929 if (chrome::ShouldUseProcessPerSiteForInstantURL(effective_url, profile)) 930 return true; 931 932#if !defined(OS_CHROMEOS) 933 if (SigninManager::IsWebBasedSigninFlowURL(effective_url)) 934 return true; 935#endif 936 937 if (!effective_url.SchemeIs(extensions::kExtensionScheme)) 938 return false; 939 940 ExtensionService* extension_service = 941 extensions::ExtensionSystem::Get(profile)->extension_service(); 942 if (!extension_service) 943 return false; 944 945 const Extension* extension = 946 extension_service->extensions()->GetExtensionOrAppByURL(effective_url); 947 if (!extension) 948 return false; 949 950 // If the URL is part of a hosted app that does not have the background 951 // permission, or that does not allow JavaScript access to the background 952 // page, we want to give each instance its own process to improve 953 // responsiveness. 954 if (extension->GetType() == Manifest::TYPE_HOSTED_APP) { 955 if (!extension->HasAPIPermission(APIPermission::kBackground) || 956 !extensions::BackgroundInfo::AllowJSAccess(extension)) { 957 return false; 958 } 959 } 960 961 // Hosted apps that have script access to their background page must use 962 // process per site, since all instances can make synchronous calls to the 963 // background window. Other extensions should use process per site as well. 964 return true; 965} 966 967// These are treated as WebUI schemes but do not get WebUI bindings. 968void ChromeContentBrowserClient::GetAdditionalWebUISchemes( 969 std::vector<std::string>* additional_schemes) { 970 additional_schemes->push_back(chrome::kChromeSearchScheme); 971} 972 973net::URLRequestContextGetter* 974ChromeContentBrowserClient::CreateRequestContext( 975 content::BrowserContext* browser_context, 976 content::ProtocolHandlerMap* protocol_handlers) { 977 Profile* profile = Profile::FromBrowserContext(browser_context); 978 return profile->CreateRequestContext(protocol_handlers); 979} 980 981net::URLRequestContextGetter* 982ChromeContentBrowserClient::CreateRequestContextForStoragePartition( 983 content::BrowserContext* browser_context, 984 const base::FilePath& partition_path, 985 bool in_memory, 986 content::ProtocolHandlerMap* protocol_handlers) { 987 Profile* profile = Profile::FromBrowserContext(browser_context); 988 return profile->CreateRequestContextForStoragePartition( 989 partition_path, in_memory, protocol_handlers); 990} 991 992bool ChromeContentBrowserClient::IsHandledURL(const GURL& url) { 993 return ProfileIOData::IsHandledURL(url); 994} 995 996bool ChromeContentBrowserClient::CanCommitURL( 997 content::RenderProcessHost* process_host, 998 const GURL& url) { 999 // We need to let most extension URLs commit in any process, since this can 1000 // be allowed due to web_accessible_resources. Most hosted app URLs may also 1001 // load in any process (e.g., in an iframe). However, the Chrome Web Store 1002 // cannot be loaded in iframes and should never be requested outside its 1003 // process. 1004 Profile* profile = 1005 Profile::FromBrowserContext(process_host->GetBrowserContext()); 1006 ExtensionService* service = 1007 extensions::ExtensionSystem::Get(profile)->extension_service(); 1008 if (!service) 1009 return true; 1010 const Extension* new_extension = 1011 service->extensions()->GetExtensionOrAppByURL(url); 1012 if (new_extension && 1013 new_extension->is_hosted_app() && 1014 new_extension->id() == extension_misc::kWebStoreAppId && 1015 !service->process_map()->Contains(new_extension->id(), 1016 process_host->GetID())) { 1017 return false; 1018 } 1019 1020 return true; 1021} 1022 1023bool ChromeContentBrowserClient::ShouldAllowOpenURL( 1024 content::SiteInstance* site_instance, const GURL& url) { 1025 GURL from_url = site_instance->GetSiteURL(); 1026 // Do not allow pages from the web or other extensions navigate to 1027 // non-web-accessible extension resources. 1028 if (url.SchemeIs(extensions::kExtensionScheme) && 1029 (from_url.SchemeIsHTTPOrHTTPS() || 1030 from_url.SchemeIs(extensions::kExtensionScheme))) { 1031 Profile* profile = Profile::FromBrowserContext( 1032 site_instance->GetProcess()->GetBrowserContext()); 1033 ExtensionService* service = 1034 extensions::ExtensionSystem::Get(profile)->extension_service(); 1035 if (!service) 1036 return true; 1037 const Extension* extension = 1038 service->extensions()->GetExtensionOrAppByURL(url); 1039 if (!extension) 1040 return true; 1041 const Extension* from_extension = 1042 service->extensions()->GetExtensionOrAppByURL( 1043 site_instance->GetSiteURL()); 1044 if (from_extension && from_extension->id() == extension->id()) 1045 return true; 1046 1047 if (!extensions::WebAccessibleResourcesInfo::IsResourceWebAccessible( 1048 extension, url.path())) 1049 return false; 1050 } 1051 return true; 1052} 1053 1054bool ChromeContentBrowserClient::IsSuitableHost( 1055 content::RenderProcessHost* process_host, 1056 const GURL& site_url) { 1057 Profile* profile = 1058 Profile::FromBrowserContext(process_host->GetBrowserContext()); 1059 // This may be NULL during tests. In that case, just assume any site can 1060 // share any host. 1061 if (!profile) 1062 return true; 1063 1064 // Instant URLs should only be in the instant process and instant process 1065 // should only have Instant URLs. 1066 InstantService* instant_service = 1067 InstantServiceFactory::GetForProfile(profile); 1068 if (instant_service) { 1069 bool is_instant_process = instant_service->IsInstantProcess( 1070 process_host->GetID()); 1071 bool should_be_in_instant_process = 1072 chrome::ShouldAssignURLToInstantRenderer(site_url, profile); 1073 if (is_instant_process || should_be_in_instant_process) 1074 return is_instant_process && should_be_in_instant_process; 1075 } 1076 1077#if !defined(OS_CHROMEOS) 1078 SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile); 1079 if (signin_manager && signin_manager->IsSigninProcess(process_host->GetID())) 1080 return SigninManager::IsWebBasedSigninFlowURL(site_url); 1081#endif 1082 1083 ExtensionService* service = 1084 extensions::ExtensionSystem::Get(profile)->extension_service(); 1085 extensions::ProcessMap* process_map = service->process_map(); 1086 1087 // Don't allow the Task Manager to share a process with anything else. 1088 // Otherwise it can affect the renderers it is observing. 1089 // Note: we could create another RenderProcessHostPrivilege bucket for 1090 // this to allow multiple chrome://tasks instances to share, but that's 1091 // a very unlikely case without serious consequences. 1092 if (site_url.GetOrigin() == GURL(chrome::kChromeUITaskManagerURL).GetOrigin()) 1093 return false; 1094 1095 // These may be NULL during tests. In that case, just assume any site can 1096 // share any host. 1097 if (!service || !process_map) 1098 return true; 1099 1100 // Otherwise, just make sure the process privilege matches the privilege 1101 // required by the site. 1102 RenderProcessHostPrivilege privilege_required = 1103 GetPrivilegeRequiredByUrl(site_url, service); 1104 return GetProcessPrivilege(process_host, process_map, service) == 1105 privilege_required; 1106} 1107 1108// This function is trying to limit the amount of processes used by extensions 1109// with background pages. It uses a globally set percentage of processes to 1110// run such extensions and if the limit is exceeded, it returns true, to 1111// indicate to the content module to group extensions together. 1112bool ChromeContentBrowserClient::ShouldTryToUseExistingProcessHost( 1113 content::BrowserContext* browser_context, const GURL& url) { 1114 // It has to be a valid URL for us to check for an extension. 1115 if (!url.is_valid()) 1116 return false; 1117 1118 Profile* profile = Profile::FromBrowserContext(browser_context); 1119 ExtensionService* service = !profile ? NULL : 1120 extensions::ExtensionSystem::Get(profile)->extension_service(); 1121 if (!service) 1122 return false; 1123 1124 // We have to have a valid extension with background page to proceed. 1125 const Extension* extension = 1126 service->extensions()->GetExtensionOrAppByURL(url); 1127 if (!extension) 1128 return false; 1129 if (!extensions::BackgroundInfo::HasBackgroundPage(extension)) 1130 return false; 1131 1132 std::set<int> process_ids; 1133 size_t max_process_count = 1134 content::RenderProcessHost::GetMaxRendererProcessCount(); 1135 1136 // Go through all profiles to ensure we have total count of extension 1137 // processes containing background pages, otherwise one profile can 1138 // starve the other. 1139 std::vector<Profile*> profiles = g_browser_process->profile_manager()-> 1140 GetLoadedProfiles(); 1141 for (size_t i = 0; i < profiles.size(); ++i) { 1142 ExtensionProcessManager* epm = 1143 extensions::ExtensionSystem::Get(profiles[i])->process_manager(); 1144 for (ExtensionProcessManager::const_iterator iter = 1145 epm->background_hosts().begin(); 1146 iter != epm->background_hosts().end(); ++iter) { 1147 const extensions::ExtensionHost* host = *iter; 1148 process_ids.insert(host->render_process_host()->GetID()); 1149 } 1150 } 1151 1152 if (process_ids.size() > 1153 (max_process_count * chrome::kMaxShareOfExtensionProcesses)) { 1154 return true; 1155 } 1156 1157 return false; 1158} 1159 1160void ChromeContentBrowserClient::SiteInstanceGotProcess( 1161 SiteInstance* site_instance) { 1162 CHECK(site_instance->HasProcess()); 1163 1164 Profile* profile = Profile::FromBrowserContext( 1165 site_instance->GetBrowserContext()); 1166 if (!profile) 1167 return; 1168 1169 // Remember the ID of the Instant process to signal the renderer process 1170 // on startup in |AppendExtraCommandLineSwitches| below. 1171 if (chrome::ShouldAssignURLToInstantRenderer( 1172 site_instance->GetSiteURL(), profile)) { 1173 InstantService* instant_service = 1174 InstantServiceFactory::GetForProfile(profile); 1175 if (instant_service) 1176 instant_service->AddInstantProcess(site_instance->GetProcess()->GetID()); 1177 } 1178 1179#if !defined(OS_CHROMEOS) 1180 // We only expect there to be one signin process as we use process-per-site 1181 // for signin URLs. The signin process will be cleared from SigninManager 1182 // when the renderer is destroyed. 1183 if (SigninManager::IsWebBasedSigninFlowURL(site_instance->GetSiteURL())) { 1184 SigninManager* signin_manager = 1185 SigninManagerFactory::GetForProfile(profile); 1186 if (signin_manager) 1187 signin_manager->SetSigninProcess(site_instance->GetProcess()->GetID()); 1188 BrowserThread::PostTask( 1189 BrowserThread::IO, FROM_HERE, 1190 base::Bind(&ExtensionInfoMap::SetSigninProcess, 1191 extensions::ExtensionSystem::Get(profile)->info_map(), 1192 site_instance->GetProcess()->GetID())); 1193 } 1194#endif 1195 1196 ExtensionService* service = 1197 extensions::ExtensionSystem::Get(profile)->extension_service(); 1198 if (!service) 1199 return; 1200 1201 const Extension* extension = service->extensions()->GetExtensionOrAppByURL( 1202 site_instance->GetSiteURL()); 1203 if (!extension) 1204 return; 1205 1206 service->process_map()->Insert(extension->id(), 1207 site_instance->GetProcess()->GetID(), 1208 site_instance->GetId()); 1209 BrowserThread::PostTask( 1210 BrowserThread::IO, FROM_HERE, 1211 base::Bind(&ExtensionInfoMap::RegisterExtensionProcess, 1212 extensions::ExtensionSystem::Get(profile)->info_map(), 1213 extension->id(), 1214 site_instance->GetProcess()->GetID(), 1215 site_instance->GetId())); 1216} 1217 1218void ChromeContentBrowserClient::SiteInstanceDeleting( 1219 SiteInstance* site_instance) { 1220 if (!site_instance->HasProcess()) 1221 return; 1222 1223 Profile* profile = Profile::FromBrowserContext( 1224 site_instance->GetBrowserContext()); 1225 ExtensionService* service = 1226 extensions::ExtensionSystem::Get(profile)->extension_service(); 1227 if (!service) 1228 return; 1229 1230 const Extension* extension = service->extensions()->GetExtensionOrAppByURL( 1231 site_instance->GetSiteURL()); 1232 if (!extension) 1233 return; 1234 1235 service->process_map()->Remove(extension->id(), 1236 site_instance->GetProcess()->GetID(), 1237 site_instance->GetId()); 1238 BrowserThread::PostTask( 1239 BrowserThread::IO, FROM_HERE, 1240 base::Bind(&ExtensionInfoMap::UnregisterExtensionProcess, 1241 extensions::ExtensionSystem::Get(profile)->info_map(), 1242 extension->id(), 1243 site_instance->GetProcess()->GetID(), 1244 site_instance->GetId())); 1245} 1246 1247bool ChromeContentBrowserClient::ShouldSwapProcessesForNavigation( 1248 SiteInstance* site_instance, 1249 const GURL& current_url, 1250 const GURL& new_url) { 1251 if (current_url.is_empty()) { 1252 // Always choose a new process when navigating to extension URLs. The 1253 // process grouping logic will combine all of a given extension's pages 1254 // into the same process. 1255 if (new_url.SchemeIs(extensions::kExtensionScheme)) 1256 return true; 1257 1258 return false; 1259 } 1260 1261 // Also, we must switch if one is an extension and the other is not the exact 1262 // same extension. 1263 if (current_url.SchemeIs(extensions::kExtensionScheme) || 1264 new_url.SchemeIs(extensions::kExtensionScheme)) { 1265 if (current_url.GetOrigin() != new_url.GetOrigin()) 1266 return true; 1267 } 1268 1269 // The checks below only matter if we can retrieve which extensions are 1270 // installed. 1271 Profile* profile = 1272 Profile::FromBrowserContext(site_instance->GetBrowserContext()); 1273 ExtensionService* service = 1274 extensions::ExtensionSystem::Get(profile)->extension_service(); 1275 if (!service) 1276 return false; 1277 1278 // We must swap if the URL is for an extension and we are not using an 1279 // extension process. 1280 const Extension* new_extension = 1281 service->extensions()->GetExtensionOrAppByURL(new_url); 1282 // Ignore all hosted apps except the Chrome Web Store, since they do not 1283 // require their own BrowsingInstance (e.g., postMessage is ok). 1284 if (new_extension && 1285 new_extension->is_hosted_app() && 1286 new_extension->id() != extension_misc::kWebStoreAppId) 1287 new_extension = NULL; 1288 if (new_extension && 1289 site_instance->HasProcess() && 1290 !service->process_map()->Contains(new_extension->id(), 1291 site_instance->GetProcess()->GetID())) 1292 return true; 1293 1294 return false; 1295} 1296 1297bool ChromeContentBrowserClient::ShouldSwapProcessesForRedirect( 1298 content::ResourceContext* resource_context, const GURL& current_url, 1299 const GURL& new_url) { 1300 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context); 1301 return extensions::CrossesExtensionProcessBoundary( 1302 io_data->GetExtensionInfoMap()->extensions(), 1303 current_url, new_url, false); 1304} 1305 1306bool ChromeContentBrowserClient::ShouldAssignSiteForURL(const GURL& url) { 1307 return !url.SchemeIs(chrome::kChromeNativeScheme); 1308} 1309 1310std::string ChromeContentBrowserClient::GetCanonicalEncodingNameByAliasName( 1311 const std::string& alias_name) { 1312 return CharacterEncoding::GetCanonicalEncodingNameByAliasName(alias_name); 1313} 1314 1315void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( 1316 CommandLine* command_line, int child_process_id) { 1317#if defined(OS_MACOSX) 1318 if (IsCrashReporterEnabled()) { 1319 command_line->AppendSwitchASCII(switches::kEnableCrashReporter, 1320 child_process_logging::GetClientId()); 1321 } 1322#elif defined(OS_POSIX) 1323 if (IsCrashReporterEnabled()) { 1324 command_line->AppendSwitchASCII(switches::kEnableCrashReporter, 1325 child_process_logging::GetClientId() + "," + base::GetLinuxDistro()); 1326 } 1327 1328#endif // OS_MACOSX 1329 1330 if (logging::DialogsAreSuppressed()) 1331 command_line->AppendSwitch(switches::kNoErrorDialogs); 1332 1333 std::string process_type = 1334 command_line->GetSwitchValueASCII(switches::kProcessType); 1335 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 1336 1337 static const char* const kCommonSwitchNames[] = { 1338 switches::kChromeFrame, 1339 switches::kUserDataDir, // Make logs go to the right file. 1340 }; 1341 command_line->CopySwitchesFrom(browser_command_line, kCommonSwitchNames, 1342 arraysize(kCommonSwitchNames)); 1343 1344 if (process_type == switches::kRendererProcess) { 1345#if defined(OS_CHROMEOS) 1346 const std::string& login_profile = 1347 browser_command_line.GetSwitchValueASCII( 1348 chromeos::switches::kLoginProfile); 1349 if (!login_profile.empty()) 1350 command_line->AppendSwitchASCII( 1351 chromeos::switches::kLoginProfile, login_profile); 1352#endif 1353 1354 content::RenderProcessHost* process = 1355 content::RenderProcessHost::FromID(child_process_id); 1356 if (process) { 1357 Profile* profile = Profile::FromBrowserContext( 1358 process->GetBrowserContext()); 1359 ExtensionService* extension_service = 1360 extensions::ExtensionSystem::Get(profile)->extension_service(); 1361 if (extension_service) { 1362 extensions::ProcessMap* process_map = extension_service->process_map(); 1363 if (process_map && process_map->Contains(process->GetID())) 1364 command_line->AppendSwitch(switches::kExtensionProcess); 1365 } 1366 1367 PrefService* prefs = profile->GetPrefs(); 1368 // Currently this pref is only registered if applied via a policy. 1369 if (prefs->HasPrefPath(prefs::kDisable3DAPIs) && 1370 prefs->GetBoolean(prefs::kDisable3DAPIs)) { 1371 // Turn this policy into a command line switch. 1372 command_line->AppendSwitch(switches::kDisable3DAPIs); 1373 } 1374 1375 // Disable client-side phishing detection in the renderer if it is 1376 // disabled in the Profile preferences or the browser process. 1377 if (!prefs->GetBoolean(prefs::kSafeBrowsingEnabled) || 1378 !g_browser_process->safe_browsing_detection_service()) { 1379 command_line->AppendSwitch( 1380 switches::kDisableClientSidePhishingDetection); 1381 } 1382 1383 if (!prefs->GetBoolean(prefs::kPrintPreviewDisabled)) 1384 command_line->AppendSwitch(switches::kRendererPrintPreview); 1385 1386 InstantService* instant_service = 1387 InstantServiceFactory::GetForProfile(profile); 1388 if (instant_service && 1389 instant_service->IsInstantProcess(process->GetID())) 1390 command_line->AppendSwitch(switches::kInstantProcess); 1391 1392#if !defined(OS_CHROMEOS) 1393 SigninManager* signin_manager = 1394 SigninManagerFactory::GetForProfile(profile); 1395 if (signin_manager && signin_manager->IsSigninProcess(process->GetID())) 1396 command_line->AppendSwitch(switches::kSigninProcess); 1397#endif 1398 } 1399 1400 if (message_center::IsRichNotificationEnabled()) 1401 command_line->AppendSwitch(switches::kDisableHTMLNotifications); 1402 1403 // Please keep this in alphabetical order. 1404 static const char* const kSwitchNames[] = { 1405 autofill::switches::kDisableInteractiveAutocomplete, 1406 autofill::switches::kEnableExperimentalFormFilling, 1407 autofill::switches::kEnableInteractiveAutocomplete, 1408 extensions::switches::kAllowLegacyExtensionManifests, 1409 extensions::switches::kAllowScriptingGallery, 1410 extensions::switches::kEnableExperimentalExtensionApis, 1411 extensions::switches::kExtensionsOnChromeURLs, 1412 switches::kAllowHTTPBackgroundPage, 1413 // TODO(victorhsieh): remove the following flag once we move PPAPI FileIO 1414 // to browser. 1415 switches::kAllowNaClFileHandleAPI, 1416 switches::kAppsCheckoutURL, 1417 switches::kAppsGalleryURL, 1418 switches::kCloudPrintServiceURL, 1419 switches::kDebugPrint, 1420 switches::kDisableBundledPpapiFlash, 1421 switches::kDisableExtensionsResourceWhitelist, 1422 switches::kDisablePnacl, 1423 switches::kDisableScriptedPrintThrottling, 1424 switches::kEnableAdview, 1425 switches::kEnableAdviewSrcAttribute, 1426 switches::kEnableAppWindowControls, 1427 switches::kEnableBenchmarking, 1428 switches::kEnableIPCFuzzing, 1429 switches::kEnableNaCl, 1430 switches::kEnableNetBenchmarking, 1431 switches::kEnablePasswordGeneration, 1432 switches::kEnableWatchdog, 1433 switches::kMemoryProfiling, 1434 switches::kMessageLoopHistogrammer, 1435 switches::kNoJsRandomness, 1436 switches::kPlaybackMode, 1437 switches::kPpapiFlashArgs, 1438 switches::kPpapiFlashInProcess, 1439 switches::kPpapiFlashPath, 1440 switches::kPpapiFlashVersion, 1441 switches::kProfilingAtStart, 1442 switches::kProfilingFile, 1443 switches::kProfilingFlush, 1444 switches::kRecordMode, 1445 switches::kSilentDumpOnDCHECK, 1446 switches::kSpdyProxyAuthOrigin, 1447 switches::kTranslateSecurityOrigin, 1448 switches::kWhitelistedExtensionID, 1449 }; 1450 1451 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 1452 arraysize(kSwitchNames)); 1453 } else if (process_type == switches::kUtilityProcess) { 1454 static const char* const kSwitchNames[] = { 1455 extensions::switches::kEnableExperimentalExtensionApis, 1456 extensions::switches::kExtensionsOnChromeURLs, 1457 switches::kAllowHTTPBackgroundPage, 1458 switches::kWhitelistedExtensionID, 1459 }; 1460 1461 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 1462 arraysize(kSwitchNames)); 1463 } else if (process_type == switches::kPluginProcess) { 1464 static const char* const kSwitchNames[] = { 1465#if defined(OS_CHROMEOS) 1466 chromeos::switches::kLoginProfile, 1467#endif 1468 switches::kMemoryProfiling, 1469 switches::kSilentDumpOnDCHECK, 1470 }; 1471 1472 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 1473 arraysize(kSwitchNames)); 1474 } else if (process_type == switches::kZygoteProcess) { 1475 static const char* const kSwitchNames[] = { 1476 // Load (in-process) Pepper plugins in-process in the zygote pre-sandbox. 1477 switches::kDisableBundledPpapiFlash, 1478 switches::kPpapiFlashInProcess, 1479 switches::kPpapiFlashPath, 1480 switches::kPpapiFlashVersion, 1481 }; 1482 1483 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 1484 arraysize(kSwitchNames)); 1485 } else if (process_type == switches::kGpuProcess) { 1486 // If --ignore-gpu-blacklist is passed in, don't send in crash reports 1487 // because GPU is expected to be unreliable. 1488 if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && 1489 !command_line->HasSwitch(switches::kDisableBreakpad)) 1490 command_line->AppendSwitch(switches::kDisableBreakpad); 1491 } 1492 1493 // The command line switch kEnableBenchmarking needs to be specified along 1494 // with the kEnableStatsTable switch to ensure that the stats table global 1495 // is initialized correctly. 1496 if (command_line->HasSwitch(switches::kEnableBenchmarking)) 1497 DCHECK(command_line->HasSwitch(switches::kEnableStatsTable)); 1498} 1499 1500std::string ChromeContentBrowserClient::GetApplicationLocale() { 1501 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) 1502 return g_io_thread_application_locale.Get(); 1503 return g_browser_process->GetApplicationLocale(); 1504} 1505 1506std::string ChromeContentBrowserClient::GetAcceptLangs( 1507 content::BrowserContext* context) { 1508 Profile* profile = Profile::FromBrowserContext(context); 1509 return profile->GetPrefs()->GetString(prefs::kAcceptLanguages); 1510} 1511 1512gfx::ImageSkia* ChromeContentBrowserClient::GetDefaultFavicon() { 1513 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1514 return rb.GetImageSkiaNamed(IDR_DEFAULT_FAVICON); 1515} 1516 1517bool ChromeContentBrowserClient::AllowAppCache( 1518 const GURL& manifest_url, 1519 const GURL& first_party, 1520 content::ResourceContext* context) { 1521 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1522 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1523 return io_data->GetCookieSettings()-> 1524 IsSettingCookieAllowed(manifest_url, first_party); 1525} 1526 1527bool ChromeContentBrowserClient::AllowGetCookie( 1528 const GURL& url, 1529 const GURL& first_party, 1530 const net::CookieList& cookie_list, 1531 content::ResourceContext* context, 1532 int render_process_id, 1533 int render_view_id) { 1534 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1535 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1536 bool allow = io_data->GetCookieSettings()-> 1537 IsReadingCookieAllowed(url, first_party); 1538 1539 BrowserThread::PostTask( 1540 BrowserThread::UI, FROM_HERE, 1541 base::Bind(&TabSpecificContentSettings::CookiesRead, render_process_id, 1542 render_view_id, url, first_party, cookie_list, !allow)); 1543 return allow; 1544} 1545 1546bool ChromeContentBrowserClient::AllowSetCookie( 1547 const GURL& url, 1548 const GURL& first_party, 1549 const std::string& cookie_line, 1550 content::ResourceContext* context, 1551 int render_process_id, 1552 int render_view_id, 1553 net::CookieOptions* options) { 1554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1555 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1556 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1557 bool allow = cookie_settings->IsSettingCookieAllowed(url, first_party); 1558 1559 BrowserThread::PostTask( 1560 BrowserThread::UI, FROM_HERE, 1561 base::Bind(&TabSpecificContentSettings::CookieChanged, render_process_id, 1562 render_view_id, url, first_party, cookie_line, *options, 1563 !allow)); 1564 return allow; 1565} 1566 1567bool ChromeContentBrowserClient::AllowSaveLocalState( 1568 content::ResourceContext* context) { 1569 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1570 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1571 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1572 ContentSetting setting = cookie_settings->GetDefaultCookieSetting(NULL); 1573 1574 // TODO(bauerb): Should we also disallow local state if the default is BLOCK? 1575 // Could we even support per-origin settings? 1576 return setting != CONTENT_SETTING_SESSION_ONLY; 1577} 1578 1579bool ChromeContentBrowserClient::AllowWorkerDatabase( 1580 const GURL& url, 1581 const string16& name, 1582 const string16& display_name, 1583 unsigned long estimated_size, 1584 content::ResourceContext* context, 1585 const std::vector<std::pair<int, int> >& render_views) { 1586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1587 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1588 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1589 bool allow = cookie_settings->IsSettingCookieAllowed(url, url); 1590 1591 // Record access to database for potential display in UI. 1592 std::vector<std::pair<int, int> >::const_iterator i; 1593 for (i = render_views.begin(); i != render_views.end(); ++i) { 1594 BrowserThread::PostTask( 1595 BrowserThread::UI, FROM_HERE, 1596 base::Bind(&TabSpecificContentSettings::WebDatabaseAccessed, 1597 i->first, i->second, url, name, display_name, !allow)); 1598 } 1599 1600 return allow; 1601} 1602 1603bool ChromeContentBrowserClient::AllowWorkerFileSystem( 1604 const GURL& url, 1605 content::ResourceContext* context, 1606 const std::vector<std::pair<int, int> >& render_views) { 1607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1608 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1609 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1610 bool allow = cookie_settings->IsSettingCookieAllowed(url, url); 1611 1612 // Record access to file system for potential display in UI. 1613 std::vector<std::pair<int, int> >::const_iterator i; 1614 for (i = render_views.begin(); i != render_views.end(); ++i) { 1615 BrowserThread::PostTask( 1616 BrowserThread::UI, FROM_HERE, 1617 base::Bind(&TabSpecificContentSettings::FileSystemAccessed, 1618 i->first, i->second, url, !allow)); 1619 } 1620 1621 return allow; 1622} 1623 1624bool ChromeContentBrowserClient::AllowWorkerIndexedDB( 1625 const GURL& url, 1626 const string16& name, 1627 content::ResourceContext* context, 1628 const std::vector<std::pair<int, int> >& render_views) { 1629 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1630 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1631 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1632 bool allow = cookie_settings->IsSettingCookieAllowed(url, url); 1633 1634 // Record access to IndexedDB for potential display in UI. 1635 std::vector<std::pair<int, int> >::const_iterator i; 1636 for (i = render_views.begin(); i != render_views.end(); ++i) { 1637 BrowserThread::PostTask( 1638 BrowserThread::UI, FROM_HERE, 1639 base::Bind(&TabSpecificContentSettings::IndexedDBAccessed, 1640 i->first, i->second, url, name, !allow)); 1641 } 1642 1643 return allow; 1644} 1645 1646net::URLRequestContext* 1647ChromeContentBrowserClient::OverrideRequestContextForURL( 1648 const GURL& url, content::ResourceContext* context) { 1649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1650 if (url.SchemeIs(extensions::kExtensionScheme)) { 1651 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1652 return io_data->extensions_request_context(); 1653 } 1654 1655 return NULL; 1656} 1657 1658QuotaPermissionContext* 1659ChromeContentBrowserClient::CreateQuotaPermissionContext() { 1660 return new ChromeQuotaPermissionContext(); 1661} 1662 1663void ChromeContentBrowserClient::AllowCertificateError( 1664 int render_process_id, 1665 int render_view_id, 1666 int cert_error, 1667 const net::SSLInfo& ssl_info, 1668 const GURL& request_url, 1669 ResourceType::Type resource_type, 1670 bool overridable, 1671 bool strict_enforcement, 1672 const base::Callback<void(bool)>& callback, 1673 content::CertificateRequestResultType* result) { 1674 if (resource_type != ResourceType::MAIN_FRAME) { 1675 // A sub-resource has a certificate error. The user doesn't really 1676 // have a context for making the right decision, so block the 1677 // request hard, without an info bar to allow showing the insecure 1678 // content. 1679 *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY; 1680 return; 1681 } 1682 1683 // If the tab is being prerendered, cancel the prerender and the request. 1684 WebContents* tab = tab_util::GetWebContentsByID( 1685 render_process_id, render_view_id); 1686 if (!tab) { 1687 NOTREACHED(); 1688 return; 1689 } 1690 prerender::PrerenderManager* prerender_manager = 1691 prerender::PrerenderManagerFactory::GetForProfile( 1692 Profile::FromBrowserContext(tab->GetBrowserContext())); 1693 if (prerender_manager && prerender_manager->IsWebContentsPrerendering(tab, 1694 NULL)) { 1695 if (prerender_manager->prerender_tracker()->TryCancel( 1696 render_process_id, render_view_id, 1697 prerender::FINAL_STATUS_SSL_ERROR)) { 1698 *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL; 1699 return; 1700 } 1701 } 1702 1703#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 1704 captive_portal::CaptivePortalTabHelper* captive_portal_tab_helper = 1705 captive_portal::CaptivePortalTabHelper::FromWebContents(tab); 1706 if (captive_portal_tab_helper) 1707 captive_portal_tab_helper->OnSSLCertError(ssl_info); 1708#endif 1709 1710 // Otherwise, display an SSL blocking page. 1711 new SSLBlockingPage(tab, cert_error, ssl_info, request_url, overridable, 1712 strict_enforcement, callback); 1713} 1714 1715void ChromeContentBrowserClient::SelectClientCertificate( 1716 int render_process_id, 1717 int render_view_id, 1718 const net::HttpNetworkSession* network_session, 1719 net::SSLCertRequestInfo* cert_request_info, 1720 const base::Callback<void(net::X509Certificate*)>& callback) { 1721 WebContents* tab = tab_util::GetWebContentsByID( 1722 render_process_id, render_view_id); 1723 if (!tab) { 1724 NOTREACHED(); 1725 return; 1726 } 1727 1728 GURL requesting_url("https://" + cert_request_info->host_and_port); 1729 DCHECK(requesting_url.is_valid()) << "Invalid URL string: https://" 1730 << cert_request_info->host_and_port; 1731 1732 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); 1733 scoped_ptr<Value> filter( 1734 profile->GetHostContentSettingsMap()->GetWebsiteSetting( 1735 requesting_url, 1736 requesting_url, 1737 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 1738 std::string(), NULL)); 1739 1740 if (filter.get()) { 1741 // Try to automatically select a client certificate. 1742 if (filter->IsType(Value::TYPE_DICTIONARY)) { 1743 DictionaryValue* filter_dict = 1744 static_cast<DictionaryValue*>(filter.get()); 1745 1746 const std::vector<scoped_refptr<net::X509Certificate> >& 1747 all_client_certs = cert_request_info->client_certs; 1748 for (size_t i = 0; i < all_client_certs.size(); ++i) { 1749 if (CertMatchesFilter(*all_client_certs[i].get(), *filter_dict)) { 1750 // Use the first certificate that is matched by the filter. 1751 callback.Run(all_client_certs[i].get()); 1752 return; 1753 } 1754 } 1755 } else { 1756 NOTREACHED(); 1757 } 1758 } 1759 1760 SSLTabHelper* ssl_tab_helper = SSLTabHelper::FromWebContents(tab); 1761 if (!ssl_tab_helper) { 1762 // If there is no SSLTabHelper for the given WebContents then we can't 1763 // show the user a dialog to select a client certificate. So we simply 1764 // proceed with no client certificate. 1765 callback.Run(NULL); 1766 return; 1767 } 1768 ssl_tab_helper->ShowClientCertificateRequestDialog( 1769 network_session, cert_request_info, callback); 1770} 1771 1772void ChromeContentBrowserClient::AddCertificate( 1773 net::URLRequest* request, 1774 net::CertificateMimeType cert_type, 1775 const void* cert_data, 1776 size_t cert_size, 1777 int render_process_id, 1778 int render_view_id) { 1779 chrome::SSLAddCertificate(request, cert_type, cert_data, cert_size, 1780 render_process_id, render_view_id); 1781} 1782 1783content::MediaObserver* ChromeContentBrowserClient::GetMediaObserver() { 1784 return MediaCaptureDevicesDispatcher::GetInstance(); 1785} 1786 1787void ChromeContentBrowserClient::RequestDesktopNotificationPermission( 1788 const GURL& source_origin, 1789 int callback_context, 1790 int render_process_id, 1791 int render_view_id) { 1792#if defined(ENABLE_NOTIFICATIONS) 1793 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1794 WebContents* contents = 1795 tab_util::GetWebContentsByID(render_process_id, render_view_id); 1796 if (!contents) { 1797 NOTREACHED(); 1798 return; 1799 } 1800 1801 // Skip showing the infobar if the request comes from an extension, and that 1802 // extension has the 'notify' permission. (If the extension does not have the 1803 // permission, the user will still be prompted.) 1804 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 1805 ExtensionInfoMap* extension_info_map = 1806 extensions::ExtensionSystem::Get(profile)->info_map(); 1807 DesktopNotificationService* notification_service = 1808 DesktopNotificationServiceFactory::GetForProfile(profile); 1809 const Extension* extension = NULL; 1810 if (extension_info_map) { 1811 ExtensionSet extensions; 1812 extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin( 1813 source_origin, render_process_id, 1814 extensions::APIPermission::kNotification, &extensions); 1815 for (ExtensionSet::const_iterator iter = extensions.begin(); 1816 iter != extensions.end(); ++iter) { 1817 if (notification_service->IsNotifierEnabled(NotifierId( 1818 NotifierId::APPLICATION, (*iter)->id()))) { 1819 extension = iter->get(); 1820 break; 1821 } 1822 } 1823 } 1824 RenderViewHost* rvh = 1825 RenderViewHost::FromID(render_process_id, render_view_id); 1826 if (IsExtensionWithPermissionOrSuggestInConsole( 1827 APIPermission::kNotification, extension, rvh)) { 1828 if (rvh) 1829 rvh->DesktopNotificationPermissionRequestDone(callback_context); 1830 return; 1831 } 1832 1833 notification_service->RequestPermission(source_origin, render_process_id, 1834 render_view_id, callback_context, contents); 1835#else 1836 NOTIMPLEMENTED(); 1837#endif 1838} 1839 1840WebKit::WebNotificationPresenter::Permission 1841 ChromeContentBrowserClient::CheckDesktopNotificationPermission( 1842 const GURL& source_origin, 1843 content::ResourceContext* context, 1844 int render_process_id) { 1845#if defined(ENABLE_NOTIFICATIONS) 1846 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1847 // Sometimes a notification may be invoked during the shutdown. 1848 // See http://crbug.com/256638 1849 if (browser_shutdown::IsTryingToQuit()) 1850 return WebKit::WebNotificationPresenter::PermissionNotAllowed; 1851 1852 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1853 1854 DesktopNotificationService* notification_service = 1855 io_data->GetNotificationService(); 1856 if (notification_service) { 1857 ExtensionInfoMap* extension_info_map = io_data->GetExtensionInfoMap(); 1858 ExtensionSet extensions; 1859 extension_info_map->GetExtensionsWithAPIPermissionForSecurityOrigin( 1860 source_origin, render_process_id, 1861 extensions::APIPermission::kNotification, &extensions); 1862 for (ExtensionSet::const_iterator iter = extensions.begin(); 1863 iter != extensions.end(); ++iter) { 1864 NotifierId notifier_id(NotifierId::APPLICATION, (*iter)->id()); 1865 if (notification_service->IsNotifierEnabled(notifier_id)) 1866 return WebKit::WebNotificationPresenter::PermissionAllowed; 1867 } 1868 1869 return notification_service->HasPermission(source_origin); 1870 } 1871 1872 return WebKit::WebNotificationPresenter::PermissionNotAllowed; 1873#else 1874 return WebKit::WebNotificationPresenter::PermissionAllowed; 1875#endif 1876} 1877 1878void ChromeContentBrowserClient::ShowDesktopNotification( 1879 const content::ShowDesktopNotificationHostMsgParams& params, 1880 int render_process_id, 1881 int render_view_id, 1882 bool worker) { 1883#if defined(ENABLE_NOTIFICATIONS) 1884 RenderViewHost* rvh = RenderViewHost::FromID( 1885 render_process_id, render_view_id); 1886 if (!rvh) { 1887 NOTREACHED(); 1888 return; 1889 } 1890 1891 content::RenderProcessHost* process = rvh->GetProcess(); 1892 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); 1893 DesktopNotificationService* service = 1894 DesktopNotificationServiceFactory::GetForProfile(profile); 1895 service->ShowDesktopNotification( 1896 params, render_process_id, render_view_id, 1897 worker ? DesktopNotificationService::WorkerNotification : 1898 DesktopNotificationService::PageNotification); 1899#else 1900 NOTIMPLEMENTED(); 1901#endif 1902} 1903 1904void ChromeContentBrowserClient::CancelDesktopNotification( 1905 int render_process_id, 1906 int render_view_id, 1907 int notification_id) { 1908#if defined(ENABLE_NOTIFICATIONS) 1909 RenderViewHost* rvh = RenderViewHost::FromID( 1910 render_process_id, render_view_id); 1911 if (!rvh) { 1912 NOTREACHED(); 1913 return; 1914 } 1915 1916 content::RenderProcessHost* process = rvh->GetProcess(); 1917 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); 1918 DesktopNotificationService* service = 1919 DesktopNotificationServiceFactory::GetForProfile(profile); 1920 service->CancelDesktopNotification( 1921 render_process_id, render_view_id, notification_id); 1922#else 1923 NOTIMPLEMENTED(); 1924#endif 1925} 1926 1927bool ChromeContentBrowserClient::CanCreateWindow( 1928 const GURL& opener_url, 1929 const GURL& opener_top_level_frame_url, 1930 const GURL& source_origin, 1931 WindowContainerType container_type, 1932 const GURL& target_url, 1933 const content::Referrer& referrer, 1934 WindowOpenDisposition disposition, 1935 const WebWindowFeatures& features, 1936 bool user_gesture, 1937 bool opener_suppressed, 1938 content::ResourceContext* context, 1939 int render_process_id, 1940 bool is_guest, 1941 int opener_id, 1942 bool* no_javascript_access) { 1943 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1944 1945 *no_javascript_access = false; 1946 1947 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1948 ExtensionInfoMap* map = io_data->GetExtensionInfoMap(); 1949 1950 // If the opener is trying to create a background window but doesn't have 1951 // the appropriate permission, fail the attempt. 1952 if (container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) { 1953 if (!map->SecurityOriginHasAPIPermission( 1954 source_origin, 1955 render_process_id, 1956 APIPermission::kBackground)) { 1957 return false; 1958 } 1959 1960 // Note: this use of GetExtensionOrAppByURL is safe but imperfect. It may 1961 // return a recently installed Extension even if this CanCreateWindow call 1962 // was made by an old copy of the page in a normal web process. That's ok, 1963 // because the permission check above would have caused an early return 1964 // already. We must use the full URL to find hosted apps, though, and not 1965 // just the origin. 1966 const Extension* extension = 1967 map->extensions().GetExtensionOrAppByURL(opener_url); 1968 if (extension && !extensions::BackgroundInfo::AllowJSAccess(extension)) 1969 *no_javascript_access = true; 1970 1971 return true; 1972 } 1973 1974 // No new browser window (popup or tab) in app mode. 1975 if (container_type == WINDOW_CONTAINER_TYPE_NORMAL && 1976 chrome::IsRunningInForcedAppMode()) { 1977 return false; 1978 } 1979 1980 if (g_browser_process->prerender_tracker() && 1981 g_browser_process->prerender_tracker()->TryCancelOnIOThread( 1982 render_process_id, 1983 opener_id, 1984 prerender::FINAL_STATUS_CREATE_NEW_WINDOW)) { 1985 return false; 1986 } 1987 1988 if (is_guest) 1989 return true; 1990 1991 // Exempt extension processes from popup blocking. 1992 if (map->process_map().Contains(render_process_id)) 1993 return true; 1994 1995 HostContentSettingsMap* content_settings = 1996 ProfileIOData::FromResourceContext(context)->GetHostContentSettingsMap(); 1997 BlockedWindowParams blocked_params(target_url, 1998 referrer, 1999 disposition, 2000 features, 2001 user_gesture, 2002 opener_suppressed, 2003 render_process_id, 2004 opener_id); 2005 2006 if (!user_gesture && !CommandLine::ForCurrentProcess()->HasSwitch( 2007 switches::kDisablePopupBlocking)) { 2008 if (content_settings->GetContentSetting(opener_top_level_frame_url, 2009 opener_top_level_frame_url, 2010 CONTENT_SETTINGS_TYPE_POPUPS, 2011 std::string()) != 2012 CONTENT_SETTING_ALLOW) { 2013 BrowserThread::PostTask(BrowserThread::UI, 2014 FROM_HERE, 2015 base::Bind(&HandleBlockedPopupOnUIThread, 2016 blocked_params)); 2017 return false; 2018 } 2019 } 2020 2021#if defined(OS_ANDROID) 2022 if (SingleTabModeTabHelper::IsRegistered(render_process_id, opener_id)) { 2023 BrowserThread::PostTask(BrowserThread::UI, 2024 FROM_HERE, 2025 base::Bind(&HandleSingleTabModeBlockOnUIThread, 2026 blocked_params)); 2027 return false; 2028 } 2029#endif 2030 2031 return true; 2032} 2033 2034std::string ChromeContentBrowserClient::GetWorkerProcessTitle( 2035 const GURL& url, content::ResourceContext* context) { 2036 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 2037 // Check if it's an extension-created worker, in which case we want to use 2038 // the name of the extension. 2039 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 2040 const Extension* extension = 2041 io_data->GetExtensionInfoMap()->extensions().GetByID(url.host()); 2042 return extension ? extension->name() : std::string(); 2043} 2044 2045void ChromeContentBrowserClient::ResourceDispatcherHostCreated() { 2046 return g_browser_process->ResourceDispatcherHostCreated(); 2047} 2048 2049// TODO(tommi): Rename from Get to Create. 2050content::SpeechRecognitionManagerDelegate* 2051 ChromeContentBrowserClient::GetSpeechRecognitionManagerDelegate() { 2052#if defined(ENABLE_INPUT_SPEECH) 2053 return new speech::ChromeSpeechRecognitionManagerDelegateBubbleUI(); 2054#else 2055 // Platforms who don't implement x-webkit-speech (a.k.a INPUT_SPEECH) just 2056 // need the base delegate without the bubble UI. 2057 return new speech::ChromeSpeechRecognitionManagerDelegate(); 2058#endif 2059} 2060 2061net::NetLog* ChromeContentBrowserClient::GetNetLog() { 2062 return g_browser_process->net_log(); 2063} 2064 2065AccessTokenStore* ChromeContentBrowserClient::CreateAccessTokenStore() { 2066 return new ChromeAccessTokenStore(); 2067} 2068 2069bool ChromeContentBrowserClient::IsFastShutdownPossible() { 2070 return true; 2071} 2072 2073void ChromeContentBrowserClient::OverrideWebkitPrefs( 2074 RenderViewHost* rvh, const GURL& url, WebPreferences* web_prefs) { 2075 Profile* profile = Profile::FromBrowserContext( 2076 rvh->GetProcess()->GetBrowserContext()); 2077 PrefService* prefs = profile->GetPrefs(); 2078 2079 FillFontFamilyMap(prefs, prefs::kWebKitStandardFontFamilyMap, 2080 &web_prefs->standard_font_family_map); 2081 FillFontFamilyMap(prefs, prefs::kWebKitFixedFontFamilyMap, 2082 &web_prefs->fixed_font_family_map); 2083 FillFontFamilyMap(prefs, prefs::kWebKitSerifFontFamilyMap, 2084 &web_prefs->serif_font_family_map); 2085 FillFontFamilyMap(prefs, prefs::kWebKitSansSerifFontFamilyMap, 2086 &web_prefs->sans_serif_font_family_map); 2087 FillFontFamilyMap(prefs, prefs::kWebKitCursiveFontFamilyMap, 2088 &web_prefs->cursive_font_family_map); 2089 FillFontFamilyMap(prefs, prefs::kWebKitFantasyFontFamilyMap, 2090 &web_prefs->fantasy_font_family_map); 2091 FillFontFamilyMap(prefs, prefs::kWebKitPictographFontFamilyMap, 2092 &web_prefs->pictograph_font_family_map); 2093 2094 web_prefs->default_font_size = 2095 prefs->GetInteger(prefs::kWebKitDefaultFontSize); 2096 web_prefs->default_fixed_font_size = 2097 prefs->GetInteger(prefs::kWebKitDefaultFixedFontSize); 2098 web_prefs->minimum_font_size = 2099 prefs->GetInteger(prefs::kWebKitMinimumFontSize); 2100 web_prefs->minimum_logical_font_size = 2101 prefs->GetInteger(prefs::kWebKitMinimumLogicalFontSize); 2102 2103 web_prefs->default_encoding = prefs->GetString(prefs::kDefaultCharset); 2104 2105 web_prefs->javascript_can_open_windows_automatically = 2106 prefs->GetBoolean(prefs::kWebKitJavascriptCanOpenWindowsAutomatically); 2107 web_prefs->dom_paste_enabled = 2108 prefs->GetBoolean(prefs::kWebKitDomPasteEnabled); 2109 web_prefs->shrinks_standalone_images_to_fit = 2110 prefs->GetBoolean(prefs::kWebKitShrinksStandaloneImagesToFit); 2111 const DictionaryValue* inspector_settings = 2112 prefs->GetDictionary(prefs::kWebKitInspectorSettings); 2113 if (inspector_settings) { 2114 for (DictionaryValue::Iterator iter(*inspector_settings); !iter.IsAtEnd(); 2115 iter.Advance()) { 2116 std::string value; 2117 if (iter.value().GetAsString(&value)) { 2118 web_prefs->inspector_settings.push_back( 2119 std::make_pair(iter.key(), value)); 2120 } 2121 } 2122 } 2123 web_prefs->tabs_to_links = prefs->GetBoolean(prefs::kWebkitTabsToLinks); 2124 2125 if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled)) 2126 web_prefs->javascript_enabled = false; 2127 if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled)) 2128 web_prefs->web_security_enabled = false; 2129 if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled)) 2130 web_prefs->plugins_enabled = false; 2131 if (!prefs->GetBoolean(prefs::kWebKitJavaEnabled)) 2132 web_prefs->java_enabled = false; 2133 web_prefs->loads_images_automatically = 2134 prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically); 2135 2136 if (prefs->GetBoolean(prefs::kDisable3DAPIs)) 2137 web_prefs->experimental_webgl_enabled = false; 2138 2139 web_prefs->memory_info_enabled = 2140 prefs->GetBoolean(prefs::kEnableMemoryInfo); 2141 web_prefs->allow_displaying_insecure_content = 2142 prefs->GetBoolean(prefs::kWebKitAllowDisplayingInsecureContent); 2143 web_prefs->allow_running_insecure_content = 2144 prefs->GetBoolean(prefs::kWebKitAllowRunningInsecureContent); 2145#if defined(OS_ANDROID) 2146 web_prefs->font_scale_factor = 2147 static_cast<float>(prefs->GetDouble(prefs::kWebKitFontScaleFactor)); 2148 web_prefs->force_enable_zoom = 2149 prefs->GetBoolean(prefs::kWebKitForceEnableZoom); 2150#endif 2151 2152#if defined(OS_ANDROID) 2153 web_prefs->password_echo_enabled = 2154 prefs->GetBoolean(prefs::kWebKitPasswordEchoEnabled); 2155#else 2156 web_prefs->password_echo_enabled = browser_defaults::kPasswordEchoEnabled; 2157#endif 2158 2159#if defined(OS_CHROMEOS) 2160 // Enable password echo during OOBE when keyboard driven flag is set. 2161 if (chromeos::UserManager::IsInitialized() && 2162 !chromeos::UserManager::Get()->IsUserLoggedIn() && 2163 !chromeos::StartupUtils::IsOobeCompleted() && 2164 chromeos::system::keyboard_settings::ForceKeyboardDrivenUINavigation()) { 2165 web_prefs->password_echo_enabled = true; 2166 } 2167#endif 2168 2169#if defined(OS_ANDROID) 2170 web_prefs->user_style_sheet_enabled = false; 2171#else 2172 // The user stylesheet watcher may not exist in a testing profile. 2173 UserStyleSheetWatcher* user_style_sheet_watcher = 2174 UserStyleSheetWatcherFactory::GetForProfile(profile).get(); 2175 if (user_style_sheet_watcher) { 2176 web_prefs->user_style_sheet_enabled = true; 2177 web_prefs->user_style_sheet_location = 2178 user_style_sheet_watcher->user_style_sheet(); 2179 } else { 2180 web_prefs->user_style_sheet_enabled = false; 2181 } 2182#endif 2183 2184 web_prefs->asynchronous_spell_checking_enabled = true; 2185 web_prefs->unified_textchecker_enabled = true; 2186 2187 web_prefs->uses_universal_detector = 2188 prefs->GetBoolean(prefs::kWebKitUsesUniversalDetector); 2189 web_prefs->text_areas_are_resizable = 2190 prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable); 2191 web_prefs->hyperlink_auditing_enabled = 2192 prefs->GetBoolean(prefs::kEnableHyperlinkAuditing); 2193 2194 // Make sure we will set the default_encoding with canonical encoding name. 2195 web_prefs->default_encoding = 2196 CharacterEncoding::GetCanonicalEncodingNameByAliasName( 2197 web_prefs->default_encoding); 2198 if (web_prefs->default_encoding.empty()) { 2199 prefs->ClearPref(prefs::kDefaultCharset); 2200 web_prefs->default_encoding = prefs->GetString(prefs::kDefaultCharset); 2201 } 2202 DCHECK(!web_prefs->default_encoding.empty()); 2203 2204 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); 2205 extensions::ViewType view_type = extensions::GetViewType(web_contents); 2206 ExtensionService* service = 2207 extensions::ExtensionSystem::Get(profile)->extension_service(); 2208 if (service) { 2209 const GURL& url = rvh->GetSiteInstance()->GetSiteURL(); 2210 const Extension* extension = service->extensions()->GetByID(url.host()); 2211 // Ensure that we are only granting extension preferences to URLs with 2212 // the correct scheme. Without this check, chrome-guest:// schemes used by 2213 // webview tags as well as hosts that happen to match the id of an 2214 // installed extension would get the wrong preferences. 2215 if (url.SchemeIs(extensions::kExtensionScheme)) { 2216 extension_webkit_preferences::SetPreferences( 2217 extension, view_type, web_prefs); 2218 } 2219 } 2220 2221 if (view_type == extensions::VIEW_TYPE_NOTIFICATION) { 2222 web_prefs->allow_scripts_to_close_windows = true; 2223 } else if (view_type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) { 2224 // Disable all kinds of acceleration for background pages. 2225 // See http://crbug.com/96005 and http://crbug.com/96006 2226 web_prefs->force_compositing_mode = false; 2227 web_prefs->accelerated_compositing_enabled = false; 2228 } 2229 2230#if defined(FILE_MANAGER_EXTENSION) 2231 // Override the default of suppressing HW compositing for WebUI pages for the 2232 // file manager, which is implemented using WebUI but wants HW acceleration 2233 // for video decode & render. 2234 if (url.SchemeIs(extensions::kExtensionScheme) && 2235 url.host() == file_manager::kFileManagerAppId) { 2236 web_prefs->accelerated_compositing_enabled = true; 2237 web_prefs->accelerated_2d_canvas_enabled = true; 2238 } 2239#endif 2240} 2241 2242void ChromeContentBrowserClient::UpdateInspectorSetting( 2243 RenderViewHost* rvh, const std::string& key, const std::string& value) { 2244 content::BrowserContext* browser_context = 2245 rvh->GetProcess()->GetBrowserContext(); 2246 DictionaryPrefUpdate update( 2247 Profile::FromBrowserContext(browser_context)->GetPrefs(), 2248 prefs::kWebKitInspectorSettings); 2249 DictionaryValue* inspector_settings = update.Get(); 2250 inspector_settings->SetWithoutPathExpansion(key, 2251 Value::CreateStringValue(value)); 2252} 2253 2254void ChromeContentBrowserClient::BrowserURLHandlerCreated( 2255 BrowserURLHandler* handler) { 2256 // Add the default URL handlers. 2257 handler->AddHandlerPair(&ExtensionWebUI::HandleChromeURLOverride, 2258 BrowserURLHandler::null_handler()); 2259 handler->AddHandlerPair(BrowserURLHandler::null_handler(), 2260 &ExtensionWebUI::HandleChromeURLOverrideReverse); 2261 2262 // about: handler. Must come before chrome: handler, since it will 2263 // rewrite about: urls to chrome: URLs and then expect chrome: to 2264 // actually handle them. 2265 handler->AddHandlerPair(&WillHandleBrowserAboutURL, 2266 BrowserURLHandler::null_handler()); 2267 2268 // Handler to rewrite chrome://newtab for InstantExtended. 2269 handler->AddHandlerPair(&chrome::HandleNewTabURLRewrite, 2270 &chrome::HandleNewTabURLReverseRewrite); 2271 2272 // chrome: & friends. 2273 handler->AddHandlerPair(&HandleWebUI, &HandleWebUIReverse); 2274} 2275 2276void ChromeContentBrowserClient::ClearCache(RenderViewHost* rvh) { 2277 Profile* profile = Profile::FromBrowserContext( 2278 rvh->GetSiteInstance()->GetProcess()->GetBrowserContext()); 2279 BrowsingDataRemover* remover = 2280 BrowsingDataRemover::CreateForUnboundedRange(profile); 2281 remover->Remove(BrowsingDataRemover::REMOVE_CACHE, 2282 BrowsingDataHelper::UNPROTECTED_WEB); 2283 // BrowsingDataRemover takes care of deleting itself when done. 2284} 2285 2286void ChromeContentBrowserClient::ClearCookies(RenderViewHost* rvh) { 2287 Profile* profile = Profile::FromBrowserContext( 2288 rvh->GetSiteInstance()->GetProcess()->GetBrowserContext()); 2289 BrowsingDataRemover* remover = 2290 BrowsingDataRemover::CreateForUnboundedRange(profile); 2291 int remove_mask = BrowsingDataRemover::REMOVE_SITE_DATA; 2292 remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB); 2293 // BrowsingDataRemover takes care of deleting itself when done. 2294} 2295 2296base::FilePath ChromeContentBrowserClient::GetDefaultDownloadDirectory() { 2297 return DownloadPrefs::GetDefaultDownloadDirectory(); 2298} 2299 2300std::string ChromeContentBrowserClient::GetDefaultDownloadName() { 2301 return l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME); 2302} 2303 2304void ChromeContentBrowserClient::DidCreatePpapiPlugin( 2305 content::BrowserPpapiHost* browser_host) { 2306#if defined(ENABLE_PLUGINS) 2307 browser_host->GetPpapiHost()->AddHostFactoryFilter( 2308 scoped_ptr<ppapi::host::HostFactory>( 2309 new ChromeBrowserPepperHostFactory(browser_host))); 2310#endif 2311} 2312 2313content::BrowserPpapiHost* 2314 ChromeContentBrowserClient::GetExternalBrowserPpapiHost( 2315 int plugin_process_id) { 2316 BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_LOADER); 2317 while (!iter.Done()) { 2318 NaClProcessHost* host = static_cast<NaClProcessHost*>(iter.GetDelegate()); 2319 if (host->process() && 2320 host->process()->GetData().id == plugin_process_id) { 2321 // Found the plugin. 2322 return host->browser_ppapi_host(); 2323 } 2324 ++iter; 2325 } 2326 return NULL; 2327} 2328 2329bool ChromeContentBrowserClient::SupportsBrowserPlugin( 2330 content::BrowserContext* browser_context, const GURL& site_url) { 2331 if (CommandLine::ForCurrentProcess()->HasSwitch( 2332 switches::kEnableBrowserPluginForAllViewTypes)) 2333 return true; 2334 2335 Profile* profile = Profile::FromBrowserContext(browser_context); 2336 ExtensionService* service = 2337 extensions::ExtensionSystem::Get(profile)->extension_service(); 2338 if (!service) 2339 return false; 2340 2341 const Extension* extension = 2342 service->extensions()->GetExtensionOrAppByURL(site_url); 2343 if (!extension) 2344 return false; 2345 2346 return extension->HasAPIPermission(APIPermission::kWebView) || 2347 extension->HasAPIPermission(APIPermission::kAdView); 2348} 2349 2350bool ChromeContentBrowserClient::AllowPepperSocketAPI( 2351 content::BrowserContext* browser_context, 2352 const GURL& url, 2353 bool private_api, 2354 const content::SocketPermissionRequest& params) { 2355#if defined(ENABLE_PLUGINS) 2356 Profile* profile = Profile::FromBrowserContext(browser_context); 2357 const ExtensionSet* extension_set = NULL; 2358 if (profile) { 2359 extension_set = extensions::ExtensionSystem::Get(profile)-> 2360 extension_service()->extensions(); 2361 } 2362 2363 if (private_api) { 2364 // Access to private socket APIs is controlled by the whitelist. 2365 if (IsExtensionOrSharedModuleWhitelisted(url, extension_set, 2366 allowed_socket_origins_)) { 2367 return true; 2368 } 2369 } else { 2370 // Access to public socket APIs is controlled by extension permissions. 2371 if (url.is_valid() && url.SchemeIs(extensions::kExtensionScheme) && 2372 extension_set) { 2373 const Extension* extension = extension_set->GetByID(url.host()); 2374 if (extension) { 2375 extensions::SocketPermission::CheckParam check_params( 2376 params.type, params.host, params.port); 2377 if (extensions::PermissionsData::CheckAPIPermissionWithParam( 2378 extension, extensions::APIPermission::kSocket, &check_params)) { 2379 return true; 2380 } 2381 } 2382 } 2383 } 2384 2385 // Allow both public and private APIs if the command line says so. 2386 return IsHostAllowedByCommandLine(url, extension_set, 2387 switches::kAllowNaClSocketAPI); 2388#else 2389 return false; 2390#endif 2391} 2392 2393ui::SelectFilePolicy* ChromeContentBrowserClient::CreateSelectFilePolicy( 2394 WebContents* web_contents) { 2395 return new ChromeSelectFilePolicy(web_contents); 2396} 2397 2398void ChromeContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem( 2399 std::vector<std::string>* additional_allowed_schemes) { 2400 ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem( 2401 additional_allowed_schemes); 2402 additional_allowed_schemes->push_back(kChromeUIScheme); 2403 additional_allowed_schemes->push_back(extensions::kExtensionScheme); 2404} 2405 2406void ChromeContentBrowserClient::GetAdditionalFileSystemBackends( 2407 content::BrowserContext* browser_context, 2408 const base::FilePath& storage_partition_path, 2409 ScopedVector<fileapi::FileSystemBackend>* additional_backends) { 2410#if !defined(OS_ANDROID) 2411 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool(); 2412 additional_backends->push_back(new MediaFileSystemBackend( 2413 storage_partition_path, 2414 pool->GetSequencedTaskRunner(pool->GetNamedSequenceToken( 2415 MediaFileSystemBackend::kMediaTaskRunnerName)).get())); 2416#endif 2417#if defined(OS_CHROMEOS) 2418 fileapi::ExternalMountPoints* external_mount_points = 2419 content::BrowserContext::GetMountPoints(browser_context); 2420 DCHECK(external_mount_points); 2421 chromeos::FileSystemBackend* backend = 2422 new chromeos::FileSystemBackend( 2423 new drive::FileSystemBackendDelegate(browser_context), 2424 browser_context->GetSpecialStoragePolicy(), 2425 external_mount_points, 2426 fileapi::ExternalMountPoints::GetSystemInstance()); 2427 backend->AddSystemMountPoints(); 2428 DCHECK(backend->CanHandleType(fileapi::kFileSystemTypeExternal)); 2429 additional_backends->push_back(backend); 2430#endif 2431 2432 additional_backends->push_back( 2433 new sync_file_system::SyncFileSystemBackend( 2434 Profile::FromBrowserContext(browser_context))); 2435} 2436 2437#if defined(OS_POSIX) && !defined(OS_MACOSX) 2438void ChromeContentBrowserClient::GetAdditionalMappedFilesForChildProcess( 2439 const CommandLine& command_line, 2440 int child_process_id, 2441 std::vector<FileDescriptorInfo>* mappings) { 2442#if defined(OS_ANDROID) 2443 base::FilePath data_path; 2444 PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &data_path); 2445 DCHECK(!data_path.empty()); 2446 2447 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; 2448 base::FilePath chrome_resources_pak = 2449 data_path.AppendASCII("chrome_100_percent.pak"); 2450 base::PlatformFile f = 2451 base::CreatePlatformFile(chrome_resources_pak, flags, NULL, NULL); 2452 DCHECK(f != base::kInvalidPlatformFileValue); 2453 mappings->push_back(FileDescriptorInfo(kAndroidChrome100PercentPakDescriptor, 2454 FileDescriptor(f, true))); 2455 2456 const std::string locale = GetApplicationLocale(); 2457 base::FilePath locale_pak = ResourceBundle::GetSharedInstance(). 2458 GetLocaleFilePath(locale, false); 2459 f = base::CreatePlatformFile(locale_pak, flags, NULL, NULL); 2460 DCHECK(f != base::kInvalidPlatformFileValue); 2461 mappings->push_back(FileDescriptorInfo(kAndroidLocalePakDescriptor, 2462 FileDescriptor(f, true))); 2463 2464 base::FilePath resources_pack_path; 2465 PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path); 2466 f = base::CreatePlatformFile(resources_pack_path, flags, NULL, NULL); 2467 DCHECK(f != base::kInvalidPlatformFileValue); 2468 mappings->push_back(FileDescriptorInfo(kAndroidUIResourcesPakDescriptor, 2469 FileDescriptor(f, true))); 2470 2471 if (IsCrashReporterEnabled()) { 2472 f = CrashDumpManager::GetInstance()->CreateMinidumpFile(child_process_id); 2473 if (f == base::kInvalidPlatformFileValue) { 2474 LOG(ERROR) << "Failed to create file for minidump, crash reporting will " 2475 "be disabled for this process."; 2476 } else { 2477 mappings->push_back(FileDescriptorInfo(kAndroidMinidumpDescriptor, 2478 FileDescriptor(f, true))); 2479 } 2480 } 2481 2482#else 2483 int crash_signal_fd = GetCrashSignalFD(command_line); 2484 if (crash_signal_fd >= 0) { 2485 mappings->push_back(FileDescriptorInfo(kCrashDumpSignal, 2486 FileDescriptor(crash_signal_fd, 2487 false))); 2488 } 2489#endif // defined(OS_ANDROID) 2490} 2491#endif // defined(OS_POSIX) && !defined(OS_MACOSX) 2492 2493#if defined(OS_WIN) 2494const wchar_t* ChromeContentBrowserClient::GetResourceDllName() { 2495 return chrome::kBrowserResourcesDll; 2496} 2497 2498void ChromeContentBrowserClient::PreSpawnRenderer( 2499 sandbox::TargetPolicy* policy, 2500 bool* success) { 2501 // This code is duplicated in nacl_exe_win_64.cc. 2502 // Allow the server side of a pipe restricted to the "chrome.nacl." 2503 // namespace so that it cannot impersonate other system or other chrome 2504 // service pipes. 2505 sandbox::ResultCode result = policy->AddRule( 2506 sandbox::TargetPolicy::SUBSYS_NAMED_PIPES, 2507 sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY, 2508 L"\\\\.\\pipe\\chrome.nacl.*"); 2509 if (result != sandbox::SBOX_ALL_OK) { 2510 *success = false; 2511 return; 2512 } 2513 2514 // Renderers need to send named pipe handles and shared memory 2515 // segment handles to NaCl loader processes. 2516 result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES, 2517 sandbox::TargetPolicy::HANDLES_DUP_ANY, 2518 L"File"); 2519 if (result != sandbox::SBOX_ALL_OK) { 2520 *success = false; 2521 return; 2522 } 2523} 2524#endif 2525 2526#if defined(USE_NSS) 2527crypto::CryptoModuleBlockingPasswordDelegate* 2528 ChromeContentBrowserClient::GetCryptoPasswordDelegate( 2529 const GURL& url) { 2530 return chrome::NewCryptoModuleBlockingDialogDelegate( 2531 chrome::kCryptoModulePasswordKeygen, url.host()); 2532} 2533#endif 2534 2535} // namespace chrome 2536