// 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/ash/extensions/file_manager/private_api_holding_space.h"
#include <memory>
#include <vector>
#include "ash/constants/ash_features.h"
#include "ash/public/cpp/holding_space/holding_space_metrics.h"
#include "base/feature_list.h"
#include "base/memory/ref_counted.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service.h"
#include "chrome/browser/ui/ash/holding_space/holding_space_keyed_service_factory.h"
#include "chrome/common/extensions/api/file_manager_private.h"
#include "chrome/common/extensions/api/file_manager_private_internal.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
#include "chromeos/ash/components/file_manager/indexing/file_index.h"
#include "chromeos/ash/components/file_manager/indexing/file_index_service.h"
#include "chromeos/ash/components/file_manager/indexing/file_index_service_registry.h"
#include "chromeos/ash/components/file_manager/indexing/file_info.h"
#include "chromeos/ash/components/file_manager/indexing/term.h"
#include "components/user_manager/user_manager.h"
#include "storage/browser/file_system/file_system_context.h"
#include "storage/browser/file_system/file_system_url.h"
#include "url/gurl.h"
namespace extensions {
FileManagerPrivateInternalToggleAddedToHoldingSpaceFunction::
FileManagerPrivateInternalToggleAddedToHoldingSpaceFunction() = default;
FileManagerPrivateInternalToggleAddedToHoldingSpaceFunction::
~FileManagerPrivateInternalToggleAddedToHoldingSpaceFunction() = default;
ExtensionFunction::ResponseAction
FileManagerPrivateInternalToggleAddedToHoldingSpaceFunction::Run() {
using extensions::api::file_manager_private_internal::
ToggleAddedToHoldingSpace::Params;
const std::optional<Params> params = Params::Create(args());
EXTENSION_FUNCTION_VALIDATE(params);
ash::HoldingSpaceKeyedService* const holding_space =
ash::HoldingSpaceKeyedServiceFactory::GetInstance()->GetService(
browser_context());
if (!holding_space) {
return RespondNow(Error("Not enabled"));
}
const user_manager::User* user =
ash::BrowserContextHelper::Get()->GetUserByBrowserContext(
browser_context());
scoped_refptr<storage::FileSystemContext> file_system_context =
file_manager::util::GetFileSystemContextForRenderFrameHost(
Profile::FromBrowserContext(browser_context()), render_frame_host());
std::vector<storage::FileSystemURL> file_system_urls;
for (const auto& item_url : params->urls) {
const storage::FileSystemURL file_system_url =
file_system_context->CrackURLInFirstPartyContext(GURL(item_url));
if (!file_system_url.is_valid()) {
return RespondNow(Error("Invalid item URL " + item_url));
}
file_system_urls.push_back(file_system_url);
}
if (params->add) {
std::erase_if(
file_system_urls,
[holding_space](const storage::FileSystemURL& file_system_url) {
return holding_space->ContainsPinnedFile(file_system_url);
});
holding_space->AddPinnedFiles(
file_system_urls, ash::holding_space_metrics::EventSource::kFilesApp);
} else {
std::erase_if(
file_system_urls,
[holding_space](const storage::FileSystemURL& file_system_url) {
return !holding_space->ContainsPinnedFile(file_system_url);
});
holding_space->RemovePinnedFiles(
file_system_urls, ash::holding_space_metrics::EventSource::kFilesApp);
}
// Also send the data to the File Index.
if (base::FeatureList::IsEnabled(ash::features::kFilesMaterializedViews)) {
// TODO(b/327534188): Use the MaterializedViews API.
auto* registry = ::ash::file_manager::FileIndexServiceRegistry::Get();
::ash::file_manager::FileIndexService* index =
registry ? registry->GetFileIndexService(user->GetAccountId())
: nullptr;
if (index) {
::ash::file_manager::Term starred("label", u"starred");
if (params->add) {
for (const auto& url : file_system_urls) {
::ash::file_manager::FileInfo info(url.ToGURL(), 0, base::Time());
LOG(ERROR) << "Adding terms: " << starred.token()
<< " url: " << url.ToGURL().spec();
index->PutFileInfo(
info,
base::BindOnce(
[](::ash::file_manager::FileIndexService* index,
const storage::FileSystemURL& url,
const ::ash::file_manager::Term& term,
::ash::file_manager::OpResults r) {
index->AddTerms(
{term}, url.ToGURL(),
base::BindOnce([](::ash::file_manager::OpResults r) {
LOG(ERROR) << "result: " << r;
}));
},
index, url, starred));
}
} else {
for (const auto& url : file_system_urls) {
LOG(ERROR) << "Removing terms: " << starred.token()
<< " url: " << url.ToGURL().spec();
index->RemoveTerms(
{starred}, url.ToGURL(),
base::BindOnce([](::ash::file_manager::OpResults r) {
LOG(ERROR) << "result: " << r;
}));
}
}
}
}
return RespondNow(NoArguments());
}
FileManagerPrivateGetHoldingSpaceStateFunction::
FileManagerPrivateGetHoldingSpaceStateFunction() = default;
FileManagerPrivateGetHoldingSpaceStateFunction::
~FileManagerPrivateGetHoldingSpaceStateFunction() = default;
ExtensionFunction::ResponseAction
FileManagerPrivateGetHoldingSpaceStateFunction::Run() {
ash::HoldingSpaceKeyedService* const holding_space =
ash::HoldingSpaceKeyedServiceFactory::GetInstance()->GetService(
browser_context());
if (!holding_space) {
return RespondNow(Error("Not enabled"));
}
std::vector<GURL> items = holding_space->GetPinnedFiles();
api::file_manager_private::HoldingSpaceState holding_space_state;
for (const auto& item : items) {
holding_space_state.item_urls.push_back(item.spec());
}
if (base::FeatureList::IsEnabled(ash::features::kFilesMaterializedViews)) {
const user_manager::User* user =
ash::BrowserContextHelper::Get()->GetUserByBrowserContext(
browser_context());
auto* registry = ::ash::file_manager::FileIndexServiceRegistry::Get();
::ash::file_manager::FileIndexService* index =
registry ? registry->GetFileIndexService(user->GetAccountId())
: nullptr;
if (!index) {
LOG(ERROR) << "Couldn't get the file index";
} else {
::ash::file_manager::Term starred("label", u"starred");
::ash::file_manager::Query q({starred});
index->Search(
q,
base::BindOnce(
&FileManagerPrivateGetHoldingSpaceStateFunction::OnSearchResult,
this));
return RespondLater();
}
}
return RespondNow(ArgumentList(
api::file_manager_private::GetHoldingSpaceState::Results::Create(
holding_space_state)));
}
void FileManagerPrivateGetHoldingSpaceStateFunction::OnSearchResult(
::ash::file_manager::SearchResults result) {
api::file_manager_private::HoldingSpaceState holding_space_state;
for (const auto& m : result.matches) {
holding_space_state.item_urls.push_back(m.file_info.file_url.spec());
}
Respond(ArgumentList(
api::file_manager_private::GetHoldingSpaceState::Results::Create(
holding_space_state)));
}
} // namespace extensions