diff options
author | calvinlo@chromium.org <calvinlo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-05 13:38:40 +0000 |
---|---|---|
committer | calvinlo@chromium.org <calvinlo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-05 13:38:40 +0000 |
commit | 1725868ad48dae8ba447596fb89ca6d18f592bd0 (patch) | |
tree | 496939779c7c695f05438d684a13b170ab3366fb /webkit | |
parent | b81d40482de05e38f3917b3546077c9a048aef15 (diff) | |
download | chromium_src-1725868ad48dae8ba447596fb89ca6d18f592bd0.zip chromium_src-1725868ad48dae8ba447596fb89ca6d18f592bd0.tar.gz chromium_src-1725868ad48dae8ba447596fb89ca6d18f592bd0.tar.bz2 |
Use PostDelayTask instead of timer to drop DB.
BUG=240621
Review URL: https://chromiumcodereview.appspot.com/15443002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@204249 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/browser/fileapi/obfuscated_file_util.cc | 97 | ||||
-rw-r--r-- | webkit/browser/fileapi/obfuscated_file_util.h | 30 | ||||
-rw-r--r-- | webkit/browser/fileapi/obfuscated_file_util_unittest.cc | 36 | ||||
-rw-r--r-- | webkit/browser/fileapi/sandbox_mount_point_provider.cc | 3 |
4 files changed, 145 insertions, 21 deletions
diff --git a/webkit/browser/fileapi/obfuscated_file_util.cc b/webkit/browser/fileapi/obfuscated_file_util.cc index 5346b93..0fe7776 100644 --- a/webkit/browser/fileapi/obfuscated_file_util.cc +++ b/webkit/browser/fileapi/obfuscated_file_util.cc @@ -16,6 +16,7 @@ #include "base/stringprintf.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" +#include "base/time.h" #include "base/utf_string_conversions.h" #include "googleurl/src/gurl.h" #include "webkit/base/origin_url_conversions.h" @@ -47,8 +48,6 @@ namespace { typedef SandboxDirectoryDatabase::FileId FileId; typedef SandboxDirectoryDatabase::FileInfo FileInfo; -const int64 kFlushDelaySeconds = 10 * 60; // 10 minutes - void InitFileInfo( SandboxDirectoryDatabase::FileInfo* file_info, SandboxDirectoryDatabase::FileId parent_id, @@ -96,6 +95,49 @@ void TouchDirectory(SandboxDirectoryDatabase* db, FileId dir_id) { NOTREACHED(); } +class Deleter { + public: + explicit Deleter(ObfuscatedFileUtil* util) : util_(util) {} + + void operator()(bool* ptr) const { + if (*ptr) + util_->ResetObjectLifetimeTracker(); + delete ptr; + } + + private: + ObfuscatedFileUtil* util_; +}; + +void MaybeDropDatabases( + ObfuscatedFileUtil* util, + scoped_refptr<base::SequencedTaskRunner> file_task_runner, + scoped_ptr<bool, Deleter> object_still_alive, + int64 db_flush_delay_seconds) { + // If object isn't alive, DB has already been dropped by dtor. + if (!*object_still_alive) + return; + + // Check to see if DB was recently used. If yes, restart timer so it triggers + // again in kFlushDelaySeconds from the last time it was used. + base::TimeDelta last_used_delta = + base::TimeTicks::Now() - util->db_last_use_time(); + int64 next_timer_delta = db_flush_delay_seconds - last_used_delta.InSeconds(); + if (next_timer_delta > 0) { + file_task_runner->PostDelayedTask( + FROM_HERE, + base::Bind(&MaybeDropDatabases, + base::Unretained(util), + file_task_runner, + base::Passed(&object_still_alive), + db_flush_delay_seconds), + base::TimeDelta::FromSeconds(next_timer_delta)); + return; + } + + util->DropDatabases(); +} + const base::FilePath::CharType kTemporaryDirectoryName[] = FILE_PATH_LITERAL("t"); const base::FilePath::CharType kPersistentDirectoryName[] = FILE_PATH_LITERAL("p"); const base::FilePath::CharType kSyncableDirectoryName[] = FILE_PATH_LITERAL("s"); @@ -255,12 +297,20 @@ class ObfuscatedOriginEnumerator ObfuscatedFileUtil::ObfuscatedFileUtil( quota::SpecialStoragePolicy* special_storage_policy, - const base::FilePath& file_system_directory) + const base::FilePath& file_system_directory, + base::SequencedTaskRunner* file_task_runner) : special_storage_policy_(special_storage_policy), - file_system_directory_(file_system_directory) { + file_system_directory_(file_system_directory), + file_task_runner_(file_task_runner), + db_flush_delay_seconds_(10 * 60), // 10 mins. + object_lifetime_tracker_(NULL) { } ObfuscatedFileUtil::~ObfuscatedFileUtil() { + // Mark as deleted so that the callback doesn't run on invalid object. + if (object_lifetime_tracker_) + *object_lifetime_tracker_ = false; + DropDatabases(); } @@ -989,6 +1039,17 @@ bool ObfuscatedFileUtil::DestroyDirectoryDatabase( return SandboxDirectoryDatabase::DestroyDatabase(path); } +void ObfuscatedFileUtil::ResetObjectLifetimeTracker() { + object_lifetime_tracker_ = NULL; +} + +void ObfuscatedFileUtil::DropDatabases() { + origin_database_.reset(); + STLDeleteContainerPairSecondPointers( + directories_.begin(), directories_.end()); + directories_.clear(); +} + // static int64 ObfuscatedFileUtil::ComputeFilePathCost(const base::FilePath& path) { return UsageForPath(VirtualPath::BaseName(path).value().size()); @@ -1279,18 +1340,24 @@ void ObfuscatedFileUtil::InvalidateUsageCache( } void ObfuscatedFileUtil::MarkUsed() { - if (timer_.IsRunning()) - timer_.Reset(); - else - timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kFlushDelaySeconds), - this, &ObfuscatedFileUtil::DropDatabases); -} + db_last_use_time_ = base::TimeTicks::Now(); -void ObfuscatedFileUtil::DropDatabases() { - origin_database_.reset(); - STLDeleteContainerPairSecondPointers( - directories_.begin(), directories_.end()); - directories_.clear(); + // If object_lifetime_tracker_ is valid, then callback timer already running. + if (object_lifetime_tracker_) + return; + + // Initialize object lifetime tracker for the first time. + object_lifetime_tracker_ = new bool(true); + + scoped_ptr<bool, Deleter> scoper(object_lifetime_tracker_, Deleter(this)); + file_task_runner_->PostDelayedTask( + FROM_HERE, + base::Bind(&MaybeDropDatabases, + base::Unretained(this), + file_task_runner_, + base::Passed(&scoper), + db_flush_delay_seconds_), + base::TimeDelta::FromSeconds(db_flush_delay_seconds_)); } bool ObfuscatedFileUtil::InitOriginDatabase(bool create) { diff --git a/webkit/browser/fileapi/obfuscated_file_util.h b/webkit/browser/fileapi/obfuscated_file_util.h index 7cd5c59..680349e 100644 --- a/webkit/browser/fileapi/obfuscated_file_util.h +++ b/webkit/browser/fileapi/obfuscated_file_util.h @@ -10,9 +10,9 @@ #include "base/files/file_path.h" #include "base/files/file_util_proxy.h" +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "base/platform_file.h" -#include "base/timer.h" #include "webkit/browser/fileapi/file_system_file_util.h" #include "webkit/browser/fileapi/file_system_url.h" #include "webkit/browser/fileapi/sandbox_directory_database.h" @@ -21,7 +21,8 @@ #include "webkit/storage/webkit_storage_export.h" namespace base { -class Time; +class SequencedTaskRunner; +class TimeTicks; } namespace quota { @@ -61,7 +62,8 @@ class WEBKIT_STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil ObfuscatedFileUtil( quota::SpecialStoragePolicy* special_storage_policy, - const base::FilePath& file_system_directory); + const base::FilePath& file_system_directory, + base::SequencedTaskRunner* file_task_runner); virtual ~ObfuscatedFileUtil(); // FileSystemFileUtil overrides. @@ -169,6 +171,12 @@ class WEBKIT_STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil // and destroys the database on the disk. bool DestroyDirectoryDatabase(const GURL& origin, FileSystemType type); + void ResetObjectLifetimeTracker(); + + void DropDatabases(); + + const base::TimeTicks& db_last_use_time() const { return db_last_use_time_; } + // Computes a cost for storing a given file in the obfuscated FSFU. // As the cost of a file is independent of the cost of its parent directories, // this ignores all but the BaseName of the supplied path. In order to @@ -183,6 +191,9 @@ class WEBKIT_STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil typedef SandboxDirectoryDatabase::FileInfo FileInfo; friend class ObfuscatedFileEnumerator; + FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase); + FRIEND_TEST_ALL_PREFIXES(ObfuscatedFileUtilTest, + MaybeDropDatabasesAlreadyDeletedCase); base::PlatformFileError GetFileInfoInternal( SandboxDirectoryDatabase* db, @@ -241,7 +252,6 @@ class WEBKIT_STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil FileSystemType type); void MarkUsed(); - void DropDatabases(); bool InitOriginDatabase(bool create); base::PlatformFileError GenerateNewLocalPath( @@ -263,7 +273,17 @@ class WEBKIT_STORAGE_EXPORT_PRIVATE ObfuscatedFileUtil scoped_ptr<SandboxOriginDatabaseInterface> origin_database_; scoped_refptr<quota::SpecialStoragePolicy> special_storage_policy_; base::FilePath file_system_directory_; - base::OneShotTimer<ObfuscatedFileUtil> timer_; + scoped_refptr<base::SequencedTaskRunner> file_task_runner_; + + // Used to delete database after a certain period of inactivity. + int64 db_flush_delay_seconds_; + base::TimeTicks db_last_use_time_; + + // Owned by MaybeDropDatabase callback, set to false when dtor runs. + // This only becomes valid when the PostDelayedTask callback is posted and + // becomes invalid again if the PostDelayedTask callback finishes. (i.e. timer + // runs out). + bool* object_lifetime_tracker_; // If this instance is initialized for an isolated partition, this should // only see a single origin. diff --git a/webkit/browser/fileapi/obfuscated_file_util_unittest.cc b/webkit/browser/fileapi/obfuscated_file_util_unittest.cc index f1fa1b1..93a4015 100644 --- a/webkit/browser/fileapi/obfuscated_file_util_unittest.cc +++ b/webkit/browser/fileapi/obfuscated_file_util_unittest.cc @@ -25,6 +25,7 @@ #include "webkit/browser/fileapi/mock_file_system_context.h" #include "webkit/browser/fileapi/obfuscated_file_util.h" #include "webkit/browser/fileapi/sandbox_file_system_test_helper.h" +#include "webkit/browser/fileapi/sandbox_origin_database.h" #include "webkit/browser/fileapi/test_file_set.h" #include "webkit/browser/quota/mock_special_storage_policy.h" #include "webkit/browser/quota/quota_manager.h" @@ -2251,4 +2252,39 @@ TEST_F(ObfuscatedFileUtilTest, TestQuotaOnOpen) { EXPECT_TRUE(base::ClosePlatformFile(file_handle)); } +TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAliveCase) { + base::ScopedTempDir data_dir; + ASSERT_TRUE(data_dir.CreateUniqueTempDir()); + ObfuscatedFileUtil file_util(NULL, + data_dir.path(), + base::MessageLoopProxy::current()); + file_util.InitOriginDatabase(true /*create*/); + ASSERT_TRUE(file_util.origin_database_ != NULL); + + // Callback to Drop DB is called while ObfuscatedFileUtilTest is still alive. + file_util.db_flush_delay_seconds_ = 0; + file_util.MarkUsed(); + base::MessageLoop::current()->RunUntilIdle(); + + ASSERT_TRUE(file_util.origin_database_ == NULL); +} + +TEST_F(ObfuscatedFileUtilTest, MaybeDropDatabasesAlreadyDeletedCase) { + // Run message loop after OFU is already deleted to make sure callback doesn't + // cause a crash for use after free. + { + base::ScopedTempDir data_dir; + ASSERT_TRUE(data_dir.CreateUniqueTempDir()); + ObfuscatedFileUtil file_util(NULL, + data_dir.path(), + base::MessageLoopProxy::current()); + file_util.InitOriginDatabase(true /*create*/); + file_util.db_flush_delay_seconds_ = 0; + file_util.MarkUsed(); + } + + // At this point the callback is still in the message queue but OFU is gone. + base::MessageLoop::current()->RunUntilIdle(); +} + } // namespace fileapi diff --git a/webkit/browser/fileapi/sandbox_mount_point_provider.cc b/webkit/browser/fileapi/sandbox_mount_point_provider.cc index 0612ad8..f448aaa 100644 --- a/webkit/browser/fileapi/sandbox_mount_point_provider.cc +++ b/webkit/browser/fileapi/sandbox_mount_point_provider.cc @@ -155,7 +155,8 @@ SandboxMountPointProvider::SandboxMountPointProvider( new AsyncFileUtilAdapter( new ObfuscatedFileUtil( special_storage_policy, - profile_path.Append(kFileSystemDirectory)))), + profile_path.Append(kFileSystemDirectory), + file_task_runner))), file_system_usage_cache_(new FileSystemUsageCache(file_task_runner)), quota_observer_(new SandboxQuotaObserver( quota_manager_proxy, |