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

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

Issue 1084523002: Files.app: Implement sending batch requests. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 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
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/drive_api_requests.h" 5 #include "google_apis/drive/drive_api_requests.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/location.h" 10 #include "base/location.h"
11 #include "base/sequenced_task_runner.h" 11 #include "base/sequenced_task_runner.h"
12 #include "base/strings/stringprintf.h"
12 #include "base/task_runner_util.h" 13 #include "base/task_runner_util.h"
13 #include "base/values.h" 14 #include "base/values.h"
14 #include "google_apis/drive/request_sender.h" 15 #include "google_apis/drive/request_sender.h"
15 #include "google_apis/drive/request_util.h" 16 #include "google_apis/drive/request_util.h"
16 #include "google_apis/drive/time_util.h" 17 #include "google_apis/drive/time_util.h"
17 #include "net/base/url_util.h" 18 #include "net/base/url_util.h"
18 19
19 namespace google_apis { 20 namespace google_apis {
20 namespace drive { 21 namespace drive {
21 namespace { 22 namespace {
22 23
24 // Format of one request in batch uploading request.
25 const char kBatchUploadRequestFormat[] =
26 "%s %s HTTP/1.1\n"
27 "Host: www.googleapis.com\n"
kinaba 2015/04/13 08:25:27 How about getting the Host domain info from UrlGen
hirono 2015/04/13 09:16:09 Done.
28 "X-Goog-Upload-Protocol: multipart\n"
29 "Content-Type: %s\n"
30 "\n"
31 "%s";
32
33 // Request header for specifying batch upload.
34 const char kBatchUploadHeader[] = "X-Goog-Upload-Protocol: batch";
35
36 // Content type of HTTP request.
37 const char kHttpContentType[] = "application/http";
38
23 // Parses the JSON value to FileResource instance and runs |callback| on the 39 // Parses the JSON value to FileResource instance and runs |callback| on the
24 // UI thread once parsing is done. 40 // UI thread once parsing is done.
25 // This is customized version of ParseJsonAndRun defined above to adapt the 41 // This is customized version of ParseJsonAndRun defined above to adapt the
26 // remaining response type. 42 // remaining response type.
27 void ParseFileResourceWithUploadRangeAndRun(const UploadRangeCallback& callback, 43 void ParseFileResourceWithUploadRangeAndRun(const UploadRangeCallback& callback,
28 const UploadRangeResponse& response, 44 const UploadRangeResponse& response,
29 scoped_ptr<base::Value> value) { 45 scoped_ptr<base::Value> value) {
30 DCHECK(!callback.is_null()); 46 DCHECK(!callback.is_null());
31 47
32 scoped_ptr<FileResource> file_resource; 48 scoped_ptr<FileResource> file_resource;
(...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after
970 } 986 }
971 987
972 //========================== BatchUploadRequest ========================== 988 //========================== BatchUploadRequest ==========================
973 989
974 BatchUploadRequest::BatchUploadRequest( 990 BatchUploadRequest::BatchUploadRequest(
975 RequestSender* sender, 991 RequestSender* sender,
976 const DriveApiUrlGenerator& url_generator) 992 const DriveApiUrlGenerator& url_generator)
977 : UrlFetchRequestBase(sender), 993 : UrlFetchRequestBase(sender),
978 sender_(sender), 994 sender_(sender),
979 url_generator_(url_generator), 995 url_generator_(url_generator),
996 committed_(false),
980 weak_ptr_factory_(this) { 997 weak_ptr_factory_(this) {
981 } 998 }
982 999
983 BatchUploadRequest::~BatchUploadRequest() { 1000 BatchUploadRequest::~BatchUploadRequest() {
984 for (const auto& child : child_requests_) { 1001 for (const auto& pair : child_requests_) {
kinaba 2015/04/13 08:25:27 Maybe: id_request_pair? for readability
hirono 2015/04/13 09:16:09 Removed this line for turning child_requests_ to v
985 // Request will be deleted in RequestFinished method. 1002 // Request will be deleted in |RequestFinished| method.
986 sender_->RequestFinished(child.request); 1003 sender_->RequestFinished(pair.second.request);
987 } 1004 }
988 } 1005 }
989 1006
990 void BatchUploadRequest::AddRequest(UrlFetchRequestBase* request) { 1007 void BatchUploadRequest::SetBoundaryForTesting(const std::string& boundary) {
1008 boundary_ = boundary;
1009 }
1010
1011 void BatchUploadRequest::AddRequest(BatchableRequestBase* request) {
kinaba 2015/04/13 08:25:27 I'm not familiar with batched request, but is it o
hirono 2015/04/13 09:16:09 The order can affect the result. I turned child_re
1012 DCHECK(CalledOnValidThread());
991 DCHECK(request); 1013 DCHECK(request);
992 child_requests_.push_back(BatchUploadChildEntry(request)); 1014 DCHECK(!child_requests_.count(request));
1015 DCHECK(!committed_);
1016 child_requests_[request] = BatchUploadChildEntry(request);
1017 request->Prepare(
1018 base::Bind(&BatchUploadRequest::OnChildRequestPrepared,
1019 weak_ptr_factory_.GetWeakPtr(),
1020 request));
1021 }
1022
1023 void BatchUploadRequest::OnChildRequestPrepared(
1024 RequestID request_id, DriveApiErrorCode result) {
1025 DCHECK(CalledOnValidThread());
1026 DCHECK(child_requests_.count(request_id));
1027 if (IsSuccessfulDriveApiErrorCode(result)) {
1028 child_requests_[request_id].prepared = true;
1029 } else {
1030 child_requests_[request_id].request->RunCallbackOnPrematureFailure(result);
1031 sender_->RequestFinished(child_requests_[request_id].request);
1032 child_requests_.erase(request_id);
1033 }
1034 MayCompletePrepare();
993 } 1035 }
994 1036
995 void BatchUploadRequest::Commit() { 1037 void BatchUploadRequest::Commit() {
996 NOTIMPLEMENTED(); 1038 DCHECK(CalledOnValidThread());
1039 DCHECK(!committed_);
1040 if (child_requests_.empty()) {
kinaba 2015/04/13 08:25:27 What about having this case as (D)CHECK? Does the
hirono 2015/04/13 09:16:09 Turned it to CHECK, and updated the comment of fun
1041 sender_->RequestFinished(this);
1042 return;
1043 }
1044 committed_ = true;
1045 MayCompletePrepare();
1046 }
1047
1048 void BatchUploadRequest::Prepare(const PrepareCallback& callback) {
1049 DCHECK(CalledOnValidThread());
1050 DCHECK(!callback.is_null());
1051 prepare_callback_ = callback;
1052 MayCompletePrepare();
1053 }
1054
1055 void BatchUploadRequest::Cancel() {
1056 for (auto& pair : child_requests_) {
1057 // Request cancel should delete the request instance.
1058 pair.second.request->Cancel();
1059 }
1060 child_requests_.clear();
1061 UrlFetchRequestBase::Cancel();
1062 }
1063
1064 void BatchUploadRequest::MayCompletePrepare() {
1065 if (!committed_ || prepare_callback_.is_null())
1066 return;
1067 for (const auto& pair : child_requests_) {
1068 if (!pair.second.prepared)
1069 return;
1070 }
1071
1072 // Build multipart body here.
1073 std::vector<ContentTypeAndData> parts;
1074 for (const auto& pair : child_requests_) {
1075 std::string type;
1076 std::string data;
1077 const bool result = pair.second.request->GetContentData(&type, &data);
1078 // Upload request must have content data.
1079 DCHECK(result);
1080
1081 const GURL url = pair.second.request->GetURL();
1082 std::string method;
1083 switch (pair.second.request->GetRequestType()) {
1084 case net::URLFetcher::POST:
1085 method = "POST";
1086 break;
1087 case net::URLFetcher::PUT:
1088 method = "PUT";
1089 break;
1090 default:
1091 NOTREACHED();
1092 break;
1093 }
1094
1095 parts.push_back(ContentTypeAndData());
1096 parts.back().type = kHttpContentType;
1097 parts.back().data = base::StringPrintf(
1098 kBatchUploadRequestFormat,
1099 method.c_str(), url.path().c_str(), type.c_str(), data.c_str());
1100 }
1101
1102 GenerateMultipartBody(MULTIPART_MIXED, boundary_, parts, &upload_content_);
1103 prepare_callback_.Run(HTTP_SUCCESS);
1104 }
1105
1106 bool BatchUploadRequest::GetContentData(std::string* upload_content_type,
1107 std::string* upload_content_data) {
1108 upload_content_type->assign(upload_content_.type);
1109 upload_content_data->assign(upload_content_.data);
1110 return true;
997 } 1111 }
998 1112
999 base::WeakPtr<BatchUploadRequest> 1113 base::WeakPtr<BatchUploadRequest>
1000 BatchUploadRequest::GetWeakPtrAsBatchUploadRequest() { 1114 BatchUploadRequest::GetWeakPtrAsBatchUploadRequest() {
1001 return weak_ptr_factory_.GetWeakPtr(); 1115 return weak_ptr_factory_.GetWeakPtr();
1002 } 1116 }
1003 1117
1004 GURL BatchUploadRequest::GetURL() const { 1118 GURL BatchUploadRequest::GetURL() const {
1005 NOTIMPLEMENTED(); 1119 return url_generator_.GetBatchUploadUrl();
1006 return GURL(); 1120 }
1121
1122 net::URLFetcher::RequestType BatchUploadRequest::GetRequestType() const {
1123 return net::URLFetcher::PUT;
1124 }
1125
1126 std::vector<std::string> BatchUploadRequest::GetExtraRequestHeaders() const {
1127 return { kBatchUploadHeader };
1007 } 1128 }
1008 1129
1009 void BatchUploadRequest::ProcessURLFetchResults(const net::URLFetcher* source) { 1130 void BatchUploadRequest::ProcessURLFetchResults(const net::URLFetcher* source) {
1010 NOTIMPLEMENTED(); 1131 if (!IsSuccessfulDriveApiErrorCode(GetErrorCode())) {
1132 RunCallbackOnPrematureFailure(GetErrorCode());
1133 sender_->RequestFinished(this);
1134 return;
1135 }
1136
1137 for (auto& entry : child_requests_) {
1138 // TODO(hirono): Split the mutlipart result and return the correct code and
1139 // body.
1140 entry.second.request->ProcessURLFetchResults(HTTP_SERVICE_UNAVAILABLE, "");
1141 // Request deletes itself after processing.
1142 }
1143
1144 child_requests_.clear();
1011 } 1145 }
1012 1146
1013 void BatchUploadRequest::RunCallbackOnPrematureFailure(DriveApiErrorCode code) { 1147 void BatchUploadRequest::RunCallbackOnPrematureFailure(DriveApiErrorCode code) {
1014 NOTIMPLEMENTED(); 1148 for (auto pair : child_requests_) {
1149 pair.second.request->RunCallbackOnPrematureFailure(code);
1150 sender_->RequestFinished(pair.second.request);
1151 }
1152 child_requests_.clear();
1015 } 1153 }
1016 1154
1017 } // namespace drive 1155 } // namespace drive
1018 } // namespace google_apis 1156 } // namespace google_apis
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698