| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/sync/glue/http_bridge.h" | 5 #include "sync/internal_api/public/http_bridge.h" |
| 6 | 6 |
| 7 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "content/public/browser/browser_thread.h" | |
| 11 #include "content/public/common/content_client.h" | |
| 12 #include "net/base/host_resolver.h" | 10 #include "net/base/host_resolver.h" |
| 13 #include "net/base/load_flags.h" | 11 #include "net/base/load_flags.h" |
| 14 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
| 15 #include "net/cookies/cookie_monster.h" | 13 #include "net/cookies/cookie_monster.h" |
| 16 #include "net/http/http_cache.h" | 14 #include "net/http/http_cache.h" |
| 17 #include "net/http/http_network_layer.h" | 15 #include "net/http/http_network_layer.h" |
| 18 #include "net/http/http_response_headers.h" | 16 #include "net/http/http_response_headers.h" |
| 19 #include "net/proxy/proxy_service.h" | 17 #include "net/proxy/proxy_service.h" |
| 20 #include "net/url_request/url_fetcher.h" | 18 #include "net/url_request/url_fetcher.h" |
| 21 #include "net/url_request/url_request_context.h" | 19 #include "net/url_request/url_request_context.h" |
| 22 #include "net/url_request/url_request_status.h" | 20 #include "net/url_request/url_request_status.h" |
| 23 | 21 |
| 24 using content::BrowserThread; | |
| 25 | |
| 26 namespace browser_sync { | 22 namespace browser_sync { |
| 27 | 23 |
| 28 HttpBridge::RequestContextGetter::RequestContextGetter( | 24 HttpBridge::RequestContextGetter::RequestContextGetter( |
| 29 net::URLRequestContextGetter* baseline_context_getter) | 25 net::URLRequestContextGetter* baseline_context_getter, |
| 30 : baseline_context_getter_(baseline_context_getter) { | 26 const std::string& user_agent) |
| 27 : baseline_context_getter_(baseline_context_getter), |
| 28 network_task_runner_( |
| 29 baseline_context_getter_->GetNetworkTaskRunner()), |
| 30 user_agent_(user_agent) { |
| 31 DCHECK(baseline_context_getter_); |
| 32 DCHECK(network_task_runner_); |
| 33 DCHECK(!user_agent_.empty()); |
| 31 } | 34 } |
| 32 | 35 |
| 33 HttpBridge::RequestContextGetter::~RequestContextGetter() {} | 36 HttpBridge::RequestContextGetter::~RequestContextGetter() {} |
| 34 | 37 |
| 35 net::URLRequestContext* | 38 net::URLRequestContext* |
| 36 HttpBridge::RequestContextGetter::GetURLRequestContext() { | 39 HttpBridge::RequestContextGetter::GetURLRequestContext() { |
| 37 // Lazily create the context. | 40 // Lazily create the context. |
| 38 if (!context_.get()) { | 41 if (!context_.get()) { |
| 39 net::URLRequestContext* baseline_context = | 42 net::URLRequestContext* baseline_context = |
| 40 baseline_context_getter_->GetURLRequestContext(); | 43 baseline_context_getter_->GetURLRequestContext(); |
| 41 context_.reset(new RequestContext(baseline_context)); | 44 context_.reset( |
| 45 new RequestContext(baseline_context, GetNetworkTaskRunner(), |
| 46 user_agent_)); |
| 42 baseline_context_getter_ = NULL; | 47 baseline_context_getter_ = NULL; |
| 43 } | 48 } |
| 44 | 49 |
| 45 // Apply the user agent which was set earlier. | |
| 46 if (is_user_agent_set()) | |
| 47 context_->set_user_agent(user_agent_); | |
| 48 | |
| 49 return context_.get(); | 50 return context_.get(); |
| 50 } | 51 } |
| 51 | 52 |
| 52 scoped_refptr<base::SingleThreadTaskRunner> | 53 scoped_refptr<base::SingleThreadTaskRunner> |
| 53 HttpBridge::RequestContextGetter::GetNetworkTaskRunner() const { | 54 HttpBridge::RequestContextGetter::GetNetworkTaskRunner() const { |
| 54 return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO); | 55 return network_task_runner_; |
| 55 } | 56 } |
| 56 | 57 |
| 57 HttpBridgeFactory::HttpBridgeFactory( | 58 HttpBridgeFactory::HttpBridgeFactory( |
| 58 net::URLRequestContextGetter* baseline_context_getter) { | 59 net::URLRequestContextGetter* baseline_context_getter, |
| 59 DCHECK(baseline_context_getter != NULL); | 60 const std::string& user_agent) |
| 60 request_context_getter_ = | 61 : request_context_getter_( |
| 61 new HttpBridge::RequestContextGetter(baseline_context_getter); | 62 new HttpBridge::RequestContextGetter( |
| 62 } | 63 baseline_context_getter, user_agent)) {} |
| 63 | 64 |
| 64 HttpBridgeFactory::~HttpBridgeFactory() { | 65 HttpBridgeFactory::~HttpBridgeFactory() { |
| 65 } | 66 } |
| 66 | 67 |
| 67 csync::HttpPostProviderInterface* HttpBridgeFactory::Create() { | 68 csync::HttpPostProviderInterface* HttpBridgeFactory::Create() { |
| 68 HttpBridge* http = new HttpBridge(request_context_getter_); | 69 HttpBridge* http = new HttpBridge(request_context_getter_); |
| 69 http->AddRef(); | 70 http->AddRef(); |
| 70 return http; | 71 return http; |
| 71 } | 72 } |
| 72 | 73 |
| 73 void HttpBridgeFactory::Destroy(csync::HttpPostProviderInterface* http) { | 74 void HttpBridgeFactory::Destroy(csync::HttpPostProviderInterface* http) { |
| 74 static_cast<HttpBridge*>(http)->Release(); | 75 static_cast<HttpBridge*>(http)->Release(); |
| 75 } | 76 } |
| 76 | 77 |
| 77 HttpBridge::RequestContext::RequestContext( | 78 HttpBridge::RequestContext::RequestContext( |
| 78 net::URLRequestContext* baseline_context) | 79 net::URLRequestContext* baseline_context, |
| 79 : baseline_context_(baseline_context) { | 80 const scoped_refptr<base::SingleThreadTaskRunner>& |
| 81 network_task_runner, |
| 82 const std::string& user_agent) |
| 83 : baseline_context_(baseline_context), |
| 84 network_task_runner_(network_task_runner), |
| 85 user_agent_(user_agent) { |
| 86 DCHECK(!user_agent_.empty()); |
| 80 | 87 |
| 81 // Create empty, in-memory cookie store. | 88 // Create empty, in-memory cookie store. |
| 82 set_cookie_store(new net::CookieMonster(NULL, NULL)); | 89 set_cookie_store(new net::CookieMonster(NULL, NULL)); |
| 83 | 90 |
| 84 // We don't use a cache for bridged loads, but we do want to share proxy info. | 91 // We don't use a cache for bridged loads, but we do want to share proxy info. |
| 85 set_host_resolver(baseline_context->host_resolver()); | 92 set_host_resolver(baseline_context->host_resolver()); |
| 86 set_proxy_service(baseline_context->proxy_service()); | 93 set_proxy_service(baseline_context->proxy_service()); |
| 87 set_ssl_config_service(baseline_context->ssl_config_service()); | 94 set_ssl_config_service(baseline_context->ssl_config_service()); |
| 88 | 95 |
| 89 // We want to share the HTTP session data with the network layer factory, | 96 // We want to share the HTTP session data with the network layer factory, |
| 90 // which includes auth_cache for proxies. | 97 // which includes auth_cache for proxies. |
| 91 // Session is not refcounted so we need to be careful to not lose the parent | 98 // Session is not refcounted so we need to be careful to not lose the parent |
| 92 // context. | 99 // context. |
| 93 net::HttpNetworkSession* session = | 100 net::HttpNetworkSession* session = |
| 94 baseline_context->http_transaction_factory()->GetSession(); | 101 baseline_context->http_transaction_factory()->GetSession(); |
| 95 DCHECK(session); | 102 DCHECK(session); |
| 96 set_http_transaction_factory(new net::HttpNetworkLayer(session)); | 103 set_http_transaction_factory(new net::HttpNetworkLayer(session)); |
| 97 | 104 |
| 98 // TODO(timsteele): We don't currently listen for pref changes of these | 105 // TODO(timsteele): We don't currently listen for pref changes of these |
| 99 // fields or CookiePolicy; I'm not sure we want to strictly follow the | 106 // fields or CookiePolicy; I'm not sure we want to strictly follow the |
| 100 // default settings, since for example if the user chooses to block all | 107 // default settings, since for example if the user chooses to block all |
| 101 // cookies, sync will start failing. Also it seems like accept_lang/charset | 108 // cookies, sync will start failing. Also it seems like accept_lang/charset |
| 102 // should be tied to whatever the sync servers expect (if anything). These | 109 // should be tied to whatever the sync servers expect (if anything). These |
| 103 // fields should probably just be settable by sync backend; though we should | 110 // fields should probably just be settable by sync backend; though we should |
| 104 // figure out if we need to give the user explicit control over policies etc. | 111 // figure out if we need to give the user explicit control over policies etc. |
| 105 set_accept_language(baseline_context->accept_language()); | 112 set_accept_language(baseline_context->accept_language()); |
| 106 set_accept_charset(baseline_context->accept_charset()); | 113 set_accept_charset(baseline_context->accept_charset()); |
| 107 | 114 |
| 108 // We default to the browser's user agent. This can (and should) be overridden | |
| 109 // with set_user_agent. | |
| 110 set_user_agent(content::GetUserAgent(GURL())); | |
| 111 | |
| 112 set_net_log(baseline_context->net_log()); | 115 set_net_log(baseline_context->net_log()); |
| 113 } | 116 } |
| 114 | 117 |
| 115 HttpBridge::RequestContext::~RequestContext() { | 118 HttpBridge::RequestContext::~RequestContext() { |
| 116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 119 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 117 delete http_transaction_factory(); | 120 delete http_transaction_factory(); |
| 118 } | 121 } |
| 119 | 122 |
| 123 const std::string& HttpBridge::RequestContext::GetUserAgent( |
| 124 const GURL& url) const { |
| 125 return user_agent_; |
| 126 } |
| 127 |
| 120 HttpBridge::URLFetchState::URLFetchState() : url_poster(NULL), | 128 HttpBridge::URLFetchState::URLFetchState() : url_poster(NULL), |
| 121 aborted(false), | 129 aborted(false), |
| 122 request_completed(false), | 130 request_completed(false), |
| 123 request_succeeded(false), | 131 request_succeeded(false), |
| 124 http_response_code(-1), | 132 http_response_code(-1), |
| 125 error_code(-1) {} | 133 error_code(-1) {} |
| 126 HttpBridge::URLFetchState::~URLFetchState() {} | 134 HttpBridge::URLFetchState::~URLFetchState() {} |
| 127 | 135 |
| 128 HttpBridge::HttpBridge(HttpBridge::RequestContextGetter* context_getter) | 136 HttpBridge::HttpBridge(HttpBridge::RequestContextGetter* context_getter) |
| 129 : context_getter_for_request_(context_getter), | 137 : context_getter_for_request_(context_getter), |
| 138 network_task_runner_( |
| 139 context_getter_for_request_->GetNetworkTaskRunner()), |
| 130 created_on_loop_(MessageLoop::current()), | 140 created_on_loop_(MessageLoop::current()), |
| 131 http_post_completed_(false, false) { | 141 http_post_completed_(false, false) { |
| 132 } | 142 } |
| 133 | 143 |
| 134 HttpBridge::~HttpBridge() { | 144 HttpBridge::~HttpBridge() { |
| 135 } | 145 } |
| 136 | 146 |
| 137 void HttpBridge::SetUserAgent(const char* user_agent) { | |
| 138 DCHECK_EQ(MessageLoop::current(), created_on_loop_); | |
| 139 if (DCHECK_IS_ON()) { | |
| 140 base::AutoLock lock(fetch_state_lock_); | |
| 141 DCHECK(!fetch_state_.request_completed); | |
| 142 } | |
| 143 context_getter_for_request_->set_user_agent(user_agent); | |
| 144 } | |
| 145 | |
| 146 void HttpBridge::SetExtraRequestHeaders(const char * headers) { | 147 void HttpBridge::SetExtraRequestHeaders(const char * headers) { |
| 147 DCHECK(extra_headers_.empty()) | 148 DCHECK(extra_headers_.empty()) |
| 148 << "HttpBridge::SetExtraRequestHeaders called twice."; | 149 << "HttpBridge::SetExtraRequestHeaders called twice."; |
| 149 extra_headers_.assign(headers); | 150 extra_headers_.assign(headers); |
| 150 } | 151 } |
| 151 | 152 |
| 152 void HttpBridge::SetURL(const char* url, int port) { | 153 void HttpBridge::SetURL(const char* url, int port) { |
| 153 DCHECK_EQ(MessageLoop::current(), created_on_loop_); | 154 DCHECK_EQ(MessageLoop::current(), created_on_loop_); |
| 154 if (DCHECK_IS_ON()) { | 155 if (DCHECK_IS_ON()) { |
| 155 base::AutoLock lock(fetch_state_lock_); | 156 base::AutoLock lock(fetch_state_lock_); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 | 189 |
| 189 bool HttpBridge::MakeSynchronousPost(int* error_code, int* response_code) { | 190 bool HttpBridge::MakeSynchronousPost(int* error_code, int* response_code) { |
| 190 DCHECK_EQ(MessageLoop::current(), created_on_loop_); | 191 DCHECK_EQ(MessageLoop::current(), created_on_loop_); |
| 191 if (DCHECK_IS_ON()) { | 192 if (DCHECK_IS_ON()) { |
| 192 base::AutoLock lock(fetch_state_lock_); | 193 base::AutoLock lock(fetch_state_lock_); |
| 193 DCHECK(!fetch_state_.request_completed); | 194 DCHECK(!fetch_state_.request_completed); |
| 194 } | 195 } |
| 195 DCHECK(url_for_request_.is_valid()) << "Invalid URL for request"; | 196 DCHECK(url_for_request_.is_valid()) << "Invalid URL for request"; |
| 196 DCHECK(!content_type_.empty()) << "Payload not set"; | 197 DCHECK(!content_type_.empty()) << "Payload not set"; |
| 197 | 198 |
| 198 if (!BrowserThread::PostTask( | 199 if (!network_task_runner_->PostTask( |
| 199 BrowserThread::IO, FROM_HERE, | 200 FROM_HERE, |
| 200 base::Bind(&HttpBridge::CallMakeAsynchronousPost, this))) { | 201 base::Bind(&HttpBridge::CallMakeAsynchronousPost, this))) { |
| 201 // This usually happens when we're in a unit test. | 202 // This usually happens when we're in a unit test. |
| 202 LOG(WARNING) << "Could not post CallMakeAsynchronousPost task"; | 203 LOG(WARNING) << "Could not post CallMakeAsynchronousPost task"; |
| 203 return false; | 204 return false; |
| 204 } | 205 } |
| 205 | 206 |
| 206 // Block until network request completes or is aborted. See | 207 // Block until network request completes or is aborted. See |
| 207 // OnURLFetchComplete and Abort. | 208 // OnURLFetchComplete and Abort. |
| 208 http_post_completed_.Wait(); | 209 http_post_completed_.Wait(); |
| 209 | 210 |
| 210 base::AutoLock lock(fetch_state_lock_); | 211 base::AutoLock lock(fetch_state_lock_); |
| 211 DCHECK(fetch_state_.request_completed || fetch_state_.aborted); | 212 DCHECK(fetch_state_.request_completed || fetch_state_.aborted); |
| 212 *error_code = fetch_state_.error_code; | 213 *error_code = fetch_state_.error_code; |
| 213 *response_code = fetch_state_.http_response_code; | 214 *response_code = fetch_state_.http_response_code; |
| 214 return fetch_state_.request_succeeded; | 215 return fetch_state_.request_succeeded; |
| 215 } | 216 } |
| 216 | 217 |
| 217 void HttpBridge::MakeAsynchronousPost() { | 218 void HttpBridge::MakeAsynchronousPost() { |
| 218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 219 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 219 base::AutoLock lock(fetch_state_lock_); | 220 base::AutoLock lock(fetch_state_lock_); |
| 220 DCHECK(!fetch_state_.request_completed); | 221 DCHECK(!fetch_state_.request_completed); |
| 221 if (fetch_state_.aborted) | 222 if (fetch_state_.aborted) |
| 222 return; | 223 return; |
| 223 | 224 |
| 224 fetch_state_.url_poster = net::URLFetcher::Create( | 225 fetch_state_.url_poster = net::URLFetcher::Create( |
| 225 url_for_request_, net::URLFetcher::POST, this); | 226 url_for_request_, net::URLFetcher::POST, this); |
| 226 fetch_state_.url_poster->SetRequestContext(context_getter_for_request_); | 227 fetch_state_.url_poster->SetRequestContext(context_getter_for_request_); |
| 227 fetch_state_.url_poster->SetUploadData(content_type_, request_content_); | 228 fetch_state_.url_poster->SetUploadData(content_type_, request_content_); |
| 228 fetch_state_.url_poster->SetExtraRequestHeaders(extra_headers_); | 229 fetch_state_.url_poster->SetExtraRequestHeaders(extra_headers_); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 256 return value; | 257 return value; |
| 257 } | 258 } |
| 258 | 259 |
| 259 void HttpBridge::Abort() { | 260 void HttpBridge::Abort() { |
| 260 base::AutoLock lock(fetch_state_lock_); | 261 base::AutoLock lock(fetch_state_lock_); |
| 261 DCHECK(!fetch_state_.aborted); | 262 DCHECK(!fetch_state_.aborted); |
| 262 if (fetch_state_.aborted || fetch_state_.request_completed) | 263 if (fetch_state_.aborted || fetch_state_.request_completed) |
| 263 return; | 264 return; |
| 264 | 265 |
| 265 fetch_state_.aborted = true; | 266 fetch_state_.aborted = true; |
| 266 if (!BrowserThread::PostTask( | 267 if (!network_task_runner_->PostTask( |
| 267 BrowserThread::IO, FROM_HERE, | 268 FROM_HERE, |
| 268 base::Bind(&HttpBridge::DestroyURLFetcherOnIOThread, this, | 269 base::Bind(&HttpBridge::DestroyURLFetcherOnIOThread, this, |
| 269 fetch_state_.url_poster))) { | 270 fetch_state_.url_poster))) { |
| 270 // Madness ensues. | 271 // Madness ensues. |
| 271 NOTREACHED() << "Could not post task to delete URLFetcher"; | 272 NOTREACHED() << "Could not post task to delete URLFetcher"; |
| 272 } | 273 } |
| 273 | 274 |
| 274 fetch_state_.url_poster = NULL; | 275 fetch_state_.url_poster = NULL; |
| 275 fetch_state_.error_code = net::ERR_ABORTED; | 276 fetch_state_.error_code = net::ERR_ABORTED; |
| 276 http_post_completed_.Signal(); | 277 http_post_completed_.Signal(); |
| 277 } | 278 } |
| 278 | 279 |
| 279 void HttpBridge::DestroyURLFetcherOnIOThread(net::URLFetcher* fetcher) { | 280 void HttpBridge::DestroyURLFetcherOnIOThread(net::URLFetcher* fetcher) { |
| 280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 281 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 281 delete fetcher; | 282 delete fetcher; |
| 282 } | 283 } |
| 283 | 284 |
| 284 void HttpBridge::OnURLFetchComplete(const net::URLFetcher* source) { | 285 void HttpBridge::OnURLFetchComplete(const net::URLFetcher* source) { |
| 285 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 286 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
| 286 base::AutoLock lock(fetch_state_lock_); | 287 base::AutoLock lock(fetch_state_lock_); |
| 287 if (fetch_state_.aborted) | 288 if (fetch_state_.aborted) |
| 288 return; | 289 return; |
| 289 | 290 |
| 290 fetch_state_.request_completed = true; | 291 fetch_state_.request_completed = true; |
| 291 fetch_state_.request_succeeded = | 292 fetch_state_.request_succeeded = |
| 292 (net::URLRequestStatus::SUCCESS == source->GetStatus().status()); | 293 (net::URLRequestStatus::SUCCESS == source->GetStatus().status()); |
| 293 fetch_state_.http_response_code = source->GetResponseCode(); | 294 fetch_state_.http_response_code = source->GetResponseCode(); |
| 294 fetch_state_.error_code = source->GetStatus().error(); | 295 fetch_state_.error_code = source->GetStatus().error(); |
| 295 | 296 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 307 // URLFetcher, so it seems most natural / "polite" to let the stack unwind. | 308 // URLFetcher, so it seems most natural / "polite" to let the stack unwind. |
| 308 MessageLoop::current()->DeleteSoon(FROM_HERE, fetch_state_.url_poster); | 309 MessageLoop::current()->DeleteSoon(FROM_HERE, fetch_state_.url_poster); |
| 309 fetch_state_.url_poster = NULL; | 310 fetch_state_.url_poster = NULL; |
| 310 | 311 |
| 311 // Wake the blocked syncer thread in MakeSynchronousPost. | 312 // Wake the blocked syncer thread in MakeSynchronousPost. |
| 312 // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted! | 313 // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted! |
| 313 http_post_completed_.Signal(); | 314 http_post_completed_.Signal(); |
| 314 } | 315 } |
| 315 | 316 |
| 316 } // namespace browser_sync | 317 } // namespace browser_sync |
| OLD | NEW |