diff options
author | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-09 17:42:10 +0000 |
---|---|---|
committer | kinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-09 17:42:10 +0000 |
commit | c4e6f9ca783c3959ae4730376723a6f0064ce783 (patch) | |
tree | a23d35c4131d5785fea0627285ce35066005cc2c /webkit/fileapi | |
parent | 36e2f42527f6b556045f44a0782dea1a04465763 (diff) | |
download | chromium_src-c4e6f9ca783c3959ae4730376723a6f0064ce783.zip chromium_src-c4e6f9ca783c3959ae4730376723a6f0064ce783.tar.gz chromium_src-c4e6f9ca783c3959ae4730376723a6f0064ce783.tar.bz2 |
Add FileChangeObserver to track changes in local file system
BUG=146290,146317
TEST=LocalFileSystemOperationTest.*, ObfuscatedFileUtilTest.*
Review URL: https://chromiumcodereview.appspot.com/10909060
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155632 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/fileapi')
-rw-r--r-- | webkit/fileapi/file_observers.h | 19 | ||||
-rw-r--r-- | webkit/fileapi/file_system_operation_context.h | 6 | ||||
-rw-r--r-- | webkit/fileapi/local_file_system_operation.h | 8 | ||||
-rw-r--r-- | webkit/fileapi/local_file_system_operation_unittest.cc | 106 | ||||
-rw-r--r-- | webkit/fileapi/mock_file_change_observer.cc | 52 | ||||
-rw-r--r-- | webkit/fileapi/mock_file_change_observer.h | 103 | ||||
-rw-r--r-- | webkit/fileapi/obfuscated_file_util.cc | 45 | ||||
-rw-r--r-- | webkit/fileapi/obfuscated_file_util_unittest.cc | 70 | ||||
-rw-r--r-- | webkit/fileapi/task_runner_bound_observer_list.h | 2 |
9 files changed, 403 insertions, 8 deletions
diff --git a/webkit/fileapi/file_observers.h b/webkit/fileapi/file_observers.h index 2022b81..8b64161 100644 --- a/webkit/fileapi/file_observers.h +++ b/webkit/fileapi/file_observers.h @@ -46,6 +46,25 @@ class FILEAPI_EXPORT FileAccessObserver { virtual void OnAccess(const FileSystemURL& url) = 0; }; +// An abstract interface to observe file changes. +// Each method of this class is called once per file/directory is created, +// removed or modified. For recursive operations each method is called for +// each subdirectory/subfile. Currently ChangeObserver is only supported +// by the local sandbox file system. +class FILEAPI_EXPORT FileChangeObserver { + public: + virtual ~FileChangeObserver() {} + + virtual void OnCreateFile(const FileSystemURL& url) = 0; + virtual void OnCreateFileFrom(const FileSystemURL& url, + const FileSystemURL& src) = 0; + virtual void OnRemoveFile(const FileSystemURL& url) = 0; + virtual void OnModifyFile(const FileSystemURL& url) = 0; + + virtual void OnCreateDirectory(const FileSystemURL& url) = 0; + virtual void OnRemoveDirectory(const FileSystemURL& url) = 0; +}; + } // namespace fileapi #endif // WEBKIT_FILEAPI_FILE_OBSERVERS_H_ diff --git a/webkit/fileapi/file_system_operation_context.h b/webkit/fileapi/file_system_operation_context.h index f1dbda2..89b109c 100644 --- a/webkit/fileapi/file_system_operation_context.h +++ b/webkit/fileapi/file_system_operation_context.h @@ -65,6 +65,11 @@ class FILEAPI_EXPORT_PRIVATE FileSystemOperationContext { return media_path_filter_; } + void set_change_observers(const ChangeObserverList& list) { + change_observers_ = list; + } + ChangeObserverList* change_observers() { return &change_observers_; } + void set_access_observers(const AccessObserverList& list) { access_observers_ = list; } @@ -83,6 +88,7 @@ class FILEAPI_EXPORT_PRIVATE FileSystemOperationContext { MediaPathFilter* media_path_filter_; AccessObserverList access_observers_; + ChangeObserverList change_observers_; UpdateObserverList update_observers_; #if defined(SUPPORT_MEDIA_FILESYSTEM) diff --git a/webkit/fileapi/local_file_system_operation.h b/webkit/fileapi/local_file_system_operation.h index b005b64..10dd19d 100644 --- a/webkit/fileapi/local_file_system_operation.h +++ b/webkit/fileapi/local_file_system_operation.h @@ -115,8 +115,8 @@ class FILEAPI_EXPORT LocalFileSystemOperation friend class TestMountPointProvider; friend class chromeos::CrosMountPointProvider; - friend class FileSystemOperationTest; - friend class FileSystemOperationWriteTest; + friend class LocalFileSystemOperationTest; + friend class LocalFileSystemOperationWriteTest; friend class FileWriterDelegateTest; friend class FileSystemQuotaTest; friend class LocalFileSystemTestOriginHelper; @@ -129,6 +129,10 @@ class FILEAPI_EXPORT LocalFileSystemOperation return operation_context_->file_system_context(); } + FileSystemOperationContext* operation_context() const { + return operation_context_.get(); + } + // The unit tests that need to specify and control the lifetime of the // file_util on their own should call this before performing the actual // operation. If it is given it will not be overwritten by the class. diff --git a/webkit/fileapi/local_file_system_operation_unittest.cc b/webkit/fileapi/local_file_system_operation_unittest.cc index d786406..d2aa935 100644 --- a/webkit/fileapi/local_file_system_operation_unittest.cc +++ b/webkit/fileapi/local_file_system_operation_unittest.cc @@ -21,6 +21,7 @@ #include "webkit/fileapi/file_system_util.h" #include "webkit/fileapi/file_util_helper.h" #include "webkit/fileapi/local_file_system_test_helper.h" +#include "webkit/fileapi/mock_file_change_observer.h" #include "webkit/quota/quota_manager.h" using quota::QuotaClient; @@ -169,6 +170,7 @@ class LocalFileSystemOperationTest : status_(kFileOperationStatusNotSet), next_unique_path_suffix_(0) { EXPECT_TRUE(base_.CreateUniqueTempDir()); + change_observers_ = MockFileChangeObserver::CreateList(&change_observer_); } LocalFileSystemOperation* operation(); @@ -198,6 +200,14 @@ class LocalFileSystemOperationTest return test_helper_.file_util(); } + const ChangeObserverList& change_observers() const { + return change_observers_; + } + + MockFileChangeObserver* change_observer() { + return &change_observer_; + } + FileSystemOperationContext* NewContext() { FileSystemOperationContext* context = test_helper_.NewOperationContext(); // Grant enough quota for all test cases. @@ -385,6 +395,9 @@ class LocalFileSystemOperationTest scoped_refptr<QuotaManager> quota_manager_; scoped_refptr<QuotaManagerProxy> quota_manager_proxy_; + MockFileChangeObserver change_observer_; + ChangeObserverList change_observers_; + int next_unique_path_suffix_; DISALLOW_COPY_AND_ASSIGN(LocalFileSystemOperationTest); @@ -410,15 +423,19 @@ void LocalFileSystemOperationTest::TearDown() { } LocalFileSystemOperation* LocalFileSystemOperationTest::operation() { - return test_helper_.NewOperation(); + LocalFileSystemOperation* operation = test_helper_.NewOperation(); + operation->operation_context()->set_change_observers(change_observers()); + return operation; } TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcDoesntExist) { FileSystemURL src(URLForPath(FilePath(FILE_PATH_LITERAL("a")))); FileSystemURL dest(URLForPath(FilePath(FILE_PATH_LITERAL("b")))); + change_observer()->ResetCount(); operation()->Move(src, dest, RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveFailureContainsPath) { @@ -428,6 +445,7 @@ TEST_F(LocalFileSystemOperationTest, TestMoveFailureContainsPath) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcDirExistsDestFile) { @@ -440,6 +458,7 @@ TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcDirExistsDestFile) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, @@ -453,6 +472,7 @@ TEST_F(LocalFileSystemOperationTest, RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcFileExistsDestDir) { @@ -465,6 +485,7 @@ TEST_F(LocalFileSystemOperationTest, TestMoveFailureSrcFileExistsDestDir) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveFailureDestParentDoesntExist) { @@ -477,6 +498,7 @@ TEST_F(LocalFileSystemOperationTest, TestMoveFailureDestParentDoesntExist) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcFileAndOverwrite) { @@ -491,6 +513,10 @@ TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcFileAndOverwrite) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists(dest_file_path)); + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); + // Move is considered 'write' access (for both side), and won't be counted // as read access. EXPECT_EQ(0, quota_manager_proxy()->storage_accessed_count()); @@ -507,6 +533,10 @@ TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcFileAndNew) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists(dest_file_path)); + + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirAndOverwrite) { @@ -519,6 +549,10 @@ TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirAndOverwrite) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists(src_dir_path)); + EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); + // Make sure we've overwritten but not moved the source under the |dest_dir|. EXPECT_TRUE(DirectoryExists(dest_dir_path)); EXPECT_FALSE(DirectoryExists( @@ -537,6 +571,10 @@ TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirAndNew) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists(src_dir_path)); EXPECT_TRUE(DirectoryExists(dest_child_dir_path)); + + EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirRecursive) { @@ -556,6 +594,12 @@ TEST_F(LocalFileSystemOperationTest, TestMoveSuccessSrcDirRecursive) { EXPECT_TRUE(FileExists(dest_dir_path.Append( VirtualPath::BaseName(child_dir_path)).Append( VirtualPath::BaseName(grandchild_file_path)))); + + EXPECT_EQ(3, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcDoesntExist) { @@ -564,6 +608,7 @@ TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcDoesntExist) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopyFailureContainsPath) { @@ -573,6 +618,7 @@ TEST_F(LocalFileSystemOperationTest, TestCopyFailureContainsPath) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcDirExistsDestFile) { @@ -585,6 +631,7 @@ TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcDirExistsDestFile) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, @@ -598,6 +645,7 @@ TEST_F(LocalFileSystemOperationTest, RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcFileExistsDestDir) { @@ -610,6 +658,7 @@ TEST_F(LocalFileSystemOperationTest, TestCopyFailureSrcFileExistsDestDir) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_INVALID_OPERATION, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopyFailureDestParentDoesntExist) { @@ -625,6 +674,7 @@ TEST_F(LocalFileSystemOperationTest, TestCopyFailureDestParentDoesntExist) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopyFailureByQuota) { @@ -670,6 +720,9 @@ TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcFileAndOverwrite) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists(dest_file_path)); EXPECT_EQ(1, quota_manager_proxy()->storage_accessed_count()); + + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcFileAndNew) { @@ -684,6 +737,9 @@ TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcFileAndNew) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists(dest_file_path)); EXPECT_EQ(1, quota_manager_proxy()->storage_accessed_count()); + + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirAndOverwrite) { @@ -700,6 +756,10 @@ TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirAndOverwrite) { EXPECT_FALSE(DirectoryExists( dest_dir_path.Append(VirtualPath::BaseName(src_dir_path)))); EXPECT_EQ(1, quota_manager_proxy()->storage_accessed_count()); + + EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirAndNew) { @@ -714,6 +774,9 @@ TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirAndNew) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists(dest_child_dir_path)); EXPECT_EQ(1, quota_manager_proxy()->storage_accessed_count()); + + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirRecursive) { @@ -734,6 +797,11 @@ TEST_F(LocalFileSystemOperationTest, TestCopySuccessSrcDirRecursive) { VirtualPath::BaseName(child_dir_path)).Append( VirtualPath::BaseName(grandchild_file_path)))); EXPECT_EQ(1, quota_manager_proxy()->storage_accessed_count()); + + EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_from_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCreateFileFailure) { @@ -744,6 +812,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateFileFailure) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessFileExists) { @@ -755,6 +824,9 @@ TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessFileExists) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists(file_path)); + + // The file was already there; did nothing. + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessExclusive) { @@ -766,6 +838,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessExclusive) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(FileExists(file_path)); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); } TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessFileDoesntExist) { @@ -776,6 +849,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateFileSuccessFileDoesntExist) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); } TEST_F(LocalFileSystemOperationTest, @@ -789,6 +863,7 @@ TEST_F(LocalFileSystemOperationTest, RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCreateDirFailureDirExists) { @@ -798,6 +873,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateDirFailureDirExists) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCreateDirFailureFileExists) { @@ -808,6 +884,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateDirFailureFileExists) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccess) { @@ -817,6 +894,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccess) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); // Dir doesn't exist. FilePath nonexisting_dir_path(FilePath( @@ -826,6 +904,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccess) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists(nonexisting_dir_path)); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); } TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccessExclusive) { @@ -838,6 +917,8 @@ TEST_F(LocalFileSystemOperationTest, TestCreateDirSuccessExclusive) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_TRUE(DirectoryExists(nonexisting_dir_path)); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestExistsAndMetadataFailure) { @@ -858,6 +939,7 @@ TEST_F(LocalFileSystemOperationTest, TestExistsAndMetadataFailure) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestExistsAndMetadataSuccess) { @@ -891,6 +973,7 @@ TEST_F(LocalFileSystemOperationTest, TestExistsAndMetadataSuccess) { ++read_access; EXPECT_EQ(read_access, quota_manager_proxy()->storage_accessed_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestTypeMismatchErrors) { @@ -924,6 +1007,7 @@ TEST_F(LocalFileSystemOperationTest, TestReadDirFailure) { MessageLoop::current()->RunAllPending(); // TODO(kkanetkar) crbug.com/54309 to change the error code. EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestReadDirSuccess) { @@ -952,6 +1036,7 @@ TEST_F(LocalFileSystemOperationTest, TestReadDirSuccess) { } } EXPECT_EQ(1, quota_manager_proxy()->storage_accessed_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestRemoveFailure) { @@ -981,6 +1066,7 @@ TEST_F(LocalFileSystemOperationTest, TestRemoveFailure) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestRemoveSuccess) { @@ -993,6 +1079,9 @@ TEST_F(LocalFileSystemOperationTest, TestRemoveSuccess) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(DirectoryExists(empty_dir_path)); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); + // Removing a non-empty directory with recursive flag == true should be ok. // parent_dir // | | @@ -1011,6 +1100,10 @@ TEST_F(LocalFileSystemOperationTest, TestRemoveSuccess) { // Remove is not a 'read' access. EXPECT_EQ(0, quota_manager_proxy()->storage_accessed_count()); + + EXPECT_EQ(2, change_observer()->get_and_reset_remove_directory_count()); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(LocalFileSystemOperationTest, TestTruncate) { @@ -1036,6 +1129,9 @@ TEST_F(LocalFileSystemOperationTest, TestTruncate) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); + // Check that its length is now 17 and that it's all zeroes after the test // data. base::PlatformFileInfo info; @@ -1057,6 +1153,9 @@ TEST_F(LocalFileSystemOperationTest, TestTruncate) { MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); + // Check that its length is now 3 and that it contains only bits of test data. EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info)); EXPECT_EQ(length, info.size); @@ -1081,6 +1180,8 @@ TEST_F(LocalFileSystemOperationTest, TestTruncateFailureByQuota) { operation()->Truncate(URLForPath(file_path), 10, RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info)); EXPECT_EQ(10, info.size); @@ -1088,6 +1189,7 @@ TEST_F(LocalFileSystemOperationTest, TestTruncateFailureByQuota) { operation()->Truncate(URLForPath(file_path), 11, RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); EXPECT_TRUE(file_util::GetFileInfo(PlatformPath(file_path), &info)); EXPECT_EQ(10, info.size); @@ -1116,6 +1218,7 @@ TEST_F(LocalFileSystemOperationTest, TestTouchFile) { RecordStatusCallback()); MessageLoop::current()->RunAllPending(); EXPECT_EQ(base::PLATFORM_FILE_OK, status()); + EXPECT_TRUE(change_observer()->HasNoChange()); EXPECT_TRUE(file_util::GetFileInfo(platform_path, &info)); // We compare as time_t here to lower our resolution, to avoid false @@ -1146,6 +1249,7 @@ TEST_F(LocalFileSystemOperationTest, TestCreateSnapshotFile) { EXPECT_EQ(base::PLATFORM_FILE_OK, status()); EXPECT_FALSE(info().is_directory); EXPECT_EQ(PlatformPath(file_path), path()); + EXPECT_TRUE(change_observer()->HasNoChange()); // The FileSystemOpration implementation does not create a // shareable file reference. diff --git a/webkit/fileapi/mock_file_change_observer.cc b/webkit/fileapi/mock_file_change_observer.cc new file mode 100644 index 0000000..c358185 --- /dev/null +++ b/webkit/fileapi/mock_file_change_observer.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/fileapi/mock_file_change_observer.h" + +namespace fileapi { + +MockFileChangeObserver::MockFileChangeObserver() + : create_file_count_(0), + create_file_from_count_(0), + remove_file_count_(0), + modify_file_count_(0), + create_directory_count_(0), + remove_directory_count_(0) {} + +MockFileChangeObserver::~MockFileChangeObserver() {} + +// static +ChangeObserverList MockFileChangeObserver::CreateList( + MockFileChangeObserver* observer) { + ChangeObserverList::Source source; + source.AddObserver(observer, base::MessageLoopProxy::current()); + return ChangeObserverList(source); +} + +void MockFileChangeObserver::OnCreateFile(const FileSystemURL& url) { + create_file_count_++; +} + +void MockFileChangeObserver::OnCreateFileFrom(const FileSystemURL& url, + const FileSystemURL& src) { + create_file_from_count_++; +} + +void MockFileChangeObserver::OnRemoveFile(const FileSystemURL& url) { + remove_file_count_++; +} + +void MockFileChangeObserver::OnModifyFile(const FileSystemURL& url) { + modify_file_count_++; +} + +void MockFileChangeObserver::OnCreateDirectory(const FileSystemURL& url) { + create_directory_count_++; +} + +void MockFileChangeObserver::OnRemoveDirectory(const FileSystemURL& url) { + remove_directory_count_++; +} + +} // namespace fileapi diff --git a/webkit/fileapi/mock_file_change_observer.h b/webkit/fileapi/mock_file_change_observer.h new file mode 100644 index 0000000..81cfad9 --- /dev/null +++ b/webkit/fileapi/mock_file_change_observer.h @@ -0,0 +1,103 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_FILEAPI_MOCK_FILE_CHANGE_OBSERVER_H_ +#define WEBKIT_FILEAPI_MOCK_FILE_CHANGE_OBSERVER_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "webkit/fileapi/file_observers.h" +#include "webkit/fileapi/file_system_url.h" +#include "webkit/fileapi/task_runner_bound_observer_list.h" + +namespace fileapi { + +// Mock file change observer. +class MockFileChangeObserver : public FileChangeObserver { + public: + MockFileChangeObserver(); + virtual ~MockFileChangeObserver(); + + // Creates a ChangeObserverList which only contains given |observer|. + static ChangeObserverList CreateList(MockFileChangeObserver* observer); + + // FileChangeObserver overrides. + virtual void OnCreateFile(const FileSystemURL& url) OVERRIDE; + virtual void OnCreateFileFrom(const FileSystemURL& url, + const FileSystemURL& src) OVERRIDE; + virtual void OnRemoveFile(const FileSystemURL& url) OVERRIDE; + virtual void OnModifyFile(const FileSystemURL& url) OVERRIDE; + virtual void OnCreateDirectory(const FileSystemURL& url) OVERRIDE; + virtual void OnRemoveDirectory(const FileSystemURL& url) OVERRIDE; + + void ResetCount() { + create_file_count_ = 0; + create_file_from_count_ = 0; + remove_file_count_ = 0; + modify_file_count_ = 0; + create_directory_count_ = 0; + remove_directory_count_ = 0; + } + + bool HasNoChange() const { + return create_file_count_ == 0 && + create_file_from_count_ == 0 && + remove_file_count_ == 0 && + modify_file_count_ == 0 && + create_directory_count_ == 0 && + remove_directory_count_ == 0; + } + + int create_file_count() const { return create_file_count_; } + int create_file_from_count() const { return create_file_from_count_; } + int remove_file_count() const { return remove_file_count_; } + int modify_file_count() const { return modify_file_count_; } + int create_directory_count() const { return create_directory_count_; } + int remove_directory_count() const { return remove_directory_count_; } + + int get_and_reset_create_file_count() { + int tmp = create_file_count_; + create_file_count_ = 0; + return tmp; + } + int get_and_reset_create_file_from_count() { + int tmp = create_file_from_count_; + create_file_from_count_ = 0; + return tmp; + } + int get_and_reset_remove_file_count() { + int tmp = remove_file_count_; + remove_file_count_ = 0; + return tmp; + } + int get_and_reset_modify_file_count() { + int tmp = modify_file_count_; + modify_file_count_ = 0; + return tmp; + } + int get_and_reset_create_directory_count() { + int tmp = create_directory_count_; + create_directory_count_ = 0; + return tmp; + } + int get_and_reset_remove_directory_count() { + int tmp = remove_directory_count_; + remove_directory_count_ = 0; + return tmp; + } + + private: + int create_file_count_; + int create_file_from_count_; + int remove_file_count_; + int modify_file_count_; + int create_directory_count_; + int remove_directory_count_; + + DISALLOW_COPY_AND_ASSIGN(MockFileChangeObserver); +}; + +} // namespace fileapi + +#endif // WEBKIT_FILEAPI_MOCK_FILE_CHANGE_OBSERVER_H_ diff --git a/webkit/fileapi/obfuscated_file_util.cc b/webkit/fileapi/obfuscated_file_util.cc index fddf937..1022954 100644 --- a/webkit/fileapi/obfuscated_file_util.cc +++ b/webkit/fileapi/obfuscated_file_util.cc @@ -293,6 +293,8 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen( if (created && base::PLATFORM_FILE_OK == error) { *created = true; UpdateUsage(context, url, growth); + context->change_observers()->Notify( + &FileChangeObserver::OnCreateFile, MakeTuple(url)); } return error; } @@ -330,8 +332,11 @@ PlatformFileError ObfuscatedFileUtil::CreateOrOpen( } // If truncating we need to update the usage. - if (error == base::PLATFORM_FILE_OK && delta) + if (error == base::PLATFORM_FILE_OK && delta) { UpdateUsage(context, url, delta); + context->change_observers()->Notify( + &FileChangeObserver::OnModifyFile, MakeTuple(url)); + } return error; } @@ -379,6 +384,8 @@ PlatformFileError ObfuscatedFileUtil::EnsureFileExists( if (created && base::PLATFORM_FILE_OK == error) { *created = true; UpdateUsage(context, url, growth); + context->change_observers()->Notify( + &FileChangeObserver::OnCreateFile, MakeTuple(url)); } return error; } @@ -436,6 +443,8 @@ PlatformFileError ObfuscatedFileUtil::CreateDirectory( return base::PLATFORM_FILE_ERROR_FAILED; } UpdateUsage(context, url, growth); + context->change_observers()->Notify( + &FileChangeObserver::OnCreateDirectory, MakeTuple(url)); if (first) { first = false; TouchDirectory(db, file_info.parent_id); @@ -545,8 +554,11 @@ PlatformFileError ObfuscatedFileUtil::Truncate( if (!AllocateQuota(context, growth)) return base::PLATFORM_FILE_ERROR_NO_SPACE; error = NativeFileUtil::Truncate(local_path, length); - if (error == base::PLATFORM_FILE_OK) + if (error == base::PLATFORM_FILE_OK) { UpdateUsage(context, url, growth); + context->change_observers()->Notify( + &FileChangeObserver::OnModifyFile, MakeTuple(url)); + } return error; } @@ -695,8 +707,22 @@ PlatformFileError ObfuscatedFileUtil::CopyOrMoveFile( if (error != base::PLATFORM_FILE_OK) return error; - if (!copy) + if (overwrite) { + context->change_observers()->Notify( + &FileChangeObserver::OnModifyFile, + MakeTuple(dest_url)); + } else { + context->change_observers()->Notify( + &FileChangeObserver::OnCreateFileFrom, + MakeTuple(dest_url, src_url)); + } + + if (!copy) { + context->change_observers()->Notify( + &FileChangeObserver::OnRemoveFile, MakeTuple(src_url)); TouchDirectory(db, src_file_info.parent_id); + } + TouchDirectory(db, dest_file_info.parent_id); UpdateUsage(context, dest_url, growth); @@ -769,6 +795,14 @@ PlatformFileError ObfuscatedFileUtil::CopyInForeignFile( if (error != base::PLATFORM_FILE_OK) return error; + if (overwrite) { + context->change_observers()->Notify( + &FileChangeObserver::OnModifyFile, MakeTuple(dest_url)); + } else { + context->change_observers()->Notify( + &FileChangeObserver::OnCreateFile, MakeTuple(dest_url)); + } + UpdateUsage(context, dest_url, growth); TouchDirectory(db, dest_file_info.parent_id); return base::PLATFORM_FILE_OK; @@ -809,6 +843,9 @@ PlatformFileError ObfuscatedFileUtil::DeleteFile( UpdateUsage(context, url, growth); TouchDirectory(db, file_info.parent_id); + context->change_observers()->Notify( + &FileChangeObserver::OnRemoveFile, MakeTuple(url)); + if (error == base::PLATFORM_FILE_ERROR_NOT_FOUND) return base::PLATFORM_FILE_OK; @@ -840,6 +877,8 @@ PlatformFileError ObfuscatedFileUtil::DeleteSingleDirectory( AllocateQuota(context, growth); UpdateUsage(context, url, growth); TouchDirectory(db, file_info.parent_id); + context->change_observers()->Notify( + &FileChangeObserver::OnRemoveDirectory, MakeTuple(url)); return base::PLATFORM_FILE_OK; } diff --git a/webkit/fileapi/obfuscated_file_util_unittest.cc b/webkit/fileapi/obfuscated_file_util_unittest.cc index 76c28ba..a7f9c4b 100644 --- a/webkit/fileapi/obfuscated_file_util_unittest.cc +++ b/webkit/fileapi/obfuscated_file_util_unittest.cc @@ -21,6 +21,7 @@ #include "webkit/fileapi/file_system_usage_cache.h" #include "webkit/fileapi/file_util_helper.h" #include "webkit/fileapi/local_file_system_test_helper.h" +#include "webkit/fileapi/mock_file_change_observer.h" #include "webkit/fileapi/mock_file_system_options.h" #include "webkit/fileapi/obfuscated_file_util.h" #include "webkit/fileapi/test_file_set.h" @@ -28,7 +29,7 @@ #include "webkit/quota/quota_manager.h" #include "webkit/quota/quota_types.h" -using namespace fileapi; +namespace fileapi { namespace { @@ -133,6 +134,8 @@ class ObfuscatedFileUtilTest : public testing::Test { test_helper_.SetUp(file_system_context_.get(), obfuscated_file_util_); + + change_observers_ = MockFileChangeObserver::CreateList(&change_observer_); } void TearDown() { @@ -154,15 +157,25 @@ class ObfuscatedFileUtilTest : public testing::Test { FileSystemOperationContext* NewContext( LocalFileSystemTestOriginHelper* helper) { + change_observer()->ResetCount(); FileSystemOperationContext* context; if (helper) context = helper->NewOperationContext(); else context = test_helper_.NewOperationContext(); context->set_allowed_bytes_growth(1024 * 1024); // Big enough for all tests. + context->set_change_observers(change_observers()); return context; } + const ChangeObserverList& change_observers() const { + return change_observers_; + } + + MockFileChangeObserver* change_observer() { + return &change_observer_; + } + // This can only be used after SetUp has run and created file_system_context_ // and obfuscated_file_util_. // Use this for tests which need to run in multiple origins; we need a test @@ -428,6 +441,7 @@ class ObfuscatedFileUtilTest : public testing::Test { context.get(), ofu(), root_url, &entries)); std::vector<base::FileUtilProxy::Entry>::iterator entry_iter; EXPECT_EQ(files.size() + directories.size(), entries.size()); + EXPECT_TRUE(change_observer()->HasNoChange()); for (entry_iter = entries.begin(); entry_iter != entries.end(); ++entry_iter) { const base::FileUtilProxy::Entry& entry = *entry_iter; @@ -452,6 +466,8 @@ class ObfuscatedFileUtilTest : public testing::Test { EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Touch( context.get(), url, last_access_time, last_modified_time)); + // Currently we fire no change notifications for Touch. + EXPECT_TRUE(change_observer()->HasNoChange()); FilePath local_path; base::PlatformFileInfo file_info; context.reset(NewContext(NULL)); @@ -468,6 +484,7 @@ class ObfuscatedFileUtilTest : public testing::Test { EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Touch( context.get(), url, last_access_time, last_modified_time)); + EXPECT_TRUE(change_observer()->HasNoChange()); context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo( context.get(), url, &file_info, &local_path)); @@ -503,6 +520,10 @@ class ObfuscatedFileUtilTest : public testing::Test { EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(context.get(), dest_url, &created)); EXPECT_TRUE(created); + + // We must have observed one (and only one) create_file_count. + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); + EXPECT_TRUE(change_observer()->HasNoChange()); } const int64 path_cost = @@ -552,6 +573,7 @@ class ObfuscatedFileUtilTest : public testing::Test { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->GetFileInfo(context.get(), url, &file_info, &data_path)); + EXPECT_TRUE(change_observer()->HasNoChange()); return file_info.last_modified; } @@ -594,7 +616,6 @@ class ObfuscatedFileUtilTest : public testing::Test { ofu()->CopyOrMoveFile(context.get(), src_file_url, dest_file_url, copy)); - if (copy) EXPECT_EQ(base::Time(), GetModifiedTime(src_dir_url)); else @@ -623,6 +644,8 @@ class ObfuscatedFileUtilTest : public testing::Test { LocalFileSystemTestOriginHelper test_helper_; quota::QuotaStatusCode quota_status_; int64 usage_; + MockFileChangeObserver change_observer_; + ChangeObserverList change_observers_; DISALLOW_COPY_AND_ASSIGN(ObfuscatedFileUtilTest); }; @@ -645,6 +668,8 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { url = CreateURLFromUTF8("test file"); + EXPECT_TRUE(change_observer()->HasNoChange()); + // Verify that file creation requires sufficient quota for the path. context.reset(NewContext(NULL)); context->set_allowed_bytes_growth( @@ -660,6 +685,7 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { ofu()->CreateOrOpen( context.get(), url, file_flags, &file_handle, &created)); ASSERT_TRUE(created); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); EXPECT_NE(base::kInvalidPlatformFileValue, file_handle); CheckFileAndCloseHandle(url, file_handle); @@ -676,6 +702,7 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { context->set_allowed_bytes_growth(0); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteFile(context.get(), url)); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); EXPECT_FALSE(file_util::PathExists(local_path)); EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), context->allowed_bytes_growth()); @@ -688,6 +715,8 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { url = directory_url.WithPath(directory_url.path().AppendASCII("file name")); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( context.get(), directory_url, exclusive, recursive)); + // The oepration created 3 directories recursively. + EXPECT_EQ(3, change_observer()->get_and_reset_create_directory_count()); context.reset(NewContext(NULL)); file_handle = base::kInvalidPlatformFileValue; @@ -695,6 +724,7 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { ofu()->CreateOrOpen( context.get(), url, file_flags, &file_handle, &created)); ASSERT_TRUE(created); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); EXPECT_NE(base::kInvalidPlatformFileValue, file_handle); CheckFileAndCloseHandle(url, file_handle); @@ -707,7 +737,11 @@ TEST_F(ObfuscatedFileUtilTest, TestCreateAndDeleteFile) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteFile(context.get(), url)); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_file_count()); EXPECT_FALSE(file_util::PathExists(local_path)); + + // Make sure we have no unexpected changes. + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(ObfuscatedFileUtilTest, TestTruncate) { @@ -722,6 +756,7 @@ TEST_F(ObfuscatedFileUtilTest, TestTruncate) { ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_TRUE(created); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); context.reset(NewContext(NULL)); FilePath local_path; @@ -732,15 +767,20 @@ TEST_F(ObfuscatedFileUtilTest, TestTruncate) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate( context.get(), url, 10)); + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); EXPECT_EQ(10, GetSize(local_path)); context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->Truncate( context.get(), url, 1)); EXPECT_EQ(1, GetSize(local_path)); + EXPECT_EQ(1, change_observer()->get_and_reset_modify_file_count()); EXPECT_FALSE(DirectoryExists(url)); EXPECT_TRUE(PathExists(url)); + + // Make sure we have no unexpected changes. + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(ObfuscatedFileUtilTest, TestQuotaOnTruncation) { @@ -817,6 +857,7 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->EnsureFileExists( context.get(), url, &created)); + EXPECT_TRUE(change_observer()->HasNoChange()); // Verify that file creation requires sufficient quota for the path. context.reset(NewContext(NULL)); @@ -827,6 +868,7 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { ASSERT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_FALSE(created); + EXPECT_TRUE(change_observer()->HasNoChange()); context.reset(NewContext(NULL)); context->set_allowed_bytes_growth( @@ -834,6 +876,7 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_TRUE(created); + EXPECT_EQ(1, change_observer()->get_and_reset_create_file_count()); CheckFileAndCloseHandle(url, base::kInvalidPlatformFileValue); @@ -841,6 +884,7 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { ASSERT_EQ(base::PLATFORM_FILE_OK, ofu()->EnsureFileExists(context.get(), url, &created)); ASSERT_FALSE(created); + EXPECT_TRUE(change_observer()->HasNoChange()); // Also test in a subdirectory. url = CreateURLFromUTF8("path/to/file.txt"); @@ -851,6 +895,8 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { context.get(), url.WithPath(url.path().DirName()), exclusive, recursive)); + // 2 directories: path/ and path/to. + EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); context.reset(NewContext(NULL)); ASSERT_EQ(base::PLATFORM_FILE_OK, @@ -858,6 +904,7 @@ TEST_F(ObfuscatedFileUtilTest, TestEnsureFileExists) { ASSERT_TRUE(created); EXPECT_FALSE(DirectoryExists(url)); EXPECT_TRUE(PathExists(url)); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { @@ -884,6 +931,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { recursive = true; EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); EXPECT_TRUE(DirectoryExists(url)); EXPECT_TRUE(PathExists(url)); @@ -901,6 +949,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_EMPTY, ofu()->DeleteSingleDirectory(context.get(), url.WithPath(url.path().DirName()))); + EXPECT_TRUE(change_observer()->HasNoChange()); base::PlatformFileInfo file_info; FilePath local_path; @@ -914,12 +963,14 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_TRUE(change_observer()->HasNoChange()); exclusive = true; recursive = true; context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_TRUE(change_observer()->HasNoChange()); // Verify that deleting a directory isn't stopped by zero quota, and that it // frees up quota from its path. @@ -927,6 +978,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { context->set_allowed_bytes_growth(0); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->DeleteSingleDirectory(context.get(), url)); + EXPECT_EQ(1, change_observer()->get_and_reset_remove_directory_count()); EXPECT_EQ(ObfuscatedFileUtil::ComputeFilePathCost(url.path()), context->allowed_bytes_growth()); @@ -948,12 +1000,14 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { ObfuscatedFileUtil::ComputeFilePathCost(url.path()) - 1); EXPECT_EQ(base::PLATFORM_FILE_ERROR_NO_SPACE, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_TRUE(change_observer()->HasNoChange()); context.reset(NewContext(NULL)); context->set_allowed_bytes_growth( ObfuscatedFileUtil::ComputeFilePathCost(url.path())); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); EXPECT_TRUE(DirectoryExists(url)); EXPECT_TRUE(PathExists(url)); @@ -963,6 +1017,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_TRUE(change_observer()->HasNoChange()); exclusive = true; recursive = false; @@ -970,6 +1025,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_TRUE(change_observer()->HasNoChange()); url = CreateURLFromUTF8("blah"); @@ -981,6 +1037,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_EQ(1, change_observer()->get_and_reset_create_directory_count()); EXPECT_TRUE(DirectoryExists(url)); EXPECT_TRUE(PathExists(url)); @@ -990,6 +1047,7 @@ TEST_F(ObfuscatedFileUtilTest, TestDirectoryOps) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_ERROR_EXISTS, ofu()->CreateDirectory( context.get(), url, exclusive, recursive)); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(ObfuscatedFileUtilTest, TestReadDirectory) { @@ -1103,11 +1161,13 @@ TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) { EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, is_copy_not_move)); + EXPECT_TRUE(change_observer()->HasNoChange()); context.reset(NewContext(NULL)); is_copy_not_move = true; EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, is_copy_not_move)); + EXPECT_TRUE(change_observer()->HasNoChange()); source_url = CreateURLFromUTF8("dir/dir/file"); bool exclusive = true; bool recursive = true; @@ -1116,15 +1176,18 @@ TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileNotFound) { context.get(), source_url.WithPath(source_url.path().DirName()), exclusive, recursive)); + EXPECT_EQ(2, change_observer()->get_and_reset_create_directory_count()); is_copy_not_move = false; EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, is_copy_not_move)); + EXPECT_TRUE(change_observer()->HasNoChange()); context.reset(NewContext(NULL)); is_copy_not_move = true; EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, is_copy_not_move)); + EXPECT_TRUE(change_observer()->HasNoChange()); } TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) { @@ -1183,6 +1246,7 @@ TEST_F(ObfuscatedFileUtilTest, TestCopyOrMoveFileSuccess) { context.reset(NewContext(NULL)); EXPECT_EQ(base::PLATFORM_FILE_OK, ofu()->CopyOrMoveFile(context.get(), source_url, dest_url, test_case.is_copy_not_move)); + if (test_case.is_copy_not_move) { base::PlatformFileInfo file_info; FilePath local_path; @@ -2210,3 +2274,5 @@ TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) { ASSERT_EQ(0, ComputeTotalFileSize()); EXPECT_TRUE(base::ClosePlatformFile(file_handle)); } + +} // namespace fileapi diff --git a/webkit/fileapi/task_runner_bound_observer_list.h b/webkit/fileapi/task_runner_bound_observer_list.h index 17a8eec..9af380f5c 100644 --- a/webkit/fileapi/task_runner_bound_observer_list.h +++ b/webkit/fileapi/task_runner_bound_observer_list.h @@ -94,9 +94,11 @@ class TaskRunnerBoundObserverList { }; class FileAccessObserver; +class FileChangeObserver; class FileUpdateObserver; typedef TaskRunnerBoundObserverList<FileAccessObserver> AccessObserverList; +typedef TaskRunnerBoundObserverList<FileChangeObserver> ChangeObserverList; typedef TaskRunnerBoundObserverList<FileUpdateObserver> UpdateObserverList; } // namespace fileapi |