resource_metadata.cc revision a93a17c8d99d686bd4a1511e5504e5e6cc9fcadf
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_metadata.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/stringprintf.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/sys_info.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/drive.pb.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::BrowserThread;
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace drive {
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Sets entry's base name from its title and other attributes.
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SetBaseNameFromTitle(ResourceEntry* entry) {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string base_name = entry->title();
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (entry->has_file_specific_info() &&
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      entry->file_specific_info().is_hosted_document()) {
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base_name += entry->file_specific_info().document_extension();
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->set_base_name(util::EscapeUtf8FileName(base_name));
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Creates an entry by copying |source|, and setting the base name properly.
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ResourceEntry CreateEntryWithProperBaseName(const ResourceEntry& source) {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResourceEntry entry(source);
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetBaseNameFromTitle(&entry);
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return entry;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Runs |callback| with |result|. Used to implement GetChildDirectories().
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RunGetChildDirectoriesCallbackWithResult(
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GetChildDirectoriesCallback& callback,
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<std::set<base::FilePath> > result) {
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(*result);
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Returns true if enough disk space is avilable for DB operation.
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// TODO(hashimoto): Merge this with FileCache's FreeDiskSpaceGetterInterface.
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool EnoughDiskSpaceIsAvailableForDBOperation(const base::FilePath& path) {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const int64 kRequiredDiskSpaceInMB = 128;  // 128 MB seems to be large enough.
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return base::SysInfo::AmountOfFreeDiskSpace(path) >=
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      kRequiredDiskSpaceInMB * (1 << 20);
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Runs |callback| with arguments.
54a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void RunGetResourceEntryCallback(const GetResourceEntryCallback& callback,
55a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                 scoped_ptr<ResourceEntry> entry,
56a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                 FileError error) {
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != FILE_ERROR_OK)
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entry.reset();
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(error, entry.Pass());
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Runs |callback| with arguments.
65a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void RunGetResourceEntryWithFilePathCallback(
66a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryWithFilePathCallback& callback,
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath* path,
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ResourceEntry> entry,
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileError error) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(path);
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != FILE_ERROR_OK)
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entry.reset();
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(error, *path, entry.Pass());
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Runs |callback| with arguments.
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RunReadDirectoryCallback(const ReadDirectoryCallback& callback,
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              scoped_ptr<ResourceEntryVector> entries,
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              FileError error) {
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != FILE_ERROR_OK)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entries.reset();
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(error, entries.Pass());
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Runs |callback| with arguments.
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void RunFileMoveCallback(const FileMoveCallback& callback,
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         base::FilePath* path,
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                         FileError error) {
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(path);
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(error, *path);
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Helper function to run tasks with FileMoveCallback.
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PostFileMoveTask(
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::TaskRunner* task_runner,
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Callback<FileError(base::FilePath* out_file_path)>& task,
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const FileMoveCallback& callback) {
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!task.is_null());
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath* file_path = new base::FilePath;
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      task_runner,
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(task, file_path),
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&RunFileMoveCallback, callback, base::Owned(file_path)));
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string DirectoryFetchInfo::ToString() const {
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return ("resource_id: " + resource_id_ +
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          ", changestamp: " + base::Int64ToString(changestamp_));
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EntryInfoResult::EntryInfoResult() : error(FILE_ERROR_FAILED) {
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EntryInfoResult::~EntryInfoResult() {
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EntryInfoPairResult::EntryInfoPairResult() {
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)EntryInfoPairResult::~EntryInfoPairResult() {
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace internal {
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ResourceMetadata::ResourceMetadata(
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& data_directory_path,
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : data_directory_path_(data_directory_path),
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_(blocking_task_runner),
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      storage_(new ResourceMetadataStorage(data_directory_path)),
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_ptr_factory_(this) {
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ResourceMetadata::Initialize(const FileOperationCallback& callback) {
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&ResourceMetadata::InitializeOnBlockingPool,
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback);
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ResourceMetadata::Destroy() {
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  weak_ptr_factory_.InvalidateWeakPtrs();
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  blocking_task_runner_->PostTask(
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&ResourceMetadata::DestroyOnBlockingPool,
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)));
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::ResetOnUIThread(const FileOperationCallback& callback) {
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
177b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&ResourceMetadata::Reset,
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback);
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
182b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::Reset() {
183b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
184b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
185b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
186b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
187b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
188b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!storage_->SetLargestChangestamp(0) ||
189b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      !RemoveEntryRecursively(util::kDriveGrandRootSpecialResourceId) ||
190b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      !SetUpDefaultEntries())
191b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_FAILED;
192b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
193b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
194b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
195b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ResourceMetadata::~ResourceMetadata() {
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)FileError ResourceMetadata::InitializeOnBlockingPool() {
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the storage.
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!storage_->Initialize())
208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_FAILED;
209c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!SetUpDefaultEntries())
211c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_FAILED;
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return FILE_ERROR_OK;
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadata::SetUpDefaultEntries() {
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Initialize the grand root and "other" entries. "/drive" and "/drive/other".
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // As an intermediate change, "/drive/root" is also added here.
221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!storage_->GetEntry(util::kDriveGrandRootSpecialResourceId)) {
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ResourceEntry root;
223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root.mutable_file_info()->set_is_directory(true);
224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root.set_resource_id(util::kDriveGrandRootSpecialResourceId);
225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    root.set_title(util::kDriveGrandRootDirName);
226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!storage_->PutEntry(CreateEntryWithProperBaseName(root)))
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!storage_->GetEntry(util::kDriveOtherDirSpecialResourceId)) {
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!PutEntryUnderDirectory(util::CreateOtherDirEntry()))
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ResourceMetadata::DestroyOnBlockingPool() {
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delete this;
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
241b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::GetLargestChangestampOnUIThread(
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GetChangestampCallback& callback) {
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
248b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&ResourceMetadata::GetLargestChangestamp,
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this)),
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
253b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::SetLargestChangestampOnUIThread(
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int64 value,
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const FileOperationCallback& callback) {
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
261b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&ResourceMetadata::SetLargestChangestamp,
262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 value),
264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      callback);
265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
267b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)int64 ResourceMetadata::GetLargestChangestamp() {
268b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
269b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return storage_->GetLargestChangestamp();
270b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
271b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
272b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::SetLargestChangestamp(int64 value) {
273b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
274b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
275b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
276b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
277b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  storage_->SetLargestChangestamp(value);
279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::AddEntryOnUIThread(const ResourceEntry& entry,
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                          const FileMoveCallback& callback) {
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostFileMoveTask(blocking_task_runner_,
288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   base::Bind(&ResourceMetadata::AddEntry,
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              base::Unretained(this),
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              entry),
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   callback);
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::AddEntry(const ResourceEntry& entry,
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                     base::FilePath* out_file_path) {
296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> existing_entry =
302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      storage_->GetEntry(entry.resource_id());
303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (existing_entry)
304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_EXISTS;
305b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
306b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> parent =
307b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      GetDirectory(entry.parent_resource_id());
308b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!parent)
309b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
310b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
311b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!PutEntryUnderDirectory(entry))
312b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_FAILED;
313b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
314b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (out_file_path)
315b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *out_file_path = GetFilePath(entry.resource_id());
316b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
317b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
318b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
319b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
320b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::MoveEntryToDirectoryOnUIThread(
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& file_path,
322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& directory_path,
323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const FileMoveCallback& callback) {
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
327b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PostFileMoveTask(blocking_task_runner_,
328b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   base::Bind(&ResourceMetadata::MoveEntryToDirectory,
329b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              base::Unretained(this),
330b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              file_path,
331b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              directory_path),
332b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   callback);
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
335b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::RenameEntryOnUIThread(const base::FilePath& file_path,
336b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                             const std::string& new_name,
337b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                             const FileMoveCallback& callback) {
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostFileMoveTask(blocking_task_runner_,
342b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   base::Bind(&ResourceMetadata::RenameEntry,
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              base::Unretained(this),
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              file_path,
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              new_name),
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   callback);
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
349b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::RemoveEntryOnUIThread(const std::string& resource_id,
350b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                             const FileMoveCallback& callback) {
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  PostFileMoveTask(blocking_task_runner_,
355b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   base::Bind(&ResourceMetadata::RemoveEntry,
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              base::Unretained(this),
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              resource_id),
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   callback);
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::RemoveEntry(const std::string& resource_id,
362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                        base::FilePath* out_file_path) {
363b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
364b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
365b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
366b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
367b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
368b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Disallow deletion of special entries "/drive" and "/drive/other".
369b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (util::IsSpecialResourceId(resource_id))
370b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_ACCESS_DENIED;
371b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
372b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = storage_->GetEntry(resource_id);
373b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!entry)
374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
375b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
376b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!RemoveEntryRecursively(entry->resource_id()))
377b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_FAILED;
378b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
379b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (out_file_path)
380b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *out_file_path = GetFilePath(entry->parent_resource_id());
381b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
382b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
383b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
384a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ResourceMetadata::GetResourceEntryByIdOnUIThread(
385c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& resource_id,
386a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryWithFilePathCallback& callback) {
387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath* file_path = new base::FilePath;
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry(new ResourceEntry);
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResourceEntry* entry_ptr = entry.get();
393c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
396a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&ResourceMetadata::GetResourceEntryById,
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 resource_id,
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 file_path,
400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 entry_ptr),
401a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&RunGetResourceEntryWithFilePathCallback,
402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback,
403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Owned(file_path),
404c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&entry)));
405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
407a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)FileError ResourceMetadata::GetResourceEntryById(
408b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& resource_id,
409b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    base::FilePath* out_file_path,
410b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    ResourceEntry* out_entry) {
411b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
412b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(!resource_id.empty());
413b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
414b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = storage_->GetEntry(resource_id);
415b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!entry)
416b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
417b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
418b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (out_file_path)
419b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *out_file_path = GetFilePath(resource_id);
420b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (out_entry)
421b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *out_entry = *entry;
422b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
423b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
424b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
425b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
426a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ResourceMetadata::GetResourceEntryByPathOnUIThread(
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& file_path,
428a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryCallback& callback) {
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry(new ResourceEntry);
433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResourceEntry* entry_ptr = entry.get();
434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
435c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
436c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
437a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&ResourceMetadata::GetResourceEntryByPath,
438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 file_path,
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 entry_ptr),
441a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&RunGetResourceEntryCallback,
442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback,
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&entry)));
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
446a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)FileError ResourceMetadata::GetResourceEntryByPath(const base::FilePath& path,
447a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                                                   ResourceEntry* out_entry) {
448b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(out_entry);
450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = FindEntryByPathSync(path);
452b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!entry)
453b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
454b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
455b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  *out_entry = *entry;
456b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
457b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
458b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
459b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::ReadDirectoryByPathOnUIThread(
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& file_path,
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ReadDirectoryCallback& callback) {
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
464c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
465c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntryVector> entries(new ResourceEntryVector);
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResourceEntryVector* entries_ptr = entries.get();
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
469c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
470b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&ResourceMetadata::ReadDirectoryByPath,
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 file_path,
473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 entries_ptr),
474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&RunReadDirectoryCallback,
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback,
476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&entries)));
477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
479b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::RefreshEntryOnUIThread(
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceEntry& in_entry,
481a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryWithFilePathCallback& callback) {
482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
485c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::FilePath* file_path = new base::FilePath;
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry(new ResourceEntry);
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResourceEntry* entry_ptr = entry.get();
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&ResourceMetadata::RefreshEntry,
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 in_entry,
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 file_path,
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 entry_ptr),
496a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      base::Bind(&RunGetResourceEntryWithFilePathCallback,
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 callback,
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Owned(file_path),
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Passed(&entry)));
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::RefreshEntry(const ResourceEntry& entry,
503b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                         base::FilePath* out_file_path,
504b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                         ResourceEntry* out_entry) {
505b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
506b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
507b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
508b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
509b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
510b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> old_entry =
511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      storage_->GetEntry(entry.resource_id());
512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!old_entry)
513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
515b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (old_entry->parent_resource_id().empty() ||  // Rejct root.
516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      old_entry->file_info().is_directory() !=  // Reject incompatible input.
517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      entry.file_info().is_directory())
518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_INVALID_OPERATION;
519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Update data.
521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> new_parent =
522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      GetDirectory(entry.parent_resource_id());
523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!new_parent)
525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Remove from the old parent and add it to the new parent with the new data.
528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!PutEntryUnderDirectory(CreateEntryWithProperBaseName(entry)))
529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return FILE_ERROR_FAILED;
530b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
531b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (out_file_path)
532b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *out_file_path = GetFilePath(entry.resource_id());
533b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
534b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (out_entry) {
535b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Note that base_name is not the same for the new entry and entry.
536b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    scoped_ptr<ResourceEntry> result_entry =
537b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        storage_->GetEntry(entry.resource_id());
538b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    DCHECK(result_entry);
539b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    *out_entry = *result_entry;
540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
541b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return FILE_ERROR_OK;
542b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
543b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
544b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::RefreshDirectoryOnUIThread(
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const DirectoryFetchInfo& directory_fetch_info,
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceEntryMap& entry_map,
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const FileMoveCallback& callback) {
548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
549c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
551b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PostFileMoveTask(blocking_task_runner_,
552b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   base::Bind(&ResourceMetadata::RefreshDirectory,
553b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              base::Unretained(this),
554b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              directory_fetch_info,
555b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                              entry_map),
556b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   callback);
557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
559b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void ResourceMetadata::GetChildDirectoriesOnUIThread(
560c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& resource_id,
561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const GetChildDirectoriesCallback& changed_dirs_callback) {
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!changed_dirs_callback.is_null());
564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::PostTaskAndReplyWithResult(
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      blocking_task_runner_,
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      FROM_HERE,
567b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(&ResourceMetadata::GetChildDirectories,
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 base::Unretained(this),
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 resource_id),
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&RunGetChildDirectoriesCallbackWithResult,
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 changed_dirs_callback));
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)scoped_ptr<std::set<base::FilePath> > ResourceMetadata::GetChildDirectories(
575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& resource_id) {
576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
577c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<std::set<base::FilePath> > changed_directories(
579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      new std::set<base::FilePath>);
580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = storage_->GetEntry(resource_id);
581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (entry && entry->file_info().is_directory())
582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    GetDescendantDirectoryPaths(resource_id, changed_directories.get());
583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return changed_directories.Pass();
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
587a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)scoped_ptr<ResourceMetadata::Iterator> ResourceMetadata::GetIterator() {
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
589b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
590a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return storage_->GetIterator();
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
593b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)base::FilePath ResourceMetadata::GetFilePath(
594b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& resource_id) {
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  base::FilePath path;
598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = storage_->GetEntry(resource_id);
599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (entry) {
600b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!entry->parent_resource_id().empty())
601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      path = GetFilePath(entry->parent_resource_id());
602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    path = path.Append(base::FilePath::FromUTF8Unsafe(entry->base_name()));
603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return path;
605c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
606c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
607b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::MoveEntryToDirectory(
608c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& file_path,
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& directory_path,
610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath* out_file_path) {
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
612c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!directory_path.empty());
613c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!file_path.empty());
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = FindEntryByPathSync(file_path);
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> destination = FindEntryByPathSync(directory_path);
620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!entry || !destination)
621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!destination->file_info().is_directory())
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_A_DIRECTORY;
624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->set_parent_resource_id(destination->resource_id());
626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
627b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return RefreshEntry(*entry, out_file_path, NULL);
628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::RenameEntry(
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& file_path,
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& new_name,
633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath* out_file_path) {
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!file_path.empty());
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!new_name.empty());
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DVLOG(1) << "RenameEntry " << file_path.value() << " to " << new_name;
639c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
640c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
641c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
642c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
643c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = FindEntryByPathSync(file_path);
644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!entry)
645c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
646c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
647c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (base::FilePath::FromUTF8Unsafe(new_name) == file_path.BaseName())
648c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_EXISTS;
649c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  entry->set_title(new_name);
651b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return RefreshEntry(*entry, out_file_path, NULL);
652c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
653c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
654c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<ResourceEntry> ResourceMetadata::FindEntryByPathSync(
655c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& file_path) {
656c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
657c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
658c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Start from the root.
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry =
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      storage_->GetEntry(util::kDriveGrandRootSpecialResourceId);
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(entry);
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(entry->parent_resource_id().empty());
663c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Check the first component.
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<base::FilePath::StringType> components;
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  file_path.GetComponents(&components);
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (components.empty() ||
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::FilePath(components[0]).AsUTF8Unsafe() != entry->base_name())
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return scoped_ptr<ResourceEntry>();
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Iterate over the remaining components.
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 1; i < components.size(); ++i) {
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string component = base::FilePath(components[i]).AsUTF8Unsafe();
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string resource_id = storage_->GetChild(entry->resource_id(),
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                       component);
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (resource_id.empty())
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return scoped_ptr<ResourceEntry>();
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entry = storage_->GetEntry(resource_id);
680c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(entry);
681c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK_EQ(entry->base_name(), component);
682c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return entry.Pass();
684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
686b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::ReadDirectoryByPath(
687c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& path,
688c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ResourceEntryVector* out_entries) {
689c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
690c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(out_entries);
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
692c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = FindEntryByPathSync(path);
693c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!entry)
694c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
695c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
696c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!entry->file_info().is_directory())
697c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_A_DIRECTORY;
698c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
699c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DirectoryChildrenToProtoVector(entry->resource_id())->swap(*out_entries);
700c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return FILE_ERROR_OK;
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
703a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ResourceMetadata::GetResourceEntryPairByPathsOnUIThread(
704c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& first_path,
705c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& second_path,
706a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryPairCallback& callback) {
707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Get the first entry.
711a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  GetResourceEntryByPathOnUIThread(
712c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      first_path,
713b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(
714a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          &ResourceMetadata::GetResourceEntryPairByPathsOnUIThreadAfterGetFirst,
715b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr(),
716b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          first_path,
717b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          second_path,
718b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          callback));
719c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
721b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)FileError ResourceMetadata::RefreshDirectory(
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const DirectoryFetchInfo& directory_fetch_info,
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceEntryMap& entry_map,
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath* out_file_path) {
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!directory_fetch_info.empty());
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NO_SPACE;
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> directory = storage_->GetEntry(
732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      directory_fetch_info.resource_id());
733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!directory)
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_FOUND;
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!directory->file_info().is_directory())
738c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return FILE_ERROR_NOT_A_DIRECTORY;
739c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
740c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  directory->mutable_directory_specific_info()->set_changestamp(
741c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      directory_fetch_info.changestamp());
742c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  storage_->PutEntry(*directory);
743c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
744c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // First, go through the entry map. We'll handle existing entries and new
745c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // entries in the loop. We'll process deleted entries afterwards.
746c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (ResourceEntryMap::const_iterator it = entry_map.begin();
747c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       it != entry_map.end(); ++it) {
748c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
749c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return FILE_ERROR_NO_SPACE;
750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
751c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceEntry& entry = it->second;
752c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Skip if the parent resource ID does not match. This is needed to
753c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // handle entries with multiple parents. For such entries, the first
754c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // parent is picked and other parents are ignored, hence some entries may
755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // have a parent resource ID which does not match the target directory's.
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    //
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // TODO(satorux): Move the filtering logic to somewhere more appropriate.
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // crbug.com/193525.
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (entry.parent_resource_id() !=
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        directory_fetch_info.resource_id()) {
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DVLOG(1) << "Wrong-parent entry rejected: " << entry.resource_id();
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!PutEntryUnderDirectory(CreateEntryWithProperBaseName(entry)))
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return FILE_ERROR_FAILED;
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Go through the existing entries and remove deleted entries.
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntryVector> entries =
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DirectoryChildrenToProtoVector(directory->resource_id());
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < entries->size(); ++i) {
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!EnoughDiskSpaceIsAvailableForDBOperation(data_directory_path_))
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return FILE_ERROR_NO_SPACE;
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceEntry& entry = entries->at(i);
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (entry_map.count(entry.resource_id()) == 0) {
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!RemoveEntryRecursively(entry.resource_id()))
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return FILE_ERROR_FAILED;
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (out_file_path)
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *out_file_path = GetFilePath(directory->resource_id());
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return FILE_ERROR_OK;
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
789c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<ResourceEntry> ResourceMetadata::GetDirectory(
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& resource_id) {
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!resource_id.empty());
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = storage_->GetEntry(resource_id);
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return entry && entry->file_info().is_directory() ?
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      entry.Pass() : scoped_ptr<ResourceEntry>();
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ResourceMetadata::GetDescendantDirectoryPaths(
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& directory_resource_id,
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::set<base::FilePath>* child_directories) {
802c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
803c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
804c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<std::string> children;
805c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  storage_->GetChildren(directory_resource_id, &children);
806c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < children.size(); ++i) {
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ResourceEntry> entry = storage_->GetEntry(children[i]);
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(entry);
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (entry->file_info().is_directory()) {
810c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      child_directories->insert(GetFilePath(entry->resource_id()));
811c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetDescendantDirectoryPaths(entry->resource_id(), child_directories);
812c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
813c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
814c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
815c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
816a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ResourceMetadata::GetResourceEntryPairByPathsOnUIThreadAfterGetFirst(
817c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& first_path,
818c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& second_path,
819a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryPairCallback& callback,
820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileError error,
821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ResourceEntry> entry) {
822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
824c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
825c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<EntryInfoPairResult> result(new EntryInfoPairResult);
826c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->first.path = first_path;
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->first.error = error;
828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->first.entry = entry.Pass();
829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the first one is not found, don't continue.
831c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (error != FILE_ERROR_OK) {
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    callback.Run(result.Pass());
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
836c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Get the second entry.
837a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  GetResourceEntryByPathOnUIThread(
838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      second_path,
839b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      base::Bind(
840a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          &ResourceMetadata::
841a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)          GetResourceEntryPairByPathsOnUIThreadAfterGetSecond,
842b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          weak_ptr_factory_.GetWeakPtr(),
843b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          second_path,
844b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          callback,
845b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)          base::Passed(&result)));
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
848a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void ResourceMetadata::GetResourceEntryPairByPathsOnUIThreadAfterGetSecond(
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::FilePath& second_path,
850a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GetResourceEntryPairCallback& callback,
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<EntryInfoPairResult> result,
852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    FileError error,
853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ResourceEntry> entry) {
854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!callback.is_null());
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(result.get());
857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->second.path = second_path;
859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->second.error = error;
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  result->second.entry = entry.Pass();
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  callback.Run(result.Pass());
863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadata::PutEntryUnderDirectory(
866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const ResourceEntry& entry) {
867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ResourceEntry updated_entry(entry);
870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The entry name may have been changed due to prior name de-duplication.
872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We need to first restore the file name based on the title before going
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // through name de-duplication again when it is added to another directory.
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SetBaseNameFromTitle(&updated_entry);
875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Do file name de-duplication - Keep changing |entry|'s name until there is
877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // no other entry with the same name under the parent.
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int modifier = 1;
879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string new_base_name = updated_entry.base_name();
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (true) {
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string existing_entry_id =
882c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        storage_->GetChild(entry.parent_resource_id(), new_base_name);
883c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (existing_entry_id.empty() || existing_entry_id == entry.resource_id())
884c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      break;
885c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::FilePath new_path =
887c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::FilePath::FromUTF8Unsafe(updated_entry.base_name());
888c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    new_path =
889c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        new_path.InsertBeforeExtension(base::StringPrintf(" (%d)", ++modifier));
890c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    new_base_name = new_path.AsUTF8Unsafe();
891c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
892c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  updated_entry.set_base_name(new_base_name);
893c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
894c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add the entry to resource map.
895c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return storage_->PutEntry(updated_entry);
896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
897c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
898c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ResourceMetadata::RemoveEntryRecursively(
899c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& resource_id) {
900c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
901c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
902c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntry> entry = storage_->GetEntry(resource_id);
903c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(entry);
904c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
905c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (entry->file_info().is_directory()) {
906c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<std::string> children;
907c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    storage_->GetChildren(resource_id, &children);
908c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (size_t i = 0; i < children.size(); ++i) {
909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (!RemoveEntryRecursively(children[i]))
910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return false;
911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return storage_->RemoveEntry(resource_id);
914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<ResourceEntryVector>
917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ResourceMetadata::DirectoryChildrenToProtoVector(
918c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& directory_resource_id) {
919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread());
920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
921c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ResourceEntryVector> entries(new ResourceEntryVector);
922c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<std::string> children;
923c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  storage_->GetChildren(directory_resource_id, &children);
924c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (size_t i = 0; i < children.size(); ++i) {
925c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    scoped_ptr<ResourceEntry> child = storage_->GetEntry(children[i]);
926c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(child);
927c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    entries->push_back(*child);
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return entries.Pass();
930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace internal
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace drive
934