| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "headless/lib/browser/headless_browser_context_impl.h" | 5 #include "headless/lib/browser/headless_browser_context_impl.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <string> |
| 9 #include <utility> |
| 10 #include <vector> |
| 8 | 11 |
| 9 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 10 #include "base/path_service.h" | 13 #include "base/path_service.h" |
| 11 #include "content/public/browser/browser_thread.h" | 14 #include "content/public/browser/browser_thread.h" |
| 12 #include "content/public/browser/resource_context.h" | 15 #include "content/public/browser/resource_context.h" |
| 13 #include "content/public/browser/storage_partition.h" | 16 #include "content/public/browser/storage_partition.h" |
| 17 #include "headless/lib/browser/headless_browser_context_options.h" |
| 14 #include "headless/lib/browser/headless_browser_impl.h" | 18 #include "headless/lib/browser/headless_browser_impl.h" |
| 15 #include "headless/lib/browser/headless_url_request_context_getter.h" | 19 #include "headless/lib/browser/headless_url_request_context_getter.h" |
| 16 #include "headless/public/util/black_hole_protocol_handler.h" | 20 #include "headless/public/util/black_hole_protocol_handler.h" |
| 17 #include "headless/public/util/in_memory_protocol_handler.h" | 21 #include "headless/public/util/in_memory_protocol_handler.h" |
| 18 #include "net/url_request/url_request_context.h" | 22 #include "net/url_request/url_request_context.h" |
| 19 | 23 |
| 20 namespace headless { | 24 namespace headless { |
| 21 | 25 |
| 22 namespace { | 26 namespace { |
| 23 const char kHeadlessMojomProtocol[] = "headless-mojom"; | 27 const char kHeadlessMojomProtocol[] = "headless-mojom"; |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 CHECK(url_request_context_getter_); | 70 CHECK(url_request_context_getter_); |
| 67 return url_request_context_getter_->GetURLRequestContext()->host_resolver(); | 71 return url_request_context_getter_->GetURLRequestContext()->host_resolver(); |
| 68 } | 72 } |
| 69 | 73 |
| 70 net::URLRequestContext* HeadlessResourceContext::GetRequestContext() { | 74 net::URLRequestContext* HeadlessResourceContext::GetRequestContext() { |
| 71 CHECK(url_request_context_getter_); | 75 CHECK(url_request_context_getter_); |
| 72 return url_request_context_getter_->GetURLRequestContext(); | 76 return url_request_context_getter_->GetURLRequestContext(); |
| 73 } | 77 } |
| 74 | 78 |
| 75 HeadlessBrowserContextImpl::HeadlessBrowserContextImpl( | 79 HeadlessBrowserContextImpl::HeadlessBrowserContextImpl( |
| 76 ProtocolHandlerMap protocol_handlers, | 80 HeadlessBrowserImpl* browser, |
| 77 HeadlessBrowser::Options* options) | 81 HeadlessBrowserContextOptions context_options) |
| 78 : protocol_handlers_(std::move(protocol_handlers)), | 82 : browser_(browser), |
| 79 options_(options), | 83 context_options_(std::move(context_options)), |
| 80 resource_context_(new HeadlessResourceContext) { | 84 resource_context_(new HeadlessResourceContext) { |
| 81 InitWhileIOAllowed(); | 85 InitWhileIOAllowed(); |
| 82 } | 86 } |
| 83 | 87 |
| 84 HeadlessBrowserContextImpl::~HeadlessBrowserContextImpl() { | 88 HeadlessBrowserContextImpl::~HeadlessBrowserContextImpl() { |
| 89 auto all_web_contents = GetAllWebContents(); |
| 90 for (auto* web_contents : all_web_contents) { |
| 91 web_contents->Close(); |
| 92 } |
| 93 |
| 85 ShutdownStoragePartitions(); | 94 ShutdownStoragePartitions(); |
| 95 |
| 86 if (resource_context_) { | 96 if (resource_context_) { |
| 87 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, | 97 content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, |
| 88 resource_context_.release()); | 98 resource_context_.release()); |
| 89 } | 99 } |
| 90 } | 100 } |
| 91 | 101 |
| 92 // static | 102 // static |
| 93 HeadlessBrowserContextImpl* HeadlessBrowserContextImpl::From( | 103 HeadlessBrowserContextImpl* HeadlessBrowserContextImpl::From( |
| 94 HeadlessBrowserContext* browser_context) { | 104 HeadlessBrowserContext* browser_context) { |
| 95 return reinterpret_cast<HeadlessBrowserContextImpl*>(browser_context); | 105 return reinterpret_cast<HeadlessBrowserContextImpl*>(browser_context); |
| 96 } | 106 } |
| 97 | 107 |
| 108 HeadlessWebContents::Builder |
| 109 HeadlessBrowserContextImpl::CreateWebContentsBuilder() { |
| 110 DCHECK(browser_->BrowserMainThread()->BelongsToCurrentThread()); |
| 111 return HeadlessWebContents::Builder(this); |
| 112 } |
| 113 |
| 98 void HeadlessBrowserContextImpl::InitWhileIOAllowed() { | 114 void HeadlessBrowserContextImpl::InitWhileIOAllowed() { |
| 99 // TODO(skyostil): Allow the embedder to override this. | 115 if (!context_options_.user_data_dir().empty()) { |
| 100 PathService::Get(base::DIR_EXE, &path_); | 116 path_ = context_options_.user_data_dir(); |
| 117 } else { |
| 118 PathService::Get(base::DIR_EXE, &path_); |
| 119 } |
| 101 BrowserContext::Initialize(this, path_); | 120 BrowserContext::Initialize(this, path_); |
| 102 } | 121 } |
| 103 | 122 |
| 104 std::unique_ptr<content::ZoomLevelDelegate> | 123 std::unique_ptr<content::ZoomLevelDelegate> |
| 105 HeadlessBrowserContextImpl::CreateZoomLevelDelegate( | 124 HeadlessBrowserContextImpl::CreateZoomLevelDelegate( |
| 106 const base::FilePath& partition_path) { | 125 const base::FilePath& partition_path) { |
| 107 return std::unique_ptr<content::ZoomLevelDelegate>(); | 126 return std::unique_ptr<content::ZoomLevelDelegate>(); |
| 108 } | 127 } |
| 109 | 128 |
| 110 base::FilePath HeadlessBrowserContextImpl::GetPath() const { | 129 base::FilePath HeadlessBrowserContextImpl::GetPath() const { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 | 175 |
| 157 net::URLRequestContextGetter* HeadlessBrowserContextImpl::CreateRequestContext( | 176 net::URLRequestContextGetter* HeadlessBrowserContextImpl::CreateRequestContext( |
| 158 content::ProtocolHandlerMap* protocol_handlers, | 177 content::ProtocolHandlerMap* protocol_handlers, |
| 159 content::URLRequestInterceptorScopedVector request_interceptors) { | 178 content::URLRequestInterceptorScopedVector request_interceptors) { |
| 160 scoped_refptr<HeadlessURLRequestContextGetter> url_request_context_getter( | 179 scoped_refptr<HeadlessURLRequestContextGetter> url_request_context_getter( |
| 161 new HeadlessURLRequestContextGetter( | 180 new HeadlessURLRequestContextGetter( |
| 162 content::BrowserThread::GetTaskRunnerForThread( | 181 content::BrowserThread::GetTaskRunnerForThread( |
| 163 content::BrowserThread::IO), | 182 content::BrowserThread::IO), |
| 164 content::BrowserThread::GetTaskRunnerForThread( | 183 content::BrowserThread::GetTaskRunnerForThread( |
| 165 content::BrowserThread::FILE), | 184 content::BrowserThread::FILE), |
| 166 protocol_handlers, std::move(protocol_handlers_), | 185 protocol_handlers, context_options_.TakeProtocolHandlers(), |
| 167 std::move(request_interceptors), options())); | 186 std::move(request_interceptors), &context_options_)); |
| 168 resource_context_->set_url_request_context_getter(url_request_context_getter); | 187 resource_context_->set_url_request_context_getter(url_request_context_getter); |
| 169 return url_request_context_getter.get(); | 188 return url_request_context_getter.get(); |
| 170 } | 189 } |
| 171 | 190 |
| 172 net::URLRequestContextGetter* | 191 net::URLRequestContextGetter* |
| 173 HeadlessBrowserContextImpl::CreateRequestContextForStoragePartition( | 192 HeadlessBrowserContextImpl::CreateRequestContextForStoragePartition( |
| 174 const base::FilePath& partition_path, | 193 const base::FilePath& partition_path, |
| 175 bool in_memory, | 194 bool in_memory, |
| 176 content::ProtocolHandlerMap* protocol_handlers, | 195 content::ProtocolHandlerMap* protocol_handlers, |
| 177 content::URLRequestInterceptorScopedVector request_interceptors) { | 196 content::URLRequestInterceptorScopedVector request_interceptors) { |
| 178 return nullptr; | 197 return nullptr; |
| 179 } | 198 } |
| 180 | 199 |
| 181 net::URLRequestContextGetter* | 200 net::URLRequestContextGetter* |
| 182 HeadlessBrowserContextImpl::CreateMediaRequestContext() { | 201 HeadlessBrowserContextImpl::CreateMediaRequestContext() { |
| 183 return resource_context_->url_request_context_getter(); | 202 return resource_context_->url_request_context_getter(); |
| 184 } | 203 } |
| 185 | 204 |
| 186 net::URLRequestContextGetter* | 205 net::URLRequestContextGetter* |
| 187 HeadlessBrowserContextImpl::CreateMediaRequestContextForStoragePartition( | 206 HeadlessBrowserContextImpl::CreateMediaRequestContextForStoragePartition( |
| 188 const base::FilePath& partition_path, | 207 const base::FilePath& partition_path, |
| 189 bool in_memory) { | 208 bool in_memory) { |
| 190 return nullptr; | 209 return nullptr; |
| 191 } | 210 } |
| 192 | 211 |
| 193 void HeadlessBrowserContextImpl::SetOptionsForTesting( | 212 std::vector<HeadlessWebContents*> |
| 194 HeadlessBrowser::Options* options) { | 213 HeadlessBrowserContextImpl::GetAllWebContents() { |
| 195 options_ = options; | 214 std::vector<HeadlessWebContents*> result; |
| 215 |
| 216 result.reserve(web_contents_map_.size()); |
| 217 |
| 218 for (const auto& web_contents_pair : web_contents_map_) { |
| 219 result.push_back(web_contents_pair.second); |
| 220 } |
| 221 |
| 222 return result; |
| 223 } |
| 224 |
| 225 void HeadlessBrowserContextImpl::RegisterWebContents( |
| 226 HeadlessWebContentsImpl* web_contents) { |
| 227 web_contents_map_[web_contents->GetDevtoolsAgentHostId()] = web_contents; |
| 228 } |
| 229 |
| 230 void HeadlessBrowserContextImpl::UnregisterWebContents( |
| 231 HeadlessWebContentsImpl* web_contents) { |
| 232 auto it = web_contents_map_.find(web_contents->GetDevtoolsAgentHostId()); |
| 233 DCHECK(it != web_contents_map_.end()); |
| 234 web_contents_map_.erase(it); |
| 235 } |
| 236 |
| 237 HeadlessBrowserImpl* HeadlessBrowserContextImpl::browser() const { |
| 238 return browser_; |
| 239 } |
| 240 |
| 241 const HeadlessBrowserContextOptions* HeadlessBrowserContextImpl::options() |
| 242 const { |
| 243 return &context_options_; |
| 196 } | 244 } |
| 197 | 245 |
| 198 HeadlessBrowserContext::Builder::Builder(HeadlessBrowserImpl* browser) | 246 HeadlessBrowserContext::Builder::Builder(HeadlessBrowserImpl* browser) |
| 199 : browser_(browser), enable_http_and_https_if_mojo_used_(false) {} | 247 : browser_(browser), |
| 248 options_(new HeadlessBrowserContextOptions(browser->options())), |
| 249 enable_http_and_https_if_mojo_used_(false) {} |
| 200 | 250 |
| 201 HeadlessBrowserContext::Builder::~Builder() = default; | 251 HeadlessBrowserContext::Builder::~Builder() = default; |
| 202 | 252 |
| 203 HeadlessBrowserContext::Builder::Builder(Builder&&) = default; | 253 HeadlessBrowserContext::Builder::Builder(Builder&&) = default; |
| 204 | 254 |
| 205 HeadlessBrowserContext::Builder& | 255 HeadlessBrowserContext::Builder& |
| 206 HeadlessBrowserContext::Builder::SetProtocolHandlers( | 256 HeadlessBrowserContext::Builder::SetProtocolHandlers( |
| 207 ProtocolHandlerMap protocol_handlers) { | 257 ProtocolHandlerMap protocol_handlers) { |
| 208 protocol_handlers_ = std::move(protocol_handlers); | 258 options_->protocol_handlers_ = std::move(protocol_handlers); |
| 209 return *this; | 259 return *this; |
| 210 } | 260 } |
| 211 | 261 |
| 262 HeadlessBrowserContext::Builder& HeadlessBrowserContext::Builder::SetUserAgent( |
| 263 const std::string& user_agent) { |
| 264 options_->user_agent_ = user_agent; |
| 265 return *this; |
| 266 } |
| 267 |
| 268 HeadlessBrowserContext::Builder& |
| 269 HeadlessBrowserContext::Builder::SetProxyServer( |
| 270 const net::HostPortPair& proxy_server) { |
| 271 options_->proxy_server_ = proxy_server; |
| 272 return *this; |
| 273 } |
| 274 |
| 275 HeadlessBrowserContext::Builder& |
| 276 HeadlessBrowserContext::Builder::SetHostResolverRules( |
| 277 const std::string& host_resolver_rules) { |
| 278 options_->host_resolver_rules_ = host_resolver_rules; |
| 279 return *this; |
| 280 } |
| 281 |
| 282 HeadlessBrowserContext::Builder& HeadlessBrowserContext::Builder::SetWindowSize( |
| 283 const gfx::Size& window_size) { |
| 284 options_->window_size_ = window_size; |
| 285 return *this; |
| 286 } |
| 287 |
| 288 HeadlessBrowserContext::Builder& |
| 289 HeadlessBrowserContext::Builder::SetUserDataDir( |
| 290 const base::FilePath& user_data_dir) { |
| 291 options_->user_data_dir_ = user_data_dir; |
| 292 return *this; |
| 293 } |
| 294 |
| 212 HeadlessBrowserContext::Builder& | 295 HeadlessBrowserContext::Builder& |
| 213 HeadlessBrowserContext::Builder::AddJsMojoBindings( | 296 HeadlessBrowserContext::Builder::AddJsMojoBindings( |
| 214 const std::string& mojom_name, | 297 const std::string& mojom_name, |
| 215 const std::string& js_bindings) { | 298 const std::string& js_bindings) { |
| 216 mojo_bindings_.emplace_back(mojom_name, js_bindings); | 299 mojo_bindings_.emplace_back(mojom_name, js_bindings); |
| 217 return *this; | 300 return *this; |
| 218 } | 301 } |
| 219 | 302 |
| 220 HeadlessBrowserContext::Builder& | 303 HeadlessBrowserContext::Builder& |
| 221 HeadlessBrowserContext::Builder::EnableUnsafeNetworkAccessWithMojoBindings( | 304 HeadlessBrowserContext::Builder::EnableUnsafeNetworkAccessWithMojoBindings( |
| 222 bool enable_http_and_https_if_mojo_used) { | 305 bool enable_http_and_https_if_mojo_used) { |
| 223 enable_http_and_https_if_mojo_used_ = enable_http_and_https_if_mojo_used; | 306 enable_http_and_https_if_mojo_used_ = enable_http_and_https_if_mojo_used; |
| 224 return *this; | 307 return *this; |
| 225 } | 308 } |
| 226 | 309 |
| 227 std::unique_ptr<HeadlessBrowserContext> | 310 std::unique_ptr<HeadlessBrowserContext> |
| 228 HeadlessBrowserContext::Builder::Build() { | 311 HeadlessBrowserContext::Builder::Build() { |
| 229 if (!mojo_bindings_.empty()) { | 312 if (!mojo_bindings_.empty()) { |
| 230 std::unique_ptr<InMemoryProtocolHandler> headless_mojom_protocol_handler( | 313 std::unique_ptr<InMemoryProtocolHandler> headless_mojom_protocol_handler( |
| 231 new InMemoryProtocolHandler()); | 314 new InMemoryProtocolHandler()); |
| 232 for (const MojoBindings& binding : mojo_bindings_) { | 315 for (const MojoBindings& binding : mojo_bindings_) { |
| 233 headless_mojom_protocol_handler->InsertResponse( | 316 headless_mojom_protocol_handler->InsertResponse( |
| 234 binding.mojom_name, | 317 binding.mojom_name, |
| 235 InMemoryProtocolHandler::Response(binding.js_bindings, | 318 InMemoryProtocolHandler::Response(binding.js_bindings, |
| 236 "application/javascript")); | 319 "application/javascript")); |
| 237 } | 320 } |
| 238 DCHECK(protocol_handlers_.find(kHeadlessMojomProtocol) == | 321 DCHECK(options_->protocol_handlers_.find(kHeadlessMojomProtocol) == |
| 239 protocol_handlers_.end()); | 322 options_->protocol_handlers_.end()); |
| 240 protocol_handlers_[kHeadlessMojomProtocol] = | 323 options_->protocol_handlers_[kHeadlessMojomProtocol] = |
| 241 std::move(headless_mojom_protocol_handler); | 324 std::move(headless_mojom_protocol_handler); |
| 242 | 325 |
| 243 // Unless you know what you're doing it's unsafe to allow http/https for a | 326 // Unless you know what you're doing it's unsafe to allow http/https for a |
| 244 // context with mojo bindings. | 327 // context with mojo bindings. |
| 245 if (!enable_http_and_https_if_mojo_used_) { | 328 if (!enable_http_and_https_if_mojo_used_) { |
| 246 protocol_handlers_[url::kHttpScheme] = | 329 options_->protocol_handlers_[url::kHttpScheme] = |
| 247 base::WrapUnique(new BlackHoleProtocolHandler()); | 330 base::WrapUnique(new BlackHoleProtocolHandler()); |
| 248 protocol_handlers_[url::kHttpsScheme] = | 331 options_->protocol_handlers_[url::kHttpsScheme] = |
| 249 base::WrapUnique(new BlackHoleProtocolHandler()); | 332 base::WrapUnique(new BlackHoleProtocolHandler()); |
| 250 } | 333 } |
| 251 } | 334 } |
| 252 | 335 |
| 253 return base::WrapUnique(new HeadlessBrowserContextImpl( | 336 return base::WrapUnique( |
| 254 std::move(protocol_handlers_), browser_->options())); | 337 new HeadlessBrowserContextImpl(browser_, std::move(*options_))); |
| 255 } | 338 } |
| 256 | 339 |
| 257 HeadlessBrowserContext::Builder::MojoBindings::MojoBindings() {} | 340 HeadlessBrowserContext::Builder::MojoBindings::MojoBindings() {} |
| 258 | 341 |
| 259 HeadlessBrowserContext::Builder::MojoBindings::MojoBindings( | 342 HeadlessBrowserContext::Builder::MojoBindings::MojoBindings( |
| 260 const std::string& mojom_name, | 343 const std::string& mojom_name, |
| 261 const std::string& js_bindings) | 344 const std::string& js_bindings) |
| 262 : mojom_name(mojom_name), js_bindings(js_bindings) {} | 345 : mojom_name(mojom_name), js_bindings(js_bindings) {} |
| 263 | 346 |
| 264 HeadlessBrowserContext::Builder::MojoBindings::~MojoBindings() {} | 347 HeadlessBrowserContext::Builder::MojoBindings::~MojoBindings() {} |
| 265 | 348 |
| 266 } // namespace headless | 349 } // namespace headless |
| OLD | NEW |