blob: 8efed98ff538cd9e3612433bae5cdd3d6372498c [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]5327dfb2011-05-03 17:50:3611#include "chrome/browser/chrome_worker_message_filter.h"
[email protected]a2176792011-05-08 19:30:4912#include "chrome/browser/content_settings/host_content_settings_map.h"
[email protected]f364d1392011-04-08 21:03:1013#include "chrome/browser/debugger/devtools_handler.h"
14#include "chrome/browser/desktop_notification_handler.h"
[email protected]f364d1392011-04-08 21:03:1015#include "chrome/browser/extensions/extension_message_handler.h"
[email protected]d977f9c2011-03-14 16:10:2616#include "chrome/browser/extensions/extension_service.h"
[email protected]763ec4ca2011-04-29 15:48:1217#include "chrome/browser/google/google_util.h"
18#include "chrome/browser/prefs/pref_service.h"
[email protected]05fcf982011-04-19 00:44:1419#include "chrome/browser/printing/printing_message_filter.h"
20#include "chrome/browser/profiles/profile.h"
21#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
[email protected]53a0afa2011-04-28 02:09:3322#include "chrome/browser/renderer_host/chrome_render_view_host_observer.h"
[email protected]d4cff272011-05-02 15:46:0123#include "chrome/browser/renderer_host/text_input_client_message_filter.h"
[email protected]05fcf982011-04-19 00:44:1424#include "chrome/browser/search_engines/search_provider_install_state_message_filter.h"
25#include "chrome/browser/spellcheck_message_filter.h"
[email protected]1fd1a502011-03-30 16:55:5626#include "chrome/browser/ui/webui/chrome_web_ui_factory.h"
[email protected]b80f68432011-05-02 17:22:3027#include "chrome/common/child_process_logging.h"
28#include "chrome/common/chrome_switches.h"
[email protected]c5dbef02011-05-13 05:06:0929#include "chrome/common/extensions/extension_messages.h"
[email protected]763ec4ca2011-04-29 15:48:1230#include "chrome/common/pref_names.h"
[email protected]c5dbef02011-05-13 05:06:0931#include "chrome/common/url_constants.h"
32#include "content/browser/browsing_instance.h"
33#include "content/browser/child_process_security_policy.h"
[email protected]05fcf982011-04-19 00:44:1434#include "content/browser/renderer_host/browser_render_process_host.h"
[email protected]d977f9c2011-03-14 16:10:2635#include "content/browser/renderer_host/render_view_host.h"
[email protected]ed24fad2011-05-10 22:44:0136#include "content/browser/renderer_host/render_view_host_notification_task.h"
[email protected]a2176792011-05-08 19:30:4937#include "content/browser/resource_context.h"
[email protected]c5dbef02011-05-13 05:06:0938#include "content/browser/site_instance.h"
[email protected]763ec4ca2011-04-29 15:48:1239#include "content/browser/tab_contents/tab_contents.h"
[email protected]5327dfb2011-05-03 17:50:3640#include "content/browser/worker_host/worker_process_host.h"
[email protected]c5dbef02011-05-13 05:06:0941#include "content/common/bindings_policy.h"
[email protected]ed24fad2011-05-10 22:44:0142#include "net/base/cookie_monster.h"
43#include "net/base/cookie_options.h"
44#include "net/base/static_cookie_policy.h"
[email protected]d977f9c2011-03-14 16:10:2645
[email protected]b80f68432011-05-02 17:22:3046#if defined(OS_LINUX)
47#include "base/linux_util.h"
48#include "chrome/browser/crash_handler_host_linux.h"
49#endif // OS_LINUX
50
[email protected]c5dbef02011-05-13 05:06:0951namespace {
52
53void InitRenderViewHostForExtensions(RenderViewHost* render_view_host) {
54 // Note that due to GetEffectiveURL(), even hosted apps will have a
55 // chrome-extension:// URL for their site, so we can ignore that wrinkle here.
56 SiteInstance* site_instance = render_view_host->site_instance();
57 const GURL& site = site_instance->site();
58 RenderProcessHost* process = render_view_host->process();
59
60 if (!site.SchemeIs(chrome::kExtensionScheme))
61 return;
62
63 Profile* profile = site_instance->browsing_instance()->profile();
64 ExtensionService* service = profile->GetExtensionService();
65 if (!service)
66 return;
67
68 ExtensionProcessManager* process_manager =
69 profile->GetExtensionProcessManager();
70 CHECK(process_manager);
71
72 // This can happen if somebody typos a chrome-extension:// URL.
73 const Extension* extension = service->GetExtensionByURL(site);
74 if (!extension)
75 return;
76
77 site_instance->GetProcess()->mark_is_extension_process();
78
79 // Register the association between extension and process with
80 // ExtensionProcessManager.
81 process_manager->RegisterExtensionProcess(extension->id(), process->id());
82
83 // Record which, if any, installed app is associated with this process.
84 // TODO(aa): Totally lame to store this state in a global map in extension
85 // service. Can we get it from EPM instead?
86 if (extension->is_app())
87 service->SetInstalledAppForRenderer(process->id(), extension);
88
89 // Some extensions use chrome:// URLs.
90 Extension::Type type = extension->GetType();
91 if (type == Extension::TYPE_EXTENSION ||
92 type == Extension::TYPE_PACKAGED_APP) {
93 ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
94 process->id(), chrome::kChromeUIScheme);
95 }
96
97 // Enable extension bindings for the renderer. Currently only extensions,
98 // packaged apps, and hosted component apps use extension bindings.
99 if (type == Extension::TYPE_EXTENSION ||
100 type == Extension::TYPE_PACKAGED_APP ||
101 (type == Extension::TYPE_HOSTED_APP &&
102 extension->location() == Extension::COMPONENT)) {
103 render_view_host->Send(new ExtensionMsg_ActivateExtension(extension->id()));
104 render_view_host->AllowBindings(BindingsPolicy::EXTENSION);
105 }
106}
107
108}
109
[email protected]d977f9c2011-03-14 16:10:26110namespace chrome {
111
[email protected]f364d1392011-04-08 21:03:10112void ChromeContentBrowserClient::RenderViewHostCreated(
113 RenderViewHost* render_view_host) {
[email protected]53a0afa2011-04-28 02:09:33114 new ChromeRenderViewHostObserver(render_view_host);
[email protected]f364d1392011-04-08 21:03:10115 new DesktopNotificationHandler(render_view_host);
116 new DevToolsHandler(render_view_host);
117 new ExtensionMessageHandler(render_view_host);
[email protected]f364d1392011-04-08 21:03:10118
[email protected]c5dbef02011-05-13 05:06:09119 InitRenderViewHostForExtensions(render_view_host);
[email protected]d977f9c2011-03-14 16:10:26120}
121
[email protected]05fcf982011-04-19 00:44:14122void ChromeContentBrowserClient::BrowserRenderProcessHostCreated(
123 BrowserRenderProcessHost* host) {
[email protected]c47cfd62011-04-29 21:27:02124 int id = host->id();
125 Profile* profile = host->profile();
[email protected]05fcf982011-04-19 00:44:14126 host->channel()->AddFilter(new ChromeRenderMessageFilter(
[email protected]c47cfd62011-04-29 21:27:02127 id, profile, profile->GetRequestContextForRenderProcess(id)));
[email protected]05fcf982011-04-19 00:44:14128 host->channel()->AddFilter(new PrintingMessageFilter());
129 host->channel()->AddFilter(
[email protected]c47cfd62011-04-29 21:27:02130 new SearchProviderInstallStateMessageFilter(id, profile));
131 host->channel()->AddFilter(new SpellCheckMessageFilter(id));
[email protected]d4cff272011-05-02 15:46:01132#if defined(OS_MACOSX)
133 host->channel()->AddFilter(new TextInputClientMessageFilter(host->id()));
134#endif
[email protected]05fcf982011-04-19 00:44:14135}
136
[email protected]5327dfb2011-05-03 17:50:36137void ChromeContentBrowserClient::WorkerProcessHostCreated(
138 WorkerProcessHost* host) {
139 host->AddFilter(new ChromeWorkerMessageFilter(host));
140}
141
[email protected]1fd1a502011-03-30 16:55:56142content::WebUIFactory* ChromeContentBrowserClient::GetWebUIFactory() {
143 return ChromeWebUIFactory::GetInstance();
144}
145
[email protected]36fb2c7c2011-04-04 15:49:08146GURL ChromeContentBrowserClient::GetEffectiveURL(Profile* profile,
147 const GURL& url) {
148 // Get the effective URL for the given actual URL. If the URL is part of an
149 // installed app, the effective URL is an extension URL with the ID of that
150 // extension as the host. This has the effect of grouping apps together in
151 // a common SiteInstance.
152 if (!profile || !profile->GetExtensionService())
153 return url;
154
155 const Extension* extension =
156 profile->GetExtensionService()->GetExtensionByWebExtent(url);
157 if (!extension)
158 return url;
159
160 // If the URL is part of an extension's web extent, convert it to an
161 // extension URL.
162 return extension->GetResourceURL(url.path());
163}
164
[email protected]763ec4ca2011-04-29 15:48:12165GURL ChromeContentBrowserClient::GetAlternateErrorPageURL(
166 const TabContents* tab) {
167 GURL url;
168 // Disable alternate error pages when in OffTheRecord/Incognito mode.
169 if (tab->profile()->IsOffTheRecord())
170 return url;
171
172 PrefService* prefs = tab->profile()->GetPrefs();
173 DCHECK(prefs);
174 if (prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled)) {
175 url = google_util::AppendGoogleLocaleParam(
176 GURL(google_util::kLinkDoctorBaseURL));
177 url = google_util::AppendGoogleTLDParam(url);
178 }
179 return url;
180}
181
182std::string ChromeContentBrowserClient::GetCanonicalEncodingNameByAliasName(
183 const std::string& alias_name) {
184 return CharacterEncoding::GetCanonicalEncodingNameByAliasName(alias_name);
185}
186
[email protected]b80f68432011-05-02 17:22:30187void ChromeContentBrowserClient::AppendExtraCommandLineSwitches(
188 CommandLine* command_line, int child_process_id) {
189#if defined(USE_LINUX_BREAKPAD)
190 if (IsCrashReporterEnabled()) {
191 command_line->AppendSwitchASCII(switches::kEnableCrashReporter,
192 child_process_logging::GetClientId() + "," + base::GetLinuxDistro());
193 }
194#elif defined(OS_MACOSX)
195 if (IsCrashReporterEnabled()) {
196 command_line->AppendSwitchASCII(switches::kEnableCrashReporter,
197 child_process_logging::GetClientId());
198 }
199#endif // OS_MACOSX
200
201 std::string process_type =
202 command_line->GetSwitchValueASCII(switches::kProcessType);
203 if (process_type == switches::kExtensionProcess ||
204 process_type == switches::kRendererProcess) {
205 const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
206 FilePath user_data_dir =
207 browser_command_line.GetSwitchValuePath(switches::kUserDataDir);
208 if (!user_data_dir.empty())
209 command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
210#if defined(OS_CHROMEOS)
211 const std::string& login_profile =
212 browser_command_line.GetSwitchValueASCII(switches::kLoginProfile);
213 if (!login_profile.empty())
214 command_line->AppendSwitchASCII(switches::kLoginProfile, login_profile);
215#endif
216
217 RenderProcessHost* process = RenderProcessHost::FromID(child_process_id);
218
219 PrefService* prefs = process->profile()->GetPrefs();
220 // Currently this pref is only registered if applied via a policy.
221 if (prefs->HasPrefPath(prefs::kDisable3DAPIs) &&
222 prefs->GetBoolean(prefs::kDisable3DAPIs)) {
223 // Turn this policy into a command line switch.
224 command_line->AppendSwitch(switches::kDisable3DAPIs);
225 }
226
227 // Disable client-side phishing detection in the renderer if it is disabled
228 // in the browser process.
229 if (!g_browser_process->safe_browsing_detection_service())
230 command_line->AppendSwitch(switches::kDisableClientSidePhishingDetection);
231 }
232}
233
234std::string ChromeContentBrowserClient::GetApplicationLocale() {
235 return g_browser_process->GetApplicationLocale();
236}
237
[email protected]a2176792011-05-08 19:30:49238bool ChromeContentBrowserClient::AllowAppCache(
[email protected]ed24fad2011-05-10 22:44:01239 const GURL& manifest_url, const content::ResourceContext& context) {
240 ContentSetting setting = context.host_content_settings_map()->
[email protected]a2176792011-05-08 19:30:49241 GetContentSetting(manifest_url, CONTENT_SETTINGS_TYPE_COOKIES, "");
242 DCHECK(setting != CONTENT_SETTING_DEFAULT);
243 return setting != CONTENT_SETTING_BLOCK;
244}
245
[email protected]ed24fad2011-05-10 22:44:01246bool ChromeContentBrowserClient::AllowGetCookie(
247 const GURL& url,
248 const GURL& first_party,
249 const net::CookieList& cookie_list,
250 const content::ResourceContext& context,
251 int render_process_id,
252 int render_view_id) {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
254 bool allow = true;
255 if (context.host_content_settings_map()->BlockThirdPartyCookies()) {
256 bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
257 switches::kBlockReadingThirdPartyCookies);
258 net::StaticCookiePolicy policy(strict ?
259 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
260 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
261 int rv = policy.CanGetCookies(url, first_party);
262 DCHECK_NE(net::ERR_IO_PENDING, rv);
263 if (rv != net::OK)
264 allow = false;
265 }
266
267 if (allow) {
268 ContentSetting setting = context.host_content_settings_map()->
269 GetContentSetting(url, CONTENT_SETTINGS_TYPE_COOKIES, "");
270 allow = setting == CONTENT_SETTING_ALLOW ||
271 setting == CONTENT_SETTING_SESSION_ONLY;
272 }
273
274 CallRenderViewHostContentSettingsDelegate(
275 render_process_id, render_view_id,
276 &RenderViewHostDelegate::ContentSettings::OnCookiesRead,
277 url, cookie_list, !allow);
278 return allow;
279}
280
281bool ChromeContentBrowserClient::AllowSetCookie(
282 const GURL& url,
283 const GURL& first_party,
284 const std::string& cookie_line,
285 const content::ResourceContext& context,
286 int render_process_id,
287 int render_view_id,
288 net::CookieOptions* options) {
289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
290 bool allow = true;
291 if (context.host_content_settings_map()->BlockThirdPartyCookies()) {
292 bool strict = CommandLine::ForCurrentProcess()->HasSwitch(
293 switches::kBlockReadingThirdPartyCookies);
294 net::StaticCookiePolicy policy(strict ?
295 net::StaticCookiePolicy::BLOCK_ALL_THIRD_PARTY_COOKIES :
296 net::StaticCookiePolicy::BLOCK_SETTING_THIRD_PARTY_COOKIES);
297 int rv = policy.CanSetCookie(url, first_party, cookie_line);
298 if (rv != net::OK)
299 allow = false;
300 }
301
302 if (allow) {
303 ContentSetting setting = context.host_content_settings_map()->
304 GetContentSetting(url, CONTENT_SETTINGS_TYPE_COOKIES, "");
305
306 if (setting == CONTENT_SETTING_SESSION_ONLY)
307 options->set_force_session();
308
309 allow = setting == CONTENT_SETTING_ALLOW ||
310 setting == CONTENT_SETTING_SESSION_ONLY;
311 }
312
313 CallRenderViewHostContentSettingsDelegate(
314 render_process_id, render_view_id,
315 &RenderViewHostDelegate::ContentSettings::OnCookieChanged,
316 url, cookie_line, *options, !allow);
317 return allow;
318}
319
[email protected]b80f68432011-05-02 17:22:30320#if defined(OS_LINUX)
321int ChromeContentBrowserClient::GetCrashSignalFD(
322 const std::string& process_type) {
323 if (process_type == switches::kRendererProcess)
324 return RendererCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
325
326 if (process_type == switches::kPluginProcess)
327 return PluginCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
328
329 if (process_type == switches::kPpapiPluginProcess)
330 return PpapiCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
331
332 if (process_type == switches::kGpuProcess)
333 return GpuCrashHandlerHostLinux::GetInstance()->GetDeathSignalSocket();
334
335 return -1;
336}
337#endif
338
[email protected]d977f9c2011-03-14 16:10:26339} // namespace chrome