Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / shell / browser / shell_content_browser_client.cc
blob17d03baabc41d110fcd49de9d0c40ff657e03344
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/path_service.h"
11 #include "content/public/browser/notification_service.h"
12 #include "content/public/browser/notification_types.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/shell/browser/shell.h"
19 #include "content/shell/browser/shell_browser_context.h"
20 #include "content/shell/browser/shell_browser_main_parts.h"
21 #include "content/shell/browser/shell_devtools_delegate.h"
22 #include "content/shell/browser/shell_message_filter.h"
23 #include "content/shell/browser/shell_net_log.h"
24 #include "content/shell/browser/shell_quota_permission_context.h"
25 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
26 #include "content/shell/browser/shell_web_contents_view_delegate_creator.h"
27 #include "content/shell/browser/webkit_test_controller.h"
28 #include "content/shell/common/shell_messages.h"
29 #include "content/shell/common/shell_switches.h"
30 #include "content/shell/common/webkit_test_helpers.h"
31 #include "content/shell/geolocation/shell_access_token_store.h"
32 #include "net/url_request/url_request_context_getter.h"
33 #include "url/gurl.h"
34 #include "webkit/common/webpreferences.h"
36 #if defined(OS_ANDROID)
37 #include "base/android/path_utils.h"
38 #include "base/path_service.h"
39 #include "components/breakpad/browser/crash_dump_manager_android.h"
40 #include "content/shell/android/shell_descriptors.h"
41 #endif
43 #if defined(OS_POSIX) && !defined(OS_MACOSX)
44 #include "base/debug/leak_annotations.h"
45 #include "base/platform_file.h"
46 #include "components/breakpad/app/breakpad_linux.h"
47 #include "components/breakpad/browser/crash_handler_host_linux.h"
48 #include "content/public/common/content_descriptors.h"
49 #endif
51 namespace content {
53 namespace {
55 ShellContentBrowserClient* g_browser_client;
56 bool g_swap_processes_for_redirect = false;
58 #if defined(OS_POSIX) && !defined(OS_MACOSX)
59 breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
60 const std::string& process_type) {
61 base::FilePath dumps_path =
62 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
63 switches::kCrashDumpsDir);
65 ANNOTATE_SCOPED_MEMORY_LEAK;
66 breakpad::CrashHandlerHostLinux* crash_handler =
67 new breakpad::CrashHandlerHostLinux(
68 process_type, dumps_path, false);
69 crash_handler->StartUploaderThread();
70 return crash_handler;
74 int GetCrashSignalFD(const CommandLine& command_line) {
75 if (!breakpad::IsCrashReporterEnabled())
76 return -1;
78 std::string process_type =
79 command_line.GetSwitchValueASCII(switches::kProcessType);
81 if (process_type == switches::kRendererProcess) {
82 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
83 if (!crash_handler)
84 crash_handler = CreateCrashHandlerHost(process_type);
85 return crash_handler->GetDeathSignalSocket();
88 if (process_type == switches::kPluginProcess) {
89 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
90 if (!crash_handler)
91 crash_handler = CreateCrashHandlerHost(process_type);
92 return crash_handler->GetDeathSignalSocket();
95 if (process_type == switches::kPpapiPluginProcess) {
96 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
97 if (!crash_handler)
98 crash_handler = CreateCrashHandlerHost(process_type);
99 return crash_handler->GetDeathSignalSocket();
102 if (process_type == switches::kGpuProcess) {
103 static breakpad::CrashHandlerHostLinux* crash_handler = NULL;
104 if (!crash_handler)
105 crash_handler = CreateCrashHandlerHost(process_type);
106 return crash_handler->GetDeathSignalSocket();
109 return -1;
111 #endif // defined(OS_POSIX) && !defined(OS_MACOSX)
113 } // namespace
115 ShellContentBrowserClient* ShellContentBrowserClient::Get() {
116 return g_browser_client;
119 void ShellContentBrowserClient::SetSwapProcessesForRedirect(bool swap) {
120 g_swap_processes_for_redirect = swap;
123 ShellContentBrowserClient::ShellContentBrowserClient()
124 : shell_browser_main_parts_(NULL) {
125 DCHECK(!g_browser_client);
126 g_browser_client = this;
127 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
128 return;
129 webkit_source_dir_ = GetWebKitRootDirFilePath();
132 ShellContentBrowserClient::~ShellContentBrowserClient() {
133 g_browser_client = NULL;
136 BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts(
137 const MainFunctionParams& parameters) {
138 shell_browser_main_parts_ = new ShellBrowserMainParts(parameters);
139 return shell_browser_main_parts_;
142 void ShellContentBrowserClient::RenderProcessHostCreated(
143 RenderProcessHost* host) {
144 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
145 return;
146 host->AddFilter(new ShellMessageFilter(
147 host->GetID(),
148 BrowserContext::GetDefaultStoragePartition(browser_context())
149 ->GetDatabaseTracker(),
150 BrowserContext::GetDefaultStoragePartition(browser_context())
151 ->GetQuotaManager(),
152 BrowserContext::GetDefaultStoragePartition(browser_context())
153 ->GetURLRequestContext()));
154 host->Send(new ShellViewMsg_SetWebKitSourceDir(webkit_source_dir_));
155 registrar_.Add(this,
156 NOTIFICATION_RENDERER_PROCESS_CREATED,
157 Source<RenderProcessHost>(host));
158 registrar_.Add(this,
159 NOTIFICATION_RENDERER_PROCESS_TERMINATED,
160 Source<RenderProcessHost>(host));
163 net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext(
164 BrowserContext* content_browser_context,
165 ProtocolHandlerMap* protocol_handlers) {
166 ShellBrowserContext* shell_browser_context =
167 ShellBrowserContextForBrowserContext(content_browser_context);
168 return shell_browser_context->CreateRequestContext(protocol_handlers);
171 net::URLRequestContextGetter*
172 ShellContentBrowserClient::CreateRequestContextForStoragePartition(
173 BrowserContext* content_browser_context,
174 const base::FilePath& partition_path,
175 bool in_memory,
176 ProtocolHandlerMap* protocol_handlers) {
177 ShellBrowserContext* shell_browser_context =
178 ShellBrowserContextForBrowserContext(content_browser_context);
179 return shell_browser_context->CreateRequestContextForStoragePartition(
180 partition_path, in_memory, protocol_handlers);
183 bool ShellContentBrowserClient::IsHandledURL(const GURL& url) {
184 if (!url.is_valid())
185 return false;
186 DCHECK_EQ(url.scheme(), StringToLowerASCII(url.scheme()));
187 // Keep in sync with ProtocolHandlers added by
188 // ShellURLRequestContextGetter::GetURLRequestContext().
189 static const char* const kProtocolList[] = {
190 chrome::kBlobScheme,
191 chrome::kFileSystemScheme,
192 chrome::kChromeUIScheme,
193 chrome::kChromeDevToolsScheme,
194 chrome::kDataScheme,
195 chrome::kFileScheme,
197 for (size_t i = 0; i < arraysize(kProtocolList); ++i) {
198 if (url.scheme() == kProtocolList[i])
199 return true;
201 return false;
204 void ShellContentBrowserClient::AppendExtraCommandLineSwitches(
205 CommandLine* command_line, int child_process_id) {
206 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
207 command_line->AppendSwitch(switches::kDumpRenderTree);
208 if (CommandLine::ForCurrentProcess()->HasSwitch(
209 switches::kExposeInternalsForTesting))
210 command_line->AppendSwitch(switches::kExposeInternalsForTesting);
211 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStableReleaseMode))
212 command_line->AppendSwitch(switches::kStableReleaseMode);
213 if (CommandLine::ForCurrentProcess()->HasSwitch(
214 switches::kEnableCrashReporter)) {
215 command_line->AppendSwitch(switches::kEnableCrashReporter);
217 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kCrashDumpsDir)) {
218 command_line->AppendSwitchPath(
219 switches::kCrashDumpsDir,
220 CommandLine::ForCurrentProcess()->GetSwitchValuePath(
221 switches::kCrashDumpsDir));
225 void ShellContentBrowserClient::OverrideWebkitPrefs(
226 RenderViewHost* render_view_host,
227 const GURL& url,
228 WebPreferences* prefs) {
229 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree))
230 return;
231 WebKitTestController::Get()->OverrideWebkitPrefs(prefs);
234 void ShellContentBrowserClient::ResourceDispatcherHostCreated() {
235 resource_dispatcher_host_delegate_.reset(
236 new ShellResourceDispatcherHostDelegate());
237 ResourceDispatcherHost::Get()->SetDelegate(
238 resource_dispatcher_host_delegate_.get());
241 std::string ShellContentBrowserClient::GetDefaultDownloadName() {
242 return "download";
245 bool ShellContentBrowserClient::SupportsBrowserPlugin(
246 content::BrowserContext* browser_context, const GURL& url) {
247 return CommandLine::ForCurrentProcess()->HasSwitch(
248 switches::kEnableBrowserPluginForAllViewTypes);
251 WebContentsViewDelegate* ShellContentBrowserClient::GetWebContentsViewDelegate(
252 WebContents* web_contents) {
253 #if !defined(USE_AURA)
254 return CreateShellWebContentsViewDelegate(web_contents);
255 #else
256 return NULL;
257 #endif
260 QuotaPermissionContext*
261 ShellContentBrowserClient::CreateQuotaPermissionContext() {
262 return new ShellQuotaPermissionContext();
265 SpeechRecognitionManagerDelegate*
266 ShellContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
267 return new ShellSpeechRecognitionManagerDelegate();
270 net::NetLog* ShellContentBrowserClient::GetNetLog() {
271 return shell_browser_main_parts_->net_log();
274 bool ShellContentBrowserClient::ShouldSwapProcessesForRedirect(
275 ResourceContext* resource_context,
276 const GURL& current_url,
277 const GURL& new_url) {
278 return g_swap_processes_for_redirect;
281 #if defined(OS_POSIX) && !defined(OS_MACOSX)
282 void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
283 const CommandLine& command_line,
284 int child_process_id,
285 std::vector<content::FileDescriptorInfo>* mappings) {
286 #if defined(OS_ANDROID)
287 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
288 base::FilePath pak_file;
289 bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file);
290 CHECK(r);
291 pak_file = pak_file.Append(FILE_PATH_LITERAL("paks"));
292 pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak"));
294 base::PlatformFile f =
295 base::CreatePlatformFile(pak_file, flags, NULL, NULL);
296 if (f == base::kInvalidPlatformFileValue) {
297 NOTREACHED() << "Failed to open file when creating renderer process: "
298 << "content_shell.pak";
300 mappings->push_back(
301 content::FileDescriptorInfo(kShellPakDescriptor,
302 base::FileDescriptor(f, true)));
304 if (breakpad::IsCrashReporterEnabled()) {
305 f = breakpad::CrashDumpManager::GetInstance()->CreateMinidumpFile(
306 child_process_id);
307 if (f == base::kInvalidPlatformFileValue) {
308 LOG(ERROR) << "Failed to create file for minidump, crash reporting will "
309 << "be disabled for this process.";
310 } else {
311 mappings->push_back(FileDescriptorInfo(kAndroidMinidumpDescriptor,
312 base::FileDescriptor(f, true)));
315 #else // !defined(OS_ANDROID)
316 int crash_signal_fd = GetCrashSignalFD(command_line);
317 if (crash_signal_fd >= 0) {
318 mappings->push_back(FileDescriptorInfo(
319 kCrashDumpSignal, base::FileDescriptor(crash_signal_fd, false)));
321 #endif // defined(OS_ANDROID)
323 #endif // defined(OS_POSIX) && !defined(OS_MACOSX)
325 void ShellContentBrowserClient::Observe(int type,
326 const NotificationSource& source,
327 const NotificationDetails& details) {
328 switch (type) {
329 case NOTIFICATION_RENDERER_PROCESS_CREATED: {
330 registrar_.Remove(this,
331 NOTIFICATION_RENDERER_PROCESS_CREATED,
332 source);
333 registrar_.Remove(this,
334 NOTIFICATION_RENDERER_PROCESS_TERMINATED,
335 source);
336 break;
339 case NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
340 registrar_.Remove(this,
341 NOTIFICATION_RENDERER_PROCESS_CREATED,
342 source);
343 registrar_.Remove(this,
344 NOTIFICATION_RENDERER_PROCESS_TERMINATED,
345 source);
346 break;
349 default:
350 NOTREACHED();
354 ShellBrowserContext* ShellContentBrowserClient::browser_context() {
355 return shell_browser_main_parts_->browser_context();
358 ShellBrowserContext*
359 ShellContentBrowserClient::off_the_record_browser_context() {
360 return shell_browser_main_parts_->off_the_record_browser_context();
363 AccessTokenStore* ShellContentBrowserClient::CreateAccessTokenStore() {
364 return new ShellAccessTokenStore(browser_context());
367 ShellBrowserContext*
368 ShellContentBrowserClient::ShellBrowserContextForBrowserContext(
369 BrowserContext* content_browser_context) {
370 if (content_browser_context == browser_context())
371 return browser_context();
372 DCHECK_EQ(content_browser_context, off_the_record_browser_context());
373 return off_the_record_browser_context();
376 } // namespace content