MacViews: Style menus to look more maccy
[chromium-blink-merge.git] / components / drive / service / drive_api_service.cc
blob644079a9e60cf579f715041c11cf91bc595fac6c
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_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(),
635 url_generator_,
636 content_type,
637 content_length,
638 parent_resource_id,
639 title,
640 callback);
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(),
658 url_generator_,
659 content_type,
660 content_length,
661 resource_id,
662 options.etag,
663 callback);
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,
675 int64 end_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(
714 sender_.get(),
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(
736 sender_.get(),
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);
766 } else {
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_,
784 callback);
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(),
799 url_generator_,
800 callback);
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);
820 return;
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()) {
845 FOR_EACH_OBSERVER(
846 DriveServiceObserver, observers_, OnReadyToSendRequests());
847 } else if (!HasRefreshToken()) {
848 FOR_EACH_OBSERVER(
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(),
857 url_generator_));
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));
872 } // namespace drive