Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / google_apis / drive / drive_api_requests.cc
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>
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>
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>
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>
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.
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 // Creates a Parents value which can be used as a part of request body.
117 scoped_ptr<base::DictionaryValue> CreateParentValue(
118     const std::string& file_id) {
119   scoped_ptr<base::DictionaryValue> parent(new base::DictionaryValue);
120   parent->SetString("kind", kParentLinkKind);
121   parent->SetString("id", file_id);
122   return parent.Pass();
123 }
124
125 }  // namespace
126
127 namespace drive {
128
129 //============================ DriveApiDataRequest ===========================
130
131 DriveApiDataRequest::DriveApiDataRequest(RequestSender* sender,
132                                          const GetDataCallback& callback)
133     : GetDataRequest(sender, callback) {
134 }
135
136 DriveApiDataRequest::~DriveApiDataRequest() {
137 }
138
139 GURL DriveApiDataRequest::GetURL() const {
140   GURL url = GetURLInternal();
141   if (!fields_.empty())
142     url = net::AppendOrReplaceQueryParameter(url, "fields", fields_);
143   return url;
144 }
145
146 //=============================== FilesGetRequest =============================
147
148 FilesGetRequest::FilesGetRequest(
149     RequestSender* sender,
150     const DriveApiUrlGenerator& url_generator,
151     const FileResourceCallback& callback)
152     : DriveApiDataRequest(
153           sender,
154           base::Bind(&ParseJsonAndRun<FileResource>, callback)),
155       url_generator_(url_generator) {
156   DCHECK(!callback.is_null());
157 }
158
159 FilesGetRequest::~FilesGetRequest() {}
160
161 GURL FilesGetRequest::GetURLInternal() const {
162   return url_generator_.GetFilesGetUrl(file_id_);
163 }
164
165 //============================ FilesAuthorizeRequest ===========================
166
167 FilesAuthorizeRequest::FilesAuthorizeRequest(
168     RequestSender* sender,
169     const DriveApiUrlGenerator& url_generator,
170     const FileResourceCallback& callback)
171     : DriveApiDataRequest(
172           sender,
173           base::Bind(&ParseJsonAndRun<FileResource>, callback)),
174       url_generator_(url_generator) {
175   DCHECK(!callback.is_null());
176 }
177
178 FilesAuthorizeRequest::~FilesAuthorizeRequest() {}
179
180 net::URLFetcher::RequestType FilesAuthorizeRequest::GetRequestType() const {
181   return net::URLFetcher::POST;
182 }
183
184 GURL FilesAuthorizeRequest::GetURLInternal() const {
185   return url_generator_.GetFilesAuthorizeUrl(file_id_, app_id_);
186 }
187
188 //============================ FilesInsertRequest ============================
189
190 FilesInsertRequest::FilesInsertRequest(
191     RequestSender* sender,
192     const DriveApiUrlGenerator& url_generator,
193     const FileResourceCallback& callback)
194     : DriveApiDataRequest(
195           sender,
196           base::Bind(&ParseJsonAndRun<FileResource>, callback)),
197       url_generator_(url_generator) {
198   DCHECK(!callback.is_null());
199 }
200
201 FilesInsertRequest::~FilesInsertRequest() {}
202
203 net::URLFetcher::RequestType FilesInsertRequest::GetRequestType() const {
204   return net::URLFetcher::POST;
205 }
206
207 bool FilesInsertRequest::GetContentData(std::string* upload_content_type,
208                                         std::string* upload_content) {
209   *upload_content_type = kContentTypeApplicationJson;
210
211   base::DictionaryValue root;
212
213   if (!last_viewed_by_me_date_.is_null()) {
214     root.SetString("lastViewedByMeDate",
215                    util::FormatTimeAsString(last_viewed_by_me_date_));
216   }
217
218   if (!mime_type_.empty())
219     root.SetString("mimeType", mime_type_);
220
221   if (!modified_date_.is_null())
222     root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
223
224   if (!parents_.empty()) {
225     base::ListValue* parents_value = new base::ListValue;
226     for (size_t i = 0; i < parents_.size(); ++i) {
227       base::DictionaryValue* parent = new base::DictionaryValue;
228       parent->SetString("id", parents_[i]);
229       parents_value->Append(parent);
230     }
231     root.Set("parents", parents_value);
232   }
233
234   if (!title_.empty())
235     root.SetString("title", title_);
236
237   base::JSONWriter::Write(&root, upload_content);
238   DVLOG(1) << "FilesInsert data: " << *upload_content_type << ", ["
239            << *upload_content << "]";
240   return true;
241 }
242
243 GURL FilesInsertRequest::GetURLInternal() const {
244   return url_generator_.GetFilesInsertUrl();
245 }
246
247 //============================== FilesPatchRequest ============================
248
249 FilesPatchRequest::FilesPatchRequest(
250     RequestSender* sender,
251     const DriveApiUrlGenerator& url_generator,
252     const FileResourceCallback& callback)
253     : DriveApiDataRequest(
254           sender,
255           base::Bind(&ParseJsonAndRun<FileResource>, callback)),
256       url_generator_(url_generator),
257       set_modified_date_(false),
258       update_viewed_date_(true) {
259   DCHECK(!callback.is_null());
260 }
261
262 FilesPatchRequest::~FilesPatchRequest() {}
263
264 net::URLFetcher::RequestType FilesPatchRequest::GetRequestType() const {
265   return net::URLFetcher::PATCH;
266 }
267
268 std::vector<std::string> FilesPatchRequest::GetExtraRequestHeaders() const {
269   std::vector<std::string> headers;
270   headers.push_back(util::kIfMatchAllHeader);
271   return headers;
272 }
273
274 GURL FilesPatchRequest::GetURLInternal() const {
275   return url_generator_.GetFilesPatchUrl(
276       file_id_, set_modified_date_, update_viewed_date_);
277 }
278
279 bool FilesPatchRequest::GetContentData(std::string* upload_content_type,
280                                        std::string* upload_content) {
281   if (title_.empty() &&
282       modified_date_.is_null() &&
283       last_viewed_by_me_date_.is_null() &&
284       parents_.empty())
285     return false;
286
287   *upload_content_type = kContentTypeApplicationJson;
288
289   base::DictionaryValue root;
290   if (!title_.empty())
291     root.SetString("title", title_);
292
293   if (!modified_date_.is_null())
294     root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
295
296   if (!last_viewed_by_me_date_.is_null()) {
297     root.SetString("lastViewedByMeDate",
298                    util::FormatTimeAsString(last_viewed_by_me_date_));
299   }
300
301   if (!parents_.empty()) {
302     base::ListValue* parents_value = new base::ListValue;
303     for (size_t i = 0; i < parents_.size(); ++i) {
304       base::DictionaryValue* parent = new base::DictionaryValue;
305       parent->SetString("id", parents_[i]);
306       parents_value->Append(parent);
307     }
308     root.Set("parents", parents_value);
309   }
310
311   base::JSONWriter::Write(&root, upload_content);
312   DVLOG(1) << "FilesPatch data: " << *upload_content_type << ", ["
313            << *upload_content << "]";
314   return true;
315 }
316
317 //============================= FilesCopyRequest ==============================
318
319 FilesCopyRequest::FilesCopyRequest(
320     RequestSender* sender,
321     const DriveApiUrlGenerator& url_generator,
322     const FileResourceCallback& callback)
323     : DriveApiDataRequest(
324           sender,
325           base::Bind(&ParseJsonAndRun<FileResource>, callback)),
326       url_generator_(url_generator) {
327   DCHECK(!callback.is_null());
328 }
329
330 FilesCopyRequest::~FilesCopyRequest() {
331 }
332
333 net::URLFetcher::RequestType FilesCopyRequest::GetRequestType() const {
334   return net::URLFetcher::POST;
335 }
336
337 GURL FilesCopyRequest::GetURLInternal() const {
338   return url_generator_.GetFilesCopyUrl(file_id_);
339 }
340
341 bool FilesCopyRequest::GetContentData(std::string* upload_content_type,
342                                       std::string* upload_content) {
343   if (parents_.empty() && title_.empty())
344     return false;
345
346   *upload_content_type = kContentTypeApplicationJson;
347
348   base::DictionaryValue root;
349
350   if (!modified_date_.is_null())
351     root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
352
353   if (!parents_.empty()) {
354     base::ListValue* parents_value = new base::ListValue;
355     for (size_t i = 0; i < parents_.size(); ++i) {
356       base::DictionaryValue* parent = new base::DictionaryValue;
357       parent->SetString("id", parents_[i]);
358       parents_value->Append(parent);
359     }
360     root.Set("parents", parents_value);
361   }
362
363   if (!title_.empty())
364     root.SetString("title", title_);
365
366   base::JSONWriter::Write(&root, upload_content);
367   DVLOG(1) << "FilesCopy data: " << *upload_content_type << ", ["
368            << *upload_content << "]";
369   return true;
370 }
371
372 //============================= FilesListRequest =============================
373
374 FilesListRequest::FilesListRequest(
375     RequestSender* sender,
376     const DriveApiUrlGenerator& url_generator,
377     const FileListCallback& callback)
378     : DriveApiDataRequest(
379           sender,
380           base::Bind(&ParseJsonOnBlockingPoolAndRun<FileList>,
381                      make_scoped_refptr(sender->blocking_task_runner()),
382                      callback)),
383       url_generator_(url_generator),
384       max_results_(100) {
385   DCHECK(!callback.is_null());
386 }
387
388 FilesListRequest::~FilesListRequest() {}
389
390 GURL FilesListRequest::GetURLInternal() const {
391   return url_generator_.GetFilesListUrl(max_results_, page_token_, q_);
392 }
393
394 //======================== FilesListNextPageRequest =========================
395
396 FilesListNextPageRequest::FilesListNextPageRequest(
397     RequestSender* sender,
398     const FileListCallback& callback)
399     : DriveApiDataRequest(
400           sender,
401           base::Bind(&ParseJsonOnBlockingPoolAndRun<FileList>,
402                      make_scoped_refptr(sender->blocking_task_runner()),
403                      callback)) {
404   DCHECK(!callback.is_null());
405 }
406
407 FilesListNextPageRequest::~FilesListNextPageRequest() {
408 }
409
410 GURL FilesListNextPageRequest::GetURLInternal() const {
411   return next_link_;
412 }
413
414 //============================ FilesDeleteRequest =============================
415
416 FilesDeleteRequest::FilesDeleteRequest(
417     RequestSender* sender,
418     const DriveApiUrlGenerator& url_generator,
419     const EntryActionCallback& callback)
420     : EntryActionRequest(sender, callback),
421       url_generator_(url_generator) {
422   DCHECK(!callback.is_null());
423 }
424
425 FilesDeleteRequest::~FilesDeleteRequest() {}
426
427 net::URLFetcher::RequestType FilesDeleteRequest::GetRequestType() const {
428   return net::URLFetcher::DELETE_REQUEST;
429 }
430
431 GURL FilesDeleteRequest::GetURL() const {
432   return url_generator_.GetFilesDeleteUrl(file_id_);
433 }
434
435 std::vector<std::string> FilesDeleteRequest::GetExtraRequestHeaders() const {
436   std::vector<std::string> headers(
437       EntryActionRequest::GetExtraRequestHeaders());
438   headers.push_back(util::GenerateIfMatchHeader(etag_));
439   return headers;
440 }
441
442 //============================ FilesTrashRequest =============================
443
444 FilesTrashRequest::FilesTrashRequest(
445     RequestSender* sender,
446     const DriveApiUrlGenerator& url_generator,
447     const FileResourceCallback& callback)
448     : DriveApiDataRequest(
449           sender,
450           base::Bind(&ParseJsonAndRun<FileResource>, callback)),
451       url_generator_(url_generator) {
452   DCHECK(!callback.is_null());
453 }
454
455 FilesTrashRequest::~FilesTrashRequest() {}
456
457 net::URLFetcher::RequestType FilesTrashRequest::GetRequestType() const {
458   return net::URLFetcher::POST;
459 }
460
461 GURL FilesTrashRequest::GetURLInternal() const {
462   return url_generator_.GetFilesTrashUrl(file_id_);
463 }
464
465 //============================== AboutGetRequest =============================
466
467 AboutGetRequest::AboutGetRequest(
468     RequestSender* sender,
469     const DriveApiUrlGenerator& url_generator,
470     const AboutResourceCallback& callback)
471     : DriveApiDataRequest(
472           sender,
473           base::Bind(&ParseJsonAndRun<AboutResource>, callback)),
474       url_generator_(url_generator) {
475   DCHECK(!callback.is_null());
476 }
477
478 AboutGetRequest::~AboutGetRequest() {}
479
480 GURL AboutGetRequest::GetURLInternal() const {
481   return url_generator_.GetAboutGetUrl();
482 }
483
484 //============================ ChangesListRequest ===========================
485
486 ChangesListRequest::ChangesListRequest(
487     RequestSender* sender,
488     const DriveApiUrlGenerator& url_generator,
489     const ChangeListCallback& callback)
490     : DriveApiDataRequest(
491           sender,
492           base::Bind(&ParseJsonOnBlockingPoolAndRun<ChangeList>,
493                      make_scoped_refptr(sender->blocking_task_runner()),
494                      callback)),
495       url_generator_(url_generator),
496       include_deleted_(true),
497       max_results_(100),
498       start_change_id_(0) {
499   DCHECK(!callback.is_null());
500 }
501
502 ChangesListRequest::~ChangesListRequest() {}
503
504 GURL ChangesListRequest::GetURLInternal() const {
505   return url_generator_.GetChangesListUrl(
506       include_deleted_, max_results_, page_token_, start_change_id_);
507 }
508
509 //======================== ChangesListNextPageRequest =========================
510
511 ChangesListNextPageRequest::ChangesListNextPageRequest(
512     RequestSender* sender,
513     const ChangeListCallback& callback)
514     : DriveApiDataRequest(
515           sender,
516           base::Bind(&ParseJsonOnBlockingPoolAndRun<ChangeList>,
517                      make_scoped_refptr(sender->blocking_task_runner()),
518                      callback)) {
519   DCHECK(!callback.is_null());
520 }
521
522 ChangesListNextPageRequest::~ChangesListNextPageRequest() {
523 }
524
525 GURL ChangesListNextPageRequest::GetURLInternal() const {
526   return next_link_;
527 }
528
529 //============================== AppsListRequest ===========================
530
531 AppsListRequest::AppsListRequest(
532     RequestSender* sender,
533     const DriveApiUrlGenerator& url_generator,
534     bool use_internal_endpoint,
535     const AppListCallback& callback)
536     : DriveApiDataRequest(
537           sender,
538           base::Bind(&ParseJsonAndRun<AppList>, callback)),
539       url_generator_(url_generator),
540       use_internal_endpoint_(use_internal_endpoint) {
541   DCHECK(!callback.is_null());
542 }
543
544 AppsListRequest::~AppsListRequest() {}
545
546 GURL AppsListRequest::GetURLInternal() const {
547   return url_generator_.GetAppsListUrl(use_internal_endpoint_);
548 }
549
550 //============================== AppsDeleteRequest ===========================
551
552 AppsDeleteRequest::AppsDeleteRequest(RequestSender* sender,
553                                      const DriveApiUrlGenerator& url_generator,
554                                      const EntryActionCallback& callback)
555     : EntryActionRequest(sender, callback),
556       url_generator_(url_generator) {
557   DCHECK(!callback.is_null());
558 }
559
560 AppsDeleteRequest::~AppsDeleteRequest() {}
561
562 net::URLFetcher::RequestType AppsDeleteRequest::GetRequestType() const {
563   return net::URLFetcher::DELETE_REQUEST;
564 }
565
566 GURL AppsDeleteRequest::GetURL() const {
567   return url_generator_.GetAppsDeleteUrl(app_id_);
568 }
569
570 //========================== ChildrenInsertRequest ============================
571
572 ChildrenInsertRequest::ChildrenInsertRequest(
573     RequestSender* sender,
574     const DriveApiUrlGenerator& url_generator,
575     const EntryActionCallback& callback)
576     : EntryActionRequest(sender, callback),
577       url_generator_(url_generator) {
578   DCHECK(!callback.is_null());
579 }
580
581 ChildrenInsertRequest::~ChildrenInsertRequest() {}
582
583 net::URLFetcher::RequestType ChildrenInsertRequest::GetRequestType() const {
584   return net::URLFetcher::POST;
585 }
586
587 GURL ChildrenInsertRequest::GetURL() const {
588   return url_generator_.GetChildrenInsertUrl(folder_id_);
589 }
590
591 bool ChildrenInsertRequest::GetContentData(std::string* upload_content_type,
592                                            std::string* upload_content) {
593   *upload_content_type = kContentTypeApplicationJson;
594
595   base::DictionaryValue root;
596   root.SetString("id", id_);
597
598   base::JSONWriter::Write(&root, upload_content);
599   DVLOG(1) << "InsertResource data: " << *upload_content_type << ", ["
600            << *upload_content << "]";
601   return true;
602 }
603
604 //========================== ChildrenDeleteRequest ============================
605
606 ChildrenDeleteRequest::ChildrenDeleteRequest(
607     RequestSender* sender,
608     const DriveApiUrlGenerator& url_generator,
609     const EntryActionCallback& callback)
610     : EntryActionRequest(sender, callback),
611       url_generator_(url_generator) {
612   DCHECK(!callback.is_null());
613 }
614
615 ChildrenDeleteRequest::~ChildrenDeleteRequest() {}
616
617 net::URLFetcher::RequestType ChildrenDeleteRequest::GetRequestType() const {
618   return net::URLFetcher::DELETE_REQUEST;
619 }
620
621 GURL ChildrenDeleteRequest::GetURL() const {
622   return url_generator_.GetChildrenDeleteUrl(child_id_, folder_id_);
623 }
624
625 //======================= InitiateUploadNewFileRequest =======================
626
627 InitiateUploadNewFileRequest::InitiateUploadNewFileRequest(
628     RequestSender* sender,
629     const DriveApiUrlGenerator& url_generator,
630     const std::string& content_type,
631     int64 content_length,
632     const std::string& parent_resource_id,
633     const std::string& title,
634     const InitiateUploadCallback& callback)
635     : InitiateUploadRequestBase(sender,
636                                 callback,
637                                 content_type,
638                                 content_length),
639       url_generator_(url_generator),
640       parent_resource_id_(parent_resource_id),
641       title_(title) {
642 }
643
644 InitiateUploadNewFileRequest::~InitiateUploadNewFileRequest() {}
645
646 GURL InitiateUploadNewFileRequest::GetURL() const {
647   return url_generator_.GetInitiateUploadNewFileUrl(!modified_date_.is_null());
648 }
649
650 net::URLFetcher::RequestType
651 InitiateUploadNewFileRequest::GetRequestType() const {
652   return net::URLFetcher::POST;
653 }
654
655 bool InitiateUploadNewFileRequest::GetContentData(
656     std::string* upload_content_type,
657     std::string* upload_content) {
658   *upload_content_type = kContentTypeApplicationJson;
659
660   base::DictionaryValue root;
661   root.SetString("title", title_);
662
663   // Fill parent link.
664   scoped_ptr<base::ListValue> parents(new base::ListValue);
665   parents->Append(CreateParentValue(parent_resource_id_).release());
666   root.Set("parents", parents.release());
667
668   if (!modified_date_.is_null())
669     root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
670
671   if (!last_viewed_by_me_date_.is_null()) {
672     root.SetString("lastViewedByMeDate",
673                    util::FormatTimeAsString(last_viewed_by_me_date_));
674   }
675
676   base::JSONWriter::Write(&root, upload_content);
677
678   DVLOG(1) << "InitiateUploadNewFile data: " << *upload_content_type << ", ["
679            << *upload_content << "]";
680   return true;
681 }
682
683 //===================== InitiateUploadExistingFileRequest ====================
684
685 InitiateUploadExistingFileRequest::InitiateUploadExistingFileRequest(
686     RequestSender* sender,
687     const DriveApiUrlGenerator& url_generator,
688     const std::string& content_type,
689     int64 content_length,
690     const std::string& resource_id,
691     const std::string& etag,
692     const InitiateUploadCallback& callback)
693     : InitiateUploadRequestBase(sender,
694                                 callback,
695                                 content_type,
696                                 content_length),
697       url_generator_(url_generator),
698       resource_id_(resource_id),
699       etag_(etag) {
700 }
701
702 InitiateUploadExistingFileRequest::~InitiateUploadExistingFileRequest() {}
703
704 GURL InitiateUploadExistingFileRequest::GetURL() const {
705   return url_generator_.GetInitiateUploadExistingFileUrl(
706       resource_id_, !modified_date_.is_null());
707 }
708
709 net::URLFetcher::RequestType
710 InitiateUploadExistingFileRequest::GetRequestType() const {
711   return net::URLFetcher::PUT;
712 }
713
714 std::vector<std::string>
715 InitiateUploadExistingFileRequest::GetExtraRequestHeaders() const {
716   std::vector<std::string> headers(
717       InitiateUploadRequestBase::GetExtraRequestHeaders());
718   headers.push_back(util::GenerateIfMatchHeader(etag_));
719   return headers;
720 }
721
722 bool InitiateUploadExistingFileRequest::GetContentData(
723     std::string* upload_content_type,
724     std::string* upload_content) {
725   base::DictionaryValue root;
726   if (!parent_resource_id_.empty()) {
727     scoped_ptr<base::ListValue> parents(new base::ListValue);
728     parents->Append(CreateParentValue(parent_resource_id_).release());
729     root.Set("parents", parents.release());
730   }
731
732   if (!title_.empty())
733     root.SetString("title", title_);
734
735   if (!modified_date_.is_null())
736     root.SetString("modifiedDate", util::FormatTimeAsString(modified_date_));
737
738   if (!last_viewed_by_me_date_.is_null()) {
739     root.SetString("lastViewedByMeDate",
740                    util::FormatTimeAsString(last_viewed_by_me_date_));
741   }
742
743   if (root.empty())
744     return false;
745
746   *upload_content_type = kContentTypeApplicationJson;
747   base::JSONWriter::Write(&root, upload_content);
748   DVLOG(1) << "InitiateUploadExistingFile data: " << *upload_content_type
749            << ", [" << *upload_content << "]";
750   return true;
751 }
752
753 //============================ ResumeUploadRequest ===========================
754
755 ResumeUploadRequest::ResumeUploadRequest(
756     RequestSender* sender,
757     const GURL& upload_location,
758     int64 start_position,
759     int64 end_position,
760     int64 content_length,
761     const std::string& content_type,
762     const base::FilePath& local_file_path,
763     const UploadRangeCallback& callback,
764     const ProgressCallback& progress_callback)
765     : ResumeUploadRequestBase(sender,
766                               upload_location,
767                               start_position,
768                               end_position,
769                               content_length,
770                               content_type,
771                               local_file_path),
772       callback_(callback),
773       progress_callback_(progress_callback) {
774   DCHECK(!callback_.is_null());
775 }
776
777 ResumeUploadRequest::~ResumeUploadRequest() {}
778
779 void ResumeUploadRequest::OnRangeRequestComplete(
780     const UploadRangeResponse& response,
781     scoped_ptr<base::Value> value) {
782   DCHECK(CalledOnValidThread());
783   ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
784 }
785
786 void ResumeUploadRequest::OnURLFetchUploadProgress(
787     const net::URLFetcher* source, int64 current, int64 total) {
788   if (!progress_callback_.is_null())
789     progress_callback_.Run(current, total);
790 }
791
792 //========================== GetUploadStatusRequest ==========================
793
794 GetUploadStatusRequest::GetUploadStatusRequest(
795     RequestSender* sender,
796     const GURL& upload_url,
797     int64 content_length,
798     const UploadRangeCallback& callback)
799     : GetUploadStatusRequestBase(sender,
800                                  upload_url,
801                                  content_length),
802       callback_(callback) {
803   DCHECK(!callback.is_null());
804 }
805
806 GetUploadStatusRequest::~GetUploadStatusRequest() {}
807
808 void GetUploadStatusRequest::OnRangeRequestComplete(
809     const UploadRangeResponse& response,
810     scoped_ptr<base::Value> value) {
811   DCHECK(CalledOnValidThread());
812   ParseFileResourceWithUploadRangeAndRun(callback_, response, value.Pass());
813 }
814
815 //========================== DownloadFileRequest ==========================
816
817 DownloadFileRequest::DownloadFileRequest(
818     RequestSender* sender,
819     const DriveApiUrlGenerator& url_generator,
820     const std::string& resource_id,
821     const base::FilePath& output_file_path,
822     const DownloadActionCallback& download_action_callback,
823     const GetContentCallback& get_content_callback,
824     const ProgressCallback& progress_callback)
825     : DownloadFileRequestBase(
826           sender,
827           download_action_callback,
828           get_content_callback,
829           progress_callback,
830           url_generator.GenerateDownloadFileUrl(resource_id),
831           output_file_path) {
832 }
833
834 DownloadFileRequest::~DownloadFileRequest() {
835 }
836
837 }  // namespace drive
838 }  // namespace google_apis