Commit f861b390 authored by yoshiki@chromium.org's avatar yoshiki@chromium.org

Drive: add a method to clear all local cache.

Mainly, this cl add the two methods to clear cache.
1) GDataCache::ClearAllOnUIThread():
- remove all the files in the cache directory.
- re-create the |metadata_| instance.
2) GDataSystemService::ClearCacheAndReset():
- unmount Drive
- cancel all the running tasks.
- call GDataCache::ClearAllOnUIThread()
- re-mount Drive

BUG=135197
TEST=out/Debug/unit_tests:GData* and out/Debug/browser_tests:GData* passes.

Review URL: https://chromiumcodereview.appspot.com/10823125

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149914 0039d316-1c4b-4281-b951-d872f2087c98
parent faf8f229
...@@ -363,7 +363,7 @@ void FileBrowserEventRouter::MountCompleted( ...@@ -363,7 +363,7 @@ void FileBrowserEventRouter::MountCompleted(
system_service ? system_service->cache() : NULL; system_service ? system_service->cache() : NULL;
if (cache) { if (cache) {
cache->SetMountedStateOnUIThread( cache->SetMountedStateOnUIThread(
source_path, false, gdata::SetMountedStateCallback()); source_path, false, gdata::ChangeCacheStateCallback());
} }
} }
} }
......
...@@ -238,10 +238,10 @@ void CollectAnyFile(std::vector<std::string>* resource_ids, ...@@ -238,10 +238,10 @@ void CollectAnyFile(std::vector<std::string>* resource_ids,
} }
// Runs callback with pointers dereferenced. // Runs callback with pointers dereferenced.
// Used to implement SetMountedStateOnUIThread. // Used to implement SetMountedStateOnUIThread and ClearAllOnUIThread.
void RunSetMountedStateCallback(const SetMountedStateCallback& callback, void RunChangeCacheStateCallback(const ChangeCacheStateCallback& callback,
GDataFileError* error, const GDataFileError* error,
FilePath* cache_file_path) { const FilePath* cache_file_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(error); DCHECK(error);
DCHECK(cache_file_path); DCHECK(cache_file_path);
...@@ -573,7 +573,7 @@ void GDataCache::UnpinOnUIThread(const std::string& resource_id, ...@@ -573,7 +573,7 @@ void GDataCache::UnpinOnUIThread(const std::string& resource_id,
void GDataCache::SetMountedStateOnUIThread( void GDataCache::SetMountedStateOnUIThread(
const FilePath& file_path, const FilePath& file_path,
bool to_mount, bool to_mount,
const SetMountedStateCallback& callback) { const ChangeCacheStateCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
GDataFileError* error = GDataFileError* error =
...@@ -587,7 +587,7 @@ void GDataCache::SetMountedStateOnUIThread( ...@@ -587,7 +587,7 @@ void GDataCache::SetMountedStateOnUIThread(
to_mount, to_mount,
error, error,
cache_file_path), cache_file_path),
base::Bind(&RunSetMountedStateCallback, base::Bind(&RunChangeCacheStateCallback,
callback, callback,
base::Owned(error), base::Owned(error),
base::Owned(cache_file_path))); base::Owned(cache_file_path)));
...@@ -682,6 +682,22 @@ void GDataCache::RemoveOnUIThread(const std::string& resource_id, ...@@ -682,6 +682,22 @@ void GDataCache::RemoveOnUIThread(const std::string& resource_id,
"" /* md5 */)); "" /* md5 */));
} }
void GDataCache::ClearAllOnUIThread(const ChangeCacheStateCallback& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
GDataFileError* error = new GDataFileError(GDATA_FILE_OK);
blocking_task_runner_->PostTaskAndReply(
FROM_HERE,
base::Bind(&GDataCache::ClearAll,
base::Unretained(this),
error),
base::Bind(&RunChangeCacheStateCallback,
callback,
base::Owned(error),
&cache_root_path_));
}
void GDataCache::RequestInitializeOnUIThread() { void GDataCache::RequestInitializeOnUIThread() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
...@@ -1435,6 +1451,16 @@ void GDataCache::Remove(const std::string& resource_id, ...@@ -1435,6 +1451,16 @@ void GDataCache::Remove(const std::string& resource_id,
*error = GDATA_FILE_OK; *error = GDATA_FILE_OK;
} }
void GDataCache::ClearAll(GDataFileError* error) {
AssertOnSequencedWorkerPool();
DCHECK(error);
bool success = file_util::Delete(cache_root_path_, true);
Initialize();
*error = success ? GDATA_FILE_OK : GDATA_FILE_ERROR_FAILED;
}
void GDataCache::OnPinned(GDataFileError* error, void GDataCache::OnPinned(GDataFileError* error,
const std::string& resource_id, const std::string& resource_id,
const std::string& md5, const std::string& md5,
......
...@@ -30,9 +30,10 @@ namespace gdata { ...@@ -30,9 +30,10 @@ namespace gdata {
class GDataCacheEntry; class GDataCacheEntry;
class GDataCacheMetadata; class GDataCacheMetadata;
// Callback for SetMountedStateOnUIThread. // Callback for SetMountedStateOnUIThread and ClearAllOnUIThread.
typedef base::Callback<void(GDataFileError error, typedef base::Callback<void(GDataFileError error,
const FilePath& file_path)> SetMountedStateCallback; const FilePath& file_path)>
ChangeCacheStateCallback;
// Callback for completion of cache operation. // Callback for completion of cache operation.
typedef base::Callback<void(GDataFileError error, typedef base::Callback<void(GDataFileError error,
...@@ -229,7 +230,7 @@ class GDataCache { ...@@ -229,7 +230,7 @@ class GDataCache {
// |dest_path| is the mounted path and |source_path| the unmounted path. // |dest_path| is the mounted path and |source_path| the unmounted path.
void SetMountedStateOnUIThread(const FilePath& file_path, void SetMountedStateOnUIThread(const FilePath& file_path,
bool to_mount, bool to_mount,
const SetMountedStateCallback& callback); const ChangeCacheStateCallback& callback);
// Modifies cache state, which involves the following: // Modifies cache state, which involves the following:
// - moves |source_path| to |dest_path| in persistent dir, where // - moves |source_path| to |dest_path| in persistent dir, where
...@@ -263,6 +264,11 @@ class GDataCache { ...@@ -263,6 +264,11 @@ class GDataCache {
void RemoveOnUIThread(const std::string& resource_id, void RemoveOnUIThread(const std::string& resource_id,
const CacheOperationCallback& callback); const CacheOperationCallback& callback);
// Does the following:
// - remove all the files in the cache directory.
// - re-create the |metadata_| instance.
void ClearAllOnUIThread(const ChangeCacheStateCallback& callback);
// Utility method to call Initialize on UI thread. // Utility method to call Initialize on UI thread.
void RequestInitializeOnUIThread(); void RequestInitializeOnUIThread();
...@@ -396,6 +402,9 @@ class GDataCache { ...@@ -396,6 +402,9 @@ class GDataCache {
void Remove(const std::string& resource_id, void Remove(const std::string& resource_id,
GDataFileError* error); GDataFileError* error);
// Used to implement ClearAllUIThread.
void ClearAll(GDataFileError* error);
// Runs callback and notifies the observers when file is pinned. // Runs callback and notifies the observers when file is pinned.
void OnPinned(GDataFileError* error, void OnPinned(GDataFileError* error,
const std::string& resource_id, const std::string& resource_id,
......
...@@ -113,6 +113,15 @@ void OnGetResourceIds(std::vector<std::string>* out_resource_ids, ...@@ -113,6 +113,15 @@ void OnGetResourceIds(std::vector<std::string>* out_resource_ids,
*out_resource_ids = resource_ids; *out_resource_ids = resource_ids;
} }
// Copies results from ClearAllOnUIThread.
void OnClearAll(GDataFileError* out_error,
FilePath* out_file_path,
GDataFileError error,
const FilePath& file_path) {
*out_file_path = file_path;
*out_error = error;
}
} // namespace } // namespace
class GDataCacheTest : public testing::Test { class GDataCacheTest : public testing::Test {
...@@ -717,6 +726,31 @@ class GDataCacheTest : public testing::Test { ...@@ -717,6 +726,31 @@ class GDataCacheTest : public testing::Test {
EXPECT_EQ(resource_id, unescaped_resource_id); EXPECT_EQ(resource_id, unescaped_resource_id);
} }
// Returns the number of the cache files with name <resource_id>, and Confirm
// that they have the <md5>. This should return 1 or 0.
size_t CountCacheFiles(const std::string& resource_id,
const std::string& md5) {
FilePath path = GetCacheFilePath(
resource_id, "*",
(test_util::ToCacheEntry(expected_cache_state_).is_pinned() ?
GDataCache::CACHE_TYPE_PERSISTENT :
GDataCache::CACHE_TYPE_TMP),
GDataCache::CACHED_FILE_FROM_SERVER);
file_util::FileEnumerator enumerator(path.DirName(), false,
file_util::FileEnumerator::FILES,
path.BaseName().value());
size_t num_files_found = 0;
for (FilePath current = enumerator.Next(); !current.empty();
current = enumerator.Next()) {
++num_files_found;
EXPECT_EQ(util::EscapeCacheFileName(resource_id) +
FilePath::kExtensionSeparator +
util::EscapeCacheFileName(md5),
current.BaseName().value());
}
return num_files_found;
}
static FilePath GetTestFilePath(const FilePath::StringType& filename) { static FilePath GetTestFilePath(const FilePath::StringType& filename) {
FilePath path; FilePath path;
std::string error; std::string error;
...@@ -805,25 +839,7 @@ TEST_F(GDataCacheTest, StoreToCacheSimple) { ...@@ -805,25 +839,7 @@ TEST_F(GDataCacheTest, StoreToCacheSimple) {
// Verify that there's only one file with name <resource_id>, i.e. previously // Verify that there's only one file with name <resource_id>, i.e. previously
// cached file with the different md5 should be deleted. // cached file with the different md5 should be deleted.
FilePath path = GetCacheFilePath( EXPECT_EQ(1U, CountCacheFiles(resource_id, md5));
resource_id, "*",
(test_util::ToCacheEntry(expected_cache_state_).is_pinned() ?
GDataCache::CACHE_TYPE_PERSISTENT :
GDataCache::CACHE_TYPE_TMP),
GDataCache::CACHED_FILE_FROM_SERVER);
file_util::FileEnumerator enumerator(path.DirName(), false,
file_util::FileEnumerator::FILES,
path.BaseName().value());
size_t num_files_found = 0;
for (FilePath current = enumerator.Next(); !current.empty();
current = enumerator.Next()) {
++num_files_found;
EXPECT_EQ(util::EscapeCacheFileName(resource_id) +
FilePath::kExtensionSeparator +
util::EscapeCacheFileName(md5),
current.BaseName().value());
}
EXPECT_EQ(1U, num_files_found);
} }
TEST_F(GDataCacheTest, GetFromCacheSimple) { TEST_F(GDataCacheTest, GetFromCacheSimple) {
...@@ -1461,4 +1477,34 @@ TEST_F(GDataCacheTest, GetResourceIdsOfAllFilesOnUIThread) { ...@@ -1461,4 +1477,34 @@ TEST_F(GDataCacheTest, GetResourceIdsOfAllFilesOnUIThread) {
EXPECT_EQ("tmp:resource_id", resource_ids[5]); EXPECT_EQ("tmp:resource_id", resource_ids[5]);
} }
TEST_F(GDataCacheTest, ClearAllOnUIThread) {
PrepareForInitCacheTest();
std::string resource_id("pdf:1a2b");
std::string md5("abcdef0123456789");
// Store an existing file.
TestStoreToCache(resource_id, md5, GetTestFilePath("root_feed.json"),
GDATA_FILE_OK, test_util::TEST_CACHE_STATE_PRESENT,
GDataCache::CACHE_TYPE_TMP);
EXPECT_EQ(1, num_callback_invocations_);
// Verify that there's only one cached file.
EXPECT_EQ(1U, CountCacheFiles(resource_id, md5));
// Clear cache.
GDataFileError error = GDATA_FILE_OK;
FilePath file_path;
cache_->ClearAllOnUIThread(base::Bind(&OnClearAll,
&error,
&file_path));
test_util::RunBlockingPoolTask();
EXPECT_EQ(GDATA_FILE_OK, error);
// Verify that all the cache is removed.
VerifyRemoveFromCache(error, resource_id, md5);
EXPECT_EQ(0U, CountCacheFiles(resource_id, md5));
}
} // namespace gdata } // namespace gdata
...@@ -40,7 +40,8 @@ const std::string* g_test_cache_root = NULL; ...@@ -40,7 +40,8 @@ const std::string* g_test_cache_root = NULL;
GDataSystemService::GDataSystemService(Profile* profile) GDataSystemService::GDataSystemService(Profile* profile)
: profile_(profile), : profile_(profile),
cache_(NULL) { cache_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool(); base::SequencedWorkerPool* blocking_pool = BrowserThread::GetBlockingPool();
blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner( blocking_task_runner_ = blocking_pool->GetSequencedTaskRunner(
...@@ -106,6 +107,30 @@ void GDataSystemService::Shutdown() { ...@@ -106,6 +107,30 @@ void GDataSystemService::Shutdown() {
documents_service_.reset(); documents_service_.reset();
} }
void GDataSystemService::ClearCacheAndRemountFileSystem(
const base::Callback<void(bool)>& callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RemoveDriveMountPoint();
docs_service()->CancelAll();
cache_->ClearAllOnUIThread(
base::Bind(&GDataSystemService::AddBackDriveMountPoint,
weak_ptr_factory_.GetWeakPtr(),
callback));
}
void GDataSystemService::AddBackDriveMountPoint(
const base::Callback<void(bool)>& callback,
GDataFileError error,
const FilePath& file_path) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
AddDriveMountPoint();
if (!callback.is_null())
callback.Run(error == GDATA_FILE_OK);
}
void GDataSystemService::AddDriveMountPoint() { void GDataSystemService::AddDriveMountPoint() {
if (!gdata::util::IsGDataAvailable(profile_)) if (!gdata::util::IsGDataAvailable(profile_))
return; return;
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/sequenced_worker_pool.h" #include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/chromeos/gdata/gdata_errorcode.h"
#include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h"
...@@ -43,6 +45,11 @@ class GDataSystemService : public ProfileKeyedService { ...@@ -43,6 +45,11 @@ class GDataSystemService : public ProfileKeyedService {
GDataContactsService* contacts_service() { return contacts_service_.get(); } GDataContactsService* contacts_service() { return contacts_service_.get(); }
DriveWebAppsRegistry* webapps_registry() { return webapps_registry_.get(); } DriveWebAppsRegistry* webapps_registry() { return webapps_registry_.get(); }
// Clears all the local cache files and in-memory data, and remounts the file
// system.
void ClearCacheAndRemountFileSystem(
const base::Callback<void(bool)>& callback);
// ProfileKeyedService override: // ProfileKeyedService override:
virtual void Shutdown() OVERRIDE; virtual void Shutdown() OVERRIDE;
...@@ -60,6 +67,11 @@ class GDataSystemService : public ProfileKeyedService { ...@@ -60,6 +67,11 @@ class GDataSystemService : public ProfileKeyedService {
// Unregisters drive mount point from File API. // Unregisters drive mount point from File API.
void RemoveDriveMountPoint(); void RemoveDriveMountPoint();
// Adds back the drive mount point. Used to implement ClearCache().
void AddBackDriveMountPoint(const base::Callback<void(bool)>& callback,
GDataFileError error,
const FilePath& file_path);
friend class GDataSystemServiceFactory; friend class GDataSystemServiceFactory;
Profile* profile_; Profile* profile_;
...@@ -73,6 +85,7 @@ class GDataSystemService : public ProfileKeyedService { ...@@ -73,6 +85,7 @@ class GDataSystemService : public ProfileKeyedService {
scoped_ptr<GDataDownloadObserver> download_observer_; scoped_ptr<GDataDownloadObserver> download_observer_;
scoped_ptr<GDataSyncClient> sync_client_; scoped_ptr<GDataSyncClient> sync_client_;
scoped_ptr<GDataContactsService> contacts_service_; scoped_ptr<GDataContactsService> contacts_service_;
base::WeakPtrFactory<GDataSystemService> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(GDataSystemService); DISALLOW_COPY_AND_ASSIGN(GDataSystemService);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment