Home | History | Annotate | Download | only in public
      1 // Copyright 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 #ifndef SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_
      6 #define SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/compiler_specific.h"
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/synchronization/lock.h"
     15 #include "base/synchronization/waitable_event.h"
     16 #include "net/url_request/url_fetcher_delegate.h"
     17 #include "net/url_request/url_request_context.h"
     18 #include "net/url_request/url_request_context_getter.h"
     19 #include "sync/base/sync_export.h"
     20 #include "sync/internal_api/public/base/cancelation_observer.h"
     21 #include "sync/internal_api/public/http_post_provider_factory.h"
     22 #include "sync/internal_api/public/http_post_provider_interface.h"
     23 #include "sync/internal_api/public/network_time_update_callback.h"
     24 #include "url/gurl.h"
     25 
     26 class HttpBridgeTest;
     27 
     28 namespace base {
     29 class MessageLoop;
     30 }
     31 
     32 namespace net {
     33 class HttpResponseHeaders;
     34 class HttpUserAgentSettings;
     35 class URLFetcher;
     36 class URLRequestJobFactory;
     37 }
     38 
     39 namespace syncer {
     40 
     41 class CancelationSignal;
     42 
     43 // A bridge between the syncer and Chromium HTTP layers.
     44 // Provides a way for the sync backend to use Chromium directly for HTTP
     45 // requests rather than depending on a third party provider (e.g libcurl).
     46 // This is a one-time use bridge. Create one for each request you want to make.
     47 // It is RefCountedThreadSafe because it can PostTask to the io loop, and thus
     48 // needs to stick around across context switches, etc.
     49 class SYNC_EXPORT_PRIVATE HttpBridge
     50     : public base::RefCountedThreadSafe<HttpBridge>,
     51       public HttpPostProviderInterface,
     52       public net::URLFetcherDelegate {
     53  public:
     54   // A request context used for HTTP requests bridged from the sync backend.
     55   // A bridged RequestContext has a dedicated in-memory cookie store and does
     56   // not use a cache. Thus the same type can be used for incognito mode.
     57   class RequestContext : public net::URLRequestContext {
     58    public:
     59     // |baseline_context| is used to obtain the accept-language
     60     // and proxy service information for bridged requests.
     61     // Typically |baseline_context| should be the net::URLRequestContext of the
     62     // currently active profile.
     63     RequestContext(
     64         net::URLRequestContext* baseline_context,
     65         const scoped_refptr<base::SingleThreadTaskRunner>&
     66             network_task_runner,
     67         const std::string& user_agent);
     68 
     69     // The destructor MUST be called on the IO thread.
     70     virtual ~RequestContext();
     71 
     72    private:
     73     net::URLRequestContext* const baseline_context_;
     74     const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
     75     scoped_ptr<net::HttpUserAgentSettings> http_user_agent_settings_;
     76     scoped_ptr<net::URLRequestJobFactory> job_factory_;
     77 
     78     DISALLOW_COPY_AND_ASSIGN(RequestContext);
     79   };
     80 
     81   // Lazy-getter for RequestContext objects.
     82   class SYNC_EXPORT_PRIVATE RequestContextGetter
     83       : public net::URLRequestContextGetter {
     84    public:
     85     RequestContextGetter(
     86         net::URLRequestContextGetter* baseline_context_getter,
     87         const std::string& user_agent);
     88 
     89     // net::URLRequestContextGetter implementation.
     90     virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE;
     91     virtual scoped_refptr<base::SingleThreadTaskRunner>
     92         GetNetworkTaskRunner() const OVERRIDE;
     93 
     94    protected:
     95     virtual ~RequestContextGetter();
     96 
     97    private:
     98     scoped_refptr<net::URLRequestContextGetter> baseline_context_getter_;
     99     const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
    100     // User agent to apply to the net::URLRequestContext.
    101     const std::string user_agent_;
    102 
    103     // Lazily initialized by GetURLRequestContext().
    104     scoped_ptr<RequestContext> context_;
    105 
    106     DISALLOW_COPY_AND_ASSIGN(RequestContextGetter);
    107   };
    108 
    109   HttpBridge(RequestContextGetter* context,
    110              const NetworkTimeUpdateCallback& network_time_update_callback);
    111 
    112   // HttpPostProvider implementation.
    113   virtual void SetExtraRequestHeaders(const char* headers) OVERRIDE;
    114   virtual void SetURL(const char* url, int port) OVERRIDE;
    115   virtual void SetPostPayload(const char* content_type, int content_length,
    116                               const char* content) OVERRIDE;
    117   virtual bool MakeSynchronousPost(int* error_code,
    118                                    int* response_code) OVERRIDE;
    119   virtual void Abort() OVERRIDE;
    120 
    121   // WARNING: these response content methods are used to extract plain old data
    122   // and not null terminated strings, so you should make sure you have read
    123   // GetResponseContentLength() characters when using GetResponseContent. e.g
    124   // string r(b->GetResponseContent(), b->GetResponseContentLength()).
    125   virtual int GetResponseContentLength() const OVERRIDE;
    126   virtual const char* GetResponseContent() const OVERRIDE;
    127   virtual const std::string GetResponseHeaderValue(
    128       const std::string& name) const OVERRIDE;
    129 
    130   // net::URLFetcherDelegate implementation.
    131   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
    132 
    133   net::URLRequestContextGetter* GetRequestContextGetterForTest() const;
    134 
    135  protected:
    136   friend class base::RefCountedThreadSafe<HttpBridge>;
    137 
    138   virtual ~HttpBridge();
    139 
    140   // Protected virtual so the unit test can override to shunt network requests.
    141   virtual void MakeAsynchronousPost();
    142 
    143  private:
    144   friend class SyncHttpBridgeTest;
    145   friend class ::HttpBridgeTest;
    146 
    147   // Called on the IO loop to issue the network request. The extra level
    148   // of indirection is so that the unit test can override this behavior but we
    149   // still have a function to statically pass to PostTask.
    150   void CallMakeAsynchronousPost() { MakeAsynchronousPost(); }
    151 
    152   // Used to destroy a fetcher when the bridge is Abort()ed, to ensure that
    153   // a reference to |this| is held while flushing any pending fetch completion
    154   // callbacks coming from the IO thread en route to finally destroying the
    155   // fetcher.
    156   void DestroyURLFetcherOnIOThread(net::URLFetcher* fetcher);
    157 
    158   void UpdateNetworkTime();
    159 
    160   // The message loop of the thread we were created on. This is the thread that
    161   // will block on MakeSynchronousPost while the IO thread fetches data from
    162   // the network.
    163   // This should be the main syncer thread (SyncerThread) which is what blocks
    164   // on network IO through curl_easy_perform.
    165   base::MessageLoop* const created_on_loop_;
    166 
    167   // The URL to POST to.
    168   GURL url_for_request_;
    169 
    170   // POST payload information.
    171   std::string content_type_;
    172   std::string request_content_;
    173   std::string extra_headers_;
    174 
    175   // A waitable event we use to provide blocking semantics to
    176   // MakeSynchronousPost. We block created_on_loop_ while the IO loop fetches
    177   // network request.
    178   base::WaitableEvent http_post_completed_;
    179 
    180   struct URLFetchState {
    181     URLFetchState();
    182     ~URLFetchState();
    183     // Our hook into the network layer is a URLFetcher. USED ONLY ON THE IO
    184     // LOOP, so we can block created_on_loop_ while the fetch is in progress.
    185     // NOTE: This is not a scoped_ptr for a reason. It must be deleted on the
    186     // same thread that created it, which isn't the same thread |this| gets
    187     // deleted on. We must manually delete url_poster_ on the IO loop.
    188     net::URLFetcher* url_poster;
    189 
    190     // Start and finish time of request. Set immediately before sending
    191     // request and after receiving response.
    192     base::Time start_time;
    193     base::Time end_time;
    194 
    195     // Used to support 'Abort' functionality.
    196     bool aborted;
    197 
    198     // Cached response data.
    199     bool request_completed;
    200     bool request_succeeded;
    201     int http_response_code;
    202     int error_code;
    203     std::string response_content;
    204     scoped_refptr<net::HttpResponseHeaders> response_headers;
    205   };
    206 
    207   // This lock synchronizes use of state involved in the flow to fetch a URL
    208   // using URLFetcher, including |fetch_state_| and
    209   // |context_getter_for_request_| on any thread, for example, this flow needs
    210   // to be synchronized to gracefully clean up URLFetcher and return
    211   // appropriate values in |error_code|.
    212   mutable base::Lock fetch_state_lock_;
    213   URLFetchState fetch_state_;
    214 
    215   // Gets a customized net::URLRequestContext for bridged requests. See
    216   // RequestContext definition for details.
    217   scoped_refptr<RequestContextGetter> context_getter_for_request_;
    218 
    219   const scoped_refptr<base::SingleThreadTaskRunner> network_task_runner_;
    220 
    221   // Callback for updating network time.
    222   NetworkTimeUpdateCallback network_time_update_callback_;
    223 
    224   DISALLOW_COPY_AND_ASSIGN(HttpBridge);
    225 };
    226 
    227 class SYNC_EXPORT HttpBridgeFactory : public HttpPostProviderFactory,
    228                                       public CancelationObserver {
    229  public:
    230   HttpBridgeFactory(
    231       net::URLRequestContextGetter* baseline_context_getter,
    232       const NetworkTimeUpdateCallback& network_time_update_callback,
    233       CancelationSignal* cancelation_signal);
    234   virtual ~HttpBridgeFactory();
    235 
    236   // HttpPostProviderFactory:
    237   virtual void Init(const std::string& user_agent) OVERRIDE;
    238   virtual HttpPostProviderInterface* Create() OVERRIDE;
    239   virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE;
    240 
    241   // CancelationObserver implementation:
    242   virtual void OnSignalReceived() OVERRIDE;
    243 
    244  private:
    245   // Protects |request_context_getter_| and |baseline_request_context_getter_|.
    246   base::Lock context_getter_lock_;
    247 
    248   // This request context is the starting point for the request_context_getter_
    249   // that we eventually use to make requests.  During shutdown we must drop all
    250   // references to it before the ProfileSyncService's Shutdown() call is
    251   // complete.
    252   scoped_refptr<net::URLRequestContextGetter> baseline_request_context_getter_;
    253 
    254   // This request context is built on top of the baseline context and shares
    255   // common components. Takes a reference to the
    256   // baseline_request_context_getter_.  It's mostly used on sync thread when
    257   // creating connection but is released as soon as possible during shutdown.
    258   // Protected by |context_getter_lock_|.
    259   scoped_refptr<HttpBridge::RequestContextGetter> request_context_getter_;
    260 
    261   NetworkTimeUpdateCallback network_time_update_callback_;
    262 
    263   CancelationSignal* const cancelation_signal_;
    264 
    265   DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory);
    266 };
    267 
    268 }  //  namespace syncer
    269 
    270 #endif  // SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_
    271