fake_file_system.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
1// Copyright (c) 2013 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/chromeos/drive/fake_file_system.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/callback.h"
10#include "base/file_util.h"
11#include "base/files/file_path.h"
12#include "base/logging.h"
13#include "chrome/browser/chromeos/drive/drive.pb.h"
14#include "chrome/browser/chromeos/drive/file_errors.h"
15#include "chrome/browser/chromeos/drive/file_system_util.h"
16#include "chrome/browser/chromeos/drive/resource_entry_conversion.h"
17#include "chrome/browser/google_apis/drive_api_parser.h"
18#include "chrome/browser/google_apis/gdata_wapi_parser.h"
19#include "content/public/browser/browser_thread.h"
20
21namespace drive {
22namespace test_util {
23
24using content::BrowserThread;
25
26FakeFileSystem::FakeFileSystem(
27    google_apis::DriveServiceInterface* drive_service)
28    : drive_service_(drive_service),
29      weak_ptr_factory_(this) {
30}
31
32FakeFileSystem::~FakeFileSystem() {
33}
34
35bool FakeFileSystem::InitializeForTesting() {
36  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
37  return cache_dir_.CreateUniqueTempDir();
38}
39
40void FakeFileSystem::Initialize() {
41  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42  InitializeForTesting();
43}
44
45void FakeFileSystem::AddObserver(FileSystemObserver* observer) {
46  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
47}
48
49void FakeFileSystem::RemoveObserver(FileSystemObserver* observer) {
50  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
51}
52
53void FakeFileSystem::CheckForUpdates() {
54  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
55}
56
57void FakeFileSystem::GetEntryInfoByResourceId(
58    const std::string& resource_id,
59    const GetEntryInfoWithFilePathCallback& callback) {
60  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
61
62  drive_service_->GetResourceEntry(
63      resource_id,
64      base::Bind(
65          &FakeFileSystem::GetEntryInfoByResourceIdAfterGetResourceEntry,
66          weak_ptr_factory_.GetWeakPtr(), callback));
67}
68
69void FakeFileSystem::TransferFileFromRemoteToLocal(
70    const base::FilePath& remote_src_file_path,
71    const base::FilePath& local_dest_file_path,
72    const FileOperationCallback& callback) {
73  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74}
75
76void FakeFileSystem::TransferFileFromLocalToRemote(
77    const base::FilePath& local_src_file_path,
78    const base::FilePath& remote_dest_file_path,
79    const FileOperationCallback& callback) {
80  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
81}
82
83void FakeFileSystem::OpenFile(const base::FilePath& file_path,
84                              const OpenFileCallback& callback) {
85  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86}
87
88void FakeFileSystem::CloseFile(const base::FilePath& file_path,
89                               const FileOperationCallback& callback) {
90  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
91}
92
93void FakeFileSystem::Copy(const base::FilePath& src_file_path,
94                          const base::FilePath& dest_file_path,
95                          const FileOperationCallback& callback) {
96  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
97}
98
99void FakeFileSystem::Move(const base::FilePath& src_file_path,
100                          const base::FilePath& dest_file_path,
101                          const FileOperationCallback& callback) {
102  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
103}
104
105void FakeFileSystem::Remove(const base::FilePath& file_path,
106                            bool is_recursive,
107                            const FileOperationCallback& callback) {
108  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
109}
110
111void FakeFileSystem::CreateDirectory(
112    const base::FilePath& directory_path,
113    bool is_exclusive,
114    bool is_recursive,
115    const FileOperationCallback& callback) {
116  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
117}
118
119void FakeFileSystem::CreateFile(const base::FilePath& file_path,
120                                bool is_exclusive,
121                                const FileOperationCallback& callback) {
122  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
123}
124
125void FakeFileSystem::Pin(const base::FilePath& file_path,
126                         const FileOperationCallback& callback) {
127  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
128}
129
130void FakeFileSystem::Unpin(const base::FilePath& file_path,
131                           const FileOperationCallback& callback) {
132  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
133}
134
135void FakeFileSystem::GetFileByPath(const base::FilePath& file_path,
136                                   const GetFileCallback& callback) {
137  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
138}
139
140void FakeFileSystem::GetFileByResourceId(
141    const std::string& resource_id,
142    const DriveClientContext& context,
143    const GetFileCallback& get_file_callback,
144    const google_apis::GetContentCallback& get_content_callback) {
145  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146}
147
148void FakeFileSystem::GetFileContentByPath(
149    const base::FilePath& file_path,
150    const GetFileContentInitializedCallback& initialized_callback,
151    const google_apis::GetContentCallback& get_content_callback,
152    const FileOperationCallback& completion_callback) {
153  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
154
155  GetEntryInfoByPath(
156      file_path,
157      base::Bind(&FakeFileSystem::GetFileContentByPathAfterGetEntryInfo,
158                 weak_ptr_factory_.GetWeakPtr(),
159                 file_path, initialized_callback, get_content_callback,
160                 completion_callback));
161}
162
163void FakeFileSystem::UpdateFileByResourceId(
164    const std::string& resource_id,
165    const DriveClientContext& context,
166    const FileOperationCallback& callback) {
167  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168}
169
170void FakeFileSystem::GetEntryInfoByPath(
171    const base::FilePath& file_path,
172    const GetEntryInfoCallback& callback) {
173  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
174
175  // Now, we only support files under my drive.
176  DCHECK(!util::IsUnderDriveMountPoint(file_path));
177
178  if (file_path == util::GetDriveMyDriveRootPath()) {
179    // Specialized for the root entry.
180    drive_service_->GetAboutResource(
181        base::Bind(
182            &FakeFileSystem::GetEntryInfoByPathAfterGetAboutResource,
183            weak_ptr_factory_.GetWeakPtr(), callback));
184    return;
185  }
186
187  GetEntryInfoByPath(
188      file_path.DirName(),
189      base::Bind(
190          &FakeFileSystem::GetEntryInfoByPathAfterGetParentEntryInfo,
191          weak_ptr_factory_.GetWeakPtr(), file_path.BaseName(), callback));
192}
193
194void FakeFileSystem::ReadDirectoryByPath(
195    const base::FilePath& file_path,
196    const ReadDirectoryWithSettingCallback& callback) {
197  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
198}
199
200void FakeFileSystem::RefreshDirectory(
201    const base::FilePath& file_path,
202    const FileOperationCallback& callback) {
203  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
204}
205
206void FakeFileSystem::Search(const std::string& search_query,
207                            const GURL& next_feed,
208                            const SearchCallback& callback) {
209  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210}
211
212void FakeFileSystem::SearchMetadata(
213    const std::string& query,
214    int options,
215    int at_most_num_matches,
216    const SearchMetadataCallback& callback) {
217  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
218}
219
220void FakeFileSystem::GetAvailableSpace(
221    const GetAvailableSpaceCallback& callback) {
222  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
223}
224
225void FakeFileSystem::AddUploadedFile(
226    scoped_ptr<google_apis::ResourceEntry> doc_entry,
227    const base::FilePath& file_content_path,
228    const FileOperationCallback& callback) {
229  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230}
231
232void FakeFileSystem::GetMetadata(
233    const GetFilesystemMetadataCallback& callback) {
234  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
235}
236
237void FakeFileSystem::MarkCacheFileAsMounted(
238    const base::FilePath& drive_file_path,
239    const OpenFileCallback& callback) {
240  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241}
242
243void FakeFileSystem::MarkCacheFileAsUnmounted(
244    const base::FilePath& cache_file_path,
245    const FileOperationCallback& callback) {
246  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
247}
248
249void FakeFileSystem::GetCacheEntryByResourceId(
250    const std::string& resource_id,
251    const std::string& md5,
252    const GetCacheEntryCallback& callback) {
253  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
254}
255
256void FakeFileSystem::Reload() {
257}
258
259// Implementation of GetFilePath.
260void FakeFileSystem::GetFilePath(const std::string& resource_id,
261                                 const GetFilePathCallback& callback) {
262  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
263
264  drive_service_->GetAboutResource(
265      base::Bind(
266          &FakeFileSystem::GetFilePathAfterGetAboutResource,
267          weak_ptr_factory_.GetWeakPtr(), resource_id, callback));
268}
269
270void FakeFileSystem::GetFilePathAfterGetAboutResource(
271    const std::string& resource_id,
272    const GetFilePathCallback& callback,
273    google_apis::GDataErrorCode error,
274    scoped_ptr<google_apis::AboutResource> about_resource) {
275  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
276
277  // We assume the call always success for test.
278  DCHECK_EQ(util::GDataToFileError(error), FILE_ERROR_OK);
279  DCHECK(about_resource);
280
281  GetFilePathInternal(about_resource->root_folder_id(), resource_id,
282                      base::FilePath(), callback);
283}
284
285void FakeFileSystem::GetFilePathInternal(
286    const std::string& root_resource_id,
287    const std::string& resource_id,
288    const base::FilePath& file_path,
289    const GetFilePathCallback& callback) {
290  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
291
292  if (resource_id == root_resource_id) {
293    // Reached to the root. Append the drive root path, and run |callback|.
294    callback.Run(util::GetDriveMyDriveRootPath().Append(file_path));
295    return;
296  }
297
298  drive_service_->GetResourceEntry(
299      resource_id,
300      base::Bind(
301          &FakeFileSystem::GetFilePathAfterGetResourceEntry,
302          weak_ptr_factory_.GetWeakPtr(),
303          root_resource_id, file_path, callback));
304}
305
306void FakeFileSystem::GetFilePathAfterGetResourceEntry(
307    const std::string& root_resource_id,
308    const base::FilePath& remaining_file_path,
309    const GetFilePathCallback& callback,
310    google_apis::GDataErrorCode error_in,
311    scoped_ptr<google_apis::ResourceEntry> resource_entry) {
312  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
313
314  // We assume the call always success for test.
315  DCHECK_EQ(util::GDataToFileError(error_in), FILE_ERROR_OK);
316  DCHECK(resource_entry);
317
318  ResourceEntry entry = ConvertToResourceEntry(*resource_entry);
319  base::FilePath file_path =
320      base::FilePath::FromUTF8Unsafe(entry.base_name()).Append(
321          remaining_file_path);
322
323  GetFilePathInternal(root_resource_id, entry.parent_resource_id(),
324                      file_path, callback);
325}
326
327// Implementation of GetEntryInfoByResourceId.
328void FakeFileSystem::GetEntryInfoByResourceIdAfterGetResourceEntry(
329    const GetEntryInfoWithFilePathCallback& callback,
330    google_apis::GDataErrorCode error_in,
331    scoped_ptr<google_apis::ResourceEntry> resource_entry) {
332  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
333
334  FileError error = util::GDataToFileError(error_in);
335  if (error != FILE_ERROR_OK) {
336    callback.Run(error, base::FilePath(), scoped_ptr<ResourceEntry>());
337    return;
338  }
339
340  DCHECK(resource_entry);
341  scoped_ptr<ResourceEntry> entry(new ResourceEntry(
342      ConvertToResourceEntry(*resource_entry)));
343
344  const std::string parent_resource_id = entry->parent_resource_id();
345  GetFilePath(
346      parent_resource_id,
347      base::Bind(
348          &FakeFileSystem::GetEntryInfoByResourceIdAfterGetFilePath,
349          weak_ptr_factory_.GetWeakPtr(),
350          callback, error, base::Passed(&entry)));
351}
352
353void FakeFileSystem::GetEntryInfoByResourceIdAfterGetFilePath(
354    const GetEntryInfoWithFilePathCallback& callback,
355    FileError error,
356    scoped_ptr<ResourceEntry> entry,
357    const base::FilePath& parent_file_path) {
358  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
359  base::FilePath file_path = parent_file_path.Append(
360      base::FilePath::FromUTF8Unsafe(entry->base_name()));
361  callback.Run(error, file_path, entry.Pass());
362}
363
364// Implementation of GetFileContentByPath.
365void FakeFileSystem::GetFileContentByPathAfterGetEntryInfo(
366    const base::FilePath& file_path,
367    const GetFileContentInitializedCallback& initialized_callback,
368    const google_apis::GetContentCallback& get_content_callback,
369    const FileOperationCallback& completion_callback,
370    FileError error,
371    scoped_ptr<ResourceEntry> entry) {
372  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
373
374  if (error != FILE_ERROR_OK) {
375    completion_callback.Run(error);
376    return;
377  }
378  DCHECK(entry);
379
380  // We're only interested in a file.
381  if (entry->file_info().is_directory()) {
382    completion_callback.Run(FILE_ERROR_NOT_A_FILE);
383    return;
384  }
385
386  // Fetch the ResourceEntry for its |download_url|.
387  drive_service_->GetResourceEntry(
388      entry->resource_id(),
389      base::Bind(&FakeFileSystem::GetFileContentByPathAfterGetResourceEntry,
390                 weak_ptr_factory_.GetWeakPtr(),
391                 file_path,
392                 initialized_callback,
393                 get_content_callback,
394                 completion_callback));
395}
396
397void FakeFileSystem::GetFileContentByPathAfterGetResourceEntry(
398    const base::FilePath& file_path,
399    const GetFileContentInitializedCallback& initialized_callback,
400    const google_apis::GetContentCallback& get_content_callback,
401    const FileOperationCallback& completion_callback,
402    google_apis::GDataErrorCode gdata_error,
403    scoped_ptr<google_apis::ResourceEntry> gdata_entry) {
404  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
405
406  FileError error = util::GDataToFileError(gdata_error);
407  if (error != FILE_ERROR_OK) {
408    completion_callback.Run(error);
409    return;
410  }
411  DCHECK(gdata_entry);
412
413  scoped_ptr<ResourceEntry> entry(
414      new ResourceEntry(ConvertToResourceEntry(*gdata_entry)));
415
416  base::FilePath cache_path =
417      cache_dir_.path().AppendASCII(entry->resource_id());
418  if (file_util::PathExists(cache_path)) {
419    // Cache file is found.
420    initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), cache_path,
421                             base::Closure());
422    completion_callback.Run(FILE_ERROR_OK);
423    return;
424  }
425
426  initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), base::FilePath(),
427                           base::Bind(&base::DoNothing));
428  drive_service_->DownloadFile(
429      file_path,
430      cache_path,
431      GURL(gdata_entry->download_url()),
432      base::Bind(&FakeFileSystem::GetFileContentByPathAfterDownloadFile,
433                 weak_ptr_factory_.GetWeakPtr(),
434                 completion_callback),
435      get_content_callback,
436      google_apis::ProgressCallback());
437}
438
439void FakeFileSystem::GetFileContentByPathAfterDownloadFile(
440    const FileOperationCallback& completion_callback,
441    google_apis::GDataErrorCode gdata_error,
442    const base::FilePath& temp_file) {
443  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
444  completion_callback.Run(util::GDataToFileError(gdata_error));
445}
446
447// Implementation of GetEntryInfoByPath.
448void FakeFileSystem::GetEntryInfoByPathAfterGetAboutResource(
449    const GetEntryInfoCallback& callback,
450    google_apis::GDataErrorCode gdata_error,
451    scoped_ptr<google_apis::AboutResource> about_resource) {
452  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
453
454  FileError error = util::GDataToFileError(gdata_error);
455  if (error != FILE_ERROR_OK) {
456    callback.Run(error, scoped_ptr<ResourceEntry>());
457    return;
458  }
459
460  DCHECK(about_resource);
461  scoped_ptr<ResourceEntry> root(new ResourceEntry);
462  root->mutable_file_info()->set_is_directory(true);
463  root->set_resource_id(about_resource->root_folder_id());
464  root->set_title(util::kDriveMyDriveRootDirName);
465  callback.Run(error, root.Pass());
466}
467
468void FakeFileSystem::GetEntryInfoByPathAfterGetParentEntryInfo(
469    const base::FilePath& base_name,
470    const GetEntryInfoCallback& callback,
471    FileError error,
472    scoped_ptr<ResourceEntry> parent_entry) {
473  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
474
475  if (error != FILE_ERROR_OK) {
476    callback.Run(error, scoped_ptr<ResourceEntry>());
477    return;
478  }
479
480  DCHECK(parent_entry);
481  drive_service_->GetResourceListInDirectory(
482      parent_entry->resource_id(),
483      base::Bind(
484          &FakeFileSystem::GetEntryInfoByPathAfterGetResourceList,
485          weak_ptr_factory_.GetWeakPtr(), base_name, callback));
486}
487
488void FakeFileSystem::GetEntryInfoByPathAfterGetResourceList(
489    const base::FilePath& base_name,
490    const GetEntryInfoCallback& callback,
491    google_apis::GDataErrorCode gdata_error,
492    scoped_ptr<google_apis::ResourceList> resource_list) {
493  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
494
495  FileError error = util::GDataToFileError(gdata_error);
496  if (error != FILE_ERROR_OK) {
497    callback.Run(error, scoped_ptr<ResourceEntry>());
498    return;
499  }
500
501  DCHECK(resource_list);
502  const ScopedVector<google_apis::ResourceEntry>& entries =
503      resource_list->entries();
504  for (size_t i = 0; i < entries.size(); ++i) {
505    scoped_ptr<ResourceEntry> entry(new ResourceEntry(
506        ConvertToResourceEntry(*entries[i])));
507    if (entry->base_name() == base_name.AsUTF8Unsafe()) {
508      // Found the target entry.
509      callback.Run(FILE_ERROR_OK, entry.Pass());
510      return;
511    }
512  }
513
514  callback.Run(FILE_ERROR_NOT_FOUND, scoped_ptr<ResourceEntry>());
515}
516
517}  // namespace test_util
518}  // namespace drive
519