Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/sync_file_system/drive_file_sync_client.h" | 5 #include "chrome/browser/sync_file_system/drive_file_sync_client.h" |
| 6 | 6 |
| 7 #include <sstream> | 7 #include <sstream> |
| 8 | 8 |
| 9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| 11 #include "base/values.h" | 11 #include "base/values.h" |
| 12 #include "chrome/browser/google_apis/drive_uploader.h" | 12 #include "chrome/browser/google_apis/drive_uploader.h" |
| 13 #include "chrome/browser/google_apis/gdata_wapi_service.h" | 13 #include "chrome/browser/google_apis/gdata_wapi_service.h" |
| 14 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h" | 14 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h" |
| 15 #include "chrome/common/extensions/extension.h" | |
| 16 #include "extensions/common/constants.h" | |
| 15 #include "net/base/escape.h" | 17 #include "net/base/escape.h" |
| 16 #include "net/base/mime_util.h" | 18 #include "net/base/mime_util.h" |
| 17 | 19 |
| 18 namespace sync_file_system { | 20 namespace sync_file_system { |
| 19 | 21 |
| 20 namespace { | 22 namespace { |
| 21 | 23 |
| 22 const char kRootResourceId[] = ""; | 24 const char kRootResourceId[] = ""; |
| 23 const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem"; | 25 const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem"; |
| 24 const char kResourceLinkPrefix[] = | |
| 25 "https://docs.google.com/feeds/default/private/full/"; | |
| 26 const char kMimeTypeOctetStream[] = "application/octet-stream"; | 26 const char kMimeTypeOctetStream[] = "application/octet-stream"; |
| 27 | 27 |
| 28 // This path is not actually used but is required by DriveUploaderInterface. | 28 // This path is not actually used but is required by DriveUploaderInterface. |
| 29 const FilePath::CharType kDummyDrivePath[] = | 29 const FilePath::CharType kDummyDrivePath[] = |
| 30 FILE_PATH_LITERAL("/dummy/drive/path"); | 30 FILE_PATH_LITERAL("/dummy/drive/path"); |
| 31 | 31 |
| 32 bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links, | 32 bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links, |
| 33 const std::string& parent_resource_id) { | 33 const GURL& parent_link) { |
| 34 bool should_not_have_parent = parent_resource_id.empty(); | 34 bool should_not_have_parent = parent_link.is_empty(); |
| 35 GURL parent_link(kResourceLinkPrefix + net::EscapePath(parent_resource_id)); | |
| 36 | 35 |
| 37 for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin(); | 36 for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin(); |
| 38 itr != links.end(); ++itr) { | 37 itr != links.end(); ++itr) { |
| 39 if ((*itr)->type() == google_apis::Link::LINK_PARENT) { | 38 if ((*itr)->type() == google_apis::Link::LINK_PARENT) { |
| 40 if (should_not_have_parent) | 39 if (should_not_have_parent) |
| 41 return false; | 40 return false; |
| 42 if ((*itr)->href() == parent_link) | 41 if ((*itr)->href().GetOrigin() == parent_link.GetOrigin() && |
| 42 (*itr)->href().path() == parent_link.path()) | |
| 43 return true; | 43 return true; |
| 44 } | 44 } |
| 45 } | 45 } |
| 46 | 46 |
| 47 return should_not_have_parent; | 47 return should_not_have_parent; |
| 48 } | 48 } |
| 49 | 49 |
| 50 google_apis::DocumentEntry* GetDocumentByTitleAndParent( | 50 google_apis::DocumentEntry* GetDocumentByTitleAndParent( |
| 51 const ScopedVector<google_apis::DocumentEntry>& entries, | 51 const ScopedVector<google_apis::DocumentEntry>& entries, |
| 52 const std::string& parent_resource_id, | 52 const GURL& parent_link, |
| 53 const string16& title) { | 53 const string16& title) { |
| 54 typedef ScopedVector<google_apis::DocumentEntry>::const_iterator iterator; | 54 typedef ScopedVector<google_apis::DocumentEntry>::const_iterator iterator; |
| 55 for (iterator itr = entries.begin(); itr != entries.end(); ++itr) { | 55 for (iterator itr = entries.begin(); itr != entries.end(); ++itr) { |
| 56 if ((*itr)->title() == title && | 56 if ((*itr)->title() == title && |
| 57 HasParentLinkTo((*itr)->links(), parent_resource_id)) { | 57 HasParentLinkTo((*itr)->links(), parent_link)) { |
| 58 return *itr; | 58 return *itr; |
| 59 } | 59 } |
| 60 } | 60 } |
| 61 return NULL; | 61 return NULL; |
| 62 } | 62 } |
| 63 | 63 |
| 64 } // namespace | 64 } // namespace |
| 65 | 65 |
| 66 DriveFileSyncClient::DriveFileSyncClient(Profile* profile) { | 66 DriveFileSyncClient::DriveFileSyncClient(Profile* profile) |
| 67 : url_generator_(GURL( | |
| 68 google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction)) { | |
| 67 drive_service_.reset(new google_apis::GDataWapiService( | 69 drive_service_.reset(new google_apis::GDataWapiService( |
| 68 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), | 70 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), |
| 69 "" /* custom_user_agent */)); | 71 "" /* custom_user_agent */)); |
| 70 drive_service_->Initialize(profile); | 72 drive_service_->Initialize(profile); |
| 71 | 73 |
| 72 drive_uploader_.reset(new google_apis::DriveUploader(drive_service_.get())); | 74 drive_uploader_.reset(new google_apis::DriveUploader(drive_service_.get())); |
| 73 } | 75 } |
| 74 | 76 |
| 75 scoped_ptr<DriveFileSyncClient> DriveFileSyncClient::CreateForTesting( | 77 scoped_ptr<DriveFileSyncClient> DriveFileSyncClient::CreateForTesting( |
| 76 Profile* profile, | 78 Profile* profile, |
| 77 scoped_ptr<google_apis::DriveServiceInterface> drive_service, | 79 scoped_ptr<google_apis::DriveServiceInterface> drive_service, |
| 78 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) { | 80 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) { |
| 79 return make_scoped_ptr(new DriveFileSyncClient( | 81 return make_scoped_ptr(new DriveFileSyncClient( |
| 80 profile, drive_service.Pass(), drive_uploader.Pass())); | 82 profile, drive_service.Pass(), drive_uploader.Pass())); |
| 81 } | 83 } |
| 82 | 84 |
| 83 DriveFileSyncClient::DriveFileSyncClient( | 85 DriveFileSyncClient::DriveFileSyncClient( |
| 84 Profile* profile, | 86 Profile* profile, |
| 85 scoped_ptr<google_apis::DriveServiceInterface> drive_service, | 87 scoped_ptr<google_apis::DriveServiceInterface> drive_service, |
| 86 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) { | 88 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) |
| 89 : url_generator_( | |
| 90 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction)) { | |
|
kinuko
2012/12/03 13:10:34
nit: Should this be given from outside? It feels a
tzik
2012/12/04 04:59:50
Done.
| |
| 87 drive_service_ = drive_service.Pass(); | 91 drive_service_ = drive_service.Pass(); |
| 88 drive_service_->Initialize(profile); | 92 drive_service_->Initialize(profile); |
| 89 | 93 |
| 90 drive_uploader_ = drive_uploader.Pass(); | 94 drive_uploader_ = drive_uploader.Pass(); |
| 91 } | 95 } |
| 92 | 96 |
| 93 DriveFileSyncClient::~DriveFileSyncClient() { | 97 DriveFileSyncClient::~DriveFileSyncClient() { |
| 94 DCHECK(CalledOnValidThread()); | 98 DCHECK(CalledOnValidThread()); |
| 95 drive_service_->CancelAll(); | 99 drive_service_->CancelAll(); |
| 96 } | 100 } |
| 97 | 101 |
| 98 void DriveFileSyncClient::GetDriveDirectoryForSyncRoot( | 102 void DriveFileSyncClient::GetDriveDirectoryForSyncRoot( |
| 99 const ResourceIdCallback& callback) { | 103 const ResourceIdCallback& callback) { |
| 100 DCHECK(CalledOnValidThread()); | 104 DCHECK(CalledOnValidThread()); |
| 101 | 105 |
| 102 std::string directory_name(kSyncRootDirectoryName); | 106 std::string directory_name(kSyncRootDirectoryName); |
| 103 SearchFilesInDirectory( | 107 SearchFilesInDirectory( |
| 104 kRootResourceId, | 108 kRootResourceId, |
| 105 FormatTitleQuery(directory_name), | 109 FormatTitleQuery(directory_name), |
| 106 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), | 110 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), |
| 107 kRootResourceId, directory_name, callback)); | 111 kRootResourceId, directory_name, callback)); |
| 108 } | 112 } |
| 109 | 113 |
| 110 void DriveFileSyncClient::GetDriveDirectoryForOrigin( | 114 void DriveFileSyncClient::GetDriveDirectoryForOrigin( |
| 111 const std::string& sync_root_resource_id, | 115 const std::string& sync_root_resource_id, |
| 112 const GURL& origin, | 116 const GURL& origin, |
| 113 const ResourceIdCallback& callback) { | 117 const ResourceIdCallback& callback) { |
| 114 DCHECK(CalledOnValidThread()); | 118 DCHECK(CalledOnValidThread()); |
| 115 | 119 |
| 116 std::string directory_name(origin.spec()); | 120 std::string directory_name(OriginToDirectoryTitle(origin)); |
| 117 SearchFilesInDirectory( | 121 SearchFilesInDirectory( |
| 118 sync_root_resource_id, | 122 sync_root_resource_id, |
| 119 FormatTitleQuery(directory_name), | 123 FormatTitleQuery(directory_name), |
| 120 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), | 124 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), |
| 121 sync_root_resource_id, directory_name, callback)); | 125 sync_root_resource_id, directory_name, callback)); |
| 122 } | 126 } |
| 123 | 127 |
| 124 void DriveFileSyncClient::DidGetDirectory( | 128 void DriveFileSyncClient::DidGetDirectory( |
| 125 const std::string& parent_resource_id, | 129 const std::string& parent_resource_id, |
| 126 const std::string& directory_name, | 130 const std::string& directory_name, |
| 127 const ResourceIdCallback& callback, | 131 const ResourceIdCallback& callback, |
| 128 google_apis::GDataErrorCode error, | 132 google_apis::GDataErrorCode error, |
| 129 scoped_ptr<google_apis::DocumentFeed> feed) { | 133 scoped_ptr<google_apis::DocumentFeed> feed) { |
| 130 DCHECK(CalledOnValidThread()); | 134 DCHECK(CalledOnValidThread()); |
| 131 DCHECK(IsStringASCII(directory_name)); | 135 DCHECK(IsStringASCII(directory_name)); |
| 132 | 136 |
| 133 if (error != google_apis::HTTP_SUCCESS) { | 137 if (error != google_apis::HTTP_SUCCESS) { |
| 134 callback.Run(error, std::string()); | 138 callback.Run(error, std::string()); |
| 135 return; | 139 return; |
| 136 } | 140 } |
| 137 | 141 |
| 142 GURL parent_link; | |
| 143 if (!parent_resource_id.empty()) | |
| 144 parent_link = ResourceIdToResourceLink(parent_resource_id); | |
| 138 google_apis::DocumentEntry* entry = GetDocumentByTitleAndParent( | 145 google_apis::DocumentEntry* entry = GetDocumentByTitleAndParent( |
| 139 feed->entries(), parent_resource_id, ASCIIToUTF16(directory_name)); | 146 feed->entries(), parent_link, ASCIIToUTF16(directory_name)); |
| 140 if (!entry) { | 147 if (!entry) { |
| 141 if (parent_resource_id.empty()) { | 148 if (parent_resource_id.empty()) { |
| 142 // Use empty content URL for root directory. | 149 // Use empty content URL for root directory. |
| 143 drive_service_->AddNewDirectory( | 150 drive_service_->AddNewDirectory( |
| 144 GURL(), // parent_content_url | 151 GURL(), // parent_content_url |
| 145 FilePath().AppendASCII(directory_name).value(), | 152 FilePath().AppendASCII(directory_name).value(), |
| 146 base::Bind(&DriveFileSyncClient::DidCreateDirectory, | 153 base::Bind(&DriveFileSyncClient::DidCreateDirectory, |
| 147 AsWeakPtr(), callback)); | 154 AsWeakPtr(), callback)); |
| 148 return; | 155 return; |
| 149 } | 156 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 const GDataErrorCallback& callback) { | 356 const GDataErrorCallback& callback) { |
| 350 DCHECK(CalledOnValidThread()); | 357 DCHECK(CalledOnValidThread()); |
| 351 drive_service_->GetDocumentEntry( | 358 drive_service_->GetDocumentEntry( |
| 352 resource_id, | 359 resource_id, |
| 353 base::Bind(&DriveFileSyncClient::DidGetDocumentEntryData, | 360 base::Bind(&DriveFileSyncClient::DidGetDocumentEntryData, |
| 354 AsWeakPtr(), | 361 AsWeakPtr(), |
| 355 base::Bind(&DriveFileSyncClient::DeleteFileInternal, | 362 base::Bind(&DriveFileSyncClient::DeleteFileInternal, |
| 356 AsWeakPtr(), remote_file_md5, callback))); | 363 AsWeakPtr(), remote_file_md5, callback))); |
| 357 } | 364 } |
| 358 | 365 |
| 366 // static | |
| 367 std::string DriveFileSyncClient::OriginToDirectoryTitle(const GURL& origin) { | |
| 368 DCHECK(origin.SchemeIs(extensions::kExtensionScheme)); | |
| 369 return origin.host(); | |
| 370 } | |
| 371 | |
| 372 // static | |
| 373 GURL DriveFileSyncClient::DirectoryTitleToOrigin(const std::string& title) { | |
| 374 return extensions::Extension::GetBaseURLFromExtensionId(title); | |
| 375 } | |
| 376 | |
| 377 GURL DriveFileSyncClient::ResourceIdToResourceLink( | |
| 378 const std::string& resource_id) const { | |
| 379 GURL link = url_generator_.GenerateDocumentEntryUrl(resource_id); | |
| 380 GURL::Replacements replacements; | |
| 381 replacements.SetQueryStr(std::string()); | |
|
kinuko
2012/12/03 13:10:34
oh ok... it's cumbersome :(
tzik
2012/12/04 04:59:50
Ah, it seems not needed since we no longer use exa
| |
| 382 return link.ReplaceComponents(replacements); | |
| 383 } | |
| 384 | |
| 359 void DriveFileSyncClient::DidGetDocumentFeedData( | 385 void DriveFileSyncClient::DidGetDocumentFeedData( |
| 360 const DocumentFeedCallback& callback, | 386 const DocumentFeedCallback& callback, |
| 361 google_apis::GDataErrorCode error, | 387 google_apis::GDataErrorCode error, |
| 362 scoped_ptr<base::Value> data) { | 388 scoped_ptr<base::Value> data) { |
| 363 DCHECK(CalledOnValidThread()); | 389 DCHECK(CalledOnValidThread()); |
| 364 | 390 |
| 365 if (error != google_apis::HTTP_SUCCESS) { | 391 if (error != google_apis::HTTP_SUCCESS) { |
| 366 callback.Run(error, scoped_ptr<google_apis::DocumentFeed>()); | 392 callback.Run(error, scoped_ptr<google_apis::DocumentFeed>()); |
| 367 return; | 393 return; |
| 368 } | 394 } |
| 369 | 395 |
| 370 DCHECK(data); | 396 DCHECK(data); |
| 397 DVLOG(1) << *data; | |
|
kinuko
2012/12/03 13:10:34
nit: can you make this logging a bit more descript
tzik
2012/12/04 04:59:50
Done. Removed.
| |
| 371 scoped_ptr<google_apis::DocumentFeed> feed( | 398 scoped_ptr<google_apis::DocumentFeed> feed( |
| 372 google_apis::DocumentFeed::ExtractAndParse(*data)); | 399 google_apis::DocumentFeed::ExtractAndParse(*data)); |
| 373 if (!feed) | 400 if (!feed) |
| 374 error = google_apis::GDATA_PARSE_ERROR; | 401 error = google_apis::GDATA_PARSE_ERROR; |
| 375 callback.Run(error, feed.Pass()); | 402 callback.Run(error, feed.Pass()); |
| 376 } | 403 } |
| 377 | 404 |
| 378 void DriveFileSyncClient::DidGetDocumentEntryData( | 405 void DriveFileSyncClient::DidGetDocumentEntryData( |
| 379 const DocumentEntryCallback& callback, | 406 const DocumentEntryCallback& callback, |
| 380 google_apis::GDataErrorCode error, | 407 google_apis::GDataErrorCode error, |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 598 } | 625 } |
| 599 | 626 |
| 600 void DriveFileSyncClient::DidDeleteFile( | 627 void DriveFileSyncClient::DidDeleteFile( |
| 601 const GDataErrorCallback& callback, | 628 const GDataErrorCallback& callback, |
| 602 google_apis::GDataErrorCode error) { | 629 google_apis::GDataErrorCode error) { |
| 603 DCHECK(CalledOnValidThread()); | 630 DCHECK(CalledOnValidThread()); |
| 604 callback.Run(error); | 631 callback.Run(error); |
| 605 } | 632 } |
| 606 | 633 |
| 607 } // namespace sync_file_system | 634 } // namespace sync_file_system |
| OLD | NEW |