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