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