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 "google_apis/drive/drive_api_requests.h"
6
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/json/json_writer.h"
10 #include "base/location.h"
11 #include "base/sequenced_task_runner.h"
12 #include "base/task_runner_util.h"
13 #include "base/values.h"
14 #include "google_apis/drive/drive_api_parser.h"
15 #include "google_apis/drive/request_sender.h"
16 #include "google_apis/drive/request_util.h"
17 #include "google_apis/drive/time_util.h"
18 #include "net/base/url_util.h"
19
20 namespace google_apis {
21 namespace {
22
23 const char kContentTypeApplicationJson[] = "application/json";
24 const char kParentLinkKind[] = "drive#fileLink";
25
26 // Parses the JSON value to a resource typed |T| and runs |callback| on the UI
27 // thread once parsing is done.
28 template<typename T>
ParseJsonAndRun(const base::Callback<void (GDataErrorCode,scoped_ptr<T>)> & callback,GDataErrorCode error,scoped_ptr<base::Value> value)29 void ParseJsonAndRun(
30 const base::Callback<void(GDataErrorCode, scoped_ptr<T>)>& callback,
31 GDataErrorCode error,
32 scoped_ptr<base::Value> value) {
33 DCHECK(!callback.is_null());
34
35 scoped_ptr<T> resource;
36 if (value) {
37 resource = T::CreateFrom(*value);
38 if (!resource) {
39 // Failed to parse the JSON value, although the JSON value is available,
40 // so let the callback know the parsing error.
41 error = GDATA_PARSE_ERROR;
42 }
43 }
44
45 callback.Run(error, resource.Pass());
46 }
47
48 // Thin adapter of T::CreateFrom.
49 template<typename T>
ParseJsonOnBlockingPool(scoped_ptr<base::Value> value)50 scoped_ptr<T> ParseJsonOnBlockingPool(scoped_ptr<base::Value> value) {
51 return T::CreateFrom(*value);
52 }
53
54 // Runs |callback| with given |error| and |value|. If |value| is null,
55 // overwrites |error| to GDATA_PARSE_ERROR.
56 template<typename T>
ParseJsonOnBlockingPoolAndRunAfterBlockingPoolTask(const base::Callback<void (GDataErrorCode,scoped_ptr<T>)> & callback,GDataErrorCode error,scoped_ptr<T> value)57 void ParseJsonOnBlockingPoolAndRunAfterBlockingPoolTask(
58 const base::Callback<void(GDataErrorCode, scoped_ptr<T>)>& callback,
59 GDataErrorCode error, scoped_ptr<T> value) {
60 if (!value)
61 error = GDATA_PARSE_ERROR;
62 callback.Run(error, value.Pass());
63 }
64
65 // Parses the JSON value to a resource typed |T| and runs |callback| on
66 // blocking pool, and then run on the current thread.
67 // TODO(hidehiko): Move this and ParseJsonAndRun defined above into base with
68 // merging the tasks running on blocking pool into one.
69 template<typename T>
ParseJsonOnBlockingPoolAndRun(scoped_refptr<base::TaskRunner> blocking_task_runner,const base::Callback<void (GDataErrorCode,scoped_ptr<T>)> & callback,GDataErrorCode error,scoped_ptr<base::Value> value)70 void ParseJsonOnBlockingPoolAndRun(
71 scoped_refptr<base::TaskRunner> blocking_task_runner,
72 const base::Callback<void(GDataErrorCode, scoped_ptr<T>)>& callback,
73 GDataErrorCode error,
74 scoped_ptr<base::Value> value) {
75 DCHECK(!callback.is_null());
76
77 if (!value) {
78 callback.Run(error, scoped_ptr<T>());
79 return;
80 }
81
82 base::PostTaskAndReplyWithResult(
83 blocking_task_runner,
84 FROM_HERE,
85 base::Bind(&ParseJsonOnBlockingPool<T>, base::Passed(&value)),
86 base::Bind(&ParseJsonOnBlockingPoolAndRunAfterBlockingPoolTask<T>,
87 callback, error));
88 }
89
90 // Parses the JSON value to FileResource instance and runs |callback| on the
91 // UI thread once parsing is done.
92 // This is customized version of ParseJsonAndRun defined above to adapt the
93 // remaining response type.
ParseFileResourceWithUploadRangeAndRun(const drive::UploadRangeCallback & callback,const UploadRangeResponse & response,scoped_ptr<base::Value> value)94 void ParseFileResourceWithUploadRangeAndRun(
95 const drive::UploadRangeCallback& callback,
96 const UploadRangeResponse& response,
97 scoped_ptr<base::Value> value) {
98 DCHECK(!callback.is_null());
99
100 scoped_ptr<FileResource> file_resource;
101 if (value) {
102 file_resource = FileResource::CreateFrom(*value);
103 if (!file_resource) {
104 callback.Run(
105 UploadRangeResponse(GDATA_PARSE_ERROR,
106 response.start_position_received,
107 response.end_position_received),
108 scoped_ptr<FileResource>());
109 return;
110 }
111 }
112
113 callback.Run(response, file_resource.Pass());
114 }
115
116 } // namespace
117
118 namespace drive {
119
120 //============================ DriveApiDataRequest ===========================
121
DriveApiDataRequest(RequestSender * sender,const GetDataCallback & callback)122 DriveApiDataRequest::DriveApiDataRequest(RequestSender* sender,
123 const GetDataCallback& callback)
124 : GetDataRequest(sender, callback) {
125 }
126
~DriveApiDataRequest()127 DriveApiDataRequest::~DriveApiDataRequest() {
128 }
129
GetURL() const130 GURL DriveApiDataRequest::GetURL() const {
131 GURL url = GetURLInternal();
132 if (!fields_.empty())
133 url = net::AppendOrReplaceQueryParameter(url, "fields", fields_);
134 return url;
135 }
136
137 //=============================== FilesGetRequest =============================
138
FilesGetRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const FileResourceCallback & callback)139 FilesGetRequest::FilesGetRequest(
140 RequestSender* sender,
141 const DriveApiUrlGenerator& url_generator,
142 const FileResourceCallback& callback)
143 : DriveApiDataRequest(
144 sender,
145 base::Bind(&ParseJsonAndRun<FileResource>, callback)),
146 url_generator_(url_generator) {
147 DCHECK(!callback.is_null());
148 }
149
~FilesGetRequest()150 FilesGetRequest::~FilesGetRequest() {}
151
GetURLInternal() const152 GURL FilesGetRequest::GetURLInternal() const {
153 return url_generator_.GetFilesGetUrl(file_id_);
154 }
155
156 //============================ FilesInsertRequest ============================
157
FilesInsertRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const FileResourceCallback & callback)158 FilesInsertRequest::FilesInsertRequest(
159 RequestSender* sender,
160 const DriveApiUrlGenerator& url_generator,
161 const FileResourceCallback& callback)
162 : DriveApiDataRequest(
163 sender,
164 base::Bind(&ParseJsonAndRun<FileResource>, callback)),
165 url_generator_(url_generator) {
166 DCHECK(!callback.is_null());
167 }
168
~FilesInsertRequest()169 FilesInsertRequest::~FilesInsertRequest() {}
170
GetRequestType() const171 net::URLFetcher::RequestType FilesInsertRequest::GetRequestType() const {
172 return net::URLFetcher::POST;
173 }
174
GetContentData(std::string * upload_content_type,std::string * upload_content)175 bool FilesInsertRequest::GetContentData(std::string* upload_content_type,
176 std::string* upload_content) {
177 *upload_content_type = kContentTypeApplicationJson;
178
179 base::DictionaryValue root;
180
181 if (!mime_type_.empty())
182 root.SetString("mimeType", mime_type_);
183
184 if (!parents_.empty()) {
185 base::ListValue* parents_value = new base::ListValue;
186 for (size_t i = 0; i < parents_.size(); ++i) {
187 base::DictionaryValue* parent = new base::DictionaryValue;
188 parent->SetString("id", parents_[i]);
189 parents_value->Append(parent);
190 }
191 root.Set("parents", parents_value);
192 }
193
194 if (!title_.empty())
195 root.SetString("title", title_);
196
197 base::JSONWriter::Write(&root, upload_content);
198 DVLOG(1) << "FilesInsert data: " << *upload_content_type << ", ["
199 << *upload_content << "]";
200 return true;
201 }
202
GetURLInternal() const203 GURL FilesInsertRequest::GetURLInternal() const {
204 return url_generator_.GetFilesInsertUrl();
205 }
206
207 //============================== FilesPatchRequest ============================
208
FilesPatchRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const FileResourceCallback & callback)209 FilesPatchRequest::FilesPatchRequest(
210 RequestSender* sender,
211 const DriveApiUrlGenerator& url_generator,
212 const FileResourceCallback& callback)
213 : DriveApiDataRequest(
214 sender,
215 base::Bind(&ParseJsonAndRun<FileResource>, callback)),
216 url_generator_(url_generator),
217 set_modified_date_(false),
218 update_viewed_date_(true) {
219 DCHECK(!callback.is_null());
220 }
221
~FilesPatchRequest()222 FilesPatchRequest::~FilesPatchRequest() {}
223
GetRequestType() const224 net::URLFetcher::RequestType FilesPatchRequest::GetRequestType() const {
225 return net::URLFetcher::PATCH;
226 }
227
GetExtraRequestHeaders() const228 std::vector<std::string> FilesPatchRequest::GetExtraRequestHeaders() const {
229 std::vector<std::string> headers;
230 headers.push_back(util::kIfMatchAllHeader);
231 return headers;
232 }
233
GetURLInternal() const234 GURL FilesPatchRequest::GetURLInternal() const {
235 return url_generator_.GetFilesPatchUrl(
236 file_id_, set_modified_date_, update_viewed_date_);
237 }
238
GetContentData(std::string * upload_content_type,std::string * upload_content)239 bool FilesPatchRequest::GetContentData(std::string* upload_content_type,
240 std::string* upload_content) {
241 if (title_.empty() &&
242 modified_date_.is_null() &&
243 last_viewed_by_me_date_.is_null() &&
244 parents_.empty())
245 return false;
246
247 *upload_content_type = kContentTypeApplicationJson;
248
249 base::DictionaryValue root;
250 if (!title_.empty())
251 root.SetString("title", title_);
252
253 if (!modified_date_.is_null())
254 root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
255
256 if (!last_viewed_by_me_date_.is_null()) {
257 root.SetString("lastViewedByMeDate",
258 util::FormatTimeAsString(last_viewed_by_me_date_));
259 }
260
261 if (!parents_.empty()) {
262 base::ListValue* parents_value = new base::ListValue;
263 for (size_t i = 0; i < parents_.size(); ++i) {
264 base::DictionaryValue* parent = new base::DictionaryValue;
265 parent->SetString("id", parents_[i]);
266 parents_value->Append(parent);
267 }
268 root.Set("parents", parents_value);
269 }
270
271 base::JSONWriter::Write(&root, upload_content);
272 DVLOG(1) << "FilesPatch data: " << *upload_content_type << ", ["
273 << *upload_content << "]";
274 return true;
275 }
276
277 //============================= FilesCopyRequest ==============================
278
FilesCopyRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const FileResourceCallback & callback)279 FilesCopyRequest::FilesCopyRequest(
280 RequestSender* sender,
281 const DriveApiUrlGenerator& url_generator,
282 const FileResourceCallback& callback)
283 : DriveApiDataRequest(
284 sender,
285 base::Bind(&ParseJsonAndRun<FileResource>, callback)),
286 url_generator_(url_generator) {
287 DCHECK(!callback.is_null());
288 }
289
~FilesCopyRequest()290 FilesCopyRequest::~FilesCopyRequest() {
291 }
292
GetRequestType() const293 net::URLFetcher::RequestType FilesCopyRequest::GetRequestType() const {
294 return net::URLFetcher::POST;
295 }
296
GetURLInternal() const297 GURL FilesCopyRequest::GetURLInternal() const {
298 return url_generator_.GetFilesCopyUrl(file_id_);
299 }
300
GetContentData(std::string * upload_content_type,std::string * upload_content)301 bool FilesCopyRequest::GetContentData(std::string* upload_content_type,
302 std::string* upload_content) {
303 if (parents_.empty() && title_.empty())
304 return false;
305
306 *upload_content_type = kContentTypeApplicationJson;
307
308 base::DictionaryValue root;
309
310 if (!modified_date_.is_null())
311 root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
312
313 if (!parents_.empty()) {
314 base::ListValue* parents_value = new base::ListValue;
315 for (size_t i = 0; i < parents_.size(); ++i) {
316 base::DictionaryValue* parent = new base::DictionaryValue;
317 parent->SetString("id", parents_[i]);
318 parents_value->Append(parent);
319 }
320 root.Set("parents", parents_value);
321 }
322
323 if (!title_.empty())
324 root.SetString("title", title_);
325
326 base::JSONWriter::Write(&root, upload_content);
327 DVLOG(1) << "FilesCopy data: " << *upload_content_type << ", ["
328 << *upload_content << "]";
329 return true;
330 }
331
332 //============================= FilesListRequest =============================
333
FilesListRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const FileListCallback & callback)334 FilesListRequest::FilesListRequest(
335 RequestSender* sender,
336 const DriveApiUrlGenerator& url_generator,
337 const FileListCallback& callback)
338 : DriveApiDataRequest(
339 sender,
340 base::Bind(&ParseJsonOnBlockingPoolAndRun<FileList>,
341 make_scoped_refptr(sender->blocking_task_runner()),
342 callback)),
343 url_generator_(url_generator),
344 max_results_(100) {
345 DCHECK(!callback.is_null());
346 }
347
~FilesListRequest()348 FilesListRequest::~FilesListRequest() {}
349
GetURLInternal() const350 GURL FilesListRequest::GetURLInternal() const {
351 return url_generator_.GetFilesListUrl(max_results_, page_token_, q_);
352 }
353
354 //======================== FilesListNextPageRequest =========================
355
FilesListNextPageRequest(RequestSender * sender,const FileListCallback & callback)356 FilesListNextPageRequest::FilesListNextPageRequest(
357 RequestSender* sender,
358 const FileListCallback& callback)
359 : DriveApiDataRequest(
360 sender,
361 base::Bind(&ParseJsonOnBlockingPoolAndRun<FileList>,
362 make_scoped_refptr(sender->blocking_task_runner()),
363 callback)) {
364 DCHECK(!callback.is_null());
365 }
366
~FilesListNextPageRequest()367 FilesListNextPageRequest::~FilesListNextPageRequest() {
368 }
369
GetURLInternal() const370 GURL FilesListNextPageRequest::GetURLInternal() const {
371 return next_link_;
372 }
373
374 //============================ FilesDeleteRequest =============================
375
FilesDeleteRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const EntryActionCallback & callback)376 FilesDeleteRequest::FilesDeleteRequest(
377 RequestSender* sender,
378 const DriveApiUrlGenerator& url_generator,
379 const EntryActionCallback& callback)
380 : EntryActionRequest(sender, callback),
381 url_generator_(url_generator) {
382 DCHECK(!callback.is_null());
383 }
384
~FilesDeleteRequest()385 FilesDeleteRequest::~FilesDeleteRequest() {}
386
GetRequestType() const387 net::URLFetcher::RequestType FilesDeleteRequest::GetRequestType() const {
388 return net::URLFetcher::DELETE_REQUEST;
389 }
390
GetURL() const391 GURL FilesDeleteRequest::GetURL() const {
392 return url_generator_.GetFilesDeleteUrl(file_id_);
393 }
394
GetExtraRequestHeaders() const395 std::vector<std::string> FilesDeleteRequest::GetExtraRequestHeaders() const {
396 std::vector<std::string> headers(
397 EntryActionRequest::GetExtraRequestHeaders());
398 headers.push_back(util::GenerateIfMatchHeader(etag_));
399 return headers;
400 }
401
402 //============================ FilesTrashRequest =============================
403
FilesTrashRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const FileResourceCallback & callback)404 FilesTrashRequest::FilesTrashRequest(
405 RequestSender* sender,
406 const DriveApiUrlGenerator& url_generator,
407 const FileResourceCallback& callback)
408 : DriveApiDataRequest(
409 sender,
410 base::Bind(&ParseJsonAndRun<FileResource>, callback)),
411 url_generator_(url_generator) {
412 DCHECK(!callback.is_null());
413 }
414
~FilesTrashRequest()415 FilesTrashRequest::~FilesTrashRequest() {}
416
GetRequestType() const417 net::URLFetcher::RequestType FilesTrashRequest::GetRequestType() const {
418 return net::URLFetcher::POST;
419 }
420
GetURLInternal() const421 GURL FilesTrashRequest::GetURLInternal() const {
422 return url_generator_.GetFilesTrashUrl(file_id_);
423 }
424
425 //============================== AboutGetRequest =============================
426
AboutGetRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const AboutResourceCallback & callback)427 AboutGetRequest::AboutGetRequest(
428 RequestSender* sender,
429 const DriveApiUrlGenerator& url_generator,
430 const AboutResourceCallback& callback)
431 : DriveApiDataRequest(
432 sender,
433 base::Bind(&ParseJsonAndRun<AboutResource>, callback)),
434 url_generator_(url_generator) {
435 DCHECK(!callback.is_null());
436 }
437
~AboutGetRequest()438 AboutGetRequest::~AboutGetRequest() {}
439
GetURLInternal() const440 GURL AboutGetRequest::GetURLInternal() const {
441 return url_generator_.GetAboutGetUrl();
442 }
443
444 //============================ ChangesListRequest ===========================
445
ChangesListRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const ChangeListCallback & callback)446 ChangesListRequest::ChangesListRequest(
447 RequestSender* sender,
448 const DriveApiUrlGenerator& url_generator,
449 const ChangeListCallback& callback)
450 : DriveApiDataRequest(
451 sender,
452 base::Bind(&ParseJsonOnBlockingPoolAndRun<ChangeList>,
453 make_scoped_refptr(sender->blocking_task_runner()),
454 callback)),
455 url_generator_(url_generator),
456 include_deleted_(true),
457 max_results_(100),
458 start_change_id_(0) {
459 DCHECK(!callback.is_null());
460 }
461
~ChangesListRequest()462 ChangesListRequest::~ChangesListRequest() {}
463
GetURLInternal() const464 GURL ChangesListRequest::GetURLInternal() const {
465 return url_generator_.GetChangesListUrl(
466 include_deleted_, max_results_, page_token_, start_change_id_);
467 }
468
469 //======================== ChangesListNextPageRequest =========================
470
ChangesListNextPageRequest(RequestSender * sender,const ChangeListCallback & callback)471 ChangesListNextPageRequest::ChangesListNextPageRequest(
472 RequestSender* sender,
473 const ChangeListCallback& callback)
474 : DriveApiDataRequest(
475 sender,
476 base::Bind(&ParseJsonOnBlockingPoolAndRun<ChangeList>,
477 make_scoped_refptr(sender->blocking_task_runner()),
478 callback)) {
479 DCHECK(!callback.is_null());
480 }
481
~ChangesListNextPageRequest()482 ChangesListNextPageRequest::~ChangesListNextPageRequest() {
483 }
484
GetURLInternal() const485 GURL ChangesListNextPageRequest::GetURLInternal() const {
486 return next_link_;
487 }
488
489 //============================== AppsListRequest ===========================
490
AppsListRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const AppListCallback & callback)491 AppsListRequest::AppsListRequest(
492 RequestSender* sender,
493 const DriveApiUrlGenerator& url_generator,
494 const AppListCallback& callback)
495 : DriveApiDataRequest(
496 sender,
497 base::Bind(&ParseJsonAndRun<AppList>, callback)),
498 url_generator_(url_generator) {
499 DCHECK(!callback.is_null());
500 }
501
~AppsListRequest()502 AppsListRequest::~AppsListRequest() {}
503
GetURLInternal() const504 GURL AppsListRequest::GetURLInternal() const {
505 return url_generator_.GetAppsListUrl();
506 }
507
508 //========================== ChildrenInsertRequest ============================
509
ChildrenInsertRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const EntryActionCallback & callback)510 ChildrenInsertRequest::ChildrenInsertRequest(
511 RequestSender* sender,
512 const DriveApiUrlGenerator& url_generator,
513 const EntryActionCallback& callback)
514 : EntryActionRequest(sender, callback),
515 url_generator_(url_generator) {
516 DCHECK(!callback.is_null());
517 }
518
~ChildrenInsertRequest()519 ChildrenInsertRequest::~ChildrenInsertRequest() {}
520
GetRequestType() const521 net::URLFetcher::RequestType ChildrenInsertRequest::GetRequestType() const {
522 return net::URLFetcher::POST;
523 }
524
GetURL() const525 GURL ChildrenInsertRequest::GetURL() const {
526 return url_generator_.GetChildrenInsertUrl(folder_id_);
527 }
528
GetContentData(std::string * upload_content_type,std::string * upload_content)529 bool ChildrenInsertRequest::GetContentData(std::string* upload_content_type,
530 std::string* upload_content) {
531 *upload_content_type = kContentTypeApplicationJson;
532
533 base::DictionaryValue root;
534 root.SetString("id", id_);
535
536 base::JSONWriter::Write(&root, upload_content);
537 DVLOG(1) << "InsertResource data: " << *upload_content_type << ", ["
538 << *upload_content << "]";
539 return true;
540 }
541
542 //========================== ChildrenDeleteRequest ============================
543
ChildrenDeleteRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const EntryActionCallback & callback)544 ChildrenDeleteRequest::ChildrenDeleteRequest(
545 RequestSender* sender,
546 const DriveApiUrlGenerator& url_generator,
547 const EntryActionCallback& callback)
548 : EntryActionRequest(sender, callback),
549 url_generator_(url_generator) {
550 DCHECK(!callback.is_null());
551 }
552
~ChildrenDeleteRequest()553 ChildrenDeleteRequest::~ChildrenDeleteRequest() {}
554
GetRequestType() const555 net::URLFetcher::RequestType ChildrenDeleteRequest::GetRequestType() const {
556 return net::URLFetcher::DELETE_REQUEST;
557 }
558
GetURL() const559 GURL ChildrenDeleteRequest::GetURL() const {
560 return url_generator_.GetChildrenDeleteUrl(child_id_, folder_id_);
561 }
562
563 //======================= InitiateUploadNewFileRequest =======================
564
InitiateUploadNewFileRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const std::string & content_type,int64 content_length,const std::string & parent_resource_id,const std::string & title,const InitiateUploadCallback & callback)565 InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
566 RequestSender* sender,
567 const DriveApiUrlGenerator& url_generator,
568 const std::string& content_type,
569 int64 content_length,
570 const std::string& parent_resource_id,
571 const std::string& title,
572 const InitiateUploadCallback& callback)
573 : InitiateUploadRequestBase(sender,
574 callback,
575 content_type,
576 content_length),
577 url_generator_(url_generator),
578 parent_resource_id_(parent_resource_id),
579 title_(title) {
580 }
581
~InitiateUploadNewFileRequest()582 InitiateUploadNewFileRequest::~InitiateUploadNewFileRequest() {}
583
GetURL() const584 GURL InitiateUploadNewFileRequest::GetURL() const {
585 return url_generator_.GetInitiateUploadNewFileUrl();
586 }
587
588 net::URLFetcher::RequestType
GetRequestType() const589 InitiateUploadNewFileRequest::GetRequestType() const {
590 return net::URLFetcher::POST;
591 }
592
GetContentData(std::string * upload_content_type,std::string * upload_content)593 bool InitiateUploadNewFileRequest::GetContentData(
594 std::string* upload_content_type,
595 std::string* upload_content) {
596 *upload_content_type = kContentTypeApplicationJson;
597
598 base::DictionaryValue root;
599 root.SetString("title", title_);
600
601 // Fill parent link.
602 {
603 scoped_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
604 parent->SetString("kind", kParentLinkKind);
605 parent->SetString("id", parent_resource_id_);
606
607 scoped_ptr<base::ListValue> parents(new base::ListValue);
608 parents->Append(parent.release());
609
610 root.Set("parents", parents.release());
611 }
612
613 base::JSONWriter::Write(&root, upload_content);
614
615 DVLOG(1) << "InitiateUploadNewFile data: " << *upload_content_type << ", ["
616 << *upload_content << "]";
617 return true;
618 }
619
620 //===================== InitiateUploadExistingFileRequest ====================
621
InitiateUploadExistingFileRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const std::string & content_type,int64 content_length,const std::string & resource_id,const std::string & etag,const InitiateUploadCallback & callback)622 InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
623 RequestSender* sender,
624 const DriveApiUrlGenerator& url_generator,
625 const std::string& content_type,
626 int64 content_length,
627 const std::string& resource_id,
628 const std::string& etag,
629 const InitiateUploadCallback& callback)
630 : InitiateUploadRequestBase(sender,
631 callback,
632 content_type,
633 content_length),
634 url_generator_(url_generator),
635 resource_id_(resource_id),
636 etag_(etag) {
637 }
638
~InitiateUploadExistingFileRequest()639 InitiateUploadExistingFileRequest::~InitiateUploadExistingFileRequest() {}
640
GetURL() const641 GURL InitiateUploadExistingFileRequest::GetURL() const {
642 return url_generator_.GetInitiateUploadExistingFileUrl(resource_id_);
643 }
644
645 net::URLFetcher::RequestType
GetRequestType() const646 InitiateUploadExistingFileRequest::GetRequestType() const {
647 return net::URLFetcher::PUT;
648 }
649
650 std::vector<std::string>
GetExtraRequestHeaders() const651 InitiateUploadExistingFileRequest::GetExtraRequestHeaders() const {
652 std::vector<std::string> headers(
653 InitiateUploadRequestBase::GetExtraRequestHeaders());
654 headers.push_back(util::GenerateIfMatchHeader(etag_));
655 return headers;
656 }
657
658 //============================ ResumeUploadRequest ===========================
659
ResumeUploadRequest(RequestSender * sender,const GURL & upload_location,int64 start_position,int64 end_position,int64 content_length,const std::string & content_type,const base::FilePath & local_file_path,const UploadRangeCallback & callback,const ProgressCallback & progress_callback)660 ResumeUploadRequest::ResumeUploadRequest(
661 RequestSender* sender,
662 const GURL& upload_location,
663 int64 start_position,
664 int64 end_position,
665 int64 content_length,
666 const std::string& content_type,
667 const base::FilePath& local_file_path,
668 const UploadRangeCallback& callback,
669 const ProgressCallback& progress_callback)
670 : ResumeUploadRequestBase(sender,
671 upload_location,
672 start_position,
673 end_position,
674 content_length,
675 content_type,
676 local_file_path),
677 callback_(callback),
678 progress_callback_(progress_callback) {
679 DCHECK(!callback_.is_null());
680 }
681
~ResumeUploadRequest()682 ResumeUploadRequest::~ResumeUploadRequest() {}
683
OnRangeRequestComplete(const UploadRangeResponse & response,scoped_ptr<base::Value> value)684 void ResumeUploadRequest::OnRangeRequestComplete(
685 const UploadRangeResponse& response,
686 scoped_ptr<base::Value> value) {
687 DCHECK(CalledOnValidThread());
688 ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
689 }
690
OnURLFetchUploadProgress(const net::URLFetcher * source,int64 current,int64 total)691 void ResumeUploadRequest::OnURLFetchUploadProgress(
692 const net::URLFetcher* source, int64 current, int64 total) {
693 if (!progress_callback_.is_null())
694 progress_callback_.Run(current, total);
695 }
696
697 //========================== GetUploadStatusRequest ==========================
698
GetUploadStatusRequest(RequestSender * sender,const GURL & upload_url,int64 content_length,const UploadRangeCallback & callback)699 GetUploadStatusRequest::GetUploadStatusRequest(
700 RequestSender* sender,
701 const GURL& upload_url,
702 int64 content_length,
703 const UploadRangeCallback& callback)
704 : GetUploadStatusRequestBase(sender,
705 upload_url,
706 content_length),
707 callback_(callback) {
708 DCHECK(!callback.is_null());
709 }
710
~GetUploadStatusRequest()711 GetUploadStatusRequest::~GetUploadStatusRequest() {}
712
OnRangeRequestComplete(const UploadRangeResponse & response,scoped_ptr<base::Value> value)713 void GetUploadStatusRequest::OnRangeRequestComplete(
714 const UploadRangeResponse& response,
715 scoped_ptr<base::Value> value) {
716 DCHECK(CalledOnValidThread());
717 ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
718 }
719
720 //========================== DownloadFileRequest ==========================
721
DownloadFileRequest(RequestSender * sender,const DriveApiUrlGenerator & url_generator,const std::string & resource_id,const base::FilePath & output_file_path,const DownloadActionCallback & download_action_callback,const GetContentCallback & get_content_callback,const ProgressCallback & progress_callback)722 DownloadFileRequest::DownloadFileRequest(
723 RequestSender* sender,
724 const DriveApiUrlGenerator& url_generator,
725 const std::string& resource_id,
726 const base::FilePath& output_file_path,
727 const DownloadActionCallback& download_action_callback,
728 const GetContentCallback& get_content_callback,
729 const ProgressCallback& progress_callback)
730 : DownloadFileRequestBase(
731 sender,
732 download_action_callback,
733 get_content_callback,
734 progress_callback,
735 url_generator.GenerateDownloadFileUrl(resource_id),
736 output_file_path) {
737 }
738
~DownloadFileRequest()739 DownloadFileRequest::~DownloadFileRequest() {
740 }
741
742 } // namespace drive
743 } // namespace google_apis
744