blob: 27d74dfd560136acc48b61e024ddd59354be5e9d [file] [log] [blame]
// Copyright 2020 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 "weblayer/browser/persistence/browser_persister_file_utils.h"
#include "base/cxx17_backports.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "components/base32/base32.h"
#include "components/sessions/core/command_storage_backend.h"
#include "components/sessions/core/session_constants.h"
#include "content/public/browser/browser_thread.h"
#include "weblayer/browser/browser_impl.h"
#include "weblayer/browser/browser_list.h"
#include "weblayer/browser/profile_impl.h"
namespace weblayer {
namespace {
bool RemoveBrowserPersistenceStorageOnBackgroundThread(
const base::FilePath& path,
base::flat_set<std::string> ids) {
DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
bool all_succeeded = true;
for (const std::string& id : ids) {
DCHECK(!id.empty());
// Original persistence path.
const base::FilePath persistence_path =
BuildBasePathForBrowserPersister(path, id);
if (!base::DeleteFile(persistence_path))
all_succeeded = false;
// Remove persistence paths with timestamps.
auto paths = sessions::CommandStorageBackend::GetSessionFilePaths(
persistence_path, sessions::CommandStorageManager::kOther);
for (const auto& path : paths) {
if (!base::DeleteFile(path))
all_succeeded = false;
}
}
return all_succeeded;
}
} // namespace
base::flat_set<std::string> GetBrowserPersistenceIdsOnBackgroundThread(
const base::FilePath& path) {
DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
base::flat_set<std::string> ids;
base::FilePath matching_path = base::FilePath().AppendASCII(
std::string(BrowserImpl::kPersistenceFilePrefix) + std::string("*"));
base::FileEnumerator iter(path, /* recursive */ false,
base::FileEnumerator::FILES, matching_path.value());
for (base::FilePath name = iter.Next(); !name.empty(); name = iter.Next()) {
// The name is base32 encoded, which is ascii.
const std::string base_name = iter.GetInfo().GetName().MaybeAsASCII();
if (base_name.size() <= base::size(BrowserImpl::kPersistenceFilePrefix))
continue;
const std::string encoded_id_and_timestamp =
base_name.substr(base::size(BrowserImpl::kPersistenceFilePrefix) - 1);
const size_t separator_index = encoded_id_and_timestamp.find(
base::FilePath(sessions::kTimestampSeparator).MaybeAsASCII());
const std::string encoded_id =
separator_index == std::string::npos
? encoded_id_and_timestamp
: encoded_id_and_timestamp.substr(0, separator_index);
const std::string decoded_id = base32::Base32Decode(encoded_id);
if (!decoded_id.empty() && ids.count(decoded_id) == 0 &&
sessions::CommandStorageBackend::IsValidFile(name)) {
ids.insert(decoded_id);
}
}
return ids;
}
base::FilePath BuildBasePathForBrowserPersister(
const base::FilePath& profile_path,
const std::string& browser_id) {
DCHECK(!browser_id.empty());
const std::string encoded_name = base32::Base32Encode(browser_id);
return profile_path.AppendASCII(BrowserImpl::kPersistenceFilePrefix +
encoded_name);
}
void RemoveBrowserPersistenceStorageImpl(
ProfileImpl* profile,
base::OnceCallback<void(bool)> done_callback,
base::flat_set<std::string> ids) {
// Remove any ids that are actively in use.
for (BrowserImpl* browser : BrowserList::GetInstance()->browsers()) {
if (browser->profile() == profile)
ids.erase(browser->GetPersistenceId());
}
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&RemoveBrowserPersistenceStorageOnBackgroundThread,
profile->GetBrowserPersisterDataBaseDir(), std::move(ids)),
std::move(done_callback));
}
} // namespace weblayer