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. CallMakeAsynchronousPost()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 const scoped_refptr<net::URLRequestContextGetter>& 232 baseline_context_getter, 233 const NetworkTimeUpdateCallback& network_time_update_callback, 234 CancelationSignal* cancelation_signal); 235 virtual ~HttpBridgeFactory(); 236 237 // HttpPostProviderFactory: 238 virtual void Init(const std::string& user_agent) OVERRIDE; 239 virtual HttpPostProviderInterface* Create() OVERRIDE; 240 virtual void Destroy(HttpPostProviderInterface* http) OVERRIDE; 241 242 // CancelationObserver implementation: 243 virtual void OnSignalReceived() OVERRIDE; 244 245 private: 246 // Protects |request_context_getter_| and |baseline_request_context_getter_|. 247 base::Lock context_getter_lock_; 248 249 // This request context is the starting point for the request_context_getter_ 250 // that we eventually use to make requests. During shutdown we must drop all 251 // references to it before the ProfileSyncService's Shutdown() call is 252 // complete. 253 scoped_refptr<net::URLRequestContextGetter> baseline_request_context_getter_; 254 255 // This request context is built on top of the baseline context and shares 256 // common components. Takes a reference to the 257 // baseline_request_context_getter_. It's mostly used on sync thread when 258 // creating connection but is released as soon as possible during shutdown. 259 // Protected by |context_getter_lock_|. 260 scoped_refptr<HttpBridge::RequestContextGetter> request_context_getter_; 261 262 NetworkTimeUpdateCallback network_time_update_callback_; 263 264 CancelationSignal* const cancelation_signal_; 265 266 DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory); 267 }; 268 269 } // namespace syncer 270 271 #endif // SYNC_INTERNAL_API_PUBLIC_HTTP_BRIDGE_H_ 272