Fix build break
[chromium-blink-merge.git] / chrome / browser / google_apis / gdata_wapi_service.cc
blob9f3c6d33bed80683c8cecc64431b83da242d954e
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/google_apis/gdata_wapi_service.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/message_loop_proxy.h"
12 #include "base/values.h"
13 #include "chrome/browser/google_apis/auth_service.h"
14 #include "chrome/browser/google_apis/drive_api_parser.h"
15 #include "chrome/browser/google_apis/gdata_wapi_operations.h"
16 #include "chrome/browser/google_apis/gdata_wapi_parser.h"
17 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h"
18 #include "chrome/browser/google_apis/operation_runner.h"
19 #include "chrome/browser/google_apis/time_util.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "net/base/url_util.h"
23 using content::BrowserThread;
25 namespace google_apis {
27 namespace {
29 // OAuth2 scopes for the documents API.
30 const char kDocsListScope[] = "https://docs.google.com/feeds/";
31 const char kSpreadsheetsScope[] = "https://spreadsheets.google.com/feeds/";
32 const char kUserContentScope[] = "https://docs.googleusercontent.com/";
33 const char kDriveAppsScope[] = "https://www.googleapis.com/auth/drive.apps";
35 // The resource ID for the root directory for WAPI is defined in the spec:
36 // https://developers.google.com/google-apps/documents-list/
37 const char kWapiRootDirectoryResourceId[] = "folder:root";
39 // Parses the JSON value to ResourceEntry runs |callback|.
40 void ParseResourceEntryAndRun(const GetResourceEntryCallback& callback,
41 GDataErrorCode error,
42 scoped_ptr<base::Value> value) {
43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
45 if (!value) {
46 callback.Run(error, scoped_ptr<ResourceEntry>());
47 return;
50 // Parsing ResourceEntry is cheap enough to do on UI thread.
51 scoped_ptr<ResourceEntry> entry =
52 google_apis::ResourceEntry::ExtractAndParse(*value);
53 if (!entry) {
54 callback.Run(GDATA_PARSE_ERROR, scoped_ptr<ResourceEntry>());
55 return;
58 callback.Run(error, entry.Pass());
61 void ParseAboutResourceAndRun(
62 const GetAboutResourceCallback& callback,
63 GDataErrorCode error,
64 scoped_ptr<AccountMetadata> account_metadata) {
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
66 DCHECK(!callback.is_null());
68 scoped_ptr<AboutResource> about_resource;
69 if (account_metadata) {
70 about_resource = AboutResource::CreateFromAccountMetadata(
71 *account_metadata, kWapiRootDirectoryResourceId);
74 callback.Run(error, about_resource.Pass());
77 void ParseAppListAndRun(
78 const GetAppListCallback& callback,
79 GDataErrorCode error,
80 scoped_ptr<AccountMetadata> account_metadata) {
81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
82 DCHECK(!callback.is_null());
84 scoped_ptr<AppList> app_list;
85 if (account_metadata) {
86 app_list = AppList::CreateFromAccountMetadata(*account_metadata);
89 callback.Run(error, app_list.Pass());
92 } // namespace
94 GDataWapiService::GDataWapiService(
95 net::URLRequestContextGetter* url_request_context_getter,
96 const GURL& base_url,
97 const std::string& custom_user_agent)
98 : url_request_context_getter_(url_request_context_getter),
99 runner_(NULL),
100 url_generator_(base_url),
101 custom_user_agent_(custom_user_agent) {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105 GDataWapiService::~GDataWapiService() {
106 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
107 if (runner_.get()) {
108 runner_->operation_registry()->RemoveObserver(this);
109 runner_->auth_service()->RemoveObserver(this);
113 AuthService* GDataWapiService::auth_service_for_testing() {
114 return runner_->auth_service();
117 void GDataWapiService::Initialize(Profile* profile) {
118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
120 std::vector<std::string> scopes;
121 scopes.push_back(kDocsListScope);
122 scopes.push_back(kSpreadsheetsScope);
123 scopes.push_back(kUserContentScope);
124 // Drive App scope is required for even WAPI v3 apps access.
125 scopes.push_back(kDriveAppsScope);
126 runner_.reset(new OperationRunner(profile,
127 url_request_context_getter_,
128 scopes,
129 custom_user_agent_));
130 runner_->Initialize();
132 runner_->auth_service()->AddObserver(this);
133 runner_->operation_registry()->AddObserver(this);
136 void GDataWapiService::AddObserver(DriveServiceObserver* observer) {
137 observers_.AddObserver(observer);
140 void GDataWapiService::RemoveObserver(DriveServiceObserver* observer) {
141 observers_.RemoveObserver(observer);
144 bool GDataWapiService::CanStartOperation() const {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
147 return HasRefreshToken();
150 void GDataWapiService::CancelAll() {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152 runner_->CancelAll();
155 bool GDataWapiService::CancelForFilePath(const base::FilePath& file_path) {
156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
157 return operation_registry()->CancelForFilePath(file_path);
160 OperationProgressStatusList GDataWapiService::GetProgressStatusList() const {
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
162 return operation_registry()->GetProgressStatusList();
165 std::string GDataWapiService::GetRootResourceId() const {
166 return kWapiRootDirectoryResourceId;
169 // Because GData WAPI support is expected to be gone somehow soon by migration
170 // to the Drive API v2, so we'll reuse GetResourceListOperation to implement
171 // following methods, instead of cleaning the operation class.
173 void GDataWapiService::GetAllResourceList(
174 const GetResourceListCallback& callback) {
175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
176 DCHECK(!callback.is_null());
178 runner_->StartOperationWithRetry(
179 new GetResourceListOperation(operation_registry(),
180 url_request_context_getter_,
181 url_generator_,
182 GURL(), // No override url
183 0, // start changestamp
184 std::string(), // empty search query
185 std::string(), // no directory resource id
186 callback));
189 void GDataWapiService::GetResourceListInDirectory(
190 const std::string& directory_resource_id,
191 const GetResourceListCallback& callback) {
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
193 DCHECK(!directory_resource_id.empty());
194 DCHECK(!callback.is_null());
196 runner_->StartOperationWithRetry(
197 new GetResourceListOperation(operation_registry(),
198 url_request_context_getter_,
199 url_generator_,
200 GURL(), // No override url
201 0, // start changestamp
202 std::string(), // empty search query
203 directory_resource_id,
204 callback));
207 void GDataWapiService::Search(const std::string& search_query,
208 const GetResourceListCallback& callback) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210 DCHECK(!search_query.empty());
211 DCHECK(!callback.is_null());
213 runner_->StartOperationWithRetry(
214 new GetResourceListOperation(operation_registry(),
215 url_request_context_getter_,
216 url_generator_,
217 GURL(), // No override url
218 0, // start changestamp
219 search_query,
220 std::string(), // no directory resource id
221 callback));
224 void GDataWapiService::SearchInDirectory(
225 const std::string& search_query,
226 const std::string& directory_resource_id,
227 const GetResourceListCallback& callback) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 DCHECK(!search_query.empty());
230 DCHECK(!directory_resource_id.empty());
231 DCHECK(!callback.is_null());
233 runner_->StartOperationWithRetry(
234 new GetResourceListOperation(
235 operation_registry(),
236 url_request_context_getter_,
237 url_generator_,
238 GURL(), // No override url
239 0, // start changestamp
240 search_query,
241 directory_resource_id,
242 callback));
245 void GDataWapiService::GetChangeList(int64 start_changestamp,
246 const GetResourceListCallback& callback) {
247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
248 DCHECK(!callback.is_null());
250 runner_->StartOperationWithRetry(
251 new GetResourceListOperation(operation_registry(),
252 url_request_context_getter_,
253 url_generator_,
254 GURL(), // No override url
255 start_changestamp,
256 std::string(), // empty search query
257 std::string(), // no directory resource id
258 callback));
261 void GDataWapiService::ContinueGetResourceList(
262 const GURL& override_url,
263 const GetResourceListCallback& callback) {
264 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
265 DCHECK(!override_url.is_empty());
266 DCHECK(!callback.is_null());
268 runner_->StartOperationWithRetry(
269 new GetResourceListOperation(operation_registry(),
270 url_request_context_getter_,
271 url_generator_,
272 override_url,
273 0, // start changestamp
274 std::string(), // empty search query
275 std::string(), // no directory resource id
276 callback));
279 void GDataWapiService::GetResourceEntry(
280 const std::string& resource_id,
281 const GetResourceEntryCallback& callback) {
282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
283 DCHECK(!callback.is_null());
285 runner_->StartOperationWithRetry(
286 new GetResourceEntryOperation(
287 operation_registry(),
288 url_request_context_getter_,
289 url_generator_,
290 resource_id,
291 base::Bind(&ParseResourceEntryAndRun, callback)));
294 void GDataWapiService::GetAccountMetadata(
295 const GetAccountMetadataCallback& callback) {
296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
297 DCHECK(!callback.is_null());
299 runner_->StartOperationWithRetry(
300 new GetAccountMetadataOperation(
301 operation_registry(),
302 url_request_context_getter_,
303 url_generator_,
304 callback,
305 true)); // Include installed apps.
308 void GDataWapiService::GetAboutResource(
309 const GetAboutResourceCallback& callback) {
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
311 DCHECK(!callback.is_null());
313 runner_->StartOperationWithRetry(
314 new GetAccountMetadataOperation(
315 operation_registry(),
316 url_request_context_getter_,
317 url_generator_,
318 base::Bind(&ParseAboutResourceAndRun, callback),
319 false)); // Exclude installed apps.
322 void GDataWapiService::GetAppList(const GetAppListCallback& callback) {
323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
324 DCHECK(!callback.is_null());
326 runner_->StartOperationWithRetry(
327 new GetAccountMetadataOperation(
328 operation_registry(),
329 url_request_context_getter_,
330 url_generator_,
331 base::Bind(&ParseAppListAndRun, callback),
332 true)); // Include installed apps.
335 void GDataWapiService::DownloadFile(
336 const base::FilePath& virtual_path,
337 const base::FilePath& local_cache_path,
338 const GURL& download_url,
339 const DownloadActionCallback& download_action_callback,
340 const GetContentCallback& get_content_callback,
341 const ProgressCallback& progress_callback) {
342 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
343 DCHECK(!download_action_callback.is_null());
344 // get_content_callback and progress_callback may be null.
346 runner_->StartOperationWithRetry(
347 new DownloadFileOperation(operation_registry(),
348 url_request_context_getter_,
349 download_action_callback,
350 get_content_callback,
351 progress_callback,
352 download_url,
353 virtual_path,
354 local_cache_path));
357 void GDataWapiService::DeleteResource(
358 const std::string& resource_id,
359 const std::string& etag,
360 const EntryActionCallback& callback) {
361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
362 DCHECK(!callback.is_null());
364 runner_->StartOperationWithRetry(
365 new DeleteResourceOperation(operation_registry(),
366 url_request_context_getter_,
367 url_generator_,
368 callback,
369 resource_id,
370 etag));
373 void GDataWapiService::AddNewDirectory(
374 const std::string& parent_resource_id,
375 const std::string& directory_name,
376 const GetResourceEntryCallback& callback) {
377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
378 DCHECK(!callback.is_null());
380 runner_->StartOperationWithRetry(
381 new CreateDirectoryOperation(operation_registry(),
382 url_request_context_getter_,
383 url_generator_,
384 base::Bind(&ParseResourceEntryAndRun,
385 callback),
386 parent_resource_id,
387 directory_name));
390 void GDataWapiService::CopyHostedDocument(
391 const std::string& resource_id,
392 const std::string& new_name,
393 const GetResourceEntryCallback& callback) {
394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
395 DCHECK(!callback.is_null());
397 runner_->StartOperationWithRetry(
398 new CopyHostedDocumentOperation(
399 operation_registry(),
400 url_request_context_getter_,
401 url_generator_,
402 base::Bind(&ParseResourceEntryAndRun, callback),
403 resource_id,
404 new_name));
407 void GDataWapiService::RenameResource(
408 const std::string& resource_id,
409 const std::string& new_name,
410 const EntryActionCallback& callback) {
411 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
412 DCHECK(!callback.is_null());
414 runner_->StartOperationWithRetry(
415 new RenameResourceOperation(operation_registry(),
416 url_request_context_getter_,
417 url_generator_,
418 callback,
419 resource_id,
420 new_name));
423 void GDataWapiService::AddResourceToDirectory(
424 const std::string& parent_resource_id,
425 const std::string& resource_id,
426 const EntryActionCallback& callback) {
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
428 DCHECK(!callback.is_null());
430 runner_->StartOperationWithRetry(
431 new AddResourceToDirectoryOperation(operation_registry(),
432 url_request_context_getter_,
433 url_generator_,
434 callback,
435 parent_resource_id,
436 resource_id));
439 void GDataWapiService::RemoveResourceFromDirectory(
440 const std::string& parent_resource_id,
441 const std::string& resource_id,
442 const EntryActionCallback& callback) {
443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
444 DCHECK(!callback.is_null());
446 runner_->StartOperationWithRetry(
447 new RemoveResourceFromDirectoryOperation(operation_registry(),
448 url_request_context_getter_,
449 url_generator_,
450 callback,
451 parent_resource_id,
452 resource_id));
455 void GDataWapiService::InitiateUploadNewFile(
456 const base::FilePath& drive_file_path,
457 const std::string& content_type,
458 int64 content_length,
459 const std::string& parent_resource_id,
460 const std::string& title,
461 const InitiateUploadCallback& callback) {
462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
463 DCHECK(!callback.is_null());
464 DCHECK(!parent_resource_id.empty());
466 runner_->StartOperationWithRetry(
467 new InitiateUploadNewFileOperation(operation_registry(),
468 url_request_context_getter_,
469 url_generator_,
470 callback,
471 drive_file_path,
472 content_type,
473 content_length,
474 parent_resource_id,
475 title));
478 void GDataWapiService::InitiateUploadExistingFile(
479 const base::FilePath& drive_file_path,
480 const std::string& content_type,
481 int64 content_length,
482 const std::string& resource_id,
483 const std::string& etag,
484 const InitiateUploadCallback& callback) {
485 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
486 DCHECK(!callback.is_null());
487 DCHECK(!resource_id.empty());
489 runner_->StartOperationWithRetry(
490 new InitiateUploadExistingFileOperation(operation_registry(),
491 url_request_context_getter_,
492 url_generator_,
493 callback,
494 drive_file_path,
495 content_type,
496 content_length,
497 resource_id,
498 etag));
501 void GDataWapiService::ResumeUpload(
502 UploadMode upload_mode,
503 const base::FilePath& drive_file_path,
504 const GURL& upload_url,
505 int64 start_position,
506 int64 end_position,
507 int64 content_length,
508 const std::string& content_type,
509 const scoped_refptr<net::IOBuffer>& buf,
510 const UploadRangeCallback& callback,
511 const ProgressCallback& progress_callback) {
512 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
513 DCHECK(!callback.is_null());
515 runner_->StartOperationWithRetry(
516 new ResumeUploadOperation(operation_registry(),
517 url_request_context_getter_,
518 callback,
519 progress_callback,
520 upload_mode,
521 drive_file_path,
522 upload_url,
523 start_position,
524 end_position,
525 content_length,
526 content_type,
527 buf));
530 void GDataWapiService::GetUploadStatus(
531 UploadMode upload_mode,
532 const base::FilePath& drive_file_path,
533 const GURL& upload_url,
534 int64 content_length,
535 const UploadRangeCallback& callback) {
536 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
537 DCHECK(!callback.is_null());
539 runner_->StartOperationWithRetry(
540 new GetUploadStatusOperation(operation_registry(),
541 url_request_context_getter_,
542 callback,
543 upload_mode,
544 drive_file_path,
545 upload_url,
546 content_length));
549 void GDataWapiService::AuthorizeApp(const std::string& resource_id,
550 const std::string& app_id,
551 const AuthorizeAppCallback& callback) {
552 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
553 DCHECK(!callback.is_null());
555 runner_->StartOperationWithRetry(
556 new AuthorizeAppOperation(
557 operation_registry(),
558 url_request_context_getter_,
559 url_generator_,
560 callback,
561 resource_id,
562 app_id));
565 bool GDataWapiService::HasAccessToken() const {
566 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
568 return runner_->auth_service()->HasAccessToken();
571 bool GDataWapiService::HasRefreshToken() const {
572 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
574 return runner_->auth_service()->HasRefreshToken();
577 void GDataWapiService::ClearAccessToken() {
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
579 return runner_->auth_service()->ClearAccessToken();
582 void GDataWapiService::ClearRefreshToken() {
583 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
584 return runner_->auth_service()->ClearRefreshToken();
587 OperationRegistry* GDataWapiService::operation_registry() const {
588 return runner_->operation_registry();
591 void GDataWapiService::OnOAuth2RefreshTokenChanged() {
592 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
593 if (CanStartOperation()) {
594 FOR_EACH_OBSERVER(
595 DriveServiceObserver, observers_, OnReadyToPerformOperations());
596 } else if (!HasRefreshToken()) {
597 FOR_EACH_OBSERVER(
598 DriveServiceObserver, observers_, OnRefreshTokenInvalid());
602 void GDataWapiService::OnProgressUpdate(
603 const OperationProgressStatusList& list) {
604 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
605 FOR_EACH_OBSERVER(
606 DriveServiceObserver, observers_, OnProgressUpdate(list));
609 } // namespace google_apis