1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_CHROMEOS_DRIVE_RESOURCE_METADATA_H_ 6 #define CHROME_BROWSER_CHROMEOS_DRIVE_RESOURCE_METADATA_H_ 7 8 #include <map> 9 #include <set> 10 #include <string> 11 #include <vector> 12 13 #include "base/callback_forward.h" 14 #include "base/files/file_path.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/weak_ptr.h" 17 #include "base/time/time.h" 18 #include "chrome/browser/chromeos/drive/file_errors.h" 19 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h" 20 21 namespace base { 22 class SequencedTaskRunner; 23 } 24 25 namespace drive { 26 27 class ResourceEntry; 28 29 typedef std::vector<ResourceEntry> ResourceEntryVector; 30 typedef std::map<std::string /* resource_id */, ResourceEntry> 31 ResourceEntryMap; 32 33 // Holds information needed to fetch contents of a directory. 34 // This object is copyable. 35 class DirectoryFetchInfo { 36 public: 37 DirectoryFetchInfo() : changestamp_(0) {} 38 DirectoryFetchInfo(const std::string& resource_id, 39 int64 changestamp) 40 : resource_id_(resource_id), 41 changestamp_(changestamp) { 42 } 43 44 // Returns true if the object is empty. 45 bool empty() const { return resource_id_.empty(); } 46 47 // Resource ID of the directory. 48 const std::string& resource_id() const { return resource_id_; } 49 50 // Changestamp of the directory. The changestamp is used to determine if 51 // the directory contents should be fetched. 52 int64 changestamp() const { return changestamp_; } 53 54 // Returns a string representation of this object. 55 std::string ToString() const; 56 57 private: 58 const std::string resource_id_; 59 const int64 changestamp_; 60 }; 61 62 // Callback similar to FileOperationCallback but with a given |file_path|. 63 // Used for operations that change a file path like moving files. 64 typedef base::Callback<void(FileError error, 65 const base::FilePath& file_path)> 66 FileMoveCallback; 67 68 // Used to get a resource entry from the file system. 69 // If |error| is not FILE_ERROR_OK, |entry_info| is set to NULL. 70 typedef base::Callback<void(FileError error, 71 scoped_ptr<ResourceEntry> entry)> 72 GetResourceEntryCallback; 73 74 typedef base::Callback<void(FileError error, 75 scoped_ptr<ResourceEntryVector> entries)> 76 ReadDirectoryCallback; 77 78 typedef base::Callback<void(int64)> GetChangestampCallback; 79 80 // This is a part of EntryInfoPairResult. 81 struct EntryInfoResult { 82 EntryInfoResult(); 83 ~EntryInfoResult(); 84 85 base::FilePath path; 86 FileError error; 87 scoped_ptr<ResourceEntry> entry; 88 }; 89 90 // The result of GetResourceEntryPairCallback(). Used to get a pair of entries 91 // in one function call. 92 struct EntryInfoPairResult { 93 EntryInfoPairResult(); 94 ~EntryInfoPairResult(); 95 96 EntryInfoResult first; 97 EntryInfoResult second; // Only filled if the first entry is found. 98 }; 99 100 // Used to receive the result from GetResourceEntryPairCallback(). 101 typedef base::Callback<void(scoped_ptr<EntryInfoPairResult> pair_result)> 102 GetResourceEntryPairCallback; 103 104 typedef base::Callback<void(const ResourceEntry& entry)> IterateCallback; 105 106 namespace internal { 107 108 // Storage for Drive Metadata. 109 // All methods must be run with |blocking_task_runner| unless otherwise noted. 110 class ResourceMetadata { 111 public: 112 typedef ResourceMetadataStorage::Iterator Iterator; 113 114 ResourceMetadata( 115 ResourceMetadataStorage* storage, 116 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner); 117 118 // Initializes this object. 119 // This method should be called before any other methods. 120 FileError Initialize() WARN_UNUSED_RESULT; 121 122 // Destroys this object. This method posts a task to |blocking_task_runner_| 123 // to safely delete this object. 124 // Must be called on the UI thread. 125 void Destroy(); 126 127 // Resets this object. 128 // Must be called on the UI thread. 129 void ResetOnUIThread(const FileOperationCallback& callback); 130 131 // Synchronous version of ResetOnUIThread. 132 FileError Reset(); 133 134 // Largest change timestamp that was the source of content for the current 135 // state of the root directory. 136 // Must be called on the UI thread. 137 void GetLargestChangestampOnUIThread(const GetChangestampCallback& callback); 138 void SetLargestChangestampOnUIThread(int64 value, 139 const FileOperationCallback& callback); 140 141 // Synchronous version of GetLargestChangestampOnUIThread. 142 int64 GetLargestChangestamp(); 143 144 // Synchronous version of SetLargestChangestampOnUIThread. 145 FileError SetLargestChangestamp(int64 value); 146 147 // Runs AddEntry() on blocking pool. Upon completion, the |callback| will be 148 // called with the new file path. 149 // |callback| must not be null. 150 // Must be called on the UI thread. 151 void AddEntryOnUIThread(const ResourceEntry& entry, 152 const FileMoveCallback& callback); 153 154 // Adds |entry| to the metadata tree based on its parent_resource_id 155 // synchronously. 156 FileError AddEntry(const ResourceEntry& entry); 157 158 // Moves entry specified by |file_path| to the directory specified by 159 // |directory_path| and calls the callback asynchronously. Removes the entry 160 // from the previous parent. |callback| must not be null. 161 // Must be called on the UI thread. 162 void MoveEntryToDirectoryOnUIThread(const base::FilePath& file_path, 163 const base::FilePath& directory_path, 164 const FileMoveCallback& callback); 165 166 // Renames entry specified by |file_path| with the new name |new_name| and 167 // calls |callback| asynchronously. |callback| must not be null. 168 // Must be called on the UI thread. 169 void RenameEntryOnUIThread(const base::FilePath& file_path, 170 const std::string& new_name, 171 const FileMoveCallback& callback); 172 173 // Removes entry with |resource_id| from its parent. 174 FileError RemoveEntry(const std::string& resource_id); 175 176 // Finds an entry (a file or a directory) by |resource_id|. 177 // |callback| must not be null. 178 // Must be called on the UI thread. 179 void GetResourceEntryByIdOnUIThread(const std::string& resource_id, 180 const GetResourceEntryCallback& callback); 181 182 // Synchronous version of GetResourceEntryByIdOnUIThread(). 183 FileError GetResourceEntryById(const std::string& resource_id, 184 ResourceEntry* out_entry); 185 186 // Finds an entry (a file or a directory) by |file_path|. 187 // |callback| must not be null. 188 // Must be called on the UI thread. 189 void GetResourceEntryByPathOnUIThread( 190 const base::FilePath& file_path, 191 const GetResourceEntryCallback& callback); 192 193 // Synchronous version of GetResourceEntryByPathOnUIThread(). 194 FileError GetResourceEntryByPath(const base::FilePath& file_path, 195 ResourceEntry* out_entry); 196 197 // Finds and reads a directory by |file_path|. 198 // |callback| must not be null. 199 // Must be called on the UI thread. 200 void ReadDirectoryByPathOnUIThread(const base::FilePath& file_path, 201 const ReadDirectoryCallback& callback); 202 203 // Synchronous version of ReadDirectoryByPathOnUIThread(). 204 FileError ReadDirectoryByPath(const base::FilePath& file_path, 205 ResourceEntryVector* out_entries); 206 207 // Similar to GetResourceEntryByPath() but this function finds a pair of 208 // entries by |first_path| and |second_path|. If the entry for 209 // |first_path| is not found, this function does not try to get the 210 // entry of |second_path|. |callback| must not be null. 211 // Must be called on the UI thread. 212 void GetResourceEntryPairByPathsOnUIThread( 213 const base::FilePath& first_path, 214 const base::FilePath& second_path, 215 const GetResourceEntryPairCallback& callback); 216 217 // Replaces an existing entry whose ID is |entry.resource_id()| with |entry|. 218 FileError RefreshEntry(const ResourceEntry& entry); 219 220 // Removes all child files of the directory pointed by 221 // |directory_fetch_info| and replaces them with 222 // |entry_map|. The changestamp of the directory will be updated per 223 // |directory_fetch_info|. |callback| is called with the directory path. 224 // |callback| must not be null. 225 // Must be called on the UI thread. 226 void RefreshDirectoryOnUIThread( 227 const DirectoryFetchInfo& directory_fetch_info, 228 const ResourceEntryMap& entry_map, 229 const FileMoveCallback& callback); 230 231 // Recursively get child directories of entry pointed to by |resource_id|. 232 void GetChildDirectories(const std::string& resource_id, 233 std::set<base::FilePath>* child_directories); 234 235 // Returns the resource id of the resource named |base_name| directly under 236 // the directory with |parent_resource_id|. 237 // If not found, empty string will be returned. 238 std::string GetChildResourceId( 239 const std::string& parent_resource_id, const std::string& base_name); 240 241 // Returns an object to iterate over entries. 242 scoped_ptr<Iterator> GetIterator(); 243 244 // Returns virtual file path of the entry. 245 base::FilePath GetFilePath(const std::string& resource_id); 246 247 private: 248 // Note: Use Destroy() to delete this object. 249 ~ResourceMetadata(); 250 251 // Sets up entries which should be present by default. 252 bool SetUpDefaultEntries(); 253 254 // Used to implement Destroy(). 255 void DestroyOnBlockingPool(); 256 257 // Used to implement MoveEntryToDirectoryOnUIThread(). 258 FileError MoveEntryToDirectory(const base::FilePath& file_path, 259 const base::FilePath& directory_path, 260 base::FilePath* out_file_path); 261 262 // Used to implement RenameEntryOnUIThread(). 263 FileError RenameEntry(const base::FilePath& file_path, 264 const std::string& new_name, 265 base::FilePath* out_file_path); 266 267 // Used to implement RefreshDirectoryOnUIThread(). 268 FileError RefreshDirectory(const DirectoryFetchInfo& directory_fetch_info, 269 const ResourceEntryMap& entry_map, 270 base::FilePath* out_file_path); 271 272 // Continues with GetResourceEntryPairByPathsOnUIThread after the first 273 // entry has been asynchronously fetched. This fetches the second entry 274 // only if the first was found. 275 void GetResourceEntryPairByPathsOnUIThreadAfterGetFirst( 276 const base::FilePath& first_path, 277 const base::FilePath& second_path, 278 const GetResourceEntryPairCallback& callback, 279 FileError error, 280 scoped_ptr<ResourceEntry> entry); 281 282 // Continues with GetResourceEntryPairByPathsOnUIThread after the second 283 // entry has been asynchronously fetched. 284 void GetResourceEntryPairByPathsOnUIThreadAfterGetSecond( 285 const base::FilePath& second_path, 286 const GetResourceEntryPairCallback& callback, 287 scoped_ptr<EntryInfoPairResult> result, 288 FileError error, 289 scoped_ptr<ResourceEntry> entry); 290 291 // Searches for |file_path| synchronously. 292 bool FindEntryByPathSync(const base::FilePath& file_path, 293 ResourceEntry* out_entry); 294 295 // Puts an entry under its parent directory. Removes the child from the old 296 // parent if there is. This method will also do name de-duplication to ensure 297 // that the exposed presentation path does not have naming conflicts. Two 298 // files with the same name "Foo" will be renames to "Foo (1)" and "Foo (2)". 299 bool PutEntryUnderDirectory(const ResourceEntry& entry); 300 301 // Removes the entry and its descendants. 302 bool RemoveEntryRecursively(const std::string& resource_id); 303 304 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; 305 306 ResourceMetadataStorage* storage_; 307 308 // This should remain the last member so it'll be destroyed first and 309 // invalidate its weak pointers before other members are destroyed. 310 base::WeakPtrFactory<ResourceMetadata> weak_ptr_factory_; 311 312 DISALLOW_COPY_AND_ASSIGN(ResourceMetadata); 313 }; 314 315 } // namespace internal 316 } // namespace drive 317 318 #endif // CHROME_BROWSER_CHROMEOS_DRIVE_RESOURCE_METADATA_H_ 319