Chromium Code Reviews| Index: chrome/browser/chromeos/file_manager/snapshot_manager.cc |
| diff --git a/chrome/browser/chromeos/file_manager/snapshot_manager.cc b/chrome/browser/chromeos/file_manager/snapshot_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..452eaec1c82d12241cb674a7888bf4fbe350f11a |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/file_manager/snapshot_manager.cc |
| @@ -0,0 +1,155 @@ |
| +// Copyright 2014 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 "chrome/browser/chromeos/file_manager/snapshot_manager.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/file_util.h" |
| +#include "base/files/file_path.h" |
| +#include "base/sequenced_task_runner.h" |
| +#include "base/sys_info.h" |
| +#include "base/task_runner_util.h" |
| +#include "chrome/browser/chromeos/file_manager/app_id.h" |
| +#include "chrome/browser/chromeos/file_manager/fileapi_util.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "google_apis/drive/task_util.h" |
| +#include "third_party/cros_system_api/constants/cryptohome.h" |
| +#include "webkit/common/blob/shareable_file_reference.h" |
| + |
| +namespace file_manager { |
| +namespace { |
| + |
| +// Name of the directory for storing the snapshot files under the storage |
| +// partition path. |
| +const base::FilePath::CharType kFileManagerSnapshotDirectoryName[] = |
| + FILE_PATH_LITERAL("FileDialogSnapshot"); |
| + |
| +// Cleans up the specified directory. |
| +void DeleteDirectory(const base::FilePath& directory) { |
|
hashimoto
2014/06/19 02:26:01
nit: What is the point of having this function ins
kinaba
2014/06/19 04:41:56
Good catch. Removed.
(Actually I hadn't been able
|
| + base::DeleteFile(directory, true /* recursive */); |
| +} |
| + |
| +// Returns true if there is sufficient disk space in |directory| for file |
| +// |size|. Besides, it heuristically cleans up old files under |directory|. |
| +bool MakeSpaceIfNecessary(const base::FilePath& directory, int64 size) { |
| + int64 free_space = base::SysInfo::AmountOfFreeDiskSpace(directory); |
| + free_space -= cryptohome::kMinFreeSpaceInBytes; |
| + |
| + // TODO(kinaba): clean old snapshot files. |
| + return (size <= free_space); |
| +} |
| + |
| +// Part of CreateManagedSnapshot. Used for retaining |file_ref| until the |
| +// blocking pool job finished. After returning from this function, |file_ref| is |
| +// freed on the IO thread. |
| +void CopyDone( |
| + const SnapshotManager::LocalPathCallback& callback, |
| + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, |
| + const base::FilePath& local_path) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| + callback.Run(local_path); |
| +} |
| + |
| +// Part of CreateManagedSnapshot. |
| +// Copy |path| into |directory| with space management. |
| +base::FilePath CopyOnBlockingPool(const base::FilePath& directory, |
| + const base::FilePath& path) { |
| + base::File::Info info; |
| + base::FilePath copied; |
| + if (!base::GetFileInfo(path, &info) || |
| + !base::CreateDirectory(directory) || |
| + !MakeSpaceIfNecessary(directory, info.size) || |
| + !base::CreateTemporaryFileInDir(directory, &copied) || |
| + !base::CopyFile(path, copied)) { |
| + return base::FilePath(); |
| + } |
| + return copied; |
| +} |
| + |
| +// Part of CreateManagedSnapshot. Copies the created file to a temporary |
| +// path. The snapshot file itself may be removed once |file_ref| is deleted. |
| +void OnCreateSnapshotFile( |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| + const base::FilePath& base_path, |
| + const SnapshotManager::LocalPathCallback& callback, |
| + base::File::Error result, |
| + const base::File::Info& file_info, |
| + const base::FilePath& platform_path, |
| + const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| + |
| + if (result != base::File::FILE_OK) { |
| + callback.Run(base::FilePath()); |
| + return; |
| + } |
| + |
| + base::PostTaskAndReplyWithResult( |
| + task_runner, |
| + FROM_HERE, |
| + base::Bind(&CopyOnBlockingPool, base_path, platform_path), |
| + base::Bind(&CopyDone, callback, file_ref)); |
| +} |
| + |
| +// Part of CreateManagedSnapshot. Runs CreateSnapshotFile method of fileapi. |
| +void CreateSnapshotFileOnIOThread( |
| + scoped_refptr<fileapi::FileSystemContext> context, |
| + scoped_refptr<base::SequencedTaskRunner> task_runner, |
| + const base::FilePath& base_path, |
| + const fileapi::FileSystemURL& url, |
| + const SnapshotManager::LocalPathCallback& callback) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
| + |
| + context->operation_runner()->CreateSnapshotFile( |
| + url, base::Bind(&OnCreateSnapshotFile, task_runner, base_path, callback)); |
| +} |
| + |
| +} // namespace |
| + |
| +SnapshotManager::SnapshotManager(Profile* profile) |
| + : profile_(profile) { |
| + base::SequencedWorkerPool* pool = |
| + content::BrowserThread::GetBlockingPool(); |
| + task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); |
| +} |
| + |
| +SnapshotManager::~SnapshotManager() { |
| + if (task_runner_ && !base_path_.empty()) { |
|
hashimoto
2014/06/19 02:26:01
nit: In which case task_runner_ becomes NULL?
kinaba
2014/06/19 04:41:56
Never.
|
| + // Clean up all snapshots in the current run. |
| + task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&DeleteDirectory, base_path_)); |
|
hashimoto
2014/06/19 02:26:01
I don't remember in which order objects are destru
kinaba
2014/06/19 04:41:56
It is still alive at this point (profile destructi
|
| + } |
| +} |
| + |
| +void SnapshotManager::CreateManagedSnapshot( |
| + const base::FilePath& absolute_file_path, |
| + const LocalPathCallback& callback) { |
| + fileapi::FileSystemContext* context = |
| + util::GetFileSystemContextForExtensionId(profile_, kFileManagerAppId); |
| + DCHECK(context); |
| + |
| + GURL url; |
| + if (!util::ConvertAbsoluteFilePathToFileSystemUrl( |
| + profile_, absolute_file_path, kFileManagerAppId, &url)) { |
| + callback.Run(base::FilePath()); |
| + return; |
| + } |
| + |
| + if (base_path_.empty()) { |
|
hashimoto
2014/06/19 02:26:01
nit: Why can't this be initialized in the ctor?
kinaba
2014/06/19 04:41:56
StorageParition/FileSystemContext related part is
|
| + base_path_ = context->partition_path().Append( |
| + kFileManagerSnapshotDirectoryName); |
| + } |
| + |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::IO, |
| + FROM_HERE, |
| + base::Bind(&CreateSnapshotFileOnIOThread, |
| + make_scoped_refptr(context), |
| + task_runner_, |
| + base_path_, |
| + context->CrackURL(url), |
| + google_apis::CreateRelayCallback(callback))); |
| +} |
| + |
| +} // namespace file_manager |