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