drive_api_service.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 "chrome/browser/drive/drive_api_service.h" 6 7#include <string> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/strings/stringprintf.h" 12#include "base/task_runner_util.h" 13#include "base/values.h" 14#include "chrome/browser/drive/drive_api_util.h" 15#include "chrome/browser/google_apis/auth_service.h" 16#include "chrome/browser/google_apis/drive_api_parser.h" 17#include "chrome/browser/google_apis/drive_api_requests.h" 18#include "chrome/browser/google_apis/gdata_wapi_parser.h" 19#include "chrome/browser/google_apis/request_sender.h" 20#include "content/public/browser/browser_thread.h" 21 22using content::BrowserThread; 23using google_apis::AppList; 24using google_apis::AuthorizeAppCallback; 25using google_apis::CancelCallback; 26using google_apis::ChangeList; 27using google_apis::DownloadActionCallback; 28using google_apis::EntryActionCallback; 29using google_apis::FileList; 30using google_apis::FileResource; 31using google_apis::GDATA_OTHER_ERROR; 32using google_apis::GDATA_PARSE_ERROR; 33using google_apis::GDataErrorCode; 34using google_apis::GetAboutRequest; 35using google_apis::GetAboutResourceCallback; 36using google_apis::GetAppListCallback; 37using google_apis::GetApplistRequest; 38using google_apis::GetChangelistRequest; 39using google_apis::GetContentCallback; 40using google_apis::GetFileRequest; 41using google_apis::GetFilelistRequest; 42using google_apis::GetResourceEntryCallback; 43using google_apis::GetResourceListCallback; 44using google_apis::HTTP_SUCCESS; 45using google_apis::InitiateUploadCallback; 46using google_apis::ProgressCallback; 47using google_apis::RequestSender; 48using google_apis::ResourceEntry; 49using google_apis::ResourceList; 50using google_apis::UploadRangeCallback; 51using google_apis::UploadRangeResponse; 52using google_apis::drive::ContinueGetFileListRequest; 53using google_apis::drive::CopyResourceRequest; 54using google_apis::drive::CreateDirectoryRequest; 55using google_apis::drive::DeleteResourceRequest; 56using google_apis::drive::DownloadFileRequest; 57using google_apis::drive::GetUploadStatusRequest; 58using google_apis::drive::InitiateUploadExistingFileRequest; 59using google_apis::drive::InitiateUploadNewFileRequest; 60using google_apis::drive::InsertResourceRequest; 61using google_apis::drive::RenameResourceRequest; 62using google_apis::drive::ResumeUploadRequest; 63using google_apis::drive::TouchResourceRequest; 64using google_apis::drive::TrashResourceRequest; 65 66namespace drive { 67 68namespace { 69 70// OAuth2 scopes for Drive API. 71const char kDriveScope[] = "https://www.googleapis.com/auth/drive"; 72const char kDriveAppsReadonlyScope[] = 73 "https://www.googleapis.com/auth/drive.apps.readonly"; 74 75// Expected max number of files resources in a http request. 76// Be careful not to use something too small because it might overload the 77// server. Be careful not to use something too large because it takes longer 78// time to fetch the result without UI response. 79const int kMaxNumFilesResourcePerRequest = 500; 80const int kMaxNumFilesResourcePerRequestForSearch = 50; 81 82scoped_ptr<ResourceList> ParseChangeListJsonToResourceList( 83 scoped_ptr<base::Value> value) { 84 scoped_ptr<ChangeList> change_list(ChangeList::CreateFrom(*value)); 85 if (!change_list) { 86 return scoped_ptr<ResourceList>(); 87 } 88 89 return ResourceList::CreateFromChangeList(*change_list); 90} 91 92scoped_ptr<ResourceList> ParseFileListJsonToResourceList( 93 scoped_ptr<base::Value> value) { 94 scoped_ptr<FileList> file_list(FileList::CreateFrom(*value)); 95 if (!file_list) { 96 return scoped_ptr<ResourceList>(); 97 } 98 99 return ResourceList::CreateFromFileList(*file_list); 100} 101 102// Parses JSON value representing either ChangeList or FileList into 103// ResourceList. 104scoped_ptr<ResourceList> ParseResourceListOnBlockingPool( 105 scoped_ptr<base::Value> value) { 106 DCHECK(value); 107 108 // Dispatch the parsing based on kind field. 109 if (ChangeList::HasChangeListKind(*value)) { 110 return ParseChangeListJsonToResourceList(value.Pass()); 111 } 112 if (FileList::HasFileListKind(*value)) { 113 return ParseFileListJsonToResourceList(value.Pass()); 114 } 115 116 // The value type is unknown, so give up to parse and return an error. 117 return scoped_ptr<ResourceList>(); 118} 119 120// Callback invoked when the parsing of resource list is completed, 121// regardless whether it is succeeded or not. 122void DidParseResourceListOnBlockingPool( 123 const GetResourceListCallback& callback, 124 scoped_ptr<ResourceList> resource_list) { 125 GDataErrorCode error = resource_list ? HTTP_SUCCESS : GDATA_PARSE_ERROR; 126 callback.Run(error, resource_list.Pass()); 127} 128 129// Sends a task to parse the JSON value into ResourceList on blocking pool, 130// with a callback which is called when the task is done. 131void ParseResourceListOnBlockingPoolAndRun( 132 scoped_refptr<base::TaskRunner> blocking_task_runner, 133 const GetResourceListCallback& callback, 134 GDataErrorCode error, 135 scoped_ptr<base::Value> value) { 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 137 DCHECK(!callback.is_null()); 138 139 if (error != HTTP_SUCCESS) { 140 // An error occurs, so run callback immediately. 141 callback.Run(error, scoped_ptr<ResourceList>()); 142 return; 143 } 144 145 PostTaskAndReplyWithResult( 146 blocking_task_runner.get(), 147 FROM_HERE, 148 base::Bind(&ParseResourceListOnBlockingPool, base::Passed(&value)), 149 base::Bind(&DidParseResourceListOnBlockingPool, callback)); 150} 151 152// Parses the FileResource value to ResourceEntry and runs |callback| on the 153// UI thread. 154void ParseResourceEntryAndRun( 155 const GetResourceEntryCallback& callback, 156 GDataErrorCode error, 157 scoped_ptr<FileResource> value) { 158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 159 DCHECK(!callback.is_null()); 160 161 if (!value) { 162 callback.Run(error, scoped_ptr<ResourceEntry>()); 163 return; 164 } 165 166 // Converting to ResourceEntry is cheap enough to do on UI thread. 167 scoped_ptr<ResourceEntry> entry = 168 ResourceEntry::CreateFromFileResource(*value); 169 if (!entry) { 170 callback.Run(GDATA_PARSE_ERROR, scoped_ptr<ResourceEntry>()); 171 return; 172 } 173 174 callback.Run(error, entry.Pass()); 175} 176 177// Parses the JSON value to AppList runs |callback| on the UI thread 178// once parsing is done. 179void ParseAppListAndRun(const google_apis::GetAppListCallback& callback, 180 google_apis::GDataErrorCode error, 181 scoped_ptr<base::Value> value) { 182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 183 DCHECK(!callback.is_null()); 184 185 if (!value) { 186 callback.Run(error, scoped_ptr<google_apis::AppList>()); 187 return; 188 } 189 190 // Parsing AppList is cheap enough to do on UI thread. 191 scoped_ptr<google_apis::AppList> app_list = 192 google_apis::AppList::CreateFrom(*value); 193 if (!app_list) { 194 callback.Run(google_apis::GDATA_PARSE_ERROR, 195 scoped_ptr<google_apis::AppList>()); 196 return; 197 } 198 199 callback.Run(error, app_list.Pass()); 200} 201 202// Parses the FileResource value to ResourceEntry for upload range request, 203// and runs |callback| on the UI thread. 204void ParseResourceEntryForUploadRangeAndRun( 205 const UploadRangeCallback& callback, 206 const UploadRangeResponse& response, 207 scoped_ptr<FileResource> value) { 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 209 DCHECK(!callback.is_null()); 210 211 if (!value) { 212 callback.Run(response, scoped_ptr<ResourceEntry>()); 213 return; 214 } 215 216 // Converting to ResourceEntry is cheap enough to do on UI thread. 217 scoped_ptr<ResourceEntry> entry = 218 ResourceEntry::CreateFromFileResource(*value); 219 if (!entry) { 220 callback.Run(UploadRangeResponse(GDATA_PARSE_ERROR, 221 response.start_position_received, 222 response.end_position_received), 223 scoped_ptr<ResourceEntry>()); 224 return; 225 } 226 227 callback.Run(response, entry.Pass()); 228} 229 230void ExtractOpenUrlAndRun(const std::string& app_id, 231 const AuthorizeAppCallback& callback, 232 GDataErrorCode error, 233 scoped_ptr<FileResource> value) { 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 235 DCHECK(!callback.is_null()); 236 237 if (!value) { 238 callback.Run(error, GURL()); 239 return; 240 } 241 242 const std::vector<FileResource::OpenWithLink>& open_with_links = 243 value->open_with_links(); 244 for (size_t i = 0; i < open_with_links.size(); ++i) { 245 if (open_with_links[i].app_id == app_id) { 246 callback.Run(HTTP_SUCCESS, open_with_links[i].open_url); 247 return; 248 } 249 } 250 251 // Not found. 252 callback.Run(GDATA_OTHER_ERROR, GURL()); 253} 254 255// The resource ID for the root directory for Drive API is defined in the spec: 256// https://developers.google.com/drive/folder 257const char kDriveApiRootDirectoryResourceId[] = "root"; 258 259} // namespace 260 261DriveAPIService::DriveAPIService( 262 net::URLRequestContextGetter* url_request_context_getter, 263 base::TaskRunner* blocking_task_runner, 264 const GURL& base_url, 265 const GURL& base_download_url, 266 const std::string& custom_user_agent) 267 : url_request_context_getter_(url_request_context_getter), 268 blocking_task_runner_(blocking_task_runner), 269 profile_(NULL), 270 url_generator_(base_url, base_download_url), 271 custom_user_agent_(custom_user_agent) { 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 273} 274 275DriveAPIService::~DriveAPIService() { 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 277 if (sender_.get()) 278 sender_->auth_service()->RemoveObserver(this); 279} 280 281void DriveAPIService::Initialize(Profile* profile) { 282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 283 profile_ = profile; 284 285 std::vector<std::string> scopes; 286 scopes.push_back(kDriveScope); 287 scopes.push_back(kDriveAppsReadonlyScope); 288 sender_.reset(new RequestSender(profile, 289 url_request_context_getter_, 290 scopes, 291 custom_user_agent_)); 292 sender_->Initialize(); 293 294 sender_->auth_service()->AddObserver(this); 295} 296 297void DriveAPIService::AddObserver(DriveServiceObserver* observer) { 298 observers_.AddObserver(observer); 299} 300 301void DriveAPIService::RemoveObserver(DriveServiceObserver* observer) { 302 observers_.RemoveObserver(observer); 303} 304 305bool DriveAPIService::CanSendRequest() const { 306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 307 308 return HasRefreshToken(); 309} 310 311std::string DriveAPIService::CanonicalizeResourceId( 312 const std::string& resource_id) const { 313 return drive::util::CanonicalizeResourceId(resource_id); 314} 315 316std::string DriveAPIService::GetRootResourceId() const { 317 return kDriveApiRootDirectoryResourceId; 318} 319 320CancelCallback DriveAPIService::GetAllResourceList( 321 const GetResourceListCallback& callback) { 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 323 DCHECK(!callback.is_null()); 324 325 // The simplest way to fetch the all resources list looks files.list method, 326 // but it seems impossible to know the returned list's changestamp. 327 // Thus, instead, we use changes.list method with includeDeleted=false here. 328 // The returned list should contain only resources currently existing. 329 return sender_->StartRequestWithRetry( 330 new GetChangelistRequest( 331 sender_.get(), 332 url_generator_, 333 false, // include deleted 334 0, 335 kMaxNumFilesResourcePerRequest, 336 base::Bind(&ParseResourceListOnBlockingPoolAndRun, 337 blocking_task_runner_, 338 callback))); 339} 340 341CancelCallback DriveAPIService::GetResourceListInDirectory( 342 const std::string& directory_resource_id, 343 const GetResourceListCallback& callback) { 344 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 345 DCHECK(!directory_resource_id.empty()); 346 DCHECK(!callback.is_null()); 347 348 // Because children.list method on Drive API v2 returns only the list of 349 // children's references, but we need all file resource list. 350 // So, here we use files.list method instead, with setting parents query. 351 // After the migration from GData WAPI to Drive API v2, we should clean the 352 // code up by moving the responsibility to include "parents" in the query 353 // to client side. 354 // We aren't interested in files in trash in this context, neither. 355 return sender_->StartRequestWithRetry( 356 new GetFilelistRequest( 357 sender_.get(), 358 url_generator_, 359 base::StringPrintf( 360 "'%s' in parents and trashed = false", 361 drive::util::EscapeQueryStringValue( 362 directory_resource_id).c_str()), 363 kMaxNumFilesResourcePerRequest, 364 base::Bind(&ParseResourceListOnBlockingPoolAndRun, 365 blocking_task_runner_, 366 callback))); 367} 368 369CancelCallback DriveAPIService::Search( 370 const std::string& search_query, 371 const GetResourceListCallback& callback) { 372 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 373 DCHECK(!search_query.empty()); 374 DCHECK(!callback.is_null()); 375 376 return sender_->StartRequestWithRetry( 377 new GetFilelistRequest( 378 sender_.get(), 379 url_generator_, 380 drive::util::TranslateQuery(search_query), 381 kMaxNumFilesResourcePerRequestForSearch, 382 base::Bind(&ParseResourceListOnBlockingPoolAndRun, 383 blocking_task_runner_, 384 callback))); 385} 386 387CancelCallback DriveAPIService::SearchByTitle( 388 const std::string& title, 389 const std::string& directory_resource_id, 390 const GetResourceListCallback& callback) { 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 392 DCHECK(!title.empty()); 393 DCHECK(!callback.is_null()); 394 395 std::string query; 396 base::StringAppendF(&query, "title = '%s'", 397 drive::util::EscapeQueryStringValue(title).c_str()); 398 if (!directory_resource_id.empty()) { 399 base::StringAppendF( 400 &query, " and '%s' in parents", 401 drive::util::EscapeQueryStringValue(directory_resource_id).c_str()); 402 } 403 query += " and trashed = false"; 404 405 return sender_->StartRequestWithRetry( 406 new GetFilelistRequest( 407 sender_.get(), 408 url_generator_, 409 query, 410 kMaxNumFilesResourcePerRequest, 411 base::Bind(&ParseResourceListOnBlockingPoolAndRun, 412 blocking_task_runner_, 413 callback))); 414} 415 416CancelCallback DriveAPIService::GetChangeList( 417 int64 start_changestamp, 418 const GetResourceListCallback& callback) { 419 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 420 DCHECK(!callback.is_null()); 421 422 return sender_->StartRequestWithRetry( 423 new GetChangelistRequest( 424 sender_.get(), 425 url_generator_, 426 true, // include deleted 427 start_changestamp, 428 kMaxNumFilesResourcePerRequest, 429 base::Bind(&ParseResourceListOnBlockingPoolAndRun, 430 blocking_task_runner_, 431 callback))); 432} 433 434CancelCallback DriveAPIService::ContinueGetResourceList( 435 const GURL& override_url, 436 const GetResourceListCallback& callback) { 437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 438 DCHECK(!callback.is_null()); 439 440 return sender_->StartRequestWithRetry( 441 new ContinueGetFileListRequest( 442 sender_.get(), 443 override_url, 444 base::Bind(&ParseResourceListOnBlockingPoolAndRun, 445 blocking_task_runner_, 446 callback))); 447} 448 449CancelCallback DriveAPIService::GetResourceEntry( 450 const std::string& resource_id, 451 const GetResourceEntryCallback& callback) { 452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 453 DCHECK(!callback.is_null()); 454 455 return sender_->StartRequestWithRetry(new GetFileRequest( 456 sender_.get(), 457 url_generator_, 458 resource_id, 459 base::Bind(&ParseResourceEntryAndRun, callback))); 460} 461 462CancelCallback DriveAPIService::GetAboutResource( 463 const GetAboutResourceCallback& callback) { 464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 465 DCHECK(!callback.is_null()); 466 467 return sender_->StartRequestWithRetry( 468 new GetAboutRequest( 469 sender_.get(), 470 url_generator_, 471 callback)); 472} 473 474CancelCallback DriveAPIService::GetAppList(const GetAppListCallback& callback) { 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 476 DCHECK(!callback.is_null()); 477 478 return sender_->StartRequestWithRetry(new GetApplistRequest( 479 sender_.get(), 480 url_generator_, 481 base::Bind(&ParseAppListAndRun, callback))); 482} 483 484CancelCallback DriveAPIService::DownloadFile( 485 const base::FilePath& local_cache_path, 486 const std::string& resource_id, 487 const DownloadActionCallback& download_action_callback, 488 const GetContentCallback& get_content_callback, 489 const ProgressCallback& progress_callback) { 490 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 491 DCHECK(!download_action_callback.is_null()); 492 // get_content_callback may be null. 493 494 return sender_->StartRequestWithRetry( 495 new DownloadFileRequest(sender_.get(), 496 url_generator_, 497 resource_id, 498 local_cache_path, 499 download_action_callback, 500 get_content_callback, 501 progress_callback)); 502} 503 504CancelCallback DriveAPIService::DeleteResource( 505 const std::string& resource_id, 506 const std::string& etag, 507 const EntryActionCallback& callback) { 508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 509 DCHECK(!callback.is_null()); 510 511 return sender_->StartRequestWithRetry(new TrashResourceRequest( 512 sender_.get(), 513 url_generator_, 514 resource_id, 515 callback)); 516} 517 518CancelCallback DriveAPIService::AddNewDirectory( 519 const std::string& parent_resource_id, 520 const std::string& directory_name, 521 const GetResourceEntryCallback& callback) { 522 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 523 DCHECK(!callback.is_null()); 524 525 return sender_->StartRequestWithRetry( 526 new CreateDirectoryRequest( 527 sender_.get(), 528 url_generator_, 529 parent_resource_id, 530 directory_name, 531 base::Bind(&ParseResourceEntryAndRun, callback))); 532} 533 534CancelCallback DriveAPIService::CopyResource( 535 const std::string& resource_id, 536 const std::string& parent_resource_id, 537 const std::string& new_name, 538 const GetResourceEntryCallback& callback) { 539 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 540 DCHECK(!callback.is_null()); 541 542 return sender_->StartRequestWithRetry( 543 new CopyResourceRequest( 544 sender_.get(), 545 url_generator_, 546 resource_id, 547 parent_resource_id, 548 new_name, 549 base::Bind(&ParseResourceEntryAndRun, callback))); 550} 551 552CancelCallback DriveAPIService::CopyHostedDocument( 553 const std::string& resource_id, 554 const std::string& new_name, 555 const GetResourceEntryCallback& callback) { 556 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 557 DCHECK(!callback.is_null()); 558 559 return sender_->StartRequestWithRetry( 560 new CopyResourceRequest( 561 sender_.get(), 562 url_generator_, 563 resource_id, 564 std::string(), // parent_resource_id. 565 new_name, 566 base::Bind(&ParseResourceEntryAndRun, callback))); 567} 568 569CancelCallback DriveAPIService::RenameResource( 570 const std::string& resource_id, 571 const std::string& new_name, 572 const EntryActionCallback& callback) { 573 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 574 DCHECK(!callback.is_null()); 575 576 return sender_->StartRequestWithRetry( 577 new RenameResourceRequest( 578 sender_.get(), 579 url_generator_, 580 resource_id, 581 new_name, 582 callback)); 583} 584 585CancelCallback DriveAPIService::TouchResource( 586 const std::string& resource_id, 587 const base::Time& modified_date, 588 const base::Time& last_viewed_by_me_date, 589 const GetResourceEntryCallback& callback) { 590 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 591 DCHECK(!modified_date.is_null()); 592 DCHECK(!last_viewed_by_me_date.is_null()); 593 DCHECK(!callback.is_null()); 594 595 return sender_->StartRequestWithRetry( 596 new TouchResourceRequest( 597 sender_.get(), 598 url_generator_, 599 resource_id, 600 modified_date, 601 last_viewed_by_me_date, 602 base::Bind(&ParseResourceEntryAndRun, callback))); 603} 604 605CancelCallback DriveAPIService::AddResourceToDirectory( 606 const std::string& parent_resource_id, 607 const std::string& resource_id, 608 const EntryActionCallback& callback) { 609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 610 DCHECK(!callback.is_null()); 611 612 return sender_->StartRequestWithRetry( 613 new InsertResourceRequest( 614 sender_.get(), 615 url_generator_, 616 parent_resource_id, 617 resource_id, 618 callback)); 619} 620 621CancelCallback DriveAPIService::RemoveResourceFromDirectory( 622 const std::string& parent_resource_id, 623 const std::string& resource_id, 624 const EntryActionCallback& callback) { 625 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 626 DCHECK(!callback.is_null()); 627 628 return sender_->StartRequestWithRetry( 629 new DeleteResourceRequest( 630 sender_.get(), 631 url_generator_, 632 parent_resource_id, 633 resource_id, 634 callback)); 635} 636 637CancelCallback DriveAPIService::InitiateUploadNewFile( 638 const std::string& content_type, 639 int64 content_length, 640 const std::string& parent_resource_id, 641 const std::string& title, 642 const InitiateUploadCallback& callback) { 643 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 644 DCHECK(!callback.is_null()); 645 646 return sender_->StartRequestWithRetry( 647 new InitiateUploadNewFileRequest( 648 sender_.get(), 649 url_generator_, 650 content_type, 651 content_length, 652 parent_resource_id, 653 title, 654 callback)); 655} 656 657CancelCallback DriveAPIService::InitiateUploadExistingFile( 658 const std::string& content_type, 659 int64 content_length, 660 const std::string& resource_id, 661 const std::string& etag, 662 const InitiateUploadCallback& callback) { 663 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 664 DCHECK(!callback.is_null()); 665 666 return sender_->StartRequestWithRetry( 667 new InitiateUploadExistingFileRequest( 668 sender_.get(), 669 url_generator_, 670 content_type, 671 content_length, 672 resource_id, 673 etag, 674 callback)); 675} 676 677CancelCallback DriveAPIService::ResumeUpload( 678 const GURL& upload_url, 679 int64 start_position, 680 int64 end_position, 681 int64 content_length, 682 const std::string& content_type, 683 const base::FilePath& local_file_path, 684 const UploadRangeCallback& callback, 685 const ProgressCallback& progress_callback) { 686 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 687 DCHECK(!callback.is_null()); 688 689 return sender_->StartRequestWithRetry( 690 new ResumeUploadRequest( 691 sender_.get(), 692 upload_url, 693 start_position, 694 end_position, 695 content_length, 696 content_type, 697 local_file_path, 698 base::Bind(&ParseResourceEntryForUploadRangeAndRun, callback), 699 progress_callback)); 700} 701 702CancelCallback DriveAPIService::GetUploadStatus( 703 const GURL& upload_url, 704 int64 content_length, 705 const UploadRangeCallback& callback) { 706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 707 DCHECK(!callback.is_null()); 708 709 return sender_->StartRequestWithRetry(new GetUploadStatusRequest( 710 sender_.get(), 711 upload_url, 712 content_length, 713 base::Bind(&ParseResourceEntryForUploadRangeAndRun, callback))); 714} 715 716CancelCallback DriveAPIService::AuthorizeApp( 717 const std::string& resource_id, 718 const std::string& app_id, 719 const AuthorizeAppCallback& callback) { 720 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 721 DCHECK(!callback.is_null()); 722 723 return sender_->StartRequestWithRetry(new GetFileRequest( 724 sender_.get(), 725 url_generator_, 726 resource_id, 727 base::Bind(&ExtractOpenUrlAndRun, app_id, callback))); 728} 729 730bool DriveAPIService::HasAccessToken() const { 731 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 732 733 return sender_->auth_service()->HasAccessToken(); 734} 735 736bool DriveAPIService::HasRefreshToken() const { 737 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 738 739 return sender_->auth_service()->HasRefreshToken(); 740} 741 742void DriveAPIService::ClearAccessToken() { 743 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 744 return sender_->auth_service()->ClearAccessToken(); 745} 746 747void DriveAPIService::ClearRefreshToken() { 748 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 749 return sender_->auth_service()->ClearRefreshToken(); 750} 751 752void DriveAPIService::OnOAuth2RefreshTokenChanged() { 753 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 754 if (CanSendRequest()) { 755 FOR_EACH_OBSERVER( 756 DriveServiceObserver, observers_, OnReadyToSendRequests()); 757 } else if (!HasRefreshToken()) { 758 FOR_EACH_OBSERVER( 759 DriveServiceObserver, observers_, OnRefreshTokenInvalid()); 760 } 761} 762 763} // namespace drive 764