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
26class HttpBridgeTest;
27
28namespace base {
29class MessageLoop;
30}
31
32namespace net {
33class HttpResponseHeaders;
34class HttpUserAgentSettings;
35class URLFetcher;
36}
37
38namespace 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.
45typedef 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.
55class 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
231class 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