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