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

Side by Side Diff: google_apis/drive/base_requests.cc

Issue 442193002: Parse Drive API responses all at once in the blocking pool. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix the cause of the regression. Created 6 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 | Annotate | Revision Log
« no previous file with comments | « google_apis/drive/base_requests.h ('k') | google_apis/drive/base_requests_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "google_apis/drive/base_requests.h" 5 #include "google_apis/drive/base_requests.h"
6 6
7 #include "base/json/json_reader.h" 7 #include "base/json/json_reader.h"
8 #include "base/location.h" 8 #include "base/location.h"
9 #include "base/sequenced_task_runner.h" 9 #include "base/sequenced_task_runner.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
(...skipping 25 matching lines...) Expand all
36 36
37 // Template for initiate upload of both GData WAPI and Drive API v2. 37 // Template for initiate upload of both GData WAPI and Drive API v2.
38 const char kUploadContentType[] = "X-Upload-Content-Type: "; 38 const char kUploadContentType[] = "X-Upload-Content-Type: ";
39 const char kUploadContentLength[] = "X-Upload-Content-Length: "; 39 const char kUploadContentLength[] = "X-Upload-Content-Length: ";
40 const char kUploadResponseLocation[] = "location"; 40 const char kUploadResponseLocation[] = "location";
41 41
42 // Template for upload data range of both GData WAPI and Drive API v2. 42 // Template for upload data range of both GData WAPI and Drive API v2.
43 const char kUploadContentRange[] = "Content-Range: bytes "; 43 const char kUploadContentRange[] = "Content-Range: bytes ";
44 const char kUploadResponseRange[] = "range"; 44 const char kUploadResponseRange[] = "range";
45 45
46 // Parse JSON string to base::Value object. 46 // Parses JSON passed in |json| on |blocking_task_runner|. Runs |callback| on
47 scoped_ptr<base::Value> ParseJsonInternal(const std::string& json) { 47 // the calling thread when finished with either success or failure.
48 int error_code = -1; 48 // The callback must not be null.
49 std::string error_message; 49 void ParseJsonOnBlockingPool(
50 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError( 50 base::TaskRunner* blocking_task_runner,
51 json, base::JSON_PARSE_RFC, &error_code, &error_message)); 51 const std::string& json,
52 52 const base::Callback<void(scoped_ptr<base::Value> value)>& callback) {
53 if (!value.get()) { 53 base::PostTaskAndReplyWithResult(
54 std::string trimmed_json; 54 blocking_task_runner,
55 if (json.size() < 80) { 55 FROM_HERE,
56 trimmed_json = json; 56 base::Bind(&google_apis::ParseJson, json),
57 } else { 57 callback);
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 } 58 }
70 59
71 // Returns response headers as a string. Returns a warning message if 60 // Returns response headers as a string. Returns a warning message if
72 // |url_fetcher| does not contain a valid response. Used only for debugging. 61 // |url_fetcher| does not contain a valid response. Used only for debugging.
73 std::string GetResponseHeadersAsString(const URLFetcher* url_fetcher) { 62 std::string GetResponseHeadersAsString(const URLFetcher* url_fetcher) {
74 // net::HttpResponseHeaders::raw_headers(), as the name implies, stores 63 // net::HttpResponseHeaders::raw_headers(), as the name implies, stores
75 // all headers in their raw format, i.e each header is null-terminated. 64 // all headers in their raw format, i.e each header is null-terminated.
76 // So logging raw_headers() only shows the first header, which is probably 65 // So logging raw_headers() only shows the first header, which is probably
77 // the status line. GetNormalizedHeaders, on the other hand, will show all 66 // the status line. GetNormalizedHeaders, on the other hand, will show all
78 // the headers, one per line, which is probably what we want. 67 // the headers, one per line, which is probably what we want.
79 std::string headers; 68 std::string headers;
80 // Check that response code indicates response headers are valid (i.e. not 69 // Check that response code indicates response headers are valid (i.e. not
81 // malformed) before we retrieve the headers. 70 // malformed) before we retrieve the headers.
82 if (url_fetcher->GetResponseCode() == URLFetcher::RESPONSE_CODE_INVALID) { 71 if (url_fetcher->GetResponseCode() == URLFetcher::RESPONSE_CODE_INVALID) {
83 headers.assign("Response headers are malformed!!"); 72 headers.assign("Response headers are malformed!!");
84 } else { 73 } else {
85 url_fetcher->GetResponseHeaders()->GetNormalizedHeaders(&headers); 74 url_fetcher->GetResponseHeaders()->GetNormalizedHeaders(&headers);
86 } 75 }
87 return headers; 76 return headers;
88 } 77 }
89 78
90 bool IsSuccessfulResponseCode(int response_code) { 79 bool IsSuccessfulResponseCode(int response_code) {
91 return 200 <= response_code && response_code <= 299; 80 return 200 <= response_code && response_code <= 299;
92 } 81 }
93 82
94 } // namespace 83 } // namespace
95 84
96 namespace google_apis { 85 namespace google_apis {
97 86
98 void ParseJson(base::TaskRunner* blocking_task_runner, 87 scoped_ptr<base::Value> ParseJson(const std::string& json) {
99 const std::string& json, 88 int error_code = -1;
100 const ParseJsonCallback& callback) { 89 std::string error_message;
101 base::PostTaskAndReplyWithResult( 90 scoped_ptr<base::Value> value(base::JSONReader::ReadAndReturnError(
102 blocking_task_runner, 91 json, base::JSON_PARSE_RFC, &error_code, &error_message));
103 FROM_HERE, 92
104 base::Bind(&ParseJsonInternal, json), 93 if (!value.get()) {
105 callback); 94 std::string trimmed_json;
95 if (json.size() < 80) {
96 trimmed_json = json;
97 } else {
98 // Take the first 50 and the last 10 bytes.
99 trimmed_json = base::StringPrintf(
100 "%s [%s bytes] %s",
101 json.substr(0, 50).c_str(),
102 base::Uint64ToString(json.size() - 60).c_str(),
103 json.substr(json.size() - 10).c_str());
104 }
105 LOG(WARNING) << "Error while parsing entry response: " << error_message
106 << ", code: " << error_code << ", json:\n" << trimmed_json;
107 }
108 return value.Pass();
106 } 109 }
107 110
108 //=========================== ResponseWriter ================================== 111 //=========================== ResponseWriter ==================================
109 ResponseWriter::ResponseWriter(base::SequencedTaskRunner* file_task_runner, 112 ResponseWriter::ResponseWriter(base::SequencedTaskRunner* file_task_runner,
110 const base::FilePath& file_path, 113 const base::FilePath& file_path,
111 const GetContentCallback& get_content_callback) 114 const GetContentCallback& get_content_callback)
112 : get_content_callback_(get_content_callback), 115 : get_content_callback_(get_content_callback),
113 weak_ptr_factory_(this) { 116 weak_ptr_factory_(this) {
114 if (!file_path.empty()) { 117 if (!file_path.empty()) {
115 file_writer_.reset( 118 file_writer_.reset(
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 DVLOG(1) << response_writer_->data(); 355 DVLOG(1) << response_writer_->data();
353 356
354 const char kErrorKey[] = "error"; 357 const char kErrorKey[] = "error";
355 const char kErrorErrorsKey[] = "errors"; 358 const char kErrorErrorsKey[] = "errors";
356 const char kErrorReasonKey[] = "reason"; 359 const char kErrorReasonKey[] = "reason";
357 const char kErrorMessageKey[] = "message"; 360 const char kErrorMessageKey[] = "message";
358 const char kErrorReasonRateLimitExceeded[] = "rateLimitExceeded"; 361 const char kErrorReasonRateLimitExceeded[] = "rateLimitExceeded";
359 const char kErrorReasonUserRateLimitExceeded[] = "userRateLimitExceeded"; 362 const char kErrorReasonUserRateLimitExceeded[] = "userRateLimitExceeded";
360 const char kErrorReasonQuotaExceeded[] = "quotaExceeded"; 363 const char kErrorReasonQuotaExceeded[] = "quotaExceeded";
361 364
362 scoped_ptr<base::Value> value(ParseJsonInternal(response_writer_->data())); 365 scoped_ptr<base::Value> value(ParseJson(response_writer_->data()));
363 base::DictionaryValue* dictionary = NULL; 366 base::DictionaryValue* dictionary = NULL;
364 base::DictionaryValue* error = NULL; 367 base::DictionaryValue* error = NULL;
365 if (value && 368 if (value &&
366 value->GetAsDictionary(&dictionary) && 369 value->GetAsDictionary(&dictionary) &&
367 dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) { 370 dictionary->GetDictionaryWithoutPathExpansion(kErrorKey, &error)) {
368 // Get error message. 371 // Get error message.
369 std::string message; 372 std::string message;
370 error->GetStringWithoutPathExpansion(kErrorMessageKey, &message); 373 error->GetStringWithoutPathExpansion(kErrorMessageKey, &message);
371 DLOG(ERROR) << "code: " << error_code_ << ", message: " << message; 374 DLOG(ERROR) << "code: " << error_code_ << ", message: " << message;
372 375
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 430
428 void EntryActionRequest::ProcessURLFetchResults(const URLFetcher* source) { 431 void EntryActionRequest::ProcessURLFetchResults(const URLFetcher* source) {
429 callback_.Run(GetErrorCode()); 432 callback_.Run(GetErrorCode());
430 OnProcessURLFetchResultsComplete(); 433 OnProcessURLFetchResultsComplete();
431 } 434 }
432 435
433 void EntryActionRequest::RunCallbackOnPrematureFailure(GDataErrorCode code) { 436 void EntryActionRequest::RunCallbackOnPrematureFailure(GDataErrorCode code) {
434 callback_.Run(code); 437 callback_.Run(code);
435 } 438 }
436 439
437 //============================== GetDataRequest ==============================
438
439 GetDataRequest::GetDataRequest(RequestSender* sender,
440 const GetDataCallback& callback)
441 : UrlFetchRequestBase(sender),
442 callback_(callback),
443 weak_ptr_factory_(this) {
444 DCHECK(!callback_.is_null());
445 }
446
447 GetDataRequest::~GetDataRequest() {}
448
449 void GetDataRequest::ParseResponse(GDataErrorCode fetch_error_code,
450 const std::string& data) {
451 DCHECK(CalledOnValidThread());
452
453 VLOG(1) << "JSON received from " << GetURL().spec() << ": "
454 << data.size() << " bytes";
455 ParseJson(blocking_task_runner(),
456 data,
457 base::Bind(&GetDataRequest::OnDataParsed,
458 weak_ptr_factory_.GetWeakPtr(),
459 fetch_error_code));
460 }
461
462 void GetDataRequest::ProcessURLFetchResults(const URLFetcher* source) {
463 GDataErrorCode fetch_error_code = GetErrorCode();
464
465 switch (fetch_error_code) {
466 case HTTP_SUCCESS:
467 case HTTP_CREATED:
468 ParseResponse(fetch_error_code, response_writer()->data());
469 break;
470 default:
471 RunCallbackOnPrematureFailure(fetch_error_code);
472 OnProcessURLFetchResultsComplete();
473 break;
474 }
475 }
476
477 void GetDataRequest::RunCallbackOnPrematureFailure(
478 GDataErrorCode fetch_error_code) {
479 callback_.Run(fetch_error_code, scoped_ptr<base::Value>());
480 }
481
482 void GetDataRequest::OnDataParsed(GDataErrorCode fetch_error_code,
483 scoped_ptr<base::Value> value) {
484 DCHECK(CalledOnValidThread());
485
486 if (!value.get())
487 fetch_error_code = GDATA_PARSE_ERROR;
488
489 callback_.Run(fetch_error_code, value.Pass());
490 OnProcessURLFetchResultsComplete();
491 }
492
493 //========================= InitiateUploadRequestBase ======================== 440 //========================= InitiateUploadRequestBase ========================
494 441
495 InitiateUploadRequestBase::InitiateUploadRequestBase( 442 InitiateUploadRequestBase::InitiateUploadRequestBase(
496 RequestSender* sender, 443 RequestSender* sender,
497 const InitiateUploadCallback& callback, 444 const InitiateUploadCallback& callback,
498 const std::string& content_type, 445 const std::string& content_type,
499 int64 content_length) 446 int64 content_length)
500 : UrlFetchRequestBase(sender), 447 : UrlFetchRequestBase(sender),
501 callback_(callback), 448 callback_(callback),
502 content_type_(content_type), 449 content_type_(content_type),
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
611 558
612 OnRangeRequestComplete(UploadRangeResponse(code, 559 OnRangeRequestComplete(UploadRangeResponse(code,
613 start_position_received, 560 start_position_received,
614 end_position_received), 561 end_position_received),
615 scoped_ptr<base::Value>()); 562 scoped_ptr<base::Value>());
616 563
617 OnProcessURLFetchResultsComplete(); 564 OnProcessURLFetchResultsComplete();
618 } else if (code == HTTP_CREATED || code == HTTP_SUCCESS) { 565 } else if (code == HTTP_CREATED || code == HTTP_SUCCESS) {
619 // The upload is successfully done. Parse the response which should be 566 // The upload is successfully done. Parse the response which should be
620 // the entry's metadata. 567 // the entry's metadata.
621 ParseJson(blocking_task_runner(), 568 ParseJsonOnBlockingPool(blocking_task_runner(),
622 response_writer()->data(), 569 response_writer()->data(),
623 base::Bind(&UploadRangeRequestBase::OnDataParsed, 570 base::Bind(&UploadRangeRequestBase::OnDataParsed,
624 weak_ptr_factory_.GetWeakPtr(), 571 weak_ptr_factory_.GetWeakPtr(),
625 code)); 572 code));
626 } else { 573 } else {
627 // Failed to upload. Run callbacks to notify the error. 574 // Failed to upload. Run callbacks to notify the error.
628 OnRangeRequestComplete( 575 OnRangeRequestComplete(
629 UploadRangeResponse(code, -1, -1), scoped_ptr<base::Value>()); 576 UploadRangeResponse(code, -1, -1), scoped_ptr<base::Value>());
630 OnProcessURLFetchResultsComplete(); 577 OnProcessURLFetchResultsComplete();
631 } 578 }
632 } 579 }
633 580
634 void UploadRangeRequestBase::OnDataParsed(GDataErrorCode code, 581 void UploadRangeRequestBase::OnDataParsed(GDataErrorCode code,
635 scoped_ptr<base::Value> value) { 582 scoped_ptr<base::Value> value) {
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
792 download_action_callback_.Run(code, temp_file); 739 download_action_callback_.Run(code, temp_file);
793 OnProcessURLFetchResultsComplete(); 740 OnProcessURLFetchResultsComplete();
794 } 741 }
795 742
796 void DownloadFileRequestBase::RunCallbackOnPrematureFailure( 743 void DownloadFileRequestBase::RunCallbackOnPrematureFailure(
797 GDataErrorCode code) { 744 GDataErrorCode code) {
798 download_action_callback_.Run(code, base::FilePath()); 745 download_action_callback_.Run(code, base::FilePath());
799 } 746 }
800 747
801 } // namespace google_apis 748 } // namespace google_apis
OLDNEW
« no previous file with comments | « google_apis/drive/base_requests.h ('k') | google_apis/drive/base_requests_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698