Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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 "chrome/browser/chromeos/file_manager/snapshot_manager.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/file_util.h" | |
| 9 #include "base/files/file_path.h" | |
| 10 #include "base/sequenced_task_runner.h" | |
| 11 #include "base/sys_info.h" | |
| 12 #include "base/task_runner_util.h" | |
| 13 #include "chrome/browser/chromeos/file_manager/app_id.h" | |
| 14 #include "chrome/browser/chromeos/file_manager/fileapi_util.h" | |
| 15 #include "chrome/browser/profiles/profile.h" | |
| 16 #include "content/public/browser/browser_thread.h" | |
| 17 #include "google_apis/drive/task_util.h" | |
| 18 #include "third_party/cros_system_api/constants/cryptohome.h" | |
| 19 #include "webkit/common/blob/shareable_file_reference.h" | |
| 20 | |
| 21 namespace file_manager { | |
| 22 namespace { | |
| 23 | |
| 24 // Name of the directory for storing the snapshot files under the storage | |
| 25 // partition path. | |
| 26 const base::FilePath::CharType kFileManagerSnapshotDirectoryName[] = | |
| 27 FILE_PATH_LITERAL("FileDialogSnapshot"); | |
| 28 | |
| 29 // Cleans up the specified directory. | |
| 30 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
| |
| 31 base::DeleteFile(directory, true /* recursive */); | |
| 32 } | |
| 33 | |
| 34 // Returns true if there is sufficient disk space in |directory| for file | |
| 35 // |size|. Besides, it heuristically cleans up old files under |directory|. | |
| 36 bool MakeSpaceIfNecessary(const base::FilePath& directory, int64 size) { | |
| 37 int64 free_space = base::SysInfo::AmountOfFreeDiskSpace(directory); | |
| 38 free_space -= cryptohome::kMinFreeSpaceInBytes; | |
| 39 | |
| 40 // TODO(kinaba): clean old snapshot files. | |
| 41 return (size <= free_space); | |
| 42 } | |
| 43 | |
| 44 // Part of CreateManagedSnapshot. Used for retaining |file_ref| until the | |
| 45 // blocking pool job finished. After returning from this function, |file_ref| is | |
| 46 // freed on the IO thread. | |
| 47 void CopyDone( | |
| 48 const SnapshotManager::LocalPathCallback& callback, | |
| 49 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref, | |
| 50 const base::FilePath& local_path) { | |
| 51 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
| 52 callback.Run(local_path); | |
| 53 } | |
| 54 | |
| 55 // Part of CreateManagedSnapshot. | |
| 56 // Copy |path| into |directory| with space management. | |
| 57 base::FilePath CopyOnBlockingPool(const base::FilePath& directory, | |
| 58 const base::FilePath& path) { | |
| 59 base::File::Info info; | |
| 60 base::FilePath copied; | |
| 61 if (!base::GetFileInfo(path, &info) || | |
| 62 !base::CreateDirectory(directory) || | |
| 63 !MakeSpaceIfNecessary(directory, info.size) || | |
| 64 !base::CreateTemporaryFileInDir(directory, &copied) || | |
| 65 !base::CopyFile(path, copied)) { | |
| 66 return base::FilePath(); | |
| 67 } | |
| 68 return copied; | |
| 69 } | |
| 70 | |
| 71 // Part of CreateManagedSnapshot. Copies the created file to a temporary | |
| 72 // path. The snapshot file itself may be removed once |file_ref| is deleted. | |
| 73 void OnCreateSnapshotFile( | |
| 74 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 75 const base::FilePath& base_path, | |
| 76 const SnapshotManager::LocalPathCallback& callback, | |
| 77 base::File::Error result, | |
| 78 const base::File::Info& file_info, | |
| 79 const base::FilePath& platform_path, | |
| 80 const scoped_refptr<webkit_blob::ShareableFileReference>& file_ref) { | |
| 81 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
| 82 | |
| 83 if (result != base::File::FILE_OK) { | |
| 84 callback.Run(base::FilePath()); | |
| 85 return; | |
| 86 } | |
| 87 | |
| 88 base::PostTaskAndReplyWithResult( | |
| 89 task_runner, | |
| 90 FROM_HERE, | |
| 91 base::Bind(&CopyOnBlockingPool, base_path, platform_path), | |
| 92 base::Bind(&CopyDone, callback, file_ref)); | |
| 93 } | |
| 94 | |
| 95 // Part of CreateManagedSnapshot. Runs CreateSnapshotFile method of fileapi. | |
| 96 void CreateSnapshotFileOnIOThread( | |
| 97 scoped_refptr<fileapi::FileSystemContext> context, | |
| 98 scoped_refptr<base::SequencedTaskRunner> task_runner, | |
| 99 const base::FilePath& base_path, | |
| 100 const fileapi::FileSystemURL& url, | |
| 101 const SnapshotManager::LocalPathCallback& callback) { | |
| 102 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | |
| 103 | |
| 104 context->operation_runner()->CreateSnapshotFile( | |
| 105 url, base::Bind(&OnCreateSnapshotFile, task_runner, base_path, callback)); | |
| 106 } | |
| 107 | |
| 108 } // namespace | |
| 109 | |
| 110 SnapshotManager::SnapshotManager(Profile* profile) | |
| 111 : profile_(profile) { | |
| 112 base::SequencedWorkerPool* pool = | |
| 113 content::BrowserThread::GetBlockingPool(); | |
| 114 task_runner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); | |
| 115 } | |
| 116 | |
| 117 SnapshotManager::~SnapshotManager() { | |
| 118 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.
| |
| 119 // Clean up all snapshots in the current run. | |
| 120 task_runner_->PostTask( | |
| 121 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
| |
| 122 } | |
| 123 } | |
| 124 | |
| 125 void SnapshotManager::CreateManagedSnapshot( | |
| 126 const base::FilePath& absolute_file_path, | |
| 127 const LocalPathCallback& callback) { | |
| 128 fileapi::FileSystemContext* context = | |
| 129 util::GetFileSystemContextForExtensionId(profile_, kFileManagerAppId); | |
| 130 DCHECK(context); | |
| 131 | |
| 132 GURL url; | |
| 133 if (!util::ConvertAbsoluteFilePathToFileSystemUrl( | |
| 134 profile_, absolute_file_path, kFileManagerAppId, &url)) { | |
| 135 callback.Run(base::FilePath()); | |
| 136 return; | |
| 137 } | |
| 138 | |
| 139 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
| |
| 140 base_path_ = context->partition_path().Append( | |
| 141 kFileManagerSnapshotDirectoryName); | |
| 142 } | |
| 143 | |
| 144 content::BrowserThread::PostTask( | |
| 145 content::BrowserThread::IO, | |
| 146 FROM_HERE, | |
| 147 base::Bind(&CreateSnapshotFileOnIOThread, | |
| 148 make_scoped_refptr(context), | |
| 149 task_runner_, | |
| 150 base_path_, | |
| 151 context->CrackURL(url), | |
| 152 google_apis::CreateRelayCallback(callback))); | |
| 153 } | |
| 154 | |
| 155 } // namespace file_manager | |
| OLD | NEW |