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 "content/public/browser/browser_thread.h"
14 #include "google_apis/drive/auth_service.h"
15 #include "google_apis/drive/drive_api_parser.h"
16 #include "google_apis/drive/drive_api_requests.h"
17 #include "google_apis/drive/gdata_errorcode.h"
18 #include "google_apis/drive/gdata_wapi_parser.h"
19 #include "google_apis/drive/gdata_wapi_requests.h"
20 #include "google_apis/drive/request_sender.h"
21 #include "google_apis/google_api_keys.h"
22 #include "net/url_request/url_request_context_getter.h"
24 using content::BrowserThread
;
25 using google_apis::AboutResourceCallback
;
26 using google_apis::AppList
;
27 using google_apis::AppListCallback
;
28 using google_apis::AuthStatusCallback
;
29 using google_apis::AuthorizeAppCallback
;
30 using google_apis::CancelCallback
;
31 using google_apis::ChangeList
;
32 using google_apis::ChangeListCallback
;
33 using google_apis::DownloadActionCallback
;
34 using google_apis::EntryActionCallback
;
35 using google_apis::FileList
;
36 using google_apis::FileListCallback
;
37 using google_apis::FileResource
;
38 using google_apis::FileResourceCallback
;
39 using google_apis::GDATA_OTHER_ERROR
;
40 using google_apis::GDATA_PARSE_ERROR
;
41 using google_apis::GDataErrorCode
;
42 using google_apis::GetContentCallback
;
43 using google_apis::GetResourceEntryRequest
;
44 using google_apis::GetShareUrlCallback
;
45 using google_apis::HTTP_NOT_IMPLEMENTED
;
46 using google_apis::HTTP_SUCCESS
;
47 using google_apis::InitiateUploadCallback
;
48 using google_apis::Link
;
49 using google_apis::ProgressCallback
;
50 using google_apis::RequestSender
;
51 using google_apis::UploadRangeResponse
;
52 using google_apis::drive::AboutGetRequest
;
53 using google_apis::drive::AppsListRequest
;
54 using google_apis::drive::ChangesListRequest
;
55 using google_apis::drive::ChangesListNextPageRequest
;
56 using google_apis::drive::ChildrenDeleteRequest
;
57 using google_apis::drive::ChildrenInsertRequest
;
58 using google_apis::drive::DownloadFileRequest
;
59 using google_apis::drive::FilesCopyRequest
;
60 using google_apis::drive::FilesGetRequest
;
61 using google_apis::drive::FilesInsertRequest
;
62 using google_apis::drive::FilesPatchRequest
;
63 using google_apis::drive::FilesListRequest
;
64 using google_apis::drive::FilesListNextPageRequest
;
65 using google_apis::drive::FilesDeleteRequest
;
66 using google_apis::drive::FilesTrashRequest
;
67 using google_apis::drive::GetUploadStatusRequest
;
68 using google_apis::drive::InitiateUploadExistingFileRequest
;
69 using google_apis::drive::InitiateUploadNewFileRequest
;
70 using google_apis::drive::ResumeUploadRequest
;
71 using google_apis::drive::UploadRangeCallback
;
77 // OAuth2 scopes for Drive API.
78 const char kDriveScope
[] = "https://www.googleapis.com/auth/drive";
79 const char kDriveAppsReadonlyScope
[] =
80 "https://www.googleapis.com/auth/drive.apps.readonly";
81 const char kDriveAppsScope
[] = "https://www.googleapis.com/auth/drive.apps";
82 const char kDocsListScope
[] = "https://docs.google.com/feeds/";
84 // Mime type to create a directory.
85 const char kFolderMimeType
[] = "application/vnd.google-apps.folder";
87 // Max number of file entries to be fetched in a single http request.
89 // The larger the number is,
90 // - The total running time to fetch the whole file list will become shorter.
91 // - The running time for a single request tends to become longer.
92 // Since the file list fetching is a completely background task, for our side,
93 // only the total time matters. However, the server seems to have a time limit
94 // per single request, which disables us to set the largest value (1000).
95 // TODO(kinaba): make it larger when the server gets faster.
96 const int kMaxNumFilesResourcePerRequest
= 300;
97 const int kMaxNumFilesResourcePerRequestForSearch
= 100;
99 // For performance, we declare all fields we use.
100 const char kAboutResourceFields
[] =
101 "kind,quotaBytesTotal,quotaBytesUsed,largestChangeId,rootFolderId";
102 const char kFileResourceFields
[] =
103 "kind,id,title,createdDate,sharedWithMeDate,mimeType,"
104 "md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
105 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
106 "parents(id,parentLink),alternateLink,"
107 "modifiedDate,lastViewedByMeDate,shared";
108 const char kFileResourceOpenWithLinksFields
[] =
109 "kind,id,openWithLinks/*";
110 const char kFileListFields
[] =
111 "kind,items(kind,id,title,createdDate,sharedWithMeDate,"
112 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
113 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
114 "parents(id,parentLink),alternateLink,"
115 "modifiedDate,lastViewedByMeDate,shared),nextLink";
116 const char kChangeListFields
[] =
117 "kind,items(file(kind,id,title,createdDate,sharedWithMeDate,"
118 "mimeType,md5Checksum,fileSize,labels/trashed,imageMediaMetadata/width,"
119 "imageMediaMetadata/height,imageMediaMetadata/rotation,etag,"
120 "parents(id,parentLink),alternateLink,modifiedDate,"
121 "lastViewedByMeDate,shared),deleted,id,fileId,modificationDate),nextLink,"
124 void ExtractOpenUrlAndRun(const std::string
& app_id
,
125 const AuthorizeAppCallback
& callback
,
126 GDataErrorCode error
,
127 scoped_ptr
<FileResource
> value
) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
129 DCHECK(!callback
.is_null());
132 callback
.Run(error
, GURL());
136 const std::vector
<FileResource::OpenWithLink
>& open_with_links
=
137 value
->open_with_links();
138 for (size_t i
= 0; i
< open_with_links
.size(); ++i
) {
139 if (open_with_links
[i
].app_id
== app_id
) {
140 callback
.Run(HTTP_SUCCESS
, open_with_links
[i
].open_url
);
146 callback
.Run(GDATA_OTHER_ERROR
, GURL());
149 void ExtractShareUrlAndRun(const google_apis::GetShareUrlCallback
& callback
,
150 google_apis::GDataErrorCode error
,
151 scoped_ptr
<google_apis::ResourceEntry
> entry
) {
152 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
154 const google_apis::Link
* share_link
=
155 entry
? entry
->GetLinkByType(google_apis::Link::LINK_SHARE
) : NULL
;
156 callback
.Run(error
, share_link
? share_link
->href() : GURL());
159 // Ignores the |entry|, and runs the |callback|.
160 void EntryActionCallbackAdapter(
161 const EntryActionCallback
& callback
,
162 GDataErrorCode error
, scoped_ptr
<FileResource
> entry
) {
166 // The resource ID for the root directory for Drive API is defined in the spec:
167 // https://developers.google.com/drive/folder
168 const char kDriveApiRootDirectoryResourceId
[] = "root";
172 DriveAPIService::DriveAPIService(
173 OAuth2TokenService
* oauth2_token_service
,
174 net::URLRequestContextGetter
* url_request_context_getter
,
175 base::SequencedTaskRunner
* blocking_task_runner
,
176 const GURL
& base_url
,
177 const GURL
& base_download_url
,
178 const GURL
& wapi_base_url
,
179 const std::string
& custom_user_agent
)
180 : oauth2_token_service_(oauth2_token_service
),
181 url_request_context_getter_(url_request_context_getter
),
182 blocking_task_runner_(blocking_task_runner
),
183 url_generator_(base_url
, base_download_url
),
184 wapi_url_generator_(wapi_base_url
),
185 custom_user_agent_(custom_user_agent
) {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
189 DriveAPIService::~DriveAPIService() {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
192 sender_
->auth_service()->RemoveObserver(this);
195 void DriveAPIService::Initialize(const std::string
& account_id
) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
198 std::vector
<std::string
> scopes
;
199 scopes
.push_back(kDriveScope
);
200 scopes
.push_back(kDriveAppsReadonlyScope
);
201 scopes
.push_back(kDriveAppsScope
);
203 // Note: The following scope is used to support GetShareUrl on Drive API v2.
204 // Unfortunately, there is no support on Drive API v2, so we need to fall back
205 // to GData WAPI for the GetShareUrl.
206 scopes
.push_back(kDocsListScope
);
208 sender_
.reset(new RequestSender(
209 new google_apis::AuthService(oauth2_token_service_
,
211 url_request_context_getter_
.get(),
213 url_request_context_getter_
.get(),
214 blocking_task_runner_
.get(),
215 custom_user_agent_
));
216 sender_
->auth_service()->AddObserver(this);
219 void DriveAPIService::AddObserver(DriveServiceObserver
* observer
) {
220 observers_
.AddObserver(observer
);
223 void DriveAPIService::RemoveObserver(DriveServiceObserver
* observer
) {
224 observers_
.RemoveObserver(observer
);
227 bool DriveAPIService::CanSendRequest() const {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
230 return HasRefreshToken();
233 std::string
DriveAPIService::GetRootResourceId() const {
234 return kDriveApiRootDirectoryResourceId
;
237 CancelCallback
DriveAPIService::GetAllFileList(
238 const FileListCallback
& callback
) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
240 DCHECK(!callback
.is_null());
242 FilesListRequest
* request
= new FilesListRequest(
243 sender_
.get(), url_generator_
, callback
);
244 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
245 request
->set_q("trashed = false"); // Exclude trashed files.
246 request
->set_fields(kFileListFields
);
247 return sender_
->StartRequestWithRetry(request
);
250 CancelCallback
DriveAPIService::GetFileListInDirectory(
251 const std::string
& directory_resource_id
,
252 const FileListCallback
& callback
) {
253 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
254 DCHECK(!directory_resource_id
.empty());
255 DCHECK(!callback
.is_null());
257 // Because children.list method on Drive API v2 returns only the list of
258 // children's references, but we need all file resource list.
259 // So, here we use files.list method instead, with setting parents query.
260 // After the migration from GData WAPI to Drive API v2, we should clean the
261 // code up by moving the responsibility to include "parents" in the query
263 // We aren't interested in files in trash in this context, neither.
264 FilesListRequest
* request
= new FilesListRequest(
265 sender_
.get(), url_generator_
, callback
);
266 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
267 request
->set_q(base::StringPrintf(
268 "'%s' in parents and trashed = false",
269 util::EscapeQueryStringValue(directory_resource_id
).c_str()));
270 request
->set_fields(kFileListFields
);
271 return sender_
->StartRequestWithRetry(request
);
274 CancelCallback
DriveAPIService::Search(
275 const std::string
& search_query
,
276 const FileListCallback
& callback
) {
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
278 DCHECK(!search_query
.empty());
279 DCHECK(!callback
.is_null());
281 FilesListRequest
* request
= new FilesListRequest(
282 sender_
.get(), url_generator_
, callback
);
283 request
->set_max_results(kMaxNumFilesResourcePerRequestForSearch
);
284 request
->set_q(util::TranslateQuery(search_query
));
285 request
->set_fields(kFileListFields
);
286 return sender_
->StartRequestWithRetry(request
);
289 CancelCallback
DriveAPIService::SearchByTitle(
290 const std::string
& title
,
291 const std::string
& directory_resource_id
,
292 const FileListCallback
& callback
) {
293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
294 DCHECK(!title
.empty());
295 DCHECK(!callback
.is_null());
298 base::StringAppendF(&query
, "title = '%s'",
299 util::EscapeQueryStringValue(title
).c_str());
300 if (!directory_resource_id
.empty()) {
302 &query
, " and '%s' in parents",
303 util::EscapeQueryStringValue(directory_resource_id
).c_str());
305 query
+= " and trashed = false";
307 FilesListRequest
* request
= new FilesListRequest(
308 sender_
.get(), url_generator_
, callback
);
309 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
310 request
->set_q(query
);
311 request
->set_fields(kFileListFields
);
312 return sender_
->StartRequestWithRetry(request
);
315 CancelCallback
DriveAPIService::GetChangeList(
316 int64 start_changestamp
,
317 const ChangeListCallback
& callback
) {
318 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
319 DCHECK(!callback
.is_null());
321 ChangesListRequest
* request
= new ChangesListRequest(
322 sender_
.get(), url_generator_
, callback
);
323 request
->set_max_results(kMaxNumFilesResourcePerRequest
);
324 request
->set_start_change_id(start_changestamp
);
325 request
->set_fields(kChangeListFields
);
326 return sender_
->StartRequestWithRetry(request
);
329 CancelCallback
DriveAPIService::GetRemainingChangeList(
330 const GURL
& next_link
,
331 const ChangeListCallback
& callback
) {
332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
333 DCHECK(!next_link
.is_empty());
334 DCHECK(!callback
.is_null());
336 ChangesListNextPageRequest
* request
= new ChangesListNextPageRequest(
337 sender_
.get(), callback
);
338 request
->set_next_link(next_link
);
339 request
->set_fields(kChangeListFields
);
340 return sender_
->StartRequestWithRetry(request
);
343 CancelCallback
DriveAPIService::GetRemainingFileList(
344 const GURL
& next_link
,
345 const FileListCallback
& callback
) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
347 DCHECK(!next_link
.is_empty());
348 DCHECK(!callback
.is_null());
350 FilesListNextPageRequest
* request
= new FilesListNextPageRequest(
351 sender_
.get(), callback
);
352 request
->set_next_link(next_link
);
353 request
->set_fields(kFileListFields
);
354 return sender_
->StartRequestWithRetry(request
);
357 CancelCallback
DriveAPIService::GetFileResource(
358 const std::string
& resource_id
,
359 const FileResourceCallback
& callback
) {
360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
361 DCHECK(!callback
.is_null());
363 FilesGetRequest
* request
= new FilesGetRequest(
364 sender_
.get(), url_generator_
, callback
);
365 request
->set_file_id(resource_id
);
366 request
->set_fields(kFileResourceFields
);
367 return sender_
->StartRequestWithRetry(request
);
370 CancelCallback
DriveAPIService::GetShareUrl(
371 const std::string
& resource_id
,
372 const GURL
& embed_origin
,
373 const GetShareUrlCallback
& callback
) {
374 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
375 DCHECK(!callback
.is_null());
377 // Unfortunately "share url" is not yet supported on Drive API v2.
378 // So, as a fallback, we use GData WAPI protocol for this method.
379 // TODO(hidehiko): Get rid of this implementation when share url is
380 // supported on Drive API v2.
381 return sender_
->StartRequestWithRetry(
382 new GetResourceEntryRequest(sender_
.get(),
386 base::Bind(&ExtractShareUrlAndRun
,
390 CancelCallback
DriveAPIService::GetAboutResource(
391 const AboutResourceCallback
& callback
) {
392 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
393 DCHECK(!callback
.is_null());
395 AboutGetRequest
* request
=
396 new AboutGetRequest(sender_
.get(), url_generator_
, callback
);
397 request
->set_fields(kAboutResourceFields
);
398 return sender_
->StartRequestWithRetry(request
);
401 CancelCallback
DriveAPIService::GetAppList(const AppListCallback
& callback
) {
402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
403 DCHECK(!callback
.is_null());
405 return sender_
->StartRequestWithRetry(
406 new AppsListRequest(sender_
.get(), url_generator_
,
407 google_apis::IsGoogleChromeAPIKeyUsed(),
411 CancelCallback
DriveAPIService::DownloadFile(
412 const base::FilePath
& local_cache_path
,
413 const std::string
& resource_id
,
414 const DownloadActionCallback
& download_action_callback
,
415 const GetContentCallback
& get_content_callback
,
416 const ProgressCallback
& progress_callback
) {
417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
418 DCHECK(!download_action_callback
.is_null());
419 // get_content_callback may be null.
421 return sender_
->StartRequestWithRetry(
422 new DownloadFileRequest(sender_
.get(),
426 download_action_callback
,
427 get_content_callback
,
431 CancelCallback
DriveAPIService::DeleteResource(
432 const std::string
& resource_id
,
433 const std::string
& etag
,
434 const EntryActionCallback
& callback
) {
435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
436 DCHECK(!callback
.is_null());
438 FilesDeleteRequest
* request
= new FilesDeleteRequest(
439 sender_
.get(), url_generator_
, callback
);
440 request
->set_file_id(resource_id
);
441 request
->set_etag(etag
);
442 return sender_
->StartRequestWithRetry(request
);
445 CancelCallback
DriveAPIService::TrashResource(
446 const std::string
& resource_id
,
447 const EntryActionCallback
& callback
) {
448 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
449 DCHECK(!callback
.is_null());
451 FilesTrashRequest
* request
= new FilesTrashRequest(
452 sender_
.get(), url_generator_
,
453 base::Bind(&EntryActionCallbackAdapter
, callback
));
454 request
->set_file_id(resource_id
);
455 request
->set_fields(kFileResourceFields
);
456 return sender_
->StartRequestWithRetry(request
);
459 CancelCallback
DriveAPIService::AddNewDirectory(
460 const std::string
& parent_resource_id
,
461 const std::string
& directory_title
,
462 const AddNewDirectoryOptions
& options
,
463 const FileResourceCallback
& callback
) {
464 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
465 DCHECK(!callback
.is_null());
467 FilesInsertRequest
* request
= new FilesInsertRequest(
468 sender_
.get(), url_generator_
, callback
);
469 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
470 request
->set_mime_type(kFolderMimeType
);
471 request
->set_modified_date(options
.modified_date
);
472 request
->add_parent(parent_resource_id
);
473 request
->set_title(directory_title
);
474 request
->set_fields(kFileResourceFields
);
475 return sender_
->StartRequestWithRetry(request
);
478 CancelCallback
DriveAPIService::CopyResource(
479 const std::string
& resource_id
,
480 const std::string
& parent_resource_id
,
481 const std::string
& new_title
,
482 const base::Time
& last_modified
,
483 const FileResourceCallback
& callback
) {
484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
485 DCHECK(!callback
.is_null());
487 FilesCopyRequest
* request
= new FilesCopyRequest(
488 sender_
.get(), url_generator_
, callback
);
489 request
->set_file_id(resource_id
);
490 request
->add_parent(parent_resource_id
);
491 request
->set_title(new_title
);
492 request
->set_modified_date(last_modified
);
493 request
->set_fields(kFileResourceFields
);
494 return sender_
->StartRequestWithRetry(request
);
497 CancelCallback
DriveAPIService::UpdateResource(
498 const std::string
& resource_id
,
499 const std::string
& parent_resource_id
,
500 const std::string
& new_title
,
501 const base::Time
& last_modified
,
502 const base::Time
& last_viewed_by_me
,
503 const FileResourceCallback
& callback
) {
504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
505 DCHECK(!callback
.is_null());
507 FilesPatchRequest
* request
= new FilesPatchRequest(
508 sender_
.get(), url_generator_
, callback
);
509 request
->set_file_id(resource_id
);
510 request
->set_title(new_title
);
511 if (!parent_resource_id
.empty())
512 request
->add_parent(parent_resource_id
);
513 if (!last_modified
.is_null()) {
514 // Need to set setModifiedDate to true to overwrite modifiedDate.
515 request
->set_set_modified_date(true);
516 request
->set_modified_date(last_modified
);
518 if (!last_viewed_by_me
.is_null()) {
519 // Need to set updateViewedDate to false, otherwise the lastViewedByMeDate
520 // will be set to the request time (not the specified time via request).
521 request
->set_update_viewed_date(false);
522 request
->set_last_viewed_by_me_date(last_viewed_by_me
);
524 request
->set_fields(kFileResourceFields
);
525 return sender_
->StartRequestWithRetry(request
);
528 CancelCallback
DriveAPIService::AddResourceToDirectory(
529 const std::string
& parent_resource_id
,
530 const std::string
& resource_id
,
531 const EntryActionCallback
& callback
) {
532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
533 DCHECK(!callback
.is_null());
535 ChildrenInsertRequest
* request
=
536 new ChildrenInsertRequest(sender_
.get(), url_generator_
, callback
);
537 request
->set_folder_id(parent_resource_id
);
538 request
->set_id(resource_id
);
539 return sender_
->StartRequestWithRetry(request
);
542 CancelCallback
DriveAPIService::RemoveResourceFromDirectory(
543 const std::string
& parent_resource_id
,
544 const std::string
& resource_id
,
545 const EntryActionCallback
& callback
) {
546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
547 DCHECK(!callback
.is_null());
549 ChildrenDeleteRequest
* request
=
550 new ChildrenDeleteRequest(sender_
.get(), url_generator_
, callback
);
551 request
->set_child_id(resource_id
);
552 request
->set_folder_id(parent_resource_id
);
553 return sender_
->StartRequestWithRetry(request
);
556 CancelCallback
DriveAPIService::InitiateUploadNewFile(
557 const std::string
& content_type
,
558 int64 content_length
,
559 const std::string
& parent_resource_id
,
560 const std::string
& title
,
561 const InitiateUploadNewFileOptions
& options
,
562 const InitiateUploadCallback
& callback
) {
563 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
564 DCHECK(!callback
.is_null());
566 InitiateUploadNewFileRequest
* request
=
567 new InitiateUploadNewFileRequest(sender_
.get(),
574 request
->set_modified_date(options
.modified_date
);
575 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
576 return sender_
->StartRequestWithRetry(request
);
579 CancelCallback
DriveAPIService::InitiateUploadExistingFile(
580 const std::string
& content_type
,
581 int64 content_length
,
582 const std::string
& resource_id
,
583 const InitiateUploadExistingFileOptions
& options
,
584 const InitiateUploadCallback
& callback
) {
585 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
586 DCHECK(!callback
.is_null());
588 InitiateUploadExistingFileRequest
* request
=
589 new InitiateUploadExistingFileRequest(sender_
.get(),
596 request
->set_parent_resource_id(options
.parent_resource_id
);
597 request
->set_title(options
.title
);
598 request
->set_modified_date(options
.modified_date
);
599 request
->set_last_viewed_by_me_date(options
.last_viewed_by_me_date
);
600 return sender_
->StartRequestWithRetry(request
);
603 CancelCallback
DriveAPIService::ResumeUpload(
604 const GURL
& upload_url
,
605 int64 start_position
,
607 int64 content_length
,
608 const std::string
& content_type
,
609 const base::FilePath
& local_file_path
,
610 const UploadRangeCallback
& callback
,
611 const ProgressCallback
& progress_callback
) {
612 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
613 DCHECK(!callback
.is_null());
615 return sender_
->StartRequestWithRetry(
616 new ResumeUploadRequest(
628 CancelCallback
DriveAPIService::GetUploadStatus(
629 const GURL
& upload_url
,
630 int64 content_length
,
631 const UploadRangeCallback
& callback
) {
632 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
633 DCHECK(!callback
.is_null());
635 return sender_
->StartRequestWithRetry(new GetUploadStatusRequest(
642 CancelCallback
DriveAPIService::AuthorizeApp(
643 const std::string
& resource_id
,
644 const std::string
& app_id
,
645 const AuthorizeAppCallback
& callback
) {
646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
647 DCHECK(!callback
.is_null());
649 // Files.Authorize is only available for whitelisted clients like official
650 // Google Chrome. In other cases, we fall back to Files.Get that returns the
651 // same value as Files.Authorize without doing authorization. In that case,
652 // the app can open if it was authorized by other means (from whitelisted
653 // clients or drive.google.com web UI.)
654 if (google_apis::IsGoogleChromeAPIKeyUsed()) {
655 google_apis::drive::FilesAuthorizeRequest
* request
=
656 new google_apis::drive::FilesAuthorizeRequest(
657 sender_
.get(), url_generator_
,
658 base::Bind(&ExtractOpenUrlAndRun
, app_id
, callback
));
659 request
->set_app_id(app_id
);
660 request
->set_file_id(resource_id
);
661 request
->set_fields(kFileResourceOpenWithLinksFields
);
662 return sender_
->StartRequestWithRetry(request
);
664 FilesGetRequest
* request
= new FilesGetRequest(
665 sender_
.get(), url_generator_
,
666 base::Bind(&ExtractOpenUrlAndRun
, app_id
, callback
));
667 request
->set_file_id(resource_id
);
668 request
->set_fields(kFileResourceOpenWithLinksFields
);
669 return sender_
->StartRequestWithRetry(request
);
673 CancelCallback
DriveAPIService::UninstallApp(
674 const std::string
& app_id
,
675 const google_apis::EntryActionCallback
& callback
) {
676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
677 DCHECK(!callback
.is_null());
679 google_apis::drive::AppsDeleteRequest
* request
=
680 new google_apis::drive::AppsDeleteRequest(sender_
.get(), url_generator_
,
682 request
->set_app_id(app_id
);
683 return sender_
->StartRequestWithRetry(request
);
686 google_apis::CancelCallback
DriveAPIService::AddPermission(
687 const std::string
& resource_id
,
688 const std::string
& email
,
689 google_apis::drive::PermissionRole role
,
690 const google_apis::EntryActionCallback
& callback
) {
691 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
692 DCHECK(!callback
.is_null());
694 google_apis::drive::PermissionsInsertRequest
* request
=
695 new google_apis::drive::PermissionsInsertRequest(sender_
.get(),
698 request
->set_id(resource_id
);
699 request
->set_role(role
);
700 request
->set_type(google_apis::drive::PERMISSION_TYPE_USER
);
701 request
->set_value(email
);
702 return sender_
->StartRequestWithRetry(request
);
705 bool DriveAPIService::HasAccessToken() const {
706 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
707 return sender_
->auth_service()->HasAccessToken();
710 void DriveAPIService::RequestAccessToken(const AuthStatusCallback
& callback
) {
711 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
712 DCHECK(!callback
.is_null());
714 const std::string access_token
= sender_
->auth_service()->access_token();
715 if (!access_token
.empty()) {
716 callback
.Run(google_apis::HTTP_NOT_MODIFIED
, access_token
);
720 // Retrieve the new auth token.
721 sender_
->auth_service()->StartAuthentication(callback
);
724 bool DriveAPIService::HasRefreshToken() const {
725 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
726 return sender_
->auth_service()->HasRefreshToken();
729 void DriveAPIService::ClearAccessToken() {
730 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
731 sender_
->auth_service()->ClearAccessToken();
734 void DriveAPIService::ClearRefreshToken() {
735 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
736 sender_
->auth_service()->ClearRefreshToken();
739 void DriveAPIService::OnOAuth2RefreshTokenChanged() {
740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
741 if (CanSendRequest()) {
743 DriveServiceObserver
, observers_
, OnReadyToSendRequests());
744 } else if (!HasRefreshToken()) {
746 DriveServiceObserver
, observers_
, OnRefreshTokenInvalid());