blob: 12a1d6bd41af12f4aa1a928813c5098415a7c395 [file] [log] [blame]
[email protected]d977f9c2011-03-14 16:10:261// Copyright (c) 2011 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
[email protected]b80f68432011-05-02 17:22:307#include "base/command_line.h"
8#include "chrome/app/breakpad_mac.h"
9#include "chrome/browser/browser_process.h"
[email protected]763ec4ca2011-04-29 15:48:1210#include "chrome/browser/character_encoding.h"
[email protected]97e6c4c2011-05-18 16:08:5111#include "chrome/browser/chrome_plugin_message_filter.h"
[email protected]5327dfb2011-05-03 17:50:3612#include "chrome/browser/chrome_worker_message_filter.h"
[email protected]a2176792011-05-08 19:30:4913#include "chrome/browser/content_settings/host_content_settings_map.h"
[email protected]8093a542011-05-13 07:29:3214#include "chrome/browser/content_settings/tab_specific_content_settings.h"
[email protected]f364d1392011-04-08 21:03:1015#include "chrome/browser/debugger/devtools_handler.h"
16#include "chrome/browser/desktop_notification_handler.h"
[email protected]f364d1392011-04-08 21:03:1017#include "chrome/browser/extensions/extension_message_handler.h"
[email protected]d977f9c2011-03-14 16:10:2618#include "chrome/browser/extensions/extension_service.h"
[email protected]763ec4ca2011-04-29 15:48:1219#include "chrome/browser/google/google_util.h"
20#include "chrome/browser/prefs/pref_service.h"
[email protected]05fcf982011-04-19 00:44:1421#include "chrome/browser/printing/printing_message_filter.h"
22#include "chrome/browser/profiles/profile.h"
[email protected]8093a542011-05-13 07:29:3223#include "chrome/browser/profiles/profile_io_data.h"
[email protected]05fcf982011-04-19 00:44:1424#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
[email protected]53a0afa2011-04-28 02:09:3325#include "chrome/browser/renderer_host/chrome_render_view_host_observer.h"
[email protected]d4cff272011-05-02 15:46:0126#include "chrome/browser/renderer_host/text_input_client_message_filter.h"
[email protected]05fcf982011-04-19 00:44:1427#include "chrome/browser/search_engines/search_provider_install_state_message_filter.h"
28#include "chrome/browser/spellcheck_message_filter.h"
[email protected]1fd1a502011-03-30 16:55:5629#include "chrome/browser/ui/webui/chrome_web_ui_factory.h"
[email protected]b80f68432011-05-02 17:22:3030#include "chrome/common/child_process_logging.h"
31#include "chrome/common/chrome_switches.h"
[email protected]c5dbef02011-05-13 05:06:0932#include "chrome/common/extensions/extension_messages.h"
[email protected]763ec4ca2011-04-29 15:48:1233#include "chrome/common/pref_names.h"
[email protected]c5dbef02011-05-13 05:06:0934#include "chrome/common/url_constants.h"
35#include "content/browser/browsing_instance.h"
36#include "content/browser/child_process_security_policy.h"
[email protected]97e6c4c2011-05-18 16:08:5137#include "content/browser/plugin_process_host.h"
[email protected]05fcf982011-04-19 00:44:1438#include "content/browser/renderer_host/browser_render_process_host.h"
[email protected]d977f9c2011-03-14 16:10:2639#include "content/browser/renderer_host/render_view_host.h"
[email protected]a2176792011-05-08 19:30:4940#include "content/browser/resource_context.h"
[email protected]c5dbef02011-05-13 05:06:0941#include "content/browser/site_instance.h"
[email protected]763ec4ca2011-04-29 15:48:1242#include "content/browser/tab_contents/tab_contents.h"
[email protected]5327dfb2011-05-03 17:50:3643#include "content/browser/worker_host/worker_process_host.h"
[email protected]c5dbef02011-05-13 05:06:0944#include "content/common/bindings_policy.h"
[email protected]ed24fad2011-05-10 22:44:0145#include "net/base/cookie_monster.h"
46#include "net/base/cookie_options.h"
47#include "net/base/static_cookie_policy.h"
[email protected]d977f9c2011-03-14 16:10:2648
[email protected]b80f68432011-05-02 17:22:3049#if defined(OS_LINUX)
50#include "base/linux_util.h"
51#include "chrome/browser/crash_handler_host_linux.h"
52#endif // OS_LINUX
53
[email protected]c5dbef02011-05-13 05:06:0954namespace {
55
56void InitRenderViewHostForExtensions(RenderViewHost* render_view_host) {
57 // Note that due to GetEffectiveURL(), even hosted apps will have a
58 // chrome-extension:// URL for their site, so we can ignore that wrinkle here.
59 SiteInstance* site_instance = render_view_host->site_instance();
60 const GURL& site = site_instance->site();
61 RenderProcessHost* process = render_view_host->process();
62
63 if (!site.SchemeIs(chrome::kExtensionScheme))
64 return;
65
66 Profile* profile = site_instance->browsing_instance()->profile();
67 ExtensionService* service = profile->GetExtensionService();
68 if (!service)
69 return;
70
71 ExtensionProcessManager* process_manager =
72 profile->GetExtensionProcessManager();
73 CHECK(process_manager);
74
75 // This can happen if somebody typos a chrome-extension:// URL.
76 const Extension* extension = service->GetExtensionByURL(site);
77 if (!extension)
78 return;
79
80 site_instance->GetProcess()->mark_is_extension_process();
81
82 // Register the association between extension and process with
83 // ExtensionProcessManager.
84 process_manager->RegisterExtensionProcess(extension->id(), process->id());
85
86 // Record which, if any, installed app is associated with this process.
87 // TODO(aa): Totally lame to store this state in a global map in extension
88 // service. Can we get it from EPM instead?
89 if (extension->is_app())
90 service->SetInstalledAppForRenderer(process->id(), extension);
91
92 // Some extensions use chrome:// URLs.
93 Extension::Type type = extension->GetType();
94 if (type == Extension::TYPE_EXTENSION ||
95 type == Extension::TYPE_PACKAGED_APP) {
96 ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
97 process->id(), chrome::kChromeUIScheme);
98 }
99
100 // Enable extension bindings for the renderer. Currently only extensions,
101 // packaged apps, and hosted component apps use extension bindings.
102 if (type == Extension::TYPE_EXTENSION ||
[email protected]2333bf22011-05-19 02:16:51103 type == Extension::TYPE_USER_SCRIPT ||
[email protected]c5dbef02011-05-13 05:06:09104 type == Extension::TYPE_PACKAGED_APP ||
105 (type == Extension::TYPE_HOSTED_APP &&
106 extension->location() == Extension::COMPONENT)) {
107 render_view_host->Send(new ExtensionMsg_ActivateExtension(extension->id()));
108 render_view_host->AllowBindings(BindingsPolicy::EXTENSION);
109 }
110}
111
112}
113
[email protected]d977f9c2011-03-14 16:10:26114namespace chrome {
115
[email protected]f364d1392011-04-08 21:03:10116void ChromeContentBrowserClient::RenderViewHostCreated(
117 RenderViewHost* render_view_host) {
[email protected]53a0afa2011-04-28 02:09:33118 new ChromeRenderViewHostObserver(render_view_host);
[email protected]f364d1392011-04-08 21:03:10119 new DesktopNotificationHandler(render_view_host);
120 new DevToolsHandler(render_view_host);
121 new ExtensionMessageHandler(render_view_host);
[email protected]f364d1392011-04-08 21:03:10122
[email protected]c5dbef02011-05-13 05:06:09123 InitRenderViewHostForExtensions(render_view_host);
[email protected]d977f9c2011-03-14 16:10:26124}
125
[email protected]05fcf982011-04-19 00:44:14126void ChromeContentBrowserClient::BrowserRenderProcessHostCreated(
127 BrowserRenderProcessHost* host) {
[email protected]c47cfd62011-04-29 21:27:02128 int id = host->id();
129 Profile* profile = host->profile();
[email protected]05fcf982011-04-19 00:44:14130 host->channel()->AddFilter(new ChromeRenderMessageFilter(
[email protected]c47cfd62011-04-29 21:27:02131 id, profile, profile->GetRequestContextForRenderProcess(id)));
[email protected]05fcf982011-04-19 00:44:14132 host->channel()->AddFilter(new PrintingMessageFilter());
133 host->channel()->AddFilter(
[email protected]c47cfd62011-04-29 21:27:02134 new SearchProviderInstallStateMessageFilter(id, profile));
135 host->channel()->AddFilter(new SpellCheckMessageFilter(id));
[email protected]d4cff272011-05-02 15:46:01136#if defined(OS_MACOSX)
137 host->channel()->AddFilter(new TextInputClientMessageFilter(host->id()));
138#endif
[email protected]05fcf982011-04-19 00:44:14139}
140
[email protected]97e6c4c2011-05-18 16:08:51141void ChromeContentBrowserClient::PluginProcessHostCreated(
142 PluginProcessHost* host) {
143 host->AddFilter(new ChromePluginMessageFilter(host));
144}
145
[email protected]5327dfb2011-05-03 17:50:36146void ChromeContentBrowserClient::WorkerProcessHostCreated(
147 WorkerProcessHost* host) {
148 host->AddFilter(new ChromeWorkerMessageFilter(host));
149}
150
[email protected]1fd1a502011-03-30 16:55:56151content::WebUIFactory* ChromeContentBrowserClient::GetWebUIFactory() {
152 return ChromeWebUIFactory::GetInstance();
153}
154
[email protected]36fb2c7c2011-04-04 15:49:08155GURL ChromeContentBrowserClient::GetEffectiveURL(Profile* profile,
156 const GURL& url) {
157 // Get the effective URL for the given actual URL. If the URL is part of an
158 // installed app, the effective URL is an extension URL with the ID of that
159 // extension as the host. This has the effect of grouping apps together in
160 // a common SiteInstance.
161 if (!profile || !profile->GetExtensionService())
162 return url;
163
164 const Extension* extension =
165 profile->GetExtensionService()->GetExtensionByWebExtent(url);
166 if (!extension)
167 return url;
168
169 // If the URL is part of an extension's web extent, convert it to an
170 // extension URL.
171 return extension->GetResourceURL(url.path());
172}
173
[email protected]763ec4ca2011-04-29 15:48:12174GURL ChromeContentBrowserClient::GetAlternateErrorPageURL(
175 const TabContents* tab) {
176 GURL url;
177 // Disable alternate error pages when in OffTheRecord/Incognito mode.
178 if (tab->profile()->IsOffTheRecord())
179 return url;
180
181 PrefService* prefs = tab->profile()->GetPrefs();
182 DCHECK(prefs);
183 if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) {
184 url = google_util::AppendGoogleLocaleParam(
185 GURL(google_util::kLinkDoctorBaseURL));
186 url = google_util::AppendGoogleTLDParam(url);
187 }
188 return url;
189}
190
191std::string ChromeContentBrowserClient::GetCanonicalEncodingNameByAliasName(
192 const std::string& alias_name) {
193 return CharacterEncoding::GetCanonicalEncodingNameByAliasName(alias_name);
194}
195
[email protected]b80f68432011-05-02 17:22:30196void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
197 CommandLine* command_line, int child_process_id) {
198#if defined(USE_LINUX_BREAKPAD)
199 if (IsCrashReporterEnabled()) {
200 command_line->AppendSwitchASCII(switches::kEnableCrashReporter,
201 child_process_logging::GetClientId() + "," + base::GetLinuxDistro());
202 }
203#elif defined(OS_MACOSX)
204 if (IsCrashReporterEnabled()) {
205 command_line->AppendSwitchASCII(switches::kEnableCrashReporter,
206 child_process_logging::GetClientId());
207 }
208#endif // OS_MACOSX
209
210 std::string process_type =
211 command_line->GetSwitchValueASCII(switches::kProcessType);
212 if (process_type == switches::kExtensionProcess ||
213 process_type == switches::kRendererProcess) {
214 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
215 FilePath user_data_dir =
216 browser_command_line.GetSwitchValuePath(switches::kUserDataDir);
217 if (!user_data_dir.empty())
218 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
219#if defined(OS_CHROMEOS)
220 const std::string& login_profile =
221 browser_command_line.GetSwitchValueASCII(switches::kLoginProfile);
222 if (!login_profile.empty())
223 command_line->AppendSwitchASCII(switches::kLoginProfile, login_profile);
224#endif
225
226 RenderProcessHost* process = RenderProcessHost::FromID(child_process_id);
227
228 PrefService* prefs = process->profile()->GetPrefs();
229 // Currently this pref is only registered if applied via a policy.
230 if (prefs->HasPrefPath(prefs::kDisable3DAPIs) &&
231 prefs->GetBoolean(prefs::kDisable3DAPIs)) {
232 // Turn this policy into a command line switch.
233 command_line->AppendSwitch(switches::kDisable3DAPIs);
234 }
235
236 // Disable client-side phishing detection in the renderer if it is disabled
237 // in the browser process.
238 if (!g_browser_process->safe_browsing_detection_service())
239 command_line->AppendSwitch(switches::kDisableClientSidePhishingDetection);
240 }
241}
242
243std::string ChromeContentBrowserClient::GetApplicationLocale() {
244 return g_browser_process->GetApplicationLocale();
245}
246
[email protected]a2176792011-05-08 19:30:49247bool ChromeContentBrowserClient::AllowAppCache(
[email protected]ed24fad2011-05-10 22:44:01248 const GURL& manifest_url, const content::ResourceContext& context) {
[email protected]8093a542011-05-13 07:29:32249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
250 ProfileIOData* io_data =
251 reinterpret_cast<ProfileIOData*>(context.GetUserData(NULL));
[email protected]efa55212011-05-13 16:19:38252 ContentSetting setting = io_data->GetHostContentSettingsMap()->
[email protected]a2176792011-05-08 19:30:49253 GetContentSetting(manifest_url, CONTENT_SETTINGS_TYPE_COOKIES, "");
254 DCHECK(setting != CONTENT_SETTING_DEFAULT);
255 return setting != CONTENT_SETTING_BLOCK;
256}
257
[email protected]ed24fad2011-05-10 22:44:01258bool ChromeContentBrowserClient::AllowGetCookie(
259 const GURL& url,
260 const GURL& first_party,
261 const net::CookieList& cookie_list,
262 const content::ResourceContext& context,
263 int render_process_id,
264 int render_view_id) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
266 bool allow = true;
[email protected]8093a542011-05-13 07:29:32267 ProfileIOData* io_data =
268 reinterpret_cast<ProfileIOData*>(context.GetUserData(NULL));
[email protected]efa55212011-05-13 16:19:38269 if (io_data->GetHostContentSettingsMap()->BlockThirdPartyCookies()) {
[email protected]ed24fad2011-05-10 22:44:01270 bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
271 switches::kBlockReadingThirdPartyCookies);
272 net::StaticCookiePolicy policy(strict ?
273 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
274 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
275 int rv = policy.CanGetCookies(url, first_party);
276 DCHECK_NE(net::ERR_IO_PENDING, rv);
277 if (rv != net::OK)
278 allow = false;
279 }
280
281 if (allow) {
[email protected]efa55212011-05-13 16:19:38282 ContentSetting setting = io_data->GetHostContentSettingsMap()->
[email protected]ed24fad2011-05-10 22:44:01283 GetContentSetting(url, CONTENT_SETTINGS_TYPE_COOKIES, "");
284 allow = setting == CONTENT_SETTING_ALLOW ||
285 setting == CONTENT_SETTING_SESSION_ONLY;
286 }
287
[email protected]8093a542011-05-13 07:29:32288 BrowserThread::PostTask(
289 BrowserThread::UI, FROM_HERE,
290 NewRunnableFunction(
291 &TabSpecificContentSettings::CookiesRead,
292 render_process_id, render_view_id, url, cookie_list, !allow));
[email protected]ed24fad2011-05-10 22:44:01293 return allow;
294}
295
296bool ChromeContentBrowserClient::AllowSetCookie(
297 const GURL& url,
298 const GURL& first_party,
299 const std::string& cookie_line,
300 const content::ResourceContext& context,
301 int render_process_id,
302 int render_view_id,
303 net::CookieOptions* options) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
305 bool allow = true;
[email protected]8093a542011-05-13 07:29:32306 ProfileIOData* io_data =
307 reinterpret_cast<ProfileIOData*>(context.GetUserData(NULL));
[email protected]efa55212011-05-13 16:19:38308 if (io_data->GetHostContentSettingsMap()->BlockThirdPartyCookies()) {
[email protected]ed24fad2011-05-10 22:44:01309 bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
310 switches::kBlockReadingThirdPartyCookies);
311 net::StaticCookiePolicy policy(strict ?
312 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
313 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
314 int rv = policy.CanSetCookie(url, first_party, cookie_line);
315 if (rv != net::OK)
316 allow = false;
317 }
318
319 if (allow) {
[email protected]efa55212011-05-13 16:19:38320 ContentSetting setting = io_data->GetHostContentSettingsMap()->
[email protected]ed24fad2011-05-10 22:44:01321 GetContentSetting(url, CONTENT_SETTINGS_TYPE_COOKIES, "");
322
323 if (setting == CONTENT_SETTING_SESSION_ONLY)
324 options->set_force_session();
325
326 allow = setting == CONTENT_SETTING_ALLOW ||
327 setting == CONTENT_SETTING_SESSION_ONLY;
328 }
329
[email protected]8093a542011-05-13 07:29:32330 BrowserThread::PostTask(
331 BrowserThread::UI, FROM_HERE,
332 NewRunnableFunction(
333 &TabSpecificContentSettings::CookieChanged,
334 render_process_id, render_view_id, url, cookie_line, *options,
335 !allow));
[email protected]ed24fad2011-05-10 22:44:01336 return allow;
337}
338
[email protected]b80f68432011-05-02 17:22:30339#if defined(OS_LINUX)
340int ChromeContentBrowserClient::GetCrashSignalFD(
341 const std::string& process_type) {
342 if (process_type == switches::kRendererProcess)
343 return RendererCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
344
345 if (process_type == switches::kPluginProcess)
346 return PluginCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
347
348 if (process_type == switches::kPpapiPluginProcess)
349 return PpapiCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
350
351 if (process_type == switches::kGpuProcess)
352 return GpuCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
353
354 return -1;
355}
356#endif
357
[email protected]d977f9c2011-03-14 16:10:26358} // namespace chrome