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