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"
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
;
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
[] =
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,"
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());
126 callback
.Run(error
, GURL());
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
);
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
) {
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";
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());
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_
,
198 url_request_context_getter_
.get(),
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
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());
285 base::StringAppendF(&query
, "title = '%s'",
286 util::EscapeQueryStringValue(title
).c_str());
287 if (!directory_resource_id
.empty()) {
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(),
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(),
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(),
415 download_action_callback
,
416 get_content_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(),
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(),
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
,
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(
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(
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
);
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_
,
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(),
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
);
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()) {
772 DriveServiceObserver
, observers_
, OnReadyToSendRequests());
773 } else if (!HasRefreshToken()) {
775 DriveServiceObserver
, observers_
, OnRefreshTokenInvalid());