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