diff --git a/atom.gyp b/atom.gyp index 4d0bab4a5aa0..c9aff86aa4a2 100644 --- a/atom.gyp +++ b/atom.gyp @@ -100,6 +100,8 @@ 'browser/native_window_observer.h', 'browser/net/adapter_request_job.cc', 'browser/net/adapter_request_job.h', + 'browser/net/atom_url_request_context_getter.cc', + 'browser/net/atom_url_request_context_getter.h', 'browser/net/atom_url_request_job_factory.cc', 'browser/net/atom_url_request_job_factory.h', 'browser/net/url_request_string_job.cc', diff --git a/browser/api/atom_api_protocol.cc b/browser/api/atom_api_protocol.cc index 498dae4e1f00..5b1919fa6759 100644 --- a/browser/api/atom_api_protocol.cc +++ b/browser/api/atom_api_protocol.cc @@ -7,10 +7,10 @@ #include "base/stl_util.h" #include "browser/atom_browser_context.h" #include "browser/net/adapter_request_job.h" +#include "browser/net/atom_url_request_context_getter.h" #include "browser/net/atom_url_request_job_factory.h" #include "content/public/browser/browser_thread.h" #include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" #include "vendor/node/src/node.h" #include "vendor/node/src/node_internals.h" @@ -55,10 +55,7 @@ v8::Handle ConvertURLRequestToV8Object( // Get the job factory. AtomURLRequestJobFactory* GetRequestJobFactory() { - return static_cast( - const_cast( - static_cast(AtomBrowserContext::Get())-> - GetRequestContext()->GetURLRequestContext()->job_factory())); + return AtomBrowserContext::Get()->url_request_context_getter()->job_factory(); } class CustomProtocolRequestJob : public AdapterRequestJob { diff --git a/browser/atom_browser_client.cc b/browser/atom_browser_client.cc index 2476dd78e163..bdff197d58fc 100644 --- a/browser/atom_browser_client.cc +++ b/browser/atom_browser_client.cc @@ -4,14 +4,9 @@ #include "browser/atom_browser_client.h" +#include "browser/atom_browser_context.h" #include "browser/atom_browser_main_parts.h" -#include "browser/net/atom_url_request_job_factory.h" -#include "content/public/common/url_constants.h" -#include "net/url_request/data_protocol_handler.h" -#include "net/url_request/file_protocol_handler.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_storage.h" -#include "vendor/brightray/browser/url_request_context_getter.h" +#include "browser/net/atom_url_request_context_getter.h" #include "webkit/glue/webpreferences.h" namespace atom { @@ -25,31 +20,8 @@ AtomBrowserClient::~AtomBrowserClient() { net::URLRequestContextGetter* AtomBrowserClient::CreateRequestContext( content::BrowserContext* browser_context, content::ProtocolHandlerMap* protocol_handlers) { - content::ProtocolHandlerMap preset_handlers; - std::swap(preset_handlers, *protocol_handlers); - - // Create our implementaton of job factory. - AtomURLRequestJobFactory* job_factory = new AtomURLRequestJobFactory; - content::ProtocolHandlerMap::iterator it; - for (it = preset_handlers.begin(); it != preset_handlers.end(); ++it) - job_factory->SetProtocolHandler(it->first, it->second.release()); - job_factory->SetProtocolHandler(chrome::kDataScheme, - new net::DataProtocolHandler); - job_factory->SetProtocolHandler(chrome::kFileScheme, - new net::FileProtocolHandler); - - // Go through default procedure. - net::URLRequestContextGetter* request_context_getter = - brightray::BrowserClient::CreateRequestContext(browser_context, - protocol_handlers); - net::URLRequestContext* request_context = - request_context_getter->GetURLRequestContext(); - - // Replace default job factory. - storage_.reset(new net::URLRequestContextStorage(request_context)); - storage_->set_job_factory(job_factory); - - return request_context_getter; + return static_cast(browser_context)-> + CreateRequestContext(protocol_handlers); } void AtomBrowserClient::OverrideWebkitPrefs( diff --git a/browser/atom_browser_client.h b/browser/atom_browser_client.h index 456ea1a2913f..3443f0a707d9 100644 --- a/browser/atom_browser_client.h +++ b/browser/atom_browser_client.h @@ -7,10 +7,6 @@ #include "brightray/browser/browser_client.h" -namespace net { -class URLRequestContextStorage; -} - namespace atom { class AtomBrowserClient : public brightray::BrowserClient { @@ -34,8 +30,6 @@ class AtomBrowserClient : public brightray::BrowserClient { virtual brightray::BrowserMainParts* OverrideCreateBrowserMainParts( const content::MainFunctionParams&) OVERRIDE; - scoped_ptr storage_; - DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient); }; diff --git a/browser/atom_browser_context.cc b/browser/atom_browser_context.cc index 59649b216f3b..e2a80b80b514 100644 --- a/browser/atom_browser_context.cc +++ b/browser/atom_browser_context.cc @@ -5,15 +5,65 @@ #include "browser/atom_browser_context.h" #include "browser/atom_browser_main_parts.h" +#include "browser/net/atom_url_request_context_getter.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/resource_context.h" +#include "vendor/brightray/browser/network_delegate.h" namespace atom { -AtomBrowserContext::AtomBrowserContext() { +using content::BrowserThread; + +class AtomResourceContext : public content::ResourceContext { + public: + AtomResourceContext() : getter_(NULL) {} + + void set_url_request_context_getter(AtomURLRequestContextGetter* getter) { + getter_ = getter; + } + + protected: + virtual net::HostResolver* GetHostResolver() OVERRIDE { + DCHECK(getter_); + return getter_->host_resolver(); + } + + virtual net::URLRequestContext* GetRequestContext() OVERRIDE { + DCHECK(getter_); + return getter_->GetURLRequestContext(); + } + + private: + AtomURLRequestContextGetter* getter_; + + DISALLOW_COPY_AND_ASSIGN(AtomResourceContext); +}; + +AtomBrowserContext::AtomBrowserContext() + : resource_context_(new AtomResourceContext) { } AtomBrowserContext::~AtomBrowserContext() { } +AtomURLRequestContextGetter* AtomBrowserContext::CreateRequestContext( + content::ProtocolHandlerMap* protocol_handlers) { + DCHECK(!url_request_getter_); + url_request_getter_ = new AtomURLRequestContextGetter( + GetPath(), + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO), + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE), + CreateNetworkDelegate().Pass(), + protocol_handlers); + + resource_context_->set_url_request_context_getter(url_request_getter_.get()); + return url_request_getter_.get(); +} + +content::ResourceContext* AtomBrowserContext::GetResourceContext() { + return resource_context_.get(); +} + // static AtomBrowserContext* AtomBrowserContext::Get() { return static_cast( diff --git a/browser/atom_browser_context.h b/browser/atom_browser_context.h index 1a97bc3fd455..45c0322e4db7 100644 --- a/browser/atom_browser_context.h +++ b/browser/atom_browser_context.h @@ -10,14 +10,34 @@ namespace atom { +class AtomResourceContext; +class AtomURLRequestContextGetter; + class AtomBrowserContext : public brightray::BrowserContext { public: AtomBrowserContext(); virtual ~AtomBrowserContext(); + // Returns the browser context singleton. static AtomBrowserContext* Get(); + // Creates or returns the request context. + AtomURLRequestContextGetter* CreateRequestContext( + content::ProtocolHandlerMap*); + + AtomURLRequestContextGetter* url_request_context_getter() const { + DCHECK(url_request_getter_); + return url_request_getter_.get(); + } + + protected: + // content::BrowserContext implementations: + virtual content::ResourceContext* GetResourceContext() OVERRIDE; + private: + scoped_ptr resource_context_; + scoped_refptr url_request_getter_; + DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext); }; diff --git a/browser/net/atom_url_request_context_getter.cc b/browser/net/atom_url_request_context_getter.cc new file mode 100644 index 000000000000..0472905527a0 --- /dev/null +++ b/browser/net/atom_url_request_context_getter.cc @@ -0,0 +1,157 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "browser/net/atom_url_request_context_getter.h" + +#include "base/string_util.h" +#include "base/threading/worker_pool.h" +#include "browser/net/atom_url_request_job_factory.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/cookie_store_factory.h" +#include "content/public/common/url_constants.h" +#include "net/cert/cert_verifier.h" +#include "net/cookies/cookie_monster.h" +#include "net/http/http_auth_handler_factory.h" +#include "net/http/http_cache.h" +#include "net/http/http_server_properties_impl.h" +#include "net/proxy/proxy_service.h" +#include "net/ssl/default_server_bound_cert_store.h" +#include "net/ssl/server_bound_cert_service.h" +#include "net/ssl/ssl_config_service_defaults.h" +#include "net/url_request/data_protocol_handler.h" +#include "net/url_request/file_protocol_handler.h" +#include "net/url_request/static_http_user_agent_settings.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_storage.h" +#include "vendor/brightray/browser/network_delegate.h" + +namespace atom { + +using content::BrowserThread; + +AtomURLRequestContextGetter::AtomURLRequestContextGetter( + const base::FilePath& base_path, + MessageLoop* io_loop, + MessageLoop* file_loop, + scoped_ptr network_delegate, + content::ProtocolHandlerMap* protocol_handlers) + : base_path_(base_path), + io_loop_(io_loop), + file_loop_(file_loop), + job_factory_(NULL), + network_delegate_(network_delegate.Pass()) { + // Must first be created on the UI thread. + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + std::swap(protocol_handlers_, *protocol_handlers); + proxy_config_service_.reset( + net::ProxyService::CreateSystemProxyConfigService( + io_loop_->message_loop_proxy(), + file_loop_)); +} + +AtomURLRequestContextGetter::~AtomURLRequestContextGetter() { +} + +net::URLRequestContext* AtomURLRequestContextGetter::GetURLRequestContext() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); + + if (!url_request_context_.get()) { + url_request_context_.reset(new net::URLRequestContext()); + url_request_context_->set_network_delegate(network_delegate_.get()); + storage_.reset( + new net::URLRequestContextStorage(url_request_context_.get())); + storage_->set_cookie_store(content::CreatePersistentCookieStore( + base_path_.Append(FILE_PATH_LITERAL("Cookies")), + false, + nullptr, + nullptr)); + storage_->set_server_bound_cert_service(new net::ServerBoundCertService( + new net::DefaultServerBoundCertStore(NULL), + base::WorkerPool::GetTaskRunner(true))); + storage_->set_http_user_agent_settings( + new net::StaticHttpUserAgentSettings( + "en-us,en", EmptyString())); + + scoped_ptr host_resolver( + net::HostResolver::CreateDefaultResolver(NULL)); + + storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); + // TODO(jam): use v8 if possible, look at chrome code. + storage_->set_proxy_service( + net::ProxyService::CreateUsingSystemProxyResolver( + proxy_config_service_.release(), + 0, + NULL)); + storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); + storage_->set_http_auth_handler_factory( + net::HttpAuthHandlerFactory::CreateDefault(host_resolver.get())); + storage_->set_http_server_properties(new net::HttpServerPropertiesImpl); + + base::FilePath cache_path = base_path_.Append(FILE_PATH_LITERAL("Cache")); + net::HttpCache::DefaultBackend* main_backend = + new net::HttpCache::DefaultBackend( + net::DISK_CACHE, + net::CACHE_BACKEND_DEFAULT, + cache_path, + 0, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE)); + + net::HttpNetworkSession::Params network_session_params; + network_session_params.cert_verifier = + url_request_context_->cert_verifier(); + network_session_params.server_bound_cert_service = + url_request_context_->server_bound_cert_service(); + network_session_params.proxy_service = + url_request_context_->proxy_service(); + network_session_params.ssl_config_service = + url_request_context_->ssl_config_service(); + network_session_params.http_auth_handler_factory = + url_request_context_->http_auth_handler_factory(); + network_session_params.network_delegate = + url_request_context_->network_delegate(); + network_session_params.http_server_properties = + url_request_context_->http_server_properties(); + network_session_params.ignore_certificate_errors = false; + + // Give |storage_| ownership at the end in case it's |mapped_host_resolver|. + storage_->set_host_resolver(host_resolver.Pass()); + network_session_params.host_resolver = + url_request_context_->host_resolver(); + + net::HttpCache* main_cache = new net::HttpCache( + network_session_params, main_backend); + storage_->set_http_transaction_factory(main_cache); + + DCHECK(!job_factory_); + job_factory_ = new AtomURLRequestJobFactory; + for (content::ProtocolHandlerMap::iterator it = protocol_handlers_.begin(); + it != protocol_handlers_.end(); + ++it) { + bool set_protocol = job_factory_->SetProtocolHandler( + it->first, + it->second.release()); + DCHECK(set_protocol); + } + protocol_handlers_.clear(); + + job_factory_->SetProtocolHandler(chrome::kDataScheme, + new net::DataProtocolHandler); + job_factory_->SetProtocolHandler(chrome::kFileScheme, + new net::FileProtocolHandler); + storage_->set_job_factory(job_factory_); + } + + return url_request_context_.get(); +} + +scoped_refptr + AtomURLRequestContextGetter::GetNetworkTaskRunner() const { + return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); +} + +net::HostResolver* AtomURLRequestContextGetter::host_resolver() { + return url_request_context_->host_resolver(); +} + +} // namespace atom diff --git a/browser/net/atom_url_request_context_getter.h b/browser/net/atom_url_request_context_getter.h new file mode 100644 index 000000000000..51a64d872ed6 --- /dev/null +++ b/browser/net/atom_url_request_context_getter.h @@ -0,0 +1,69 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_ +#define ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_ + +#include "base/files/file_path.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/content_browser_client.h" +#include "net/url_request/url_request_context_getter.h" + +namespace base { +class MessageLoop; +} + +namespace brightray { +class NetworkDelegate; +} + +namespace net { +class HostResolver; +class ProxyConfigService; +class URLRequestContextStorage; +} + +namespace atom { + +class AtomURLRequestJobFactory; + +class AtomURLRequestContextGetter : public net::URLRequestContextGetter { + public: + AtomURLRequestContextGetter( + const base::FilePath& base_path, + base::MessageLoop* io_loop, + base::MessageLoop* file_loop, + scoped_ptr network_delegate, + content::ProtocolHandlerMap* protocol_handlers); + + // net::URLRequestContextGetter implementations: + virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE; + virtual scoped_refptr + GetNetworkTaskRunner() const OVERRIDE; + + net::HostResolver* host_resolver(); + net::URLRequestContextStorage* storage() const { return storage_.get(); } + AtomURLRequestJobFactory* job_factory() const { return job_factory_; } + + protected: + virtual ~AtomURLRequestContextGetter(); + + private: + base::FilePath base_path_; + base::MessageLoop* io_loop_; + base::MessageLoop* file_loop_; + AtomURLRequestJobFactory* job_factory_; + + scoped_ptr proxy_config_service_; + scoped_ptr network_delegate_; + scoped_ptr storage_; + scoped_ptr url_request_context_; + content::ProtocolHandlerMap protocol_handlers_; + + DISALLOW_COPY_AND_ASSIGN(AtomURLRequestContextGetter); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_ATOM_URL_REQUEST_CONTEXT_GETTER_H_