Roll src/third_party/WebKit 9f7fb92:f103b33 (svn 202621:202622)
[chromium-blink-merge.git] / components / drive / service / drive_api_service.cc
blob2f47fe64af3f4e58d65af323fbb734e3f35ef3fc
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"
7 #include <string>
8 #include <vector>
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;
69 namespace drive {
71 namespace {
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[] =
107 "kind,id,shareLink";
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,"
120 "largestChangeId";
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());
128 if (!value) {
129 callback.Run(error, GURL());
130 return;
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);
138 return;
142 // Not found.
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) {
156 callback.Run(error);
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";
163 } // namespace
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.
178 if (batch_request_)
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,
199 progress_callback));
200 // Batch request can be null when pre-authorization for the requst is failed
201 // in request sender.
202 if (batch_request_)
203 batch_request_->AddRequest(delegate.release());
204 else
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.
230 if (batch_request_)
231 batch_request_->AddRequest(delegate.release());
232 else
233 delegate->NotifyError(DRIVE_OTHER_ERROR);
234 return cancel_callback_;
237 void BatchRequestConfigurator::Commit() {
238 DCHECK(CalledOnValidThread());
239 if (!batch_request_)
240 return;
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());
261 if (sender_.get())
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_,
280 account_id,
281 url_request_context_getter_.get(),
282 scopes),
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
335 // to client side.
336 // We aren't interested in files in trash in this context, neither.
337 return files_list_request_runner_->CreateAndStartWithSizeBackoff(
338 kMaxNumFilesResourcePerRequest,
339 base::StringPrintf(
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());
365 std::string query;
366 base::StringAppendF(&query, "title = '%s'",
367 util::EscapeQueryStringValue(title).c_str());
368 if (!directory_resource_id.empty()) {
369 base::StringAppendF(
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(),
433 callback);
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_visibility(options.visibility);
534 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
535 request->set_mime_type(kFolderMimeType);
536 request->set_modified_date(options.modified_date);
537 request->add_parent(parent_resource_id);
538 request->set_title(directory_title);
539 request->set_properties(options.properties);
540 request->set_fields(kFileResourceFields);
541 return sender_->StartRequestWithAuthRetry(request);
544 CancelCallback DriveAPIService::CopyResource(
545 const std::string& resource_id,
546 const std::string& parent_resource_id,
547 const std::string& new_title,
548 const base::Time& last_modified,
549 const FileResourceCallback& callback) {
550 DCHECK(thread_checker_.CalledOnValidThread());
551 DCHECK(!callback.is_null());
553 FilesCopyRequest* request = new FilesCopyRequest(
554 sender_.get(), url_generator_, callback);
555 request->set_file_id(resource_id);
556 request->add_parent(parent_resource_id);
557 request->set_title(new_title);
558 request->set_modified_date(last_modified);
559 request->set_fields(kFileResourceFields);
560 return sender_->StartRequestWithAuthRetry(request);
563 CancelCallback DriveAPIService::UpdateResource(
564 const std::string& resource_id,
565 const std::string& parent_resource_id,
566 const std::string& new_title,
567 const base::Time& last_modified,
568 const base::Time& last_viewed_by_me,
569 const google_apis::drive::Properties& properties,
570 const FileResourceCallback& callback) {
571 DCHECK(thread_checker_.CalledOnValidThread());
572 DCHECK(!callback.is_null());
574 FilesPatchRequest* request = new FilesPatchRequest(
575 sender_.get(), url_generator_, callback);
576 request->set_file_id(resource_id);
577 request->set_title(new_title);
578 if (!parent_resource_id.empty())
579 request->add_parent(parent_resource_id);
580 if (!last_modified.is_null()) {
581 // Need to set setModifiedDate to true to overwrite modifiedDate.
582 request->set_set_modified_date(true);
583 request->set_modified_date(last_modified);
585 if (!last_viewed_by_me.is_null()) {
586 // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
587 // will be set to the request time (not the specified time via request).
588 request->set_update_viewed_date(false);
589 request->set_last_viewed_by_me_date(last_viewed_by_me);
591 request->set_fields(kFileResourceFields);
592 request->set_properties(properties);
593 return sender_->StartRequestWithAuthRetry(request);
596 CancelCallback DriveAPIService::AddResourceToDirectory(
597 const std::string& parent_resource_id,
598 const std::string& resource_id,
599 const EntryActionCallback& callback) {
600 DCHECK(thread_checker_.CalledOnValidThread());
601 DCHECK(!callback.is_null());
603 ChildrenInsertRequest* request =
604 new ChildrenInsertRequest(sender_.get(), url_generator_, callback);
605 request->set_folder_id(parent_resource_id);
606 request->set_id(resource_id);
607 return sender_->StartRequestWithAuthRetry(request);
610 CancelCallback DriveAPIService::RemoveResourceFromDirectory(
611 const std::string& parent_resource_id,
612 const std::string& resource_id,
613 const EntryActionCallback& callback) {
614 DCHECK(thread_checker_.CalledOnValidThread());
615 DCHECK(!callback.is_null());
617 ChildrenDeleteRequest* request =
618 new ChildrenDeleteRequest(sender_.get(), url_generator_, callback);
619 request->set_child_id(resource_id);
620 request->set_folder_id(parent_resource_id);
621 return sender_->StartRequestWithAuthRetry(request);
624 CancelCallback DriveAPIService::InitiateUploadNewFile(
625 const std::string& content_type,
626 int64 content_length,
627 const std::string& parent_resource_id,
628 const std::string& title,
629 const UploadNewFileOptions& options,
630 const InitiateUploadCallback& callback) {
631 DCHECK(thread_checker_.CalledOnValidThread());
632 DCHECK(!callback.is_null());
634 InitiateUploadNewFileRequest* request =
635 new InitiateUploadNewFileRequest(sender_.get(),
636 url_generator_,
637 content_type,
638 content_length,
639 parent_resource_id,
640 title,
641 callback);
642 request->set_modified_date(options.modified_date);
643 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
644 request->set_properties(options.properties);
645 return sender_->StartRequestWithAuthRetry(request);
648 CancelCallback DriveAPIService::InitiateUploadExistingFile(
649 const std::string& content_type,
650 int64 content_length,
651 const std::string& resource_id,
652 const UploadExistingFileOptions& options,
653 const InitiateUploadCallback& callback) {
654 DCHECK(thread_checker_.CalledOnValidThread());
655 DCHECK(!callback.is_null());
657 InitiateUploadExistingFileRequest* request =
658 new InitiateUploadExistingFileRequest(sender_.get(),
659 url_generator_,
660 content_type,
661 content_length,
662 resource_id,
663 options.etag,
664 callback);
665 request->set_parent_resource_id(options.parent_resource_id);
666 request->set_title(options.title);
667 request->set_modified_date(options.modified_date);
668 request->set_last_viewed_by_me_date(options.last_viewed_by_me_date);
669 request->set_properties(options.properties);
670 return sender_->StartRequestWithAuthRetry(request);
673 CancelCallback DriveAPIService::ResumeUpload(
674 const GURL& upload_url,
675 int64 start_position,
676 int64 end_position,
677 int64 content_length,
678 const std::string& content_type,
679 const base::FilePath& local_file_path,
680 const UploadRangeCallback& callback,
681 const ProgressCallback& progress_callback) {
682 DCHECK(thread_checker_.CalledOnValidThread());
683 DCHECK(!callback.is_null());
685 return sender_->StartRequestWithAuthRetry(new ResumeUploadRequest(
686 sender_.get(), upload_url, start_position, end_position, content_length,
687 content_type, local_file_path, callback, progress_callback));
690 CancelCallback DriveAPIService::GetUploadStatus(
691 const GURL& upload_url,
692 int64 content_length,
693 const UploadRangeCallback& callback) {
694 DCHECK(thread_checker_.CalledOnValidThread());
695 DCHECK(!callback.is_null());
697 return sender_->StartRequestWithAuthRetry(new GetUploadStatusRequest(
698 sender_.get(), upload_url, content_length, callback));
701 CancelCallback DriveAPIService::MultipartUploadNewFile(
702 const std::string& content_type,
703 int64 content_length,
704 const std::string& parent_resource_id,
705 const std::string& title,
706 const base::FilePath& local_file_path,
707 const drive::UploadNewFileOptions& options,
708 const FileResourceCallback& callback,
709 const google_apis::ProgressCallback& progress_callback) {
710 DCHECK(thread_checker_.CalledOnValidThread());
711 DCHECK(!callback.is_null());
713 return sender_->StartRequestWithAuthRetry(
714 new google_apis::drive::SingleBatchableDelegateRequest(
715 sender_.get(),
716 new google_apis::drive::MultipartUploadNewFileDelegate(
717 sender_->blocking_task_runner(), title, parent_resource_id,
718 content_type, content_length, options.modified_date,
719 options.last_viewed_by_me_date, local_file_path,
720 options.properties, url_generator_, callback,
721 progress_callback)));
724 CancelCallback DriveAPIService::MultipartUploadExistingFile(
725 const std::string& content_type,
726 int64 content_length,
727 const std::string& resource_id,
728 const base::FilePath& local_file_path,
729 const drive::UploadExistingFileOptions& options,
730 const FileResourceCallback& callback,
731 const google_apis::ProgressCallback& progress_callback) {
732 DCHECK(thread_checker_.CalledOnValidThread());
733 DCHECK(!callback.is_null());
735 return sender_->StartRequestWithAuthRetry(
736 new google_apis::drive::SingleBatchableDelegateRequest(
737 sender_.get(),
738 new google_apis::drive::MultipartUploadExistingFileDelegate(
739 sender_->blocking_task_runner(), options.title, resource_id,
740 options.parent_resource_id, content_type, content_length,
741 options.modified_date, options.last_viewed_by_me_date,
742 local_file_path, options.etag, options.properties, url_generator_,
743 callback, progress_callback)));
746 CancelCallback DriveAPIService::AuthorizeApp(
747 const std::string& resource_id,
748 const std::string& app_id,
749 const AuthorizeAppCallback& callback) {
750 DCHECK(thread_checker_.CalledOnValidThread());
751 DCHECK(!callback.is_null());
753 // Files.Authorize is only available for whitelisted clients like official
754 // Google Chrome. In other cases, we fall back to Files.Get that returns the
755 // same value as Files.Authorize without doing authorization. In that case,
756 // the app can open if it was authorized by other means (from whitelisted
757 // clients or drive.google.com web UI.)
758 if (google_apis::IsGoogleChromeAPIKeyUsed()) {
759 google_apis::drive::FilesAuthorizeRequest* request =
760 new google_apis::drive::FilesAuthorizeRequest(
761 sender_.get(), url_generator_,
762 base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
763 request->set_app_id(app_id);
764 request->set_file_id(resource_id);
765 request->set_fields(kFileResourceOpenWithLinksFields);
766 return sender_->StartRequestWithAuthRetry(request);
767 } else {
768 FilesGetRequest* request = new FilesGetRequest(
769 sender_.get(), url_generator_, google_apis::IsGoogleChromeAPIKeyUsed(),
770 base::Bind(&ExtractOpenUrlAndRun, app_id, callback));
771 request->set_file_id(resource_id);
772 request->set_fields(kFileResourceOpenWithLinksFields);
773 return sender_->StartRequestWithAuthRetry(request);
777 CancelCallback DriveAPIService::UninstallApp(
778 const std::string& app_id,
779 const google_apis::EntryActionCallback& callback) {
780 DCHECK(thread_checker_.CalledOnValidThread());
781 DCHECK(!callback.is_null());
783 google_apis::drive::AppsDeleteRequest* request =
784 new google_apis::drive::AppsDeleteRequest(sender_.get(), url_generator_,
785 callback);
786 request->set_app_id(app_id);
787 return sender_->StartRequestWithAuthRetry(request);
790 google_apis::CancelCallback DriveAPIService::AddPermission(
791 const std::string& resource_id,
792 const std::string& email,
793 google_apis::drive::PermissionRole role,
794 const google_apis::EntryActionCallback& callback) {
795 DCHECK(thread_checker_.CalledOnValidThread());
796 DCHECK(!callback.is_null());
798 google_apis::drive::PermissionsInsertRequest* request =
799 new google_apis::drive::PermissionsInsertRequest(sender_.get(),
800 url_generator_,
801 callback);
802 request->set_id(resource_id);
803 request->set_role(role);
804 request->set_type(google_apis::drive::PERMISSION_TYPE_USER);
805 request->set_value(email);
806 return sender_->StartRequestWithAuthRetry(request);
809 bool DriveAPIService::HasAccessToken() const {
810 DCHECK(thread_checker_.CalledOnValidThread());
811 return sender_->auth_service()->HasAccessToken();
814 void DriveAPIService::RequestAccessToken(const AuthStatusCallback& callback) {
815 DCHECK(thread_checker_.CalledOnValidThread());
816 DCHECK(!callback.is_null());
818 const std::string access_token = sender_->auth_service()->access_token();
819 if (!access_token.empty()) {
820 callback.Run(google_apis::HTTP_NOT_MODIFIED, access_token);
821 return;
824 // Retrieve the new auth token.
825 sender_->auth_service()->StartAuthentication(callback);
828 bool DriveAPIService::HasRefreshToken() const {
829 DCHECK(thread_checker_.CalledOnValidThread());
830 return sender_->auth_service()->HasRefreshToken();
833 void DriveAPIService::ClearAccessToken() {
834 DCHECK(thread_checker_.CalledOnValidThread());
835 sender_->auth_service()->ClearAccessToken();
838 void DriveAPIService::ClearRefreshToken() {
839 DCHECK(thread_checker_.CalledOnValidThread());
840 sender_->auth_service()->ClearRefreshToken();
843 void DriveAPIService::OnOAuth2RefreshTokenChanged() {
844 DCHECK(thread_checker_.CalledOnValidThread());
845 if (CanSendRequest()) {
846 FOR_EACH_OBSERVER(
847 DriveServiceObserver, observers_, OnReadyToSendRequests());
848 } else if (!HasRefreshToken()) {
849 FOR_EACH_OBSERVER(
850 DriveServiceObserver, observers_, OnRefreshTokenInvalid());
854 scoped_ptr<BatchRequestConfiguratorInterface>
855 DriveAPIService::StartBatchRequest() {
856 scoped_ptr<google_apis::drive::BatchUploadRequest> request(
857 new google_apis::drive::BatchUploadRequest(sender_.get(),
858 url_generator_));
859 const base::WeakPtr<google_apis::drive::BatchUploadRequest> weak_ref =
860 request->GetWeakPtrAsBatchUploadRequest();
861 // Have sender_ manage the lifetime of the request.
862 // TODO(hirono): Currently we need to pass the ownership of the request to
863 // RequestSender before the request is committed because the request has a
864 // reference to RequestSender and we should ensure to delete the request when
865 // the sender is deleted. Resolve the circulating dependency and fix it.
866 const google_apis::CancelCallback callback =
867 sender_->StartRequestWithAuthRetry(request.release());
868 return make_scoped_ptr<BatchRequestConfiguratorInterface>(
869 new BatchRequestConfigurator(weak_ref, sender_->blocking_task_runner(),
870 url_generator_, callback));
873 } // namespace drive