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