Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / content / shell / browser / shell_content_browser_client.cc
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.
4
5 #include "content/shell/browser/shell_content_browser_client.h"
6
7 #include "base/base_switches.h"
8 #include "base/command_line.h"
9 #include "base/files/file.h"
10 #include "base/files/file_util.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/layout_test/layout_test_browser_main_parts.h"
21 #include "content/shell/browser/layout_test/layout_test_resource_dispatcher_host_delegate.h"
22 #include "content/shell/browser/shell.h"
23 #include "content/shell/browser/shell_access_token_store.h"
24 #include "content/shell/browser/shell_browser_context.h"
25 #include "content/shell/browser/shell_browser_main_parts.h"
26 #include "content/shell/browser/shell_devtools_manager_delegate.h"
27 #include "content/shell/browser/shell_net_log.h"
28 #include "content/shell/browser/shell_quota_permission_context.h"
29 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
30 #include "content/shell/browser/shell_web_contents_view_delegate_creator.h"
31 #include "content/shell/browser/webkit_test_controller.h"
32 #include "content/shell/common/shell_messages.h"
33 #include "content/shell/common/shell_switches.h"
34 #include "content/shell/common/webkit_test_helpers.h"
35 #include "net/url_request/url_request_context_getter.h"
36 #include "url/gurl.h"
37
38 #if defined(OS_ANDROID)
39 #include "base/android/path_utils.h"
40 #include "components/crash/browser/crash_dump_manager_android.h"
41 #include "content/shell/android/shell_descriptors.h"
42 #endif
43
44 #if defined(OS_POSIX) && !defined(OS_MACOSX)
45 #include "base/debug/leak_annotations.h"
46 #include "components/crash/app/breakpad_linux.h"
47 #include "components/crash/browser/crash_handler_host_linux.h"
48 #include "content/public/common/content_descriptors.h"
49 #endif
50
51 #if defined(OS_WIN)
52 #include "content/common/sandbox_win.h"
53 #include "sandbox/win/src/sandbox.h"
54 #endif
55
56 namespace content {
57
58 namespace {
59
60 ShellContentBrowserClient* g_browser_client;
61 bool g_swap_processes_for_redirect = false;
62
63 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
64 breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
65     const std::string& process_type) {
66   base::FilePath dumps_path =
67       CommandLine::ForCurrentProcess()->GetSwitchValuePath(
68           switches::kCrashDumpsDir);
69   {
70     ANNOTATE_SCOPED_MEMORY_LEAK;
71     breakpad::CrashHandlerHostLinux* crash_handler =
72         new breakpad::CrashHandlerHostLinux(
73             process_type, dumps_path, false);
74     crash_handler->StartUploaderThread();
75     return crash_handler;
76   }
77 }
78
79 int GetCrashSignalFD(const CommandLine& command_line) {
80   if (!breakpad::IsCrashReporterEnabled())
81     return -1;
82
83   std::string process_type =
84       command_line.GetSwitchValueASCII(switches::kProcessType);
85
86   if (process_type == switches::kRendererProcess) {
87     static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
88     if (!crash_handler)
89       crash_handler = CreateCrashHandlerHost(process_type);
90     return crash_handler->GetDeathSignalSocket();
91   }
92
93   if (process_type == switches::kPluginProcess) {
94     static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
95     if (!crash_handler)
96       crash_handler = CreateCrashHandlerHost(process_type);
97     return crash_handler->GetDeathSignalSocket();
98   }
99
100   if (process_type == switches::kPpapiPluginProcess) {
101     static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
102     if (!crash_handler)
103       crash_handler = CreateCrashHandlerHost(process_type);
104     return crash_handler->GetDeathSignalSocket();
105   }
106
107   if (process_type == switches::kGpuProcess) {
108     static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
109     if (!crash_handler)
110       crash_handler = CreateCrashHandlerHost(process_type);
111     return crash_handler->GetDeathSignalSocket();
112   }
113
114   return -1;
115 }
116 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
117
118 }  // namespace
119
120 ShellContentBrowserClient* ShellContentBrowserClient::Get() {
121   return g_browser_client;
122 }
123
124 void ShellContentBrowserClient::SetSwapProcessesForRedirect(bool swap) {
125   g_swap_processes_for_redirect = swap;
126 }
127
128 ShellContentBrowserClient::ShellContentBrowserClient()
129     : shell_browser_main_parts_(NULL) {
130   DCHECK(!g_browser_client);
131   g_browser_client = this;
132 }
133
134 ShellContentBrowserClient::~ShellContentBrowserClient() {
135   g_browser_client = NULL;
136 }
137
138 BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
139     const MainFunctionParams& parameters) {
140   shell_browser_main_parts_ =
141       CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)
142           ? new LayoutTestBrowserMainParts(parameters)
143           : new ShellBrowserMainParts(parameters);
144   return shell_browser_main_parts_;
145 }
146
147 void ShellContentBrowserClient::RenderProcessWillLaunch(
148     RenderProcessHost* host) {
149   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kExposeIpcEcho))
150     host->AddFilter(new IPCEchoMessageFilter());
151 }
152
153 net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
154     BrowserContext* content_browser_context,
155     ProtocolHandlerMap* protocol_handlers,
156     URLRequestInterceptorScopedVector request_interceptors) {
157   ShellBrowserContext* shell_browser_context =
158       ShellBrowserContextForBrowserContext(content_browser_context);
159   return shell_browser_context->CreateRequestContext(
160       protocol_handlers, request_interceptors.Pass());
161 }
162
163 net::URLRequestContextGetter*
164 ShellContentBrowserClient::CreateRequestContextForStoragePartition(
165     BrowserContext* content_browser_context,
166     const base::FilePath& partition_path,
167     bool in_memory,
168     ProtocolHandlerMap* protocol_handlers,
169     URLRequestInterceptorScopedVector request_interceptors) {
170   ShellBrowserContext* shell_browser_context =
171       ShellBrowserContextForBrowserContext(content_browser_context);
172   return shell_browser_context->CreateRequestContextForStoragePartition(
173       partition_path,
174       in_memory,
175       protocol_handlers,
176       request_interceptors.Pass());
177 }
178
179 bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
180   if (!url.is_valid())
181     return false;
182   DCHECK_EQ(url.scheme(), base::StringToLowerASCII(url.scheme()));
183   // Keep in sync with ProtocolHandlers added by
184   // ShellURLRequestContextGetter::GetURLRequestContext().
185   static const char* const kProtocolList[] = {
186       url::kBlobScheme,
187       url::kFileSystemScheme,
188       kChromeUIScheme,
189       kChromeDevToolsScheme,
190       url::kDataScheme,
191       url::kFileScheme,
192   };
193   for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
194     if (url.scheme() == kProtocolList[i])
195       return true;
196   }
197   return false;
198 }
199
200 void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
201     CommandLine* command_line, int child_process_id) {
202   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
203     command_line->AppendSwitch(switches::kDumpRenderTree);
204   if (CommandLine::ForCurrentProcess()->HasSwitch(
205       switches::kEnableFontAntialiasing))
206     command_line->AppendSwitch(switches::kEnableFontAntialiasing);
207   if (CommandLine::ForCurrentProcess()->HasSwitch(
208       switches::kExposeInternalsForTesting))
209     command_line->AppendSwitch(switches::kExposeInternalsForTesting);
210   if (CommandLine::ForCurrentProcess()->HasSwitch(
211       switches::kExposeIpcEcho))
212     command_line->AppendSwitch(switches::kExposeIpcEcho);
213   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStableReleaseMode))
214     command_line->AppendSwitch(switches::kStableReleaseMode);
215   if (CommandLine::ForCurrentProcess()->HasSwitch(
216           switches::kEnableCrashReporter)) {
217     command_line->AppendSwitch(switches::kEnableCrashReporter);
218   }
219   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir)) {
220     command_line->AppendSwitchPath(
221         switches::kCrashDumpsDir,
222         CommandLine::ForCurrentProcess()->GetSwitchValuePath(
223             switches::kCrashDumpsDir));
224   }
225   if (CommandLine::ForCurrentProcess()->HasSwitch(
226           switches::kEnableLeakDetection)) {
227     command_line->AppendSwitchASCII(
228         switches::kEnableLeakDetection,
229         CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
230             switches::kEnableLeakDetection));
231   }
232   if (CommandLine::ForCurrentProcess()->HasSwitch(
233         switches::kRegisterFontFiles)) {
234     command_line->AppendSwitchASCII(
235         switches::kRegisterFontFiles,
236         CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
237             switches::kRegisterFontFiles));
238   }
239 }
240
241 void ShellContentBrowserClient::OverrideWebkitPrefs(
242     RenderViewHost* render_view_host,
243     const GURL& url,
244     WebPreferences* prefs) {
245   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
246     return;
247   WebKitTestController::Get()->OverrideWebkitPrefs(prefs);
248 }
249
250 void ShellContentBrowserClient::ResourceDispatcherHostCreated() {
251   resource_dispatcher_host_delegate_.reset(
252       CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)
253           ? new LayoutTestResourceDispatcherHostDelegate
254           : new ShellResourceDispatcherHostDelegate);
255   ResourceDispatcherHost::Get()->SetDelegate(
256       resource_dispatcher_host_delegate_.get());
257 }
258
259 std::string ShellContentBrowserClient::GetDefaultDownloadName() {
260   return "download";
261 }
262
263 WebContentsViewDelegate* ShellContentBrowserClient::GetWebContentsViewDelegate(
264     WebContents* web_contents) {
265 #if !defined(USE_AURA)
266   return CreateShellWebContentsViewDelegate(web_contents);
267 #else
268   return NULL;
269 #endif
270 }
271
272 QuotaPermissionContext*
273 ShellContentBrowserClient::CreateQuotaPermissionContext() {
274   return new ShellQuotaPermissionContext();
275 }
276
277 SpeechRecognitionManagerDelegate*
278     ShellContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
279   return new ShellSpeechRecognitionManagerDelegate();
280 }
281
282 net::NetLog* ShellContentBrowserClient::GetNetLog() {
283   return shell_browser_main_parts_->net_log();
284 }
285
286 bool ShellContentBrowserClient::ShouldSwapProcessesForRedirect(
287     ResourceContext* resource_context,
288     const GURL& current_url,
289     const GURL& new_url) {
290   return g_swap_processes_for_redirect;
291 }
292
293 DevToolsManagerDelegate*
294 ShellContentBrowserClient::GetDevToolsManagerDelegate() {
295   return new ShellDevToolsManagerDelegate(browser_context());
296 }
297
298 #if defined(OS_POSIX) && !defined(OS_MACOSX)
299 void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
300     const CommandLine& command_line,
301     int child_process_id,
302     FileDescriptorInfo* mappings) {
303 #if defined(OS_ANDROID)
304   int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
305   base::FilePath pak_file;
306   bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
307   CHECK(r);
308   pak_file = pak_file.Append(FILE_PATH_LITERAL("paks"));
309   pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
310
311   base::File f(pak_file, flags);
312   if (!f.IsValid()) {
313     NOTREACHED() << "Failed to open file when creating renderer process: "
314                  << "content_shell.pak";
315   }
316
317   mappings->Transfer(kShellPakDescriptor, base::ScopedFD(f.TakePlatformFile()));
318
319   if (breakpad::IsCrashReporterEnabled()) {
320     f = breakpad::CrashDumpManager::GetInstance()->CreateMinidumpFile(
321         child_process_id);
322     if (!f.IsValid()) {
323       LOG(ERROR) << "Failed to create file for minidump, crash reporting will "
324                  << "be disabled for this process.";
325     } else {
326       mappings->Transfer(kAndroidMinidumpDescriptor,
327                          base::ScopedFD(f.TakePlatformFile()));
328     }
329   }
330 #else  // !defined(OS_ANDROID)
331   int crash_signal_fd = GetCrashSignalFD(command_line);
332   if (crash_signal_fd >= 0) {
333     mappings->Share(kCrashDumpSignal, crash_signal_fd);
334   }
335 #endif  // defined(OS_ANDROID)
336 }
337 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
338
339 #if defined(OS_WIN)
340 void ShellContentBrowserClient::PreSpawnRenderer(sandbox::TargetPolicy* policy,
341                                                  bool* success) {
342   // Add sideloaded font files for testing. See also DIR_WINDOWS_FONTS
343   // addition in |StartSandboxedProcess|.
344   std::vector<std::string> font_files = GetSideloadFontFiles();
345   for (std::vector<std::string>::const_iterator i(font_files.begin());
346       i != font_files.end();
347       ++i) {
348     policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
349         sandbox::TargetPolicy::FILES_ALLOW_READONLY,
350         base::UTF8ToWide(*i).c_str());
351   }
352 }
353 #endif  // OS_WIN
354
355 ShellBrowserContext* ShellContentBrowserClient::browser_context() {
356   return shell_browser_main_parts_->browser_context();
357 }
358
359 ShellBrowserContext*
360     ShellContentBrowserClient::off_the_record_browser_context() {
361   return shell_browser_main_parts_->off_the_record_browser_context();
362 }
363
364 AccessTokenStore* ShellContentBrowserClient::CreateAccessTokenStore() {
365   return new ShellAccessTokenStore(browser_context());
366 }
367
368 ShellBrowserContext*
369 ShellContentBrowserClient::ShellBrowserContextForBrowserContext(
370     BrowserContext* content_browser_context) {
371   if (content_browser_context == browser_context())
372     return browser_context();
373   DCHECK_EQ(content_browser_context, off_the_record_browser_context());
374   return off_the_record_browser_context();
375 }
376
377 }  // namespace content