blob: d446a57d0cdb7a3a0f96dfac84dd34133784f1ec [file] [log] [blame]
initial.commit586acc5fe2008-07-26 22:42:521// Copyright 2008, Google Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8// * Redistributions of source code must retain the above copyright
9// notice, this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above
11// copyright notice, this list of conditions and the following disclaimer
12// in the documentation and/or other materials provided with the
13// distribution.
14// * Neither the name of Google Inc. nor the names of its
15// contributors may be used to endorse or promote products derived from
16// this software without specific prior written permission.
17//
18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
[email protected]175adac2008-07-30 17:28:0430#include "net/url_request/url_request_http_job.h"
initial.commit586acc5fe2008-07-26 22:42:5231
[email protected]39ce5c02008-08-22 04:03:4432#include "base/compiler_specific.h"
initial.commit586acc5fe2008-07-26 22:42:5233#include "base/message_loop.h"
34#include "base/string_util.h"
35#include "net/base/cookie_monster.h"
36#include "net/base/net_errors.h"
37#include "net/base/net_util.h"
38#include "net/http/http_response_info.h"
39#include "net/http/http_transaction.h"
40#include "net/http/http_transaction_factory.h"
41#include "net/url_request/url_request.h"
42#include "net/url_request/url_request_error_job.h"
43
44// TODO(darin): make sure the port blocking code is not lost
45
initial.commit586acc5fe2008-07-26 22:42:5246// static
[email protected]175adac2008-07-30 17:28:0447URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
48 const std::string& scheme) {
initial.commit586acc5fe2008-07-26 22:42:5249 DCHECK(scheme == "http" || scheme == "https");
50
[email protected]8ac1a752008-07-31 19:40:3751 if (!net::IsPortAllowedByDefault(request->url().IntPort()))
initial.commit586acc5fe2008-07-26 22:42:5252 return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT);
53
54 if (!request->context() ||
55 !request->context()->http_transaction_factory()) {
56 NOTREACHED() << "requires a valid context";
57 return new URLRequestErrorJob(request, net::ERR_INVALID_ARGUMENT);
58 }
59
[email protected]175adac2008-07-30 17:28:0460 return new URLRequestHttpJob(request);
initial.commit586acc5fe2008-07-26 22:42:5261}
62
[email protected]175adac2008-07-30 17:28:0463URLRequestHttpJob::URLRequestHttpJob(URLRequest* request)
initial.commit586acc5fe2008-07-26 22:42:5264 : URLRequestJob(request),
initial.commit586acc5fe2008-07-26 22:42:5265 transaction_(NULL),
66 response_info_(NULL),
[email protected]a9bb6f692008-07-30 16:40:1067 proxy_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH),
68 server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH),
[email protected]39ce5c02008-08-22 04:03:4469 ALLOW_THIS_IN_INITIALIZER_LIST(
70 start_callback_(this, &URLRequestHttpJob::OnStartCompleted)),
71 ALLOW_THIS_IN_INITIALIZER_LIST(
72 read_callback_(this, &URLRequestHttpJob::OnReadCompleted)),
[email protected]3589e552008-08-20 23:11:3473 read_in_progress_(false),
74 context_(request->context()) {
initial.commit586acc5fe2008-07-26 22:42:5275}
76
[email protected]175adac2008-07-30 17:28:0477URLRequestHttpJob::~URLRequestHttpJob() {
initial.commit586acc5fe2008-07-26 22:42:5278 if (transaction_)
79 DestroyTransaction();
80}
81
[email protected]175adac2008-07-30 17:28:0482void URLRequestHttpJob::SetUpload(net::UploadData* upload) {
initial.commit586acc5fe2008-07-26 22:42:5283 DCHECK(!transaction_) << "cannot change once started";
84 request_info_.upload_data = upload;
85}
86
[email protected]175adac2008-07-30 17:28:0487void URLRequestHttpJob::SetExtraRequestHeaders(
initial.commit586acc5fe2008-07-26 22:42:5288 const std::string& headers) {
89 DCHECK(!transaction_) << "cannot change once started";
90 request_info_.extra_headers = headers;
91}
92
[email protected]175adac2008-07-30 17:28:0493void URLRequestHttpJob::Start() {
initial.commit586acc5fe2008-07-26 22:42:5294 DCHECK(!transaction_);
95
96 // TODO(darin): URLRequest::referrer() should return a GURL
97 GURL referrer(request_->referrer());
98
99 // Ensure that we do not send username and password fields in the referrer.
100 if (referrer.has_username() || referrer.has_password()) {
101 GURL::Replacements referrer_mods;
102 referrer_mods.ClearUsername();
103 referrer_mods.ClearPassword();
104 referrer = referrer.ReplaceComponents(referrer_mods);
105 }
106
107 request_info_.url = request_->url();
108 request_info_.referrer = referrer;
109 request_info_.method = request_->method();
110 request_info_.load_flags = request_->load_flags();
111
112 if (request_->context())
113 request_info_.user_agent = request_->context()->user_agent();
114
115 AddExtraHeaders();
116
117 StartTransaction();
118}
119
[email protected]175adac2008-07-30 17:28:04120void URLRequestHttpJob::Kill() {
initial.commit586acc5fe2008-07-26 22:42:52121 if (!transaction_)
122 return;
123
124 DestroyTransaction();
125 URLRequestJob::Kill();
126}
127
[email protected]175adac2008-07-30 17:28:04128net::LoadState URLRequestHttpJob::GetLoadState() const {
initial.commit586acc5fe2008-07-26 22:42:52129 return transaction_ ? transaction_->GetLoadState() : net::LOAD_STATE_IDLE;
130}
131
[email protected]175adac2008-07-30 17:28:04132uint64 URLRequestHttpJob::GetUploadProgress() const {
initial.commit586acc5fe2008-07-26 22:42:52133 return transaction_ ? transaction_->GetUploadProgress() : 0;
134}
135
[email protected]175adac2008-07-30 17:28:04136bool URLRequestHttpJob::GetMimeType(std::string* mime_type) {
initial.commit586acc5fe2008-07-26 22:42:52137 DCHECK(transaction_);
138
139 if (!response_info_)
140 return false;
141
142 return response_info_->headers->GetMimeType(mime_type);
143}
144
[email protected]175adac2008-07-30 17:28:04145bool URLRequestHttpJob::GetCharset(std::string* charset) {
initial.commit586acc5fe2008-07-26 22:42:52146 DCHECK(transaction_);
147
148 if (!response_info_)
149 return false;
150
151 return response_info_->headers->GetCharset(charset);
152}
153
[email protected]175adac2008-07-30 17:28:04154void URLRequestHttpJob::GetResponseInfo(net::HttpResponseInfo* info) {
initial.commit586acc5fe2008-07-26 22:42:52155 DCHECK(request_);
156 DCHECK(transaction_);
157
158 if (response_info_)
159 *info = *response_info_;
160}
161
[email protected]175adac2008-07-30 17:28:04162bool URLRequestHttpJob::GetResponseCookies(
initial.commit586acc5fe2008-07-26 22:42:52163 std::vector<std::string>* cookies) {
164 DCHECK(transaction_);
165
166 if (!response_info_)
167 return false;
168
169 if (response_cookies_.empty())
170 FetchResponseCookies();
171
172 cookies->clear();
173 cookies->swap(response_cookies_);
174 return true;
175}
176
[email protected]175adac2008-07-30 17:28:04177int URLRequestHttpJob::GetResponseCode() {
initial.commit586acc5fe2008-07-26 22:42:52178 DCHECK(transaction_);
179
180 if (!response_info_)
181 return -1;
182
183 return response_info_->headers->response_code();
184}
185
[email protected]175adac2008-07-30 17:28:04186bool URLRequestHttpJob::GetContentEncoding(std::string* encoding_type) {
initial.commit586acc5fe2008-07-26 22:42:52187 DCHECK(transaction_);
188
189 if (!response_info_)
190 return false;
191
192 // TODO(darin): what if there are multiple content encodings?
193 return response_info_->headers->EnumerateHeader(NULL, "Content-Encoding",
194 encoding_type);
195}
196
[email protected]175adac2008-07-30 17:28:04197bool URLRequestHttpJob::IsRedirectResponse(GURL* location,
198 int* http_status_code) {
initial.commit586acc5fe2008-07-26 22:42:52199 if (!response_info_)
200 return false;
201
202 std::string value;
203 if (!response_info_->headers->IsRedirect(&value))
204 return false;
205
206 *location = request_->url().Resolve(value);
207 *http_status_code = response_info_->headers->response_code();
208 return true;
209}
210
[email protected]175adac2008-07-30 17:28:04211bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
initial.commit586acc5fe2008-07-26 22:42:52212 // We only allow redirects to certain "safe" protocols. This does not
213 // restrict redirects to externally handled protocols. Our consumer would
214 // need to take care of those.
215
216 if (!URLRequest::IsHandledURL(location))
217 return true;
218
219 static const char* kSafeSchemes[] = {
220 "http",
221 "https",
222 "ftp"
223 };
224
225 for (size_t i = 0; i < arraysize(kSafeSchemes); ++i) {
226 if (location.SchemeIs(kSafeSchemes[i]))
227 return true;
228 }
229
230 return false;
231}
232
[email protected]175adac2008-07-30 17:28:04233bool URLRequestHttpJob::NeedsAuth() {
initial.commit586acc5fe2008-07-26 22:42:52234 int code = GetResponseCode();
235 if (code == -1)
236 return false;
237
238 // Check if we need either Proxy or WWW Authentication. This could happen
239 // because we either provided no auth info, or provided incorrect info.
240 switch (code) {
241 case 407:
[email protected]a9bb6f692008-07-30 16:40:10242 if (proxy_auth_state_ == net::AUTH_STATE_CANCELED)
initial.commit586acc5fe2008-07-26 22:42:52243 return false;
[email protected]a9bb6f692008-07-30 16:40:10244 proxy_auth_state_ = net::AUTH_STATE_NEED_AUTH;
initial.commit586acc5fe2008-07-26 22:42:52245 return true;
246 case 401:
[email protected]a9bb6f692008-07-30 16:40:10247 if (server_auth_state_ == net::AUTH_STATE_CANCELED)
initial.commit586acc5fe2008-07-26 22:42:52248 return false;
[email protected]a9bb6f692008-07-30 16:40:10249 server_auth_state_ = net::AUTH_STATE_NEED_AUTH;
initial.commit586acc5fe2008-07-26 22:42:52250 return true;
251 }
252 return false;
253}
254
[email protected]175adac2008-07-30 17:28:04255void URLRequestHttpJob::GetAuthChallengeInfo(
[email protected]a9bb6f692008-07-30 16:40:10256 scoped_refptr<net::AuthChallengeInfo>* result) {
initial.commit586acc5fe2008-07-26 22:42:52257 DCHECK(transaction_);
258 DCHECK(response_info_);
259
260 // sanity checks:
[email protected]a9bb6f692008-07-30 16:40:10261 DCHECK(proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH ||
262 server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
initial.commit586acc5fe2008-07-26 22:42:52263 DCHECK(response_info_->headers->response_code() == 401 ||
264 response_info_->headers->response_code() == 407);
265
266 *result = response_info_->auth_challenge;
267}
268
[email protected]175adac2008-07-30 17:28:04269void URLRequestHttpJob::GetCachedAuthData(
[email protected]a9bb6f692008-07-30 16:40:10270 const net::AuthChallengeInfo& auth_info,
271 scoped_refptr<net::AuthData>* auth_data) {
272 net::AuthCache* auth_cache =
initial.commit586acc5fe2008-07-26 22:42:52273 request_->context()->http_transaction_factory()->GetAuthCache();
274 if (!auth_cache) {
275 *auth_data = NULL;
276 return;
277 }
[email protected]a9bb6f692008-07-30 16:40:10278 std::string auth_cache_key =
279 net::AuthCache::HttpKey(request_->url(), auth_info);
initial.commit586acc5fe2008-07-26 22:42:52280 *auth_data = auth_cache->Lookup(auth_cache_key);
281}
282
[email protected]175adac2008-07-30 17:28:04283void URLRequestHttpJob::SetAuth(const std::wstring& username,
284 const std::wstring& password) {
initial.commit586acc5fe2008-07-26 22:42:52285 DCHECK(transaction_);
286
287 // Proxy gets set first, then WWW.
[email protected]a9bb6f692008-07-30 16:40:10288 if (proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH) {
289 proxy_auth_state_ = net::AUTH_STATE_HAVE_AUTH;
initial.commit586acc5fe2008-07-26 22:42:52290 } else {
[email protected]a9bb6f692008-07-30 16:40:10291 DCHECK(server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
292 server_auth_state_ = net::AUTH_STATE_HAVE_AUTH;
initial.commit586acc5fe2008-07-26 22:42:52293 }
294
295 // These will be reset in OnStartCompleted.
296 response_info_ = NULL;
297 response_cookies_.clear();
298
299 // No matter what, we want to report our status as IO pending since we will
300 // be notifying our consumer asynchronously via OnStartCompleted.
301 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
302
303 int rv = transaction_->RestartWithAuth(username, password,
304 &start_callback_);
305 if (rv == net::ERR_IO_PENDING)
306 return;
307
308 // The transaction started synchronously, but we need to notify the
309 // URLRequest delegate via the message loop.
310 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]175adac2008-07-30 17:28:04311 this, &URLRequestHttpJob::OnStartCompleted, rv));
initial.commit586acc5fe2008-07-26 22:42:52312}
313
[email protected]175adac2008-07-30 17:28:04314void URLRequestHttpJob::CancelAuth() {
initial.commit586acc5fe2008-07-26 22:42:52315 // Proxy gets set first, then WWW.
[email protected]a9bb6f692008-07-30 16:40:10316 if (proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH) {
317 proxy_auth_state_ = net::AUTH_STATE_CANCELED;
initial.commit586acc5fe2008-07-26 22:42:52318 } else {
[email protected]a9bb6f692008-07-30 16:40:10319 DCHECK(server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
320 server_auth_state_ = net::AUTH_STATE_CANCELED;
initial.commit586acc5fe2008-07-26 22:42:52321 }
322
323 // These will be reset in OnStartCompleted.
324 response_info_ = NULL;
325 response_cookies_.clear();
326
327 // OK, let the consumer read the error page...
328 //
329 // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
330 // which will cause the consumer to receive OnResponseStarted instead of
331 // OnAuthRequired.
332 //
333 // We have to do this via InvokeLater to avoid "recursing" the consumer.
334 //
335 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]175adac2008-07-30 17:28:04336 this, &URLRequestHttpJob::OnStartCompleted, net::OK));
initial.commit586acc5fe2008-07-26 22:42:52337}
338
[email protected]175adac2008-07-30 17:28:04339void URLRequestHttpJob::ContinueDespiteLastError() {
initial.commit586acc5fe2008-07-26 22:42:52340 DCHECK(transaction_);
341 DCHECK(!response_info_) << "should not have a response yet";
342
343 // No matter what, we want to report our status as IO pending since we will
344 // be notifying our consumer asynchronously via OnStartCompleted.
345 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
346
347 int rv = transaction_->RestartIgnoringLastError(&start_callback_);
348 if (rv == net::ERR_IO_PENDING)
349 return;
350
351 // The transaction started synchronously, but we need to notify the
352 // URLRequest delegate via the message loop.
353 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]175adac2008-07-30 17:28:04354 this, &URLRequestHttpJob::OnStartCompleted, rv));
initial.commit586acc5fe2008-07-26 22:42:52355}
356
[email protected]175adac2008-07-30 17:28:04357bool URLRequestHttpJob::GetMoreData() {
initial.commit586acc5fe2008-07-26 22:42:52358 return transaction_ && !read_in_progress_;
359}
360
[email protected]175adac2008-07-30 17:28:04361bool URLRequestHttpJob::ReadRawData(char* buf, int buf_size, int *bytes_read) {
initial.commit586acc5fe2008-07-26 22:42:52362 DCHECK_NE(buf_size, 0);
363 DCHECK(bytes_read);
364 DCHECK(!read_in_progress_);
365
366 int rv = transaction_->Read(buf, buf_size, &read_callback_);
367 if (rv >= 0) {
368 *bytes_read = rv;
369 return true;
370 }
371
372 if (rv == net::ERR_IO_PENDING) {
373 read_in_progress_ = true;
374 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
375 } else {
376 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
377 }
378
379 return false;
380}
381
[email protected]175adac2008-07-30 17:28:04382void URLRequestHttpJob::OnStartCompleted(int result) {
initial.commit586acc5fe2008-07-26 22:42:52383 // If the request was destroyed, then there is no more work to do.
384 if (!request_ || !request_->delegate())
385 return;
386
387 // If the transaction was destroyed, then the job was cancelled, and
388 // we can just ignore this notification.
389 if (!transaction_)
390 return;
391
392 // Clear the IO_PENDING status
393 SetStatus(URLRequestStatus());
394
395 if (result == net::OK) {
396 NotifyHeadersComplete();
397 } else if (net::IsCertificateError(result)) {
398 // We encountered an SSL certificate error. Ask our delegate to decide
399 // what we should do.
400 // TODO(wtc): also pass ssl_info.cert_status, or just pass the whole
401 // ssl_info.
402 request_->delegate()->OnSSLCertificateError(
403 request_, result, transaction_->GetResponseInfo()->ssl_info.cert);
404 } else {
405 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
406 }
407}
408
[email protected]175adac2008-07-30 17:28:04409void URLRequestHttpJob::OnReadCompleted(int result) {
initial.commit586acc5fe2008-07-26 22:42:52410 read_in_progress_ = false;
411
412 if (result == 0) {
413 NotifyDone(URLRequestStatus());
414 } else if (result < 0) {
415 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
416 } else {
417 // Clear the IO_PENDING status
418 SetStatus(URLRequestStatus());
419 }
420
421 NotifyReadComplete(result);
422}
423
[email protected]175adac2008-07-30 17:28:04424void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52425 DCHECK(!response_info_);
426
427 response_info_ = transaction_->GetResponseInfo();
428
429 // Get the Set-Cookie values, and send them to our cookie database.
430
431 FetchResponseCookies();
432
433 URLRequestContext* ctx = request_->context();
434 if (ctx && ctx->cookie_store() &&
435 ctx->cookie_policy()->CanSetCookie(request_->url(),
436 request_->policy_url()))
437 ctx->cookie_store()->SetCookies(request_->url(), response_cookies_);
438
439 URLRequestJob::NotifyHeadersComplete();
440}
441
[email protected]175adac2008-07-30 17:28:04442void URLRequestHttpJob::DestroyTransaction() {
initial.commit586acc5fe2008-07-26 22:42:52443 DCHECK(transaction_);
444
445 transaction_->Destroy();
446 transaction_ = NULL;
447 response_info_ = NULL;
448}
449
[email protected]175adac2008-07-30 17:28:04450void URLRequestHttpJob::StartTransaction() {
initial.commit586acc5fe2008-07-26 22:42:52451 // NOTE: This method assumes that request_info_ is already setup properly.
452
453 // Create a transaction.
454 DCHECK(!transaction_);
455
456 DCHECK(request_->context());
457 DCHECK(request_->context()->http_transaction_factory());
458
459 transaction_ =
460 request_->context()->http_transaction_factory()->CreateTransaction();
461
462 // No matter what, we want to report our status as IO pending since we will
463 // be notifying our consumer asynchronously via OnStartCompleted.
464 SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
465
466 int rv;
467 if (transaction_) {
468 rv = transaction_->Start(&request_info_, &start_callback_);
469 if (rv == net::ERR_IO_PENDING)
470 return;
471 } else {
472 rv = net::ERR_FAILED;
473 }
474
475 // The transaction started synchronously, but we need to notify the
476 // URLRequest delegate via the message loop.
477 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
[email protected]175adac2008-07-30 17:28:04478 this, &URLRequestHttpJob::OnStartCompleted, rv));
initial.commit586acc5fe2008-07-26 22:42:52479}
480
[email protected]175adac2008-07-30 17:28:04481void URLRequestHttpJob::AddExtraHeaders() {
initial.commit586acc5fe2008-07-26 22:42:52482 URLRequestContext* context = request_->context();
483 if (context) {
484 // Add in the cookie header. TODO might we need more than one header?
485 if (context->cookie_store() &&
486 context->cookie_policy()->CanGetCookies(request_->url(),
487 request_->policy_url())) {
488 std::string cookies = request_->context()->cookie_store()->
489 GetCookiesWithOptions(request_->url(),
[email protected]8ac1a752008-07-31 19:40:37490 net::CookieMonster::INCLUDE_HTTPONLY);
initial.commit586acc5fe2008-07-26 22:42:52491 if (!cookies.empty())
492 request_info_.extra_headers += "Cookie: " + cookies + "\r\n";
493 }
494 if (!context->accept_language().empty())
495 request_info_.extra_headers += "Accept-Language: " +
496 context->accept_language() + "\r\n";
497 if (!context->accept_charset().empty())
498 request_info_.extra_headers += "Accept-Charset: " +
499 context->accept_charset() + "\r\n";
500 }
501
502#ifdef CHROME_LAST_MINUTE
503 // Tell the server what compression formats we support.
504 request_info_.extra_headers += "Accept-Encoding: gzip,deflate,bzip2\r\n";
505#else
506 // Tell the server that we support gzip/deflate encoding.
507 request_info_.extra_headers += "Accept-Encoding: gzip,deflate";
508
509 // const string point to google domain
510 static const char kGoogleDomain[] = "google.com";
511 static const unsigned int kGoogleDomainLen = arraysize(kGoogleDomain) - 1;
512 static const char kLocalHostName[] = "localhost";
513
514 // At now, only support bzip2 feature for those requests which are
515 // sent to google domain or localhost.
516 // TODO(jnd) : we will remove the "google.com" domain check before launch.
517 // See bug : 861940
518 const std::string &host = request_->url().host();
519
520 if (host == kLocalHostName ||
521 request_->url().DomainIs(kGoogleDomain, kGoogleDomainLen)) {
522 request_info_.extra_headers += ",bzip2\r\n";
523 } else {
524 request_info_.extra_headers += "\r\n";
525 }
526#endif
527}
528
[email protected]175adac2008-07-30 17:28:04529void URLRequestHttpJob::FetchResponseCookies() {
initial.commit586acc5fe2008-07-26 22:42:52530 DCHECK(response_info_);
531 DCHECK(response_cookies_.empty());
532
533 std::string name = "Set-Cookie";
534 std::string value;
535
536 void* iter = NULL;
537 while (response_info_->headers->EnumerateHeader(&iter, name, &value))
538 response_cookies_.push_back(value);
539}