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