fake_drive_service_helper.cc revision 46d4c2bc3267f3f028f39e7e311b0f89aba2e4fd
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  fake_drive_service_->RenameResource(
183      file_id, new_title,
184      CreateResultReceiver(&error));
185  base::RunLoop().RunUntilIdle();
186  return error;
187}
188
189GDataErrorCode 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
200GDataErrorCode 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
211GDataErrorCode 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
234GDataErrorCode 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
249GDataErrorCode 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
265GDataErrorCode 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
276GDataErrorCode 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
302GDataErrorCode 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
311GDataErrorCode 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
337void 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
343base::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