chrome_content_browser_client.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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/path_service.h" 14#include "base/string_tokenizer.h" 15#include "base/utf_string_conversions.h" 16#include "chrome/app/breakpad_mac.h" 17#include "chrome/browser/browser_about_handler.h" 18#include "chrome/browser/browser_process.h" 19#include "chrome/browser/browsing_data/browsing_data_helper.h" 20#include "chrome/browser/browsing_data/browsing_data_remover.h" 21#include "chrome/browser/character_encoding.h" 22#include "chrome/browser/chrome_benchmarking_message_filter.h" 23#include "chrome/browser/chrome_quota_permission_context.h" 24#include "chrome/browser/content_settings/content_settings_utils.h" 25#include "chrome/browser/content_settings/cookie_settings.h" 26#include "chrome/browser/content_settings/host_content_settings_map.h" 27#include "chrome/browser/content_settings/tab_specific_content_settings.h" 28#include "chrome/browser/defaults.h" 29#include "chrome/browser/download/download_util.h" 30#include "chrome/browser/extensions/api/web_request/web_request_api.h" 31#include "chrome/browser/extensions/extension_host.h" 32#include "chrome/browser/extensions/extension_info_map.h" 33#include "chrome/browser/extensions/extension_process_manager.h" 34#include "chrome/browser/extensions/extension_service.h" 35#include "chrome/browser/extensions/extension_system.h" 36#include "chrome/browser/extensions/extension_web_ui.h" 37#include "chrome/browser/extensions/extension_webkit_preferences.h" 38#include "chrome/browser/extensions/message_handler.h" 39#include "chrome/browser/geolocation/chrome_access_token_store.h" 40#include "chrome/browser/google/google_util.h" 41#include "chrome/browser/infobars/infobar_tab_helper.h" 42#include "chrome/browser/media/media_internals.h" 43#include "chrome/browser/nacl_host/nacl_process_host.h" 44#include "chrome/browser/net/chrome_net_log.h" 45#include "chrome/browser/notifications/desktop_notification_service.h" 46#include "chrome/browser/notifications/desktop_notification_service_factory.h" 47#include "chrome/browser/pepper_gtalk_message_filter.h" 48#include "chrome/browser/platform_util.h" 49#include "chrome/browser/prefs/pref_service.h" 50#include "chrome/browser/prefs/scoped_user_pref_update.h" 51#include "chrome/browser/prerender/prerender_manager.h" 52#include "chrome/browser/prerender/prerender_manager_factory.h" 53#include "chrome/browser/prerender/prerender_message_filter.h" 54#include "chrome/browser/prerender/prerender_tracker.h" 55#include "chrome/browser/printing/printing_message_filter.h" 56#include "chrome/browser/profiles/profile.h" 57#include "chrome/browser/profiles/profile_io_data.h" 58#include "chrome/browser/profiles/profile_manager.h" 59#include "chrome/browser/renderer_host/chrome_render_message_filter.h" 60#include "chrome/browser/renderer_host/chrome_render_view_host_observer.h" 61#include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" 62#include "chrome/browser/renderer_host/plugin_info_message_filter.h" 63#include "chrome/browser/search_engines/search_provider_install_state_message_filter.h" 64#include "chrome/browser/speech/chrome_speech_recognition_manager_delegate.h" 65#include "chrome/browser/spellchecker/spellcheck_message_filter.h" 66#include "chrome/browser/ssl/ssl_add_cert_handler.h" 67#include "chrome/browser/ssl/ssl_blocking_page.h" 68#include "chrome/browser/ssl/ssl_tab_helper.h" 69#include "chrome/browser/tab_contents/tab_util.h" 70#include "chrome/browser/toolkit_extra_parts.h" 71#include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h" 72#include "chrome/browser/ui/tab_contents/tab_contents.h" 73#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" 74#include "chrome/browser/user_style_sheet_watcher.h" 75#include "chrome/browser/user_style_sheet_watcher_factory.h" 76#include "chrome/browser/view_type_utils.h" 77#include "chrome/common/child_process_logging.h" 78#include "chrome/common/chrome_constants.h" 79#include "chrome/common/chrome_paths.h" 80#include "chrome/common/chrome_switches.h" 81#include "chrome/common/extensions/extension.h" 82#include "chrome/common/extensions/extension_process_policy.h" 83#include "chrome/common/extensions/extension_set.h" 84#include "chrome/common/extensions/permissions/socket_permission.h" 85#include "chrome/common/logging_chrome.h" 86#include "chrome/common/pref_names.h" 87#include "chrome/common/render_messages.h" 88#include "chrome/common/url_constants.h" 89#include "content/public/browser/browser_child_process_host.h" 90#include "content/public/browser/browser_main_parts.h" 91#include "content/public/browser/browser_ppapi_host.h" 92#include "content/public/browser/browser_url_handler.h" 93#include "content/public/browser/child_process_data.h" 94#include "content/public/browser/child_process_security_policy.h" 95#include "content/public/browser/compositor_util.h" 96#include "content/public/browser/render_process_host.h" 97#include "content/public/browser/render_view_host.h" 98#include "content/public/browser/resource_context.h" 99#include "content/public/browser/site_instance.h" 100#include "content/public/browser/web_contents.h" 101#include "content/public/browser/web_contents_view.h" 102#include "content/public/common/child_process_host.h" 103#include "content/public/common/content_descriptors.h" 104#include "grit/generated_resources.h" 105#include "grit/ui_resources.h" 106#include "net/base/escape.h" 107#include "net/base/ssl_cert_request_info.h" 108#include "net/cookies/canonical_cookie.h" 109#include "net/cookies/cookie_options.h" 110#include "ppapi/host/ppapi_host.h" 111#include "ui/base/l10n/l10n_util.h" 112#include "ui/base/resource/resource_bundle.h" 113#include "webkit/glue/webpreferences.h" 114#include "webkit/plugins/plugin_switches.h" 115 116#if defined(OS_WIN) 117#include "chrome/browser/chrome_browser_main_win.h" 118#elif defined(OS_MACOSX) 119#include "chrome/browser/chrome_browser_main_mac.h" 120#include "chrome/browser/spellchecker/spellcheck_message_filter_mac.h" 121#elif defined(OS_CHROMEOS) 122#include "chrome/browser/chromeos/chrome_browser_main_chromeos.h" 123#include "chrome/browser/chromeos/login/user_manager.h" 124#elif defined(OS_LINUX) 125#include "chrome/browser/chrome_browser_main_linux.h" 126#elif defined(OS_ANDROID) 127#include "chrome/browser/android/crash_dump_manager.h" 128#include "chrome/browser/chrome_browser_main_android.h" 129#include "chrome/common/descriptors_android.h" 130#elif defined(OS_POSIX) 131#include "chrome/browser/chrome_browser_main_posix.h" 132#endif 133 134#if defined(OS_LINUX) || defined(OS_OPENBSD) || defined(OS_ANDROID) 135#include "base/linux_util.h" 136#include "chrome/browser/crash_handler_host_linux.h" 137#endif 138 139#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 140#include "chrome/browser/captive_portal/captive_portal_tab_helper.h" 141#endif 142 143#if defined(OS_ANDROID) 144#include "ui/base/ui_base_paths.h" 145#endif 146 147#if defined(USE_NSS) 148#include "chrome/browser/ui/crypto_module_password_dialog.h" 149#endif 150 151using base::FileDescriptor; 152using content::AccessTokenStore; 153using content::BrowserChildProcessHostIterator; 154using content::BrowserThread; 155using content::BrowserURLHandler; 156using content::ChildProcessSecurityPolicy; 157using content::FileDescriptorInfo; 158using content::QuotaPermissionContext; 159using content::RenderViewHost; 160using content::SiteInstance; 161using content::WebContents; 162using extensions::APIPermission; 163using extensions::Extension; 164using webkit_glue::WebPreferences; 165 166namespace { 167 168const char* kPredefinedAllowedSocketOrigins[] = { 169 "okddffdblfhhnmhodogpojmfkjmhinfp", // Test SSH Client 170 "pnhechapfaindjhompbnflcldabbghjo", // HTerm App (SSH Client) 171 "bglhmjfplikpjnfoegeomebmfnkjomhe", // see crbug.com/122126 172 "gbchcmhmhahfdphkhkmpfmihenigjmpp", // Chrome Remote Desktop 173 "kgngmbheleoaphbjbaiobfdepmghbfah", // Pre-release Chrome Remote Desktop 174 "odkaodonbgfohohmklejpjiejmcipmib", // Dogfood Chrome Remote Desktop 175 "ojoimpklfciegopdfgeenehpalipignm", // Chromoting canary 176 "cbkkbcmdlboombapidmoeolnmdacpkch", // see crbug.com/129089 177 "hhnbmknkdabfoieppbbljkhkfjcmcbjh", // see crbug.com/134099 178 "mablfbjkhmhkmefkjjacnbaikjkipphg", // see crbug.com/134099 179 "pdeelgamlgannhelgoegilelnnojegoh", // see crbug.com/134099 180 "cabapfdbkniadpollkckdnedaanlciaj", // see crbug.com/134099 181 "mapljbgnjledlpdmlchihnmeclmefbba", // see crbug.com/134099 182 "ghbfeebgmiidnnmeobbbaiamklmpbpii", // see crbug.com/134099 183 "jdfhpkjeckflbbleddjlpimecpbjdeep" // see crbug.com/142514 184}; 185 186// Returns a copy of the given url with its host set to given host and path set 187// to given path. Other parts of the url will be the same. 188GURL ReplaceURLHostAndPath(const GURL& url, 189 const std::string& host, 190 const std::string& path) { 191 url_canon::Replacements<char> replacements; 192 replacements.SetHost(host.c_str(), 193 url_parse::Component(0, host.length())); 194 replacements.SetPath(path.c_str(), 195 url_parse::Component(0, path.length())); 196 return url.ReplaceComponents(replacements); 197} 198 199// Maps "foo://bar/baz/" to "foo://chrome/bar/baz/". 200GURL AddUberHost(const GURL& url) { 201 const std::string uber_host = chrome::kChromeUIUberHost; 202 const std::string new_path = url.host() + url.path(); 203 204 return ReplaceURLHostAndPath(url, uber_host, new_path); 205} 206 207// If url->host() is "chrome" and url->path() has characters other than the 208// first slash, changes the url from "foo://chrome/bar/" to "foo://bar/" and 209// returns true. Otherwise returns false. 210bool RemoveUberHost(GURL* url) { 211 if (url->host() != chrome::kChromeUIUberHost) 212 return false; 213 214 if (url->path().empty() || url->path() == "/") 215 return false; 216 217 const std::string old_path = url->path(); 218 219 const std::string::size_type separator = old_path.find('/', 1); 220 std::string new_host; 221 std::string new_path; 222 if (separator == std::string::npos) { 223 new_host = old_path.substr(1); 224 } else { 225 new_host = old_path.substr(1, separator - 1); 226 new_path = old_path.substr(separator); 227 } 228 229 *url = ReplaceURLHostAndPath(*url, new_host, new_path); 230 231 return true; 232} 233 234// Handles rewriting Web UI URLs. 235bool HandleWebUI(GURL* url, content::BrowserContext* browser_context) { 236 // Do not handle special URLs such as "about:foo" 237 if (!url->host().empty()) { 238 const GURL chrome_url = AddUberHost(*url); 239 240 // Handle valid "chrome://chrome/foo" URLs so the reverse handler will 241 // be called. 242 if (ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL( 243 browser_context, chrome_url)) 244 return true; 245 } 246 247 if (!ChromeWebUIControllerFactory::GetInstance()->UseWebUIForURL( 248 browser_context, *url)) 249 return false; 250 251#if defined(OS_CHROMEOS) 252 // Special case : in ChromeOS in Guest mode bookmarks and history are 253 // disabled for security reasons. New tab page explains the reasons, so 254 // we redirect user to new tab page. 255 if (chromeos::UserManager::Get()->IsLoggedInAsGuest()) { 256 if (url->SchemeIs(chrome::kChromeUIScheme) && 257 (url->DomainIs(chrome::kChromeUIBookmarksHost) || 258 url->DomainIs(chrome::kChromeUIHistoryHost))) { 259 // Rewrite with new tab URL 260 *url = GURL(chrome::kChromeUINewTabURL); 261 } 262 } 263#endif 264 265 // Special case the new tab page. In older versions of Chrome, the new tab 266 // page was hosted at chrome-internal:<blah>. This might be in people's saved 267 // sessions or bookmarks, so we say any URL with that scheme triggers the new 268 // tab page. 269 if (url->SchemeIs(chrome::kChromeInternalScheme)) { 270 // Rewrite it with the proper new tab URL. 271 *url = GURL(chrome::kChromeUINewTabURL); 272 } 273 274 return true; 275} 276 277// Reverse URL handler for Web UI. Maps "chrome://chrome/foo/" to 278// "chrome://foo/". 279bool HandleWebUIReverse(GURL* url, content::BrowserContext* browser_context) { 280 if (!url->is_valid() || !url->SchemeIs(chrome::kChromeUIScheme)) 281 return false; 282 283 return RemoveUberHost(url); 284} 285 286// Used by the GetPrivilegeRequiredByUrl() and GetProcessPrivilege() functions 287// below. Extension, and isolated apps require different privileges to be 288// granted to their RenderProcessHosts. This classification allows us to make 289// sure URLs are served by hosts with the right set of privileges. 290enum RenderProcessHostPrivilege { 291 PRIV_NORMAL, 292 PRIV_HOSTED, 293 PRIV_ISOLATED, 294 PRIV_EXTENSION, 295}; 296 297RenderProcessHostPrivilege GetPrivilegeRequiredByUrl( 298 const GURL& url, 299 ExtensionService* service) { 300 // Default to a normal renderer cause it is lower privileged. This should only 301 // occur if the URL on a site instance is either malformed, or uninitialized. 302 // If it is malformed, then there is no need for better privileges anyways. 303 // If it is uninitialized, but eventually settles on being an a scheme other 304 // than normal webrenderer, the navigation logic will correct us out of band 305 // anyways. 306 if (!url.is_valid()) 307 return PRIV_NORMAL; 308 309 if (url.SchemeIs(chrome::kExtensionScheme)) { 310 const Extension* extension = 311 service->extensions()->GetByID(url.host()); 312 if (extension && extension->is_storage_isolated()) 313 return PRIV_ISOLATED; 314 if (extension && extension->is_hosted_app()) 315 return PRIV_HOSTED; 316 317 return PRIV_EXTENSION; 318 } 319 320 return PRIV_NORMAL; 321} 322 323RenderProcessHostPrivilege GetProcessPrivilege( 324 content::RenderProcessHost* process_host, 325 extensions::ProcessMap* process_map, 326 ExtensionService* service) { 327 std::set<std::string> extension_ids = 328 process_map->GetExtensionsInProcess(process_host->GetID()); 329 if (extension_ids.empty()) 330 return PRIV_NORMAL; 331 332 for (std::set<std::string>::iterator iter = extension_ids.begin(); 333 iter != extension_ids.end(); ++iter) { 334 const Extension* extension = service->GetExtensionById(*iter, false); 335 if (extension && extension->is_storage_isolated()) 336 return PRIV_ISOLATED; 337 if (extension && extension->is_hosted_app()) 338 return PRIV_HOSTED; 339 } 340 341 return PRIV_EXTENSION; 342} 343 344bool CertMatchesFilter(const net::X509Certificate& cert, 345 const base::DictionaryValue& filter) { 346 // TODO(markusheintz): This is the minimal required filter implementation. 347 // Implement a better matcher. 348 349 // An empty filter matches any client certificate since no requirements are 350 // specified at all. 351 if (filter.empty()) 352 return true; 353 354 std::string common_name; 355 if (filter.GetString("ISSUER.CN", &common_name) && 356 (cert.issuer().common_name == common_name)) { 357 return true; 358 } 359 return false; 360} 361 362// Fills |map| with the per-script font prefs under path |map_name|. 363void FillFontFamilyMap(const PrefService* prefs, 364 const char* map_name, 365 WebPreferences::ScriptFontFamilyMap* map) { 366 for (size_t i = 0; i < prefs::kWebKitScriptsForFontFamilyMapsLength; ++i) { 367 const char* script = prefs::kWebKitScriptsForFontFamilyMaps[i]; 368 std::string pref_name = base::StringPrintf("%s.%s", map_name, script); 369 std::string font_family = prefs->GetString(pref_name.c_str()); 370 if (!font_family.empty()) 371 (*map)[script] = UTF8ToUTF16(font_family); 372 } 373} 374 375#if defined(OS_POSIX) && !defined(OS_MACOSX) 376int GetCrashSignalFD(const CommandLine& command_line) { 377 if (command_line.HasSwitch(switches::kExtensionProcess)) { 378 ExtensionCrashHandlerHostLinux* crash_handler = 379 ExtensionCrashHandlerHostLinux::GetInstance(); 380 return crash_handler->GetDeathSignalSocket(); 381 } 382 383 std::string process_type = 384 command_line.GetSwitchValueASCII(switches::kProcessType); 385 386 if (process_type == switches::kRendererProcess) 387 return RendererCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 388 389 if (process_type == switches::kPluginProcess) 390 return PluginCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 391 392 if (process_type == switches::kPpapiPluginProcess) 393 return PpapiCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 394 395 if (process_type == switches::kGpuProcess) 396 return GpuCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket(); 397 398 return -1; 399} 400#endif // defined(OS_POSIX) && !defined(OS_MACOSX) 401 402} // namespace 403 404namespace chrome { 405 406ChromeContentBrowserClient::ChromeContentBrowserClient() { 407 for (size_t i = 0; i < arraysize(kPredefinedAllowedSocketOrigins); ++i) 408 allowed_socket_origins_.insert(kPredefinedAllowedSocketOrigins[i]); 409} 410 411ChromeContentBrowserClient::~ChromeContentBrowserClient() { 412} 413 414// static 415void ChromeContentBrowserClient::RegisterUserPrefs(PrefService* prefs) { 416 prefs->RegisterBooleanPref(prefs::kDisable3DAPIs, 417 false, 418 PrefService::UNSYNCABLE_PREF); 419 prefs->RegisterBooleanPref(prefs::kEnableHyperlinkAuditing, 420 true, 421 PrefService::UNSYNCABLE_PREF); 422 prefs->RegisterBooleanPref(prefs::kEnableMemoryInfo, 423 false, 424 PrefService::UNSYNCABLE_PREF); 425} 426 427content::BrowserMainParts* ChromeContentBrowserClient::CreateBrowserMainParts( 428 const content::MainFunctionParams& parameters) { 429 ChromeBrowserMainParts* main_parts; 430 // Construct the Main browser parts based on the OS type. 431#if defined(OS_WIN) 432 main_parts = new ChromeBrowserMainPartsWin(parameters); 433#elif defined(OS_MACOSX) 434 main_parts = new ChromeBrowserMainPartsMac(parameters); 435#elif defined(OS_CHROMEOS) 436 main_parts = new ChromeBrowserMainPartsChromeos(parameters); 437#elif defined(OS_LINUX) 438 main_parts = new ChromeBrowserMainPartsLinux(parameters); 439#elif defined(OS_ANDROID) 440 main_parts = new ChromeBrowserMainPartsAndroid(parameters); 441#elif defined(OS_POSIX) 442 main_parts = new ChromeBrowserMainPartsPosix(parameters); 443#else 444 NOTREACHED(); 445 main_parts = new ChromeBrowserMainParts(parameters); 446#endif 447 448 // Construct additional browser parts. Stages are called in the order in 449 // which they are added. 450#if defined(TOOLKIT_GTK) 451 chrome::AddGtkToolkitExtraParts(main_parts); 452#endif 453 454#if defined(TOOLKIT_VIEWS) 455 chrome::AddViewsToolkitExtraParts(main_parts); 456#endif 457 458#if defined(USE_ASH) 459 chrome::AddAshToolkitExtraParts(main_parts); 460#endif 461 462#if defined(USE_AURA) 463 chrome::AddAuraToolkitExtraParts(main_parts); 464#endif 465 466 return main_parts; 467} 468 469content::WebContentsView* 470 ChromeContentBrowserClient::OverrideCreateWebContentsView( 471 WebContents* web_contents, 472 content::RenderViewHostDelegateView** render_view_host_delegate_view) { 473 return NULL; 474} 475 476std::string ChromeContentBrowserClient::GetStoragePartitionIdForSite( 477 content::BrowserContext* browser_context, 478 const GURL& site) { 479 std::string partition_id; 480 481 // The partition ID for webview guest processes is the string value of its 482 // SiteInstance URL - "chrome-guest://app_id/persist?partition". 483 if (site.SchemeIs(chrome::kGuestScheme)) 484 partition_id = site.spec(); 485 486 DCHECK(IsValidStoragePartitionId(browser_context,partition_id)); 487 return partition_id; 488} 489 490bool ChromeContentBrowserClient::IsValidStoragePartitionId( 491 content::BrowserContext* browser_context, 492 const std::string& partition_id) { 493 // The default ID is empty and is always valid. 494 if (partition_id.empty()) 495 return true; 496 497 return GURL(partition_id).is_valid(); 498} 499 500void ChromeContentBrowserClient::GetStoragePartitionConfigForSite( 501 content::BrowserContext* browser_context, 502 const GURL& site, 503 std::string* partition_domain, 504 std::string* partition_name, 505 bool* in_memory) { 506 // For the webview tag, we create special guest processes, which host the 507 // tag content separately from the main application that embeds the tag. 508 // A webview tag can specify both the partition name and whether the storage 509 // for that partition should be persisted. Each tag gets a SiteInstance with 510 // a specially formatted URL, based on the application it is hosted by and 511 // the partition requested by it. The format for that URL is: 512 // chrome-guest://partition_domain/persist?partition_name 513 if (site.SchemeIs(chrome::kGuestScheme)) { 514 // Since guest URLs are only used for packaged apps, there must be an app 515 // id in the URL. 516 CHECK(site.has_host()); 517 *partition_domain = site.host(); 518 // Since persistence is optional, the path must either be empty or the 519 // literal string. 520 *in_memory = (site.path() != "/persist"); 521 // The partition name is user supplied value, which we have encoded when the 522 // URL was created, so it needs to be decoded. 523 *partition_name = net::UnescapeURLComponent(site.query(), 524 net::UnescapeRule::NORMAL); 525 return; 526 } 527 528 const Extension* extension = NULL; 529 Profile* profile = Profile::FromBrowserContext(browser_context); 530 ExtensionService* extension_service = 531 extensions::ExtensionSystem::Get(profile)->extension_service(); 532 if (extension_service) { 533 extension = extension_service->extensions()-> 534 GetExtensionOrAppByURL(ExtensionURLInfo(site)); 535 if (extension && extension->is_storage_isolated()) { 536 // Extensions which have storage isolation enabled (e.g., apps), use 537 // the extension id as the |partition_domain|. 538 *partition_domain = extension->id(); 539 partition_name->clear(); 540 *in_memory = false; 541 return; 542 } 543 } 544 545 // All other cases use the default, browser-wide, storage partition. 546 partition_domain->clear(); 547 partition_name->clear(); 548 *in_memory = false; 549} 550 551content::WebContentsViewDelegate* 552 ChromeContentBrowserClient::GetWebContentsViewDelegate( 553 content::WebContents* web_contents) { 554 return chrome::CreateWebContentsViewDelegate(web_contents); 555} 556 557void ChromeContentBrowserClient::RenderViewHostCreated( 558 RenderViewHost* render_view_host) { 559 560 SiteInstance* site_instance = render_view_host->GetSiteInstance(); 561 Profile* profile = Profile::FromBrowserContext( 562 site_instance->GetBrowserContext()); 563 564 new ChromeRenderViewHostObserver(render_view_host, 565 profile->GetNetworkPredictor()); 566 new extensions::MessageHandler(render_view_host); 567} 568 569void ChromeContentBrowserClient::RenderProcessHostCreated( 570 content::RenderProcessHost* host) { 571 int id = host->GetID(); 572 Profile* profile = Profile::FromBrowserContext(host->GetBrowserContext()); 573 host->GetChannel()->AddFilter(new ChromeRenderMessageFilter( 574 id, profile, profile->GetRequestContextForRenderProcess(id))); 575 host->GetChannel()->AddFilter(new PluginInfoMessageFilter(id, profile)); 576#if defined(ENABLE_PRINTING) 577 host->GetChannel()->AddFilter(new PrintingMessageFilter(id, profile)); 578#endif 579 host->GetChannel()->AddFilter( 580 new SearchProviderInstallStateMessageFilter(id, profile)); 581 host->GetChannel()->AddFilter(new SpellCheckMessageFilter(id)); 582#if defined(OS_MACOSX) 583 host->GetChannel()->AddFilter(new SpellCheckMessageFilterMac()); 584#endif 585 host->GetChannel()->AddFilter(new ChromeBenchmarkingMessageFilter( 586 id, profile, profile->GetRequestContextForRenderProcess(id))); 587 host->GetChannel()->AddFilter( 588 new prerender::PrerenderMessageFilter(id, profile)); 589 590 host->Send(new ChromeViewMsg_SetIsIncognitoProcess( 591 profile->IsOffTheRecord())); 592 593 SendExtensionWebRequestStatusToHost(host); 594 595 RendererContentSettingRules rules; 596 GetRendererContentSettingRules(profile->GetHostContentSettingsMap(), &rules); 597 host->Send(new ChromeViewMsg_SetContentSettingRules(rules)); 598 599#if defined(OS_ANDROID) && defined(USE_LINUX_BREAKPAD) 600 InitCrashDumpManager(); 601#endif 602} 603 604void ChromeContentBrowserClient::BrowserChildProcessHostCreated( 605 content::BrowserChildProcessHost* host) { 606 host->GetHost()->AddFilter(new PepperGtalkMessageFilter()); 607} 608 609content::WebUIControllerFactory* 610 ChromeContentBrowserClient::GetWebUIControllerFactory() { 611 return ChromeWebUIControllerFactory::GetInstance(); 612} 613 614GURL ChromeContentBrowserClient::GetEffectiveURL( 615 content::BrowserContext* browser_context, const GURL& url) { 616 Profile* profile = Profile::FromBrowserContext(browser_context); 617 // Get the effective URL for the given actual URL. If the URL is part of an 618 // installed app, the effective URL is an extension URL with the ID of that 619 // extension as the host. This has the effect of grouping apps together in 620 // a common SiteInstance. 621 if (!profile || !profile->GetExtensionService()) 622 return url; 623 624 const Extension* extension = profile->GetExtensionService()->extensions()-> 625 GetHostedAppByURL(ExtensionURLInfo(url)); 626 if (!extension) 627 return url; 628 629 // Bookmark apps do not use the hosted app process model, and should be 630 // treated as normal URLs. 631 if (extension->from_bookmark()) 632 return url; 633 634 // If the URL is part of an extension's web extent, convert it to an 635 // extension URL. 636 return extension->GetResourceURL(url.path()); 637} 638 639bool ChromeContentBrowserClient::ShouldUseProcessPerSite( 640 content::BrowserContext* browser_context, const GURL& effective_url) { 641 // Non-extension URLs should generally use process-per-site-instance. 642 // Because we expect to use the effective URL, URLs for hosted apps (apart 643 // from bookmark apps) should have an extension scheme by now. 644 if (!effective_url.SchemeIs(chrome::kExtensionScheme)) 645 return false; 646 647 Profile* profile = Profile::FromBrowserContext(browser_context); 648 if (!profile || !profile->GetExtensionService()) 649 return false; 650 651 const Extension* extension = profile->GetExtensionService()->extensions()-> 652 GetExtensionOrAppByURL(ExtensionURLInfo(effective_url)); 653 if (!extension) 654 return false; 655 656 // If the URL is part of a hosted app that does not have the background 657 // permission, or that does not allow JavaScript access to the background 658 // page, we want to give each instance its own process to improve 659 // responsiveness. 660 if (extension->GetType() == Extension::TYPE_HOSTED_APP) { 661 if (!extension->HasAPIPermission(APIPermission::kBackground) || 662 !extension->allow_background_js_access()) { 663 return false; 664 } 665 } 666 667 // Hosted apps that have script access to their background page must use 668 // process per site, since all instances can make synchronous calls to the 669 // background window. Other extensions should use process per site as well. 670 return true; 671} 672 673bool ChromeContentBrowserClient::IsHandledURL(const GURL& url) { 674 return ProfileIOData::IsHandledURL(url); 675} 676 677bool ChromeContentBrowserClient::IsSuitableHost( 678 content::RenderProcessHost* process_host, 679 const GURL& site_url) { 680 Profile* profile = 681 Profile::FromBrowserContext(process_host->GetBrowserContext()); 682 ExtensionService* service = profile->GetExtensionService(); 683 extensions::ProcessMap* process_map = service->process_map(); 684 685 // Don't allow the Task Manager to share a process with anything else. 686 // Otherwise it can affect the renderers it is observing. 687 // Note: we could create another RenderProcessHostPrivilege bucket for 688 // this to allow multiple chrome://tasks instances to share, but that's 689 // a very unlikely case without serious consequences. 690 if (site_url.GetOrigin() == GURL(chrome::kChromeUITaskManagerURL).GetOrigin()) 691 return false; 692 693 // These may be NULL during tests. In that case, just assume any site can 694 // share any host. 695 if (!service || !process_map) 696 return true; 697 698 // Experimental: 699 // If --enable-strict-site-isolation is enabled, do not allow non-WebUI pages 700 // to share a renderer process. (We could allow pages from the same site or 701 // extensions of the same type to share, if we knew what the given process 702 // was dedicated to. Allowing no sharing is simpler for now.) This may 703 // cause resource exhaustion issues if too many sites are open at once. 704 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 705 if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) 706 return false; 707 708 // Otherwise, just make sure the process privilege matches the privilege 709 // required by the site. 710 RenderProcessHostPrivilege privilege_required = 711 GetPrivilegeRequiredByUrl(site_url, service); 712 return GetProcessPrivilege(process_host, process_map, service) == 713 privilege_required; 714} 715 716// This function is trying to limit the amount of processes used by extensions 717// with background pages. It uses a globally set percentage of processes to 718// run such extensions and if the limit is exceeded, it returns true, to 719// indicate to the content module to group extensions together. 720bool ChromeContentBrowserClient::ShouldTryToUseExistingProcessHost( 721 content::BrowserContext* browser_context, const GURL& url) { 722 // It has to be a valid URL for us to check for an extension. 723 if (!url.is_valid()) 724 return false; 725 726 Profile* profile = Profile::FromBrowserContext(browser_context); 727 ExtensionService* service = profile->GetExtensionService(); 728 if (!service) 729 return false; 730 731 // We have to have a valid extension with background page to proceed. 732 const Extension* extension = 733 service->extensions()->GetExtensionOrAppByURL(ExtensionURLInfo(url)); 734 if (!extension) 735 return false; 736 if (!extension->has_background_page()) 737 return false; 738 739 std::set<int> process_ids; 740 size_t max_process_count = 741 content::RenderProcessHost::GetMaxRendererProcessCount(); 742 743 // Go through all profiles to ensure we have total count of extension 744 // processes containing background pages, otherwise one profile can 745 // starve the other. 746 std::vector<Profile*> profiles = g_browser_process->profile_manager()-> 747 GetLoadedProfiles(); 748 for (size_t i = 0; i < profiles.size(); ++i) { 749 ExtensionProcessManager* epm = 750 extensions::ExtensionSystem::Get(profiles[i])->process_manager(); 751 for (ExtensionProcessManager::const_iterator iter = 752 epm->background_hosts().begin(); 753 iter != epm->background_hosts().end(); ++iter) { 754 const extensions::ExtensionHost* host = *iter; 755 process_ids.insert(host->render_process_host()->GetID()); 756 } 757 } 758 759 if (process_ids.size() > 760 (max_process_count * chrome::kMaxShareOfExtensionProcesses)) { 761 return true; 762 } 763 764 return false; 765} 766 767void ChromeContentBrowserClient::SiteInstanceGotProcess( 768 SiteInstance* site_instance) { 769 CHECK(site_instance->HasProcess()); 770 771 Profile* profile = Profile::FromBrowserContext( 772 site_instance->GetBrowserContext()); 773 ExtensionService* service = profile->GetExtensionService(); 774 if (!service) 775 return; 776 777 const Extension* extension = 778 service->extensions()->GetExtensionOrAppByURL(ExtensionURLInfo( 779 site_instance->GetSiteURL())); 780 if (!extension) 781 return; 782 783 service->process_map()->Insert(extension->id(), 784 site_instance->GetProcess()->GetID(), 785 site_instance->GetId()); 786 BrowserThread::PostTask( 787 BrowserThread::IO, FROM_HERE, 788 base::Bind(&ExtensionInfoMap::RegisterExtensionProcess, 789 extensions::ExtensionSystem::Get(profile)->info_map(), 790 extension->id(), 791 site_instance->GetProcess()->GetID(), 792 site_instance->GetId())); 793} 794 795void ChromeContentBrowserClient::SiteInstanceDeleting( 796 SiteInstance* site_instance) { 797 if (!site_instance->HasProcess()) 798 return; 799 800 Profile* profile = Profile::FromBrowserContext( 801 site_instance->GetBrowserContext()); 802 ExtensionService* service = profile->GetExtensionService(); 803 if (!service) 804 return; 805 806 const Extension* extension = 807 service->extensions()->GetExtensionOrAppByURL( 808 ExtensionURLInfo(site_instance->GetSiteURL())); 809 if (!extension) 810 return; 811 812 service->process_map()->Remove(extension->id(), 813 site_instance->GetProcess()->GetID(), 814 site_instance->GetId()); 815 BrowserThread::PostTask( 816 BrowserThread::IO, FROM_HERE, 817 base::Bind(&ExtensionInfoMap::UnregisterExtensionProcess, 818 extensions::ExtensionSystem::Get(profile)->info_map(), 819 extension->id(), 820 site_instance->GetProcess()->GetID(), 821 site_instance->GetId())); 822} 823 824bool ChromeContentBrowserClient::ShouldSwapProcessesForNavigation( 825 const GURL& current_url, 826 const GURL& new_url) { 827 if (current_url.is_empty()) { 828 // Always choose a new process when navigating to extension URLs. The 829 // process grouping logic will combine all of a given extension's pages 830 // into the same process. 831 if (new_url.SchemeIs(chrome::kExtensionScheme)) 832 return true; 833 834 return false; 835 } 836 837 // Also, we must switch if one is an extension and the other is not the exact 838 // same extension. 839 if (current_url.SchemeIs(chrome::kExtensionScheme) || 840 new_url.SchemeIs(chrome::kExtensionScheme)) { 841 if (current_url.GetOrigin() != new_url.GetOrigin()) 842 return true; 843 } 844 845 return false; 846} 847 848bool ChromeContentBrowserClient::ShouldSwapProcessesForRedirect( 849 content::ResourceContext* resource_context, const GURL& current_url, 850 const GURL& new_url) { 851 ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context); 852 return extensions::CrossesExtensionProcessBoundary( 853 io_data->GetExtensionInfoMap()->extensions(), 854 ExtensionURLInfo(current_url), ExtensionURLInfo(new_url), false); 855} 856 857std::string ChromeContentBrowserClient::GetCanonicalEncodingNameByAliasName( 858 const std::string& alias_name) { 859 return CharacterEncoding::GetCanonicalEncodingNameByAliasName(alias_name); 860} 861 862void ChromeContentBrowserClient::AppendExtraCommandLineSwitches( 863 CommandLine* command_line, int child_process_id) { 864#if defined(USE_LINUX_BREAKPAD) 865 if (IsCrashReporterEnabled()) { 866 command_line->AppendSwitchASCII(switches::kEnableCrashReporter, 867 child_process_logging::GetClientId() + "," + base::GetLinuxDistro()); 868 } 869#elif defined(OS_MACOSX) 870 if (IsCrashReporterEnabled()) { 871 command_line->AppendSwitchASCII(switches::kEnableCrashReporter, 872 child_process_logging::GetClientId()); 873 } 874#endif // OS_MACOSX 875 876 if (logging::DialogsAreSuppressed()) 877 command_line->AppendSwitch(switches::kNoErrorDialogs); 878 879 std::string process_type = 880 command_line->GetSwitchValueASCII(switches::kProcessType); 881 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 882 if (process_type == switches::kRendererProcess) { 883 FilePath user_data_dir = 884 browser_command_line.GetSwitchValuePath(switches::kUserDataDir); 885 if (!user_data_dir.empty()) 886 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir); 887#if defined(OS_CHROMEOS) 888 const std::string& login_profile = 889 browser_command_line.GetSwitchValueASCII(switches::kLoginProfile); 890 if (!login_profile.empty()) 891 command_line->AppendSwitchASCII(switches::kLoginProfile, login_profile); 892#endif 893 894 content::RenderProcessHost* process = 895 content::RenderProcessHost::FromID(child_process_id); 896 if (process) { 897 Profile* profile = Profile::FromBrowserContext( 898 process->GetBrowserContext()); 899 if (profile->GetExtensionService()) { 900 extensions::ProcessMap* process_map = 901 profile->GetExtensionService()->process_map(); 902 if (process_map && process_map->Contains(process->GetID())) 903 command_line->AppendSwitch(switches::kExtensionProcess); 904 } 905 906 PrefService* prefs = profile->GetPrefs(); 907 // Currently this pref is only registered if applied via a policy. 908 if (prefs->HasPrefPath(prefs::kDisable3DAPIs) && 909 prefs->GetBoolean(prefs::kDisable3DAPIs)) { 910 // Turn this policy into a command line switch. 911 command_line->AppendSwitch(switches::kDisable3DAPIs); 912 } 913 914 // Disable client-side phishing detection in the renderer if it is 915 // disabled in the Profile preferences or the browser process. 916 if (!prefs->GetBoolean(prefs::kSafeBrowsingEnabled) || 917 !g_browser_process->safe_browsing_detection_service()) { 918 command_line->AppendSwitch( 919 switches::kDisableClientSidePhishingDetection); 920 } 921 922 if (!prefs->GetBoolean(prefs::kPrintPreviewDisabled)) 923 command_line->AppendSwitch(switches::kRendererPrintPreview); 924 } 925 926 if (content::IsThreadedCompositingEnabled()) 927 command_line->AppendSwitch(switches::kEnableThreadedCompositing); 928 929 // Please keep this in alphabetical order. 930 static const char* const kSwitchNames[] = { 931 switches::kAllowHTTPBackgroundPage, 932 switches::kAllowLegacyExtensionManifests, 933 switches::kAllowScriptingGallery, 934 switches::kAppsCheckoutURL, 935 switches::kAppsGalleryURL, 936 switches::kCloudPrintServiceURL, 937 switches::kDebugPrint, 938 switches::kDisableBundledPpapiFlash, 939 switches::kDisableExtensionsResourceWhitelist, 940 switches::kDisableScriptedPrintThrottling, 941 switches::kDumpHistogramsOnExit, 942 switches::kEnableBenchmarking, 943 switches::kEnableBundledPpapiFlash, 944 switches::kEnableChromeStyleDialogs, 945 switches::kEnableCrxlessWebApps, 946 switches::kEnableExperimentalExtensionApis, 947 switches::kEnableIPCFuzzing, 948 switches::kEnableInteractiveAutocomplete, 949 switches::kEnableNaCl, 950 switches::kEnableNaClSRPCProxy, 951 switches::kEnablePasswordGeneration, 952 switches::kEnablePnacl, 953 switches::kEnableWatchdog, 954 switches::kMemoryProfiling, 955 switches::kMessageLoopHistogrammer, 956 switches::kNoJsRandomness, 957 switches::kPerformCrashAnalysis, 958 switches::kPlaybackMode, 959 switches::kPpapiFlashArgs, 960 switches::kPpapiFlashInProcess, 961 switches::kPpapiFlashPath, 962 switches::kPpapiFlashVersion, 963 switches::kProfilingAtStart, 964 switches::kProfilingFile, 965 switches::kProfilingFlush, 966 switches::kRecordMode, 967 switches::kSilentDumpOnDCHECK, 968 switches::kSpdyProxyOrigin, 969 switches::kWhitelistedExtensionID, 970 }; 971 972 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 973 arraysize(kSwitchNames)); 974 } else if (process_type == switches::kUtilityProcess) { 975 static const char* const kSwitchNames[] = { 976 switches::kAllowHTTPBackgroundPage, 977 switches::kEnableExperimentalExtensionApis, 978 switches::kWhitelistedExtensionID, 979 }; 980 981 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 982 arraysize(kSwitchNames)); 983 } else if (process_type == switches::kPluginProcess) { 984 static const char* const kSwitchNames[] = { 985 #if defined(OS_CHROMEOS) 986 switches::kLoginProfile, 987 #endif 988 switches::kMemoryProfiling, 989 switches::kSilentDumpOnDCHECK, 990 switches::kUserDataDir, 991 }; 992 993 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 994 arraysize(kSwitchNames)); 995 } else if (process_type == switches::kZygoteProcess) { 996 static const char* const kSwitchNames[] = { 997 switches::kUserDataDir, // Make logs go to the right file. 998 // Load (in-process) Pepper plugins in-process in the zygote pre-sandbox. 999 switches::kDisableBundledPpapiFlash, 1000 switches::kEnableBundledPpapiFlash, 1001 switches::kPpapiFlashInProcess, 1002 switches::kPpapiFlashPath, 1003 switches::kPpapiFlashVersion, 1004 }; 1005 1006 command_line->CopySwitchesFrom(browser_command_line, kSwitchNames, 1007 arraysize(kSwitchNames)); 1008 } else if (process_type == switches::kGpuProcess) { 1009 // If --ignore-gpu-blacklist is passed in, don't send in crash reports 1010 // because GPU is expected to be unreliable. 1011 if (browser_command_line.HasSwitch(switches::kIgnoreGpuBlacklist) && 1012 !command_line->HasSwitch(switches::kDisableBreakpad)) 1013 command_line->AppendSwitch(switches::kDisableBreakpad); 1014 } 1015 1016 // The command line switch kEnableBenchmarking needs to be specified along 1017 // with the kEnableStatsTable switch to ensure that the stats table global 1018 // is initialized correctly. 1019 if (command_line->HasSwitch(switches::kEnableBenchmarking)) 1020 DCHECK(command_line->HasSwitch(switches::kEnableStatsTable)); 1021} 1022 1023std::string ChromeContentBrowserClient::GetApplicationLocale() { 1024 if (BrowserThread::CurrentlyOn(BrowserThread::IO)) 1025 return io_thread_application_locale_; 1026 return g_browser_process->GetApplicationLocale(); 1027} 1028 1029std::string ChromeContentBrowserClient::GetAcceptLangs( 1030 content::BrowserContext* context) { 1031 Profile* profile = Profile::FromBrowserContext(context); 1032 return profile->GetPrefs()->GetString(prefs::kAcceptLanguages); 1033} 1034 1035gfx::ImageSkia* ChromeContentBrowserClient::GetDefaultFavicon() { 1036 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 1037 return rb.GetImageSkiaNamed(IDR_DEFAULT_FAVICON); 1038} 1039 1040bool ChromeContentBrowserClient::AllowAppCache( 1041 const GURL& manifest_url, 1042 const GURL& first_party, 1043 content::ResourceContext* context) { 1044 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1045 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1046 return io_data->GetCookieSettings()-> 1047 IsSettingCookieAllowed(manifest_url, first_party); 1048} 1049 1050bool ChromeContentBrowserClient::AllowGetCookie( 1051 const GURL& url, 1052 const GURL& first_party, 1053 const net::CookieList& cookie_list, 1054 content::ResourceContext* context, 1055 int render_process_id, 1056 int render_view_id) { 1057 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1058 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1059 bool allow = io_data->GetCookieSettings()-> 1060 IsReadingCookieAllowed(url, first_party); 1061 1062 BrowserThread::PostTask( 1063 BrowserThread::UI, FROM_HERE, 1064 base::Bind(&TabSpecificContentSettings::CookiesRead, render_process_id, 1065 render_view_id, url, first_party, cookie_list, !allow)); 1066 return allow; 1067} 1068 1069bool ChromeContentBrowserClient::AllowSetCookie( 1070 const GURL& url, 1071 const GURL& first_party, 1072 const std::string& cookie_line, 1073 content::ResourceContext* context, 1074 int render_process_id, 1075 int render_view_id, 1076 net::CookieOptions* options) { 1077 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1078 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1079 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1080 bool allow = cookie_settings->IsSettingCookieAllowed(url, first_party); 1081 1082 BrowserThread::PostTask( 1083 BrowserThread::UI, FROM_HERE, 1084 base::Bind(&TabSpecificContentSettings::CookieChanged, render_process_id, 1085 render_view_id, url, first_party, cookie_line, *options, 1086 !allow)); 1087 return allow; 1088} 1089 1090bool ChromeContentBrowserClient::AllowPluginLocalDataAccess( 1091 const GURL& document_url, 1092 const GURL& plugin_url, 1093 content::ResourceContext* context) { 1094 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1095 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1096 return io_data->GetCookieSettings()->IsReadingCookieAllowed(document_url, 1097 plugin_url); 1098} 1099 1100bool ChromeContentBrowserClient::AllowPluginLocalDataSessionOnly( 1101 const GURL& url, 1102 content::ResourceContext* context) { 1103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1104 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1105 return io_data->GetCookieSettings()->IsCookieSessionOnly(url); 1106} 1107 1108bool ChromeContentBrowserClient::AllowSaveLocalState( 1109 content::ResourceContext* context) { 1110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1111 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1112 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1113 ContentSetting setting = cookie_settings->GetDefaultCookieSetting(NULL); 1114 1115 // TODO(bauerb): Should we also disallow local state if the default is BLOCK? 1116 // Could we even support per-origin settings? 1117 return setting != CONTENT_SETTING_SESSION_ONLY; 1118} 1119 1120bool ChromeContentBrowserClient::AllowWorkerDatabase( 1121 const GURL& url, 1122 const string16& name, 1123 const string16& display_name, 1124 unsigned long estimated_size, 1125 content::ResourceContext* context, 1126 const std::vector<std::pair<int, int> >& render_views) { 1127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1128 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1129 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1130 bool allow = cookie_settings->IsSettingCookieAllowed(url, url); 1131 1132 // Record access to database for potential display in UI. 1133 std::vector<std::pair<int, int> >::const_iterator i; 1134 for (i = render_views.begin(); i != render_views.end(); ++i) { 1135 BrowserThread::PostTask( 1136 BrowserThread::UI, FROM_HERE, 1137 base::Bind(&TabSpecificContentSettings::WebDatabaseAccessed, 1138 i->first, i->second, url, name, display_name, !allow)); 1139 } 1140 1141 return allow; 1142} 1143 1144bool ChromeContentBrowserClient::AllowWorkerFileSystem( 1145 const GURL& url, 1146 content::ResourceContext* context, 1147 const std::vector<std::pair<int, int> >& render_views) { 1148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1149 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1150 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1151 bool allow = cookie_settings->IsSettingCookieAllowed(url, url); 1152 1153 // Record access to file system for potential display in UI. 1154 std::vector<std::pair<int, int> >::const_iterator i; 1155 for (i = render_views.begin(); i != render_views.end(); ++i) { 1156 BrowserThread::PostTask( 1157 BrowserThread::UI, FROM_HERE, 1158 base::Bind(&TabSpecificContentSettings::FileSystemAccessed, 1159 i->first, i->second, url, !allow)); 1160 } 1161 1162 return allow; 1163} 1164 1165bool ChromeContentBrowserClient::AllowWorkerIndexedDB( 1166 const GURL& url, 1167 const string16& name, 1168 content::ResourceContext* context, 1169 const std::vector<std::pair<int, int> >& render_views) { 1170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1171 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1172 CookieSettings* cookie_settings = io_data->GetCookieSettings(); 1173 bool allow = cookie_settings->IsSettingCookieAllowed(url, url); 1174 1175 // Record access to IndexedDB for potential display in UI. 1176 std::vector<std::pair<int, int> >::const_iterator i; 1177 for (i = render_views.begin(); i != render_views.end(); ++i) { 1178 BrowserThread::PostTask( 1179 BrowserThread::UI, FROM_HERE, 1180 base::Bind(&TabSpecificContentSettings::IndexedDBAccessed, 1181 i->first, i->second, url, name, !allow)); 1182 } 1183 1184 return allow; 1185} 1186 1187net::URLRequestContext* 1188ChromeContentBrowserClient::OverrideRequestContextForURL( 1189 const GURL& url, content::ResourceContext* context) { 1190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1191 if (url.SchemeIs(chrome::kExtensionScheme)) { 1192 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1193 return io_data->extensions_request_context(); 1194 } 1195 1196 return NULL; 1197} 1198 1199QuotaPermissionContext* 1200ChromeContentBrowserClient::CreateQuotaPermissionContext() { 1201 return new ChromeQuotaPermissionContext(); 1202} 1203 1204void ChromeContentBrowserClient::OpenItem(const FilePath& path) { 1205 platform_util::OpenItem(path); 1206} 1207 1208void ChromeContentBrowserClient::ShowItemInFolder(const FilePath& path) { 1209 platform_util::ShowItemInFolder(path); 1210} 1211 1212void ChromeContentBrowserClient::AllowCertificateError( 1213 int render_process_id, 1214 int render_view_id, 1215 int cert_error, 1216 const net::SSLInfo& ssl_info, 1217 const GURL& request_url, 1218 bool overridable, 1219 bool strict_enforcement, 1220 const base::Callback<void(bool)>& callback, 1221 bool* cancel_request) { 1222 // If the tab is being prerendered, cancel the prerender and the request. 1223 WebContents* tab = tab_util::GetWebContentsByID( 1224 render_process_id, render_view_id); 1225 if (!tab) { 1226 NOTREACHED(); 1227 return; 1228 } 1229 prerender::PrerenderManager* prerender_manager = 1230 prerender::PrerenderManagerFactory::GetForProfile( 1231 Profile::FromBrowserContext(tab->GetBrowserContext())); 1232 if (prerender_manager && prerender_manager->IsWebContentsPrerendering(tab, 1233 NULL)) { 1234 if (prerender_manager->prerender_tracker()->TryCancel( 1235 render_process_id, render_view_id, 1236 prerender::FINAL_STATUS_SSL_ERROR)) { 1237 *cancel_request = true; 1238 return; 1239 } 1240 } 1241 1242#if defined(ENABLE_CAPTIVE_PORTAL_DETECTION) 1243 captive_portal::CaptivePortalTabHelper* captive_portal_tab_helper = 1244 captive_portal::CaptivePortalTabHelper::FromWebContents(tab); 1245 if (captive_portal_tab_helper) 1246 captive_portal_tab_helper->OnSSLCertError(ssl_info); 1247#endif 1248 1249 // Otherwise, display an SSL blocking page. 1250 new SSLBlockingPage(tab, cert_error, ssl_info, request_url, overridable, 1251 strict_enforcement, callback); 1252} 1253 1254void ChromeContentBrowserClient::SelectClientCertificate( 1255 int render_process_id, 1256 int render_view_id, 1257 const net::HttpNetworkSession* network_session, 1258 net::SSLCertRequestInfo* cert_request_info, 1259 const base::Callback<void(net::X509Certificate*)>& callback) { 1260 WebContents* tab = tab_util::GetWebContentsByID( 1261 render_process_id, render_view_id); 1262 if (!tab) { 1263 NOTREACHED(); 1264 return; 1265 } 1266 1267 GURL requesting_url("https://" + cert_request_info->host_and_port); 1268 DCHECK(requesting_url.is_valid()) << "Invalid URL string: https://" 1269 << cert_request_info->host_and_port; 1270 1271 Profile* profile = Profile::FromBrowserContext(tab->GetBrowserContext()); 1272 scoped_ptr<Value> filter( 1273 profile->GetHostContentSettingsMap()->GetWebsiteSetting( 1274 requesting_url, 1275 requesting_url, 1276 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 1277 std::string(), NULL)); 1278 1279 if (filter.get()) { 1280 // Try to automatically select a client certificate. 1281 if (filter->IsType(Value::TYPE_DICTIONARY)) { 1282 DictionaryValue* filter_dict = 1283 static_cast<DictionaryValue*>(filter.get()); 1284 1285 const std::vector<scoped_refptr<net::X509Certificate> >& 1286 all_client_certs = cert_request_info->client_certs; 1287 for (size_t i = 0; i < all_client_certs.size(); ++i) { 1288 if (CertMatchesFilter(*all_client_certs[i], *filter_dict)) { 1289 // Use the first certificate that is matched by the filter. 1290 callback.Run(all_client_certs[i]); 1291 return; 1292 } 1293 } 1294 } else { 1295 NOTREACHED(); 1296 } 1297 } 1298 1299 SSLTabHelper* ssl_tab_helper = SSLTabHelper::FromWebContents(tab); 1300 if (!ssl_tab_helper) { 1301 // If there is no SSLTabHelper for the given WebContents then we can't 1302 // show the user a dialog to select a client certificate. So we simply 1303 // proceed with no client certificate. 1304 callback.Run(NULL); 1305 return; 1306 } 1307 ssl_tab_helper->ShowClientCertificateRequestDialog( 1308 network_session, cert_request_info, callback); 1309} 1310 1311void ChromeContentBrowserClient::AddNewCertificate( 1312 net::URLRequest* request, 1313 net::X509Certificate* cert, 1314 int render_process_id, 1315 int render_view_id) { 1316 // The handler will run the UI and delete itself when it's finished. 1317 new SSLAddCertHandler(request, cert, render_process_id, render_view_id); 1318} 1319 1320content::MediaObserver* ChromeContentBrowserClient::GetMediaObserver() { 1321 return MediaInternals::GetInstance(); 1322} 1323 1324void ChromeContentBrowserClient::RequestDesktopNotificationPermission( 1325 const GURL& source_origin, 1326 int callback_context, 1327 int render_process_id, 1328 int render_view_id) { 1329#if defined(ENABLE_NOTIFICATIONS) 1330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1331 WebContents* contents = 1332 tab_util::GetWebContentsByID(render_process_id, render_view_id); 1333 if (!contents) { 1334 NOTREACHED(); 1335 return; 1336 } 1337 1338 // Skip showing the infobar if the request comes from an extension, and that 1339 // extension has the 'notify' permission. (If the extension does not have the 1340 // permission, the user will still be prompted.) 1341 Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext()); 1342 ExtensionService* service = profile->GetExtensionService(); 1343 const Extension* extension = !service ? NULL : 1344 service->extensions()->GetExtensionOrAppByURL(ExtensionURLInfo( 1345 source_origin)); 1346 if (extension && 1347 extension->HasAPIPermission(APIPermission::kNotification)) { 1348 RenderViewHost* rvh = 1349 RenderViewHost::FromID(render_process_id, render_view_id); 1350 if (rvh) 1351 rvh->DesktopNotificationPermissionRequestDone(callback_context); 1352 return; 1353 } 1354 1355 DesktopNotificationService* notifications = 1356 DesktopNotificationServiceFactory::GetForProfile(profile); 1357 notifications->RequestPermission(source_origin, render_process_id, 1358 render_view_id, callback_context, contents); 1359#else 1360 NOTIMPLEMENTED(); 1361#endif 1362} 1363 1364WebKit::WebNotificationPresenter::Permission 1365 ChromeContentBrowserClient::CheckDesktopNotificationPermission( 1366 const GURL& source_origin, 1367 content::ResourceContext* context, 1368 int render_process_id) { 1369#if defined(ENABLE_NOTIFICATIONS) 1370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1371 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1372 if (io_data->GetExtensionInfoMap()->SecurityOriginHasAPIPermission( 1373 source_origin, render_process_id, 1374 APIPermission::kNotification)) 1375 return WebKit::WebNotificationPresenter::PermissionAllowed; 1376 1377 // Fall back to the regular notification preferences, which works on an 1378 // origin basis. 1379 return io_data->GetNotificationService() ? 1380 io_data->GetNotificationService()->HasPermission(source_origin) : 1381 WebKit::WebNotificationPresenter::PermissionNotAllowed; 1382#else 1383 return WebKit::WebNotificationPresenter::PermissionAllowed; 1384#endif 1385} 1386 1387void ChromeContentBrowserClient::ShowDesktopNotification( 1388 const content::ShowDesktopNotificationHostMsgParams& params, 1389 int render_process_id, 1390 int render_view_id, 1391 bool worker) { 1392#if defined(ENABLE_NOTIFICATIONS) 1393 RenderViewHost* rvh = RenderViewHost::FromID( 1394 render_process_id, render_view_id); 1395 if (!rvh) { 1396 NOTREACHED(); 1397 return; 1398 } 1399 1400 content::RenderProcessHost* process = rvh->GetProcess(); 1401 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); 1402 DesktopNotificationService* service = 1403 DesktopNotificationServiceFactory::GetForProfile(profile); 1404 service->ShowDesktopNotification( 1405 params, render_process_id, render_view_id, 1406 worker ? DesktopNotificationService::WorkerNotification : 1407 DesktopNotificationService::PageNotification); 1408#else 1409 NOTIMPLEMENTED(); 1410#endif 1411} 1412 1413void ChromeContentBrowserClient::CancelDesktopNotification( 1414 int render_process_id, 1415 int render_view_id, 1416 int notification_id) { 1417#if defined(ENABLE_NOTIFICATIONS) 1418 RenderViewHost* rvh = RenderViewHost::FromID( 1419 render_process_id, render_view_id); 1420 if (!rvh) { 1421 NOTREACHED(); 1422 return; 1423 } 1424 1425 content::RenderProcessHost* process = rvh->GetProcess(); 1426 Profile* profile = Profile::FromBrowserContext(process->GetBrowserContext()); 1427 DesktopNotificationService* service = 1428 DesktopNotificationServiceFactory::GetForProfile(profile); 1429 service->CancelDesktopNotification( 1430 render_process_id, render_view_id, notification_id); 1431#else 1432 NOTIMPLEMENTED(); 1433#endif 1434} 1435 1436bool ChromeContentBrowserClient::CanCreateWindow( 1437 const GURL& opener_url, 1438 const GURL& source_origin, 1439 WindowContainerType container_type, 1440 content::ResourceContext* context, 1441 int render_process_id, 1442 bool* no_javascript_access) { 1443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1444 1445 *no_javascript_access = false; 1446 1447 // If the opener is trying to create a background window but doesn't have 1448 // the appropriate permission, fail the attempt. 1449 if (container_type == WINDOW_CONTAINER_TYPE_BACKGROUND) { 1450 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1451 ExtensionInfoMap* map = io_data->GetExtensionInfoMap(); 1452 1453 if (!map->SecurityOriginHasAPIPermission( 1454 source_origin, 1455 render_process_id, 1456 APIPermission::kBackground)) { 1457 return false; 1458 } 1459 1460 // Note: this use of GetExtensionOrAppByURL is safe but imperfect. It may 1461 // return a recently installed Extension even if this CanCreateWindow call 1462 // was made by an old copy of the page in a normal web process. That's ok, 1463 // because the permission check above would have caused an early return 1464 // already. We must use the full URL to find hosted apps, though, and not 1465 // just the origin. 1466 const Extension* extension = map->extensions().GetExtensionOrAppByURL( 1467 ExtensionURLInfo(opener_url)); 1468 if (extension && !extension->allow_background_js_access()) 1469 *no_javascript_access = true; 1470 } 1471 return true; 1472} 1473 1474std::string ChromeContentBrowserClient::GetWorkerProcessTitle( 1475 const GURL& url, content::ResourceContext* context) { 1476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1477 // Check if it's an extension-created worker, in which case we want to use 1478 // the name of the extension. 1479 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context); 1480 const Extension* extension = 1481 io_data->GetExtensionInfoMap()->extensions().GetByID(url.host()); 1482 return extension ? extension->name() : std::string(); 1483} 1484 1485void ChromeContentBrowserClient::ResourceDispatcherHostCreated() { 1486 return g_browser_process->ResourceDispatcherHostCreated(); 1487} 1488 1489content::SpeechRecognitionManagerDelegate* 1490 ChromeContentBrowserClient::GetSpeechRecognitionManagerDelegate() { 1491#if defined(ENABLE_INPUT_SPEECH) 1492 return new speech::ChromeSpeechRecognitionManagerDelegate(); 1493#else 1494 return NULL; 1495#endif 1496} 1497 1498net::NetLog* ChromeContentBrowserClient::GetNetLog() { 1499 return g_browser_process->net_log(); 1500} 1501 1502AccessTokenStore* ChromeContentBrowserClient::CreateAccessTokenStore() { 1503 return new ChromeAccessTokenStore(); 1504} 1505 1506bool ChromeContentBrowserClient::IsFastShutdownPossible() { 1507 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess(); 1508 return !browser_command_line.HasSwitch(switches::kChromeFrame); 1509} 1510 1511void ChromeContentBrowserClient::OverrideWebkitPrefs( 1512 RenderViewHost* rvh, const GURL& url, WebPreferences* web_prefs) { 1513 Profile* profile = Profile::FromBrowserContext( 1514 rvh->GetProcess()->GetBrowserContext()); 1515 PrefService* prefs = profile->GetPrefs(); 1516 1517 FillFontFamilyMap(prefs, prefs::kWebKitStandardFontFamilyMap, 1518 &web_prefs->standard_font_family_map); 1519 FillFontFamilyMap(prefs, prefs::kWebKitFixedFontFamilyMap, 1520 &web_prefs->fixed_font_family_map); 1521 FillFontFamilyMap(prefs, prefs::kWebKitSerifFontFamilyMap, 1522 &web_prefs->serif_font_family_map); 1523 FillFontFamilyMap(prefs, prefs::kWebKitSansSerifFontFamilyMap, 1524 &web_prefs->sans_serif_font_family_map); 1525 FillFontFamilyMap(prefs, prefs::kWebKitCursiveFontFamilyMap, 1526 &web_prefs->cursive_font_family_map); 1527 FillFontFamilyMap(prefs, prefs::kWebKitFantasyFontFamilyMap, 1528 &web_prefs->fantasy_font_family_map); 1529 FillFontFamilyMap(prefs, prefs::kWebKitPictographFontFamilyMap, 1530 &web_prefs->pictograph_font_family_map); 1531 1532 web_prefs->default_font_size = 1533 prefs->GetInteger(prefs::kWebKitDefaultFontSize); 1534 web_prefs->default_fixed_font_size = 1535 prefs->GetInteger(prefs::kWebKitDefaultFixedFontSize); 1536 web_prefs->minimum_font_size = 1537 prefs->GetInteger(prefs::kWebKitMinimumFontSize); 1538 web_prefs->minimum_logical_font_size = 1539 prefs->GetInteger(prefs::kWebKitMinimumLogicalFontSize); 1540 1541 web_prefs->default_encoding = prefs->GetString(prefs::kDefaultCharset); 1542 1543 web_prefs->javascript_can_open_windows_automatically = 1544 prefs->GetBoolean(prefs::kWebKitJavascriptCanOpenWindowsAutomatically); 1545 web_prefs->dom_paste_enabled = 1546 prefs->GetBoolean(prefs::kWebKitDomPasteEnabled); 1547 web_prefs->shrinks_standalone_images_to_fit = 1548 prefs->GetBoolean(prefs::kWebKitShrinksStandaloneImagesToFit); 1549 const DictionaryValue* inspector_settings = 1550 prefs->GetDictionary(prefs::kWebKitInspectorSettings); 1551 if (inspector_settings) { 1552 for (DictionaryValue::key_iterator iter(inspector_settings->begin_keys()); 1553 iter != inspector_settings->end_keys(); ++iter) { 1554 std::string value; 1555 if (inspector_settings->GetStringWithoutPathExpansion(*iter, &value)) 1556 web_prefs->inspector_settings.push_back( 1557 std::make_pair(*iter, value)); 1558 } 1559 } 1560 web_prefs->tabs_to_links = prefs->GetBoolean(prefs::kWebkitTabsToLinks); 1561 1562 if (!prefs->GetBoolean(prefs::kWebKitJavascriptEnabled)) 1563 web_prefs->javascript_enabled = false; 1564 if (!prefs->GetBoolean(prefs::kWebKitWebSecurityEnabled)) 1565 web_prefs->web_security_enabled = false; 1566 if (!prefs->GetBoolean(prefs::kWebKitPluginsEnabled)) 1567 web_prefs->plugins_enabled = false; 1568 if (!prefs->GetBoolean(prefs::kWebKitJavaEnabled)) 1569 web_prefs->java_enabled = false; 1570 web_prefs->loads_images_automatically = 1571 prefs->GetBoolean(prefs::kWebKitLoadsImagesAutomatically); 1572 1573 if (prefs->GetBoolean(prefs::kDisable3DAPIs)) 1574 web_prefs->experimental_webgl_enabled = false; 1575 1576 web_prefs->memory_info_enabled = 1577 prefs->GetBoolean(prefs::kEnableMemoryInfo); 1578 web_prefs->allow_displaying_insecure_content = 1579 prefs->GetBoolean(prefs::kWebKitAllowDisplayingInsecureContent); 1580 web_prefs->allow_running_insecure_content = 1581 prefs->GetBoolean(prefs::kWebKitAllowRunningInsecureContent); 1582#if defined(OS_ANDROID) 1583 web_prefs->font_scale_factor = 1584 static_cast<float>(prefs->GetDouble(prefs::kWebKitFontScaleFactor)); 1585 web_prefs->force_enable_zoom = 1586 prefs->GetBoolean(prefs::kWebKitForceEnableZoom); 1587#endif 1588 web_prefs->password_echo_enabled = browser_defaults::kPasswordEchoEnabled; 1589 1590 // The user stylesheet watcher may not exist in a testing profile. 1591 UserStyleSheetWatcher* user_style_sheet_watcher = 1592 UserStyleSheetWatcherFactory::GetForProfile(profile); 1593 if (user_style_sheet_watcher) { 1594 web_prefs->user_style_sheet_enabled = true; 1595 web_prefs->user_style_sheet_location = 1596 user_style_sheet_watcher->user_style_sheet(); 1597 } else { 1598 web_prefs->user_style_sheet_enabled = false; 1599 } 1600 1601 web_prefs->asynchronous_spell_checking_enabled = 1602#if defined(OS_MACOSX) 1603 // TODO(hbono): Bug 107371: Implement asynchronous spellchecking API for 1604 // Mac so it uses NSSpellChecker in the background. 1605 false; 1606#else 1607 !CommandLine::ForCurrentProcess()-> 1608 HasSwitch(switches::kForceSyncSpellCheck); 1609#endif 1610 web_prefs->unified_textchecker_enabled = 1611 web_prefs->asynchronous_spell_checking_enabled; 1612 1613 web_prefs->uses_universal_detector = 1614 prefs->GetBoolean(prefs::kWebKitUsesUniversalDetector); 1615 web_prefs->text_areas_are_resizable = 1616 prefs->GetBoolean(prefs::kWebKitTextAreasAreResizable); 1617 web_prefs->hyperlink_auditing_enabled = 1618 prefs->GetBoolean(prefs::kEnableHyperlinkAuditing); 1619 1620 // Make sure we will set the default_encoding with canonical encoding name. 1621 web_prefs->default_encoding = 1622 CharacterEncoding::GetCanonicalEncodingNameByAliasName( 1623 web_prefs->default_encoding); 1624 if (web_prefs->default_encoding.empty()) { 1625 prefs->ClearPref(prefs::kDefaultCharset); 1626 web_prefs->default_encoding = prefs->GetString(prefs::kDefaultCharset); 1627 } 1628 DCHECK(!web_prefs->default_encoding.empty()); 1629 1630 WebContents* web_contents = WebContents::FromRenderViewHost(rvh); 1631 chrome::ViewType view_type = chrome::GetViewType(web_contents); 1632 ExtensionService* service = profile->GetExtensionService(); 1633 if (service) { 1634 const GURL& url = rvh->GetSiteInstance()->GetSiteURL(); 1635 const Extension* extension = service->extensions()->GetByID(url.host()); 1636 // Ensure that we are only granting extension preferences to URLs with 1637 // the correct scheme. Without this check, chrome-guest:// schemes used by 1638 // webview tags as well as hosts that happen to match the id of an 1639 // installed extension would get the wrong preferences. 1640 if (url.SchemeIs(chrome::kExtensionScheme)) { 1641 extension_webkit_preferences::SetPreferences( 1642 extension, view_type, web_prefs); 1643 } 1644 } 1645 1646 if (content::IsForceCompositingModeEnabled()) 1647 web_prefs->force_compositing_mode = true; 1648 1649 if (view_type == chrome::VIEW_TYPE_NOTIFICATION) { 1650 web_prefs->allow_scripts_to_close_windows = true; 1651 } else if (view_type == chrome::VIEW_TYPE_BACKGROUND_CONTENTS) { 1652 // Disable all kinds of acceleration for background pages. 1653 // See http://crbug.com/96005 and http://crbug.com/96006 1654 web_prefs->force_compositing_mode = false; 1655 web_prefs->accelerated_compositing_enabled = false; 1656 web_prefs->accelerated_2d_canvas_enabled = false; 1657 web_prefs->accelerated_video_enabled = false; 1658 web_prefs->accelerated_painting_enabled = false; 1659 web_prefs->accelerated_plugins_enabled = false; 1660 } 1661 1662#if defined(FILE_MANAGER_EXTENSION) 1663 // Override the default of suppressing HW compositing for WebUI pages for the 1664 // file manager, which is implemented using WebUI but wants HW acceleration 1665 // for video decode & render. 1666 if (url.spec() == chrome::kChromeUIFileManagerURL) { 1667 web_prefs->accelerated_compositing_enabled = true; 1668 web_prefs->accelerated_2d_canvas_enabled = true; 1669 } 1670#endif 1671} 1672 1673void ChromeContentBrowserClient::UpdateInspectorSetting( 1674 RenderViewHost* rvh, const std::string& key, const std::string& value) { 1675 content::BrowserContext* browser_context = 1676 rvh->GetProcess()->GetBrowserContext(); 1677 DictionaryPrefUpdate update( 1678 Profile::FromBrowserContext(browser_context)->GetPrefs(), 1679 prefs::kWebKitInspectorSettings); 1680 DictionaryValue* inspector_settings = update.Get(); 1681 inspector_settings->SetWithoutPathExpansion(key, 1682 Value::CreateStringValue(value)); 1683} 1684 1685void ChromeContentBrowserClient::ClearInspectorSettings(RenderViewHost* rvh) { 1686 content::BrowserContext* browser_context = 1687 rvh->GetProcess()->GetBrowserContext(); 1688 Profile::FromBrowserContext(browser_context)->GetPrefs()-> 1689 ClearPref(prefs::kWebKitInspectorSettings); 1690} 1691 1692void ChromeContentBrowserClient::BrowserURLHandlerCreated( 1693 BrowserURLHandler* handler) { 1694 // Add the default URL handlers. 1695 handler->AddHandlerPair(&ExtensionWebUI::HandleChromeURLOverride, 1696 BrowserURLHandler::null_handler()); 1697 handler->AddHandlerPair(BrowserURLHandler::null_handler(), 1698 &ExtensionWebUI::HandleChromeURLOverrideReverse); 1699 1700 // about: handler. Must come before chrome: handler, since it will 1701 // rewrite about: urls to chrome: URLs and then expect chrome: to 1702 // actually handle them. 1703 handler->AddHandlerPair(&WillHandleBrowserAboutURL, 1704 BrowserURLHandler::null_handler()); 1705 // chrome: & friends. 1706 handler->AddHandlerPair(&HandleWebUI, &HandleWebUIReverse); 1707} 1708 1709void ChromeContentBrowserClient::ClearCache(RenderViewHost* rvh) { 1710 Profile* profile = Profile::FromBrowserContext( 1711 rvh->GetSiteInstance()->GetProcess()->GetBrowserContext()); 1712 BrowsingDataRemover* remover = 1713 BrowsingDataRemover::CreateForUnboundedRange(profile); 1714 remover->Remove(BrowsingDataRemover::REMOVE_CACHE, 1715 BrowsingDataHelper::UNPROTECTED_WEB); 1716 // BrowsingDataRemover takes care of deleting itself when done. 1717} 1718 1719void ChromeContentBrowserClient::ClearCookies(RenderViewHost* rvh) { 1720 Profile* profile = Profile::FromBrowserContext( 1721 rvh->GetSiteInstance()->GetProcess()->GetBrowserContext()); 1722 BrowsingDataRemover* remover = 1723 BrowsingDataRemover::CreateForUnboundedRange(profile); 1724 int remove_mask = BrowsingDataRemover::REMOVE_SITE_DATA; 1725 remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB); 1726 // BrowsingDataRemover takes care of deleting itself when done. 1727} 1728 1729FilePath ChromeContentBrowserClient::GetDefaultDownloadDirectory() { 1730 return download_util::GetDefaultDownloadDirectory(); 1731} 1732 1733std::string ChromeContentBrowserClient::GetDefaultDownloadName() { 1734 return l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME); 1735} 1736 1737void ChromeContentBrowserClient::DidCreatePpapiPlugin( 1738 content::BrowserPpapiHost* browser_host) { 1739 browser_host->GetPpapiHost()->AddHostFactoryFilter( 1740 scoped_ptr<ppapi::host::HostFactory>( 1741 new ChromeBrowserPepperHostFactory(browser_host))); 1742} 1743 1744content::BrowserPpapiHost* 1745 ChromeContentBrowserClient::GetExternalBrowserPpapiHost( 1746 int plugin_process_id) { 1747 BrowserChildProcessHostIterator iter(content::PROCESS_TYPE_NACL_LOADER); 1748 while (!iter.Done()) { 1749 NaClProcessHost* host = static_cast<NaClProcessHost*>(iter.GetDelegate()); 1750 if (host->process() && 1751 host->process()->GetData().id == plugin_process_id) { 1752 // Found the plugin. 1753 return host->browser_ppapi_host(); 1754 } 1755 ++iter; 1756 } 1757 return NULL; 1758} 1759 1760bool ChromeContentBrowserClient::AllowPepperSocketAPI( 1761 content::BrowserContext* browser_context, 1762 const GURL& url, 1763 const content::SocketPermissionRequest& params) { 1764 if (!url.is_valid()) 1765 return false; 1766 1767 std::string host = url.host(); 1768 if (url.SchemeIs(kExtensionScheme) && allowed_socket_origins_.count(host)) 1769 return true; 1770 1771 Profile* profile = Profile::FromBrowserContext(browser_context); 1772 const Extension* extension = NULL; 1773 if (profile && profile->GetExtensionService()) { 1774 extension = profile->GetExtensionService()->extensions()-> 1775 GetExtensionOrAppByURL(ExtensionURLInfo(url)); 1776 } 1777 1778 // Need to check this now and not on construction because otherwise it won't 1779 // work with browser_tests. 1780 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 1781 std::string allowed_list = 1782 command_line.GetSwitchValueASCII(switches::kAllowNaClSocketAPI); 1783 if (allowed_list == "*") { 1784 // The wildcard allows socket API only for packaged and platform apps. 1785 return extension && 1786 (extension->GetType() == Extension::TYPE_LEGACY_PACKAGED_APP || 1787 extension->GetType() == Extension::TYPE_PLATFORM_APP); 1788 } else if (!allowed_list.empty()) { 1789 StringTokenizer t(allowed_list, ","); 1790 while (t.GetNext()) { 1791 if (t.token() == host) 1792 return true; 1793 } 1794 } 1795 1796 if (!extension) 1797 return false; 1798 1799 extensions::SocketPermission::CheckParam extension_params( 1800 params.type, params.host, params.port); 1801 if (extension->CheckAPIPermissionWithParam(APIPermission::kSocket, 1802 &extension_params)) 1803 return true; 1804 1805 return false; 1806} 1807 1808bool ChromeContentBrowserClient::AllowPepperPrivateFileAPI() { 1809 return CommandLine::ForCurrentProcess()->HasSwitch( 1810 switches::kPpapiFlashInProcess); 1811} 1812 1813FilePath ChromeContentBrowserClient::GetHyphenDictionaryDirectory() { 1814 FilePath directory; 1815 PathService::Get(chrome::DIR_APP_DICTIONARIES, &directory); 1816 return directory.Append(FILE_PATH_LITERAL("Hyphen")); 1817} 1818 1819#if defined(OS_POSIX) && !defined(OS_MACOSX) 1820void ChromeContentBrowserClient::GetAdditionalMappedFilesForChildProcess( 1821 const CommandLine& command_line, 1822 int child_process_id, 1823 std::vector<FileDescriptorInfo>* mappings) { 1824#if defined(OS_ANDROID) 1825 FilePath data_path; 1826 PathService::Get(ui::DIR_RESOURCE_PAKS_ANDROID, &data_path); 1827 DCHECK(!data_path.empty()); 1828 1829 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; 1830 FilePath chrome_pak = data_path.AppendASCII("chrome.pak"); 1831 base::PlatformFile f = 1832 base::CreatePlatformFile(chrome_pak, flags, NULL, NULL); 1833 DCHECK(f != base::kInvalidPlatformFileValue); 1834 mappings->push_back(FileDescriptorInfo(kAndroidChromePakDescriptor, 1835 FileDescriptor(f, true))); 1836 1837 FilePath chrome_resources_pak = 1838 data_path.AppendASCII("chrome_100_percent.pak"); 1839 f = base::CreatePlatformFile(chrome_resources_pak, flags, NULL, NULL); 1840 DCHECK(f != base::kInvalidPlatformFileValue); 1841 mappings->push_back(FileDescriptorInfo(kAndroidUIResourcesPakDescriptor, 1842 FileDescriptor(f, true))); 1843 1844 const std::string locale = GetApplicationLocale(); 1845 FilePath locale_pak = ResourceBundle::GetSharedInstance(). 1846 GetLocaleFilePath(locale, false); 1847 f = base::CreatePlatformFile(locale_pak, flags, NULL, NULL); 1848 DCHECK(f != base::kInvalidPlatformFileValue); 1849 mappings->push_back(FileDescriptorInfo(kAndroidLocalePakDescriptor, 1850 FileDescriptor(f, true))); 1851 1852#if defined(USE_LINUX_BREAKPAD) 1853 f = crash_dump_manager_->CreateMinidumpFile(child_process_id); 1854 if (f == base::kInvalidPlatformFileValue) { 1855 LOG(ERROR) << "Failed to create file for minidump, crash reporting will be " 1856 "disabled for this process."; 1857 } else { 1858 mappings->push_back(FileDescriptorInfo(kAndroidMinidumpDescriptor, 1859 FileDescriptor(f, true))); 1860 } 1861#endif // defined(USE_LINUX_BREAKPAD) 1862 1863#else 1864 int crash_signal_fd = GetCrashSignalFD(command_line); 1865 if (crash_signal_fd >= 0) { 1866 mappings->push_back(FileDescriptorInfo(kCrashDumpSignal, 1867 FileDescriptor(crash_signal_fd, 1868 false))); 1869 } 1870#endif // defined(OS_ANDROID) 1871} 1872#endif // defined(OS_POSIX) && !defined(OS_MACOSX) 1873 1874#if defined(OS_WIN) 1875const wchar_t* ChromeContentBrowserClient::GetResourceDllName() { 1876 return chrome::kBrowserResourcesDll; 1877} 1878#endif 1879 1880#if defined(OS_ANDROID) 1881void ChromeContentBrowserClient::InitCrashDumpManager() { 1882 if (!crash_dump_manager_.get()) 1883 crash_dump_manager_.reset(new CrashDumpManager()); 1884} 1885#endif 1886 1887#if defined(USE_NSS) 1888crypto::CryptoModuleBlockingPasswordDelegate* 1889 ChromeContentBrowserClient::GetCryptoPasswordDelegate( 1890 const GURL& url) { 1891 return chrome::NewCryptoModuleBlockingDialogDelegate( 1892 chrome::kCryptoModulePasswordKeygen, url.host()); 1893} 1894#endif 1895 1896void ChromeContentBrowserClient::SetApplicationLocale( 1897 const std::string& locale) { 1898 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1899 1900 // This object is guaranteed to outlive all threads so we don't have to 1901 // worry about the lack of refcounting and can just post as Unretained. 1902 // 1903 // The common case is that this function is called early in Chrome startup 1904 // before any threads are created (it will also be called later if the user 1905 // changes the pref). In this case, there will be no threads created and 1906 // posting will fail. When there are no threads, we can just set the string 1907 // without worrying about threadsafety. 1908 if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 1909 base::Bind( 1910 &ChromeContentBrowserClient::SetApplicationLocaleOnIOThread, 1911 base::Unretained(this), locale))) 1912 io_thread_application_locale_ = locale; 1913} 1914 1915void ChromeContentBrowserClient::SetApplicationLocaleOnIOThread( 1916 const std::string& locale) { 1917 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1918 io_thread_application_locale_ = locale; 1919} 1920 1921} // namespace chrome 1922