| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_ |
| #define SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_ |
| |
| #include <string> |
| |
| #include "base/basictypes.h" |
| #include "base/callback.h" |
| #include "base/compiler_specific.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/synchronization/lock.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "net/base/network_time_notifier.h" |
| #include "net/url_request/url_fetcher_delegate.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/url_request/url_request_context_getter.h" |
| #include "sync/base/sync_export.h" |
| #include "sync/internal_api/public/base/cancelation_observer.h" |
| #include "sync/internal_api/public/http_post_provider_factory.h" |
| #include "sync/internal_api/public/http_post_provider_interface.h" |
| #include "url/gurl.h" |
| |
| class HttpBridgeTest; |
| |
| namespace base { |
| class MessageLoop; |
| } |
| |
| namespace net { |
| class HttpResponseHeaders; |
| class HttpUserAgentSettings; |
| class URLFetcher; |
| } |
| |
| namespace syncer { |
| |
| class CancelationSignal; |
| |
| // Callback for updating the network time. |
| // Params: |
| // const base::Time& network_time - the new network time. |
| // const base::TimeDelta& resolution - how precise the reading is. |
| // const base::TimeDelta& latency - the http request's latency. |
| typedef base::Callback<void(const base::Time&, |
| const base::TimeDelta&, |
| const base::TimeDelta&)> NetworkTimeUpdateCallback; |
| |
| // A bridge between the syncer and Chromium HTTP layers. |
| // Provides a way for the sync backend to use Chromium directly for HTTP |
| // requests rather than depending on a third party provider (e.g libcurl). |
| // This is a one-time use bridge. Create one for each request you want to make. |
| // It is RefCountedThreadSafe because it can PostTask to the io loop, and thus |
| // needs to stick around across context switches, etc. |
| class SYNC_EXPORT_PRIVATE HttpBridge |
| : public base::RefCountedThreadSafe<HttpBridge>, |
| public HttpPostProviderInterface, |
| public net::URLFetcherDelegate { |
| public: |
| // A request context used for HTTP requests bridged from the sync backend. |
| // A bridged RequestContext has a dedicated in-memory cookie store and does |
| // not use a cache. Thus the same type can be used for incognito mode. |
| class RequestContext : public net::URLRequestContext { |
| public: |
| // |baseline_context| is used to obtain the accept-language |
| // and proxy service information for bridged requests. |
| // Typically |baseline_context| should be the net::URLRequestContext of the |
| // currently active profile. |
| RequestContext( |
| net::URLRequestContext* baseline_context, |
| const scoped_refptr<base::SingleThreadTaskRunner>& |
| network_task_runner, |
| const std::string& user_agent); |
| |
| // The destructor MUST be called on the IO thread. |
| virtual ~RequestContext(); |
| |
| private: |
| net::URLRequestContext* const baseline_context_; |
| const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; |
| scoped_ptr<net::HttpUserAgentSettings> http_user_agent_settings_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RequestContext); |
| }; |
| |
| // Lazy-getter for RequestContext objects. |
| class SYNC_EXPORT_PRIVATE RequestContextGetter |
| : public net::URLRequestContextGetter { |
| public: |
| RequestContextGetter( |
| net::URLRequestContextGetter* baseline_context_getter, |
| const std::string& user_agent); |
| |
| // net::URLRequestContextGetter implementation. |
| virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE; |
| virtual scoped_refptr<base::SingleThreadTaskRunner> |
| GetNetworkTaskRunner() const OVERRIDE; |
| |
| protected: |
| virtual ~RequestContextGetter(); |
| |
| private: |
| scoped_refptr<net::URLRequestContextGetter> baseline_context_getter_; |
| const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; |
| // User agent to apply to the net::URLRequestContext. |
| const std::string user_agent_; |
| |
| // Lazily initialized by GetURLRequestContext(). |
| scoped_ptr<RequestContext> context_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RequestContextGetter); |
| }; |
| |
| HttpBridge(RequestContextGetter* context, |
| const NetworkTimeUpdateCallback& network_time_update_callback); |
| |
| // HttpPostProvider implementation. |
| virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE; |
| virtual void SetURL(const char* url, int port) OVERRIDE; |
| virtual void SetPostPayload(const char* content_type, int content_length, |
| const char* content) OVERRIDE; |
| virtual bool MakeSynchronousPost(int* error_code, |
| int* response_code) OVERRIDE; |
| virtual void Abort() OVERRIDE; |
| |
| // WARNING: these response content methods are used to extract plain old data |
| // and not null terminated strings, so you should make sure you have read |
| // GetResponseContentLength() characters when using GetResponseContent. e.g |
| // string r(b->GetResponseContent(), b->GetResponseContentLength()). |
| virtual int GetResponseContentLength() const OVERRIDE; |
| virtual const char* GetResponseContent() const OVERRIDE; |
| virtual const std::string GetResponseHeaderValue( |
| const std::string& name) const OVERRIDE; |
| |
| // net::URLFetcherDelegate implementation. |
| virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
| |
| net::URLRequestContextGetter* GetRequestContextGetterForTest() const; |
| |
| protected: |
| friend class base::RefCountedThreadSafe<HttpBridge>; |
| |
| virtual ~HttpBridge(); |
| |
| // Protected virtual so the unit test can override to shunt network requests. |
| virtual void MakeAsynchronousPost(); |
| |
| private: |
| friend class SyncHttpBridgeTest; |
| friend class ::HttpBridgeTest; |
| |
| // Called on the IO loop to issue the network request. The extra level |
| // of indirection is so that the unit test can override this behavior but we |
| // still have a function to statically pass to PostTask. |
| void CallMakeAsynchronousPost() { MakeAsynchronousPost(); } |
| |
| // Used to destroy a fetcher when the bridge is Abort()ed, to ensure that |
| // a reference to |this| is held while flushing any pending fetch completion |
| // callbacks coming from the IO thread en route to finally destroying the |
| // fetcher. |
| void DestroyURLFetcherOnIOThread(net::URLFetcher* fetcher); |
| |
| void UpdateNetworkTime(); |
| |
| // The message loop of the thread we were created on. This is the thread that |
| // will block on MakeSynchronousPost while the IO thread fetches data from |
| // the network. |
| // This should be the main syncer thread (SyncerThread) which is what blocks |
| // on network IO through curl_easy_perform. |
| base::MessageLoop* const created_on_loop_; |
| |
| // The URL to POST to. |
| GURL url_for_request_; |
| |
| // POST payload information. |
| std::string content_type_; |
| std::string request_content_; |
| std::string extra_headers_; |
| |
| // A waitable event we use to provide blocking semantics to |
| // MakeSynchronousPost. We block created_on_loop_ while the IO loop fetches |
| // network request. |
| base::WaitableEvent http_post_completed_; |
| |
| struct URLFetchState { |
| URLFetchState(); |
| ~URLFetchState(); |
| // Our hook into the network layer is a URLFetcher. USED ONLY ON THE IO |
| // LOOP, so we can block created_on_loop_ while the fetch is in progress. |
| // NOTE: This is not a scoped_ptr for a reason. It must be deleted on the |
| // same thread that created it, which isn't the same thread |this| gets |
| // deleted on. We must manually delete url_poster_ on the IO loop. |
| net::URLFetcher* url_poster; |
| |
| // Start and finish time of request. Set immediately before sending |
| // request and after receiving response. |
| base::Time start_time; |
| base::Time end_time; |
| |
| // Used to support 'Abort' functionality. |
| bool aborted; |
| |
| // Cached response data. |
| bool request_completed; |
| bool request_succeeded; |
| int http_response_code; |
| int error_code; |
| std::string response_content; |
| scoped_refptr<net::HttpResponseHeaders> response_headers; |
| }; |
| |
| // This lock synchronizes use of state involved in the flow to fetch a URL |
| // using URLFetcher, including |fetch_state_| and |
| // |context_getter_for_request_| on any thread, for example, this flow needs |
| // to be synchronized to gracefully clean up URLFetcher and return |
| // appropriate values in |error_code|. |
| mutable base::Lock fetch_state_lock_; |
| URLFetchState fetch_state_; |
| |
| // Gets a customized net::URLRequestContext for bridged requests. See |
| // RequestContext definition for details. |
| scoped_refptr<RequestContextGetter> context_getter_for_request_; |
| |
| const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_; |
| |
| // Callback for updating network time. |
| NetworkTimeUpdateCallback network_time_update_callback_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HttpBridge); |
| }; |
| |
| class SYNC_EXPORT HttpBridgeFactory : public HttpPostProviderFactory, |
| public CancelationObserver { |
| public: |
| HttpBridgeFactory( |
| net::URLRequestContextGetter* baseline_context_getter, |
| const NetworkTimeUpdateCallback& network_time_update_callback, |
| CancelationSignal* cancelation_signal); |
| virtual ~HttpBridgeFactory(); |
| |
| // HttpPostProviderFactory: |
| virtual void Init(const std::string& user_agent) OVERRIDE; |
| virtual HttpPostProviderInterface* Create() OVERRIDE; |
| virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE; |
| |
| // CancelationObserver implementation: |
| virtual void OnSignalReceived() OVERRIDE; |
| |
| private: |
| // Protects |request_context_getter_| and |baseline_request_context_getter_|. |
| base::Lock context_getter_lock_; |
| |
| // This request context is the starting point for the request_context_getter_ |
| // that we eventually use to make requests. During shutdown we must drop all |
| // references to it before the ProfileSyncService's Shutdown() call is |
| // complete. |
| scoped_refptr<net::URLRequestContextGetter> baseline_request_context_getter_; |
| |
| // This request context is built on top of the baseline context and shares |
| // common components. Takes a reference to the |
| // baseline_request_context_getter_. It's mostly used on sync thread when |
| // creating connection but is released as soon as possible during shutdown. |
| // Protected by |context_getter_lock_|. |
| scoped_refptr<HttpBridge::RequestContextGetter> request_context_getter_; |
| |
| NetworkTimeUpdateCallback network_time_update_callback_; |
| |
| CancelationSignal* const cancelation_signal_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory); |
| }; |
| |
| } // namespace syncer |
| |
| #endif // SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_ |