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. 53 void set_user_agent(const std::string& ua) { user_agent_ = ua; } 54 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 78 void set_user_agent(const std::string& ua) { user_agent_ = ua; } 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: 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) 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. 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