Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / content / shell / browser / shell_content_browser_client.cc
blob6a58fa98403fec0594ec7dadd92fed5c76e1fede
1 // Copyright 2013 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.
5 #include "content/shell/browser/shell_content_browser_client.h"
7 #include "base/base_switches.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/files/file.h"
11 #include "base/path_service.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/browser/render_process_host.h"
14 #include "content/public/browser/resource_dispatcher_host.h"
15 #include "content/public/browser/storage_partition.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/common/url_constants.h"
18 #include "content/public/common/web_preferences.h"
19 #include "content/shell/browser/ipc_echo_message_filter.h"
20 #include "content/shell/browser/shell.h"
21 #include "content/shell/browser/shell_browser_context.h"
22 #include "content/shell/browser/shell_browser_main_parts.h"
23 #include "content/shell/browser/shell_devtools_delegate.h"
24 #include "content/shell/browser/shell_message_filter.h"
25 #include "content/shell/browser/shell_net_log.h"
26 #include "content/shell/browser/shell_notification_manager.h"
27 #include "content/shell/browser/shell_quota_permission_context.h"
28 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
29 #include "content/shell/browser/shell_web_contents_view_delegate_creator.h"
30 #include "content/shell/browser/webkit_test_controller.h"
31 #include "content/shell/common/shell_messages.h"
32 #include "content/shell/common/shell_switches.h"
33 #include "content/shell/common/webkit_test_helpers.h"
34 #include "content/shell/geolocation/shell_access_token_store.h"
35 #include "net/url_request/url_request_context_getter.h"
36 #include "url/gurl.h"
38 #if defined(OS_ANDROID)
39 #include "base/android/path_utils.h"
40 #include "base/path_service.h"
41 #include "components/crash/browser/crash_dump_manager_android.h"
42 #include "content/shell/android/shell_descriptors.h"
43 #endif
45 #if defined(OS_POSIX) && !defined(OS_MACOSX)
46 #include "base/debug/leak_annotations.h"
47 #include "components/crash/app/breakpad_linux.h"
48 #include "components/crash/browser/crash_handler_host_linux.h"
49 #include "content/public/common/content_descriptors.h"
50 #endif
52 #if defined(OS_WIN)
53 #include "content/common/sandbox_win.h"
54 #include "sandbox/win/src/sandbox.h"
55 #endif
57 namespace content {
59 namespace {
61 ShellContentBrowserClient* g_browser_client;
62 bool g_swap_processes_for_redirect = false;
64 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
65 breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
66 const std::string& process_type) {
67 base::FilePath dumps_path =
68 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
69 switches::kCrashDumpsDir);
71 ANNOTATE_SCOPED_MEMORY_LEAK;
72 breakpad::CrashHandlerHostLinux* crash_handler =
73 new breakpad::CrashHandlerHostLinux(
74 process_type, dumps_path, false);
75 crash_handler->StartUploaderThread();
76 return crash_handler;
80 int GetCrashSignalFD(const CommandLine& command_line) {
81 if (!breakpad::IsCrashReporterEnabled())
82 return -1;
84 std::string process_type =
85 command_line.GetSwitchValueASCII(switches::kProcessType);
87 if (process_type == switches::kRendererProcess) {
88 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
89 if (!crash_handler)
90 crash_handler = CreateCrashHandlerHost(process_type);
91 return crash_handler->GetDeathSignalSocket();
94 if (process_type == switches::kPluginProcess) {
95 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
96 if (!crash_handler)
97 crash_handler = CreateCrashHandlerHost(process_type);
98 return crash_handler->GetDeathSignalSocket();
101 if (process_type == switches::kPpapiPluginProcess) {
102 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
103 if (!crash_handler)
104 crash_handler = CreateCrashHandlerHost(process_type);
105 return crash_handler->GetDeathSignalSocket();
108 if (process_type == switches::kGpuProcess) {
109 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
110 if (!crash_handler)
111 crash_handler = CreateCrashHandlerHost(process_type);
112 return crash_handler->GetDeathSignalSocket();
115 return -1;
117 #endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
119 void RequestDesktopNotificationPermissionOnIO(
120 const GURL& source_origin,
121 RenderFrameHost* render_frame_host,
122 const base::Callback<void(blink::WebNotificationPermission)>& callback) {
123 ShellNotificationManager* manager =
124 ShellContentBrowserClient::Get()->GetShellNotificationManager();
125 if (manager)
126 manager->RequestPermission(source_origin, callback);
127 else
128 callback.Run(blink::WebNotificationPermissionAllowed);
131 } // namespace
133 ShellContentBrowserClient* ShellContentBrowserClient::Get() {
134 return g_browser_client;
137 void ShellContentBrowserClient::SetSwapProcessesForRedirect(bool swap) {
138 g_swap_processes_for_redirect = swap;
141 ShellContentBrowserClient::ShellContentBrowserClient()
142 : shell_browser_main_parts_(NULL) {
143 DCHECK(!g_browser_client);
144 g_browser_client = this;
145 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
146 return;
147 webkit_source_dir_ = GetWebKitRootDirFilePath();
150 ShellContentBrowserClient::~ShellContentBrowserClient() {
151 g_browser_client = NULL;
154 ShellNotificationManager*
155 ShellContentBrowserClient::GetShellNotificationManager() {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
157 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
158 return NULL;
160 if (!shell_notification_manager_)
161 shell_notification_manager_.reset(new ShellNotificationManager());
163 return shell_notification_manager_.get();
166 BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
167 const MainFunctionParams& parameters) {
168 shell_browser_main_parts_ = new ShellBrowserMainParts(parameters);
169 return shell_browser_main_parts_;
172 void ShellContentBrowserClient::RenderProcessWillLaunch(
173 RenderProcessHost* host) {
174 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kExposeIpcEcho))
175 host->AddFilter(new IPCEchoMessageFilter());
176 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
177 return;
178 host->AddFilter(new ShellMessageFilter(
179 host->GetID(),
180 BrowserContext::GetDefaultStoragePartition(browser_context())
181 ->GetDatabaseTracker(),
182 BrowserContext::GetDefaultStoragePartition(browser_context())
183 ->GetQuotaManager(),
184 BrowserContext::GetDefaultStoragePartition(browser_context())
185 ->GetURLRequestContext()));
186 host->Send(new ShellViewMsg_SetWebKitSourceDir(webkit_source_dir_));
189 net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
190 BrowserContext* content_browser_context,
191 ProtocolHandlerMap* protocol_handlers,
192 URLRequestInterceptorScopedVector request_interceptors) {
193 ShellBrowserContext* shell_browser_context =
194 ShellBrowserContextForBrowserContext(content_browser_context);
195 return shell_browser_context->CreateRequestContext(
196 protocol_handlers, request_interceptors.Pass());
199 net::URLRequestContextGetter*
200 ShellContentBrowserClient::CreateRequestContextForStoragePartition(
201 BrowserContext* content_browser_context,
202 const base::FilePath& partition_path,
203 bool in_memory,
204 ProtocolHandlerMap* protocol_handlers,
205 URLRequestInterceptorScopedVector request_interceptors) {
206 ShellBrowserContext* shell_browser_context =
207 ShellBrowserContextForBrowserContext(content_browser_context);
208 return shell_browser_context->CreateRequestContextForStoragePartition(
209 partition_path,
210 in_memory,
211 protocol_handlers,
212 request_interceptors.Pass());
215 bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
216 if (!url.is_valid())
217 return false;
218 DCHECK_EQ(url.scheme(), base::StringToLowerASCII(url.scheme()));
219 // Keep in sync with ProtocolHandlers added by
220 // ShellURLRequestContextGetter::GetURLRequestContext().
221 static const char* const kProtocolList[] = {
222 url::kBlobScheme,
223 url::kFileSystemScheme,
224 kChromeUIScheme,
225 kChromeDevToolsScheme,
226 url::kDataScheme,
227 url::kFileScheme,
229 for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
230 if (url.scheme() == kProtocolList[i])
231 return true;
233 return false;
236 void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
237 CommandLine* command_line, int child_process_id) {
238 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
239 command_line->AppendSwitch(switches::kDumpRenderTree);
240 if (CommandLine::ForCurrentProcess()->HasSwitch(
241 switches::kEnableFontAntialiasing))
242 command_line->AppendSwitch(switches::kEnableFontAntialiasing);
243 if (CommandLine::ForCurrentProcess()->HasSwitch(
244 switches::kExposeInternalsForTesting))
245 command_line->AppendSwitch(switches::kExposeInternalsForTesting);
246 if (CommandLine::ForCurrentProcess()->HasSwitch(
247 switches::kExposeIpcEcho))
248 command_line->AppendSwitch(switches::kExposeIpcEcho);
249 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStableReleaseMode))
250 command_line->AppendSwitch(switches::kStableReleaseMode);
251 if (CommandLine::ForCurrentProcess()->HasSwitch(
252 switches::kEnableCrashReporter)) {
253 command_line->AppendSwitch(switches::kEnableCrashReporter);
255 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir)) {
256 command_line->AppendSwitchPath(
257 switches::kCrashDumpsDir,
258 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
259 switches::kCrashDumpsDir));
261 if (CommandLine::ForCurrentProcess()->HasSwitch(
262 switches::kEnableLeakDetection)) {
263 command_line->AppendSwitchASCII(
264 switches::kEnableLeakDetection,
265 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
266 switches::kEnableLeakDetection));
268 if (CommandLine::ForCurrentProcess()->HasSwitch(
269 switches::kRegisterFontFiles)) {
270 command_line->AppendSwitchASCII(
271 switches::kRegisterFontFiles,
272 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
273 switches::kRegisterFontFiles));
277 void ShellContentBrowserClient::OverrideWebkitPrefs(
278 RenderViewHost* render_view_host,
279 const GURL& url,
280 WebPreferences* prefs) {
281 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
282 return;
283 WebKitTestController::Get()->OverrideWebkitPrefs(prefs);
286 void ShellContentBrowserClient::ResourceDispatcherHostCreated() {
287 resource_dispatcher_host_delegate_.reset(
288 new ShellResourceDispatcherHostDelegate());
289 ResourceDispatcherHost::Get()->SetDelegate(
290 resource_dispatcher_host_delegate_.get());
293 std::string ShellContentBrowserClient::GetDefaultDownloadName() {
294 return "download";
297 WebContentsViewDelegate* ShellContentBrowserClient::GetWebContentsViewDelegate(
298 WebContents* web_contents) {
299 #if !defined(USE_AURA)
300 return CreateShellWebContentsViewDelegate(web_contents);
301 #else
302 return NULL;
303 #endif
306 QuotaPermissionContext*
307 ShellContentBrowserClient::CreateQuotaPermissionContext() {
308 return new ShellQuotaPermissionContext();
311 void ShellContentBrowserClient::RequestDesktopNotificationPermission(
312 const GURL& source_origin,
313 RenderFrameHost* render_frame_host,
314 const base::Callback<void(blink::WebNotificationPermission)>& callback) {
315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
316 BrowserThread::PostTask(BrowserThread::IO,
317 FROM_HERE,
318 base::Bind(&RequestDesktopNotificationPermissionOnIO,
319 source_origin,
320 render_frame_host,
321 callback));
324 blink::WebNotificationPermission
325 ShellContentBrowserClient::CheckDesktopNotificationPermission(
326 const GURL& source_url,
327 ResourceContext* context,
328 int render_process_id) {
329 ShellNotificationManager* manager = GetShellNotificationManager();
330 if (manager)
331 return manager->CheckPermission(source_url);
333 return blink::WebNotificationPermissionAllowed;
336 SpeechRecognitionManagerDelegate*
337 ShellContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
338 return new ShellSpeechRecognitionManagerDelegate();
341 net::NetLog* ShellContentBrowserClient::GetNetLog() {
342 return shell_browser_main_parts_->net_log();
345 bool ShellContentBrowserClient::ShouldSwapProcessesForRedirect(
346 ResourceContext* resource_context,
347 const GURL& current_url,
348 const GURL& new_url) {
349 return g_swap_processes_for_redirect;
352 #if defined(OS_POSIX) && !defined(OS_MACOSX)
353 void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
354 const CommandLine& command_line,
355 int child_process_id,
356 std::vector<FileDescriptorInfo>* mappings) {
357 #if defined(OS_ANDROID)
358 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
359 base::FilePath pak_file;
360 bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
361 CHECK(r);
362 pak_file = pak_file.Append(FILE_PATH_LITERAL("paks"));
363 pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
365 base::File f(pak_file, flags);
366 if (!f.IsValid()) {
367 NOTREACHED() << "Failed to open file when creating renderer process: "
368 << "content_shell.pak";
370 mappings->push_back(
371 FileDescriptorInfo(kShellPakDescriptor, base::FileDescriptor(f.Pass())));
373 if (breakpad::IsCrashReporterEnabled()) {
374 f = breakpad::CrashDumpManager::GetInstance()->CreateMinidumpFile(
375 child_process_id);
376 if (!f.IsValid()) {
377 LOG(ERROR) << "Failed to create file for minidump, crash reporting will "
378 << "be disabled for this process.";
379 } else {
380 mappings->push_back(
381 FileDescriptorInfo(kAndroidMinidumpDescriptor,
382 base::FileDescriptor(f.Pass())));
385 #else // !defined(OS_ANDROID)
386 int crash_signal_fd = GetCrashSignalFD(command_line);
387 if (crash_signal_fd >= 0) {
388 mappings->push_back(FileDescriptorInfo(
389 kCrashDumpSignal, base::FileDescriptor(crash_signal_fd, false)));
391 #endif // defined(OS_ANDROID)
393 #endif // defined(OS_POSIX) && !defined(OS_MACOSX)
395 #if defined(OS_WIN)
396 void ShellContentBrowserClient::PreSpawnRenderer(sandbox::TargetPolicy* policy,
397 bool* success) {
398 // Add sideloaded font files for testing. See also DIR_WINDOWS_FONTS
399 // addition in |StartSandboxedProcess|.
400 std::vector<std::string> font_files = GetSideloadFontFiles();
401 for (std::vector<std::string>::const_iterator i(font_files.begin());
402 i != font_files.end();
403 ++i) {
404 policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
405 sandbox::TargetPolicy::FILES_ALLOW_READONLY,
406 base::UTF8ToWide(*i).c_str());
409 #endif // OS_WIN
411 ShellBrowserContext* ShellContentBrowserClient::browser_context() {
412 return shell_browser_main_parts_->browser_context();
415 ShellBrowserContext*
416 ShellContentBrowserClient::off_the_record_browser_context() {
417 return shell_browser_main_parts_->off_the_record_browser_context();
420 AccessTokenStore* ShellContentBrowserClient::CreateAccessTokenStore() {
421 return new ShellAccessTokenStore(browser_context());
424 ShellBrowserContext*
425 ShellContentBrowserClient::ShellBrowserContextForBrowserContext(
426 BrowserContext* content_browser_context) {
427 if (content_browser_context == browser_context())
428 return browser_context();
429 DCHECK_EQ(content_browser_context, off_the_record_browser_context());
430 return off_the_record_browser_context();
433 } // namespace content