| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/webshare/prepare_directory_task.h" |
| |
| #include "base/files/file.h" |
| #include "base/files/file_enumerator.h" |
| #include "base/system/sys_info.h" |
| #include "base/task/task_traits.h" |
| #include "base/task/thread_pool.h" |
| #include "base/threading/scoped_blocking_call.h" |
| #include "build/build_config.h" |
| #include "content/public/browser/browser_thread.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include "third_party/cros_system_api/constants/cryptohome.h" |
| #endif |
| |
| using content::BrowserThread; |
| |
| namespace { |
| |
| void DeleteSharedFiles(std::vector<base::FilePath> file_paths) { |
| base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, |
| base::BlockingType::WILL_BLOCK); |
| for (const base::FilePath& name : file_paths) { |
| base::DeletePathRecursively(name); |
| } |
| } |
| |
| } // namespace |
| |
| namespace webshare { |
| |
| constexpr base::TimeDelta PrepareDirectoryTask::kSharedFileLifetime; |
| |
| PrepareDirectoryTask::PrepareDirectoryTask(base::FilePath directory, |
| uint64_t required_space) |
| : directory_(std::move(directory)), required_space_(required_space) {} |
| |
| PrepareDirectoryTask::PrepareDirectoryTask( |
| base::FilePath directory, |
| uint64_t required_space, |
| blink::mojom::ShareService::ShareCallback callback) |
| : directory_(std::move(directory)), |
| required_space_(required_space), |
| callback_(std::move(callback)) {} |
| |
| PrepareDirectoryTask::~PrepareDirectoryTask() = default; |
| |
| void PrepareDirectoryTask::Start() { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| base::ThreadPool::PostTaskAndReplyWithResult( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, |
| base::BindOnce(&PrepareDirectoryTask::PrepareDirectory, directory_, |
| required_space_), |
| base::BindOnce(&PrepareDirectoryTask::OnPrepareDirectory, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void PrepareDirectoryTask::StartWithCallback( |
| PrepareDirectoryCallback callback) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| base::ThreadPool::PostTaskAndReplyWithResult( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, |
| base::BindOnce(&PrepareDirectoryTask::PrepareDirectory, directory_, |
| required_space_), |
| std::move(callback)); |
| } |
| |
| // static |
| void PrepareDirectoryTask::ScheduleSharedFileDeletion( |
| std::vector<base::FilePath> file_paths, |
| base::TimeDelta delay) { |
| base::ThreadPool::PostDelayedTask( |
| FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, |
| base::BindOnce(&DeleteSharedFiles, std::move(file_paths)), delay); |
| } |
| |
| // static |
| base::File::Error PrepareDirectoryTask::PrepareDirectory( |
| base::FilePath directory, |
| uint64_t required_space) { |
| base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, |
| base::BlockingType::WILL_BLOCK); |
| |
| base::File::Error result = base::File::FILE_OK; |
| if (base::CreateDirectoryAndGetError(directory, &result)) { |
| // Delete any old files in |directory|. |
| const base::Time cutoff_time = base::Time::Now() - kSharedFileLifetime; |
| base::FileEnumerator enumerator( |
| directory, /*recursive=*/false, |
| base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES); |
| for (base::FilePath name = enumerator.Next(); !name.empty(); |
| name = enumerator.Next()) { |
| if (enumerator.GetInfo().GetLastModifiedTime() <= cutoff_time) { |
| base::DeletePathRecursively(name); |
| } |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| if (base::SysInfo::AmountOfFreeDiskSpace(directory) < |
| static_cast<int64_t>(cryptohome::kMinFreeSpaceInBytes + |
| required_space)) { |
| #elif BUILDFLAG(IS_MAC) |
| if (base::SysInfo::AmountOfFreeDiskSpace(directory) < |
| static_cast<int64_t>(required_space)) { |
| #else |
| if (false) { |
| #endif |
| result = base::File::FILE_ERROR_NO_SPACE; |
| VLOG(1) << "Insufficient space for sharing files"; |
| } |
| } else { |
| DCHECK(result != base::File::FILE_OK); |
| VLOG(1) << "Could not create directory for shared files"; |
| } |
| |
| return result; |
| } |
| |
| void PrepareDirectoryTask::OnPrepareDirectory(base::File::Error result) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| if (callback_) { |
| std::move(callback_).Run((result == base::File::FILE_OK) |
| ? blink::mojom::ShareError::OK |
| : blink::mojom::ShareError::PERMISSION_DENIED); |
| } |
| } |
| |
| } // namespace webshare |