fake_drive_service_helper.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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
22using google_apis::AboutResource;
23using google_apis::FileList;
24using google_apis::FileResource;
25using google_apis::GDataErrorCode;
26using google_apis::ResourceEntry;
27
28namespace sync_file_system {
29namespace drive_backend {
30
31namespace {
32
33void 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
44void 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
53FakeDriveServiceHelper::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
63FakeDriveServiceHelper::~FakeDriveServiceHelper() {
64}
65
66GDataErrorCode 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
85GDataErrorCode 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
102GDataErrorCode 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
124GDataErrorCode 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
140GDataErrorCode 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
151GDataErrorCode 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
161GDataErrorCode 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
178GDataErrorCode FakeDriveServiceHelper::RenameResource(
179    const std::string& file_id,
180    const std::string& new_title) {
181  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
182  scoped_ptr<FileResource> entry;
183  fake_drive_service_->UpdateResource(
184      file_id, std::string(), new_title, base::Time(), base::Time(),
185      CreateResultReceiver(&error, &entry));
186  base::RunLoop().RunUntilIdle();
187  return error;
188}
189
190GDataErrorCode FakeDriveServiceHelper::AddResourceToDirectory(
191    const std::string& parent_folder_id,
192    const std::string& file_id) {
193  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
194  fake_drive_service_->AddResourceToDirectory(
195      parent_folder_id, file_id,
196      CreateResultReceiver(&error));
197  base::RunLoop().RunUntilIdle();
198  return error;
199}
200
201GDataErrorCode FakeDriveServiceHelper::RemoveResourceFromDirectory(
202    const std::string& parent_folder_id,
203    const std::string& file_id) {
204  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
205  fake_drive_service_->RemoveResourceFromDirectory(
206      parent_folder_id, file_id,
207      CreateResultReceiver(&error));
208  base::RunLoop().RunUntilIdle();
209  return error;
210}
211
212GDataErrorCode FakeDriveServiceHelper::GetSyncRootFolderID(
213    std::string* sync_root_folder_id) {
214  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
215  scoped_ptr<FileList> resource_list;
216  fake_drive_service_->SearchByTitle(
217      sync_root_folder_title_, std::string(),
218      CreateResultReceiver(&error, &resource_list));
219  base::RunLoop().RunUntilIdle();
220  if (error != google_apis::HTTP_SUCCESS)
221    return error;
222
223  const ScopedVector<FileResource>& items = resource_list->items();
224  for (ScopedVector<FileResource>::const_iterator itr = items.begin();
225       itr != items.end(); ++itr) {
226    const FileResource& item = **itr;
227    if (item.parents().empty()) {
228      *sync_root_folder_id = item.file_id();
229      return google_apis::HTTP_SUCCESS;
230    }
231  }
232  return google_apis::HTTP_NOT_FOUND;
233}
234
235GDataErrorCode FakeDriveServiceHelper::ListFilesInFolder(
236    const std::string& folder_id,
237    ScopedVector<ResourceEntry>* entries) {
238  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
239  scoped_ptr<FileList> list;
240  fake_drive_service_->GetFileListInDirectory(
241      folder_id,
242      CreateResultReceiver(&error, &list));
243  base::RunLoop().RunUntilIdle();
244  if (error != google_apis::HTTP_SUCCESS)
245    return error;
246
247  return CompleteListing(list.Pass(), entries);
248}
249
250GDataErrorCode FakeDriveServiceHelper::SearchByTitle(
251    const std::string& folder_id,
252    const std::string& title,
253    ScopedVector<ResourceEntry>* entries) {
254  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
255  scoped_ptr<FileList> list;
256  fake_drive_service_->SearchByTitle(
257      title, folder_id,
258      CreateResultReceiver(&error, &list));
259  base::RunLoop().RunUntilIdle();
260  if (error != google_apis::HTTP_SUCCESS)
261    return error;
262
263  return CompleteListing(list.Pass(), entries);
264}
265
266GDataErrorCode FakeDriveServiceHelper::GetFileResource(
267    const std::string& file_id,
268    scoped_ptr<FileResource>* entry) {
269  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
270  fake_drive_service_->GetFileResource(
271      file_id,
272      CreateResultReceiver(&error, entry));
273  base::RunLoop().RunUntilIdle();
274  return error;
275}
276
277GDataErrorCode FakeDriveServiceHelper::ReadFile(
278    const std::string& file_id,
279    std::string* file_content) {
280  scoped_ptr<google_apis::FileResource> file;
281  GDataErrorCode error = GetFileResource(file_id, &file);
282  if (error != google_apis::HTTP_SUCCESS)
283    return error;
284  if (!file)
285    return google_apis::GDATA_PARSE_ERROR;
286
287  error = google_apis::GDATA_OTHER_ERROR;
288  base::FilePath temp_file;
289  EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_, &temp_file));
290  fake_drive_service_->DownloadFile(
291      temp_file, file->file_id(),
292      base::Bind(&DownloadResultCallback, &error),
293      google_apis::GetContentCallback(),
294      google_apis::ProgressCallback());
295  base::RunLoop().RunUntilIdle();
296  if (error != google_apis::HTTP_SUCCESS)
297    return error;
298
299  return base::ReadFileToString(temp_file, file_content)
300      ? google_apis::HTTP_SUCCESS : google_apis::GDATA_FILE_ERROR;
301}
302
303GDataErrorCode FakeDriveServiceHelper::GetAboutResource(
304    scoped_ptr<AboutResource>* about_resource) {
305  GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
306  fake_drive_service_->GetAboutResource(
307      CreateResultReceiver(&error, about_resource));
308  base::RunLoop().RunUntilIdle();
309  return error;
310}
311
312GDataErrorCode FakeDriveServiceHelper::CompleteListing(
313    scoped_ptr<FileList> list,
314    ScopedVector<ResourceEntry>* entries) {
315  while (true) {
316    entries->reserve(entries->size() + list->items().size());
317    for (ScopedVector<FileResource>::const_iterator itr =
318             list->items().begin(); itr != list->items().end(); ++itr) {
319      entries->push_back(
320          drive::util::ConvertFileResourceToResourceEntry(**itr).release());
321    }
322
323    GURL next_feed = list->next_link();
324    if (next_feed.is_empty())
325      return google_apis::HTTP_SUCCESS;
326
327    GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
328    list.reset();
329    fake_drive_service_->GetRemainingFileList(
330        next_feed,
331        CreateResultReceiver(&error, &list));
332    base::RunLoop().RunUntilIdle();
333    if (error != google_apis::HTTP_SUCCESS)
334      return error;
335  }
336}
337
338void FakeDriveServiceHelper::Initialize() {
339  ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
340  temp_dir_ = base_dir_.path().Append(FPL("tmp"));
341  ASSERT_TRUE(base::CreateDirectory(temp_dir_));
342}
343
344base::FilePath FakeDriveServiceHelper::WriteToTempFile(
345    const std::string& content) {
346  base::FilePath temp_file;
347  EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_, &temp_file));
348  EXPECT_EQ(static_cast<int>(content.size()),
349            base::WriteFile(temp_file, content.data(), content.size()));
350  return temp_file;
351}
352
353}  // namespace drive_backend
354}  // namespace sync_file_system
355