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 "components/drive/service/drive_api_service.h"
10 #include "base/bind.h"
11 #include "base/strings/stringprintf.h"
12 #include "components/drive/drive_api_util.h"
13 #include "google_apis/drive/auth_service.h"
14 #include "google_apis/drive/base_requests.h"
15 #include "google_apis/drive/drive_api_parser.h"
16 #include "google_apis/drive/drive_api_requests.h"
17 #include "google_apis/drive/files_list_request_runner.h"
18 #include "google_apis/drive/request_sender.h"
19 #include "google_apis/google_api_keys.h"
20 #include "net/url_request/url_request_context_getter.h"
22 using google_apis::AboutResourceCallback
;
23 using google_apis::AppList
;
24 using google_apis::AppListCallback
;
25 using google_apis::AuthStatusCallback
;
26 using google_apis::AuthorizeAppCallback
;
27 using google_apis::CancelCallback
;
28 using google_apis::ChangeList
;
29 using google_apis::ChangeListCallback
;
30 using google_apis::DownloadActionCallback
;
31 using google_apis::EntryActionCallback
;
32 using google_apis::FileList
;
33 using google_apis::FileListCallback
;
34 using google_apis::FileResource
;
35 using google_apis::FileResourceCallback
;
36 using google_apis::DRIVE_OTHER_ERROR
;
37 using google_apis::DRIVE_PARSE_ERROR
;
38 using google_apis::DriveApiErrorCode
;
39 using google_apis::GetContentCallback
;
40 using google_apis::GetShareUrlCallback
;
41 using google_apis::HTTP_NOT_IMPLEMENTED
;
42 using google_apis::HTTP_SUCCESS
;
43 using google_apis::InitiateUploadCallback
;
44 using google_apis::ProgressCallback
;
45 using google_apis::RequestSender
;
46 using google_apis::FilesListRequestRunner
;
47 using google_apis::UploadRangeResponse
;
48 using google_apis::drive::AboutGetRequest
;
49 using google_apis::drive::AppsListRequest
;
50 using google_apis::drive::ChangesListRequest
;
51 using google_apis::drive::ChangesListNextPageRequest
;
52 using google_apis::drive::ChildrenDeleteRequest
;
53 using google_apis::drive::ChildrenInsertRequest
;
54 using google_apis::drive::DownloadFileRequest
;
55 using google_apis::drive::FilesCopyRequest
;
56 using google_apis::drive::FilesGetRequest
;
57 using google_apis::drive::FilesInsertRequest
;
58 using google_apis::drive::FilesPatchRequest
;
59 using google_apis::drive::FilesListRequest
;
60 using google_apis::drive::FilesListNextPageRequest
;
61 using google_apis::drive::FilesDeleteRequest
;
62 using google_apis::drive::FilesTrashRequest
;
63 using google_apis::drive::GetUploadStatusRequest
;
64 using google_apis::drive::InitiateUploadExistingFileRequest
;
65 using google_apis::drive::InitiateUploadNewFileRequest
;
66 using google_apis::drive::ResumeUploadRequest
;
67 using google_apis::drive::UploadRangeCallback
;
73 // OAuth2 scopes for Drive API.
74 const char kDriveScope
[] = "https://www.googleapis.com/auth/drive";
75 const char kDriveAppsReadonlyScope
[] =
76 "https://www.googleapis.com/auth/drive.apps.readonly";
77 const char kDriveAppsScope
[] = "https://www.googleapis.com/auth/drive.apps";
78 const char kDocsListScope
[] = "https://docs.google.com/feeds/";
80 // Mime type to create a directory.
81 const char kFolderMimeType
[] = "application/vnd.google-apps.folder";
83 // Max number of file entries to be fetched in a single http request.
85 // The larger the number is,
86 // - The total running time to fetch the whole file list will become shorter.
87 // - The running time for a single request tends to become longer.
88 // Since the file list fetching is a completely background task, for our side,
89 // only the total time matters. However, the server seems to have a time limit
90 // per single request, which disables us to set the largest value (1000).
91 // TODO(kinaba): make it larger when the server gets faster.
92 const int kMaxNumFilesResourcePerRequest
= 300;
93 const int kMaxNumFilesResourcePerRequestForSearch
= 100;
95 // For performance, we declare all fields we use.
96 const char kAboutResourceFields
[] =
97 "kind,quotaBytesTotal,quotaBytesUsedAggregate,largestChangeId,rootFolderId";
98 const char kFileResourceFields
[] =
99 "kind,id,title,createdDate,sharedWithMeDate,mimeType,"
100 "md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
101 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
102 "parents(id,parentLink),alternateLink,"
103 "modifiedDate,lastViewedByMeDate,shared";
104 const char kFileResourceOpenWithLinksFields
[] =
105 "kind,id,openWithLinks/*";
106 const char kFileResourceShareLinkFields
[] =
108 const char kFileListFields
[] =
109 "kind,items(kind,id,title,createdDate,sharedWithMeDate,"
110 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
111 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
112 "parents(id,parentLink),alternateLink,"
113 "modifiedDate,lastViewedByMeDate,shared),nextLink";
114 const char kChangeListFields
[] =
115 "kind,items(file(kind,id,title,createdDate,sharedWithMeDate,"
116 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
117 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
118 "parents(id,parentLink),alternateLink,modifiedDate,"
119 "lastViewedByMeDate,shared),deleted,id,fileId,modificationDate),nextLink,"
122 void ExtractOpenUrlAndRun(const std::string
& app_id
,
123 const AuthorizeAppCallback
& callback
,
124 DriveApiErrorCode error
,
125 scoped_ptr
<FileResource
> value
) {
126 DCHECK(!callback
.is_null());
129 callback
.Run(error
, GURL());
133 const std::vector
<FileResource::OpenWithLink
>& open_with_links
=
134 value
->open_with_links();
135 for (size_t i
= 0; i
< open_with_links
.size(); ++i
) {
136 if (open_with_links
[i
].app_id
== app_id
) {
137 callback
.Run(HTTP_SUCCESS
, open_with_links
[i
].open_url
);
143 callback
.Run(DRIVE_OTHER_ERROR
, GURL());
146 void ExtractShareUrlAndRun(const GetShareUrlCallback
& callback
,
147 DriveApiErrorCode error
,
148 scoped_ptr
<FileResource
> value
) {
149 callback
.Run(error
, value
? value
->share_link() : GURL());
152 // Ignores the |entry|, and runs the |callback|.
153 void EntryActionCallbackAdapter(
154 const EntryActionCallback
& callback
,
155 DriveApiErrorCode error
, scoped_ptr
<FileResource
> entry
) {
159 // The resource ID for the root directory for Drive API is defined in the spec:
160 // https://developers.google.com/drive/folder
161 const char kDriveApiRootDirectoryResourceId
[] = "root";
165 BatchRequestConfigurator::BatchRequestConfigurator(
166 const base::WeakPtr
<google_apis::drive::BatchUploadRequest
>& batch_request
,
167 base::SequencedTaskRunner
* task_runner
,
168 const google_apis::DriveApiUrlGenerator
& url_generator
,
169 const google_apis::CancelCallback
& cancel_callback
)
170 : batch_request_(batch_request
),
171 task_runner_(task_runner
),
172 url_generator_(url_generator
),
173 cancel_callback_(cancel_callback
) {
176 BatchRequestConfigurator::~BatchRequestConfigurator() {
177 // The batch requst has not been committed.
179 cancel_callback_
.Run();
182 google_apis::CancelCallback
BatchRequestConfigurator::MultipartUploadNewFile(
183 const std::string
& content_type
,
184 int64 content_length
,
185 const std::string
& parent_resource_id
,
186 const std::string
& title
,
187 const base::FilePath
& local_file_path
,
188 const UploadNewFileOptions
& options
,
189 const google_apis::FileResourceCallback
& callback
,
190 const google_apis::ProgressCallback
& progress_callback
) {
191 DCHECK(CalledOnValidThread());
192 DCHECK(!callback
.is_null());
194 scoped_ptr
<google_apis::BatchableDelegate
> delegate(
195 new google_apis::drive::MultipartUploadNewFileDelegate(
196 task_runner_
.get(), title
, parent_resource_id
, content_type
,
197 content_length
, options
.modified_date
, options
.last_viewed_by_me_date
,
198 local_file_path
, options
.properties
, url_generator_
, callback
,
200 // Batch request can be null when pre-authorization for the requst is failed
201 // in request sender.
203 batch_request_
->AddRequest(delegate
.release());
205 delegate
->NotifyError(DRIVE_OTHER_ERROR
);
206 return cancel_callback_
;
209 google_apis::CancelCallback
210 BatchRequestConfigurator::MultipartUploadExistingFile(
211 const std::string
& content_type
,
212 int64 content_length
,
213 const std::string
& resource_id
,
214 const base::FilePath
& local_file_path
,
215 const UploadExistingFileOptions
& options
,
216 const google_apis::FileResourceCallback
& callback
,
217 const google_apis::ProgressCallback
& progress_callback
) {
218 DCHECK(CalledOnValidThread());
219 DCHECK(!callback
.is_null());
221 scoped_ptr
<google_apis::BatchableDelegate
> delegate(
222 new google_apis::drive::MultipartUploadExistingFileDelegate(
223 task_runner_
.get(), options
.title
, resource_id
,
224 options
.parent_resource_id
, content_type
, content_length
,
225 options
.modified_date
, options
.last_viewed_by_me_date
,
226 local_file_path
, options
.etag
, options
.properties
, url_generator_
,
227 callback
, progress_callback
));
228 // Batch request can be null when pre-authorization for the requst is failed
229 // in request sender.
231 batch_request_
->AddRequest(delegate
.release());
233 delegate
->NotifyError(DRIVE_OTHER_ERROR
);
234 return cancel_callback_
;
237 void BatchRequestConfigurator::Commit() {
238 DCHECK(CalledOnValidThread());
241 batch_request_
->Commit();
242 batch_request_
.reset();
245 DriveAPIService::DriveAPIService(
246 OAuth2TokenService
* oauth2_token_service
,
247 net::URLRequestContextGetter
* url_request_context_getter
,
248 base::SequencedTaskRunner
* blocking_task_runner
,
249 const GURL
& base_url
,
250 const GURL
& base_download_url
,
251 const std::string
& custom_user_agent
)
252 : oauth2_token_service_(oauth2_token_service
),
253 url_request_context_getter_(url_request_context_getter
),
254 blocking_task_runner_(blocking_task_runner
),
255 url_generator_(base_url
, base_download_url
),
256 custom_user_agent_(custom_user_agent
) {
259 DriveAPIService::~DriveAPIService() {
260 DCHECK(thread_checker_
.CalledOnValidThread());
262 sender_
->auth_service()->RemoveObserver(this);
265 void DriveAPIService::Initialize(const std::string
& account_id
) {
266 DCHECK(thread_checker_
.CalledOnValidThread());
268 std::vector
<std::string
> scopes
;
269 scopes
.push_back(kDriveScope
);
270 scopes
.push_back(kDriveAppsReadonlyScope
);
271 scopes
.push_back(kDriveAppsScope
);
273 // Note: The following scope is used to support GetShareUrl on Drive API v2.
274 // Unfortunately, there is no support on Drive API v2, so we need to fall back
275 // to GData WAPI for the GetShareUrl.
276 scopes
.push_back(kDocsListScope
);
278 sender_
.reset(new RequestSender(
279 new google_apis::AuthService(oauth2_token_service_
,
281 url_request_context_getter_
.get(),
283 url_request_context_getter_
.get(),
284 blocking_task_runner_
.get(),
285 custom_user_agent_
));
286 sender_
->auth_service()->AddObserver(this);
288 files_list_request_runner_
.reset(
289 new FilesListRequestRunner(sender_
.get(), url_generator_
));
292 void DriveAPIService::AddObserver(DriveServiceObserver
* observer
) {
293 observers_
.AddObserver(observer
);
296 void DriveAPIService::RemoveObserver(DriveServiceObserver
* observer
) {
297 observers_
.RemoveObserver(observer
);
300 bool DriveAPIService::CanSendRequest() const {
301 DCHECK(thread_checker_
.CalledOnValidThread());
303 return HasRefreshToken();
306 std::string
DriveAPIService::GetRootResourceId() const {
307 return kDriveApiRootDirectoryResourceId
;
310 CancelCallback
DriveAPIService::GetAllFileList(
311 const FileListCallback
& callback
) {
312 DCHECK(thread_checker_
.CalledOnValidThread());
313 DCHECK(!callback
.is_null());
315 FilesListRequest
* request
= new FilesListRequest(
316 sender_
.get(), url_generator_
, callback
);
317 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
318 request
->set_q("trashed = false"); // Exclude trashed files.
319 request
->set_fields(kFileListFields
);
320 return sender_
->StartRequestWithAuthRetry(request
);
323 CancelCallback
DriveAPIService::GetFileListInDirectory(
324 const std::string
& directory_resource_id
,
325 const FileListCallback
& callback
) {
326 DCHECK(thread_checker_
.CalledOnValidThread());
327 DCHECK(!directory_resource_id
.empty());
328 DCHECK(!callback
.is_null());
330 // Because children.list method on Drive API v2 returns only the list of
331 // children's references, but we need all file resource list.
332 // So, here we use files.list method instead, with setting parents query.
333 // After the migration from GData WAPI to Drive API v2, we should clean the
334 // code up by moving the responsibility to include "parents" in the query
336 // We aren't interested in files in trash in this context, neither.
337 return files_list_request_runner_
->CreateAndStartWithSizeBackoff(
338 kMaxNumFilesResourcePerRequest
,
340 "'%s' in parents and trashed = false",
341 util::EscapeQueryStringValue(directory_resource_id
).c_str()),
342 kFileListFields
, callback
);
345 CancelCallback
DriveAPIService::Search(
346 const std::string
& search_query
,
347 const FileListCallback
& callback
) {
348 DCHECK(thread_checker_
.CalledOnValidThread());
349 DCHECK(!search_query
.empty());
350 DCHECK(!callback
.is_null());
352 return files_list_request_runner_
->CreateAndStartWithSizeBackoff(
353 kMaxNumFilesResourcePerRequestForSearch
,
354 util::TranslateQuery(search_query
), kFileListFields
, callback
);
357 CancelCallback
DriveAPIService::SearchByTitle(
358 const std::string
& title
,
359 const std::string
& directory_resource_id
,
360 const FileListCallback
& callback
) {
361 DCHECK(thread_checker_
.CalledOnValidThread());
362 DCHECK(!title
.empty());
363 DCHECK(!callback
.is_null());
366 base::StringAppendF(&query
, "title = '%s'",
367 util::EscapeQueryStringValue(title
).c_str());
368 if (!directory_resource_id
.empty()) {
370 &query
, " and '%s' in parents",
371 util::EscapeQueryStringValue(directory_resource_id
).c_str());
373 query
+= " and trashed = false";
375 FilesListRequest
* request
= new FilesListRequest(
376 sender_
.get(), url_generator_
, callback
);
377 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
378 request
->set_q(query
);
379 request
->set_fields(kFileListFields
);
380 return sender_
->StartRequestWithAuthRetry(request
);
383 CancelCallback
DriveAPIService::GetChangeList(
384 int64 start_changestamp
,
385 const ChangeListCallback
& callback
) {
386 DCHECK(thread_checker_
.CalledOnValidThread());
387 DCHECK(!callback
.is_null());
389 ChangesListRequest
* request
= new ChangesListRequest(
390 sender_
.get(), url_generator_
, callback
);
391 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
392 request
->set_start_change_id(start_changestamp
);
393 request
->set_fields(kChangeListFields
);
394 return sender_
->StartRequestWithAuthRetry(request
);
397 CancelCallback
DriveAPIService::GetRemainingChangeList(
398 const GURL
& next_link
,
399 const ChangeListCallback
& callback
) {
400 DCHECK(thread_checker_
.CalledOnValidThread());
401 DCHECK(!next_link
.is_empty());
402 DCHECK(!callback
.is_null());
404 ChangesListNextPageRequest
* request
= new ChangesListNextPageRequest(
405 sender_
.get(), callback
);
406 request
->set_next_link(next_link
);
407 request
->set_fields(kChangeListFields
);
408 return sender_
->StartRequestWithAuthRetry(request
);
411 CancelCallback
DriveAPIService::GetRemainingFileList(
412 const GURL
& next_link
,
413 const FileListCallback
& callback
) {
414 DCHECK(thread_checker_
.CalledOnValidThread());
415 DCHECK(!next_link
.is_empty());
416 DCHECK(!callback
.is_null());
418 FilesListNextPageRequest
* request
= new FilesListNextPageRequest(
419 sender_
.get(), callback
);
420 request
->set_next_link(next_link
);
421 request
->set_fields(kFileListFields
);
422 return sender_
->StartRequestWithAuthRetry(request
);
425 CancelCallback
DriveAPIService::GetFileResource(
426 const std::string
& resource_id
,
427 const FileResourceCallback
& callback
) {
428 DCHECK(thread_checker_
.CalledOnValidThread());
429 DCHECK(!callback
.is_null());
431 FilesGetRequest
* request
= new FilesGetRequest(
432 sender_
.get(), url_generator_
, google_apis::IsGoogleChromeAPIKeyUsed(),
434 request
->set_file_id(resource_id
);
435 request
->set_fields(kFileResourceFields
);
436 return sender_
->StartRequestWithAuthRetry(request
);
439 CancelCallback
DriveAPIService::GetShareUrl(
440 const std::string
& resource_id
,
441 const GURL
& embed_origin
,
442 const GetShareUrlCallback
& callback
) {
443 DCHECK(thread_checker_
.CalledOnValidThread());
444 DCHECK(!callback
.is_null());
446 if (!google_apis::IsGoogleChromeAPIKeyUsed()) {
447 LOG(ERROR
) << "Only the official build of Chrome OS can open share dialogs "
448 << "from the file manager.";
451 FilesGetRequest
* request
= new FilesGetRequest(
452 sender_
.get(), url_generator_
, google_apis::IsGoogleChromeAPIKeyUsed(),
453 base::Bind(&ExtractShareUrlAndRun
, callback
));
454 request
->set_file_id(resource_id
);
455 request
->set_fields(kFileResourceShareLinkFields
);
456 request
->set_embed_origin(embed_origin
);
457 return sender_
->StartRequestWithAuthRetry(request
);
460 CancelCallback
DriveAPIService::GetAboutResource(
461 const AboutResourceCallback
& callback
) {
462 DCHECK(thread_checker_
.CalledOnValidThread());
463 DCHECK(!callback
.is_null());
465 AboutGetRequest
* request
=
466 new AboutGetRequest(sender_
.get(), url_generator_
, callback
);
467 request
->set_fields(kAboutResourceFields
);
468 return sender_
->StartRequestWithAuthRetry(request
);
471 CancelCallback
DriveAPIService::GetAppList(const AppListCallback
& callback
) {
472 DCHECK(thread_checker_
.CalledOnValidThread());
473 DCHECK(!callback
.is_null());
475 return sender_
->StartRequestWithAuthRetry(
476 new AppsListRequest(sender_
.get(), url_generator_
,
477 google_apis::IsGoogleChromeAPIKeyUsed(), callback
));
480 CancelCallback
DriveAPIService::DownloadFile(
481 const base::FilePath
& local_cache_path
,
482 const std::string
& resource_id
,
483 const DownloadActionCallback
& download_action_callback
,
484 const GetContentCallback
& get_content_callback
,
485 const ProgressCallback
& progress_callback
) {
486 DCHECK(thread_checker_
.CalledOnValidThread());
487 DCHECK(!download_action_callback
.is_null());
488 // get_content_callback may be null.
490 return sender_
->StartRequestWithAuthRetry(new DownloadFileRequest(
491 sender_
.get(), url_generator_
, resource_id
, local_cache_path
,
492 download_action_callback
, get_content_callback
, progress_callback
));
495 CancelCallback
DriveAPIService::DeleteResource(
496 const std::string
& resource_id
,
497 const std::string
& etag
,
498 const EntryActionCallback
& callback
) {
499 DCHECK(thread_checker_
.CalledOnValidThread());
500 DCHECK(!callback
.is_null());
502 FilesDeleteRequest
* request
= new FilesDeleteRequest(
503 sender_
.get(), url_generator_
, callback
);
504 request
->set_file_id(resource_id
);
505 request
->set_etag(etag
);
506 return sender_
->StartRequestWithAuthRetry(request
);
509 CancelCallback
DriveAPIService::TrashResource(
510 const std::string
& resource_id
,
511 const EntryActionCallback
& callback
) {
512 DCHECK(thread_checker_
.CalledOnValidThread());
513 DCHECK(!callback
.is_null());
515 FilesTrashRequest
* request
= new FilesTrashRequest(
516 sender_
.get(), url_generator_
,
517 base::Bind(&EntryActionCallbackAdapter
, callback
));
518 request
->set_file_id(resource_id
);
519 request
->set_fields(kFileResourceFields
);
520 return sender_
->StartRequestWithAuthRetry(request
);
523 CancelCallback
DriveAPIService::AddNewDirectory(
524 const std::string
& parent_resource_id
,
525 const std::string
& directory_title
,
526 const AddNewDirectoryOptions
& options
,
527 const FileResourceCallback
& callback
) {
528 DCHECK(thread_checker_
.CalledOnValidThread());
529 DCHECK(!callback
.is_null());
531 FilesInsertRequest
* request
= new FilesInsertRequest(
532 sender_
.get(), url_generator_
, callback
);
533 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
534 request
->set_mime_type(kFolderMimeType
);
535 request
->set_modified_date(options
.modified_date
);
536 request
->add_parent(parent_resource_id
);
537 request
->set_title(directory_title
);
538 request
->set_properties(options
.properties
);
539 request
->set_fields(kFileResourceFields
);
540 return sender_
->StartRequestWithAuthRetry(request
);
543 CancelCallback
DriveAPIService::CopyResource(
544 const std::string
& resource_id
,
545 const std::string
& parent_resource_id
,
546 const std::string
& new_title
,
547 const base::Time
& last_modified
,
548 const FileResourceCallback
& callback
) {
549 DCHECK(thread_checker_
.CalledOnValidThread());
550 DCHECK(!callback
.is_null());
552 FilesCopyRequest
* request
= new FilesCopyRequest(
553 sender_
.get(), url_generator_
, callback
);
554 request
->set_file_id(resource_id
);
555 request
->add_parent(parent_resource_id
);
556 request
->set_title(new_title
);
557 request
->set_modified_date(last_modified
);
558 request
->set_fields(kFileResourceFields
);
559 return sender_
->StartRequestWithAuthRetry(request
);
562 CancelCallback
DriveAPIService::UpdateResource(
563 const std::string
& resource_id
,
564 const std::string
& parent_resource_id
,
565 const std::string
& new_title
,
566 const base::Time
& last_modified
,
567 const base::Time
& last_viewed_by_me
,
568 const google_apis::drive::Properties
& properties
,
569 const FileResourceCallback
& callback
) {
570 DCHECK(thread_checker_
.CalledOnValidThread());
571 DCHECK(!callback
.is_null());
573 FilesPatchRequest
* request
= new FilesPatchRequest(
574 sender_
.get(), url_generator_
, callback
);
575 request
->set_file_id(resource_id
);
576 request
->set_title(new_title
);
577 if (!parent_resource_id
.empty())
578 request
->add_parent(parent_resource_id
);
579 if (!last_modified
.is_null()) {
580 // Need to set setModifiedDate to true to overwrite modifiedDate.
581 request
->set_set_modified_date(true);
582 request
->set_modified_date(last_modified
);
584 if (!last_viewed_by_me
.is_null()) {
585 // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
586 // will be set to the request time (not the specified time via request).
587 request
->set_update_viewed_date(false);
588 request
->set_last_viewed_by_me_date(last_viewed_by_me
);
590 request
->set_fields(kFileResourceFields
);
591 request
->set_properties(properties
);
592 return sender_
->StartRequestWithAuthRetry(request
);
595 CancelCallback
DriveAPIService::AddResourceToDirectory(
596 const std::string
& parent_resource_id
,
597 const std::string
& resource_id
,
598 const EntryActionCallback
& callback
) {
599 DCHECK(thread_checker_
.CalledOnValidThread());
600 DCHECK(!callback
.is_null());
602 ChildrenInsertRequest
* request
=
603 new ChildrenInsertRequest(sender_
.get(), url_generator_
, callback
);
604 request
->set_folder_id(parent_resource_id
);
605 request
->set_id(resource_id
);
606 return sender_
->StartRequestWithAuthRetry(request
);
609 CancelCallback
DriveAPIService::RemoveResourceFromDirectory(
610 const std::string
& parent_resource_id
,
611 const std::string
& resource_id
,
612 const EntryActionCallback
& callback
) {
613 DCHECK(thread_checker_
.CalledOnValidThread());
614 DCHECK(!callback
.is_null());
616 ChildrenDeleteRequest
* request
=
617 new ChildrenDeleteRequest(sender_
.get(), url_generator_
, callback
);
618 request
->set_child_id(resource_id
);
619 request
->set_folder_id(parent_resource_id
);
620 return sender_
->StartRequestWithAuthRetry(request
);
623 CancelCallback
DriveAPIService::InitiateUploadNewFile(
624 const std::string
& content_type
,
625 int64 content_length
,
626 const std::string
& parent_resource_id
,
627 const std::string
& title
,
628 const UploadNewFileOptions
& options
,
629 const InitiateUploadCallback
& callback
) {
630 DCHECK(thread_checker_
.CalledOnValidThread());
631 DCHECK(!callback
.is_null());
633 InitiateUploadNewFileRequest
* request
=
634 new InitiateUploadNewFileRequest(sender_
.get(),
641 request
->set_modified_date(options
.modified_date
);
642 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
643 request
->set_properties(options
.properties
);
644 return sender_
->StartRequestWithAuthRetry(request
);
647 CancelCallback
DriveAPIService::InitiateUploadExistingFile(
648 const std::string
& content_type
,
649 int64 content_length
,
650 const std::string
& resource_id
,
651 const UploadExistingFileOptions
& options
,
652 const InitiateUploadCallback
& callback
) {
653 DCHECK(thread_checker_
.CalledOnValidThread());
654 DCHECK(!callback
.is_null());
656 InitiateUploadExistingFileRequest
* request
=
657 new InitiateUploadExistingFileRequest(sender_
.get(),
664 request
->set_parent_resource_id(options
.parent_resource_id
);
665 request
->set_title(options
.title
);
666 request
->set_modified_date(options
.modified_date
);
667 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
668 request
->set_properties(options
.properties
);
669 return sender_
->StartRequestWithAuthRetry(request
);
672 CancelCallback
DriveAPIService::ResumeUpload(
673 const GURL
& upload_url
,
674 int64 start_position
,
676 int64 content_length
,
677 const std::string
& content_type
,
678 const base::FilePath
& local_file_path
,
679 const UploadRangeCallback
& callback
,
680 const ProgressCallback
& progress_callback
) {
681 DCHECK(thread_checker_
.CalledOnValidThread());
682 DCHECK(!callback
.is_null());
684 return sender_
->StartRequestWithAuthRetry(new ResumeUploadRequest(
685 sender_
.get(), upload_url
, start_position
, end_position
, content_length
,
686 content_type
, local_file_path
, callback
, progress_callback
));
689 CancelCallback
DriveAPIService::GetUploadStatus(
690 const GURL
& upload_url
,
691 int64 content_length
,
692 const UploadRangeCallback
& callback
) {
693 DCHECK(thread_checker_
.CalledOnValidThread());
694 DCHECK(!callback
.is_null());
696 return sender_
->StartRequestWithAuthRetry(new GetUploadStatusRequest(
697 sender_
.get(), upload_url
, content_length
, callback
));
700 CancelCallback
DriveAPIService::MultipartUploadNewFile(
701 const std::string
& content_type
,
702 int64 content_length
,
703 const std::string
& parent_resource_id
,
704 const std::string
& title
,
705 const base::FilePath
& local_file_path
,
706 const drive::UploadNewFileOptions
& options
,
707 const FileResourceCallback
& callback
,
708 const google_apis::ProgressCallback
& progress_callback
) {
709 DCHECK(thread_checker_
.CalledOnValidThread());
710 DCHECK(!callback
.is_null());
712 return sender_
->StartRequestWithAuthRetry(
713 new google_apis::drive::SingleBatchableDelegateRequest(
715 new google_apis::drive::MultipartUploadNewFileDelegate(
716 sender_
->blocking_task_runner(), title
, parent_resource_id
,
717 content_type
, content_length
, options
.modified_date
,
718 options
.last_viewed_by_me_date
, local_file_path
,
719 options
.properties
, url_generator_
, callback
,
720 progress_callback
)));
723 CancelCallback
DriveAPIService::MultipartUploadExistingFile(
724 const std::string
& content_type
,
725 int64 content_length
,
726 const std::string
& resource_id
,
727 const base::FilePath
& local_file_path
,
728 const drive::UploadExistingFileOptions
& options
,
729 const FileResourceCallback
& callback
,
730 const google_apis::ProgressCallback
& progress_callback
) {
731 DCHECK(thread_checker_
.CalledOnValidThread());
732 DCHECK(!callback
.is_null());
734 return sender_
->StartRequestWithAuthRetry(
735 new google_apis::drive::SingleBatchableDelegateRequest(
737 new google_apis::drive::MultipartUploadExistingFileDelegate(
738 sender_
->blocking_task_runner(), options
.title
, resource_id
,
739 options
.parent_resource_id
, content_type
, content_length
,
740 options
.modified_date
, options
.last_viewed_by_me_date
,
741 local_file_path
, options
.etag
, options
.properties
, url_generator_
,
742 callback
, progress_callback
)));
745 CancelCallback
DriveAPIService::AuthorizeApp(
746 const std::string
& resource_id
,
747 const std::string
& app_id
,
748 const AuthorizeAppCallback
& callback
) {
749 DCHECK(thread_checker_
.CalledOnValidThread());
750 DCHECK(!callback
.is_null());
752 // Files.Authorize is only available for whitelisted clients like official
753 // Google Chrome. In other cases, we fall back to Files.Get that returns the
754 // same value as Files.Authorize without doing authorization. In that case,
755 // the app can open if it was authorized by other means (from whitelisted
756 // clients or drive.google.com web UI.)
757 if (google_apis::IsGoogleChromeAPIKeyUsed()) {
758 google_apis::drive::FilesAuthorizeRequest
* request
=
759 new google_apis::drive::FilesAuthorizeRequest(
760 sender_
.get(), url_generator_
,
761 base::Bind(&ExtractOpenUrlAndRun
, app_id
, callback
));
762 request
->set_app_id(app_id
);
763 request
->set_file_id(resource_id
);
764 request
->set_fields(kFileResourceOpenWithLinksFields
);
765 return sender_
->StartRequestWithAuthRetry(request
);
767 FilesGetRequest
* request
= new FilesGetRequest(
768 sender_
.get(), url_generator_
, google_apis::IsGoogleChromeAPIKeyUsed(),
769 base::Bind(&ExtractOpenUrlAndRun
, app_id
, callback
));
770 request
->set_file_id(resource_id
);
771 request
->set_fields(kFileResourceOpenWithLinksFields
);
772 return sender_
->StartRequestWithAuthRetry(request
);
776 CancelCallback
DriveAPIService::UninstallApp(
777 const std::string
& app_id
,
778 const google_apis::EntryActionCallback
& callback
) {
779 DCHECK(thread_checker_
.CalledOnValidThread());
780 DCHECK(!callback
.is_null());
782 google_apis::drive::AppsDeleteRequest
* request
=
783 new google_apis::drive::AppsDeleteRequest(sender_
.get(), url_generator_
,
785 request
->set_app_id(app_id
);
786 return sender_
->StartRequestWithAuthRetry(request
);
789 google_apis::CancelCallback
DriveAPIService::AddPermission(
790 const std::string
& resource_id
,
791 const std::string
& email
,
792 google_apis::drive::PermissionRole role
,
793 const google_apis::EntryActionCallback
& callback
) {
794 DCHECK(thread_checker_
.CalledOnValidThread());
795 DCHECK(!callback
.is_null());
797 google_apis::drive::PermissionsInsertRequest
* request
=
798 new google_apis::drive::PermissionsInsertRequest(sender_
.get(),
801 request
->set_id(resource_id
);
802 request
->set_role(role
);
803 request
->set_type(google_apis::drive::PERMISSION_TYPE_USER
);
804 request
->set_value(email
);
805 return sender_
->StartRequestWithAuthRetry(request
);
808 bool DriveAPIService::HasAccessToken() const {
809 DCHECK(thread_checker_
.CalledOnValidThread());
810 return sender_
->auth_service()->HasAccessToken();
813 void DriveAPIService::RequestAccessToken(const AuthStatusCallback
& callback
) {
814 DCHECK(thread_checker_
.CalledOnValidThread());
815 DCHECK(!callback
.is_null());
817 const std::string access_token
= sender_
->auth_service()->access_token();
818 if (!access_token
.empty()) {
819 callback
.Run(google_apis::HTTP_NOT_MODIFIED
, access_token
);
823 // Retrieve the new auth token.
824 sender_
->auth_service()->StartAuthentication(callback
);
827 bool DriveAPIService::HasRefreshToken() const {
828 DCHECK(thread_checker_
.CalledOnValidThread());
829 return sender_
->auth_service()->HasRefreshToken();
832 void DriveAPIService::ClearAccessToken() {
833 DCHECK(thread_checker_
.CalledOnValidThread());
834 sender_
->auth_service()->ClearAccessToken();
837 void DriveAPIService::ClearRefreshToken() {
838 DCHECK(thread_checker_
.CalledOnValidThread());
839 sender_
->auth_service()->ClearRefreshToken();
842 void DriveAPIService::OnOAuth2RefreshTokenChanged() {
843 DCHECK(thread_checker_
.CalledOnValidThread());
844 if (CanSendRequest()) {
846 DriveServiceObserver
, observers_
, OnReadyToSendRequests());
847 } else if (!HasRefreshToken()) {
849 DriveServiceObserver
, observers_
, OnRefreshTokenInvalid());
853 scoped_ptr
<BatchRequestConfiguratorInterface
>
854 DriveAPIService::StartBatchRequest() {
855 scoped_ptr
<google_apis::drive::BatchUploadRequest
> request(
856 new google_apis::drive::BatchUploadRequest(sender_
.get(),
858 const base::WeakPtr
<google_apis::drive::BatchUploadRequest
> weak_ref
=
859 request
->GetWeakPtrAsBatchUploadRequest();
860 // Have sender_ manage the lifetime of the request.
861 // TODO(hirono): Currently we need to pass the ownership of the request to
862 // RequestSender before the request is committed because the request has a
863 // reference to RequestSender and we should ensure to delete the request when
864 // the sender is deleted. Resolve the circulating dependency and fix it.
865 const google_apis::CancelCallback callback
=
866 sender_
->StartRequestWithAuthRetry(request
.release());
867 return make_scoped_ptr
<BatchRequestConfiguratorInterface
>(
868 new BatchRequestConfigurator(weak_ref
, sender_
->blocking_task_runner(),
869 url_generator_
, callback
));