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 BatchRequestConfigurator::BatchRequestConfigurator(
163 const base::WeakPtr
<google_apis::drive::BatchUploadRequest
>& batch_request
,
164 const google_apis::CancelCallback
& cancel_callback
)
165 : batch_request_(batch_request
), cancel_callback_(cancel_callback
) {
168 BatchRequestConfigurator::~BatchRequestConfigurator() {
169 // The batch requst has not been committed.
171 cancel_callback_
.Run();
174 google_apis::CancelCallback
BatchRequestConfigurator::MultipartUploadNewFile(
175 const std::string
& content_type
,
176 int64 content_length
,
177 const std::string
& parent_resource_id
,
178 const std::string
& title
,
179 const base::FilePath
& local_file_path
,
180 const UploadNewFileOptions
& options
,
181 const google_apis::FileResourceCallback
& callback
,
182 const google_apis::ProgressCallback
& progress_callback
) {
183 DCHECK(CalledOnValidThread());
184 DCHECK(!callback
.is_null());
186 DCHECK(batch_request_
);
188 batch_request_
->AddRequest(
189 new google_apis::drive::MultipartUploadNewFileRequest(
190 batch_request_
->sender(), title
, parent_resource_id
, content_type
,
191 content_length
, options
.modified_date
, options
.last_viewed_by_me_date
,
192 local_file_path
, options
.properties
, batch_request_
->url_generator(),
193 callback
, progress_callback
));
194 return cancel_callback_
;
197 google_apis::CancelCallback
198 BatchRequestConfigurator::MultipartUploadExistingFile(
199 const std::string
& content_type
,
200 int64 content_length
,
201 const std::string
& resource_id
,
202 const base::FilePath
& local_file_path
,
203 const UploadExistingFileOptions
& options
,
204 const google_apis::FileResourceCallback
& callback
,
205 const google_apis::ProgressCallback
& progress_callback
) {
206 DCHECK(CalledOnValidThread());
207 DCHECK(!callback
.is_null());
208 DCHECK(batch_request_
);
210 batch_request_
->AddRequest(
211 new google_apis::drive::MultipartUploadExistingFileRequest(
212 batch_request_
->sender(), options
.title
, resource_id
,
213 options
.parent_resource_id
, content_type
, content_length
,
214 options
.modified_date
, options
.last_viewed_by_me_date
,
215 local_file_path
, options
.etag
, options
.properties
,
216 batch_request_
->url_generator(), callback
, progress_callback
));
217 return cancel_callback_
;
220 void BatchRequestConfigurator::Commit() {
221 DCHECK(CalledOnValidThread());
224 batch_request_
->Commit();
225 batch_request_
.reset();
228 DriveAPIService::DriveAPIService(
229 OAuth2TokenService
* oauth2_token_service
,
230 net::URLRequestContextGetter
* url_request_context_getter
,
231 base::SequencedTaskRunner
* blocking_task_runner
,
232 const GURL
& base_url
,
233 const GURL
& base_download_url
,
234 const std::string
& custom_user_agent
)
235 : oauth2_token_service_(oauth2_token_service
),
236 url_request_context_getter_(url_request_context_getter
),
237 blocking_task_runner_(blocking_task_runner
),
238 url_generator_(base_url
, base_download_url
),
239 custom_user_agent_(custom_user_agent
) {
242 DriveAPIService::~DriveAPIService() {
243 DCHECK(thread_checker_
.CalledOnValidThread());
245 sender_
->auth_service()->RemoveObserver(this);
248 void DriveAPIService::Initialize(const std::string
& account_id
) {
249 DCHECK(thread_checker_
.CalledOnValidThread());
251 std::vector
<std::string
> scopes
;
252 scopes
.push_back(kDriveScope
);
253 scopes
.push_back(kDriveAppsReadonlyScope
);
254 scopes
.push_back(kDriveAppsScope
);
256 // Note: The following scope is used to support GetShareUrl on Drive API v2.
257 // Unfortunately, there is no support on Drive API v2, so we need to fall back
258 // to GData WAPI for the GetShareUrl.
259 scopes
.push_back(kDocsListScope
);
261 sender_
.reset(new RequestSender(
262 new google_apis::AuthService(oauth2_token_service_
,
264 url_request_context_getter_
.get(),
266 url_request_context_getter_
.get(),
267 blocking_task_runner_
.get(),
268 custom_user_agent_
));
269 sender_
->auth_service()->AddObserver(this);
272 void DriveAPIService::AddObserver(DriveServiceObserver
* observer
) {
273 observers_
.AddObserver(observer
);
276 void DriveAPIService::RemoveObserver(DriveServiceObserver
* observer
) {
277 observers_
.RemoveObserver(observer
);
280 bool DriveAPIService::CanSendRequest() const {
281 DCHECK(thread_checker_
.CalledOnValidThread());
283 return HasRefreshToken();
286 std::string
DriveAPIService::GetRootResourceId() const {
287 return kDriveApiRootDirectoryResourceId
;
290 CancelCallback
DriveAPIService::GetAllFileList(
291 const FileListCallback
& callback
) {
292 DCHECK(thread_checker_
.CalledOnValidThread());
293 DCHECK(!callback
.is_null());
295 FilesListRequest
* request
= new FilesListRequest(
296 sender_
.get(), url_generator_
, callback
);
297 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
298 request
->set_q("trashed = false"); // Exclude trashed files.
299 request
->set_fields(kFileListFields
);
300 return sender_
->StartRequestWithRetry(request
);
303 CancelCallback
DriveAPIService::GetFileListInDirectory(
304 const std::string
& directory_resource_id
,
305 const FileListCallback
& callback
) {
306 DCHECK(thread_checker_
.CalledOnValidThread());
307 DCHECK(!directory_resource_id
.empty());
308 DCHECK(!callback
.is_null());
310 // Because children.list method on Drive API v2 returns only the list of
311 // children's references, but we need all file resource list.
312 // So, here we use files.list method instead, with setting parents query.
313 // After the migration from GData WAPI to Drive API v2, we should clean the
314 // code up by moving the responsibility to include "parents" in the query
316 // We aren't interested in files in trash in this context, neither.
317 FilesListRequest
* request
= new FilesListRequest(
318 sender_
.get(), url_generator_
, callback
);
319 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
320 request
->set_q(base::StringPrintf(
321 "'%s' in parents and trashed = false",
322 util::EscapeQueryStringValue(directory_resource_id
).c_str()));
323 request
->set_fields(kFileListFields
);
324 return sender_
->StartRequestWithRetry(request
);
327 CancelCallback
DriveAPIService::Search(
328 const std::string
& search_query
,
329 const FileListCallback
& callback
) {
330 DCHECK(thread_checker_
.CalledOnValidThread());
331 DCHECK(!search_query
.empty());
332 DCHECK(!callback
.is_null());
334 FilesListRequest
* request
= new FilesListRequest(
335 sender_
.get(), url_generator_
, callback
);
336 request
->set_max_results(kMaxNumFilesResourcePerRequestForSearch
);
337 request
->set_q(util::TranslateQuery(search_query
));
338 request
->set_fields(kFileListFields
);
339 return sender_
->StartRequestWithRetry(request
);
342 CancelCallback
DriveAPIService::SearchByTitle(
343 const std::string
& title
,
344 const std::string
& directory_resource_id
,
345 const FileListCallback
& callback
) {
346 DCHECK(thread_checker_
.CalledOnValidThread());
347 DCHECK(!title
.empty());
348 DCHECK(!callback
.is_null());
351 base::StringAppendF(&query
, "title = '%s'",
352 util::EscapeQueryStringValue(title
).c_str());
353 if (!directory_resource_id
.empty()) {
355 &query
, " and '%s' in parents",
356 util::EscapeQueryStringValue(directory_resource_id
).c_str());
358 query
+= " and trashed = false";
360 FilesListRequest
* request
= new FilesListRequest(
361 sender_
.get(), url_generator_
, callback
);
362 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
363 request
->set_q(query
);
364 request
->set_fields(kFileListFields
);
365 return sender_
->StartRequestWithRetry(request
);
368 CancelCallback
DriveAPIService::GetChangeList(
369 int64 start_changestamp
,
370 const ChangeListCallback
& callback
) {
371 DCHECK(thread_checker_
.CalledOnValidThread());
372 DCHECK(!callback
.is_null());
374 ChangesListRequest
* request
= new ChangesListRequest(
375 sender_
.get(), url_generator_
, callback
);
376 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
377 request
->set_start_change_id(start_changestamp
);
378 request
->set_fields(kChangeListFields
);
379 return sender_
->StartRequestWithRetry(request
);
382 CancelCallback
DriveAPIService::GetRemainingChangeList(
383 const GURL
& next_link
,
384 const ChangeListCallback
& callback
) {
385 DCHECK(thread_checker_
.CalledOnValidThread());
386 DCHECK(!next_link
.is_empty());
387 DCHECK(!callback
.is_null());
389 ChangesListNextPageRequest
* request
= new ChangesListNextPageRequest(
390 sender_
.get(), callback
);
391 request
->set_next_link(next_link
);
392 request
->set_fields(kChangeListFields
);
393 return sender_
->StartRequestWithRetry(request
);
396 CancelCallback
DriveAPIService::GetRemainingFileList(
397 const GURL
& next_link
,
398 const FileListCallback
& callback
) {
399 DCHECK(thread_checker_
.CalledOnValidThread());
400 DCHECK(!next_link
.is_empty());
401 DCHECK(!callback
.is_null());
403 FilesListNextPageRequest
* request
= new FilesListNextPageRequest(
404 sender_
.get(), callback
);
405 request
->set_next_link(next_link
);
406 request
->set_fields(kFileListFields
);
407 return sender_
->StartRequestWithRetry(request
);
410 CancelCallback
DriveAPIService::GetFileResource(
411 const std::string
& resource_id
,
412 const FileResourceCallback
& callback
) {
413 DCHECK(thread_checker_
.CalledOnValidThread());
414 DCHECK(!callback
.is_null());
416 FilesGetRequest
* request
= new FilesGetRequest(
417 sender_
.get(), url_generator_
, google_apis::IsGoogleChromeAPIKeyUsed(),
419 request
->set_file_id(resource_id
);
420 request
->set_fields(kFileResourceFields
);
421 return sender_
->StartRequestWithRetry(request
);
424 CancelCallback
DriveAPIService::GetShareUrl(
425 const std::string
& resource_id
,
426 const GURL
& embed_origin
,
427 const GetShareUrlCallback
& callback
) {
428 DCHECK(thread_checker_
.CalledOnValidThread());
429 DCHECK(!callback
.is_null());
431 if (!google_apis::IsGoogleChromeAPIKeyUsed()) {
432 LOG(ERROR
) << "Only the official build of Chrome OS can open share dialogs "
433 << "from the file manager.";
436 FilesGetRequest
* request
= new FilesGetRequest(
437 sender_
.get(), url_generator_
, google_apis::IsGoogleChromeAPIKeyUsed(),
438 base::Bind(&ExtractShareUrlAndRun
, callback
));
439 request
->set_file_id(resource_id
);
440 request
->set_fields(kFileResourceShareLinkFields
);
441 request
->set_embed_origin(embed_origin
);
442 return sender_
->StartRequestWithRetry(request
);
445 CancelCallback
DriveAPIService::GetAboutResource(
446 const AboutResourceCallback
& callback
) {
447 DCHECK(thread_checker_
.CalledOnValidThread());
448 DCHECK(!callback
.is_null());
450 AboutGetRequest
* request
=
451 new AboutGetRequest(sender_
.get(), url_generator_
, callback
);
452 request
->set_fields(kAboutResourceFields
);
453 return sender_
->StartRequestWithRetry(request
);
456 CancelCallback
DriveAPIService::GetAppList(const AppListCallback
& callback
) {
457 DCHECK(thread_checker_
.CalledOnValidThread());
458 DCHECK(!callback
.is_null());
460 return sender_
->StartRequestWithRetry(
461 new AppsListRequest(sender_
.get(), url_generator_
,
462 google_apis::IsGoogleChromeAPIKeyUsed(),
466 CancelCallback
DriveAPIService::DownloadFile(
467 const base::FilePath
& local_cache_path
,
468 const std::string
& resource_id
,
469 const DownloadActionCallback
& download_action_callback
,
470 const GetContentCallback
& get_content_callback
,
471 const ProgressCallback
& progress_callback
) {
472 DCHECK(thread_checker_
.CalledOnValidThread());
473 DCHECK(!download_action_callback
.is_null());
474 // get_content_callback may be null.
476 return sender_
->StartRequestWithRetry(
477 new DownloadFileRequest(sender_
.get(),
481 download_action_callback
,
482 get_content_callback
,
486 CancelCallback
DriveAPIService::DeleteResource(
487 const std::string
& resource_id
,
488 const std::string
& etag
,
489 const EntryActionCallback
& callback
) {
490 DCHECK(thread_checker_
.CalledOnValidThread());
491 DCHECK(!callback
.is_null());
493 FilesDeleteRequest
* request
= new FilesDeleteRequest(
494 sender_
.get(), url_generator_
, callback
);
495 request
->set_file_id(resource_id
);
496 request
->set_etag(etag
);
497 return sender_
->StartRequestWithRetry(request
);
500 CancelCallback
DriveAPIService::TrashResource(
501 const std::string
& resource_id
,
502 const EntryActionCallback
& callback
) {
503 DCHECK(thread_checker_
.CalledOnValidThread());
504 DCHECK(!callback
.is_null());
506 FilesTrashRequest
* request
= new FilesTrashRequest(
507 sender_
.get(), url_generator_
,
508 base::Bind(&EntryActionCallbackAdapter
, callback
));
509 request
->set_file_id(resource_id
);
510 request
->set_fields(kFileResourceFields
);
511 return sender_
->StartRequestWithRetry(request
);
514 CancelCallback
DriveAPIService::AddNewDirectory(
515 const std::string
& parent_resource_id
,
516 const std::string
& directory_title
,
517 const AddNewDirectoryOptions
& options
,
518 const FileResourceCallback
& callback
) {
519 DCHECK(thread_checker_
.CalledOnValidThread());
520 DCHECK(!callback
.is_null());
522 FilesInsertRequest
* request
= new FilesInsertRequest(
523 sender_
.get(), url_generator_
, callback
);
524 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
525 request
->set_mime_type(kFolderMimeType
);
526 request
->set_modified_date(options
.modified_date
);
527 request
->add_parent(parent_resource_id
);
528 request
->set_title(directory_title
);
529 request
->set_properties(options
.properties
);
530 request
->set_fields(kFileResourceFields
);
531 return sender_
->StartRequestWithRetry(request
);
534 CancelCallback
DriveAPIService::CopyResource(
535 const std::string
& resource_id
,
536 const std::string
& parent_resource_id
,
537 const std::string
& new_title
,
538 const base::Time
& last_modified
,
539 const FileResourceCallback
& callback
) {
540 DCHECK(thread_checker_
.CalledOnValidThread());
541 DCHECK(!callback
.is_null());
543 FilesCopyRequest
* request
= new FilesCopyRequest(
544 sender_
.get(), url_generator_
, callback
);
545 request
->set_file_id(resource_id
);
546 request
->add_parent(parent_resource_id
);
547 request
->set_title(new_title
);
548 request
->set_modified_date(last_modified
);
549 request
->set_fields(kFileResourceFields
);
550 return sender_
->StartRequestWithRetry(request
);
553 CancelCallback
DriveAPIService::UpdateResource(
554 const std::string
& resource_id
,
555 const std::string
& parent_resource_id
,
556 const std::string
& new_title
,
557 const base::Time
& last_modified
,
558 const base::Time
& last_viewed_by_me
,
559 const google_apis::drive::Properties
& properties
,
560 const FileResourceCallback
& callback
) {
561 DCHECK(thread_checker_
.CalledOnValidThread());
562 DCHECK(!callback
.is_null());
564 FilesPatchRequest
* request
= new FilesPatchRequest(
565 sender_
.get(), url_generator_
, callback
);
566 request
->set_file_id(resource_id
);
567 request
->set_title(new_title
);
568 if (!parent_resource_id
.empty())
569 request
->add_parent(parent_resource_id
);
570 if (!last_modified
.is_null()) {
571 // Need to set setModifiedDate to true to overwrite modifiedDate.
572 request
->set_set_modified_date(true);
573 request
->set_modified_date(last_modified
);
575 if (!last_viewed_by_me
.is_null()) {
576 // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
577 // will be set to the request time (not the specified time via request).
578 request
->set_update_viewed_date(false);
579 request
->set_last_viewed_by_me_date(last_viewed_by_me
);
581 request
->set_fields(kFileResourceFields
);
582 request
->set_properties(properties
);
583 return sender_
->StartRequestWithRetry(request
);
586 CancelCallback
DriveAPIService::AddResourceToDirectory(
587 const std::string
& parent_resource_id
,
588 const std::string
& resource_id
,
589 const EntryActionCallback
& callback
) {
590 DCHECK(thread_checker_
.CalledOnValidThread());
591 DCHECK(!callback
.is_null());
593 ChildrenInsertRequest
* request
=
594 new ChildrenInsertRequest(sender_
.get(), url_generator_
, callback
);
595 request
->set_folder_id(parent_resource_id
);
596 request
->set_id(resource_id
);
597 return sender_
->StartRequestWithRetry(request
);
600 CancelCallback
DriveAPIService::RemoveResourceFromDirectory(
601 const std::string
& parent_resource_id
,
602 const std::string
& resource_id
,
603 const EntryActionCallback
& callback
) {
604 DCHECK(thread_checker_
.CalledOnValidThread());
605 DCHECK(!callback
.is_null());
607 ChildrenDeleteRequest
* request
=
608 new ChildrenDeleteRequest(sender_
.get(), url_generator_
, callback
);
609 request
->set_child_id(resource_id
);
610 request
->set_folder_id(parent_resource_id
);
611 return sender_
->StartRequestWithRetry(request
);
614 CancelCallback
DriveAPIService::InitiateUploadNewFile(
615 const std::string
& content_type
,
616 int64 content_length
,
617 const std::string
& parent_resource_id
,
618 const std::string
& title
,
619 const UploadNewFileOptions
& options
,
620 const InitiateUploadCallback
& callback
) {
621 DCHECK(thread_checker_
.CalledOnValidThread());
622 DCHECK(!callback
.is_null());
624 InitiateUploadNewFileRequest
* request
=
625 new InitiateUploadNewFileRequest(sender_
.get(),
632 request
->set_modified_date(options
.modified_date
);
633 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
634 request
->set_properties(options
.properties
);
635 return sender_
->StartRequestWithRetry(request
);
638 CancelCallback
DriveAPIService::InitiateUploadExistingFile(
639 const std::string
& content_type
,
640 int64 content_length
,
641 const std::string
& resource_id
,
642 const UploadExistingFileOptions
& options
,
643 const InitiateUploadCallback
& callback
) {
644 DCHECK(thread_checker_
.CalledOnValidThread());
645 DCHECK(!callback
.is_null());
647 InitiateUploadExistingFileRequest
* request
=
648 new InitiateUploadExistingFileRequest(sender_
.get(),
655 request
->set_parent_resource_id(options
.parent_resource_id
);
656 request
->set_title(options
.title
);
657 request
->set_modified_date(options
.modified_date
);
658 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
659 request
->set_properties(options
.properties
);
660 return sender_
->StartRequestWithRetry(request
);
663 CancelCallback
DriveAPIService::ResumeUpload(
664 const GURL
& upload_url
,
665 int64 start_position
,
667 int64 content_length
,
668 const std::string
& content_type
,
669 const base::FilePath
& local_file_path
,
670 const UploadRangeCallback
& callback
,
671 const ProgressCallback
& progress_callback
) {
672 DCHECK(thread_checker_
.CalledOnValidThread());
673 DCHECK(!callback
.is_null());
675 return sender_
->StartRequestWithRetry(
676 new ResumeUploadRequest(
688 CancelCallback
DriveAPIService::GetUploadStatus(
689 const GURL
& upload_url
,
690 int64 content_length
,
691 const UploadRangeCallback
& callback
) {
692 DCHECK(thread_checker_
.CalledOnValidThread());
693 DCHECK(!callback
.is_null());
695 return sender_
->StartRequestWithRetry(new GetUploadStatusRequest(
702 CancelCallback
DriveAPIService::MultipartUploadNewFile(
703 const std::string
& content_type
,
704 int64 content_length
,
705 const std::string
& parent_resource_id
,
706 const std::string
& title
,
707 const base::FilePath
& local_file_path
,
708 const drive::UploadNewFileOptions
& options
,
709 const FileResourceCallback
& callback
,
710 const google_apis::ProgressCallback
& progress_callback
) {
711 DCHECK(thread_checker_
.CalledOnValidThread());
712 DCHECK(!callback
.is_null());
714 return sender_
->StartRequestWithRetry(
715 new google_apis::drive::MultipartUploadNewFileRequest(
716 sender_
.get(), title
, parent_resource_id
, content_type
,
717 content_length
, options
.modified_date
, options
.last_viewed_by_me_date
,
718 local_file_path
, options
.properties
, url_generator_
, callback
,
722 CancelCallback
DriveAPIService::MultipartUploadExistingFile(
723 const std::string
& content_type
,
724 int64 content_length
,
725 const std::string
& resource_id
,
726 const base::FilePath
& local_file_path
,
727 const drive::UploadExistingFileOptions
& options
,
728 const FileResourceCallback
& callback
,
729 const google_apis::ProgressCallback
& progress_callback
) {
730 DCHECK(thread_checker_
.CalledOnValidThread());
731 DCHECK(!callback
.is_null());
733 return sender_
->StartRequestWithRetry(
734 new google_apis::drive::MultipartUploadExistingFileRequest(
735 sender_
.get(), options
.title
, resource_id
, options
.parent_resource_id
,
736 content_type
, content_length
, options
.modified_date
,
737 options
.last_viewed_by_me_date
, local_file_path
, options
.etag
,
738 options
.properties
, url_generator_
, callback
, progress_callback
));
741 CancelCallback
DriveAPIService::AuthorizeApp(
742 const std::string
& resource_id
,
743 const std::string
& app_id
,
744 const AuthorizeAppCallback
& callback
) {
745 DCHECK(thread_checker_
.CalledOnValidThread());
746 DCHECK(!callback
.is_null());
748 // Files.Authorize is only available for whitelisted clients like official
749 // Google Chrome. In other cases, we fall back to Files.Get that returns the
750 // same value as Files.Authorize without doing authorization. In that case,
751 // the app can open if it was authorized by other means (from whitelisted
752 // clients or drive.google.com web UI.)
753 if (google_apis::IsGoogleChromeAPIKeyUsed()) {
754 google_apis::drive::FilesAuthorizeRequest
* request
=
755 new google_apis::drive::FilesAuthorizeRequest(
756 sender_
.get(), url_generator_
,
757 base::Bind(&ExtractOpenUrlAndRun
, app_id
, callback
));
758 request
->set_app_id(app_id
);
759 request
->set_file_id(resource_id
);
760 request
->set_fields(kFileResourceOpenWithLinksFields
);
761 return sender_
->StartRequestWithRetry(request
);
763 FilesGetRequest
* request
= new FilesGetRequest(
764 sender_
.get(), url_generator_
, google_apis::IsGoogleChromeAPIKeyUsed(),
765 base::Bind(&ExtractOpenUrlAndRun
, app_id
, callback
));
766 request
->set_file_id(resource_id
);
767 request
->set_fields(kFileResourceOpenWithLinksFields
);
768 return sender_
->StartRequestWithRetry(request
);
772 CancelCallback
DriveAPIService::UninstallApp(
773 const std::string
& app_id
,
774 const google_apis::EntryActionCallback
& callback
) {
775 DCHECK(thread_checker_
.CalledOnValidThread());
776 DCHECK(!callback
.is_null());
778 google_apis::drive::AppsDeleteRequest
* request
=
779 new google_apis::drive::AppsDeleteRequest(sender_
.get(), url_generator_
,
781 request
->set_app_id(app_id
);
782 return sender_
->StartRequestWithRetry(request
);
785 google_apis::CancelCallback
DriveAPIService::AddPermission(
786 const std::string
& resource_id
,
787 const std::string
& email
,
788 google_apis::drive::PermissionRole role
,
789 const google_apis::EntryActionCallback
& callback
) {
790 DCHECK(thread_checker_
.CalledOnValidThread());
791 DCHECK(!callback
.is_null());
793 google_apis::drive::PermissionsInsertRequest
* request
=
794 new google_apis::drive::PermissionsInsertRequest(sender_
.get(),
797 request
->set_id(resource_id
);
798 request
->set_role(role
);
799 request
->set_type(google_apis::drive::PERMISSION_TYPE_USER
);
800 request
->set_value(email
);
801 return sender_
->StartRequestWithRetry(request
);
804 bool DriveAPIService::HasAccessToken() const {
805 DCHECK(thread_checker_
.CalledOnValidThread());
806 return sender_
->auth_service()->HasAccessToken();
809 void DriveAPIService::RequestAccessToken(const AuthStatusCallback
& callback
) {
810 DCHECK(thread_checker_
.CalledOnValidThread());
811 DCHECK(!callback
.is_null());
813 const std::string access_token
= sender_
->auth_service()->access_token();
814 if (!access_token
.empty()) {
815 callback
.Run(google_apis::HTTP_NOT_MODIFIED
, access_token
);
819 // Retrieve the new auth token.
820 sender_
->auth_service()->StartAuthentication(callback
);
823 bool DriveAPIService::HasRefreshToken() const {
824 DCHECK(thread_checker_
.CalledOnValidThread());
825 return sender_
->auth_service()->HasRefreshToken();
828 void DriveAPIService::ClearAccessToken() {
829 DCHECK(thread_checker_
.CalledOnValidThread());
830 sender_
->auth_service()->ClearAccessToken();
833 void DriveAPIService::ClearRefreshToken() {
834 DCHECK(thread_checker_
.CalledOnValidThread());
835 sender_
->auth_service()->ClearRefreshToken();
838 void DriveAPIService::OnOAuth2RefreshTokenChanged() {
839 DCHECK(thread_checker_
.CalledOnValidThread());
840 if (CanSendRequest()) {
842 DriveServiceObserver
, observers_
, OnReadyToSendRequests());
843 } else if (!HasRefreshToken()) {
845 DriveServiceObserver
, observers_
, OnRefreshTokenInvalid());
849 scoped_ptr
<BatchRequestConfiguratorInterface
>
850 DriveAPIService::StartBatchRequest() {
851 scoped_ptr
<google_apis::drive::BatchUploadRequest
> request(
852 new google_apis::drive::BatchUploadRequest(sender_
.get(),
854 const base::WeakPtr
<google_apis::drive::BatchUploadRequest
> weak_ref
=
855 request
->GetWeakPtrAsBatchUploadRequest();
856 // Have sender_ manage the lifetime of the request.
857 // TODO(hirono): Currently we need to pass the ownership of the request to
858 // RequestSender before the request is committed because the request has a
859 // reference to RequestSender and we should ensure to delete the request when
860 // the sender is deleted. Resolve the circulating dependency and fix it.
861 const google_apis::CancelCallback callback
=
862 sender_
->StartRequestWithRetry(request
.release());
863 return make_scoped_ptr
<BatchRequestConfiguratorInterface
>(
864 new BatchRequestConfigurator(weak_ref
, callback
));