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.
4
5 #include "chrome/browser/drive/gdata_wapi_service.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/sequenced_task_runner.h"
13 #include "base/values.h"
14 #include "chrome/browser/drive/drive_api_util.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "google_apis/drive/auth_service.h"
17 #include "google_apis/drive/drive_api_parser.h"
18 #include "google_apis/drive/gdata_errorcode.h"
19 #include "google_apis/drive/gdata_wapi_parser.h"
20 #include "google_apis/drive/gdata_wapi_requests.h"
21 #include "google_apis/drive/gdata_wapi_url_generator.h"
22 #include "google_apis/drive/request_sender.h"
23 #include "net/url_request/url_request_context_getter.h"
24
25 using content::BrowserThread;
26 using google_apis::AboutResource;
27 using google_apis::AboutResourceCallback;
28 using google_apis::AccountMetadata;
29 using google_apis::AddResourceToDirectoryRequest;
30 using google_apis::AppList;
31 using google_apis::AppListCallback;
32 using google_apis::AuthService;
33 using google_apis::AuthStatusCallback;
34 using google_apis::AuthorizeAppCallback;
35 using google_apis::AuthorizeAppRequest;
36 using google_apis::CancelCallback;
37 using google_apis::CreateDirectoryRequest;
38 using google_apis::DeleteResourceRequest;
39 using google_apis::DownloadActionCallback;
40 using google_apis::DownloadFileRequest;
41 using google_apis::EntryActionCallback;
42 using google_apis::GDATA_PARSE_ERROR;
43 using google_apis::GDataErrorCode;
44 using google_apis::GetAccountMetadataRequest;
45 using google_apis::GetContentCallback;
46 using google_apis::GetResourceEntryCallback;
47 using google_apis::GetResourceEntryRequest;
48 using google_apis::GetResourceListCallback;
49 using google_apis::GetResourceListRequest;
50 using google_apis::GetShareUrlCallback;
51 using google_apis::GetUploadStatusRequest;
52 using google_apis::HTTP_NOT_IMPLEMENTED;
53 using google_apis::InitiateUploadCallback;
54 using google_apis::InitiateUploadExistingFileRequest;
55 using google_apis::InitiateUploadNewFileRequest;
56 using google_apis::Link;
57 using google_apis::ProgressCallback;
58 using google_apis::RemoveResourceFromDirectoryRequest;
59 using google_apis::RenameResourceRequest;
60 using google_apis::RequestSender;
61 using google_apis::ResourceEntry;
62 using google_apis::ResumeUploadRequest;
63 using google_apis::SearchByTitleRequest;
64 using google_apis::UploadRangeCallback;
65
66 namespace drive {
67
68 namespace {
69
70 // OAuth2 scopes for the documents API.
71 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/";
72 const char kUserContentScope[] = "https://docs.googleusercontent.com/";
73
74 // Parses the JSON value to ResourceEntry runs |callback|.
ParseResourceEntryAndRun(const GetResourceEntryCallback & callback,GDataErrorCode error,scoped_ptr<base::Value> value)75 void ParseResourceEntryAndRun(const GetResourceEntryCallback& callback,
76 GDataErrorCode error,
77 scoped_ptr<base::Value> value) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
79
80 if (!value) {
81 callback.Run(error, scoped_ptr<ResourceEntry>());
82 return;
83 }
84
85 // Parsing ResourceEntry is cheap enough to do on UI thread.
86 scoped_ptr<ResourceEntry> entry =
87 google_apis::ResourceEntry::ExtractAndParse(*value);
88 if (!entry) {
89 callback.Run(GDATA_PARSE_ERROR, scoped_ptr<ResourceEntry>());
90 return;
91 }
92
93 callback.Run(error, entry.Pass());
94 }
95
ConvertAboutResourceAndRun(const AboutResourceCallback & callback,GDataErrorCode error,scoped_ptr<AccountMetadata> account_metadata)96 void ConvertAboutResourceAndRun(
97 const AboutResourceCallback& callback,
98 GDataErrorCode error,
99 scoped_ptr<AccountMetadata> account_metadata) {
100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
101 DCHECK(!callback.is_null());
102
103 scoped_ptr<AboutResource> about_resource;
104 if (account_metadata) {
105 about_resource = util::ConvertAccountMetadataToAboutResource(
106 *account_metadata, util::kWapiRootDirectoryResourceId);
107 }
108
109 callback.Run(error, about_resource.Pass());
110 }
111
ConvertAppListAndRun(const AppListCallback & callback,GDataErrorCode error,scoped_ptr<AccountMetadata> account_metadata)112 void ConvertAppListAndRun(
113 const AppListCallback& callback,
114 GDataErrorCode error,
115 scoped_ptr<AccountMetadata> account_metadata) {
116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117 DCHECK(!callback.is_null());
118
119 scoped_ptr<AppList> app_list;
120 if (account_metadata)
121 app_list = util::ConvertAccountMetadataToAppList(*account_metadata);
122
123 callback.Run(error, app_list.Pass());
124 }
125
126 } // namespace
127
GDataWapiService(OAuth2TokenService * oauth2_token_service,net::URLRequestContextGetter * url_request_context_getter,base::SequencedTaskRunner * blocking_task_runner,const GURL & base_url,const GURL & base_download_url,const std::string & custom_user_agent)128 GDataWapiService::GDataWapiService(
129 OAuth2TokenService* oauth2_token_service,
130 net::URLRequestContextGetter* url_request_context_getter,
131 base::SequencedTaskRunner* blocking_task_runner,
132 const GURL& base_url,
133 const GURL& base_download_url,
134 const std::string& custom_user_agent)
135 : oauth2_token_service_(oauth2_token_service),
136 url_request_context_getter_(url_request_context_getter),
137 blocking_task_runner_(blocking_task_runner),
138 url_generator_(base_url, base_download_url),
139 custom_user_agent_(custom_user_agent) {
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
141 }
142
~GDataWapiService()143 GDataWapiService::~GDataWapiService() {
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145 if (sender_.get())
146 sender_->auth_service()->RemoveObserver(this);
147 }
148
Initialize(const std::string & account_id)149 void GDataWapiService::Initialize(const std::string& account_id) {
150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
151
152 std::vector<std::string> scopes;
153 scopes.push_back(util::kDocsListScope);
154 scopes.push_back(kSpreadsheetsScope);
155 scopes.push_back(kUserContentScope);
156 // Drive App scope is required for even WAPI v3 apps access.
157 scopes.push_back(util::kDriveAppsScope);
158 sender_.reset(new RequestSender(
159 new AuthService(oauth2_token_service_,
160 account_id,
161 url_request_context_getter_.get(),
162 scopes),
163 url_request_context_getter_.get(),
164 blocking_task_runner_.get(),
165 custom_user_agent_));
166
167 sender_->auth_service()->AddObserver(this);
168 }
169
AddObserver(DriveServiceObserver * observer)170 void GDataWapiService::AddObserver(DriveServiceObserver* observer) {
171 observers_.AddObserver(observer);
172 }
173
RemoveObserver(DriveServiceObserver * observer)174 void GDataWapiService::RemoveObserver(DriveServiceObserver* observer) {
175 observers_.RemoveObserver(observer);
176 }
177
CanSendRequest() const178 bool GDataWapiService::CanSendRequest() const {
179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
180
181 return HasRefreshToken();
182 }
183
GetResourceIdCanonicalizer() const184 ResourceIdCanonicalizer GDataWapiService::GetResourceIdCanonicalizer() const {
185 return util::GetIdentityResourceIdCanonicalizer();
186 }
187
GetRootResourceId() const188 std::string GDataWapiService::GetRootResourceId() const {
189 return util::kWapiRootDirectoryResourceId;
190 }
191
192 // Because GData WAPI support is expected to be gone somehow soon by migration
193 // to the Drive API v2, so we'll reuse GetResourceListRequest to implement
194 // following methods, instead of cleaning the request class.
195
GetAllResourceList(const GetResourceListCallback & callback)196 CancelCallback GDataWapiService::GetAllResourceList(
197 const GetResourceListCallback& callback) {
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
199 DCHECK(!callback.is_null());
200
201 return sender_->StartRequestWithRetry(
202 new GetResourceListRequest(sender_.get(),
203 url_generator_,
204 GURL(), // No override url
205 0, // start changestamp
206 std::string(), // empty search query
207 std::string(), // no directory resource id
208 callback));
209 }
210
GetResourceListInDirectory(const std::string & directory_resource_id,const GetResourceListCallback & callback)211 CancelCallback GDataWapiService::GetResourceListInDirectory(
212 const std::string& directory_resource_id,
213 const GetResourceListCallback& callback) {
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
215 DCHECK(!directory_resource_id.empty());
216 DCHECK(!callback.is_null());
217
218 return sender_->StartRequestWithRetry(
219 new GetResourceListRequest(sender_.get(),
220 url_generator_,
221 GURL(), // No override url
222 0, // start changestamp
223 std::string(), // empty search query
224 directory_resource_id,
225 callback));
226 }
227
Search(const std::string & search_query,const GetResourceListCallback & callback)228 CancelCallback GDataWapiService::Search(
229 const std::string& search_query,
230 const GetResourceListCallback& callback) {
231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
232 DCHECK(!search_query.empty());
233 DCHECK(!callback.is_null());
234
235 return sender_->StartRequestWithRetry(
236 new GetResourceListRequest(sender_.get(),
237 url_generator_,
238 GURL(), // No override url
239 0, // start changestamp
240 search_query,
241 std::string(), // no directory resource id
242 callback));
243 }
244
SearchByTitle(const std::string & title,const std::string & directory_resource_id,const GetResourceListCallback & callback)245 CancelCallback GDataWapiService::SearchByTitle(
246 const std::string& title,
247 const std::string& directory_resource_id,
248 const GetResourceListCallback& callback) {
249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
250 DCHECK(!title.empty());
251 DCHECK(!callback.is_null());
252
253 return sender_->StartRequestWithRetry(
254 new SearchByTitleRequest(sender_.get(),
255 url_generator_,
256 title,
257 directory_resource_id,
258 callback));
259 }
260
GetChangeList(int64 start_changestamp,const GetResourceListCallback & callback)261 CancelCallback GDataWapiService::GetChangeList(
262 int64 start_changestamp,
263 const GetResourceListCallback& callback) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 DCHECK(!callback.is_null());
266
267 return sender_->StartRequestWithRetry(
268 new GetResourceListRequest(sender_.get(),
269 url_generator_,
270 GURL(), // No override url
271 start_changestamp,
272 std::string(), // empty search query
273 std::string(), // no directory resource id
274 callback));
275 }
276
GetRemainingChangeList(const GURL & next_link,const GetResourceListCallback & callback)277 CancelCallback GDataWapiService::GetRemainingChangeList(
278 const GURL& next_link,
279 const GetResourceListCallback& callback) {
280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
281 DCHECK(!next_link.is_empty());
282 DCHECK(!callback.is_null());
283
284 return GetRemainingResourceList(next_link, callback);
285 }
286
GetRemainingFileList(const GURL & next_link,const GetResourceListCallback & callback)287 CancelCallback GDataWapiService::GetRemainingFileList(
288 const GURL& next_link,
289 const GetResourceListCallback& callback) {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
291 DCHECK(!next_link.is_empty());
292 DCHECK(!callback.is_null());
293
294 return GetRemainingResourceList(next_link, callback);
295 }
296
GetResourceEntry(const std::string & resource_id,const GetResourceEntryCallback & callback)297 CancelCallback GDataWapiService::GetResourceEntry(
298 const std::string& resource_id,
299 const GetResourceEntryCallback& callback) {
300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
301 DCHECK(!callback.is_null());
302
303 return sender_->StartRequestWithRetry(
304 new GetResourceEntryRequest(sender_.get(),
305 url_generator_,
306 resource_id,
307 GURL(),
308 base::Bind(&ParseResourceEntryAndRun,
309 callback)));
310 }
311
GetShareUrl(const std::string & resource_id,const GURL & embed_origin,const GetShareUrlCallback & callback)312 CancelCallback GDataWapiService::GetShareUrl(
313 const std::string& resource_id,
314 const GURL& embed_origin,
315 const GetShareUrlCallback& callback) {
316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
317 DCHECK(!callback.is_null());
318
319 return sender_->StartRequestWithRetry(
320 new GetResourceEntryRequest(sender_.get(),
321 url_generator_,
322 resource_id,
323 embed_origin,
324 base::Bind(&util::ParseShareUrlAndRun,
325 callback)));
326 }
327
GetAboutResource(const AboutResourceCallback & callback)328 CancelCallback GDataWapiService::GetAboutResource(
329 const AboutResourceCallback& callback) {
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
331 DCHECK(!callback.is_null());
332
333 return sender_->StartRequestWithRetry(
334 new GetAccountMetadataRequest(
335 sender_.get(),
336 url_generator_,
337 base::Bind(&ConvertAboutResourceAndRun, callback),
338 false)); // Exclude installed apps.
339 }
340
GetAppList(const AppListCallback & callback)341 CancelCallback GDataWapiService::GetAppList(const AppListCallback& callback) {
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343 DCHECK(!callback.is_null());
344
345 return sender_->StartRequestWithRetry(
346 new GetAccountMetadataRequest(sender_.get(),
347 url_generator_,
348 base::Bind(&ConvertAppListAndRun, callback),
349 true)); // Include installed apps.
350 }
351
DownloadFile(const base::FilePath & local_cache_path,const std::string & resource_id,const DownloadActionCallback & download_action_callback,const GetContentCallback & get_content_callback,const ProgressCallback & progress_callback)352 CancelCallback GDataWapiService::DownloadFile(
353 const base::FilePath& local_cache_path,
354 const std::string& resource_id,
355 const DownloadActionCallback& download_action_callback,
356 const GetContentCallback& get_content_callback,
357 const ProgressCallback& progress_callback) {
358 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
359 DCHECK(!download_action_callback.is_null());
360 // get_content_callback and progress_callback may be null.
361
362 return sender_->StartRequestWithRetry(
363 new DownloadFileRequest(sender_.get(),
364 url_generator_,
365 download_action_callback,
366 get_content_callback,
367 progress_callback,
368 resource_id,
369 local_cache_path));
370 }
371
DeleteResource(const std::string & resource_id,const std::string & etag,const EntryActionCallback & callback)372 CancelCallback GDataWapiService::DeleteResource(
373 const std::string& resource_id,
374 const std::string& etag,
375 const EntryActionCallback& callback) {
376 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
377 DCHECK(!callback.is_null());
378
379 NOTIMPLEMENTED();
380 callback.Run(google_apis::GDATA_OTHER_ERROR);
381 return CancelCallback();
382 }
383
TrashResource(const std::string & resource_id,const EntryActionCallback & callback)384 CancelCallback GDataWapiService::TrashResource(
385 const std::string& resource_id,
386 const EntryActionCallback& callback) {
387 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
388 DCHECK(!callback.is_null());
389
390 const std::string empty_etag;
391 return sender_->StartRequestWithRetry(
392 new DeleteResourceRequest(sender_.get(),
393 url_generator_,
394 callback,
395 resource_id,
396 empty_etag));
397 }
398
AddNewDirectory(const std::string & parent_resource_id,const std::string & directory_title,const GetResourceEntryCallback & callback)399 CancelCallback GDataWapiService::AddNewDirectory(
400 const std::string& parent_resource_id,
401 const std::string& directory_title,
402 const GetResourceEntryCallback& callback) {
403 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
404 DCHECK(!callback.is_null());
405
406 return sender_->StartRequestWithRetry(
407 new CreateDirectoryRequest(sender_.get(),
408 url_generator_,
409 base::Bind(&ParseResourceEntryAndRun,
410 callback),
411 parent_resource_id,
412 directory_title));
413 }
414
CopyResource(const std::string & resource_id,const std::string & parent_resource_id,const std::string & new_title,const base::Time & last_modified,const GetResourceEntryCallback & callback)415 CancelCallback GDataWapiService::CopyResource(
416 const std::string& resource_id,
417 const std::string& parent_resource_id,
418 const std::string& new_title,
419 const base::Time& last_modified,
420 const GetResourceEntryCallback& callback) {
421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
422 DCHECK(!callback.is_null());
423
424 // GData WAPI doesn't support "copy" of regular files.
425 // This method should never be called if GData WAPI is enabled.
426 // Instead, client code should download the file (if needed) and upload it.
427 NOTREACHED();
428 return CancelCallback();
429 }
430
UpdateResource(const std::string & resource_id,const std::string & parent_resource_id,const std::string & new_title,const base::Time & last_modified,const base::Time & last_viewed_by_me,const google_apis::GetResourceEntryCallback & callback)431 CancelCallback GDataWapiService::UpdateResource(
432 const std::string& resource_id,
433 const std::string& parent_resource_id,
434 const std::string& new_title,
435 const base::Time& last_modified,
436 const base::Time& last_viewed_by_me,
437 const google_apis::GetResourceEntryCallback& callback) {
438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
439 DCHECK(!callback.is_null());
440
441 // GData WAPI doesn't support to "move" resources.
442 // This method should never be called if GData WAPI is enabled.
443 // Instead, client code should rename the file, add new parent, and then
444 // remove the old parent.
445 NOTREACHED();
446 return CancelCallback();
447 }
448
RenameResource(const std::string & resource_id,const std::string & new_title,const EntryActionCallback & callback)449 CancelCallback GDataWapiService::RenameResource(
450 const std::string& resource_id,
451 const std::string& new_title,
452 const EntryActionCallback& callback) {
453 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
454 DCHECK(!callback.is_null());
455
456 return sender_->StartRequestWithRetry(
457 new RenameResourceRequest(sender_.get(),
458 url_generator_,
459 callback,
460 resource_id,
461 new_title));
462 }
463
AddResourceToDirectory(const std::string & parent_resource_id,const std::string & resource_id,const EntryActionCallback & callback)464 CancelCallback GDataWapiService::AddResourceToDirectory(
465 const std::string& parent_resource_id,
466 const std::string& resource_id,
467 const EntryActionCallback& callback) {
468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
469 DCHECK(!callback.is_null());
470
471 return sender_->StartRequestWithRetry(
472 new AddResourceToDirectoryRequest(sender_.get(),
473 url_generator_,
474 callback,
475 parent_resource_id,
476 resource_id));
477 }
478
RemoveResourceFromDirectory(const std::string & parent_resource_id,const std::string & resource_id,const EntryActionCallback & callback)479 CancelCallback GDataWapiService::RemoveResourceFromDirectory(
480 const std::string& parent_resource_id,
481 const std::string& resource_id,
482 const EntryActionCallback& callback) {
483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
484 DCHECK(!callback.is_null());
485
486 return sender_->StartRequestWithRetry(
487 new RemoveResourceFromDirectoryRequest(sender_.get(),
488 url_generator_,
489 callback,
490 parent_resource_id,
491 resource_id));
492 }
493
InitiateUploadNewFile(const std::string & content_type,int64 content_length,const std::string & parent_resource_id,const std::string & title,const InitiateUploadCallback & callback)494 CancelCallback GDataWapiService::InitiateUploadNewFile(
495 const std::string& content_type,
496 int64 content_length,
497 const std::string& parent_resource_id,
498 const std::string& title,
499 const InitiateUploadCallback& callback) {
500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
501 DCHECK(!callback.is_null());
502 DCHECK(!parent_resource_id.empty());
503
504 return sender_->StartRequestWithRetry(
505 new InitiateUploadNewFileRequest(sender_.get(),
506 url_generator_,
507 callback,
508 content_type,
509 content_length,
510 parent_resource_id,
511 title));
512 }
513
InitiateUploadExistingFile(const std::string & content_type,int64 content_length,const std::string & resource_id,const std::string & etag,const InitiateUploadCallback & callback)514 CancelCallback GDataWapiService::InitiateUploadExistingFile(
515 const std::string& content_type,
516 int64 content_length,
517 const std::string& resource_id,
518 const std::string& etag,
519 const InitiateUploadCallback& callback) {
520 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
521 DCHECK(!callback.is_null());
522 DCHECK(!resource_id.empty());
523
524 return sender_->StartRequestWithRetry(
525 new InitiateUploadExistingFileRequest(sender_.get(),
526 url_generator_,
527 callback,
528 content_type,
529 content_length,
530 resource_id,
531 etag));
532 }
533
ResumeUpload(const GURL & upload_url,int64 start_position,int64 end_position,int64 content_length,const std::string & content_type,const base::FilePath & local_file_path,const UploadRangeCallback & callback,const ProgressCallback & progress_callback)534 CancelCallback GDataWapiService::ResumeUpload(
535 const GURL& upload_url,
536 int64 start_position,
537 int64 end_position,
538 int64 content_length,
539 const std::string& content_type,
540 const base::FilePath& local_file_path,
541 const UploadRangeCallback& callback,
542 const ProgressCallback& progress_callback) {
543 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
544 DCHECK(!callback.is_null());
545
546 return sender_->StartRequestWithRetry(
547 new ResumeUploadRequest(sender_.get(),
548 callback,
549 progress_callback,
550 upload_url,
551 start_position,
552 end_position,
553 content_length,
554 content_type,
555 local_file_path));
556 }
557
GetUploadStatus(const GURL & upload_url,int64 content_length,const UploadRangeCallback & callback)558 CancelCallback GDataWapiService::GetUploadStatus(
559 const GURL& upload_url,
560 int64 content_length,
561 const UploadRangeCallback& callback) {
562 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
563 DCHECK(!callback.is_null());
564
565 return sender_->StartRequestWithRetry(
566 new GetUploadStatusRequest(sender_.get(),
567 callback,
568 upload_url,
569 content_length));
570 }
571
AuthorizeApp(const std::string & resource_id,const std::string & app_id,const AuthorizeAppCallback & callback)572 CancelCallback GDataWapiService::AuthorizeApp(
573 const std::string& resource_id,
574 const std::string& app_id,
575 const AuthorizeAppCallback& callback) {
576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
577 DCHECK(!callback.is_null());
578
579 return sender_->StartRequestWithRetry(
580 new AuthorizeAppRequest(sender_.get(),
581 url_generator_,
582 callback,
583 resource_id,
584 app_id));
585 }
586
GetResourceListInDirectoryByWapi(const std::string & directory_resource_id,const google_apis::GetResourceListCallback & callback)587 CancelCallback GDataWapiService::GetResourceListInDirectoryByWapi(
588 const std::string& directory_resource_id,
589 const google_apis::GetResourceListCallback& callback) {
590 return GetResourceListInDirectory(directory_resource_id, callback);
591 }
592
GetRemainingResourceList(const GURL & next_link,const google_apis::GetResourceListCallback & callback)593 CancelCallback GDataWapiService::GetRemainingResourceList(
594 const GURL& next_link,
595 const google_apis::GetResourceListCallback& callback) {
596 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
597 DCHECK(!next_link.is_empty());
598 DCHECK(!callback.is_null());
599
600 return sender_->StartRequestWithRetry(
601 new GetResourceListRequest(sender_.get(),
602 url_generator_,
603 next_link,
604 0, // start changestamp
605 std::string(), // empty search query
606 std::string(), // no directory resource id
607 callback));
608 }
609
HasAccessToken() const610 bool GDataWapiService::HasAccessToken() const {
611 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
612
613 return sender_->auth_service()->HasAccessToken();
614 }
615
RequestAccessToken(const AuthStatusCallback & callback)616 void GDataWapiService::RequestAccessToken(const AuthStatusCallback& callback) {
617 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
618 DCHECK(!callback.is_null());
619
620 const std::string access_token = sender_->auth_service()->access_token();
621 if (!access_token.empty()) {
622 callback.Run(google_apis::HTTP_NOT_MODIFIED, access_token);
623 return;
624 }
625
626 // Retrieve the new auth token.
627 sender_->auth_service()->StartAuthentication(callback);
628 }
629
HasRefreshToken() const630 bool GDataWapiService::HasRefreshToken() const {
631 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
632 return sender_->auth_service()->HasRefreshToken();
633 }
634
ClearAccessToken()635 void GDataWapiService::ClearAccessToken() {
636 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
637 sender_->auth_service()->ClearAccessToken();
638 }
639
ClearRefreshToken()640 void GDataWapiService::ClearRefreshToken() {
641 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
642 sender_->auth_service()->ClearRefreshToken();
643 }
644
OnOAuth2RefreshTokenChanged()645 void GDataWapiService::OnOAuth2RefreshTokenChanged() {
646 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
647 if (CanSendRequest()) {
648 FOR_EACH_OBSERVER(
649 DriveServiceObserver, observers_, OnReadyToSendRequests());
650 } else if (!HasRefreshToken()) {
651 FOR_EACH_OBSERVER(
652 DriveServiceObserver, observers_, OnRefreshTokenInvalid());
653 }
654 }
655
656 } // namespace drive
657