test_file_system_backend.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "content/public/test/test_file_system_backend.h" 6 7#include <set> 8#include <string> 9#include <vector> 10 11#include "base/files/file.h" 12#include "base/files/file_util.h" 13#include "base/memory/weak_ptr.h" 14#include "base/observer_list.h" 15#include "base/sequenced_task_runner.h" 16#include "base/thread_task_runner_handle.h" 17#include "storage/browser/blob/file_stream_reader.h" 18#include "storage/browser/fileapi/copy_or_move_file_validator.h" 19#include "storage/browser/fileapi/file_observers.h" 20#include "storage/browser/fileapi/file_system_operation.h" 21#include "storage/browser/fileapi/file_system_operation_context.h" 22#include "storage/browser/fileapi/file_system_quota_util.h" 23#include "storage/browser/fileapi/local_file_util.h" 24#include "storage/browser/fileapi/native_file_util.h" 25#include "storage/browser/fileapi/quota/quota_reservation.h" 26#include "storage/browser/fileapi/sandbox_file_stream_writer.h" 27#include "storage/browser/fileapi/watcher_manager.h" 28#include "storage/browser/quota/quota_manager.h" 29#include "storage/common/fileapi/file_system_util.h" 30 31using storage::FileSystemContext; 32using storage::FileSystemOperation; 33using storage::FileSystemOperationContext; 34using storage::FileSystemURL; 35 36namespace content { 37 38namespace { 39 40// Stub implementation of storage::LocalFileUtil. 41class TestFileUtil : public storage::LocalFileUtil { 42 public: 43 explicit TestFileUtil(const base::FilePath& base_path) 44 : base_path_(base_path) {} 45 virtual ~TestFileUtil() {} 46 47 // LocalFileUtil overrides. 48 virtual base::File::Error GetLocalFilePath( 49 FileSystemOperationContext* context, 50 const FileSystemURL& file_system_url, 51 base::FilePath* local_file_path) OVERRIDE { 52 *local_file_path = base_path_.Append(file_system_url.path()); 53 return base::File::FILE_OK; 54 } 55 56 private: 57 base::FilePath base_path_; 58}; 59 60// Stub implementation of storage::WatcherManager. Emits a fake notification 61// after a directory watcher is set successfully. 62class TestWatcherManager : public storage::WatcherManager { 63 public: 64 TestWatcherManager() : weak_ptr_factory_(this) {} 65 virtual ~TestWatcherManager() {} 66 67 // storage::WatcherManager overrides. 68 virtual void AddObserver(Observer* observer) OVERRIDE { 69 observers_.AddObserver(observer); 70 } 71 72 virtual void RemoveObserver(Observer* observer) OVERRIDE { 73 observers_.RemoveObserver(observer); 74 } 75 76 virtual bool HasObserver(Observer* observer) const OVERRIDE { 77 return observers_.HasObserver(observer); 78 } 79 80 virtual void WatchDirectory(const storage::FileSystemURL& url, 81 bool recursive, 82 const StatusCallback& callback) OVERRIDE { 83 if (recursive) { 84 base::ThreadTaskRunnerHandle::Get()->PostTask( 85 FROM_HERE, 86 base::Bind(callback, base::File::FILE_ERROR_INVALID_OPERATION)); 87 return; 88 } 89 90 const GURL gurl = url.ToGURL(); 91 if (watched_urls_.find(gurl) != watched_urls_.end()) { 92 base::ThreadTaskRunnerHandle::Get()->PostTask( 93 FROM_HERE, base::Bind(callback, base::File::FILE_ERROR_EXISTS)); 94 return; 95 } 96 97 watched_urls_.insert(gurl); 98 base::ThreadTaskRunnerHandle::Get()->PostTask( 99 FROM_HERE, base::Bind(callback, base::File::FILE_OK)); 100 101 // Send a fake changed notification. 102 base::ThreadTaskRunnerHandle::Get()->PostTask( 103 FROM_HERE, 104 base::Bind(&TestWatcherManager::SendFakeChangeNotification, 105 weak_ptr_factory_.GetWeakPtr(), 106 url)); 107 108 // Send a fake removed notification. 109 base::ThreadTaskRunnerHandle::Get()->PostTask( 110 FROM_HERE, 111 base::Bind(&TestWatcherManager::SendFakeRemoveNotification, 112 weak_ptr_factory_.GetWeakPtr(), 113 url)); 114 } 115 116 virtual void UnwatchEntry(const storage::FileSystemURL& url, 117 const StatusCallback& callback) OVERRIDE { 118 const GURL gurl = url.ToGURL(); 119 if (watched_urls_.find(gurl) == watched_urls_.end()) { 120 base::ThreadTaskRunnerHandle::Get()->PostTask( 121 FROM_HERE, base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND)); 122 return; 123 } 124 125 watched_urls_.erase(gurl); 126 base::ThreadTaskRunnerHandle::Get()->PostTask( 127 FROM_HERE, base::Bind(callback, base::File::FILE_OK)); 128 } 129 130 private: 131 // Sends a fake notification to each observer about a changed entry 132 // represented by |url|, as long as it is still being watched. 133 void SendFakeChangeNotification(const storage::FileSystemURL& url) { 134 if (watched_urls_.find(url.ToGURL()) == watched_urls_.end()) 135 return; 136 137 FOR_EACH_OBSERVER(Observer, observers_, OnEntryChanged(url)); 138 } 139 140 // Sends a fake notification to each observer about a removed entry 141 // represented by |url|, as long as it is still being watched. 142 void SendFakeRemoveNotification(const storage::FileSystemURL& url) { 143 if (watched_urls_.find(url.ToGURL()) == watched_urls_.end()) 144 return; 145 146 FOR_EACH_OBSERVER(Observer, observers_, OnEntryRemoved(url)); 147 } 148 149 ObserverList<Observer> observers_; 150 std::set<GURL> watched_urls_; 151 152 base::WeakPtrFactory<TestWatcherManager> weak_ptr_factory_; 153}; 154 155} // namespace 156 157// This only supports single origin. 158class TestFileSystemBackend::QuotaUtil : public storage::FileSystemQuotaUtil, 159 public storage::FileUpdateObserver { 160 public: 161 QuotaUtil() : usage_(0) {} 162 virtual ~QuotaUtil() {} 163 164 // FileSystemQuotaUtil overrides. 165 virtual base::File::Error DeleteOriginDataOnFileTaskRunner( 166 FileSystemContext* context, 167 storage::QuotaManagerProxy* proxy, 168 const GURL& origin_url, 169 storage::FileSystemType type) OVERRIDE { 170 NOTREACHED(); 171 return base::File::FILE_OK; 172 } 173 174 virtual scoped_refptr<storage::QuotaReservation> 175 CreateQuotaReservationOnFileTaskRunner( 176 const GURL& origin_url, 177 storage::FileSystemType type) OVERRIDE { 178 NOTREACHED(); 179 return scoped_refptr<storage::QuotaReservation>(); 180 } 181 182 virtual void GetOriginsForTypeOnFileTaskRunner( 183 storage::FileSystemType type, 184 std::set<GURL>* origins) OVERRIDE { 185 NOTREACHED(); 186 } 187 188 virtual void GetOriginsForHostOnFileTaskRunner( 189 storage::FileSystemType type, 190 const std::string& host, 191 std::set<GURL>* origins) OVERRIDE { 192 NOTREACHED(); 193 } 194 195 virtual int64 GetOriginUsageOnFileTaskRunner( 196 FileSystemContext* context, 197 const GURL& origin_url, 198 storage::FileSystemType type) OVERRIDE { 199 return usage_; 200 } 201 202 // FileUpdateObserver overrides. 203 virtual void OnStartUpdate(const FileSystemURL& url) OVERRIDE {} 204 virtual void OnUpdate(const FileSystemURL& url, int64 delta) OVERRIDE { 205 usage_ += delta; 206 } 207 virtual void OnEndUpdate(const FileSystemURL& url) OVERRIDE {} 208 209 private: 210 int64 usage_; 211 DISALLOW_COPY_AND_ASSIGN(QuotaUtil); 212}; 213 214TestFileSystemBackend::TestFileSystemBackend( 215 base::SequencedTaskRunner* task_runner, 216 const base::FilePath& base_path) 217 : base_path_(base_path), 218 task_runner_(task_runner), 219 file_util_( 220 new storage::AsyncFileUtilAdapter(new TestFileUtil(base_path))), 221 watcher_manager_(new TestWatcherManager()), 222 quota_util_(new QuotaUtil), 223 require_copy_or_move_validator_(false) { 224 update_observers_ = 225 update_observers_.AddObserver(quota_util_.get(), task_runner_.get()); 226} 227 228TestFileSystemBackend::~TestFileSystemBackend() { 229} 230 231bool TestFileSystemBackend::CanHandleType(storage::FileSystemType type) const { 232 return (type == storage::kFileSystemTypeTest); 233} 234 235void TestFileSystemBackend::Initialize(FileSystemContext* context) { 236} 237 238void TestFileSystemBackend::ResolveURL(const FileSystemURL& url, 239 storage::OpenFileSystemMode mode, 240 const OpenFileSystemCallback& callback) { 241 callback.Run(GetFileSystemRootURI(url.origin(), url.type()), 242 GetFileSystemName(url.origin(), url.type()), 243 base::File::FILE_OK); 244} 245 246storage::AsyncFileUtil* TestFileSystemBackend::GetAsyncFileUtil( 247 storage::FileSystemType type) { 248 return file_util_.get(); 249} 250 251storage::WatcherManager* TestFileSystemBackend::GetWatcherManager( 252 storage::FileSystemType type) { 253 return watcher_manager_.get(); 254} 255 256storage::CopyOrMoveFileValidatorFactory* 257TestFileSystemBackend::GetCopyOrMoveFileValidatorFactory( 258 storage::FileSystemType type, 259 base::File::Error* error_code) { 260 DCHECK(error_code); 261 *error_code = base::File::FILE_OK; 262 if (require_copy_or_move_validator_) { 263 if (!copy_or_move_file_validator_factory_) 264 *error_code = base::File::FILE_ERROR_SECURITY; 265 return copy_or_move_file_validator_factory_.get(); 266 } 267 return NULL; 268} 269 270void TestFileSystemBackend::InitializeCopyOrMoveFileValidatorFactory( 271 scoped_ptr<storage::CopyOrMoveFileValidatorFactory> factory) { 272 if (!copy_or_move_file_validator_factory_) 273 copy_or_move_file_validator_factory_ = factory.Pass(); 274} 275 276FileSystemOperation* TestFileSystemBackend::CreateFileSystemOperation( 277 const FileSystemURL& url, 278 FileSystemContext* context, 279 base::File::Error* error_code) const { 280 scoped_ptr<FileSystemOperationContext> operation_context( 281 new FileSystemOperationContext(context)); 282 operation_context->set_update_observers(*GetUpdateObservers(url.type())); 283 operation_context->set_change_observers(*GetChangeObservers(url.type())); 284 return FileSystemOperation::Create(url, context, operation_context.Pass()); 285} 286 287bool TestFileSystemBackend::SupportsStreaming( 288 const storage::FileSystemURL& url) const { 289 return false; 290} 291 292bool TestFileSystemBackend::HasInplaceCopyImplementation( 293 storage::FileSystemType type) const { 294 return true; 295} 296 297scoped_ptr<storage::FileStreamReader> 298TestFileSystemBackend::CreateFileStreamReader( 299 const FileSystemURL& url, 300 int64 offset, 301 int64 max_bytes_to_read, 302 const base::Time& expected_modification_time, 303 FileSystemContext* context) const { 304 return scoped_ptr<storage::FileStreamReader>( 305 storage::FileStreamReader::CreateForFileSystemFile( 306 context, url, offset, expected_modification_time)); 307} 308 309scoped_ptr<storage::FileStreamWriter> 310TestFileSystemBackend::CreateFileStreamWriter( 311 const FileSystemURL& url, 312 int64 offset, 313 FileSystemContext* context) const { 314 return scoped_ptr<storage::FileStreamWriter>( 315 new storage::SandboxFileStreamWriter( 316 context, url, offset, *GetUpdateObservers(url.type()))); 317} 318 319storage::FileSystemQuotaUtil* TestFileSystemBackend::GetQuotaUtil() { 320 return quota_util_.get(); 321} 322 323const storage::UpdateObserverList* TestFileSystemBackend::GetUpdateObservers( 324 storage::FileSystemType type) const { 325 return &update_observers_; 326} 327 328const storage::ChangeObserverList* TestFileSystemBackend::GetChangeObservers( 329 storage::FileSystemType type) const { 330 return &change_observers_; 331} 332 333const storage::AccessObserverList* TestFileSystemBackend::GetAccessObservers( 334 storage::FileSystemType type) const { 335 return NULL; 336} 337 338void TestFileSystemBackend::AddFileChangeObserver( 339 storage::FileChangeObserver* observer) { 340 change_observers_ = 341 change_observers_.AddObserver(observer, task_runner_.get()); 342} 343 344} // namespace content 345