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/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 //========================== PermissionsInsertRequest ==========================
    838 
    839 PermissionsInsertRequest::PermissionsInsertRequest(
    840     RequestSender* sender,
    841     const DriveApiUrlGenerator& url_generator,
    842     const EntryActionCallback& callback)
    843     : EntryActionRequest(sender, callback),
    844       url_generator_(url_generator),
    845       type_(PERMISSION_TYPE_USER),
    846       role_(PERMISSION_ROLE_READER) {
    847 }
    848 
    849 PermissionsInsertRequest::~PermissionsInsertRequest() {
    850 }
    851 
    852 GURL PermissionsInsertRequest::GetURL() const {
    853   return url_generator_.GetPermissionsInsertUrl(id_);
    854 }
    855 
    856 net::URLFetcher::RequestType
    857 PermissionsInsertRequest::GetRequestType() const {
    858   return net::URLFetcher::POST;
    859 }
    860 
    861 bool PermissionsInsertRequest::GetContentData(std::string* upload_content_type,
    862                                               std::string* upload_content) {
    863   *upload_content_type = kContentTypeApplicationJson;
    864 
    865   base::DictionaryValue root;
    866   switch (type_) {
    867     case PERMISSION_TYPE_ANYONE:
    868       root.SetString("type", "anyone");
    869       break;
    870     case PERMISSION_TYPE_DOMAIN:
    871       root.SetString("type", "domain");
    872       break;
    873     case PERMISSION_TYPE_GROUP:
    874       root.SetString("type", "group");
    875       break;
    876     case PERMISSION_TYPE_USER:
    877       root.SetString("type", "user");
    878       break;
    879   }
    880   switch (role_) {
    881     case PERMISSION_ROLE_OWNER:
    882       root.SetString("role", "owner");
    883       break;
    884     case PERMISSION_ROLE_READER:
    885       root.SetString("role", "reader");
    886       break;
    887     case PERMISSION_ROLE_WRITER:
    888       root.SetString("role", "writer");
    889       break;
    890     case PERMISSION_ROLE_COMMENTER:
    891       root.SetString("role", "reader");
    892       {
    893         base::ListValue* list = new base::ListValue;
    894         list->AppendString("commenter");
    895         root.Set("additionalRoles", list);
    896       }
    897       break;
    898   }
    899   root.SetString("value", value_);
    900   base::JSONWriter::Write(&root, upload_content);
    901   return true;
    902 }
    903 
    904 }  // namespace drive
    905 }  // namespace google_apis
    906