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

Side by Side Diff: chrome/browser/google_apis/base_requests.cc

Issue 96413002: Move c/b/google_apis to google_apis/drive. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/google_apis/base_requests.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/location.h"
9 #include "base/sequenced_task_runner.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/task_runner_util.h"
13 #include "base/values.h"
14 #include "chrome/browser/google_apis/request_sender.h"
15 #include "chrome/browser/google_apis/task_util.h"
16 #include "net/base/io_buffer.h"
17 #include "net/base/load_flags.h"
18 #include "net/base/net_errors.h"
19 #include "net/http/http_byte_range.h"
20 #include "net/http/http_response_headers.h"
21 #include "net/http/http_util.h"
22 #include "net/url_request/url_fetcher.h"
23 #include "net/url_request/url_request_status.h"
24
25 using net::URLFetcher;
26
27 namespace {
28
29 // Template for optional OAuth2 authorization HTTP header.
30 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
31 // Template for GData API version HTTP header.
32 const char kGDataVersionHeader[] = "GData-Version: 3.0";
33
34 // Maximum number of attempts for re-authentication per request.
35 const int kMaxReAuthenticateAttemptsPerRequest = 1;
36
37 // Template for initiate upload of both GData WAPI and Drive API v2.
38 const char kUploadContentType[] = "X-Upload-Content-Type: ";
39 const char kUploadContentLength[] = "X-Upload-Content-Length: ";
40 const char kUploadResponseLocation[] = "location";
41
42 // Template for upload data range of both GData WAPI and Drive API v2.
43 const char kUploadContentRange[] = "Content-Range: bytes ";
44 const char kUploadResponseRange[] = "range";
45
46 // Parse JSON string to base::Value object.
47 scoped_ptr<base::Value> ParseJsonInternal(const std::string& json) {
48 int error_code = -1;
49 std::string error_message;
50 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
51 json, base::JSON_PARSE_RFC, &error_code, &error_message));
52
53 if (!value.get()) {
54 std::string trimmed_json;
55 if (json.size() < 80) {
56 trimmed_json = json;
57 } else {
58 // Take the first 50 and the last 10 bytes.
59 trimmed_json = base::StringPrintf(
60 "%s [%s bytes] %s",
61 json.substr(0, 50).c_str(),
62 base::Uint64ToString(json.size() - 60).c_str(),
63 json.substr(json.size() - 10).c_str());
64 }
65 LOG(WARNING) << "Error while parsing entry response: " << error_message
66 << ", code: " << error_code << ", json:\n" << trimmed_json;
67 }
68 return value.Pass();
69 }
70
71 // Returns response headers as a string. Returns a warning message if
72 // |url_fetcher| does not contain a valid response. Used only for debugging.
73 std::string GetResponseHeadersAsString(
74 const URLFetcher* url_fetcher) {
75 // net::HttpResponseHeaders::raw_headers(), as the name implies, stores
76 // all headers in their raw format, i.e each header is null-terminated.
77 // So logging raw_headers() only shows the first header, which is probably
78 // the status line. GetNormalizedHeaders, on the other hand, will show all
79 // the headers, one per line, which is probably what we want.
80 std::string headers;
81 // Check that response code indicates response headers are valid (i.e. not
82 // malformed) before we retrieve the headers.
83 if (url_fetcher->GetResponseCode() == URLFetcher::RESPONSE_CODE_INVALID) {
84 headers.assign("Response headers are malformed!!");
85 } else {
86 url_fetcher->GetResponseHeaders()->GetNormalizedHeaders(&headers);
87 }
88 return headers;
89 }
90
91 bool IsSuccessfulResponseCode(int response_code) {
92 return 200 <= response_code && response_code <= 299;
93 }
94
95 } // namespace
96
97 namespace google_apis {
98
99 void ParseJson(base::TaskRunner* blocking_task_runner,
100 const std::string& json,
101 const ParseJsonCallback& callback) {
102 base::PostTaskAndReplyWithResult(
103 blocking_task_runner,
104 FROM_HERE,
105 base::Bind(&ParseJsonInternal, json),
106 callback);
107 }
108
109 //=========================== ResponseWriter ==================================
110 ResponseWriter::ResponseWriter(net::URLFetcher* url_fetcher,
111 base::SequencedTaskRunner* file_task_runner,
112 const base::FilePath& file_path,
113 const GetContentCallback& get_content_callback)
114 : url_fetcher_(url_fetcher),
115 get_content_callback_(get_content_callback) {
116 if (!file_path.empty()) {
117 file_writer_.reset(
118 new net::URLFetcherFileWriter(file_task_runner, file_path));
119 }
120 }
121
122 ResponseWriter::~ResponseWriter() {
123 }
124
125 void ResponseWriter::DisownFile() {
126 DCHECK(file_writer_);
127 file_writer_->DisownFile();
128 }
129
130 int ResponseWriter::Initialize(const net::CompletionCallback& callback) {
131 if (file_writer_)
132 return file_writer_->Initialize(callback);
133
134 data_.clear();
135 return net::OK;
136 }
137
138 int ResponseWriter::Write(net::IOBuffer* buffer,
139 int num_bytes,
140 const net::CompletionCallback& callback) {
141 // |get_content_callback_| and |file_writer_| are used only when the response
142 // code is successful one.
143 if (IsSuccessfulResponseCode(url_fetcher_->GetResponseCode())) {
144 if (!get_content_callback_.is_null()) {
145 get_content_callback_.Run(
146 HTTP_SUCCESS,
147 make_scoped_ptr(new std::string(buffer->data(), num_bytes)));
148 }
149
150 if (file_writer_)
151 return file_writer_->Write(buffer, num_bytes, callback);
152 }
153
154 data_.append(buffer->data(), num_bytes);
155 return num_bytes;
156 }
157
158 int ResponseWriter::Finish(const net::CompletionCallback& callback) {
159 if (file_writer_)
160 return file_writer_->Finish(callback);
161
162 return net::OK;
163 }
164
165 //============================ UrlFetchRequestBase ===========================
166
167 UrlFetchRequestBase::UrlFetchRequestBase(RequestSender* sender)
168 : re_authenticate_count_(0),
169 sender_(sender),
170 error_code_(GDATA_OTHER_ERROR),
171 weak_ptr_factory_(this) {
172 }
173
174 UrlFetchRequestBase::~UrlFetchRequestBase() {}
175
176 void UrlFetchRequestBase::Start(const std::string& access_token,
177 const std::string& custom_user_agent,
178 const ReAuthenticateCallback& callback) {
179 DCHECK(CalledOnValidThread());
180 DCHECK(!access_token.empty());
181 DCHECK(!callback.is_null());
182 DCHECK(re_authenticate_callback_.is_null());
183
184 re_authenticate_callback_ = callback;
185
186 GURL url = GetURL();
187 if (url.is_empty()) {
188 // Error is found on generating the url. Send the error message to the
189 // callback, and then return immediately without trying to connect
190 // to the server.
191 RunCallbackOnPrematureFailure(GDATA_OTHER_ERROR);
192 return;
193 }
194 DVLOG(1) << "URL: " << url.spec();
195
196 URLFetcher::RequestType request_type = GetRequestType();
197 url_fetcher_.reset(
198 URLFetcher::Create(url, request_type, this));
199 url_fetcher_->SetRequestContext(sender_->url_request_context_getter());
200 // Always set flags to neither send nor save cookies.
201 url_fetcher_->SetLoadFlags(
202 net::LOAD_DO_NOT_SEND_COOKIES | net::LOAD_DO_NOT_SAVE_COOKIES |
203 net::LOAD_DISABLE_CACHE);
204
205 base::FilePath output_file_path;
206 GetContentCallback get_content_callback;
207 GetOutputFilePath(&output_file_path, &get_content_callback);
208 if (!get_content_callback.is_null())
209 get_content_callback = CreateRelayCallback(get_content_callback);
210 response_writer_ = new ResponseWriter(url_fetcher_.get(),
211 blocking_task_runner(),
212 output_file_path,
213 get_content_callback);
214 url_fetcher_->SaveResponseWithWriter(
215 scoped_ptr<net::URLFetcherResponseWriter>(response_writer_));
216
217 // Add request headers.
218 // Note that SetExtraRequestHeaders clears the current headers and sets it
219 // to the passed-in headers, so calling it for each header will result in
220 // only the last header being set in request headers.
221 if (!custom_user_agent.empty())
222 url_fetcher_->AddExtraRequestHeader("User-Agent: " + custom_user_agent);
223 url_fetcher_->AddExtraRequestHeader(kGDataVersionHeader);
224 url_fetcher_->AddExtraRequestHeader(
225 base::StringPrintf(kAuthorizationHeaderFormat, access_token.data()));
226 std::vector<std::string> headers = GetExtraRequestHeaders();
227 for (size_t i = 0; i < headers.size(); ++i) {
228 url_fetcher_->AddExtraRequestHeader(headers[i]);
229 DVLOG(1) << "Extra header: " << headers[i];
230 }
231
232 // Set upload data if available.
233 std::string upload_content_type;
234 std::string upload_content;
235 if (GetContentData(&upload_content_type, &upload_content)) {
236 url_fetcher_->SetUploadData(upload_content_type, upload_content);
237 } else {
238 base::FilePath local_file_path;
239 int64 range_offset = 0;
240 int64 range_length = 0;
241 if (GetContentFile(&local_file_path, &range_offset, &range_length,
242 &upload_content_type)) {
243 url_fetcher_->SetUploadFilePath(
244 upload_content_type,
245 local_file_path,
246 range_offset,
247 range_length,
248 blocking_task_runner());
249 } else {
250 // Even if there is no content data, UrlFetcher requires to set empty
251 // upload data string for POST, PUT and PATCH methods, explicitly.
252 // It is because that most requests of those methods have non-empty
253 // body, and UrlFetcher checks whether it is actually not forgotten.
254 if (request_type == URLFetcher::POST ||
255 request_type == URLFetcher::PUT ||
256 request_type == URLFetcher::PATCH) {
257 // Set empty upload content-type and upload content, so that
258 // the request will have no "Content-type: " header and no content.
259 url_fetcher_->SetUploadData(std::string(), std::string());
260 }
261 }
262 }
263
264 url_fetcher_->Start();
265 }
266
267 URLFetcher::RequestType UrlFetchRequestBase::GetRequestType() const {
268 return URLFetcher::GET;
269 }
270
271 std::vector<std::string> UrlFetchRequestBase::GetExtraRequestHeaders() const {
272 return std::vector<std::string>();
273 }
274
275 bool UrlFetchRequestBase::GetContentData(std::string* upload_content_type,
276 std::string* upload_content) {
277 return false;
278 }
279
280 bool UrlFetchRequestBase::GetContentFile(base::FilePath* local_file_path,
281 int64* range_offset,
282 int64* range_length,
283 std::string* upload_content_type) {
284 return false;
285 }
286
287 void UrlFetchRequestBase::GetOutputFilePath(
288 base::FilePath* local_file_path,
289 GetContentCallback* get_content_callback) {
290 }
291
292 void UrlFetchRequestBase::Cancel() {
293 response_writer_ = NULL;
294 url_fetcher_.reset(NULL);
295 RunCallbackOnPrematureFailure(GDATA_CANCELLED);
296 sender_->RequestFinished(this);
297 }
298
299 GDataErrorCode UrlFetchRequestBase::GetErrorCode() {
300 return error_code_;
301 }
302
303 bool UrlFetchRequestBase::CalledOnValidThread() {
304 return thread_checker_.CalledOnValidThread();
305 }
306
307 base::SequencedTaskRunner* UrlFetchRequestBase::blocking_task_runner() const {
308 return sender_->blocking_task_runner();
309 }
310
311 void UrlFetchRequestBase::OnProcessURLFetchResultsComplete() {
312 sender_->RequestFinished(this);
313 }
314
315 void UrlFetchRequestBase::OnURLFetchComplete(const URLFetcher* source) {
316 DVLOG(1) << "Response headers:\n" << GetResponseHeadersAsString(source);
317
318 // Determine error code.
319 error_code_ = static_cast<GDataErrorCode>(source->GetResponseCode());
320 if (!source->GetStatus().is_success()) {
321 switch (source->GetStatus().error()) {
322 case net::ERR_NETWORK_CHANGED:
323 error_code_ = GDATA_NO_CONNECTION;
324 break;
325 default:
326 error_code_ = GDATA_OTHER_ERROR;
327 }
328 }
329
330 // The server may return detailed error status in JSON.
331 // See https://developers.google.com/drive/handle-errors
332 if (!IsSuccessfulResponseCode(error_code_)) {
333 DVLOG(1) << response_writer_->data();
334
335 const char kErrorKey[] = "error";
336 const char kErrorErrorsKey[] = "errors";
337 const char kErrorReasonKey[] = "reason";
338 const char kErrorMessageKey[] = "message";
339 const char kErrorReasonRateLimitExceeded[] = "rateLimitExceeded";
340 const char kErrorReasonUserRateLimitExceeded[] = "userRateLimitExceeded";
341
342 scoped_ptr<base::Value> value(ParseJsonInternal(response_writer_->data()));
343 base::DictionaryValue* dictionary = NULL;
344 base::DictionaryValue* error = NULL;
345 if (value &&
346 value->GetAsDictionary(&dictionary) &&
347 dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) {
348 // Get error message.
349 std::string message;
350 error->GetStringWithoutPathExpansion(kErrorMessageKey, &message);
351 DLOG(ERROR) << "code: " << error_code_ << ", message: " << message;
352
353 // Override the error code based on the reason of the first error.
354 base::ListValue* errors = NULL;
355 base::DictionaryValue* first_error = NULL;
356 if (error->GetListWithoutPathExpansion(kErrorErrorsKey, &errors) &&
357 errors->GetDictionary(0, &first_error)) {
358 std::string reason;
359 first_error->GetStringWithoutPathExpansion(kErrorReasonKey, &reason);
360 if (reason == kErrorReasonRateLimitExceeded ||
361 reason == kErrorReasonUserRateLimitExceeded)
362 error_code_ = HTTP_SERVICE_UNAVAILABLE;
363 }
364 }
365 }
366
367 // Handle authentication failure.
368 if (error_code_ == HTTP_UNAUTHORIZED) {
369 if (++re_authenticate_count_ <= kMaxReAuthenticateAttemptsPerRequest) {
370 // Reset re_authenticate_callback_ so Start() can be called again.
371 ReAuthenticateCallback callback = re_authenticate_callback_;
372 re_authenticate_callback_.Reset();
373 callback.Run(this);
374 return;
375 }
376
377 OnAuthFailed(error_code_);
378 return;
379 }
380
381 // Overridden by each specialization
382 ProcessURLFetchResults(source);
383 }
384
385 void UrlFetchRequestBase::OnAuthFailed(GDataErrorCode code) {
386 RunCallbackOnPrematureFailure(code);
387 sender_->RequestFinished(this);
388 }
389
390 base::WeakPtr<AuthenticatedRequestInterface>
391 UrlFetchRequestBase::GetWeakPtr() {
392 return weak_ptr_factory_.GetWeakPtr();
393 }
394
395 //============================ EntryActionRequest ============================
396
397 EntryActionRequest::EntryActionRequest(RequestSender* sender,
398 const EntryActionCallback& callback)
399 : UrlFetchRequestBase(sender),
400 callback_(callback) {
401 DCHECK(!callback_.is_null());
402 }
403
404 EntryActionRequest::~EntryActionRequest() {}
405
406 void EntryActionRequest::ProcessURLFetchResults(const URLFetcher* source) {
407 callback_.Run(GetErrorCode());
408 OnProcessURLFetchResultsComplete();
409 }
410
411 void EntryActionRequest::RunCallbackOnPrematureFailure(GDataErrorCode code) {
412 callback_.Run(code);
413 }
414
415 //============================== GetDataRequest ==============================
416
417 GetDataRequest::GetDataRequest(RequestSender* sender,
418 const GetDataCallback& callback)
419 : UrlFetchRequestBase(sender),
420 callback_(callback),
421 weak_ptr_factory_(this) {
422 DCHECK(!callback_.is_null());
423 }
424
425 GetDataRequest::~GetDataRequest() {}
426
427 void GetDataRequest::ParseResponse(GDataErrorCode fetch_error_code,
428 const std::string& data) {
429 DCHECK(CalledOnValidThread());
430
431 VLOG(1) << "JSON received from " << GetURL().spec() << ": "
432 << data.size() << " bytes";
433 ParseJson(blocking_task_runner(),
434 data,
435 base::Bind(&GetDataRequest::OnDataParsed,
436 weak_ptr_factory_.GetWeakPtr(),
437 fetch_error_code));
438 }
439
440 void GetDataRequest::ProcessURLFetchResults(const URLFetcher* source) {
441 GDataErrorCode fetch_error_code = GetErrorCode();
442
443 switch (fetch_error_code) {
444 case HTTP_SUCCESS:
445 case HTTP_CREATED:
446 ParseResponse(fetch_error_code, response_writer()->data());
447 break;
448 default:
449 RunCallbackOnPrematureFailure(fetch_error_code);
450 OnProcessURLFetchResultsComplete();
451 break;
452 }
453 }
454
455 void GetDataRequest::RunCallbackOnPrematureFailure(
456 GDataErrorCode fetch_error_code) {
457 callback_.Run(fetch_error_code, scoped_ptr<base::Value>());
458 }
459
460 void GetDataRequest::OnDataParsed(GDataErrorCode fetch_error_code,
461 scoped_ptr<base::Value> value) {
462 DCHECK(CalledOnValidThread());
463
464 if (!value.get())
465 fetch_error_code = GDATA_PARSE_ERROR;
466
467 callback_.Run(fetch_error_code, value.Pass());
468 OnProcessURLFetchResultsComplete();
469 }
470
471 //========================= InitiateUploadRequestBase ========================
472
473 InitiateUploadRequestBase::InitiateUploadRequestBase(
474 RequestSender* sender,
475 const InitiateUploadCallback& callback,
476 const std::string& content_type,
477 int64 content_length)
478 : UrlFetchRequestBase(sender),
479 callback_(callback),
480 content_type_(content_type),
481 content_length_(content_length) {
482 DCHECK(!callback_.is_null());
483 DCHECK(!content_type_.empty());
484 DCHECK_GE(content_length_, 0);
485 }
486
487 InitiateUploadRequestBase::~InitiateUploadRequestBase() {}
488
489 void InitiateUploadRequestBase::ProcessURLFetchResults(
490 const URLFetcher* source) {
491 GDataErrorCode code = GetErrorCode();
492
493 std::string upload_location;
494 if (code == HTTP_SUCCESS) {
495 // Retrieve value of the first "Location" header.
496 source->GetResponseHeaders()->EnumerateHeader(NULL,
497 kUploadResponseLocation,
498 &upload_location);
499 }
500
501 callback_.Run(code, GURL(upload_location));
502 OnProcessURLFetchResultsComplete();
503 }
504
505 void InitiateUploadRequestBase::RunCallbackOnPrematureFailure(
506 GDataErrorCode code) {
507 callback_.Run(code, GURL());
508 }
509
510 std::vector<std::string>
511 InitiateUploadRequestBase::GetExtraRequestHeaders() const {
512 std::vector<std::string> headers;
513 headers.push_back(kUploadContentType + content_type_);
514 headers.push_back(
515 kUploadContentLength + base::Int64ToString(content_length_));
516 return headers;
517 }
518
519 //============================ UploadRangeResponse =============================
520
521 UploadRangeResponse::UploadRangeResponse()
522 : code(HTTP_SUCCESS),
523 start_position_received(0),
524 end_position_received(0) {
525 }
526
527 UploadRangeResponse::UploadRangeResponse(GDataErrorCode code,
528 int64 start_position_received,
529 int64 end_position_received)
530 : code(code),
531 start_position_received(start_position_received),
532 end_position_received(end_position_received) {
533 }
534
535 UploadRangeResponse::~UploadRangeResponse() {
536 }
537
538 //========================== UploadRangeRequestBase ==========================
539
540 UploadRangeRequestBase::UploadRangeRequestBase(RequestSender* sender,
541 const GURL& upload_url)
542 : UrlFetchRequestBase(sender),
543 upload_url_(upload_url),
544 weak_ptr_factory_(this) {
545 }
546
547 UploadRangeRequestBase::~UploadRangeRequestBase() {}
548
549 GURL UploadRangeRequestBase::GetURL() const {
550 // This is very tricky to get json from this request. To do that, &alt=json
551 // has to be appended not here but in InitiateUploadRequestBase::GetURL().
552 return upload_url_;
553 }
554
555 URLFetcher::RequestType UploadRangeRequestBase::GetRequestType() const {
556 return URLFetcher::PUT;
557 }
558
559 void UploadRangeRequestBase::ProcessURLFetchResults(
560 const URLFetcher* source) {
561 GDataErrorCode code = GetErrorCode();
562 net::HttpResponseHeaders* hdrs = source->GetResponseHeaders();
563
564 if (code == HTTP_RESUME_INCOMPLETE) {
565 // Retrieve value of the first "Range" header.
566 // The Range header is appeared only if there is at least one received
567 // byte. So, initialize the positions by 0 so that the [0,0) will be
568 // returned via the |callback_| for empty data case.
569 int64 start_position_received = 0;
570 int64 end_position_received = 0;
571 std::string range_received;
572 hdrs->EnumerateHeader(NULL, kUploadResponseRange, &range_received);
573 if (!range_received.empty()) { // Parse the range header.
574 std::vector<net::HttpByteRange> ranges;
575 if (net::HttpUtil::ParseRangeHeader(range_received, &ranges) &&
576 !ranges.empty() ) {
577 // We only care about the first start-end pair in the range.
578 //
579 // Range header represents the range inclusively, while we are treating
580 // ranges exclusively (i.e., end_position_received should be one passed
581 // the last valid index). So "+ 1" is added.
582 start_position_received = ranges[0].first_byte_position();
583 end_position_received = ranges[0].last_byte_position() + 1;
584 }
585 }
586 // The Range header has the received data range, so the start position
587 // should be always 0.
588 DCHECK_EQ(start_position_received, 0);
589
590 OnRangeRequestComplete(UploadRangeResponse(code,
591 start_position_received,
592 end_position_received),
593 scoped_ptr<base::Value>());
594
595 OnProcessURLFetchResultsComplete();
596 } else if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
597 // The upload is successfully done. Parse the response which should be
598 // the entry's metadata.
599 ParseJson(blocking_task_runner(),
600 response_writer()->data(),
601 base::Bind(&UploadRangeRequestBase::OnDataParsed,
602 weak_ptr_factory_.GetWeakPtr(),
603 code));
604 } else {
605 // Failed to upload. Run callbacks to notify the error.
606 OnRangeRequestComplete(
607 UploadRangeResponse(code, -1, -1), scoped_ptr<base::Value>());
608 OnProcessURLFetchResultsComplete();
609 }
610 }
611
612 void UploadRangeRequestBase::OnDataParsed(GDataErrorCode code,
613 scoped_ptr<base::Value> value) {
614 DCHECK(CalledOnValidThread());
615 DCHECK(code == HTTP_CREATED || code == HTTP_SUCCESS);
616
617 OnRangeRequestComplete(UploadRangeResponse(code, -1, -1), value.Pass());
618 OnProcessURLFetchResultsComplete();
619 }
620
621 void UploadRangeRequestBase::RunCallbackOnPrematureFailure(
622 GDataErrorCode code) {
623 OnRangeRequestComplete(
624 UploadRangeResponse(code, 0, 0), scoped_ptr<base::Value>());
625 }
626
627 //========================== ResumeUploadRequestBase =========================
628
629 ResumeUploadRequestBase::ResumeUploadRequestBase(
630 RequestSender* sender,
631 const GURL& upload_location,
632 int64 start_position,
633 int64 end_position,
634 int64 content_length,
635 const std::string& content_type,
636 const base::FilePath& local_file_path)
637 : UploadRangeRequestBase(sender, upload_location),
638 start_position_(start_position),
639 end_position_(end_position),
640 content_length_(content_length),
641 content_type_(content_type),
642 local_file_path_(local_file_path) {
643 DCHECK_LE(start_position_, end_position_);
644 }
645
646 ResumeUploadRequestBase::~ResumeUploadRequestBase() {}
647
648 std::vector<std::string>
649 ResumeUploadRequestBase::GetExtraRequestHeaders() const {
650 if (content_length_ == 0) {
651 // For uploading an empty document, just PUT an empty content.
652 DCHECK_EQ(start_position_, 0);
653 DCHECK_EQ(end_position_, 0);
654 return std::vector<std::string>();
655 }
656
657 // The header looks like
658 // Content-Range: bytes <start_position>-<end_position>/<content_length>
659 // for example:
660 // Content-Range: bytes 7864320-8388607/13851821
661 // The header takes inclusive range, so we adjust by "end_position - 1".
662 DCHECK_GE(start_position_, 0);
663 DCHECK_GT(end_position_, 0);
664 DCHECK_GE(content_length_, 0);
665
666 std::vector<std::string> headers;
667 headers.push_back(
668 std::string(kUploadContentRange) +
669 base::Int64ToString(start_position_) + "-" +
670 base::Int64ToString(end_position_ - 1) + "/" +
671 base::Int64ToString(content_length_));
672 return headers;
673 }
674
675 bool ResumeUploadRequestBase::GetContentFile(
676 base::FilePath* local_file_path,
677 int64* range_offset,
678 int64* range_length,
679 std::string* upload_content_type) {
680 if (start_position_ == end_position_) {
681 // No content data.
682 return false;
683 }
684
685 *local_file_path = local_file_path_;
686 *range_offset = start_position_;
687 *range_length = end_position_ - start_position_;
688 *upload_content_type = content_type_;
689 return true;
690 }
691
692 //======================== GetUploadStatusRequestBase ========================
693
694 GetUploadStatusRequestBase::GetUploadStatusRequestBase(RequestSender* sender,
695 const GURL& upload_url,
696 int64 content_length)
697 : UploadRangeRequestBase(sender, upload_url),
698 content_length_(content_length) {}
699
700 GetUploadStatusRequestBase::~GetUploadStatusRequestBase() {}
701
702 std::vector<std::string>
703 GetUploadStatusRequestBase::GetExtraRequestHeaders() const {
704 // The header looks like
705 // Content-Range: bytes */<content_length>
706 // for example:
707 // Content-Range: bytes */13851821
708 DCHECK_GE(content_length_, 0);
709
710 std::vector<std::string> headers;
711 headers.push_back(
712 std::string(kUploadContentRange) + "*/" +
713 base::Int64ToString(content_length_));
714 return headers;
715 }
716
717 //============================ DownloadFileRequestBase =========================
718
719 DownloadFileRequestBase::DownloadFileRequestBase(
720 RequestSender* sender,
721 const DownloadActionCallback& download_action_callback,
722 const GetContentCallback& get_content_callback,
723 const ProgressCallback& progress_callback,
724 const GURL& download_url,
725 const base::FilePath& output_file_path)
726 : UrlFetchRequestBase(sender),
727 download_action_callback_(download_action_callback),
728 get_content_callback_(get_content_callback),
729 progress_callback_(progress_callback),
730 download_url_(download_url),
731 output_file_path_(output_file_path) {
732 DCHECK(!download_action_callback_.is_null());
733 DCHECK(!output_file_path_.empty());
734 // get_content_callback may be null.
735 }
736
737 DownloadFileRequestBase::~DownloadFileRequestBase() {}
738
739 // Overridden from UrlFetchRequestBase.
740 GURL DownloadFileRequestBase::GetURL() const {
741 return download_url_;
742 }
743
744 void DownloadFileRequestBase::GetOutputFilePath(
745 base::FilePath* local_file_path,
746 GetContentCallback* get_content_callback) {
747 // Configure so that the downloaded content is saved to |output_file_path_|.
748 *local_file_path = output_file_path_;
749 *get_content_callback = get_content_callback_;
750 }
751
752 void DownloadFileRequestBase::OnURLFetchDownloadProgress(
753 const URLFetcher* source,
754 int64 current,
755 int64 total) {
756 if (!progress_callback_.is_null())
757 progress_callback_.Run(current, total);
758 }
759
760 void DownloadFileRequestBase::ProcessURLFetchResults(const URLFetcher* source) {
761 GDataErrorCode code = GetErrorCode();
762
763 // Take over the ownership of the the downloaded temp file.
764 base::FilePath temp_file;
765 if (code == HTTP_SUCCESS) {
766 response_writer()->DisownFile();
767 temp_file = output_file_path_;
768 }
769
770 download_action_callback_.Run(code, temp_file);
771 OnProcessURLFetchResultsComplete();
772 }
773
774 void DownloadFileRequestBase::RunCallbackOnPrematureFailure(
775 GDataErrorCode code) {
776 download_action_callback_.Run(code, base::FilePath());
777 }
778
779 } // namespace google_apis
OLDNEW
« no previous file with comments | « chrome/browser/google_apis/base_requests.h ('k') | chrome/browser/google_apis/base_requests_server_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698