• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 CHROME_BROWSER_SYNC_GLUE_HTTP_BRIDGE_H_
6 #define CHROME_BROWSER_SYNC_GLUE_HTTP_BRIDGE_H_
7 #pragma once
8 
9 #include <string>
10 
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/synchronization/lock.h"
15 #include "base/synchronization/waitable_event.h"
16 #include "chrome/browser/sync/engine/http_post_provider_factory.h"
17 #include "chrome/browser/sync/engine/http_post_provider_interface.h"
18 #include "chrome/browser/sync/engine/syncapi.h"
19 #include "chrome/common/net/url_fetcher.h"
20 #include "googleurl/src/gurl.h"
21 #include "net/url_request/url_request_context.h"
22 #include "net/url_request/url_request_context_getter.h"
23 #include "testing/gtest/include/gtest/gtest_prod.h"
24 
25 class MessageLoop;
26 class HttpBridgeTest;
27 
28 namespace browser_sync {
29 
30 // A bridge between the syncer and Chromium HTTP layers.
31 // Provides a way for the sync backend to use Chromium directly for HTTP
32 // requests rather than depending on a third party provider (e.g libcurl).
33 // This is a one-time use bridge. Create one for each request you want to make.
34 // It is RefCountedThreadSafe because it can PostTask to the io loop, and thus
35 // needs to stick around across context switches, etc.
36 class HttpBridge : public base::RefCountedThreadSafe<HttpBridge>,
37                    public sync_api::HttpPostProviderInterface,
38                    public URLFetcher::Delegate {
39  public:
40   // A request context used for HTTP requests bridged from the sync backend.
41   // A bridged RequestContext has a dedicated in-memory cookie store and does
42   // not use a cache. Thus the same type can be used for incognito mode.
43   class RequestContext : public net::URLRequestContext {
44    public:
45     // |baseline_context| is used to obtain the accept-language,
46     // accept-charsets, and proxy service information for bridged requests.
47     // Typically |baseline_context| should be the net::URLRequestContext of the
48     // currently active profile.
49     explicit RequestContext(net::URLRequestContext* baseline_context);
50 
51     // Set the user agent for requests using this context. The default is
52     // the browser's UA string.
set_user_agent(const std::string & ua)53     void set_user_agent(const std::string& ua) { user_agent_ = ua; }
54 
GetUserAgent(const GURL & url)55     virtual const std::string& GetUserAgent(const GURL& url) const {
56       // If the user agent is set explicitly return that, otherwise call the
57       // base class method to return default value.
58       return user_agent_.empty() ?
59           net::URLRequestContext::GetUserAgent(url) : user_agent_;
60     }
61 
62    private:
63     // The destructor MUST be called on the IO thread.
64     ~RequestContext();
65 
66     std::string user_agent_;
67     net::URLRequestContext* baseline_context_;
68 
69     DISALLOW_COPY_AND_ASSIGN(RequestContext);
70   };
71 
72   // Lazy-getter for RequestContext objects.
73   class RequestContextGetter : public net::URLRequestContextGetter {
74    public:
75     explicit RequestContextGetter(
76         net::URLRequestContextGetter* baseline_context_getter);
77 
set_user_agent(const std::string & ua)78     void set_user_agent(const std::string& ua) { user_agent_ = ua; }
is_user_agent_set()79     bool is_user_agent_set() const { return !user_agent_.empty(); }
80 
81     // net::URLRequestContextGetter implementation.
82     virtual net::URLRequestContext* GetURLRequestContext();
83     virtual scoped_refptr<base::MessageLoopProxy> GetIOMessageLoopProxy() const;
84 
85    private:
~RequestContextGetter()86     ~RequestContextGetter() {}
87 
88     // User agent to apply to the net::URLRequestContext.
89     std::string user_agent_;
90 
91     scoped_refptr<net::URLRequestContextGetter> baseline_context_getter_;
92 
93     // Lazily initialized by GetURLRequestContext().
94     scoped_refptr<RequestContext> context_;
95 
96     DISALLOW_COPY_AND_ASSIGN(RequestContextGetter);
97   };
98 
99   explicit HttpBridge(RequestContextGetter* context);
100 
101   // sync_api::HttpPostProvider implementation.
102   virtual void SetUserAgent(const char* user_agent);
103   virtual void SetExtraRequestHeaders(const char* headers);
104   virtual void SetURL(const char* url, int port);
105   virtual void SetPostPayload(const char* content_type, int content_length,
106                               const char* content);
107   virtual bool MakeSynchronousPost(int* os_error_code, int* response_code);
108   virtual void Abort();
109 
110   // WARNING: these response content methods are used to extract plain old data
111   // and not null terminated strings, so you should make sure you have read
112   // GetResponseContentLength() characters when using GetResponseContent. e.g
113   // string r(b->GetResponseContent(), b->GetResponseContentLength()).
114   virtual int GetResponseContentLength() const;
115   virtual const char* GetResponseContent() const;
116   virtual const std::string GetResponseHeaderValue(
117       const std::string& name) const;
118 
119   // URLFetcher::Delegate implementation.
120   virtual void OnURLFetchComplete(const URLFetcher* source,
121                                   const GURL& url,
122                                   const net::URLRequestStatus& status,
123                                   int response_code,
124                                   const ResponseCookies& cookies,
125                                   const std::string& data);
126 
127 #if defined(UNIT_TEST)
GetRequestContextGetter()128   net::URLRequestContextGetter* GetRequestContextGetter() const {
129     return context_getter_for_request_;
130   }
131 #endif
132 
133  protected:
134   friend class base::RefCountedThreadSafe<HttpBridge>;
135 
136   virtual ~HttpBridge();
137 
138   // Protected virtual so the unit test can override to shunt network requests.
139   virtual void MakeAsynchronousPost();
140 
141  private:
142   friend class ::HttpBridgeTest;
143 
144   // Called on the IO loop to issue the network request. The extra level
145   // of indirection is so that the unit test can override this behavior but we
146   // still have a function to statically pass to PostTask.
CallMakeAsynchronousPost()147   void CallMakeAsynchronousPost() { MakeAsynchronousPost(); }
148 
149   // Gets a customized net::URLRequestContext for bridged requests. See
150   // RequestContext definition for details.
151   scoped_refptr<RequestContextGetter> context_getter_for_request_;
152 
153   // The message loop of the thread we were created on. This is the thread that
154   // will block on MakeSynchronousPost while the IO thread fetches data from
155   // the network.
156   // This should be the main syncer thread (SyncerThread) which is what blocks
157   // on network IO through curl_easy_perform.
158   MessageLoop* const created_on_loop_;
159 
160   // The URL to POST to.
161   GURL url_for_request_;
162 
163   // POST payload information.
164   std::string content_type_;
165   std::string request_content_;
166   std::string extra_headers_;
167 
168   // A waitable event we use to provide blocking semantics to
169   // MakeSynchronousPost. We block created_on_loop_ while the IO loop fetches
170   // network request.
171   base::WaitableEvent http_post_completed_;
172 
173   struct URLFetchState {
174     URLFetchState();
175     ~URLFetchState();
176     // Our hook into the network layer is a URLFetcher. USED ONLY ON THE IO
177     // LOOP, so we can block created_on_loop_ while the fetch is in progress.
178     // NOTE: This is not a scoped_ptr for a reason. It must be deleted on the
179     // same thread that created it, which isn't the same thread |this| gets
180     // deleted on. We must manually delete url_poster_ on the IO loop.
181     URLFetcher* url_poster;
182 
183     // Used to support 'Abort' functionality.
184     bool aborted;
185 
186     // Cached response data.
187     bool request_completed;
188     bool request_succeeded;
189     int http_response_code;
190     int os_error_code;
191     std::string response_content;
192     scoped_refptr<net::HttpResponseHeaders> response_headers;
193   };
194 
195   // This lock synchronizes use of state involved in the flow to fetch a URL
196   // using URLFetcher.  Because we can Abort() from any thread, for example,
197   // this flow needs to be synchronized to gracefully clean up URLFetcher and
198   // return appropriate values in os_error_code.
199   mutable base::Lock fetch_state_lock_;
200   URLFetchState fetch_state_;
201 
202   DISALLOW_COPY_AND_ASSIGN(HttpBridge);
203 };
204 
205 class HttpBridgeFactory : public sync_api::HttpPostProviderFactory {
206  public:
207   explicit HttpBridgeFactory(
208       net::URLRequestContextGetter* baseline_context_getter);
209   virtual ~HttpBridgeFactory();
210 
211   // sync_api::HttpPostProviderFactory:
212   virtual sync_api::HttpPostProviderInterface* Create() OVERRIDE;
213   virtual void Destroy(sync_api::HttpPostProviderInterface* http) OVERRIDE;
214 
215  private:
216   // This request context is built on top of the baseline context and shares
217   // common components.
218   HttpBridge::RequestContextGetter* GetRequestContextGetter();
219 
220   scoped_refptr<HttpBridge::RequestContextGetter> request_context_getter_;
221 
222   DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory);
223 };
224 
225 }  //  namespace browser_sync
226 
227 #endif  // CHROME_BROWSER_SYNC_GLUE_HTTP_BRIDGE_H_
228