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