base::Time multiplicative operator overloading
[chromium-blink-merge.git] / chrome / browser / drive / drive_api_service.cc
blobd22811f00f49e1152c24d25b083dd891d4bb33e4
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 "google_apis/drive/auth_service.h"
14 #include "google_apis/drive/drive_api_parser.h"
15 #include "google_apis/drive/drive_api_requests.h"
16 #include "google_apis/drive/request_sender.h"
17 #include "google_apis/google_api_keys.h"
18 #include "net/url_request/url_request_context_getter.h"
20 using google_apis::AboutResourceCallback;
21 using google_apis::AppList;
22 using google_apis::AppListCallback;
23 using google_apis::AuthStatusCallback;
24 using google_apis::AuthorizeAppCallback;
25 using google_apis::CancelCallback;
26 using google_apis::ChangeList;
27 using google_apis::ChangeListCallback;
28 using google_apis::DownloadActionCallback;
29 using google_apis::EntryActionCallback;
30 using google_apis::FileList;
31 using google_apis::FileListCallback;
32 using google_apis::FileResource;
33 using google_apis::FileResourceCallback;
34 using google_apis::DRIVE_OTHER_ERROR;
35 using google_apis::DRIVE_PARSE_ERROR;
36 using google_apis::DriveApiErrorCode;
37 using google_apis::GetContentCallback;
38 using google_apis::GetShareUrlCallback;
39 using google_apis::HTTP_NOT_IMPLEMENTED;
40 using google_apis::HTTP_SUCCESS;
41 using google_apis::InitiateUploadCallback;
42 using google_apis::ProgressCallback;
43 using google_apis::RequestSender;
44 using google_apis::UploadRangeResponse;
45 using google_apis::drive::AboutGetRequest;
46 using google_apis::drive::AppsListRequest;
47 using google_apis::drive::ChangesListRequest;
48 using google_apis::drive::ChangesListNextPageRequest;
49 using google_apis::drive::ChildrenDeleteRequest;
50 using google_apis::drive::ChildrenInsertRequest;
51 using google_apis::drive::DownloadFileRequest;
52 using google_apis::drive::FilesCopyRequest;
53 using google_apis::drive::FilesGetRequest;
54 using google_apis::drive::FilesInsertRequest;
55 using google_apis::drive::FilesPatchRequest;
56 using google_apis::drive::FilesListRequest;
57 using google_apis::drive::FilesListNextPageRequest;
58 using google_apis::drive::FilesDeleteRequest;
59 using google_apis::drive::FilesTrashRequest;
60 using google_apis::drive::GetUploadStatusRequest;
61 using google_apis::drive::InitiateUploadExistingFileRequest;
62 using google_apis::drive::InitiateUploadNewFileRequest;
63 using google_apis::drive::ResumeUploadRequest;
64 using google_apis::drive::UploadRangeCallback;
66 namespace drive {
68 namespace {
70 // OAuth2 scopes for Drive API.
71 const char kDriveScope[] = "https://www.googleapis.com/auth/drive";
72 const char kDriveAppsReadonlyScope[] =
73 "https://www.googleapis.com/auth/drive.apps.readonly";
74 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps";
75 const char kDocsListScope[] = "https://docs.google.com/feeds/";
77 // Mime type to create a directory.
78 const char kFolderMimeType[] = "application/vnd.google-apps.folder";
80 // Max number of file entries to be fetched in a single http request.
82 // The larger the number is,
83 // - The total running time to fetch the whole file list will become shorter.
84 // - The running time for a single request tends to become longer.
85 // Since the file list fetching is a completely background task, for our side,
86 // only the total time matters. However, the server seems to have a time limit
87 // per single request, which disables us to set the largest value (1000).
88 // TODO(kinaba): make it larger when the server gets faster.
89 const int kMaxNumFilesResourcePerRequest = 300;
90 const int kMaxNumFilesResourcePerRequestForSearch = 100;
92 // For performance, we declare all fields we use.
93 const char kAboutResourceFields[] =
94 "kind,quotaBytesTotal,quotaBytesUsed,largestChangeId,rootFolderId";
95 const char kFileResourceFields[] =
96 "kind,id,title,createdDate,sharedWithMeDate,mimeType,"
97 "md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
98 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
99 "parents(id,parentLink),alternateLink,"
100 "modifiedDate,lastViewedByMeDate,shared";
101 const char kFileResourceOpenWithLinksFields[] =
102 "kind,id,openWithLinks/*";
103 const char kFileResourceShareLinkFields[] =
104 "kind,id,shareLink";
105 const char kFileListFields[] =
106 "kind,items(kind,id,title,createdDate,sharedWithMeDate,"
107 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
108 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
109 "parents(id,parentLink),alternateLink,"
110 "modifiedDate,lastViewedByMeDate,shared),nextLink";
111 const char kChangeListFields[] =
112 "kind,items(file(kind,id,title,createdDate,sharedWithMeDate,"
113 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
114 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
115 "parents(id,parentLink),alternateLink,modifiedDate,"
116 "lastViewedByMeDate,shared),deleted,id,fileId,modificationDate),nextLink,"
117 "largestChangeId";
119 void ExtractOpenUrlAndRun(const std::string& app_id,
120 const AuthorizeAppCallback& callback,
121 DriveApiErrorCode error,
122 scoped_ptr<FileResource> value) {
123 DCHECK(!callback.is_null());
125 if (!value) {
126 callback.Run(error, GURL());
127 return;
130 const std::vector<FileResource::OpenWithLink>& open_with_links =
131 value->open_with_links();
132 for (size_t i = 0; i < open_with_links.size(); ++i) {
133 if (open_with_links[i].app_id == app_id) {
134 callback.Run(HTTP_SUCCESS, open_with_links[i].open_url);
135 return;
139 // Not found.
140 callback.Run(DRIVE_OTHER_ERROR, GURL());
143 void ExtractShareUrlAndRun(const GetShareUrlCallback& callback,
144 DriveApiErrorCode error,
145 scoped_ptr<FileResource> value) {
146 callback.Run(error, value ? value->share_link() : GURL());
149 // Ignores the |entry|, and runs the |callback|.
150 void EntryActionCallbackAdapter(
151 const EntryActionCallback& callback,
152 DriveApiErrorCode error, scoped_ptr<FileResource> entry) {
153 callback.Run(error);
156 // The resource ID for the root directory for Drive API is defined in the spec:
157 // https://developers.google.com/drive/folder
158 const char kDriveApiRootDirectoryResourceId[] = "root";
160 } // namespace
162 DriveAPIService::DriveAPIService(
163 OAuth2TokenService* oauth2_token_service,
164 net::URLRequestContextGetter* url_request_context_getter,
165 base::SequencedTaskRunner* blocking_task_runner,
166 const GURL& base_url,
167 const GURL& base_download_url,
168 const std::string& custom_user_agent)
169 : oauth2_token_service_(oauth2_token_service),
170 url_request_context_getter_(url_request_context_getter),
171 blocking_task_runner_(blocking_task_runner),
172 url_generator_(base_url, base_download_url),
173 custom_user_agent_(custom_user_agent) {
176 DriveAPIService::~DriveAPIService() {
177 DCHECK(thread_checker_.CalledOnValidThread());
178 if (sender_.get())
179 sender_->auth_service()->RemoveObserver(this);
182 void DriveAPIService::Initialize(const std::string& account_id) {
183 DCHECK(thread_checker_.CalledOnValidThread());
185 std::vector<std::string> scopes;
186 scopes.push_back(kDriveScope);
187 scopes.push_back(kDriveAppsReadonlyScope);
188 scopes.push_back(kDriveAppsScope);
190 // Note: The following scope is used to support GetShareUrl on Drive API v2.
191 // Unfortunately, there is no support on Drive API v2, so we need to fall back
192 // to GData WAPI for the GetShareUrl.
193 scopes.push_back(kDocsListScope);
195 sender_.reset(new RequestSender(
196 new google_apis::AuthService(oauth2_token_service_,
197 account_id,
198 url_request_context_getter_.get(),
199 scopes),
200 url_request_context_getter_.get(),
201 blocking_task_runner_.get(),
202 custom_user_agent_));
203 sender_->auth_service()->AddObserver(this);
206 void DriveAPIService::AddObserver(DriveServiceObserver* observer) {
207 observers_.AddObserver(observer);
210 void DriveAPIService::RemoveObserver(DriveServiceObserver* observer) {
211 observers_.RemoveObserver(observer);
214 bool DriveAPIService::CanSendRequest() const {
215 DCHECK(thread_checker_.CalledOnValidThread());
217 return HasRefreshToken();
220 std::string DriveAPIService::GetRootResourceId() const {
221 return kDriveApiRootDirectoryResourceId;
224 CancelCallback DriveAPIService::GetAllFileList(
225 const FileListCallback& callback) {
226 DCHECK(thread_checker_.CalledOnValidThread());
227 DCHECK(!callback.is_null());
229 FilesListRequest* request = new FilesListRequest(
230 sender_.get(), url_generator_, callback);
231 request->set_max_results(kMaxNumFilesResourcePerRequest);
232 request->set_q("trashed = false"); // Exclude trashed files.
233 request->set_fields(kFileListFields);
234 return sender_->StartRequestWithRetry(request);
237 CancelCallback DriveAPIService::GetFileListInDirectory(
238 const std::string& directory_resource_id,
239 const FileListCallback& callback) {
240 DCHECK(thread_checker_.CalledOnValidThread());
241 DCHECK(!directory_resource_id.empty());
242 DCHECK(!callback.is_null());
244 // Because children.list method on Drive API v2 returns only the list of
245 // children's references, but we need all file resource list.
246 // So, here we use files.list method instead, with setting parents query.
247 // After the migration from GData WAPI to Drive API v2, we should clean the
248 // code up by moving the responsibility to include "parents" in the query
249 // to client side.
250 // We aren't interested in files in trash in this context, neither.
251 FilesListRequest* request = new FilesListRequest(
252 sender_.get(), url_generator_, callback);
253 request->set_max_results(kMaxNumFilesResourcePerRequest);
254 request->set_q(base::StringPrintf(
255 "'%s' in parents and trashed = false",
256 util::EscapeQueryStringValue(directory_resource_id).c_str()));
257 request->set_fields(kFileListFields);
258 return sender_->StartRequestWithRetry(request);
261 CancelCallback DriveAPIService::Search(
262 const std::string& search_query,
263 const FileListCallback& callback) {
264 DCHECK(thread_checker_.CalledOnValidThread());
265 DCHECK(!search_query.empty());
266 DCHECK(!callback.is_null());
268 FilesListRequest* request = new FilesListRequest(
269 sender_.get(), url_generator_, callback);
270 request->set_max_results(kMaxNumFilesResourcePerRequestForSearch);
271 request->set_q(util::TranslateQuery(search_query));
272 request->set_fields(kFileListFields);
273 return sender_->StartRequestWithRetry(request);
276 CancelCallback DriveAPIService::SearchByTitle(
277 const std::string& title,
278 const std::string& directory_resource_id,
279 const FileListCallback& callback) {
280 DCHECK(thread_checker_.CalledOnValidThread());
281 DCHECK(!title.empty());
282 DCHECK(!callback.is_null());
284 std::string query;
285 base::StringAppendF(&query, "title = '%s'",
286 util::EscapeQueryStringValue(title).c_str());
287 if (!directory_resource_id.empty()) {
288 base::StringAppendF(
289 &query, " and '%s' in parents",
290 util::EscapeQueryStringValue(directory_resource_id).c_str());
292 query += " and trashed = false";
294 FilesListRequest* request = new FilesListRequest(
295 sender_.get(), url_generator_, callback);
296 request->set_max_results(kMaxNumFilesResourcePerRequest);
297 request->set_q(query);
298 request->set_fields(kFileListFields);
299 return sender_->StartRequestWithRetry(request);
302 CancelCallback DriveAPIService::GetChangeList(
303 int64 start_changestamp,
304 const ChangeListCallback& callback) {
305 DCHECK(thread_checker_.CalledOnValidThread());
306 DCHECK(!callback.is_null());
308 ChangesListRequest* request = new ChangesListRequest(
309 sender_.get(), url_generator_, callback);
310 request->set_max_results(kMaxNumFilesResourcePerRequest);
311 request->set_start_change_id(start_changestamp);
312 request->set_fields(kChangeListFields);
313 return sender_->StartRequestWithRetry(request);
316 CancelCallback DriveAPIService::GetRemainingChangeList(
317 const GURL& next_link,
318 const ChangeListCallback& callback) {
319 DCHECK(thread_checker_.CalledOnValidThread());
320 DCHECK(!next_link.is_empty());
321 DCHECK(!callback.is_null());
323 ChangesListNextPageRequest* request = new ChangesListNextPageRequest(
324 sender_.get(), callback);
325 request->set_next_link(next_link);
326 request->set_fields(kChangeListFields);
327 return sender_->StartRequestWithRetry(request);
330 CancelCallback DriveAPIService::GetRemainingFileList(
331 const GURL& next_link,
332 const FileListCallback& callback) {
333 DCHECK(thread_checker_.CalledOnValidThread());
334 DCHECK(!next_link.is_empty());
335 DCHECK(!callback.is_null());
337 FilesListNextPageRequest* request = new FilesListNextPageRequest(
338 sender_.get(), callback);
339 request->set_next_link(next_link);
340 request->set_fields(kFileListFields);
341 return sender_->StartRequestWithRetry(request);
344 CancelCallback DriveAPIService::GetFileResource(
345 const std::string& resource_id,
346 const FileResourceCallback& callback) {
347 DCHECK(thread_checker_.CalledOnValidThread());
348 DCHECK(!callback.is_null());
350 FilesGetRequest* request = new FilesGetRequest(
351 sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
352 callback);
353 request->set_file_id(resource_id);
354 request->set_fields(kFileResourceFields);
355 return sender_->StartRequestWithRetry(request);
358 CancelCallback DriveAPIService::GetShareUrl(
359 const std::string& resource_id,
360 const GURL& embed_origin,
361 const GetShareUrlCallback& callback) {
362 DCHECK(thread_checker_.CalledOnValidThread());
363 DCHECK(!callback.is_null());
365 if (!google_apis::IsGoogleChromeAPIKeyUsed()) {
366 LOG(ERROR) << "Only the official build of Chrome OS can open share dialogs "
367 << "from the file manager.";
370 FilesGetRequest* request = new FilesGetRequest(
371 sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
372 base::Bind(&ExtractShareUrlAndRun, callback));
373 request->set_file_id(resource_id);
374 request->set_fields(kFileResourceShareLinkFields);
375 request->set_embed_origin(embed_origin);
376 return sender_->StartRequestWithRetry(request);
379 CancelCallback DriveAPIService::GetAboutResource(
380 const AboutResourceCallback& callback) {
381 DCHECK(thread_checker_.CalledOnValidThread());
382 DCHECK(!callback.is_null());
384 AboutGetRequest* request =
385 new AboutGetRequest(sender_.get(), url_generator_, callback);
386 request->set_fields(kAboutResourceFields);
387 return sender_->StartRequestWithRetry(request);
390 CancelCallback DriveAPIService::GetAppList(const AppListCallback& callback) {
391 DCHECK(thread_checker_.CalledOnValidThread());
392 DCHECK(!callback.is_null());
394 return sender_->StartRequestWithRetry(
395 new AppsListRequest(sender_.get(), url_generator_,
396 google_apis::IsGoogleChromeAPIKeyUsed(),
397 callback));
400 CancelCallback DriveAPIService::DownloadFile(
401 const base::FilePath& local_cache_path,
402 const std::string& resource_id,
403 const DownloadActionCallback& download_action_callback,
404 const GetContentCallback& get_content_callback,
405 const ProgressCallback& progress_callback) {
406 DCHECK(thread_checker_.CalledOnValidThread());
407 DCHECK(!download_action_callback.is_null());
408 // get_content_callback may be null.
410 return sender_->StartRequestWithRetry(
411 new DownloadFileRequest(sender_.get(),
412 url_generator_,
413 resource_id,
414 local_cache_path,
415 download_action_callback,
416 get_content_callback,
417 progress_callback));
420 CancelCallback DriveAPIService::DeleteResource(
421 const std::string& resource_id,
422 const std::string& etag,
423 const EntryActionCallback& callback) {
424 DCHECK(thread_checker_.CalledOnValidThread());
425 DCHECK(!callback.is_null());
427 FilesDeleteRequest* request = new FilesDeleteRequest(
428 sender_.get(), url_generator_, callback);
429 request->set_file_id(resource_id);
430 request->set_etag(etag);
431 return sender_->StartRequestWithRetry(request);
434 CancelCallback DriveAPIService::TrashResource(
435 const std::string& resource_id,
436 const EntryActionCallback& callback) {
437 DCHECK(thread_checker_.CalledOnValidThread());
438 DCHECK(!callback.is_null());
440 FilesTrashRequest* request = new FilesTrashRequest(
441 sender_.get(), url_generator_,
442 base::Bind(&EntryActionCallbackAdapter, callback));
443 request->set_file_id(resource_id);
444 request->set_fields(kFileResourceFields);
445 return sender_->StartRequestWithRetry(request);
448 CancelCallback DriveAPIService::AddNewDirectory(
449 const std::string& parent_resource_id,
450 const std::string& directory_title,
451 const AddNewDirectoryOptions& options,
452 const FileResourceCallback& callback) {
453 DCHECK(thread_checker_.CalledOnValidThread());
454 DCHECK(!callback.is_null());
456 FilesInsertRequest* request = new FilesInsertRequest(
457 sender_.get(), url_generator_, callback);
458 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
459 request->set_mime_type(kFolderMimeType);
460 request->set_modified_date(options.modified_date);
461 request->add_parent(parent_resource_id);
462 request->set_title(directory_title);
463 request->set_fields(kFileResourceFields);
464 return sender_->StartRequestWithRetry(request);
467 CancelCallback DriveAPIService::CopyResource(
468 const std::string& resource_id,
469 const std::string& parent_resource_id,
470 const std::string& new_title,
471 const base::Time& last_modified,
472 const FileResourceCallback& callback) {
473 DCHECK(thread_checker_.CalledOnValidThread());
474 DCHECK(!callback.is_null());
476 FilesCopyRequest* request = new FilesCopyRequest(
477 sender_.get(), url_generator_, callback);
478 request->set_file_id(resource_id);
479 request->add_parent(parent_resource_id);
480 request->set_title(new_title);
481 request->set_modified_date(last_modified);
482 request->set_fields(kFileResourceFields);
483 return sender_->StartRequestWithRetry(request);
486 CancelCallback DriveAPIService::UpdateResource(
487 const std::string& resource_id,
488 const std::string& parent_resource_id,
489 const std::string& new_title,
490 const base::Time& last_modified,
491 const base::Time& last_viewed_by_me,
492 const google_apis::drive::Properties& properties,
493 const FileResourceCallback& callback) {
494 DCHECK(thread_checker_.CalledOnValidThread());
495 DCHECK(!callback.is_null());
497 FilesPatchRequest* request = new FilesPatchRequest(
498 sender_.get(), url_generator_, callback);
499 request->set_file_id(resource_id);
500 request->set_title(new_title);
501 if (!parent_resource_id.empty())
502 request->add_parent(parent_resource_id);
503 if (!last_modified.is_null()) {
504 // Need to set setModifiedDate to true to overwrite modifiedDate.
505 request->set_set_modified_date(true);
506 request->set_modified_date(last_modified);
508 if (!last_viewed_by_me.is_null()) {
509 // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
510 // will be set to the request time (not the specified time via request).
511 request->set_update_viewed_date(false);
512 request->set_last_viewed_by_me_date(last_viewed_by_me);
514 request->set_fields(kFileResourceFields);
515 request->set_properties(properties);
516 return sender_->StartRequestWithRetry(request);
519 CancelCallback DriveAPIService::AddResourceToDirectory(
520 const std::string& parent_resource_id,
521 const std::string& resource_id,
522 const EntryActionCallback& callback) {
523 DCHECK(thread_checker_.CalledOnValidThread());
524 DCHECK(!callback.is_null());
526 ChildrenInsertRequest* request =
527 new ChildrenInsertRequest(sender_.get(), url_generator_, callback);
528 request->set_folder_id(parent_resource_id);
529 request->set_id(resource_id);
530 return sender_->StartRequestWithRetry(request);
533 CancelCallback DriveAPIService::RemoveResourceFromDirectory(
534 const std::string& parent_resource_id,
535 const std::string& resource_id,
536 const EntryActionCallback& callback) {
537 DCHECK(thread_checker_.CalledOnValidThread());
538 DCHECK(!callback.is_null());
540 ChildrenDeleteRequest* request =
541 new ChildrenDeleteRequest(sender_.get(), url_generator_, callback);
542 request->set_child_id(resource_id);
543 request->set_folder_id(parent_resource_id);
544 return sender_->StartRequestWithRetry(request);
547 CancelCallback DriveAPIService::InitiateUploadNewFile(
548 const std::string& content_type,
549 int64 content_length,
550 const std::string& parent_resource_id,
551 const std::string& title,
552 const UploadNewFileOptions& options,
553 const InitiateUploadCallback& callback) {
554 DCHECK(thread_checker_.CalledOnValidThread());
555 DCHECK(!callback.is_null());
557 InitiateUploadNewFileRequest* request =
558 new InitiateUploadNewFileRequest(sender_.get(),
559 url_generator_,
560 content_type,
561 content_length,
562 parent_resource_id,
563 title,
564 callback);
565 request->set_modified_date(options.modified_date);
566 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
567 return sender_->StartRequestWithRetry(request);
570 CancelCallback DriveAPIService::InitiateUploadExistingFile(
571 const std::string& content_type,
572 int64 content_length,
573 const std::string& resource_id,
574 const UploadExistingFileOptions& options,
575 const InitiateUploadCallback& callback) {
576 DCHECK(thread_checker_.CalledOnValidThread());
577 DCHECK(!callback.is_null());
579 InitiateUploadExistingFileRequest* request =
580 new InitiateUploadExistingFileRequest(sender_.get(),
581 url_generator_,
582 content_type,
583 content_length,
584 resource_id,
585 options.etag,
586 callback);
587 request->set_parent_resource_id(options.parent_resource_id);
588 request->set_title(options.title);
589 request->set_modified_date(options.modified_date);
590 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
591 return sender_->StartRequestWithRetry(request);
594 CancelCallback DriveAPIService::ResumeUpload(
595 const GURL& upload_url,
596 int64 start_position,
597 int64 end_position,
598 int64 content_length,
599 const std::string& content_type,
600 const base::FilePath& local_file_path,
601 const UploadRangeCallback& callback,
602 const ProgressCallback& progress_callback) {
603 DCHECK(thread_checker_.CalledOnValidThread());
604 DCHECK(!callback.is_null());
606 return sender_->StartRequestWithRetry(
607 new ResumeUploadRequest(
608 sender_.get(),
609 upload_url,
610 start_position,
611 end_position,
612 content_length,
613 content_type,
614 local_file_path,
615 callback,
616 progress_callback));
619 CancelCallback DriveAPIService::GetUploadStatus(
620 const GURL& upload_url,
621 int64 content_length,
622 const UploadRangeCallback& callback) {
623 DCHECK(thread_checker_.CalledOnValidThread());
624 DCHECK(!callback.is_null());
626 return sender_->StartRequestWithRetry(new GetUploadStatusRequest(
627 sender_.get(),
628 upload_url,
629 content_length,
630 callback));
633 CancelCallback DriveAPIService::MultipartUploadNewFile(
634 const std::string& content_type,
635 int64 content_length,
636 const std::string& parent_resource_id,
637 const std::string& title,
638 const base::FilePath& local_file_path,
639 const UploadNewFileOptions& options,
640 const FileResourceCallback& callback,
641 const google_apis::ProgressCallback& progress_callback) {
642 DCHECK(thread_checker_.CalledOnValidThread());
643 DCHECK(!callback.is_null());
645 return sender_->StartRequestWithRetry(
646 new google_apis::drive::MultipartUploadNewFileRequest(
647 sender_.get(), title, parent_resource_id, content_type,
648 content_length, options.modified_date, options.last_viewed_by_me_date,
649 local_file_path, url_generator_, callback, progress_callback));
652 CancelCallback DriveAPIService::MultipartUploadExistingFile(
653 const std::string& content_type,
654 int64 content_length,
655 const std::string& resource_id,
656 const base::FilePath& local_file_path,
657 const UploadExistingFileOptions& options,
658 const FileResourceCallback& callback,
659 const google_apis::ProgressCallback& progress_callback) {
660 DCHECK(thread_checker_.CalledOnValidThread());
661 DCHECK(!callback.is_null());
663 return sender_->StartRequestWithRetry(
664 new google_apis::drive::MultipartUploadExistingFileRequest(
665 sender_.get(), options.title, resource_id, options.parent_resource_id,
666 content_type, content_length, options.modified_date,
667 options.last_viewed_by_me_date, local_file_path, options.etag,
668 url_generator_, callback, progress_callback));
671 CancelCallback DriveAPIService::AuthorizeApp(
672 const std::string& resource_id,
673 const std::string& app_id,
674 const AuthorizeAppCallback& callback) {
675 DCHECK(thread_checker_.CalledOnValidThread());
676 DCHECK(!callback.is_null());
678 // Files.Authorize is only available for whitelisted clients like official
679 // Google Chrome. In other cases, we fall back to Files.Get that returns the
680 // same value as Files.Authorize without doing authorization. In that case,
681 // the app can open if it was authorized by other means (from whitelisted
682 // clients or drive.google.com web UI.)
683 if (google_apis::IsGoogleChromeAPIKeyUsed()) {
684 google_apis::drive::FilesAuthorizeRequest* request =
685 new google_apis::drive::FilesAuthorizeRequest(
686 sender_.get(), url_generator_,
687 base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
688 request->set_app_id(app_id);
689 request->set_file_id(resource_id);
690 request->set_fields(kFileResourceOpenWithLinksFields);
691 return sender_->StartRequestWithRetry(request);
692 } else {
693 FilesGetRequest* request = new FilesGetRequest(
694 sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
695 base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
696 request->set_file_id(resource_id);
697 request->set_fields(kFileResourceOpenWithLinksFields);
698 return sender_->StartRequestWithRetry(request);
702 CancelCallback DriveAPIService::UninstallApp(
703 const std::string& app_id,
704 const google_apis::EntryActionCallback& callback) {
705 DCHECK(thread_checker_.CalledOnValidThread());
706 DCHECK(!callback.is_null());
708 google_apis::drive::AppsDeleteRequest* request =
709 new google_apis::drive::AppsDeleteRequest(sender_.get(), url_generator_,
710 callback);
711 request->set_app_id(app_id);
712 return sender_->StartRequestWithRetry(request);
715 google_apis::CancelCallback DriveAPIService::AddPermission(
716 const std::string& resource_id,
717 const std::string& email,
718 google_apis::drive::PermissionRole role,
719 const google_apis::EntryActionCallback& callback) {
720 DCHECK(thread_checker_.CalledOnValidThread());
721 DCHECK(!callback.is_null());
723 google_apis::drive::PermissionsInsertRequest* request =
724 new google_apis::drive::PermissionsInsertRequest(sender_.get(),
725 url_generator_,
726 callback);
727 request->set_id(resource_id);
728 request->set_role(role);
729 request->set_type(google_apis::drive::PERMISSION_TYPE_USER);
730 request->set_value(email);
731 return sender_->StartRequestWithRetry(request);
734 bool DriveAPIService::HasAccessToken() const {
735 DCHECK(thread_checker_.CalledOnValidThread());
736 return sender_->auth_service()->HasAccessToken();
739 void DriveAPIService::RequestAccessToken(const AuthStatusCallback& callback) {
740 DCHECK(thread_checker_.CalledOnValidThread());
741 DCHECK(!callback.is_null());
743 const std::string access_token = sender_->auth_service()->access_token();
744 if (!access_token.empty()) {
745 callback.Run(google_apis::HTTP_NOT_MODIFIED, access_token);
746 return;
749 // Retrieve the new auth token.
750 sender_->auth_service()->StartAuthentication(callback);
753 bool DriveAPIService::HasRefreshToken() const {
754 DCHECK(thread_checker_.CalledOnValidThread());
755 return sender_->auth_service()->HasRefreshToken();
758 void DriveAPIService::ClearAccessToken() {
759 DCHECK(thread_checker_.CalledOnValidThread());
760 sender_->auth_service()->ClearAccessToken();
763 void DriveAPIService::ClearRefreshToken() {
764 DCHECK(thread_checker_.CalledOnValidThread());
765 sender_->auth_service()->ClearRefreshToken();
768 void DriveAPIService::OnOAuth2RefreshTokenChanged() {
769 DCHECK(thread_checker_.CalledOnValidThread());
770 if (CanSendRequest()) {
771 FOR_EACH_OBSERVER(
772 DriveServiceObserver, observers_, OnReadyToSendRequests());
773 } else if (!HasRefreshToken()) {
774 FOR_EACH_OBSERVER(
775 DriveServiceObserver, observers_, OnRefreshTokenInvalid());
779 } // namespace drive