From c21cade7f5b31da2f090df31f3793d2349afac35 Mon Sep 17 00:00:00 2001 From: Stanislas Polu Date: Mon, 1 Dec 2014 15:44:52 -0800 Subject: [PATCH] Request proxying --- src/api/thrust_session_binding.cc | 25 +++- src/browser/session/thrust_session.cc | 17 ++- src/browser/session/thrust_session.h | 7 +- .../session/thrust_session_cookie_store.h | 2 +- .../thrust_session_proxy_config_service.cc | 120 ++++++++++++++++++ .../thrust_session_proxy_config_service.h | 61 +++++++++ src/net/url_request_context_getter.cc | 18 +-- src/net/url_request_context_getter.h | 7 +- thrust_shell.gyp | 2 + 9 files changed, 228 insertions(+), 31 deletions(-) create mode 100644 src/browser/session/thrust_session_proxy_config_service.cc create mode 100644 src/browser/session/thrust_session_proxy_config_service.h diff --git a/src/api/thrust_session_binding.cc b/src/api/thrust_session_binding.cc index 8231db1..f4b2c0a 100644 --- a/src/api/thrust_session_binding.cc +++ b/src/api/thrust_session_binding.cc @@ -9,6 +9,7 @@ #include "content/public/browser/browser_thread.h" #include "src/browser/session/thrust_session.h" +#include "src/browser/session/thrust_session_proxy_config_service.h" namespace { @@ -148,10 +149,7 @@ ThrustSessionBinding::CallLocalMethod( base::DictionaryValue* res = new base::DictionaryValue; LOG(INFO) << "CALL " << method; - if(method.compare("off_the_record") == 0) { - res->SetBoolean("off_the_record", session_->IsOffTheRecord()); - } - else if(method.compare("visitedlink_add") == 0) { + if(method.compare("visitedlink_add") == 0) { std::string url = ""; args->GetString("url", &url); session_->GetVisitedLinkStore()->Add(url); @@ -159,6 +157,25 @@ ThrustSessionBinding::CallLocalMethod( else if(method.compare("visitedlink_clear") == 0) { session_->GetVisitedLinkStore()->Clear(); } + else if(method.compare("proxy_set") == 0) { + std::string rules = ""; + args->GetString("rules", &rules); + ThrustSessionProxyConfigService* proxy_config_service = + session_->GetProxyConfigService(); + if(proxy_config_service != NULL) { + proxy_config_service->SetProxyRules(rules); + } + } + else if(method.compare("proxy_clear") == 0) { + ThrustSessionProxyConfigService* proxy_config_service = + session_->GetProxyConfigService(); + if(proxy_config_service != NULL) { + proxy_config_service->ClearProxyRules(); + } + } + else if(method.compare("is_off_the_record") == 0) { + res->SetBoolean("off_the_record", session_->IsOffTheRecord()); + } else { err = "exo_session_binding:method_not_found"; } diff --git a/src/browser/session/thrust_session.cc b/src/browser/session/thrust_session.cc index b9c09ce..706c3f2 100644 --- a/src/browser/session/thrust_session.cc +++ b/src/browser/session/thrust_session.cc @@ -22,6 +22,7 @@ #include "src/browser/browser_main_parts.h" #include "src/browser/browser_client.h" #include "src/browser/web_view/web_view_guest.h" +#include "src/browser/session/thrust_session_proxy_config_service.h" using namespace content; @@ -94,6 +95,10 @@ ThrustSession::ThrustSession( visitedlink_store_->Init(); + /* It will be owned by the URLRequestContextGetter (proxy service owns */ + /* a scoped_ptr on it) as soon as it is initiated. */ + proxy_config_service_ = new ThrustSessionProxyConfigService(this); + ThrustShellBrowserClient::Get()->RegisterThrustSession(this); LOG(INFO) << "ThrustSession Constructor " << this; } @@ -101,9 +106,11 @@ ThrustSession::ThrustSession( ThrustSession::~ThrustSession() { - /* If we're here that means that ou JS wrapper has been reclaimed */ LOG(INFO) << "ThrustSession Destructor " << this; + /* NOTE: We don't delete the proxy_config_service_ as it is owned by the */ + /* UrlRequestContextGetter as soon as it is initialized */ + /* The ResourceContext is created on the UI thread but live son the IO */ /* thread, so it must be deleted there. */ if(resource_context_) { @@ -165,8 +172,6 @@ ThrustSession::CreateRequestContext( this, ignore_certificate_errors_, GetPath(), - BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO), - BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE), protocol_handlers, request_interceptors.Pass(), ThrustShellMainParts::Get()->net_log()); @@ -200,6 +205,12 @@ ThrustSession::GetVisitedLinkStore() return visitedlink_store_.get(); } +ThrustSessionProxyConfigService* +ThrustSession::GetProxyConfigService() +{ + return proxy_config_service_; +} + /******************************************************************************/ /* BROWSER_PLUGIN_GUEST_MANAGER */ /******************************************************************************/ diff --git a/src/browser/session/thrust_session.h b/src/browser/session/thrust_session.h index 5ccfd83..f1f7dae 100644 --- a/src/browser/session/thrust_session.h +++ b/src/browser/session/thrust_session.h @@ -25,6 +25,7 @@ class ResourceContext; class ThrustShellURLRequestContextGetter; class ThrustShellDownloadManagerDelegate; class ThrustSessionBinding; +class ThrustSessionProxyConfigService; // ### ThrustSession // @@ -62,6 +63,7 @@ class ThrustSession : public brightray::BrowserContext, ThrustSessionCookieStore* GetCookieStore(); ThrustSessionVisitedLinkStore* GetVisitedLinkStore(); + ThrustSessionProxyConfigService* GetProxyConfigService(); /****************************************************************************/ /* REQUEST CONTEXT GETTER HELPERS */ @@ -114,8 +116,6 @@ class ThrustSession : public brightray::BrowserContext, int GetNextInstanceID(); - - private: class ExoResourceContext; @@ -133,6 +133,7 @@ class ThrustSession : public brightray::BrowserContext, scoped_refptr url_request_getter_; scoped_refptr cookie_store_; scoped_refptr visitedlink_store_; + ThrustSessionProxyConfigService* proxy_config_service_; std::map guest_web_contents_; int current_instance_id_; @@ -140,6 +141,8 @@ class ThrustSession : public brightray::BrowserContext, friend class ThrustSessionCookieStore; friend class WebViewGuest; friend class GuestWebContentsObserver; + friend class ThrustSessionProxyConfigService; + friend class ThrustShellURLRequestContextGetter; DISALLOW_COPY_AND_ASSIGN(ThrustSession); }; diff --git a/src/browser/session/thrust_session_cookie_store.h b/src/browser/session/thrust_session_cookie_store.h index e83411e..e597880 100644 --- a/src/browser/session/thrust_session_cookie_store.h +++ b/src/browser/session/thrust_session_cookie_store.h @@ -32,7 +32,7 @@ typedef net::CookieMonster::PersistentCookieStore::LoadedCallback ThrustSessionCookieStore(ThrustSession* parent, bool dummy = false); /****************************************************************************/ - /* COOKIE MONSTER PERSISTENT STORE IMPLEMENTATION */ + /* COOKIE MONSTER PERSISTENT STORE IMPLEMENTATION */ /****************************************************************************/ virtual void Load(const LoadedCallback& loaded_callback) OVERRIDE; diff --git a/src/browser/session/thrust_session_proxy_config_service.cc b/src/browser/session/thrust_session_proxy_config_service.cc new file mode 100644 index 0000000..204c595 --- /dev/null +++ b/src/browser/session/thrust_session_proxy_config_service.cc @@ -0,0 +1,120 @@ +// Copyright (c) 2014 Stanislas Polu. +// See the LICENSE file. + +#include "src/browser/session/thrust_session_proxy_config_service.h" + +#include "net/proxy/proxy_service.h" +#include "net/proxy/proxy_config_service_fixed.h" +#include "content/public/browser/browser_thread.h" + +#include "src/browser/session/thrust_session.h" + +using namespace content; + +namespace thrust_shell { + +ThrustSessionProxyConfigService::ThrustSessionProxyConfigService( + ThrustSession* parent) +: parent_(parent) +{ + LOG(INFO) << "ThrustSesionProxyConfigService Constructor: " << this; + + system_service_.reset( + net::ProxyService::CreateSystemProxyConfigService( + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO) + ->message_loop_proxy().get(), + BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE))); + fixed_service_.reset(); +} + +ThrustSessionProxyConfigService::~ThrustSessionProxyConfigService() +{ + /* We nullify the proxy service in parent to prevent erroneous access */ + /* after it gets reclaimed. */ + parent_->proxy_config_service_ = NULL; + + LOG(INFO) << "ThrustSesionProxyConfigService Destructor: " << this; +} + +/******************************************************************************/ +/* PUBLIC API */ +/******************************************************************************/ +void +ThrustSessionProxyConfigService::SetProxyRules( + std::string& proxy_string) +{ + net::ProxyConfig proxy_config; + proxy_config.proxy_rules().ParseFromString(proxy_string); + fixed_service_.reset(new net::ProxyConfigServiceFixed(proxy_config)); + + LOG(INFO) << "ThrustSesionProxyConfigService SetProxyRules: " << proxy_string; + + if(observers_.might_have_observers()) { + ObserverList::Iterator it(observers_); + Observer* obs; + while((obs = it.GetNext()) != NULL) { + fixed_service_->AddObserver(obs); + } + } + FOR_EACH_OBSERVER(Observer, observers_, + OnProxyConfigChanged(proxy_config, CONFIG_VALID)); +} + +void +ThrustSessionProxyConfigService::ClearProxyRules() +{ + fixed_service_.reset(); + + net::ProxyConfig proxy_config; + net::ProxyConfigService::ConfigAvailability avail = + this->GetLatestProxyConfig(&proxy_config); + + FOR_EACH_OBSERVER(Observer, observers_, + OnProxyConfigChanged(proxy_config, avail)); +} + +/******************************************************************************/ +/* PROXY CONFIG SERVICE IMPLEMENTATION */ +/******************************************************************************/ +void +ThrustSessionProxyConfigService::AddObserver( + Observer* observer) +{ + observers_.AddObserver(observer); + if(fixed_service_.get()) { + fixed_service_->AddObserver(observer); + } + system_service_->AddObserver(observer); +} + +void +ThrustSessionProxyConfigService::RemoveObserver( + Observer* observer) +{ + observers_.RemoveObserver(observer); + if(fixed_service_.get()) { + fixed_service_->RemoveObserver(observer); + } + system_service_->RemoveObserver(observer); +} + +net::ProxyConfigService::ConfigAvailability +ThrustSessionProxyConfigService::GetLatestProxyConfig( + net::ProxyConfig* config) +{ + if(fixed_service_.get()) { + return fixed_service_->GetLatestProxyConfig(config); + } + return system_service_->GetLatestProxyConfig(config); +} + +void +ThrustSessionProxyConfigService::OnLazyPoll() +{ + if(fixed_service_.get()) { + fixed_service_->OnLazyPoll(); + } + system_service_->OnLazyPoll(); +} + +} // namespace thrust_shell diff --git a/src/browser/session/thrust_session_proxy_config_service.h b/src/browser/session/thrust_session_proxy_config_service.h new file mode 100644 index 0000000..0cc804b --- /dev/null +++ b/src/browser/session/thrust_session_proxy_config_service.h @@ -0,0 +1,61 @@ +// Copyright (c) 2014 Stanislas Polu. +// See the LICENSE file. + +#ifndef THRUST_SHELL_BROWSER_SESSION_THRUST_SESSION_PROXY_CONFIG_SERVICE_H_ +#define THRUST_SHELL_BROWSER_SESSION_THRUST_SESSION_PROXY_CONFIG_SERVICE_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" +#include "net/proxy/proxy_config_service.h" + +namespace thrust_shell { + +class ThrustSession; + +// ### ThrustSessionProxyConfigService +// +// The ThrustSessionProxyConfigService is the glue between the system proxy +// service and custom proxy rules set by the user for a given thrust_session. +// This proxy service is passed as argument to the +// ThrustShellURLRequestContextGetter to manage all proxy information. +// +// The ProxyConfigService expose two simple methods SetProxyString and +// ClearProxyString to set or clear (return to system settings) the proxy rules +// for all requests made for this session +class ThrustSessionProxyConfigService : public net::ProxyConfigService { +public: + // ### THrustSessionProxyConfigService + ThrustSessionProxyConfigService(ThrustSession* parent); + ~ThrustSessionProxyConfigService(); + + /****************************************************************************/ + /* PUBLIC API */ + /****************************************************************************/ + void SetProxyRules(std::string& rules); + void ClearProxyRules(); + + /****************************************************************************/ + /* PROXY CONFIG SERVICE IMPLEMENTATION */ + /****************************************************************************/ + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + + virtual ConfigAvailability GetLatestProxyConfig( + net::ProxyConfig* config) OVERRIDE; + virtual void OnLazyPoll() OVERRIDE; + +private: + ThrustSession* parent_; + + ObserverList observers_; + scoped_ptr system_service_; + scoped_ptr fixed_service_; + + friend class ThrustSession; + + DISALLOW_COPY_AND_ASSIGN(ThrustSessionProxyConfigService); +}; + +} // namespace thrust_shell + +#endif // THRUST_SHELL_BROWSER_SESSION_THRUST_SESSION_PROXY_CONFIG_SERVICE_H_ diff --git a/src/net/url_request_context_getter.cc b/src/net/url_request_context_getter.cc index 617d00f..57b7701 100644 --- a/src/net/url_request_context_getter.cc +++ b/src/net/url_request_context_getter.cc @@ -67,29 +67,18 @@ ThrustShellURLRequestContextGetter::ThrustShellURLRequestContextGetter( ThrustSession* parent, bool ignore_certificate_errors, const base::FilePath& base_path, - base::MessageLoop* io_loop, - base::MessageLoop* file_loop, ProtocolHandlerMap* protocol_handlers, URLRequestInterceptorScopedVector request_interceptors, net::NetLog* net_log) : parent_(parent), ignore_certificate_errors_(ignore_certificate_errors), base_path_(base_path), - io_loop_(io_loop), - file_loop_(file_loop), net_log_(net_log), request_interceptors_(request_interceptors.Pass()) { // Must first be created on the UI thread. DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); std::swap(protocol_handlers_, *protocol_handlers); - - // We must create the proxy config service on the UI loop on Linux because it - // must synchronously run on the glib message loop. This will be passed to - // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). - proxy_config_service_.reset( - net::ProxyService::CreateSystemProxyConfigService( - io_loop_->message_loop_proxy().get(), file_loop_)); } ThrustShellURLRequestContextGetter::~ThrustShellURLRequestContextGetter() @@ -137,11 +126,10 @@ ThrustShellURLRequestContextGetter::GetURLRequestContext() storage_->set_cert_verifier(net::CertVerifier::CreateDefault()); storage_->set_transport_security_state(new net::TransportSecurityState); - /* TODO(spolu): use v8 if possible, look at chrome code. */ + storage_->set_proxy_service( - net::ProxyService::CreateUsingSystemProxyResolver( - proxy_config_service_.release(), - 0, + net::ProxyService::CreateWithoutProxyResolver( + (net::ProxyConfigService*)parent_->proxy_config_service_, url_request_context_->net_log())); storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults); diff --git a/src/net/url_request_context_getter.h b/src/net/url_request_context_getter.h index 205cd39..0ce733c 100644 --- a/src/net/url_request_context_getter.h +++ b/src/net/url_request_context_getter.h @@ -36,8 +36,6 @@ class ThrustShellURLRequestContextGetter : public net::URLRequestContextGetter { ThrustSession* parent, bool ignore_certificate_errors, const base::FilePath& base_path, - base::MessageLoop* io_loop, - base::MessageLoop* file_loop, content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors, net::NetLog* net_log); @@ -53,14 +51,11 @@ class ThrustShellURLRequestContextGetter : public net::URLRequestContextGetter { virtual ~ThrustShellURLRequestContextGetter(); private: - ThrustSession* parent_; + ThrustSession* parent_; bool ignore_certificate_errors_; base::FilePath base_path_; - base::MessageLoop* io_loop_; - base::MessageLoop* file_loop_; net::NetLog* net_log_; - scoped_ptr proxy_config_service_; scoped_ptr network_delegate_; scoped_ptr storage_; scoped_ptr url_request_context_; diff --git a/thrust_shell.gyp b/thrust_shell.gyp index 98eaa1e..9121535 100644 --- a/thrust_shell.gyp +++ b/thrust_shell.gyp @@ -53,6 +53,8 @@ 'src/browser/session/thrust_session_cookie_store.cc', 'src/browser/session/thrust_session_visitedlink_store.h', 'src/browser/session/thrust_session_visitedlink_store.cc', + 'src/browser/session/thrust_session_proxy_config_service.h', + 'src/browser/session/thrust_session_proxy_config_service.cc', 'src/browser/thrust_window.h', 'src/browser/thrust_window.cc', 'src/browser/thrust_window_views.cc',