1 // Copyright 2014 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/sync_file_system/drive_backend/fake_drive_service_helper.h" 6 7 #include "base/bind.h" 8 #include "base/file_util.h" 9 #include "base/message_loop/message_loop.h" 10 #include "base/run_loop.h" 11 #include "base/threading/sequenced_worker_pool.h" 12 #include "chrome/browser/drive/drive_api_util.h" 13 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h" 14 #include "chrome/browser/sync_file_system/sync_status_code.h" 15 #include "google_apis/drive/drive_api_parser.h" 16 #include "google_apis/drive/gdata_wapi_parser.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 #include "webkit/browser/fileapi/file_system_url.h" 19 20 #define FPL(path) FILE_PATH_LITERAL(path) 21 22 using google_apis::AboutResource; 23 using google_apis::FileList; 24 using google_apis::FileResource; 25 using google_apis::GDataErrorCode; 26 using google_apis::ResourceEntry; 27 28 namespace sync_file_system { 29 namespace drive_backend { 30 31 namespace { 32 33 void UploadResultCallback(GDataErrorCode* error_out, 34 scoped_ptr<FileResource>* entry_out, 35 GDataErrorCode error, 36 const GURL& upload_location, 37 scoped_ptr<FileResource> entry) { 38 ASSERT_TRUE(error_out); 39 ASSERT_TRUE(entry_out); 40 *error_out = error; 41 *entry_out = entry.Pass(); 42 } 43 44 void DownloadResultCallback(GDataErrorCode* error_out, 45 GDataErrorCode error, 46 const base::FilePath& local_file) { 47 ASSERT_TRUE(error_out); 48 *error_out = error; 49 } 50 51 } // namespace 52 53 FakeDriveServiceHelper::FakeDriveServiceHelper( 54 drive::FakeDriveService* fake_drive_service, 55 drive::DriveUploaderInterface* drive_uploader, 56 const std::string& sync_root_folder_title) 57 : fake_drive_service_(fake_drive_service), 58 drive_uploader_(drive_uploader), 59 sync_root_folder_title_(sync_root_folder_title) { 60 Initialize(); 61 } 62 63 FakeDriveServiceHelper::~FakeDriveServiceHelper() { 64 } 65 66 GDataErrorCode FakeDriveServiceHelper::AddOrphanedFolder( 67 const std::string& title, 68 std::string* folder_id) { 69 std::string root_folder_id = fake_drive_service_->GetRootResourceId(); 70 GDataErrorCode error = AddFolder(root_folder_id, title, folder_id); 71 if (error != google_apis::HTTP_CREATED) 72 return error; 73 74 error = google_apis::GDATA_OTHER_ERROR; 75 fake_drive_service_->RemoveResourceFromDirectory( 76 root_folder_id, *folder_id, 77 CreateResultReceiver(&error)); 78 base::RunLoop().RunUntilIdle(); 79 80 if (error != google_apis::HTTP_NO_CONTENT && folder_id) 81 return error; 82 return google_apis::HTTP_CREATED; 83 } 84 85 GDataErrorCode FakeDriveServiceHelper::AddFolder( 86 const std::string& parent_folder_id, 87 const std::string& title, 88 std::string* folder_id) { 89 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 90 scoped_ptr<FileResource> folder; 91 fake_drive_service_->AddNewDirectory( 92 parent_folder_id, title, 93 drive::DriveServiceInterface::AddNewDirectoryOptions(), 94 CreateResultReceiver(&error, &folder)); 95 base::RunLoop().RunUntilIdle(); 96 97 if (error == google_apis::HTTP_CREATED && folder_id) 98 *folder_id = folder->file_id(); 99 return error; 100 } 101 102 GDataErrorCode FakeDriveServiceHelper::AddFile( 103 const std::string& parent_folder_id, 104 const std::string& title, 105 const std::string& content, 106 std::string* file_id) { 107 base::FilePath temp_file = WriteToTempFile(content); 108 109 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 110 scoped_ptr<FileResource> file; 111 drive_uploader_->UploadNewFile( 112 parent_folder_id, temp_file, title, 113 "application/octet-stream", 114 drive::DriveUploader::UploadNewFileOptions(), 115 base::Bind(&UploadResultCallback, &error, &file), 116 google_apis::ProgressCallback()); 117 base::RunLoop().RunUntilIdle(); 118 119 if (error == google_apis::HTTP_SUCCESS && file_id) 120 *file_id = file->file_id(); 121 return error; 122 } 123 124 GDataErrorCode FakeDriveServiceHelper::UpdateFile( 125 const std::string& file_id, 126 const std::string& content) { 127 base::FilePath temp_file = WriteToTempFile(content); 128 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 129 scoped_ptr<FileResource> file; 130 drive_uploader_->UploadExistingFile( 131 file_id, temp_file, 132 "application/octet-stream", 133 drive::DriveUploader::UploadExistingFileOptions(), 134 base::Bind(&UploadResultCallback, &error, &file), 135 google_apis::ProgressCallback()); 136 base::RunLoop().RunUntilIdle(); 137 return error; 138 } 139 140 GDataErrorCode FakeDriveServiceHelper::DeleteResource( 141 const std::string& file_id) { 142 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 143 fake_drive_service_->DeleteResource( 144 file_id, 145 std::string(), // etag 146 CreateResultReceiver(&error)); 147 base::RunLoop().RunUntilIdle(); 148 return error; 149 } 150 151 GDataErrorCode FakeDriveServiceHelper::TrashResource( 152 const std::string& file_id) { 153 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 154 fake_drive_service_->TrashResource( 155 file_id, 156 CreateResultReceiver(&error)); 157 base::RunLoop().RunUntilIdle(); 158 return error; 159 } 160 161 GDataErrorCode FakeDriveServiceHelper::UpdateModificationTime( 162 const std::string& file_id, 163 const base::Time& modification_time) { 164 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 165 scoped_ptr<FileResource> entry; 166 error = GetFileResource(file_id, &entry); 167 if (error != google_apis::HTTP_SUCCESS) 168 return error; 169 170 fake_drive_service_->UpdateResource( 171 file_id, std::string(), entry->title(), 172 modification_time, entry->last_viewed_by_me_date(), 173 CreateResultReceiver(&error, &entry)); 174 base::RunLoop().RunUntilIdle(); 175 return error; 176 } 177 178 GDataErrorCode FakeDriveServiceHelper::RenameResource( 179 const std::string& file_id, 180 const std::string& new_title) { 181 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 182 fake_drive_service_->RenameResource( 183 file_id, new_title, 184 CreateResultReceiver(&error)); 185 base::RunLoop().RunUntilIdle(); 186 return error; 187 } 188 189 GDataErrorCode FakeDriveServiceHelper::AddResourceToDirectory( 190 const std::string& parent_folder_id, 191 const std::string& file_id) { 192 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 193 fake_drive_service_->AddResourceToDirectory( 194 parent_folder_id, file_id, 195 CreateResultReceiver(&error)); 196 base::RunLoop().RunUntilIdle(); 197 return error; 198 } 199 200 GDataErrorCode FakeDriveServiceHelper::RemoveResourceFromDirectory( 201 const std::string& parent_folder_id, 202 const std::string& file_id) { 203 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 204 fake_drive_service_->RemoveResourceFromDirectory( 205 parent_folder_id, file_id, 206 CreateResultReceiver(&error)); 207 base::RunLoop().RunUntilIdle(); 208 return error; 209 } 210 211 GDataErrorCode FakeDriveServiceHelper::GetSyncRootFolderID( 212 std::string* sync_root_folder_id) { 213 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 214 scoped_ptr<FileList> resource_list; 215 fake_drive_service_->SearchByTitle( 216 sync_root_folder_title_, std::string(), 217 CreateResultReceiver(&error, &resource_list)); 218 base::RunLoop().RunUntilIdle(); 219 if (error != google_apis::HTTP_SUCCESS) 220 return error; 221 222 const ScopedVector<FileResource>& items = resource_list->items(); 223 for (ScopedVector<FileResource>::const_iterator itr = items.begin(); 224 itr != items.end(); ++itr) { 225 const FileResource& item = **itr; 226 if (item.parents().empty()) { 227 *sync_root_folder_id = item.file_id(); 228 return google_apis::HTTP_SUCCESS; 229 } 230 } 231 return google_apis::HTTP_NOT_FOUND; 232 } 233 234 GDataErrorCode FakeDriveServiceHelper::ListFilesInFolder( 235 const std::string& folder_id, 236 ScopedVector<ResourceEntry>* entries) { 237 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 238 scoped_ptr<FileList> list; 239 fake_drive_service_->GetFileListInDirectory( 240 folder_id, 241 CreateResultReceiver(&error, &list)); 242 base::RunLoop().RunUntilIdle(); 243 if (error != google_apis::HTTP_SUCCESS) 244 return error; 245 246 return CompleteListing(list.Pass(), entries); 247 } 248 249 GDataErrorCode FakeDriveServiceHelper::SearchByTitle( 250 const std::string& folder_id, 251 const std::string& title, 252 ScopedVector<ResourceEntry>* entries) { 253 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 254 scoped_ptr<FileList> list; 255 fake_drive_service_->SearchByTitle( 256 title, folder_id, 257 CreateResultReceiver(&error, &list)); 258 base::RunLoop().RunUntilIdle(); 259 if (error != google_apis::HTTP_SUCCESS) 260 return error; 261 262 return CompleteListing(list.Pass(), entries); 263 } 264 265 GDataErrorCode FakeDriveServiceHelper::GetFileResource( 266 const std::string& file_id, 267 scoped_ptr<FileResource>* entry) { 268 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 269 fake_drive_service_->GetFileResource( 270 file_id, 271 CreateResultReceiver(&error, entry)); 272 base::RunLoop().RunUntilIdle(); 273 return error; 274 } 275 276 GDataErrorCode FakeDriveServiceHelper::ReadFile( 277 const std::string& file_id, 278 std::string* file_content) { 279 scoped_ptr<google_apis::FileResource> file; 280 GDataErrorCode error = GetFileResource(file_id, &file); 281 if (error != google_apis::HTTP_SUCCESS) 282 return error; 283 if (!file) 284 return google_apis::GDATA_PARSE_ERROR; 285 286 error = google_apis::GDATA_OTHER_ERROR; 287 base::FilePath temp_file; 288 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_, &temp_file)); 289 fake_drive_service_->DownloadFile( 290 temp_file, file->file_id(), 291 base::Bind(&DownloadResultCallback, &error), 292 google_apis::GetContentCallback(), 293 google_apis::ProgressCallback()); 294 base::RunLoop().RunUntilIdle(); 295 if (error != google_apis::HTTP_SUCCESS) 296 return error; 297 298 return base::ReadFileToString(temp_file, file_content) 299 ? google_apis::HTTP_SUCCESS : google_apis::GDATA_FILE_ERROR; 300 } 301 302 GDataErrorCode FakeDriveServiceHelper::GetAboutResource( 303 scoped_ptr<AboutResource>* about_resource) { 304 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 305 fake_drive_service_->GetAboutResource( 306 CreateResultReceiver(&error, about_resource)); 307 base::RunLoop().RunUntilIdle(); 308 return error; 309 } 310 311 GDataErrorCode FakeDriveServiceHelper::CompleteListing( 312 scoped_ptr<FileList> list, 313 ScopedVector<ResourceEntry>* entries) { 314 while (true) { 315 entries->reserve(entries->size() + list->items().size()); 316 for (ScopedVector<FileResource>::const_iterator itr = 317 list->items().begin(); itr != list->items().end(); ++itr) { 318 entries->push_back( 319 drive::util::ConvertFileResourceToResourceEntry(**itr).release()); 320 } 321 322 GURL next_feed = list->next_link(); 323 if (next_feed.is_empty()) 324 return google_apis::HTTP_SUCCESS; 325 326 GDataErrorCode error = google_apis::GDATA_OTHER_ERROR; 327 list.reset(); 328 fake_drive_service_->GetRemainingFileList( 329 next_feed, 330 CreateResultReceiver(&error, &list)); 331 base::RunLoop().RunUntilIdle(); 332 if (error != google_apis::HTTP_SUCCESS) 333 return error; 334 } 335 } 336 337 void FakeDriveServiceHelper::Initialize() { 338 ASSERT_TRUE(base_dir_.CreateUniqueTempDir()); 339 temp_dir_ = base_dir_.path().Append(FPL("tmp")); 340 ASSERT_TRUE(base::CreateDirectory(temp_dir_)); 341 } 342 343 base::FilePath FakeDriveServiceHelper::WriteToTempFile( 344 const std::string& content) { 345 base::FilePath temp_file; 346 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_, &temp_file)); 347 EXPECT_EQ(static_cast<int>(content.size()), 348 base::WriteFile(temp_file, content.data(), content.size())); 349 return temp_file; 350 } 351 352 } // namespace drive_backend 353 } // namespace sync_file_system 354