Upstream version 10.39.225.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/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"
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 void RequestDesktopNotificationPermissionOnIO(
119     const GURL& source_origin,
120     RenderFrameHost* render_frame_host,
121     const base::Callback<void(blink::WebNotificationPermission)>& callback) {
122   ShellNotificationManager* manager =
123       ShellContentBrowserClient::Get()->GetShellNotificationManager();
124   if (manager)
125     manager->RequestPermission(source_origin, callback);
126   else
127     callback.Run(blink::WebNotificationPermissionAllowed);
128 }
129
130 }  // namespace
131
132 ShellContentBrowserClient* ShellContentBrowserClient::Get() {
133   return g_browser_client;
134 }
135
136 void ShellContentBrowserClient::SetSwapProcessesForRedirect(bool swap) {
137   g_swap_processes_for_redirect = swap;
138 }
139
140 ShellContentBrowserClient::ShellContentBrowserClient()
141     : shell_browser_main_parts_(NULL) {
142   DCHECK(!g_browser_client);
143   g_browser_client = this;
144   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
145     return;
146   webkit_source_dir_ = GetWebKitRootDirFilePath();
147 }
148
149 ShellContentBrowserClient::~ShellContentBrowserClient() {
150   g_browser_client = NULL;
151 }
152
153 ShellNotificationManager*
154 ShellContentBrowserClient::GetShellNotificationManager() {
155   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
156   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
157     return NULL;
158
159   if (!shell_notification_manager_)
160     shell_notification_manager_.reset(new ShellNotificationManager());
161
162   return shell_notification_manager_.get();
163 }
164
165 BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
166     const MainFunctionParams& parameters) {
167   shell_browser_main_parts_ = new ShellBrowserMainParts(parameters);
168   return shell_browser_main_parts_;
169 }
170
171 void ShellContentBrowserClient::RenderProcessWillLaunch(
172     RenderProcessHost* host) {
173   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kExposeIpcEcho))
174     host->AddFilter(new IPCEchoMessageFilter());
175   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
176     return;
177   host->AddFilter(new ShellMessageFilter(
178       host->GetID(),
179       BrowserContext::GetDefaultStoragePartition(browser_context())
180           ->GetDatabaseTracker(),
181       BrowserContext::GetDefaultStoragePartition(browser_context())
182           ->GetQuotaManager(),
183       BrowserContext::GetDefaultStoragePartition(browser_context())
184           ->GetURLRequestContext()));
185   host->Send(new ShellViewMsg_SetWebKitSourceDir(webkit_source_dir_));
186 }
187
188 net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
189     BrowserContext* content_browser_context,
190     ProtocolHandlerMap* protocol_handlers,
191     URLRequestInterceptorScopedVector request_interceptors) {
192   ShellBrowserContext* shell_browser_context =
193       ShellBrowserContextForBrowserContext(content_browser_context);
194   return shell_browser_context->CreateRequestContext(
195       protocol_handlers, request_interceptors.Pass());
196 }
197
198 net::URLRequestContextGetter*
199 ShellContentBrowserClient::CreateRequestContextForStoragePartition(
200     BrowserContext* content_browser_context,
201     const base::FilePath& partition_path,
202     bool in_memory,
203     ProtocolHandlerMap* protocol_handlers,
204     URLRequestInterceptorScopedVector request_interceptors) {
205   ShellBrowserContext* shell_browser_context =
206       ShellBrowserContextForBrowserContext(content_browser_context);
207   return shell_browser_context->CreateRequestContextForStoragePartition(
208       partition_path,
209       in_memory,
210       protocol_handlers,
211       request_interceptors.Pass());
212 }
213
214 bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
215   if (!url.is_valid())
216     return false;
217   DCHECK_EQ(url.scheme(), base::StringToLowerASCII(url.scheme()));
218   // Keep in sync with ProtocolHandlers added by
219   // ShellURLRequestContextGetter::GetURLRequestContext().
220   static const char* const kProtocolList[] = {
221       url::kBlobScheme,
222       url::kFileSystemScheme,
223       kChromeUIScheme,
224       kChromeDevToolsScheme,
225       url::kDataScheme,
226       url::kFileScheme,
227   };
228   for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
229     if (url.scheme() == kProtocolList[i])
230       return true;
231   }
232   return false;
233 }
234
235 void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
236     CommandLine* command_line, int child_process_id) {
237   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
238     command_line->AppendSwitch(switches::kDumpRenderTree);
239   if (CommandLine::ForCurrentProcess()->HasSwitch(
240       switches::kEnableFontAntialiasing))
241     command_line->AppendSwitch(switches::kEnableFontAntialiasing);
242   if (CommandLine::ForCurrentProcess()->HasSwitch(
243       switches::kExposeInternalsForTesting))
244     command_line->AppendSwitch(switches::kExposeInternalsForTesting);
245   if (CommandLine::ForCurrentProcess()->HasSwitch(
246       switches::kExposeIpcEcho))
247     command_line->AppendSwitch(switches::kExposeIpcEcho);
248   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStableReleaseMode))
249     command_line->AppendSwitch(switches::kStableReleaseMode);
250   if (CommandLine::ForCurrentProcess()->HasSwitch(
251           switches::kEnableCrashReporter)) {
252     command_line->AppendSwitch(switches::kEnableCrashReporter);
253   }
254   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir)) {
255     command_line->AppendSwitchPath(
256         switches::kCrashDumpsDir,
257         CommandLine::ForCurrentProcess()->GetSwitchValuePath(
258             switches::kCrashDumpsDir));
259   }
260   if (CommandLine::ForCurrentProcess()->HasSwitch(
261           switches::kEnableLeakDetection)) {
262     command_line->AppendSwitchASCII(
263         switches::kEnableLeakDetection,
264         CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
265             switches::kEnableLeakDetection));
266   }
267   if (CommandLine::ForCurrentProcess()->HasSwitch(
268         switches::kRegisterFontFiles)) {
269     command_line->AppendSwitchASCII(
270         switches::kRegisterFontFiles,
271         CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
272             switches::kRegisterFontFiles));
273   }
274 }
275
276 void ShellContentBrowserClient::OverrideWebkitPrefs(
277     RenderViewHost* render_view_host,
278     const GURL& url,
279     WebPreferences* prefs) {
280   if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
281     return;
282   WebKitTestController::Get()->OverrideWebkitPrefs(prefs);
283 }
284
285 void ShellContentBrowserClient::ResourceDispatcherHostCreated() {
286   resource_dispatcher_host_delegate_.reset(
287       new ShellResourceDispatcherHostDelegate());
288   ResourceDispatcherHost::Get()->SetDelegate(
289       resource_dispatcher_host_delegate_.get());
290 }
291
292 std::string ShellContentBrowserClient::GetDefaultDownloadName() {
293   return "download";
294 }
295
296 WebContentsViewDelegate* ShellContentBrowserClient::GetWebContentsViewDelegate(
297     WebContents* web_contents) {
298 #if !defined(USE_AURA)
299   return CreateShellWebContentsViewDelegate(web_contents);
300 #else
301   return NULL;
302 #endif
303 }
304
305 QuotaPermissionContext*
306 ShellContentBrowserClient::CreateQuotaPermissionContext() {
307   return new ShellQuotaPermissionContext();
308 }
309
310 void ShellContentBrowserClient::RequestDesktopNotificationPermission(
311     const GURL& source_origin,
312     RenderFrameHost* render_frame_host,
313     const base::Callback<void(blink::WebNotificationPermission)>& callback) {
314   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
315   BrowserThread::PostTask(BrowserThread::IO,
316                           FROM_HERE,
317                           base::Bind(&RequestDesktopNotificationPermissionOnIO,
318                               source_origin,
319                               render_frame_host,
320                               callback));
321 }
322
323 blink::WebNotificationPermission
324 ShellContentBrowserClient::CheckDesktopNotificationPermission(
325     const GURL& source_url,
326     ResourceContext* context,
327     int render_process_id) {
328   ShellNotificationManager* manager = GetShellNotificationManager();
329   if (manager)
330     return manager->CheckPermission(source_url);
331
332   return blink::WebNotificationPermissionAllowed;
333 }
334
335 SpeechRecognitionManagerDelegate*
336     ShellContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
337   return new ShellSpeechRecognitionManagerDelegate();
338 }
339
340 net::NetLog* ShellContentBrowserClient::GetNetLog() {
341   return shell_browser_main_parts_->net_log();
342 }
343
344 bool ShellContentBrowserClient::ShouldSwapProcessesForRedirect(
345     ResourceContext* resource_context,
346     const GURL& current_url,
347     const GURL& new_url) {
348   return g_swap_processes_for_redirect;
349 }
350
351 DevToolsManagerDelegate*
352 ShellContentBrowserClient::GetDevToolsManagerDelegate() {
353   return new ShellDevToolsManagerDelegate(browser_context());
354 }
355
356 #if defined(OS_POSIX) && !defined(OS_MACOSX)
357 void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
358     const CommandLine& command_line,
359     int child_process_id,
360     std::vector<FileDescriptorInfo>* mappings) {
361 #if defined(OS_ANDROID)
362   int flags = base::File::FLAG_OPEN | base::File::FLAG_READ;
363   base::FilePath pak_file;
364   bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
365   CHECK(r);
366   pak_file = pak_file.Append(FILE_PATH_LITERAL("paks"));
367   pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
368
369   base::File f(pak_file, flags);
370   if (!f.IsValid()) {
371     NOTREACHED() << "Failed to open file when creating renderer process: "
372                  << "content_shell.pak";
373   }
374   mappings->push_back(
375       FileDescriptorInfo(kShellPakDescriptor, base::FileDescriptor(f.Pass())));
376
377   if (breakpad::IsCrashReporterEnabled()) {
378     f = breakpad::CrashDumpManager::GetInstance()->CreateMinidumpFile(
379         child_process_id);
380     if (!f.IsValid()) {
381       LOG(ERROR) << "Failed to create file for minidump, crash reporting will "
382                  << "be disabled for this process.";
383     } else {
384       mappings->push_back(
385           FileDescriptorInfo(kAndroidMinidumpDescriptor,
386                              base::FileDescriptor(f.Pass())));
387     }
388   }
389 #else  // !defined(OS_ANDROID)
390   int crash_signal_fd = GetCrashSignalFD(command_line);
391   if (crash_signal_fd >= 0) {
392     mappings->push_back(FileDescriptorInfo(
393         kCrashDumpSignal, base::FileDescriptor(crash_signal_fd, false)));
394   }
395 #endif  // defined(OS_ANDROID)
396 }
397 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
398
399 #if defined(OS_WIN)
400 void ShellContentBrowserClient::PreSpawnRenderer(sandbox::TargetPolicy* policy,
401                                                  bool* success) {
402   // Add sideloaded font files for testing. See also DIR_WINDOWS_FONTS
403   // addition in |StartSandboxedProcess|.
404   std::vector<std::string> font_files = GetSideloadFontFiles();
405   for (std::vector<std::string>::const_iterator i(font_files.begin());
406       i != font_files.end();
407       ++i) {
408     policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
409         sandbox::TargetPolicy::FILES_ALLOW_READONLY,
410         base::UTF8ToWide(*i).c_str());
411   }
412 }
413 #endif  // OS_WIN
414
415 ShellBrowserContext* ShellContentBrowserClient::browser_context() {
416   return shell_browser_main_parts_->browser_context();
417 }
418
419 ShellBrowserContext*
420     ShellContentBrowserClient::off_the_record_browser_context() {
421   return shell_browser_main_parts_->off_the_record_browser_context();
422 }
423
424 AccessTokenStore* ShellContentBrowserClient::CreateAccessTokenStore() {
425   return new ShellAccessTokenStore(browser_context());
426 }
427
428 ShellBrowserContext*
429 ShellContentBrowserClient::ShellBrowserContextForBrowserContext(
430     BrowserContext* content_browser_context) {
431   if (content_browser_context == browser_context())
432     return browser_context();
433   DCHECK_EQ(content_browser_context, off_the_record_browser_context());
434   return off_the_record_browser_context();
435 }
436
437 }  // namespace content