Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / chrome / browser / drive / drive_api_service.cc
blobe2f42bec24904abdacfee0820dfe34a7d8c52fba
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.
5 #include "chrome/browser/drive/drive_api_service.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/drive/drive_api_util.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "google_apis/drive/auth_service.h"
15 #include "google_apis/drive/drive_api_parser.h"
16 #include "google_apis/drive/drive_api_requests.h"
17 #include "google_apis/drive/gdata_errorcode.h"
18 #include "google_apis/drive/gdata_wapi_parser.h"
19 #include "google_apis/drive/gdata_wapi_requests.h"
20 #include "google_apis/drive/request_sender.h"
21 #include "google_apis/google_api_keys.h"
22 #include "net/url_request/url_request_context_getter.h"
24 using content::BrowserThread;
25 using google_apis::AboutResourceCallback;
26 using google_apis::AppList;
27 using google_apis::AppListCallback;
28 using google_apis::AuthStatusCallback;
29 using google_apis::AuthorizeAppCallback;
30 using google_apis::CancelCallback;
31 using google_apis::ChangeList;
32 using google_apis::ChangeListCallback;
33 using google_apis::DownloadActionCallback;
34 using google_apis::EntryActionCallback;
35 using google_apis::FileList;
36 using google_apis::FileListCallback;
37 using google_apis::FileResource;
38 using google_apis::FileResourceCallback;
39 using google_apis::GDATA_OTHER_ERROR;
40 using google_apis::GDATA_PARSE_ERROR;
41 using google_apis::GDataErrorCode;
42 using google_apis::GetContentCallback;
43 using google_apis::GetResourceEntryRequest;
44 using google_apis::GetShareUrlCallback;
45 using google_apis::HTTP_NOT_IMPLEMENTED;
46 using google_apis::HTTP_SUCCESS;
47 using google_apis::InitiateUploadCallback;
48 using google_apis::Link;
49 using google_apis::ProgressCallback;
50 using google_apis::RequestSender;
51 using google_apis::UploadRangeResponse;
52 using google_apis::drive::AboutGetRequest;
53 using google_apis::drive::AppsListRequest;
54 using google_apis::drive::ChangesListRequest;
55 using google_apis::drive::ChangesListNextPageRequest;
56 using google_apis::drive::ChildrenDeleteRequest;
57 using google_apis::drive::ChildrenInsertRequest;
58 using google_apis::drive::DownloadFileRequest;
59 using google_apis::drive::FilesCopyRequest;
60 using google_apis::drive::FilesGetRequest;
61 using google_apis::drive::FilesInsertRequest;
62 using google_apis::drive::FilesPatchRequest;
63 using google_apis::drive::FilesListRequest;
64 using google_apis::drive::FilesListNextPageRequest;
65 using google_apis::drive::FilesDeleteRequest;
66 using google_apis::drive::FilesTrashRequest;
67 using google_apis::drive::GetUploadStatusRequest;
68 using google_apis::drive::InitiateUploadExistingFileRequest;
69 using google_apis::drive::InitiateUploadNewFileRequest;
70 using google_apis::drive::ResumeUploadRequest;
71 using google_apis::drive::UploadRangeCallback;
73 namespace drive {
75 namespace {
77 // OAuth2 scopes for Drive API.
78 const char kDriveScope[] = "https://www.googleapis.com/auth/drive";
79 const char kDriveAppsReadonlyScope[] =
80 "https://www.googleapis.com/auth/drive.apps.readonly";
81 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps";
82 const char kDocsListScope[] = "https://docs.google.com/feeds/";
84 // Mime type to create a directory.
85 const char kFolderMimeType[] = "application/vnd.google-apps.folder";
87 // Max number of file entries to be fetched in a single http request.
89 // The larger the number is,
90 // - The total running time to fetch the whole file list will become shorter.
91 // - The running time for a single request tends to become longer.
92 // Since the file list fetching is a completely background task, for our side,
93 // only the total time matters. However, the server seems to have a time limit
94 // per single request, which disables us to set the largest value (1000).
95 // TODO(kinaba): make it larger when the server gets faster.
96 const int kMaxNumFilesResourcePerRequest = 300;
97 const int kMaxNumFilesResourcePerRequestForSearch = 100;
99 // For performance, we declare all fields we use.
100 const char kAboutResourceFields[] =
101 "kind,quotaBytesTotal,quotaBytesUsed,largestChangeId,rootFolderId";
102 const char kFileResourceFields[] =
103 "kind,id,title,createdDate,sharedWithMeDate,mimeType,"
104 "md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
105 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
106 "parents(id,parentLink),alternateLink,"
107 "modifiedDate,lastViewedByMeDate,shared";
108 const char kFileResourceOpenWithLinksFields[] =
109 "kind,id,openWithLinks/*";
110 const char kFileListFields[] =
111 "kind,items(kind,id,title,createdDate,sharedWithMeDate,"
112 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
113 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
114 "parents(id,parentLink),alternateLink,"
115 "modifiedDate,lastViewedByMeDate,shared),nextLink";
116 const char kChangeListFields[] =
117 "kind,items(file(kind,id,title,createdDate,sharedWithMeDate,"
118 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
119 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
120 "parents(id,parentLink),alternateLink,modifiedDate,"
121 "lastViewedByMeDate,shared),deleted,id,fileId,modificationDate),nextLink,"
122 "largestChangeId";
124 void ExtractOpenUrlAndRun(const std::string& app_id,
125 const AuthorizeAppCallback& callback,
126 GDataErrorCode error,
127 scoped_ptr<FileResource> value) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
129 DCHECK(!callback.is_null());
131 if (!value) {
132 callback.Run(error, GURL());
133 return;
136 const std::vector<FileResource::OpenWithLink>& open_with_links =
137 value->open_with_links();
138 for (size_t i = 0; i < open_with_links.size(); ++i) {
139 if (open_with_links[i].app_id == app_id) {
140 callback.Run(HTTP_SUCCESS, open_with_links[i].open_url);
141 return;
145 // Not found.
146 callback.Run(GDATA_OTHER_ERROR, GURL());
149 void ExtractShareUrlAndRun(const google_apis::GetShareUrlCallback& callback,
150 google_apis::GDataErrorCode error,
151 scoped_ptr<google_apis::ResourceEntry> entry) {
152 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
154 const google_apis::Link* share_link =
155 entry ? entry->GetLinkByType(google_apis::Link::LINK_SHARE) : NULL;
156 callback.Run(error, share_link ? share_link->href() : GURL());
159 // Ignores the |entry|, and runs the |callback|.
160 void EntryActionCallbackAdapter(
161 const EntryActionCallback& callback,
162 GDataErrorCode error, scoped_ptr<FileResource> entry) {
163 callback.Run(error);
166 // The resource ID for the root directory for Drive API is defined in the spec:
167 // https://developers.google.com/drive/folder
168 const char kDriveApiRootDirectoryResourceId[] = "root";
170 } // namespace
172 DriveAPIService::DriveAPIService(
173 OAuth2TokenService* oauth2_token_service,
174 net::URLRequestContextGetter* url_request_context_getter,
175 base::SequencedTaskRunner* blocking_task_runner,
176 const GURL& base_url,
177 const GURL& base_download_url,
178 const GURL& wapi_base_url,
179 const std::string& custom_user_agent)
180 : oauth2_token_service_(oauth2_token_service),
181 url_request_context_getter_(url_request_context_getter),
182 blocking_task_runner_(blocking_task_runner),
183 url_generator_(base_url, base_download_url),
184 wapi_url_generator_(wapi_base_url),
185 custom_user_agent_(custom_user_agent) {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
189 DriveAPIService::~DriveAPIService() {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191 if (sender_.get())
192 sender_->auth_service()->RemoveObserver(this);
195 void DriveAPIService::Initialize(const std::string& account_id) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198 std::vector<std::string> scopes;
199 scopes.push_back(kDriveScope);
200 scopes.push_back(kDriveAppsReadonlyScope);
201 scopes.push_back(kDriveAppsScope);
203 // Note: The following scope is used to support GetShareUrl on Drive API v2.
204 // Unfortunately, there is no support on Drive API v2, so we need to fall back
205 // to GData WAPI for the GetShareUrl.
206 scopes.push_back(kDocsListScope);
208 sender_.reset(new RequestSender(
209 new google_apis::AuthService(oauth2_token_service_,
210 account_id,
211 url_request_context_getter_.get(),
212 scopes),
213 url_request_context_getter_.get(),
214 blocking_task_runner_.get(),
215 custom_user_agent_));
216 sender_->auth_service()->AddObserver(this);
219 void DriveAPIService::AddObserver(DriveServiceObserver* observer) {
220 observers_.AddObserver(observer);
223 void DriveAPIService::RemoveObserver(DriveServiceObserver* observer) {
224 observers_.RemoveObserver(observer);
227 bool DriveAPIService::CanSendRequest() const {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230 return HasRefreshToken();
233 std::string DriveAPIService::GetRootResourceId() const {
234 return kDriveApiRootDirectoryResourceId;
237 CancelCallback DriveAPIService::GetAllFileList(
238 const FileListCallback& callback) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
240 DCHECK(!callback.is_null());
242 FilesListRequest* request = new FilesListRequest(
243 sender_.get(), url_generator_, callback);
244 request->set_max_results(kMaxNumFilesResourcePerRequest);
245 request->set_q("trashed = false"); // Exclude trashed files.
246 request->set_fields(kFileListFields);
247 return sender_->StartRequestWithRetry(request);
250 CancelCallback DriveAPIService::GetFileListInDirectory(
251 const std::string& directory_resource_id,
252 const FileListCallback& callback) {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254 DCHECK(!directory_resource_id.empty());
255 DCHECK(!callback.is_null());
257 // Because children.list method on Drive API v2 returns only the list of
258 // children's references, but we need all file resource list.
259 // So, here we use files.list method instead, with setting parents query.
260 // After the migration from GData WAPI to Drive API v2, we should clean the
261 // code up by moving the responsibility to include "parents" in the query
262 // to client side.
263 // We aren't interested in files in trash in this context, neither.
264 FilesListRequest* request = new FilesListRequest(
265 sender_.get(), url_generator_, callback);
266 request->set_max_results(kMaxNumFilesResourcePerRequest);
267 request->set_q(base::StringPrintf(
268 "'%s' in parents and trashed = false",
269 util::EscapeQueryStringValue(directory_resource_id).c_str()));
270 request->set_fields(kFileListFields);
271 return sender_->StartRequestWithRetry(request);
274 CancelCallback DriveAPIService::Search(
275 const std::string& search_query,
276 const FileListCallback& callback) {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
278 DCHECK(!search_query.empty());
279 DCHECK(!callback.is_null());
281 FilesListRequest* request = new FilesListRequest(
282 sender_.get(), url_generator_, callback);
283 request->set_max_results(kMaxNumFilesResourcePerRequestForSearch);
284 request->set_q(util::TranslateQuery(search_query));
285 request->set_fields(kFileListFields);
286 return sender_->StartRequestWithRetry(request);
289 CancelCallback DriveAPIService::SearchByTitle(
290 const std::string& title,
291 const std::string& directory_resource_id,
292 const FileListCallback& callback) {
293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
294 DCHECK(!title.empty());
295 DCHECK(!callback.is_null());
297 std::string query;
298 base::StringAppendF(&query, "title = '%s'",
299 util::EscapeQueryStringValue(title).c_str());
300 if (!directory_resource_id.empty()) {
301 base::StringAppendF(
302 &query, " and '%s' in parents",
303 util::EscapeQueryStringValue(directory_resource_id).c_str());
305 query += " and trashed = false";
307 FilesListRequest* request = new FilesListRequest(
308 sender_.get(), url_generator_, callback);
309 request->set_max_results(kMaxNumFilesResourcePerRequest);
310 request->set_q(query);
311 request->set_fields(kFileListFields);
312 return sender_->StartRequestWithRetry(request);
315 CancelCallback DriveAPIService::GetChangeList(
316 int64 start_changestamp,
317 const ChangeListCallback& callback) {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
319 DCHECK(!callback.is_null());
321 ChangesListRequest* request = new ChangesListRequest(
322 sender_.get(), url_generator_, callback);
323 request->set_max_results(kMaxNumFilesResourcePerRequest);
324 request->set_start_change_id(start_changestamp);
325 request->set_fields(kChangeListFields);
326 return sender_->StartRequestWithRetry(request);
329 CancelCallback DriveAPIService::GetRemainingChangeList(
330 const GURL& next_link,
331 const ChangeListCallback& callback) {
332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
333 DCHECK(!next_link.is_empty());
334 DCHECK(!callback.is_null());
336 ChangesListNextPageRequest* request = new ChangesListNextPageRequest(
337 sender_.get(), callback);
338 request->set_next_link(next_link);
339 request->set_fields(kChangeListFields);
340 return sender_->StartRequestWithRetry(request);
343 CancelCallback DriveAPIService::GetRemainingFileList(
344 const GURL& next_link,
345 const FileListCallback& callback) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
347 DCHECK(!next_link.is_empty());
348 DCHECK(!callback.is_null());
350 FilesListNextPageRequest* request = new FilesListNextPageRequest(
351 sender_.get(), callback);
352 request->set_next_link(next_link);
353 request->set_fields(kFileListFields);
354 return sender_->StartRequestWithRetry(request);
357 CancelCallback DriveAPIService::GetFileResource(
358 const std::string& resource_id,
359 const FileResourceCallback& callback) {
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
361 DCHECK(!callback.is_null());
363 FilesGetRequest* request = new FilesGetRequest(
364 sender_.get(), url_generator_, callback);
365 request->set_file_id(resource_id);
366 request->set_fields(kFileResourceFields);
367 return sender_->StartRequestWithRetry(request);
370 CancelCallback DriveAPIService::GetShareUrl(
371 const std::string& resource_id,
372 const GURL& embed_origin,
373 const GetShareUrlCallback& callback) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
375 DCHECK(!callback.is_null());
377 // Unfortunately "share url" is not yet supported on Drive API v2.
378 // So, as a fallback, we use GData WAPI protocol for this method.
379 // TODO(hidehiko): Get rid of this implementation when share url is
380 // supported on Drive API v2.
381 return sender_->StartRequestWithRetry(
382 new GetResourceEntryRequest(sender_.get(),
383 wapi_url_generator_,
384 resource_id,
385 embed_origin,
386 base::Bind(&ExtractShareUrlAndRun,
387 callback)));
390 CancelCallback DriveAPIService::GetAboutResource(
391 const AboutResourceCallback& callback) {
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
393 DCHECK(!callback.is_null());
395 AboutGetRequest* request =
396 new AboutGetRequest(sender_.get(), url_generator_, callback);
397 request->set_fields(kAboutResourceFields);
398 return sender_->StartRequestWithRetry(request);
401 CancelCallback DriveAPIService::GetAppList(const AppListCallback& callback) {
402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
403 DCHECK(!callback.is_null());
405 return sender_->StartRequestWithRetry(
406 new AppsListRequest(sender_.get(), url_generator_,
407 google_apis::IsGoogleChromeAPIKeyUsed(),
408 callback));
411 CancelCallback DriveAPIService::DownloadFile(
412 const base::FilePath& local_cache_path,
413 const std::string& resource_id,
414 const DownloadActionCallback& download_action_callback,
415 const GetContentCallback& get_content_callback,
416 const ProgressCallback& progress_callback) {
417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
418 DCHECK(!download_action_callback.is_null());
419 // get_content_callback may be null.
421 return sender_->StartRequestWithRetry(
422 new DownloadFileRequest(sender_.get(),
423 url_generator_,
424 resource_id,
425 local_cache_path,
426 download_action_callback,
427 get_content_callback,
428 progress_callback));
431 CancelCallback DriveAPIService::DeleteResource(
432 const std::string& resource_id,
433 const std::string& etag,
434 const EntryActionCallback& callback) {
435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
436 DCHECK(!callback.is_null());
438 FilesDeleteRequest* request = new FilesDeleteRequest(
439 sender_.get(), url_generator_, callback);
440 request->set_file_id(resource_id);
441 request->set_etag(etag);
442 return sender_->StartRequestWithRetry(request);
445 CancelCallback DriveAPIService::TrashResource(
446 const std::string& resource_id,
447 const EntryActionCallback& callback) {
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
449 DCHECK(!callback.is_null());
451 FilesTrashRequest* request = new FilesTrashRequest(
452 sender_.get(), url_generator_,
453 base::Bind(&EntryActionCallbackAdapter, callback));
454 request->set_file_id(resource_id);
455 request->set_fields(kFileResourceFields);
456 return sender_->StartRequestWithRetry(request);
459 CancelCallback DriveAPIService::AddNewDirectory(
460 const std::string& parent_resource_id,
461 const std::string& directory_title,
462 const AddNewDirectoryOptions& options,
463 const FileResourceCallback& callback) {
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
465 DCHECK(!callback.is_null());
467 FilesInsertRequest* request = new FilesInsertRequest(
468 sender_.get(), url_generator_, callback);
469 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
470 request->set_mime_type(kFolderMimeType);
471 request->set_modified_date(options.modified_date);
472 request->add_parent(parent_resource_id);
473 request->set_title(directory_title);
474 request->set_fields(kFileResourceFields);
475 return sender_->StartRequestWithRetry(request);
478 CancelCallback DriveAPIService::CopyResource(
479 const std::string& resource_id,
480 const std::string& parent_resource_id,
481 const std::string& new_title,
482 const base::Time& last_modified,
483 const FileResourceCallback& callback) {
484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
485 DCHECK(!callback.is_null());
487 FilesCopyRequest* request = new FilesCopyRequest(
488 sender_.get(), url_generator_, callback);
489 request->set_file_id(resource_id);
490 request->add_parent(parent_resource_id);
491 request->set_title(new_title);
492 request->set_modified_date(last_modified);
493 request->set_fields(kFileResourceFields);
494 return sender_->StartRequestWithRetry(request);
497 CancelCallback DriveAPIService::UpdateResource(
498 const std::string& resource_id,
499 const std::string& parent_resource_id,
500 const std::string& new_title,
501 const base::Time& last_modified,
502 const base::Time& last_viewed_by_me,
503 const FileResourceCallback& callback) {
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
505 DCHECK(!callback.is_null());
507 FilesPatchRequest* request = new FilesPatchRequest(
508 sender_.get(), url_generator_, callback);
509 request->set_file_id(resource_id);
510 request->set_title(new_title);
511 if (!parent_resource_id.empty())
512 request->add_parent(parent_resource_id);
513 if (!last_modified.is_null()) {
514 // Need to set setModifiedDate to true to overwrite modifiedDate.
515 request->set_set_modified_date(true);
516 request->set_modified_date(last_modified);
518 if (!last_viewed_by_me.is_null()) {
519 // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
520 // will be set to the request time (not the specified time via request).
521 request->set_update_viewed_date(false);
522 request->set_last_viewed_by_me_date(last_viewed_by_me);
524 request->set_fields(kFileResourceFields);
525 return sender_->StartRequestWithRetry(request);
528 CancelCallback DriveAPIService::AddResourceToDirectory(
529 const std::string& parent_resource_id,
530 const std::string& resource_id,
531 const EntryActionCallback& callback) {
532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
533 DCHECK(!callback.is_null());
535 ChildrenInsertRequest* request =
536 new ChildrenInsertRequest(sender_.get(), url_generator_, callback);
537 request->set_folder_id(parent_resource_id);
538 request->set_id(resource_id);
539 return sender_->StartRequestWithRetry(request);
542 CancelCallback DriveAPIService::RemoveResourceFromDirectory(
543 const std::string& parent_resource_id,
544 const std::string& resource_id,
545 const EntryActionCallback& callback) {
546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
547 DCHECK(!callback.is_null());
549 ChildrenDeleteRequest* request =
550 new ChildrenDeleteRequest(sender_.get(), url_generator_, callback);
551 request->set_child_id(resource_id);
552 request->set_folder_id(parent_resource_id);
553 return sender_->StartRequestWithRetry(request);
556 CancelCallback DriveAPIService::InitiateUploadNewFile(
557 const std::string& content_type,
558 int64 content_length,
559 const std::string& parent_resource_id,
560 const std::string& title,
561 const InitiateUploadNewFileOptions& options,
562 const InitiateUploadCallback& callback) {
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
564 DCHECK(!callback.is_null());
566 InitiateUploadNewFileRequest* request =
567 new InitiateUploadNewFileRequest(sender_.get(),
568 url_generator_,
569 content_type,
570 content_length,
571 parent_resource_id,
572 title,
573 callback);
574 request->set_modified_date(options.modified_date);
575 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
576 return sender_->StartRequestWithRetry(request);
579 CancelCallback DriveAPIService::InitiateUploadExistingFile(
580 const std::string& content_type,
581 int64 content_length,
582 const std::string& resource_id,
583 const InitiateUploadExistingFileOptions& options,
584 const InitiateUploadCallback& callback) {
585 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
586 DCHECK(!callback.is_null());
588 InitiateUploadExistingFileRequest* request =
589 new InitiateUploadExistingFileRequest(sender_.get(),
590 url_generator_,
591 content_type,
592 content_length,
593 resource_id,
594 options.etag,
595 callback);
596 request->set_parent_resource_id(options.parent_resource_id);
597 request->set_title(options.title);
598 request->set_modified_date(options.modified_date);
599 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
600 return sender_->StartRequestWithRetry(request);
603 CancelCallback DriveAPIService::ResumeUpload(
604 const GURL& upload_url,
605 int64 start_position,
606 int64 end_position,
607 int64 content_length,
608 const std::string& content_type,
609 const base::FilePath& local_file_path,
610 const UploadRangeCallback& callback,
611 const ProgressCallback& progress_callback) {
612 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
613 DCHECK(!callback.is_null());
615 return sender_->StartRequestWithRetry(
616 new ResumeUploadRequest(
617 sender_.get(),
618 upload_url,
619 start_position,
620 end_position,
621 content_length,
622 content_type,
623 local_file_path,
624 callback,
625 progress_callback));
628 CancelCallback DriveAPIService::GetUploadStatus(
629 const GURL& upload_url,
630 int64 content_length,
631 const UploadRangeCallback& callback) {
632 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
633 DCHECK(!callback.is_null());
635 return sender_->StartRequestWithRetry(new GetUploadStatusRequest(
636 sender_.get(),
637 upload_url,
638 content_length,
639 callback));
642 CancelCallback DriveAPIService::AuthorizeApp(
643 const std::string& resource_id,
644 const std::string& app_id,
645 const AuthorizeAppCallback& callback) {
646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
647 DCHECK(!callback.is_null());
649 // Files.Authorize is only available for whitelisted clients like official
650 // Google Chrome. In other cases, we fall back to Files.Get that returns the
651 // same value as Files.Authorize without doing authorization. In that case,
652 // the app can open if it was authorized by other means (from whitelisted
653 // clients or drive.google.com web UI.)
654 if (google_apis::IsGoogleChromeAPIKeyUsed()) {
655 google_apis::drive::FilesAuthorizeRequest* request =
656 new google_apis::drive::FilesAuthorizeRequest(
657 sender_.get(), url_generator_,
658 base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
659 request->set_app_id(app_id);
660 request->set_file_id(resource_id);
661 request->set_fields(kFileResourceOpenWithLinksFields);
662 return sender_->StartRequestWithRetry(request);
663 } else {
664 FilesGetRequest* request = new FilesGetRequest(
665 sender_.get(), url_generator_,
666 base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
667 request->set_file_id(resource_id);
668 request->set_fields(kFileResourceOpenWithLinksFields);
669 return sender_->StartRequestWithRetry(request);
673 CancelCallback DriveAPIService::UninstallApp(
674 const std::string& app_id,
675 const google_apis::EntryActionCallback& callback) {
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
677 DCHECK(!callback.is_null());
679 google_apis::drive::AppsDeleteRequest* request =
680 new google_apis::drive::AppsDeleteRequest(sender_.get(), url_generator_,
681 callback);
682 request->set_app_id(app_id);
683 return sender_->StartRequestWithRetry(request);
686 google_apis::CancelCallback DriveAPIService::AddPermission(
687 const std::string& resource_id,
688 const std::string& email,
689 google_apis::drive::PermissionRole role,
690 const google_apis::EntryActionCallback& callback) {
691 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
692 DCHECK(!callback.is_null());
694 google_apis::drive::PermissionsInsertRequest* request =
695 new google_apis::drive::PermissionsInsertRequest(sender_.get(),
696 url_generator_,
697 callback);
698 request->set_id(resource_id);
699 request->set_role(role);
700 request->set_type(google_apis::drive::PERMISSION_TYPE_USER);
701 request->set_value(email);
702 return sender_->StartRequestWithRetry(request);
705 bool DriveAPIService::HasAccessToken() const {
706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
707 return sender_->auth_service()->HasAccessToken();
710 void DriveAPIService::RequestAccessToken(const AuthStatusCallback& callback) {
711 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
712 DCHECK(!callback.is_null());
714 const std::string access_token = sender_->auth_service()->access_token();
715 if (!access_token.empty()) {
716 callback.Run(google_apis::HTTP_NOT_MODIFIED, access_token);
717 return;
720 // Retrieve the new auth token.
721 sender_->auth_service()->StartAuthentication(callback);
724 bool DriveAPIService::HasRefreshToken() const {
725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
726 return sender_->auth_service()->HasRefreshToken();
729 void DriveAPIService::ClearAccessToken() {
730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
731 sender_->auth_service()->ClearAccessToken();
734 void DriveAPIService::ClearRefreshToken() {
735 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
736 sender_->auth_service()->ClearRefreshToken();
739 void DriveAPIService::OnOAuth2RefreshTokenChanged() {
740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
741 if (CanSendRequest()) {
742 FOR_EACH_OBSERVER(
743 DriveServiceObserver, observers_, OnReadyToSendRequests());
744 } else if (!HasRefreshToken()) {
745 FOR_EACH_OBSERVER(
746 DriveServiceObserver, observers_, OnRefreshTokenInvalid());
750 } // namespace drive