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