1 // Copyright (c) 2012 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/shell_content_browser_client.h" 6 7 #include "base/command_line.h" 8 #include "base/file_util.h" 9 #include "base/path_service.h" 10 #include "content/public/browser/notification_service.h" 11 #include "content/public/browser/notification_types.h" 12 #include "content/public/browser/render_process_host.h" 13 #include "content/public/browser/resource_dispatcher_host.h" 14 #include "content/public/browser/storage_partition.h" 15 #include "content/public/common/content_switches.h" 16 #include "content/public/common/url_constants.h" 17 #include "content/shell/common/shell_messages.h" 18 #include "content/shell/common/shell_switches.h" 19 #include "content/shell/common/webkit_test_helpers.h" 20 #include "content/shell/geolocation/shell_access_token_store.h" 21 #include "content/shell/shell.h" 22 #include "content/shell/shell_browser_context.h" 23 #include "content/shell/shell_browser_main_parts.h" 24 #include "content/shell/shell_devtools_delegate.h" 25 #include "content/shell/shell_message_filter.h" 26 #include "content/shell/shell_net_log.h" 27 #include "content/shell/shell_quota_permission_context.h" 28 #include "content/shell/shell_resource_dispatcher_host_delegate.h" 29 #include "content/shell/shell_web_contents_view_delegate_creator.h" 30 #include "content/shell/webkit_test_controller.h" 31 #include "net/url_request/url_request_context_getter.h" 32 #include "url/gurl.h" 33 #include "webkit/common/webpreferences.h" 34 35 #if defined(OS_ANDROID) 36 #include "base/android/path_utils.h" 37 #include "base/path_service.h" 38 #include "base/platform_file.h" 39 #include "content/shell/android/shell_descriptors.h" 40 #endif 41 42 namespace content { 43 44 namespace { 45 46 ShellContentBrowserClient* g_browser_client; 47 bool g_swap_processes_for_redirect = false; 48 49 } // namespace 50 51 ShellContentBrowserClient* ShellContentBrowserClient::Get() { 52 return g_browser_client; 53 } 54 55 void ShellContentBrowserClient::SetSwapProcessesForRedirect(bool swap) { 56 g_swap_processes_for_redirect = swap; 57 } 58 59 ShellContentBrowserClient::ShellContentBrowserClient() 60 : shell_browser_main_parts_(NULL) { 61 DCHECK(!g_browser_client); 62 g_browser_client = this; 63 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 64 return; 65 webkit_source_dir_ = GetWebKitRootDirFilePath(); 66 } 67 68 ShellContentBrowserClient::~ShellContentBrowserClient() { 69 g_browser_client = NULL; 70 } 71 72 BrowserMainParts* ShellContentBrowserClient::CreateBrowserMainParts( 73 const MainFunctionParams& parameters) { 74 shell_browser_main_parts_ = new ShellBrowserMainParts(parameters); 75 return shell_browser_main_parts_; 76 } 77 78 void ShellContentBrowserClient::RenderProcessHostCreated( 79 RenderProcessHost* host) { 80 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 81 return; 82 host->GetChannel()->AddFilter(new ShellMessageFilter( 83 host->GetID(), 84 BrowserContext::GetDefaultStoragePartition(browser_context()) 85 ->GetDatabaseTracker(), 86 BrowserContext::GetDefaultStoragePartition(browser_context()) 87 ->GetQuotaManager(), 88 BrowserContext::GetDefaultStoragePartition(browser_context()) 89 ->GetURLRequestContext())); 90 host->Send(new ShellViewMsg_SetWebKitSourceDir(webkit_source_dir_)); 91 registrar_.Add(this, 92 NOTIFICATION_RENDERER_PROCESS_CREATED, 93 Source<RenderProcessHost>(host)); 94 registrar_.Add(this, 95 NOTIFICATION_RENDERER_PROCESS_TERMINATED, 96 Source<RenderProcessHost>(host)); 97 } 98 99 net::URLRequestContextGetter* ShellContentBrowserClient::CreateRequestContext( 100 BrowserContext* content_browser_context, 101 ProtocolHandlerMap* protocol_handlers) { 102 ShellBrowserContext* shell_browser_context = 103 ShellBrowserContextForBrowserContext(content_browser_context); 104 return shell_browser_context->CreateRequestContext(protocol_handlers); 105 } 106 107 net::URLRequestContextGetter* 108 ShellContentBrowserClient::CreateRequestContextForStoragePartition( 109 BrowserContext* content_browser_context, 110 const base::FilePath& partition_path, 111 bool in_memory, 112 ProtocolHandlerMap* protocol_handlers) { 113 ShellBrowserContext* shell_browser_context = 114 ShellBrowserContextForBrowserContext(content_browser_context); 115 return shell_browser_context->CreateRequestContextForStoragePartition( 116 partition_path, in_memory, protocol_handlers); 117 } 118 119 bool ShellContentBrowserClient::IsHandledURL(const GURL& url) { 120 if (!url.is_valid()) 121 return false; 122 DCHECK_EQ(url.scheme(), StringToLowerASCII(url.scheme())); 123 // Keep in sync with ProtocolHandlers added by 124 // ShellURLRequestContextGetter::GetURLRequestContext(). 125 static const char* const kProtocolList[] = { 126 chrome::kBlobScheme, 127 chrome::kFileSystemScheme, 128 chrome::kChromeUIScheme, 129 chrome::kChromeDevToolsScheme, 130 chrome::kDataScheme, 131 chrome::kFileScheme, 132 }; 133 for (size_t i = 0; i < arraysize(kProtocolList); ++i) { 134 if (url.scheme() == kProtocolList[i]) 135 return true; 136 } 137 return false; 138 } 139 140 void ShellContentBrowserClient::AppendExtraCommandLineSwitches( 141 CommandLine* command_line, int child_process_id) { 142 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 143 command_line->AppendSwitch(switches::kDumpRenderTree); 144 if (CommandLine::ForCurrentProcess()->HasSwitch( 145 switches::kExposeInternalsForTesting)) 146 command_line->AppendSwitch(switches::kExposeInternalsForTesting); 147 } 148 149 void ShellContentBrowserClient::OverrideWebkitPrefs( 150 RenderViewHost* render_view_host, 151 const GURL& url, 152 WebPreferences* prefs) { 153 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) 154 return; 155 WebKitTestController::Get()->OverrideWebkitPrefs(prefs); 156 } 157 158 void ShellContentBrowserClient::ResourceDispatcherHostCreated() { 159 resource_dispatcher_host_delegate_.reset( 160 new ShellResourceDispatcherHostDelegate()); 161 ResourceDispatcherHost::Get()->SetDelegate( 162 resource_dispatcher_host_delegate_.get()); 163 } 164 165 std::string ShellContentBrowserClient::GetDefaultDownloadName() { 166 return "download"; 167 } 168 169 bool ShellContentBrowserClient::SupportsBrowserPlugin( 170 content::BrowserContext* browser_context, const GURL& url) { 171 return CommandLine::ForCurrentProcess()->HasSwitch( 172 switches::kEnableBrowserPluginForAllViewTypes); 173 } 174 175 WebContentsViewDelegate* ShellContentBrowserClient::GetWebContentsViewDelegate( 176 WebContents* web_contents) { 177 #if !defined(USE_AURA) 178 return CreateShellWebContentsViewDelegate(web_contents); 179 #else 180 return NULL; 181 #endif 182 } 183 184 QuotaPermissionContext* 185 ShellContentBrowserClient::CreateQuotaPermissionContext() { 186 return new ShellQuotaPermissionContext(); 187 } 188 189 net::NetLog* ShellContentBrowserClient::GetNetLog() { 190 return shell_browser_main_parts_->net_log(); 191 } 192 193 bool ShellContentBrowserClient::ShouldSwapProcessesForRedirect( 194 ResourceContext* resource_context, 195 const GURL& current_url, 196 const GURL& new_url) { 197 return g_swap_processes_for_redirect; 198 } 199 200 #if defined(OS_ANDROID) 201 void ShellContentBrowserClient::GetAdditionalMappedFilesForChildProcess( 202 const CommandLine& command_line, 203 int child_process_id, 204 std::vector<content::FileDescriptorInfo>* mappings) { 205 int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ; 206 base::FilePath pak_file; 207 bool r = PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file); 208 CHECK(r); 209 pak_file = pak_file.Append(FILE_PATH_LITERAL("paks")); 210 pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak")); 211 212 base::PlatformFile f = 213 base::CreatePlatformFile(pak_file, flags, NULL, NULL); 214 if (f == base::kInvalidPlatformFileValue) { 215 NOTREACHED() << "Failed to open file when creating renderer process: " 216 << "content_shell.pak"; 217 } 218 mappings->push_back( 219 content::FileDescriptorInfo(kShellPakDescriptor, 220 base::FileDescriptor(f, true))); 221 } 222 #endif 223 224 void ShellContentBrowserClient::Observe(int type, 225 const NotificationSource& source, 226 const NotificationDetails& details) { 227 switch (type) { 228 case NOTIFICATION_RENDERER_PROCESS_CREATED: { 229 registrar_.Remove(this, 230 NOTIFICATION_RENDERER_PROCESS_CREATED, 231 source); 232 registrar_.Remove(this, 233 NOTIFICATION_RENDERER_PROCESS_TERMINATED, 234 source); 235 break; 236 } 237 238 case NOTIFICATION_RENDERER_PROCESS_TERMINATED: { 239 registrar_.Remove(this, 240 NOTIFICATION_RENDERER_PROCESS_CREATED, 241 source); 242 registrar_.Remove(this, 243 NOTIFICATION_RENDERER_PROCESS_TERMINATED, 244 source); 245 break; 246 } 247 248 default: 249 NOTREACHED(); 250 } 251 } 252 253 ShellBrowserContext* ShellContentBrowserClient::browser_context() { 254 return shell_browser_main_parts_->browser_context(); 255 } 256 257 ShellBrowserContext* 258 ShellContentBrowserClient::off_the_record_browser_context() { 259 return shell_browser_main_parts_->off_the_record_browser_context(); 260 } 261 262 AccessTokenStore* ShellContentBrowserClient::CreateAccessTokenStore() { 263 return new ShellAccessTokenStore(browser_context()); 264 } 265 266 ShellBrowserContext* 267 ShellContentBrowserClient::ShellBrowserContextForBrowserContext( 268 BrowserContext* content_browser_context) { 269 if (content_browser_context == browser_context()) 270 return browser_context(); 271 DCHECK_EQ(content_browser_context, off_the_record_browser_context()); 272 return off_the_record_browser_context(); 273 } 274 275 } // namespace content 276