Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(269)

Side by Side Diff: chrome/browser/sync/glue/http_bridge.cc

Issue 160542: Rolling back 22317 (Closed) Base URL: svn://chrome-svn.corp.google.com/chrome/trunk/src/
Patch Set: Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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 #ifdef CHROME_PERSONALIZATION
6
7 #include "chrome/browser/sync/glue/http_bridge.h"
8
9 #include "base/message_loop.h"
10 #include "base/string_util.h"
11 #include "chrome/browser/chrome_thread.h"
12 #include "chrome/browser/profile.h"
13 #include "net/base/cookie_monster.h"
14 #include "net/base/load_flags.h"
15 #include "net/http/http_network_layer.h"
16 #include "net/proxy/proxy_service.h"
17 #include "net/url_request/url_request_status.h"
18 #include "webkit/glue/webkit_glue.h"
19
20 namespace browser_sync {
21
22 HttpBridge::RequestContext* HttpBridgeFactory::GetRequestContext() {
23 if (!request_context_) {
24 request_context_ =
25 new HttpBridge::RequestContext(Profile::GetDefaultRequestContext());
26 request_context_->AddRef();
27 }
28 return request_context_;
29 }
30
31 HttpBridgeFactory::~HttpBridgeFactory() {
32 if (request_context_) {
33 // Clean up request context on IO thread.
34 ChromeThread::GetMessageLoop(ChromeThread::IO)->ReleaseSoon(FROM_HERE,
35 request_context_);
36 request_context_ = NULL;
37 }
38 }
39
40 sync_api::HttpPostProviderInterface* HttpBridgeFactory::Create() {
41 // TODO(timsteele): We want the active profile request context.
42 HttpBridge* http = new HttpBridge(GetRequestContext(),
43 ChromeThread::GetMessageLoop(ChromeThread::IO));
44 http->AddRef();
45 return http;
46 }
47
48 void HttpBridgeFactory::Destroy(sync_api::HttpPostProviderInterface* http) {
49 static_cast<HttpBridge*>(http)->Release();
50 }
51
52 HttpBridge::RequestContext::RequestContext(
53 const URLRequestContext* baseline_context) {
54
55 // Create empty, in-memory cookie store.
56 cookie_store_ = new net::CookieMonster();
57
58 // We don't use a cache for bridged loads, but we do want to share proxy info.
59 host_resolver_ = baseline_context->host_resolver();
60 proxy_service_ = baseline_context->proxy_service();
61 http_transaction_factory_ =
62 net::HttpNetworkLayer::CreateFactory(host_resolver_, proxy_service_);
63
64 // TODO(timsteele): We don't currently listen for pref changes of these
65 // fields or CookiePolicy; I'm not sure we want to strictly follow the
66 // default settings, since for example if the user chooses to block all
67 // cookies, sync will start failing. Also it seems like accept_lang/charset
68 // should be tied to whatever the sync servers expect (if anything). These
69 // fields should probably just be settable by sync backend; though we should
70 // figure out if we need to give the user explicit control over policies etc.
71 accept_language_ = baseline_context->accept_language();
72 accept_charset_ = baseline_context->accept_charset();
73
74 // We default to the browser's user agent. This can (and should) be overridden
75 // with set_user_agent.
76 user_agent_ = webkit_glue::GetUserAgent(GURL());
77 }
78
79 HttpBridge::RequestContext::~RequestContext() {
80 delete cookie_store_;
81 delete http_transaction_factory_;
82 }
83
84 HttpBridge::HttpBridge(HttpBridge::RequestContext* context,
85 MessageLoop* io_loop)
86 : context_for_request_(context),
87 url_poster_(NULL),
88 created_on_loop_(MessageLoop::current()),
89 io_loop_(io_loop),
90 request_completed_(false),
91 request_succeeded_(false),
92 http_response_code_(-1),
93 http_post_completed_(false, false),
94 use_io_loop_for_testing_(false) {
95 context_for_request_->AddRef();
96 }
97
98 HttpBridge::~HttpBridge() {
99 io_loop_->ReleaseSoon(FROM_HERE, context_for_request_);
100 }
101
102 void HttpBridge::SetUserAgent(const char* user_agent) {
103 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
104 DCHECK(!request_completed_);
105 context_for_request_->set_user_agent(user_agent);
106 }
107
108 void HttpBridge::SetURL(const char* url, int port) {
109 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
110 DCHECK(!request_completed_);
111 DCHECK(url_for_request_.is_empty())
112 << "HttpBridge::SetURL called more than once?!";
113 GURL temp(url);
114 GURL::Replacements replacements;
115 std::string port_str = IntToString(port);
116 replacements.SetPort(port_str.c_str(),
117 url_parse::Component(0, port_str.length()));
118 url_for_request_ = temp.ReplaceComponents(replacements);
119 }
120
121 void HttpBridge::SetPostPayload(const char* content_type,
122 int content_length,
123 const char* content) {
124 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
125 DCHECK(!request_completed_);
126 DCHECK(content_type_.empty()) << "Bridge payload already set.";
127 DCHECK_GE(content_length, 0) << "Content length < 0";
128 content_type_ = content_type;
129 if (!content || (content_length == 0)) {
130 DCHECK_EQ(content_length, 0);
131 request_content_ = " "; // TODO(timsteele): URLFetcher requires non-empty
132 // content for POSTs whereas CURL does not, for now
133 // we hack this to support the sync backend.
134 } else {
135 request_content_.assign(content, content_length);
136 }
137 }
138
139 void HttpBridge::AddCookieForRequest(const char* cookie) {
140 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
141 DCHECK(!request_completed_);
142 DCHECK(url_for_request_.is_valid()) << "Valid URL not set.";
143 if (!url_for_request_.is_valid()) return;
144
145 if (!context_for_request_->cookie_store()->SetCookie(url_for_request_,
146 cookie)) {
147 DLOG(WARNING) << "Cookie " << cookie
148 << " could not be added for url: " << url_for_request_ << ".";
149 }
150 }
151
152 bool HttpBridge::MakeSynchronousPost(int* os_error_code, int* response_code) {
153 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
154 DCHECK(!request_completed_);
155 DCHECK(url_for_request_.is_valid()) << "Invalid URL for request";
156 DCHECK(!content_type_.empty()) << "Payload not set";
157 DCHECK(context_for_request_->is_user_agent_set()) << "User agent not set";
158
159 io_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
160 &HttpBridge::CallMakeAsynchronousPost));
161
162 if (!http_post_completed_.Wait()) // Block until network request completes.
163 NOTREACHED(); // See OnURLFetchComplete.
164
165 DCHECK(request_completed_);
166 *os_error_code = os_error_code_;
167 *response_code = http_response_code_;
168 return request_succeeded_;
169 }
170
171 void HttpBridge::MakeAsynchronousPost() {
172 DCHECK_EQ(MessageLoop::current(), io_loop_);
173 DCHECK(!request_completed_);
174
175 url_poster_ = new URLFetcher(url_for_request_, URLFetcher::POST, this);
176 url_poster_->set_request_context(context_for_request_);
177 url_poster_->set_upload_data(content_type_, request_content_);
178
179 if (use_io_loop_for_testing_)
180 url_poster_->set_io_loop(io_loop_);
181
182 url_poster_->Start();
183 }
184
185 int HttpBridge::GetResponseContentLength() const {
186 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
187 DCHECK(request_completed_);
188 return response_content_.size();
189 }
190
191 const char* HttpBridge::GetResponseContent() const {
192 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
193 DCHECK(request_completed_);
194 return response_content_.c_str();
195 }
196
197 int HttpBridge::GetResponseCookieCount() const {
198 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
199 DCHECK(request_completed_);
200 return response_cookies_.size();
201 }
202
203 const char* HttpBridge::GetResponseCookieAt(int cookie_number) const {
204 DCHECK_EQ(MessageLoop::current(), created_on_loop_);
205 DCHECK(request_completed_);
206 bool valid_number = (cookie_number >= 0) &&
207 (static_cast<size_t>(cookie_number) < response_cookies_.size());
208 DCHECK(valid_number);
209 if (!valid_number)
210 return NULL;
211 return response_cookies_[cookie_number].c_str();
212 }
213
214 void HttpBridge::OnURLFetchComplete(const URLFetcher *source, const GURL &url,
215 const URLRequestStatus &status,
216 int response_code,
217 const ResponseCookies &cookies,
218 const std::string &data) {
219 DCHECK_EQ(MessageLoop::current(), io_loop_);
220
221 request_completed_ = true;
222 request_succeeded_ = (URLRequestStatus::SUCCESS == status.status());
223 http_response_code_ = response_code;
224 os_error_code_ = status.os_error();
225
226 // TODO(timsteele): For now we need this "fixup" to match up with what the
227 // sync backend expects. This seems to be non-standard and shouldn't be done
228 // here in HttpBridge, and it breaks part of the unittest.
229 for (size_t i = 0; i < cookies.size(); ++i) {
230 net::CookieMonster::ParsedCookie parsed_cookie(cookies[i]);
231 std::string cookie = " \t \t \t \t \t";
232 cookie += parsed_cookie.Name() + "\t";
233 cookie += parsed_cookie.Value();
234 response_cookies_.push_back(cookie);
235 }
236
237 response_content_ = data;
238
239 // End of the line for url_poster_. It lives only on the io_loop.
240 // We defer deletion because we're inside a callback from a component of the
241 // URLFetcher, so it seems most natural / "polite" to let the stack unwind.
242 io_loop_->DeleteSoon(FROM_HERE, url_poster_);
243 url_poster_ = NULL;
244
245 // Wake the blocked syncer thread in MakeSynchronousPost.
246 // WARNING: DONT DO ANYTHING AFTER THIS CALL! |this| may be deleted!
247 http_post_completed_.Signal();
248 }
249
250 } // namespace browser_sync
251
252 #endif // CHROME_PERSONALIZATION
OLDNEW
« no previous file with comments | « chrome/browser/sync/glue/http_bridge.h ('k') | chrome/browser/sync/glue/http_bridge_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698