0

ash: More Lacros-related app_service cleanup

Based on the previous CL in this chain, we can now remove the remaining
crosapi definitions in app_service.mojom and app_service_types.mojom and
any implementations and support code. In particular, the removal of
OnPreferredAppsChanged (AppServiceSubscriber) lets us do some further
simplications.

Bug: b:365741912, b:365902693
Change-Id: I44ac207e1c0d87b1a1d3babb2d173f5d470b06fe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6238183
Reviewed-by: Hidehiko Abe <hidehiko@chromium.org>
Reviewed-by: Tim Sergeant <tsergeant@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Reviewed-by: Di Wu <diwux@google.com>
Cr-Commit-Position: refs/heads/main@{#1417955}
This commit is contained in:
Georg Neis
2025-02-09 19:34:08 -08:00
committed by Chromium LUCI CQ
parent 3dd3043232
commit be52349273
24 changed files with 3 additions and 5095 deletions

@ -56,9 +56,7 @@
#include "chromeos/ash/experiences/arc/intent_helper/intent_filter.h"
#include "chromeos/ash/experiences/arc/mojom/intent_helper.mojom-shared.h"
#include "chromeos/ash/experiences/arc/mojom/intent_helper.mojom.h"
#include "chromeos/crosapi/mojom/app_service_types.mojom.h"
#include "extensions/common/manifest_handlers/action_handlers_handler.h"
#include "net/base/filename_util.h"
#include "storage/browser/file_system/file_system_url.h"
#endif // BUILDFLAG(IS_CHROMEOS)
@ -848,129 +846,6 @@ apps::IntentFilterPtr CreateIntentFilterForArc(
return intent_filter;
}
crosapi::mojom::IntentPtr ConvertAppServiceToCrosapiIntent(
const apps::IntentPtr& app_service_intent,
Profile* profile) {
auto crosapi_intent = crosapi::mojom::Intent::New();
crosapi_intent->action = app_service_intent->action;
if (app_service_intent->url.has_value()) {
crosapi_intent->url = app_service_intent->url.value();
}
if (app_service_intent->mime_type.has_value()) {
crosapi_intent->mime_type = app_service_intent->mime_type.value();
}
if (app_service_intent->share_text.has_value()) {
crosapi_intent->share_text = app_service_intent->share_text.value();
}
if (app_service_intent->share_title.has_value()) {
crosapi_intent->share_title = app_service_intent->share_title.value();
}
if (!app_service_intent->files.empty() && profile) {
std::vector<crosapi::mojom::IntentFilePtr> crosapi_files;
for (const auto& file : app_service_intent->files) {
if (file->url.SchemeIsFile()) {
auto crosapi_file = crosapi::mojom::IntentFile::New();
net::FileURLToFilePath(file->url, &crosapi_file->file_path);
crosapi_file->mime_type = file->mime_type;
crosapi_files.push_back(std::move(crosapi_file));
} else if (file->url.SchemeIsFileSystem()) {
auto file_system_url = apps::GetFileSystemURL(profile, file->url);
if (file_system_url.is_valid()) {
base::FilePath path =
file_system_url.TypeImpliesPathIsReal()
? file_system_url.path()
: fusebox::Server::SubstituteFuseboxFilePath(file_system_url);
if (!path.empty()) {
auto crosapi_file = crosapi::mojom::IntentFile::New();
crosapi_file->file_path = std::move(path);
crosapi_file->mime_type = file->mime_type;
crosapi_files.push_back(std::move(crosapi_file));
}
}
}
}
crosapi_intent->files = std::move(crosapi_files);
}
if (app_service_intent->activity_name.has_value()) {
crosapi_intent->activity_name = app_service_intent->activity_name.value();
}
if (app_service_intent->data.has_value()) {
crosapi_intent->data = app_service_intent->data.value();
}
if (app_service_intent->ui_bypassed.has_value()) {
crosapi_intent->ui_bypassed = app_service_intent->ui_bypassed.value();
}
if (!app_service_intent->extras.empty()) {
crosapi_intent->extras = app_service_intent->extras;
}
return crosapi_intent;
}
apps::IntentPtr CreateAppServiceIntentFromCrosapi(
const crosapi::mojom::IntentPtr& crosapi_intent,
Profile* profile) {
auto app_service_intent =
std::make_unique<apps::Intent>(crosapi_intent->action);
if (crosapi_intent->url.has_value()) {
app_service_intent->url = crosapi_intent->url.value();
}
if (crosapi_intent->mime_type.has_value()) {
app_service_intent->mime_type = crosapi_intent->mime_type.value();
}
if (crosapi_intent->share_text.has_value()) {
app_service_intent->share_text = crosapi_intent->share_text.value();
}
if (crosapi_intent->share_title.has_value()) {
app_service_intent->share_title = crosapi_intent->share_title.value();
}
if (crosapi_intent->files.has_value() && profile) {
std::vector<apps::IntentFilePtr> intent_files;
for (const auto& file : crosapi_intent->files.value()) {
auto file_url = apps::GetFileSystemUrl(profile, file->file_path);
if (file_url.is_empty()) {
continue;
}
auto intent_file = std::make_unique<apps::IntentFile>(file_url);
intent_file->mime_type = file->mime_type;
intent_files.push_back(std::move(intent_file));
}
if (intent_files.size() > 0) {
app_service_intent->files = std::move(intent_files);
}
}
if (crosapi_intent->activity_name.has_value()) {
app_service_intent->activity_name = crosapi_intent->activity_name.value();
}
if (crosapi_intent->data.has_value()) {
app_service_intent->data = crosapi_intent->data.value();
}
if (crosapi_intent->ui_bypassed.has_value()) {
app_service_intent->ui_bypassed = crosapi_intent->ui_bypassed.value();
}
if (crosapi_intent->extras.has_value()) {
app_service_intent->extras = crosapi_intent->extras.value();
}
return app_service_intent;
}
crosapi::mojom::IntentPtr CreateCrosapiIntentForViewFiles(
std::vector<base::FilePath> file_paths) {
auto intent = crosapi::mojom::Intent::New();
intent->action = kIntentActionView;
std::vector<crosapi::mojom::IntentFilePtr> crosapi_files;
for (const auto& file_path : file_paths) {
auto crosapi_file = crosapi::mojom::IntentFile::New();
crosapi_file->file_path = file_path;
crosapi_files.push_back(std::move(crosapi_file));
}
intent->files = std::move(crosapi_files);
return intent;
}
#endif // BUILDFLAG(IS_CHROMEOS)
} // namespace apps_util

@ -16,7 +16,6 @@
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/ash/experiences/arc/mojom/intent_helper.mojom-forward.h"
#include "chromeos/crosapi/mojom/app_service_types.mojom-forward.h"
namespace arc {
class ArcIntentHelperBridge;
@ -116,37 +115,8 @@ arc::IntentFilter ConvertAppServiceToArcIntentFilter(
// nullptr if the intent filter from ARC is not valid.
apps::IntentFilterPtr CreateIntentFilterForArc(
const arc::IntentFilter& arc_intent_filter);
// Convert App Service Intent to Crosapi Intent.
// |profile| is only needed when the intent contains files, can be filled with
// null otherwise.
// If |profile| is null when converting intent contains files, the files
// fields will not be converted.
// TODO(crbug.com/40199088): Needs manual conversion rather than mojom traits
// because Lacros does not support FileSystemURL as Ash, this method can be
// replaced with mojom traits after migrating the App Service Intent to use the
// file path.
crosapi::mojom::IntentPtr ConvertAppServiceToCrosapiIntent(
const apps::IntentPtr& app_service_intent,
Profile* profile);
// Convert Crosapi Intent to App Service Intent. Note that the converted App
// Service Intent will not contain the files field in lacros-chrome.
// |profile| is only needed when the intent contains files, can be filled with
// null otherwise.
// If |profile| is null when converting intent contains files, the files
// fields will not be converted.
// TODO(crbug.com/40199088): Needs manual conversion rather than mojom traits
// because Lacros does not support FileSystemURL as Ash, this method can be
// replaced with mojom traits after migrating the App Service Intent to use the
// file path.
apps::IntentPtr CreateAppServiceIntentFromCrosapi(
const crosapi::mojom::IntentPtr& crosapi_intent,
Profile* profile);
crosapi::mojom::IntentPtr CreateCrosapiIntentForViewFiles(
std::vector<base::FilePath> file_paths);
#endif // BUILDFLAG(IS_CHROMEOS)
} // namespace apps_util
#endif // CHROME_BROWSER_APPS_APP_SERVICE_INTENT_UTIL_H_

@ -17,7 +17,6 @@
#include "base/test/scoped_feature_list.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/ash/file_manager/fileapi_util.h"
#include "chrome/browser/web_applications/test/web_app_test_utils.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chromeos/ash/experiences/arc/intent_helper/intent_constants.h"
@ -35,25 +34,11 @@
#include "url/gurl.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "base/strings/strcat.h"
#include "chrome/browser/ash/file_manager/path_util.h"
#include "chrome/browser/ash/fusebox/fusebox_server.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/ash/experiences/arc/mojom/intent_common.mojom.h"
#include "chromeos/ash/experiences/arc/mojom/intent_helper.mojom.h"
#include "chromeos/crosapi/mojom/app_service_types.mojom.h"
#include "content/public/test/browser_task_environment.h"
#include "extensions/common/extension.h"
#include "net/base/filename_util.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/common/file_system/file_system_mount_option.h"
#include "storage/common/file_system/file_system_types.h"
#include "storage/common/file_system/file_system_util.h"
#include "url/origin.h"
#include "url/url_constants.h"
class TestingProfile;
#endif // BUILDFLAG(IS_CHROMEOS)
using apps::Condition;
@ -825,205 +810,4 @@ TEST_F(IntentUtilsTest, ConvertArcIntentFilter_ReturnskFile) {
}
}
}
TEST_F(IntentUtilsTest, CrosapiIntentConversion) {
apps::IntentPtr original_intent = std::make_unique<apps::Intent>(
apps_util::kIntentActionView, GURL("www.google.com"));
auto crosapi_intent =
apps_util::ConvertAppServiceToCrosapiIntent(original_intent, nullptr);
auto converted_intent =
apps_util::CreateAppServiceIntentFromCrosapi(crosapi_intent, nullptr);
EXPECT_EQ(*original_intent, *converted_intent);
original_intent = apps_util::MakeShareIntent("text", "title");
crosapi_intent =
apps_util::ConvertAppServiceToCrosapiIntent(original_intent, nullptr);
converted_intent =
apps_util::CreateAppServiceIntentFromCrosapi(crosapi_intent, nullptr);
EXPECT_EQ(*original_intent, *converted_intent);
original_intent =
std::make_unique<apps::Intent>(apps_util::kIntentActionView);
original_intent->data = "geo:0,0?q=1600%20amphitheatre%20parkway";
crosapi_intent =
apps_util::ConvertAppServiceToCrosapiIntent(original_intent, nullptr);
converted_intent =
apps_util::CreateAppServiceIntentFromCrosapi(crosapi_intent, nullptr);
EXPECT_EQ(*original_intent, *converted_intent);
// Test intent with all params (except for files) filled in at once.
// `files` param requires profile which is null in this unit test.
original_intent = std::make_unique<apps::Intent>(apps_util::kIntentActionView,
GURL("www.google.com"));
original_intent->share_text = "text";
original_intent->share_title = "title";
original_intent->activity_name = "com.android.vending.AssetBrowserActivity";
original_intent->data = "geo:0,0?q=1600%20amphitheatre%20parkway";
original_intent->ui_bypassed = true;
original_intent->extras = base::flat_map<std::string, std::string>{
{"android.intent.extra.TESTING", "testing"}};
crosapi_intent =
apps_util::ConvertAppServiceToCrosapiIntent(original_intent, nullptr);
converted_intent =
apps_util::CreateAppServiceIntentFromCrosapi(crosapi_intent, nullptr);
EXPECT_EQ(*original_intent, *converted_intent);
}
class IntentUtilsFileTest : public ::testing::Test {
public:
void SetUp() override {
testing::Test::SetUp();
profile_manager_ = std::make_unique<TestingProfileManager>(
TestingBrowserProcess::GetGlobal());
ASSERT_TRUE(profile_manager_->SetUp());
profile_ = profile_manager_->CreateTestingProfile("testing_profile");
// kFileSystemTypeLocal versus kFileSystemTypeArcContent means that the
// second one needs to go through Fusebox, as its
// FileSystemURL::TypeImpliesPathIsReal() returns false.
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
mount_name_local_, storage::FileSystemType::kFileSystemTypeLocal,
storage::FileSystemMountOption(), base::FilePath(fs_root_local_)));
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
mount_name_arc_, storage::kFileSystemTypeArcContent,
storage::FileSystemMountOption(), base::FilePath(fs_root_arc_)));
}
void TearDown() override {
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
mount_name_arc_));
ASSERT_TRUE(
storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
mount_name_local_));
profile_manager_->DeleteAllTestingProfiles();
profile_ = nullptr;
profile_manager_.reset();
}
TestingProfile* GetProfile() { return profile_; }
// FileUtils explicitly relies on ChromeOS Files.app for files manipulation.
const url::Origin GetFileManagerOrigin() {
return url::Origin::Create(file_manager::util::GetFileManagerURL());
}
// For a given |root| converts the given virtual |path| to a GURL.
GURL ToGURL(const base::FilePath& root, const std::string& path) {
const std::string abs_path = root.Append(path).value();
return GURL(base::StrCat({url::kFileSystemScheme, ":",
GetFileManagerOrigin().Serialize(), abs_path}));
}
protected:
const std::string mount_name_arc_ = "TestMountNameArc";
const std::string mount_name_local_ = "TestMountNameLocal";
const std::string fs_root_arc_ = "/fake/android/content/path";
const std::string fs_root_local_ = "/path/to/test/filesystemroot";
private:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<TestingProfileManager> profile_manager_;
raw_ptr<TestingProfile, DanglingUntriaged> profile_;
};
class IntentUtilsFileSystemSchemeTest
: public IntentUtilsFileTest,
public ::testing::WithParamInterface<storage::FileSystemType> {};
TEST_P(IntentUtilsFileSystemSchemeTest, ConvertFileSystemScheme) {
constexpr char fusebox_subdir[] = "my_subdir";
constexpr bool read_only = false;
fusebox::Server fusebox_server(nullptr);
fusebox_server.RegisterFSURLPrefix(
fusebox_subdir,
base::StrCat({url::kFileSystemScheme, ":",
GetFileManagerOrigin().Serialize(), storage::kExternalDir,
"/", mount_name_arc_}),
read_only);
base::FilePath in_path;
base::FilePath out_path;
switch (GetParam()) {
case storage::kFileSystemTypeLocal:
in_path = base::FilePath(storage::kExternalDir).Append(mount_name_local_);
out_path = base::FilePath(fs_root_local_);
break;
case storage::kFileSystemTypeArcContent:
in_path = base::FilePath(storage::kExternalDir).Append(mount_name_arc_);
out_path = base::FilePath(file_manager::util::kFuseBoxMediaPath)
.Append(fusebox_subdir);
break;
default:
NOTREACHED();
}
auto app_service_intent = std::make_unique<apps::Intent>("action");
app_service_intent->mime_type = "*/*";
const std::string relative_path = "Documents/foo.txt";
const std::string mime_type = "text/plain";
auto url = ToGURL(in_path, relative_path);
EXPECT_TRUE(url.SchemeIsFileSystem());
app_service_intent->files = std::vector<apps::IntentFilePtr>{};
auto file = std::make_unique<apps::IntentFile>(url);
file->mime_type = mime_type;
app_service_intent->files.push_back(std::move(file));
auto crosapi_intent = apps_util::ConvertAppServiceToCrosapiIntent(
app_service_intent, GetProfile());
EXPECT_EQ(app_service_intent->action, crosapi_intent->action);
EXPECT_EQ(app_service_intent->mime_type, crosapi_intent->mime_type);
ASSERT_TRUE(crosapi_intent->files.has_value());
ASSERT_EQ(crosapi_intent->files.value().size(), 1U);
EXPECT_EQ(crosapi_intent->files.value()[0]->file_path,
out_path.Append(base::FilePath(relative_path)));
EXPECT_EQ(crosapi_intent->files.value()[0]->mime_type, mime_type);
}
INSTANTIATE_TEST_SUITE_P(
IntentUtilsFileSystemScheme,
IntentUtilsFileSystemSchemeTest,
testing::ValuesIn({storage::kFileSystemTypeLocal,
storage::kFileSystemTypeArcContent}));
TEST_F(IntentUtilsFileTest, ConvertFileScheme) {
auto app_service_intent = std::make_unique<apps::Intent>("action");
app_service_intent->mime_type = "*/*";
base::FilePath path("/path/to/document.txt");
const std::string mime_type = "text/plain";
auto url = net::FilePathToFileURL(path);
EXPECT_TRUE(url.SchemeIsFile());
app_service_intent->files = std::vector<apps::IntentFilePtr>{};
auto file = std::make_unique<apps::IntentFile>(url);
file->mime_type = mime_type;
app_service_intent->files.push_back(std::move(file));
auto crosapi_intent = apps_util::ConvertAppServiceToCrosapiIntent(
app_service_intent, GetProfile());
EXPECT_EQ(app_service_intent->action, crosapi_intent->action);
EXPECT_EQ(app_service_intent->mime_type, crosapi_intent->mime_type);
ASSERT_TRUE(crosapi_intent->files.has_value());
ASSERT_EQ(crosapi_intent->files.value().size(), 1U);
EXPECT_EQ(crosapi_intent->files.value()[0]->file_path, path);
EXPECT_EQ(crosapi_intent->files.value()[0]->mime_type, mime_type);
}
TEST_F(IntentUtilsFileTest, CrosapiIntentToAppService) {
const std::string path = "Documents/foo.txt";
std::vector<base::FilePath> file_paths;
file_paths.push_back(base::FilePath(fs_root_local_).Append(path));
auto crosapi_intent =
apps_util::CreateCrosapiIntentForViewFiles(std::move(file_paths));
auto app_service_intent = apps_util::CreateAppServiceIntentFromCrosapi(
crosapi_intent, GetProfile());
EXPECT_EQ(app_service_intent->action, crosapi_intent->action);
EXPECT_EQ(app_service_intent->mime_type, crosapi_intent->mime_type);
ASSERT_TRUE(crosapi_intent->files.has_value());
ASSERT_EQ(crosapi_intent->files.value().size(), 1U);
EXPECT_EQ(
app_service_intent->files[0]->url,
ToGURL(base::FilePath(storage::kExternalDir).Append(mount_name_local_),
path));
}
#endif // BUILDFLAG(IS_CHROMEOS)

@ -6,37 +6,7 @@
#include "build/build_config.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/crosapi/mojom/app_service_types.mojom.h"
#endif // BUILDFLAG(IS_CHROMEOS)
namespace apps {
namespace {
#if BUILDFLAG(IS_CHROMEOS)
LaunchResult::State ConvertMojomLaunchResultStateToLaunchResultState(
crosapi::mojom::LaunchResultState state) {
switch (state) {
case crosapi::mojom::LaunchResultState::kFailed:
return LaunchResult::State::kFailed;
case crosapi::mojom::LaunchResultState::kFailedDirectoryNotShared:
return LaunchResult::State::kFailedDirectoryNotShared;
case crosapi::mojom::LaunchResultState::kSuccess:
return LaunchResult::State::kSuccess;
}
}
crosapi::mojom::LaunchResultState
ConvertLaunchResultStateToMojomLaunchResultState(LaunchResult::State state) {
switch (state) {
case LaunchResult::State::kFailed:
return crosapi::mojom::LaunchResultState::kFailed;
case LaunchResult::State::kFailedDirectoryNotShared:
return crosapi::mojom::LaunchResultState::kFailedDirectoryNotShared;
case LaunchResult::State::kSuccess:
return crosapi::mojom::LaunchResultState::kSuccess;
}
}
#endif // BUILDFLAG(IS_CHROMEOS)
} // namespace
LaunchResult::LaunchResult() = default;
LaunchResult::~LaunchResult() = default;
@ -45,75 +15,6 @@ LaunchResult::LaunchResult(LaunchResult&& other) = default;
LaunchResult::LaunchResult(LaunchResult::State state) : state(state) {}
#if BUILDFLAG(IS_CHROMEOS)
LaunchResult ConvertMojomLaunchResultToLaunchResult(
crosapi::mojom::LaunchResultPtr mojom_launch_result) {
auto launch_result = LaunchResult();
if (mojom_launch_result->instance_ids) {
for (auto token : *mojom_launch_result->instance_ids) {
launch_result.instance_ids.push_back(std::move(token));
}
} else {
launch_result.instance_ids.push_back(
std::move(mojom_launch_result->instance_id));
}
launch_result.state = ConvertMojomLaunchResultStateToLaunchResultState(
mojom_launch_result->state);
return launch_result;
}
base::OnceCallback<void(crosapi::mojom::LaunchResultPtr)>
LaunchResultToMojomLaunchResultCallback(LaunchCallback callback) {
return base::BindOnce(
[](LaunchCallback inner_callback,
crosapi::mojom::LaunchResultPtr mojom_launch_result) {
std::move(inner_callback)
.Run(ConvertMojomLaunchResultToLaunchResult(
std::move(mojom_launch_result)));
},
std::move(callback));
}
crosapi::mojom::LaunchResultPtr ConvertLaunchResultToMojomLaunchResult(
LaunchResult&& launch_result) {
auto mojom_launch_result = crosapi::mojom::LaunchResult::New();
mojom_launch_result->instance_ids = std::vector<base::UnguessableToken>();
for (auto& token : launch_result.instance_ids) {
if (!token.is_empty()) {
mojom_launch_result->instance_ids->push_back(token);
}
}
// This is a deprecated field, but unfortunately we cannot leave it blank,
// because the serialization code check-fails if this field
// is not set. So we just set it to the first of the instance_ids or create
// a dummy value.
// Code will always use the instance_ids field over the instance_id, as
// demonstrated above, so this is safe.
if (!launch_result.instance_ids.empty()) {
mojom_launch_result->instance_id =
mojom_launch_result->instance_ids->front();
} else {
mojom_launch_result->instance_id = base::UnguessableToken::Create();
}
mojom_launch_result->state =
ConvertLaunchResultStateToMojomLaunchResultState(launch_result.state);
return mojom_launch_result;
}
LaunchCallback MojomLaunchResultToLaunchResultCallback(
base::OnceCallback<void(crosapi::mojom::LaunchResultPtr)> callback) {
return base::BindOnce(
[](base::OnceCallback<void(crosapi::mojom::LaunchResultPtr)>
inner_callback,
LaunchResult&& launch_result) {
std::move(inner_callback)
.Run(ConvertLaunchResultToMojomLaunchResult(
std::move(launch_result)));
},
std::move(callback));
}
#endif // BUILDFLAG(IS_CHROMEOS)
LaunchResult ConvertBoolToLaunchResult(bool success) {
return success ? LaunchResult(State::kSuccess) : LaunchResult(State::kFailed);
}

@ -9,11 +9,6 @@
#include "base/functional/callback_forward.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/crosapi/mojom/app_service_types.mojom-forward.h"
#endif // BUILDFLAG(IS_CHROMEOS)
namespace apps {
// LaunchResult and LaunchCallback can be used in ChromeOS and other
@ -40,20 +35,6 @@ struct LaunchResult {
using LaunchCallback = base::OnceCallback<void(LaunchResult&&)>;
using State = LaunchResult::State;
#if BUILDFLAG(IS_CHROMEOS)
LaunchResult ConvertMojomLaunchResultToLaunchResult(
crosapi::mojom::LaunchResultPtr mojom_launch_result);
base::OnceCallback<void(crosapi::mojom::LaunchResultPtr)>
LaunchResultToMojomLaunchResultCallback(LaunchCallback callback);
crosapi::mojom::LaunchResultPtr ConvertLaunchResultToMojomLaunchResult(
LaunchResult&&);
LaunchCallback MojomLaunchResultToLaunchResultCallback(
base::OnceCallback<void(crosapi::mojom::LaunchResultPtr)> callback);
#endif // BUILDFLAG(IS_CHROMEOS)
LaunchResult ConvertBoolToLaunchResult(bool success);
bool ConvertLaunchResultToBool(const LaunchResult& result);

@ -45,89 +45,6 @@
#include "ash/public/cpp/new_window_delegate.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chromeos/ash/experiences/arc/mojom/app.mojom.h"
#include "chromeos/crosapi/mojom/app_service_types.mojom-shared.h"
#include "chromeos/crosapi/mojom/app_service_types.mojom.h"
namespace {
// Use manual mapping for launch container and window open disposition because
// we cannot use mojom traits for crosapi::mojom::LaunchParams yet. Move to auto
// mapping when the AppService Intent struct is converted to use FilePaths.
crosapi::mojom::LaunchContainer ConvertAppServiceToCrosapiLaunchContainer(
apps::LaunchContainer input) {
switch (input) {
case apps::LaunchContainer::kLaunchContainerWindow:
return crosapi::mojom::LaunchContainer::kLaunchContainerWindow;
case apps::LaunchContainer::kLaunchContainerTab:
return crosapi::mojom::LaunchContainer::kLaunchContainerTab;
case apps::LaunchContainer::kLaunchContainerNone:
return crosapi::mojom::LaunchContainer::kLaunchContainerNone;
case apps::LaunchContainer::kLaunchContainerPanelDeprecated:
NOTREACHED();
}
NOTREACHED();
}
apps::LaunchContainer ConvertCrosapiToAppServiceLaunchContainer(
crosapi::mojom::LaunchContainer input) {
switch (input) {
case crosapi::mojom::LaunchContainer::kLaunchContainerWindow:
return apps::LaunchContainer::kLaunchContainerWindow;
case crosapi::mojom::LaunchContainer::kLaunchContainerTab:
return apps::LaunchContainer::kLaunchContainerTab;
case crosapi::mojom::LaunchContainer::kLaunchContainerNone:
return apps::LaunchContainer::kLaunchContainerNone;
}
NOTREACHED();
}
crosapi::mojom::WindowOpenDisposition ConvertWindowOpenDispositionToCrosapi(
WindowOpenDisposition input) {
switch (input) {
case WindowOpenDisposition::UNKNOWN:
return crosapi::mojom::WindowOpenDisposition::kUnknown;
case WindowOpenDisposition::CURRENT_TAB:
return crosapi::mojom::WindowOpenDisposition::kCurrentTab;
case WindowOpenDisposition::NEW_FOREGROUND_TAB:
return crosapi::mojom::WindowOpenDisposition::kNewForegroundTab;
case WindowOpenDisposition::NEW_BACKGROUND_TAB:
return crosapi::mojom::WindowOpenDisposition::kNewBackgroundTab;
case WindowOpenDisposition::NEW_WINDOW:
return crosapi::mojom::WindowOpenDisposition::kNewWindow;
case WindowOpenDisposition::NEW_POPUP:
return crosapi::mojom::WindowOpenDisposition::kNewPopup;
case WindowOpenDisposition::SINGLETON_TAB:
case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE:
case WindowOpenDisposition::SAVE_TO_DISK:
case WindowOpenDisposition::OFF_THE_RECORD:
case WindowOpenDisposition::IGNORE_ACTION:
case WindowOpenDisposition::SWITCH_TO_TAB:
NOTREACHED();
}
NOTREACHED();
}
WindowOpenDisposition ConvertWindowOpenDispositionFromCrosapi(
crosapi::mojom::WindowOpenDisposition input) {
switch (input) {
case crosapi::mojom::WindowOpenDisposition::kUnknown:
return WindowOpenDisposition::UNKNOWN;
case crosapi::mojom::WindowOpenDisposition::kCurrentTab:
return WindowOpenDisposition::CURRENT_TAB;
case crosapi::mojom::WindowOpenDisposition::kNewForegroundTab:
return WindowOpenDisposition::NEW_FOREGROUND_TAB;
case crosapi::mojom::WindowOpenDisposition::kNewBackgroundTab:
return WindowOpenDisposition::NEW_BACKGROUND_TAB;
case crosapi::mojom::WindowOpenDisposition::kNewWindow:
return WindowOpenDisposition::NEW_WINDOW;
case crosapi::mojom::WindowOpenDisposition::kNewPopup:
return WindowOpenDisposition::NEW_POPUP;
}
NOTREACHED();
}
} // namespace
#endif // BUILDFLAG(IS_CHROMEOS)
namespace apps {
@ -374,83 +291,6 @@ arc::mojom::WindowInfoPtr MakeArcWindowInfo(WindowInfoPtr window_info) {
return arc_window_info;
}
crosapi::mojom::LaunchParamsPtr ConvertLaunchParamsToCrosapi(
const AppLaunchParams& params,
Profile* profile) {
auto crosapi_params = crosapi::mojom::LaunchParams::New();
crosapi_params->app_id = params.app_id;
crosapi_params->launch_source = params.launch_source;
// Both launch_files and override_url will be represent by intent in crosapi
// launch params. These info will normally represent in the intent field in
// the launch params, if not, then generate the intent from these fields
if (params.intent) {
crosapi_params->intent =
apps_util::ConvertAppServiceToCrosapiIntent(params.intent, profile);
} else if (!params.override_url.is_empty()) {
crosapi_params->intent = apps_util::ConvertAppServiceToCrosapiIntent(
std::make_unique<Intent>(apps_util::kIntentActionView,
params.override_url),
profile);
} else if (!params.launch_files.empty()) {
std::vector<base::FilePath> files = params.launch_files;
crosapi_params->intent =
apps_util::CreateCrosapiIntentForViewFiles(std::move(files));
}
crosapi_params->container =
ConvertAppServiceToCrosapiLaunchContainer(params.container);
crosapi_params->disposition =
ConvertWindowOpenDispositionToCrosapi(params.disposition);
crosapi_params->display_id = params.display_id;
return crosapi_params;
}
AppLaunchParams ConvertCrosapiToLaunchParams(
const crosapi::mojom::LaunchParamsPtr& crosapi_params,
Profile* profile) {
AppLaunchParams params(
crosapi_params->app_id,
ConvertCrosapiToAppServiceLaunchContainer(crosapi_params->container),
ConvertWindowOpenDispositionFromCrosapi(crosapi_params->disposition),
crosapi_params->launch_source, crosapi_params->display_id);
if (!crosapi_params->intent) {
return params;
}
if (crosapi_params->intent->url.has_value()) {
params.override_url = crosapi_params->intent->url.value();
}
if (crosapi_params->intent->files.has_value()) {
for (const auto& file : crosapi_params->intent->files.value()) {
params.launch_files.push_back(file->file_path);
}
}
params.intent = apps_util::CreateAppServiceIntentFromCrosapi(
crosapi_params->intent, profile);
return params;
}
crosapi::mojom::LaunchParamsPtr CreateCrosapiLaunchParamsWithEventFlags(
AppServiceProxy* proxy,
const std::string& app_id,
int event_flags,
LaunchSource launch_source,
int64_t display_id) {
WindowMode window_mode = WindowMode::kUnknown;
proxy->AppRegistryCache().ForOneApp(app_id,
[&window_mode](const AppUpdate& update) {
window_mode = update.WindowMode();
});
auto launch_params = apps::CreateAppIdLaunchParamsWithEventFlags(
app_id, event_flags, launch_source, display_id,
/*fallback_container=*/
ConvertWindowModeToAppLaunchContainer(window_mode));
return apps::ConvertLaunchParamsToCrosapi(launch_params, proxy->profile());
}
AppIdsToLaunchForUrl::AppIdsToLaunchForUrl() = default;
AppIdsToLaunchForUrl::AppIdsToLaunchForUrl(AppIdsToLaunchForUrl&&) = default;
AppIdsToLaunchForUrl::~AppIdsToLaunchForUrl() = default;

@ -21,7 +21,6 @@
#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/apps/app_service/app_service_proxy_forward.h"
#include "chromeos/ash/experiences/arc/mojom/app.mojom-forward.h"
#include "chromeos/crosapi/mojom/app_service_types.mojom-forward.h"
#endif // BUILDFLAG(IS_CHROMEOS)
class Browser;
@ -84,27 +83,6 @@ int GetSessionIdForRestoreFromWebContents(
// Helper to convert apps::mojom::WindowInfoPtr to arc::mojom::WindowInfoPtr.
arc::mojom::WindowInfoPtr MakeArcWindowInfo(WindowInfoPtr window_info);
// Helper to convert apps::AppLaunchParams to crosapi::mojom::LaunchParams.
// This is needed because we cannot use traits to convert Intent at the moment,
// After that is done, this can be moved to the mojom type traits.
crosapi::mojom::LaunchParamsPtr ConvertLaunchParamsToCrosapi(
const AppLaunchParams& params,
Profile* profile);
// Helper to convert crosapi::mojom::LaunchParams to apps::AppLaunchParams.
// This is needed because we cannot use traits to convert Intent at the moment,
// After that is done, this can be moved to the mojom type traits.
AppLaunchParams ConvertCrosapiToLaunchParams(
const crosapi::mojom::LaunchParamsPtr& crosapi_params,
Profile* profile);
crosapi::mojom::LaunchParamsPtr CreateCrosapiLaunchParamsWithEventFlags(
AppServiceProxy* proxy,
const std::string& app_id,
int event_flags,
LaunchSource launch_source,
int64_t display_id);
// Container for holding possible app IDs that can launch a PWA for a given URL.
struct AppIdsToLaunchForUrl {
AppIdsToLaunchForUrl();

@ -18,7 +18,6 @@
#include "ui/display/types/display_constants.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/crosapi/mojom/app_service_types.mojom.h"
#include "ash/public/cpp/test/test_new_window_delegate.h"
#include "chrome/browser/apps/app_service/publishers/app_publisher.h"
#include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h"
@ -210,97 +209,6 @@ TEST_F(LaunchUtilsTest, GetLaunchFilesFromCommandLine_CustomProtocol) {
}
#if BUILDFLAG(IS_CHROMEOS)
// Verifies that convert params (with no override url, intent, files) to crosapi
// and back works.
TEST_F(LaunchUtilsTest, ConvertToCrosapi) {
auto container = apps::LaunchContainer::kLaunchContainerWindow;
auto disposition = WindowOpenDisposition::NEW_WINDOW;
const int64_t kDisplayId = 1;
auto params = CreateLaunchParams(container, disposition, false, kDisplayId);
auto crosapi_params = apps::ConvertLaunchParamsToCrosapi(params, &profile_);
auto converted_params =
apps::ConvertCrosapiToLaunchParams(crosapi_params, &profile_);
EXPECT_EQ(params.app_id, converted_params.app_id);
EXPECT_EQ(params.container, converted_params.container);
EXPECT_EQ(params.disposition, converted_params.disposition);
EXPECT_EQ(params.launch_source, converted_params.launch_source);
EXPECT_EQ(params.display_id, converted_params.display_id);
}
// Verifies that convert params with override url to crosapi and back works.
TEST_F(LaunchUtilsTest, ConvertToCrosapiUrl) {
auto container = apps::LaunchContainer::kLaunchContainerWindow;
auto disposition = WindowOpenDisposition::NEW_WINDOW;
const int64_t kDisplayId = 2;
auto params = CreateLaunchParams(container, disposition, false, kDisplayId);
params.override_url = GURL("abc.example.com");
auto crosapi_params = apps::ConvertLaunchParamsToCrosapi(params, &profile_);
auto converted_params =
apps::ConvertCrosapiToLaunchParams(crosapi_params, &profile_);
EXPECT_EQ(params.app_id, converted_params.app_id);
EXPECT_EQ(params.container, converted_params.container);
EXPECT_EQ(params.disposition, converted_params.disposition);
EXPECT_EQ(params.launch_source, converted_params.launch_source);
EXPECT_EQ(params.override_url, converted_params.override_url);
EXPECT_EQ(params.display_id, converted_params.display_id);
}
// Verifies that convert params with files to crosapi and back works.
TEST_F(LaunchUtilsTest, ConvertToCrosapiFiles) {
auto container = apps::LaunchContainer::kLaunchContainerWindow;
auto disposition = WindowOpenDisposition::NEW_WINDOW;
const int64_t kDisplayId = 3;
auto params = CreateLaunchParams(container, disposition, false, kDisplayId);
params.launch_files.emplace_back("root");
auto crosapi_params = apps::ConvertLaunchParamsToCrosapi(params, &profile_);
auto converted_params =
apps::ConvertCrosapiToLaunchParams(crosapi_params, &profile_);
EXPECT_EQ(params.app_id, converted_params.app_id);
EXPECT_EQ(params.container, converted_params.container);
EXPECT_EQ(params.disposition, converted_params.disposition);
EXPECT_EQ(params.launch_source, converted_params.launch_source);
EXPECT_EQ(params.display_id, converted_params.display_id);
EXPECT_EQ(params.launch_files, converted_params.launch_files);
}
// Verifies that convert params with intent to crosapi and back works.
TEST_F(LaunchUtilsTest, ConvertToCrosapiIntent) {
auto container = apps::LaunchContainer::kLaunchContainerWindow;
auto disposition = WindowOpenDisposition::NEW_WINDOW;
const int64_t kDisplayId = 4;
auto params = CreateLaunchParams(container, disposition, false, kDisplayId);
params.intent = std::make_unique<apps::Intent>(apps_util::kIntentActionView,
GURL("abc.example.com"));
auto crosapi_params = apps::ConvertLaunchParamsToCrosapi(params, &profile_);
auto converted_params =
apps::ConvertCrosapiToLaunchParams(crosapi_params, &profile_);
EXPECT_EQ(params.app_id, converted_params.app_id);
EXPECT_EQ(params.container, converted_params.container);
EXPECT_EQ(params.disposition, converted_params.disposition);
EXPECT_EQ(params.launch_source, converted_params.launch_source);
EXPECT_EQ(params.display_id, converted_params.display_id);
EXPECT_EQ(*params.intent, *converted_params.intent);
}
// Verifies that convert params from crosapi with incomplete params works.
TEST_F(LaunchUtilsTest, FromCrosapiIncomplete) {
auto params = crosapi::mojom::LaunchParams::New();
params->app_id = "aaaa";
params->launch_source = apps::LaunchSource::kFromIntentUrl;
auto converted_params = apps::ConvertCrosapiToLaunchParams(params, &profile_);
EXPECT_EQ(params->app_id, converted_params.app_id);
EXPECT_EQ(apps::LaunchContainer::kLaunchContainerNone,
converted_params.container);
EXPECT_EQ(WindowOpenDisposition::UNKNOWN, converted_params.disposition);
EXPECT_EQ(apps::LaunchSource::kFromIntentUrl, converted_params.launch_source);
}
// Fake AppPublisher for tracking app launches.
class FakePublisher : public AppPublisher {
public:

@ -63,7 +63,6 @@ test("chromeos_unittests") {
"//chromeos/components/firewall_hole:unit_tests",
"//chromeos/constants:unit_tests",
"//chromeos/crosapi/cpp:unit_tests",
"//chromeos/crosapi/mojom:unit_tests",
"//chromeos/dbus:unit_tests",
"//chromeos/printing:unit_tests",
"//chromeos/process_proxy:unit_tests",

@ -11,9 +11,6 @@ include_rules = [
]
specific_include_rules = {
"app_service_types_mojom_traits_unittest\.cc": [
"+ui/gfx/image/image_unittest_util.h"
],
"desk_template_mojom_traits\.cc" : [
"+ui/gfx/range/range.h"
],

@ -8,8 +8,6 @@ import("//printing/buildflags/buildflags.gni")
mojom("mojom") {
sources = [
"account_manager.mojom",
"app_service.mojom",
"app_service_types.mojom",
"arc.mojom",
"audio_service.mojom",
"authentication.mojom",
@ -164,10 +162,6 @@ mojom("mojom") {
move_only = true
nullable_is_same_type = true
},
{
mojom = "crosapi.mojom.UninstallSource"
cpp = "::apps::UninstallSource"
},
{
mojom = "crosapi.mojom.CapabilityAccess"
cpp = "::apps::CapabilityAccessPtr"
@ -226,16 +220,6 @@ mojom("mojom") {
cpp = "::apps::PermissionPtr"
move_only = true
},
{
mojom = "crosapi.mojom.PreferredApp"
cpp = "::apps::PreferredAppPtr"
move_only = true
},
{
mojom = "crosapi.mojom.PreferredAppChanges"
cpp = "::apps::PreferredAppChangesPtr"
move_only = true
},
{
mojom = "crosapi.mojom.WebAppInstallResultCode"
cpp = "::webapps::InstallResultCode"
@ -272,7 +256,6 @@ mojom("mojom") {
},
]
traits_headers = [
"//chromeos/crosapi/mojom/app_service_types_mojom_traits.h",
"//chromeos/crosapi/mojom/cert_database_mojom_traits.h",
"//chromeos/crosapi/mojom/desk_mojom_traits.h",
"//chromeos/crosapi/mojom/desk_template_mojom_traits.h",
@ -290,7 +273,6 @@ mojom("mojom") {
"//components/services/app_service/public/cpp/preferred_app.h",
]
traits_sources = [
"//chromeos/crosapi/mojom/app_service_types_mojom_traits.cc",
"//chromeos/crosapi/mojom/cert_database_mojom_traits.cc",
"//chromeos/crosapi/mojom/desk_mojom_traits.cc",
"//chromeos/crosapi/mojom/desk_template_mojom_traits.cc",
@ -339,17 +321,3 @@ mojom("structured_metrics_service") {
]
webui_module_path = "/"
}
source_set("unit_tests") {
testonly = true
sources = [ "app_service_types_mojom_traits_unittest.cc" ]
deps = [
":mojom",
"//base/test:test_support",
"//components/services/app_service",
"//mojo/public/cpp/test_support:test_utils",
"//testing/gtest",
"//ui/gfx:test_support",
]
}

@ -1,153 +0,0 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module crosapi.mojom;
import "chromeos/crosapi/mojom/app_service_types.mojom";
import "chromeos/crosapi/mojom/ui_constants.mojom";
// Interacts with the app service. Implemented in lacros-chrome and called in
// ash-chrome.
// Next version: 22
// Next method id: 22
[Uuid="2031a614-3f0b-4111-8977-fd96fd780cb7"]
interface AppController {
// Directly uninstalls |app_id| without prompting the user.
// If |clear_site_data| is true, any site data associated with the app will
// be removed.
// If |report_abuse| is true, the app will be reported for abuse to the Web
// Store.
[MinVersion=1]
Uninstall@1(
string app_id,
UninstallSource uninstall_source,
bool clear_site_data,
bool report_abuse);
// Pauses an app to stop the current running app, and apply the icon effect
// to indicate the app is paused.
// Pause a paused app will make the app stay paused, and pause an app
// that is not currently running will only change the icon to paused
// indication and make the app in pause state when the app is launched the
// next time.
[MinVersion=3]
PauseApp@2(string app_id);
// Unpauses an app, and recover the icon effect for the app to indicate
// the app is no longer paused.
// Unpause an unpaused app will make the app stay unpaused, and unpause
// an app that is not currently running will only change the icon back to
// normal state and make the app in normal state when the app is launched
// the next time.
[MinVersion=3]
UnpauseApp@3(string app_id);
// Returns the context menu items for an app with |app_id| to show in app
// list and shelf. This interface only returns menu items that needs to be
// populated in lacros-chrome (e.g. app-specific shortcuts).
[MinVersion=4]
GetMenuModel@4(string app_id) => (MenuItems menu_items);
// Load icon for an app with |app_id| from lacros-chrome.
// |icon_key| contains the arguments for an app icon, see
// apps::mojom::IconKey for more details. |icon_type| represent the icon
// format requested (e.g. compressed, uncompressed. etc). |size_hint_in_dip|
// is a hint of how big the icon should be. All these fields are necessary
// to fill to get the required icon.
// There should always be a return value for this method. If there is an
// error during the loading, the return value should be a default IconValue
// struct, with IconType = kUnknown to indicate it's an error case. If loading
// succeeded, the size of the returning icon is expected to be as close as
// possible with the |size_hint_in_dip| set in the interface, but may not be
// exactly the same.
// DEPRECATED. Use GetCompressedIcon() instead.
[MinVersion=5]
DEPRECATED_LoadIcon@5(
string app_id,
IconKey icon_key,
IconType icon_type,
int32 size_hint_in_dip) => (IconValue icon_value);
// Requests a compressed icon data for an app identified by `app_id` from
// lacros-chrome. The icon is identified by `size_in_dip` and `scale_factor`.
// Calls `callback` with the result.
[MinVersion=20]
GetCompressedIcon@20(
string app_id,
int32 size_in_dip,
ResourceScaleFactor scale_factor) => (IconValue icon_value);
// Opens the app platform settings page for the app with |app_id|.
// e.g. for web app, it opens the Chrome site settings page for the app.
[MinVersion=6]
OpenNativeSettings@6(string app_id);
// Set the window display mode for the app identified by |app_id|.
// |window_mode| represents how the app will be open in (e.g. in a
// standalone window or in a browser tab).
[MinVersion=7]
SetWindowMode@7(
string app_id,
WindowMode window_mode);
// Launch the app with |params|. The params include |app_id|,
// |launch_source|, and optional |intent| at the moment. This method will
// return |launch_result| to allow us find out which instance the app is
// running in.
[MinVersion=10]
Launch@8(LaunchParams params) => (LaunchResult launch_result);
// Sends the execution command to Lacros when user selects an item in the
// context menu to execute for an app with |app_id|. Current only the
// shortcut items in context menu need to be executed in lacros-chrome.
// The |id| represent which item user selected.
// This method will launch the app with selected shortcut and return
// |launch_result| to allow us find out which instance the app is running in.
[MinVersion=12]
ExecuteContextMenuCommand@9(
string app_id,
string id) => (LaunchResult launch_result);
// Close all instances of the given |app_id|.
[MinVersion=13]
StopApp@10(string app_id);
// Change permission setting for the app with |app_id|.
[MinVersion=14]
SetPermission@11(
string app_id,
Permission permission);
// Requests the size of an app with |app_id|. Publishers are expected to
// calculate and update the size of the app and publish this to App Service
[MinVersion=21]UpdateAppSize@21(string app_id);
};
// Interacts with the app service. Implemented in lacros-chrome and called in
// ash-chrome. This interface will allow the app service to push updates to
// the lacros-chrome so that the browser can access the app service info
// in the same process.
// Next version: 16
// Next method id: 3
[Uuid="d77d3b7e-ef90-4615-b81b-7e43482a4d5e"]
interface AppServiceSubscriber {
// Receives a stream of apps from ash-chrome from a publisher, and save to
// AppRegistryCache.
// If |should_notify_initialized| is true, notifies observers that |app_type|
// has finished initiating apps.
[MinVersion=9]
OnApps@0(array<App> deltas, AppType app_type, bool should_notify_initialized);
// Indicates that a changes have been made by App Service to the preferred
// apps list. All of the changes should be applied to the subscriber's copy of
// the list using PreferredAppsList::ApplyBulkUpdate.
[MinVersion=15]
OnPreferredAppsChanged@1(PreferredAppChanges changes);
// On startup, Ash informs Lacros of the user's historically preferred apps
// for given intents. This allows Lacros to initialize its in-memory
// representation of the user's preferred apps.
[MinVersion=15]
InitializePreferredApps@2(array<PreferredApp> preferred_apps);
};

@ -1,656 +0,0 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// NOTE: Future MinVersion values should take into account that MinVersion is
// scoped per struct. In the past, some of the MinVersion values in this file
// were set based on the understanding that the entire file should share a
// MinVersion counter.
module crosapi.mojom;
import "mojo/public/mojom/base/file_path.mojom";
import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "ui/gfx/image/mojom/image.mojom";
import "url/mojom/url.mojom";
// Information about an app. See components/services/app_service/README.md.
// This struct is used to transport App data between lacros-chrome and
// ash-chrome. It is intended to be the minimal subset of apps::mojom::App
// required for this purpose, and exists to allow apps::mojom::App to not have
// to be versioned.
// See components/services/app_service/public/cpp/app_types.h for details for
// the structs in this file.
struct App {
AppType app_type@0;
string app_id@1;
// The fields above are mandatory. Everything else below is optional.
Readiness readiness@2;
string? name@3;
string? short_name@4;
// An optional, publisher-specific ID for this app, e.g. for Android apps,
// this field contains the Android package name, and for web apps, it
// contains the start URL.
string? publisher_id@5;
string? description@6;
string? version@7;
array<string> additional_search_terms@8;
IconKey? icon_key@9;
mojo_base.mojom.Time? last_launch_time@10;
mojo_base.mojom.Time? install_time@11;
// Whether the app was installed by sync, policy or as a default app.
InstallReason install_reason@12;
OptionalBool recommendable@13;
OptionalBool searchable@14;
OptionalBool show_in_launcher@15;
OptionalBool show_in_shelf@16;
OptionalBool show_in_search@17;
OptionalBool show_in_management@18;
// Whether the app icon should add the notification badging.
OptionalBool has_badge@19;
// Paused apps cannot be launched, and any running apps that become paused
// will be stopped. This is independent of whether or not the app is ready to
// be launched (defined by the Readiness field).
OptionalBool paused@20;
// This vector stores all the intent filters defined in this app. Each
// intent filter defines a matching criteria for whether an intent can
// be handled by this app. One app can have multiple intent filters.
array<IntentFilter> intent_filters@21;
// Whether the app's display mode is in the browser or otherwise.
[MinVersion=2]
WindowMode window_mode@22;
[MinVersion=7, RenamedFrom="policy_id"]
// DEPRECATED, replaced with |policy_ids| below.
string? deprecated_policy_id@23;
// This vector must be treated atomically, if there is a permission
// change, the publisher must send through the entire list of permissions.
// Should contain no duplicate IDs.
// If null during updates, Subscriber can assume no changes.
// There is no guarantee that this is sorted by any criteria.
[MinVersion=8]
array<Permission>? permissions@24;
[MinVersion=11]
// Whether the app publisher allows the app to be uninstalled.
OptionalBool allow_uninstall@25;
[MinVersion=12]
// kTrue if the app is able to handle intents and should be shown in intent
// surfaces.
OptionalBool handles_intents@26;
[MinVersion=18, RenamedFrom="shortcuts"]
// DEPRECATED, will be replaced by specific interfaces to update shortcuts.
// This struct is not used in production yet, so it's safe to deprecate.
array<REMOVED_01>? deprecated_shortcuts@27;
[MinVersion=19]
OptionalBool is_platform_app@28;
[MinVersion=20]
// IDs used for policy to identify the app.
// For web apps, it contains the install URL(s).
array<string>? policy_ids@29;
// The amount of storage (in bytes) used by the app.
[MinVersion=21]
uint64? app_size_in_bytes@30;
// The amount of storage (in bytes) used by the app's data.
[MinVersion=21]
uint64? data_size_in_bytes@31;
[MinVersion=22]
// Whether the app publisher allows the app to be closed.
OptionalBool allow_close@32;
[MinVersion=23]
// Whether the app publisher allows the user to select app open mode.
OptionalBool allow_window_mode_selection@33;
[MinVersion=24]
// An optional ID for the package that installed this app.
PackageId? installer_package_id@34;
};
// The types of apps available in the registry.
[Extensible]
enum AppType {
[Default] kUnknown = 0,
kArc = 1, // Android app.
kWeb = 2, // Web app.
kSystemWeb = 3, // System web app.
// kStandaloneBrowserChromeApp = 4, // Removed. No longer used.
// kStandaloneBrowserExtension = 5, // Removed. No longer used.
};
// Whether an app is ready to launch, i.e. installed.
[Extensible]
enum Readiness {
[Default] kUnknown = 0,
kReady, // Installed and launchable.
kDisabledByBlocklist, // Disabled by SafeBrowsing.
kDisabledByPolicy, // Disabled by admin policy.
kDisabledByUser, // Disabled by explicit user action.
kTerminated, // Renderer process crashed.
kUninstalledByUser,
// Removed apps are purged from the registry cache and have their
// associated memory freed. Subscribers are not notified of removed
// apps, so publishers must set the app as uninstalled before
// removing it.
kRemoved,
// This is used for all non-user initiated uninstallation.
[MinVersion=1] kUninstalledByNonUser,
[MinVersion=2] kDisabledByLocalSettings, // Disabled by local settings.
};
// The reason why the app was installed.
[Extensible, RenamedFrom="crosapi.mojom.InstallSource"]
enum InstallReason {
[Default] kUnknown = 0,
kSystem, // Installed with the system and is considered a part of the OS.
kPolicy, // Installed by policy.
kOem, // Installed by an OEM.
kDefault, // Preinstalled by default, but is not considered a system app.
kSync, // Installed by sync.
kUser, // Installed by user action.
[MinVersion=7] kSubApp, // Installed by the SubApp API call.
[MinVersion=8] kKiosk, // Installed by Kiosk on Chrome OS.
[MinVersion=9] kCommandLine, // Deprecated, no longer used.
};
// Augments a bool to include an 'unknown' value.
[Extensible]
enum OptionalBool {
[Default] kUnknown = 0,
kFalse,
kTrue,
};
// `IconUpdateVersion` should hold a bool to specify whether the icon image is
// updated by the app when the publisher publishes the app. `IconUpdateVersion`
// should never hold a int32_t when calling OnApps to publish apps.
//
// AppRegistryCache generates an int32_t for `IconUpdateVersion` to notify
// AppService clients whether reload the icon, when merging `deltas`.
// `IconUpdateVersion` should never hold a bool in AppRegistryCache's `states_`.
//
// When the icon has a valid `resource_id`, IconUpdateVersion is
// `kInitVersion`, and never changes.
//
// When an app is added, if the icon doesn't have a valid `resource_id`,
// IconUpdateVersion is set as `kInitVersion`.
//
// If the app updates the icon image, IconUpdateVersion is set as true by a
// Publisher, and AppService increases the saved IconUpdateVersion to notify
// AppService clients to reload icons.
//
// When IconUpdateVersion is an int32_t, the exact value of the number isn't
// important, only that newer IconKey's (those that were created more recently)
// have a larger IconUpdateVersion than older IconKey's.
//
// IconUpdateVersion isn't changed if `icon_effects` is changed.
// IconUpdateVersion is increased only when the app updates, or upgrades, and
// publish a new icon image.
//
// See components/services/app_service/public/cpp/icon_types.h for details
union IconUpdateVersion {
bool raw_icon_updated;
int32 timeline;
};
struct IconKey {
// A monotonically increasing number so that, after an icon update, a new
// IconKey, one that is different in terms of field-by-field equality, can be
// broadcast by a Publisher.
//
// The exact value of the number isn't important, only that newer IconKey's
// (those that were created more recently) have a larger timeline than older
// IconKey's.
//
// This is, in some sense, *a* version number, but the field is not called
// "version", to avoid any possible confusion that it encodes *the* app's
// version number, e.g. the "2.3.5" in "FooBar version 2.3.5 is installed".
//
// DEPRECATED, replaced with `update_version` below.
[RenamedFrom="timeline"]
uint64 deprecated_timeline;
// A bitmask of icon post-processing effects, such as desaturation to gray
// and rounding the corners.
// The mask enum apps::IconEffects is defined in
// chrome/browser/apps/app_service/app_icon/app_icon_factory.h and will remain
// stable.
uint32 icon_effects;
// True when the raw icon is updated. After an icon update, a new IconKey can
// be broadcast by a Publisher. Then the AppService icon directory should be
// removed to fetch the new raw icon from the app.
//
// DEPRECATED, replaced with `update_version` below.
[MinVersion=22, RenamedFrom="raw_icon_updated"]
bool deprecated_raw_icon_updated;
// The icon updated info to notify AppService clients to reload the icon.
//
// If the app updates the icon image, `update_version` is set as true by a
// Publisher, and AppService increases the saved `update_version` to notify
// AppService clients to reload icons.
//
// `update_version` isn't changed if `icon_effects` is changed.
// `update_version` is increased only when the app updates, or upgrades, and
// publish a new icon image.
[MinVersion=23]
IconUpdateVersion? update_version;
};
// The intent filter matching condition types.
[Extensible]
enum ConditionType {
[Default] kScheme, // Matches the URL scheme (e.g. https, tel).
kAuthority, // Matches the URL host and optionally the port
// (e.g. www.google.com:443).
kPath, // Matches the URL path (e.g. /abc/*).
kAction, // Matches the action type (e.g. view, send).
kMimeType, // Matches the top-level mime type (e.g. text/plain).
[MinVersion=1] kFileExtension, // Deprecated.
[MinVersion=4] kFile // Matches against all files.
};
// The pattern match type for intent filter pattern condition.
[Extensible]
enum PatternMatchType {
[Default] kNone = 0,
kLiteral,
kPrefix,
kGlob,
kMimeType,
[MinVersion=1] kFileExtension,
[MinVersion=6] kIsDirectory,
[MinVersion=16] kSuffix
};
// For pattern type of condition, the value match will be based on the pattern
// match type. If the match_type is kNone, then an exact match with the value
// will be required.
struct ConditionValue {
string value;
PatternMatchType match_type; // This will be None for non pattern conditions.
};
// The condition for an intent filter. It matches if the intent contains this
// condition type and the corresponding value matches with any of the
// condition_values.
struct Condition {
ConditionType condition_type;
array<ConditionValue> condition_values;
};
// An intent filter is defined by an app, and contains a list of conditions that
// an intent needs to match. If all conditions match, then this intent filter
// matches against an intent.
struct IntentFilter {
array<Condition> conditions;
// Activity which registered this filter. We only fill this field for ARC
// share intent filters.
string? activity_name;
// The label shown to the user for this activity.
string? activity_label;
};
// What caused the app to be uninstalled.
[Extensible]
enum UninstallSource {
[Default] kUnknown = 0,
kAppList, // Uninstall by the user from the App List (Launcher)
kAppManagement, // Uninstall by the user from the App Management page
kShelf, // Uninstall by the user from the Shelf
kMigration, // Uninstall by app migration.
};
// Information about whether an app is accessing some capability, e.g. camera,
// microphone.
struct CapabilityAccess {
string app_id;
// Whether the app is accessing camera.
OptionalBool camera;
// Whether the app is accessing microphone.
OptionalBool microphone;
};
[Extensible]
enum IconType {
// Sentinel value used in error cases.
[Default] kUnknown,
// Icon as an uncompressed gfx::ImageSkia with no standard Chrome OS mask.
kUncompressed,
// Icon as compressed bytes in PNG format with no standard Chrome OS mask.
kCompressed,
// Icon as an uncompressed gfx::ImageSkia with the standard Chrome OS mask
// applied. This is the default suggested icon type.
kStandard,
};
// The icon value for each app.
struct IconValue {
// The icon format and whether it uses Chrome OS mask.
IconType icon_type@0;
// The uncompressed icon data in gfx::ImageSkia format.
gfx.mojom.ImageSkia? uncompressed@1;
// The compressed icon data in PNG format.
array<uint8>? compressed@2;
// Whether this icon data is a placeholder icon.
bool is_placeholder_icon@3;
// Whether this icon is a maskable icon. Per
// https://www.w3.org/TR/appmanifest/#icon-masks, we apply a white background
// for the maskable icon in its safe zone, and clear the standard icon effect,
// apply the mask to the icon without shrinking it.
[MinVersion=21] bool is_maskable_icon@4;
};
// MenuItems are used to populate context menus.
struct MenuItems {
array<MenuItem> items@0;
};
// The context menu model for each app. For web apps currently it's the info
// for shortcut items.
struct MenuItem {
string label@0; // The string label, may be empty.
gfx.mojom.ImageSkia? image@1; // The image icon, may be null.
[MinVersion=3]string? id@2; // The id of the item.
};
[Extensible]
// The mode that the app will be opened in (e.g. standalone window or browser
// tab).
enum WindowMode {
[Default] kUnknown = 0,
// Opens in a standalone window
kWindow,
// Opens in the default web browser
kBrowser,
// Opens in a tabbed app window
kTabbedWindow,
};
// Metadata for a single file shared through an intent.
struct IntentFile {
// The file path of the file to share.
mojo_base.mojom.FilePath file_path@0;
// File MIME type.
[MinVersion=15] string? mime_type@1;
};
// Action and resource handling request. This should
// be kept in sync with ConvertIntentToValue and ConvertValueToIntent in
// components/services/app_service/public/cpp/intent_util.*
struct Intent {
string action@0; // Intent action. e.g. view, send.
url.mojom.Url? url@1; // The URL of the intent. e.g. https://www.google.com/.
string? mime_type@2; // MIME type. e.g. text/plain, image/*.
string? share_text@3; // Text to share. e.g. Share link to other app.
string? share_title@4; // Title for the share.
// The files to view or share.
[MinVersion=5] array<IntentFile>? files@5;
// The activity for the app to launch.
[MinVersion=13] string? activity_name@6;
[MinVersion=14] string? data@7;
[MinVersion=15] bool? ui_bypassed@8; // Whether or not the user saw the UI.
[MinVersion=15] map<string, string>? extras@9; // Optional string extras.
};
[Extensible]
enum LaunchResultState {
[Default] kFailed,
kFailedDirectoryNotShared,
kSuccess,
};
// The result from launching an app.
struct LaunchResult {
// The id to represent which instance the app is launched in. Deprecated: use
// `instance_ids`.
mojo_base.mojom.UnguessableToken instance_id@0;
// The IDs that represent the instances the app is launched in.
[MinVersion=1] array<mojo_base.mojom.UnguessableToken>? instance_ids@1;
[MinVersion=2] LaunchResultState state@2;
};
// Enumeration of app launch sources.
[Extensible]
enum LaunchSource {
[Default] kUnknown = 0,
kFromAppListGrid, // Grid of apps, not the search box.
kFromAppListGridContextMenu, // Grid of apps; context menu.
kFromAppListQuery, // Query-dependent results (larger icons).
kFromAppListQueryContextMenu, // Query-dependent results; context menu.
kFromAppListRecommendation, // Query-less recommendations (smaller
// icons).
kFromParentalControls, // Parental Controls Settings Section and
// Per App time notification.
kFromShelf, // Shelf.
kFromFileManager, // FileManager.
kFromLink, // Left-clicking on links in the browser.
kFromOmnibox, // Enter URL in the Omnibox in the
// browser.
kFromChromeInternal, // Chrome internal call.
kFromKeyboard, // Keyboard shortcut for opening app.
kFromOtherApp, // Clicking link in another app or webui.
kFromMenu, // Menu.
kFromInstalledNotification, // Installed notification
kFromTest, // Test
kFromArc, // Arc.
kFromSharesheet, // Sharesheet.
kFromReleaseNotesNotification, // Release Notes Notification.
kFromFullRestore, // Full restore.
kFromSmartTextContextMenu, // Smart text selection context menu.
kFromDiscoverTabNotification, // Discover Tab Notification.
[MinVersion=10] kFromManagementApi, // Management API.
[MinVersion=10] kFromKiosk, // Kiosk.
[MinVersion=10] kFromNewTabPage, // New tab page.
[MinVersion=10] kFromIntentUrl, // Intent Url.
[MinVersion=10] kFromOsLogin, // Run on OS login.
[MinVersion=10] kFromProtocolHandler, // Protocol handler.
[MinVersion=10] kFromUrlHandler, // Url handler.
[MinVersion=11] kFromSysTrayCalendar, // System Tray Calendar.
[MinVersion=12] kFromInstaller, // Installation UI.
[MinVersion=13] kFromFirstRun, // First Run.
[MinVersion=14] kFromWelcomeTour, // Welcome Tour.
[MinVersion=15] kFromFocusMode, // Focus Mode panel.
[MinVersion=16] kFromSparky, // Sparky.
[MinVersion=36] kFromNavigationCapturing, // WebApp Navigation Capturing.
};
[Extensible]
// The container type to launch the application in.
enum LaunchContainer {
[Default] kLaunchContainerNone, // No specified container
kLaunchContainerWindow, // Window container
kLaunchContainerTab, // Tab container
};
[Extensible]
// Controls how a tab is opened in a window.
enum WindowOpenDisposition {
[Default] kUnknown,
kCurrentTab,
kNewForegroundTab,
kNewBackgroundTab,
kNewWindow,
[MinVersion=1] kNewPopup,
};
// The parameters to launch an app.
struct LaunchParams {
string app_id@0; // The app id of the app.
LaunchSource launch_source@1; // The app launch source.
Intent? intent@2; // The intent the app will launch with.
// The container the app will launch in.
[MinVersion=14]LaunchContainer container@3;
// How the tab opened in a window if app is opened in tab.
[MinVersion=14]WindowOpenDisposition disposition@4;
// An id that indicates which display the app should be launched in.
[MinVersion=15]int64 display_id@5;
};
struct Permission {
PermissionType permission_type@0;
PermissionValue value@1;
// If the permission is managed by an enterprise policy.
bool is_managed@2;
};
// The types of permissions in App Service.
[Extensible]
enum PermissionType {
[Default] kUnknown = 0,
kCamera = 1,
kLocation = 2,
kMicrophone = 3,
kNotifications = 4,
[MinVersion=9] kContacts = 5,
[MinVersion=9] kStorage = 6,
[MinVersion=10] kFileHandling = 7,
};
enum TriState {
kAllow,
kBlock,
kAsk,
};
union PermissionValue {
bool bool_value;
TriState tristate_value;
};
// Represents changes which have been made to the preferred apps list, both
// adding new filters and removing existing filters. The map is keyed by
// |app_id|, and the value is the list of the filters that is added/removed
// for that |app_id|.
struct PreferredAppChanges {
map<string, array<IntentFilter>> added_filters;
map<string, array<IntentFilter>> removed_filters;
};
// Represents the entry of the preferred apps list.
struct PreferredApp {
IntentFilter intent_filter;
string app_id;
};
[Extensible]
enum PackageIdType {
[Default] kUnknown = 0,
kWeb = 1,
kArc = 2,
};
// A globally unique stable identifier for an installable app package.
struct PackageId {
// The app type of the package.
PackageIdType package_type;
// A platform-specific unique ID for the package. For example, for
// PackageIdType::kArc, the identifier will be the package name. Must be
// non-empty.
string identifier;
};
// Information about an app shortcut.
// This struct is used to transport App Shortcut data between lacros-chrome and
// ash-chrome. It is intended to be the minimal subset of apps::Shortcut
// required for this purpose.
//
// See components/services/app_service/public/cpp/shortcut/shortcut.h for
// details for the structs in this file.
struct AppShortcut {
// 'host_app_id' and 'local_id' should not be changeable after creation.
// The host app of the shortcut.
string host_app_id@0;
// The locally unique identifier for the shortcut within an app. This id would
// be used to launch the shortcut or load shortcut icon from the app.
string local_id@1;
// Name of the shortcut.
string? name@2;
// Represents what icon should be loaded for this shortcut, icon key will
// change if the icon has been updated from the publisher.
IconKey? icon_key@3;
// Whether the shortcut publisher allows the shortcut to be removed by user.
[MinVersion=1] bool? allow_removal@4;
};
// DEPRECATED
[RenamedFrom="crosapi.mojom.Shortcut"]
struct REMOVED_01 {
// DEPRECATED
string shortcut_id@0;
// DEPRECATED
string name@1;
// DEPRECATED
uint8 position@2;
};
// Controller registration result in App Service.
[Extensible]
enum ControllerRegistrationResult {
[Default] kSuccess = 0,
kFailed = 1,
};
// Represents parameters for installing an app.
// Next version: 2
struct InstallAppParams {
// Represents the origin of the installation.
// Next version: 3
[Extensible]
enum Surface {
[Default] kUnknown = 0,
kAppInstallUriUnknown = 1,
[MinVersion=1] kAppInstallUriShowoff = 2,
[MinVersion=1] kAppInstallUriMall = 3,
[MinVersion=1] kAppInstallUriGetit = 4,
[MinVersion=1] kAppInstallUriLauncher = 5,
[MinVersion=2] kAppInstallUriPeripherals = 6,
};
Surface surface@0;
// Represents which package_id to fetch from Almanac to be installed.
string? serialized_package_id@1;
// Instance ID of a parent window to anchor the app install dialog to. If not
// provided or a corresponding window is not found, the app install dialog is
// created without anchoring to a parent.
[MinVersion=1] mojo_base.mojom.UnguessableToken? window_id@2;
};
// Represents the result of an InstallApp() request.
// Currently empty but will be extended with fields as needed.
struct AppInstallResult {
};

File diff suppressed because it is too large Load Diff

@ -1,487 +0,0 @@
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_CROSAPI_MOJOM_APP_SERVICE_TYPES_MOJOM_TRAITS_H_
#define CHROMEOS_CROSAPI_MOJOM_APP_SERVICE_TYPES_MOJOM_TRAITS_H_
#include <optional>
#include <string>
#include "chromeos/crosapi/mojom/app_service_types.mojom.h"
#include "components/services/app_service/public/cpp/app.h"
#include "components/services/app_service/public/cpp/app_launch_util.h"
#include "components/services/app_service/public/cpp/app_types.h"
#include "components/services/app_service/public/cpp/capability_access.h"
#include "components/services/app_service/public/cpp/icon_types.h"
#include "components/services/app_service/public/cpp/intent_filter.h"
#include "components/services/app_service/public/cpp/package_id.h"
#include "components/services/app_service/public/cpp/permission.h"
#include "components/services/app_service/public/cpp/preferred_app.h"
#include "components/services/app_service/public/cpp/shortcut/shortcut.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace mojo {
template <>
struct StructTraits<crosapi::mojom::AppDataView, apps::AppPtr> {
static apps::AppType app_type(const apps::AppPtr& r) { return r->app_type; }
static const std::string& app_id(const apps::AppPtr& r) { return r->app_id; }
static apps::Readiness readiness(const apps::AppPtr& r) {
return r->readiness;
}
static const std::optional<std::string>& name(const apps::AppPtr& r) {
return r->name;
}
static const std::optional<std::string>& short_name(const apps::AppPtr& r) {
return r->short_name;
}
static const std::optional<std::string>& publisher_id(const apps::AppPtr& r) {
return r->publisher_id;
}
static const std::optional<std::string>& description(const apps::AppPtr& r) {
return r->description;
}
static const std::optional<std::string>& version(const apps::AppPtr& r) {
return r->version;
}
static const std::vector<std::string>& additional_search_terms(
const apps::AppPtr& r) {
return r->additional_search_terms;
}
static apps::IconKeyPtr icon_key(const apps::AppPtr& r);
static const std::optional<base::Time>& last_launch_time(
const apps::AppPtr& r) {
return r->last_launch_time;
}
static const std::optional<base::Time>& install_time(const apps::AppPtr& r) {
return r->install_time;
}
static const apps::InstallReason& install_reason(const apps::AppPtr& r) {
return r->install_reason;
}
// This method is required for Ash-Lacros backwards compatibility.
static std::optional<std::string> deprecated_policy_id(const apps::AppPtr& r);
static const std::vector<std::string>& policy_ids(const apps::AppPtr& r) {
return r->policy_ids;
}
static crosapi::mojom::OptionalBool recommendable(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool searchable(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool show_in_launcher(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool show_in_shelf(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool show_in_search(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool show_in_management(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool has_badge(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool paused(const apps::AppPtr& r);
static const apps::IntentFilters& intent_filters(const apps::AppPtr& r) {
return r->intent_filters;
}
static const apps::WindowMode& window_mode(const apps::AppPtr& r) {
return r->window_mode;
}
static const apps::Permissions& permissions(const apps::AppPtr& r) {
return r->permissions;
}
static crosapi::mojom::OptionalBool allow_uninstall(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool handles_intents(const apps::AppPtr& r);
// This method is required for Ash-Lacros backwards compatibility.
static std::vector<crosapi::mojom::REMOVED_01Ptr> deprecated_shortcuts(
const apps::AppPtr& r) {
return {};
}
static crosapi::mojom::OptionalBool is_platform_app(const apps::AppPtr& r);
static std::optional<uint64_t> app_size_in_bytes(const apps::AppPtr& r);
static std::optional<uint64_t> data_size_in_bytes(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool allow_close(const apps::AppPtr& r);
static crosapi::mojom::OptionalBool allow_window_mode_selection(
const apps::AppPtr& r);
static std::optional<apps::PackageId> installer_package_id(
const apps::AppPtr& r) {
return r->installer_package_id;
}
static bool Read(crosapi::mojom::AppDataView data, apps::AppPtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::AppType, apps::AppType> {
static crosapi::mojom::AppType ToMojom(apps::AppType input);
static bool FromMojom(crosapi::mojom::AppType input, apps::AppType* output);
};
template <>
struct EnumTraits<crosapi::mojom::Readiness, apps::Readiness> {
static crosapi::mojom::Readiness ToMojom(apps::Readiness input);
static bool FromMojom(crosapi::mojom::Readiness input,
apps::Readiness* output);
};
template <>
struct UnionTraits<crosapi::mojom::IconUpdateVersionDataView,
apps::IconKey::UpdateVersion> {
static crosapi::mojom::IconUpdateVersionDataView::Tag GetTag(
const apps::IconKey::UpdateVersion& r);
static bool IsNull(const apps::IconKey::UpdateVersion& r) { return false; }
static void SetToNull(apps::IconKey::UpdateVersion* out) {}
static bool raw_icon_updated(const apps::IconKey::UpdateVersion& r) {
if (absl::holds_alternative<bool>(r)) {
return absl::get<bool>(r);
}
return false;
}
static int32_t timeline(const apps::IconKey::UpdateVersion& r) {
if (absl::holds_alternative<int32_t>(r)) {
return absl::get<int32_t>(r);
}
return apps::IconKey::kInvalidVersion;
}
static bool Read(crosapi::mojom::IconUpdateVersionDataView data,
apps::IconKey::UpdateVersion* out);
};
template <>
struct StructTraits<crosapi::mojom::IconKeyDataView, apps::IconKeyPtr> {
static bool IsNull(const apps::IconKeyPtr& r) { return !r; }
static void SetToNull(apps::IconKeyPtr* r) { r->reset(); }
// This method is required for Ash-Lacros backwards compatibility.
static uint64_t deprecated_timeline(const apps::IconKeyPtr& r) {
return absl::holds_alternative<int32_t>(r->update_version)
? absl::get<int32_t>(r->update_version)
: apps::IconKey::kInvalidVersion;
}
static uint32_t icon_effects(const apps::IconKeyPtr& r) {
return r->icon_effects;
}
// This method is required for Ash-Lacros backwards compatibility.
static bool deprecated_raw_icon_updated(const apps::IconKeyPtr& r) {
return absl::holds_alternative<bool>(r->update_version)
? absl::get<bool>(r->update_version)
: false;
}
static apps::IconKey::UpdateVersion update_version(
const apps::IconKeyPtr& r) {
return r->update_version;
}
static bool Read(crosapi::mojom::IconKeyDataView, apps::IconKeyPtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::InstallReason, apps::InstallReason> {
static crosapi::mojom::InstallReason ToMojom(apps::InstallReason input);
static bool FromMojom(crosapi::mojom::InstallReason input,
apps::InstallReason* output);
};
template <>
struct StructTraits<crosapi::mojom::IntentFilterDataView,
apps::IntentFilterPtr> {
static const std::vector<apps::ConditionPtr>& conditions(
const apps::IntentFilterPtr& r) {
return r->conditions;
}
static const std::optional<std::string>& activity_name(
const apps::IntentFilterPtr& r) {
return r->activity_name;
}
static const std::optional<std::string>& activity_label(
const apps::IntentFilterPtr& r) {
return r->activity_label;
}
static bool Read(crosapi::mojom::IntentFilterDataView,
apps::IntentFilterPtr* out);
};
template <>
struct StructTraits<crosapi::mojom::ConditionDataView, apps::ConditionPtr> {
static const apps::ConditionType& condition_type(
const apps::ConditionPtr& r) {
return r->condition_type;
}
static const apps::ConditionValues& condition_values(
const apps::ConditionPtr& r) {
return r->condition_values;
}
static bool Read(crosapi::mojom::ConditionDataView, apps::ConditionPtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::ConditionType, apps::ConditionType> {
static crosapi::mojom::ConditionType ToMojom(apps::ConditionType input);
static bool FromMojom(crosapi::mojom::ConditionType input,
apps::ConditionType* output);
};
template <>
struct StructTraits<crosapi::mojom::ConditionValueDataView,
apps::ConditionValuePtr> {
static const std::string& value(const apps::ConditionValuePtr& r) {
return r->value;
}
static const apps::PatternMatchType& match_type(
const apps::ConditionValuePtr& r) {
return r->match_type;
}
static bool Read(crosapi::mojom::ConditionValueDataView,
apps::ConditionValuePtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::PatternMatchType, apps::PatternMatchType> {
static crosapi::mojom::PatternMatchType ToMojom(apps::PatternMatchType input);
static bool FromMojom(crosapi::mojom::PatternMatchType input,
apps::PatternMatchType* output);
};
template <>
struct EnumTraits<crosapi::mojom::UninstallSource, apps::UninstallSource> {
static crosapi::mojom::UninstallSource ToMojom(apps::UninstallSource input);
static bool FromMojom(crosapi::mojom::UninstallSource input,
apps::UninstallSource* output);
};
template <>
struct StructTraits<crosapi::mojom::CapabilityAccessDataView,
apps::CapabilityAccessPtr> {
static const std::string& app_id(const apps::CapabilityAccessPtr& r) {
return r->app_id;
}
static crosapi::mojom::OptionalBool camera(
const apps::CapabilityAccessPtr& r);
static crosapi::mojom::OptionalBool microphone(
const apps::CapabilityAccessPtr& r);
static bool Read(crosapi::mojom::CapabilityAccessDataView,
apps::CapabilityAccessPtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::IconType, apps::IconType> {
static crosapi::mojom::IconType ToMojom(apps::IconType input);
static bool FromMojom(crosapi::mojom::IconType input, apps::IconType* output);
};
template <>
struct StructTraits<crosapi::mojom::IconValueDataView, apps::IconValuePtr> {
static apps::IconType icon_type(const apps::IconValuePtr& r) {
return r->icon_type;
}
static const gfx::ImageSkia& uncompressed(const apps::IconValuePtr& r) {
return r->uncompressed;
}
static const std::vector<uint8_t>& compressed(const apps::IconValuePtr& r) {
return r->compressed;
}
static bool is_placeholder_icon(const apps::IconValuePtr& r) {
return r->is_placeholder_icon;
}
static bool is_maskable_icon(const apps::IconValuePtr& r) {
return r->is_maskable_icon;
}
static bool Read(crosapi::mojom::IconValueDataView, apps::IconValuePtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::WindowMode, apps::WindowMode> {
static crosapi::mojom::WindowMode ToMojom(apps::WindowMode input);
static bool FromMojom(crosapi::mojom::WindowMode input,
apps::WindowMode* output);
};
template <>
struct EnumTraits<crosapi::mojom::LaunchSource, apps::LaunchSource> {
static crosapi::mojom::LaunchSource ToMojom(apps::LaunchSource input);
static bool FromMojom(crosapi::mojom::LaunchSource input,
apps::LaunchSource* output);
};
template <>
struct StructTraits<crosapi::mojom::PermissionDataView, apps::PermissionPtr> {
static apps::PermissionType permission_type(const apps::PermissionPtr& r) {
return r->permission_type;
}
static const apps::Permission::PermissionValue& value(
const apps::PermissionPtr& r) {
return r->value;
}
static bool is_managed(const apps::PermissionPtr& r) { return r->is_managed; }
static bool Read(crosapi::mojom::PermissionDataView,
apps::PermissionPtr* out);
};
template <>
struct EnumTraits<crosapi::mojom::PermissionType, apps::PermissionType> {
static crosapi::mojom::PermissionType ToMojom(apps::PermissionType input);
static bool FromMojom(crosapi::mojom::PermissionType input,
apps::PermissionType* output);
};
template <>
struct EnumTraits<crosapi::mojom::TriState, apps::TriState> {
static crosapi::mojom::TriState ToMojom(apps::TriState input);
static bool FromMojom(crosapi::mojom::TriState input, apps::TriState* output);
};
template <>
struct UnionTraits<crosapi::mojom::PermissionValueDataView,
apps::Permission::PermissionValue> {
static crosapi::mojom::PermissionValueDataView::Tag GetTag(
const apps::Permission::PermissionValue& r);
static bool IsNull(const apps::Permission::PermissionValue& r) {
return false;
}
static void SetToNull(apps::Permission::PermissionValue* out) {}
static bool bool_value(const apps::Permission::PermissionValue& r) {
if (absl::holds_alternative<bool>(r)) {
return absl::get<bool>(r);
}
return false;
}
static apps::TriState tristate_value(
const apps::Permission::PermissionValue& r) {
if (absl::holds_alternative<apps::TriState>(r)) {
return absl::get<apps::TriState>(r);
}
return apps::TriState::kBlock;
}
static bool Read(crosapi::mojom::PermissionValueDataView data,
apps::Permission::PermissionValue* out);
};
template <>
struct StructTraits<crosapi::mojom::PreferredAppDataView,
apps::PreferredAppPtr> {
static apps::IntentFilterPtr intent_filter(const apps::PreferredAppPtr& r) {
return r->intent_filter->Clone();
}
static const std::string& app_id(const apps::PreferredAppPtr& r) {
return r->app_id;
}
static bool Read(crosapi::mojom::PreferredAppDataView,
apps::PreferredAppPtr* out);
};
template <>
struct StructTraits<crosapi::mojom::PreferredAppChangesDataView,
apps::PreferredAppChangesPtr> {
static base::flat_map<std::string, apps::IntentFilters> added_filters(
const apps::PreferredAppChangesPtr& r) {
return apps::CloneIntentFiltersMap(r->added_filters);
}
static base::flat_map<std::string, apps::IntentFilters> removed_filters(
const apps::PreferredAppChangesPtr& r) {
return apps::CloneIntentFiltersMap(r->removed_filters);
}
static bool Read(crosapi::mojom::PreferredAppChangesDataView,
apps::PreferredAppChangesPtr* out);
};
template <>
struct StructTraits<crosapi::mojom::AppShortcutDataView, apps::ShortcutPtr> {
static const std::string& host_app_id(const apps::ShortcutPtr& r) {
return r->host_app_id;
}
static const std::string& local_id(const apps::ShortcutPtr& r) {
return r->local_id;
}
static const std::optional<std::string>& name(const apps::ShortcutPtr& r) {
return r->name;
}
static apps::IconKeyPtr icon_key(const apps::ShortcutPtr& r);
static const std::optional<bool>& allow_removal(const apps::ShortcutPtr& r) {
return r->allow_removal;
}
static bool Read(crosapi::mojom::AppShortcutDataView data,
apps::ShortcutPtr* out);
};
template <>
struct StructTraits<crosapi::mojom::PackageIdDataView, apps::PackageId> {
static crosapi::mojom::PackageIdType package_type(const apps::PackageId& r);
static const std::string& identifier(const apps::PackageId& r) {
return r.identifier();
}
static bool Read(crosapi::mojom::PackageIdDataView data,
apps::PackageId* out);
};
} // namespace mojo
#endif // CHROMEOS_CROSAPI_MOJOM_APP_SERVICE_TYPES_MOJOM_TRAITS_H_

File diff suppressed because it is too large Load Diff

@ -9,7 +9,6 @@ import "chromeos/components/payments/mojom/payment_app.mojom";
import "chromeos/components/remote_apps/mojom/remote_apps.mojom";
import "chromeos/components/sensors/mojom/cros_sensor_service.mojom";
import "chromeos/crosapi/mojom/account_manager.mojom";
import "chromeos/crosapi/mojom/app_service.mojom";
import "chromeos/crosapi/mojom/arc.mojom";
import "chromeos/crosapi/mojom/audio_service.mojom";
import "chromeos/crosapi/mojom/authentication.mojom";

@ -24,31 +24,6 @@ std::unique_ptr<PreferredApp> PreferredApp::Clone() const {
return std::make_unique<PreferredApp>(intent_filter->Clone(), app_id);
}
PreferredAppChanges::PreferredAppChanges() = default;
PreferredAppChanges::~PreferredAppChanges() = default;
PreferredAppChangesPtr PreferredAppChanges::Clone() const {
auto preferred_app_changes = std::make_unique<PreferredAppChanges>();
for (const auto& added_filter : added_filters) {
apps::IntentFilters filters;
for (auto& filter : added_filter.second) {
filters.push_back(filter->Clone());
}
preferred_app_changes->added_filters[added_filter.first] =
std::move(filters);
}
for (const auto& removed_filter : removed_filters) {
apps::IntentFilters filters;
for (auto& filter : removed_filter.second) {
filters.push_back(filter->Clone());
}
preferred_app_changes->removed_filters[removed_filter.first] =
std::move(filters);
}
return preferred_app_changes;
}
PreferredApps ClonePreferredApps(const PreferredApps& preferred_apps) {
PreferredApps ret;
ret.reserve(preferred_apps.size());

@ -32,22 +32,6 @@ struct COMPONENT_EXPORT(APP_TYPES) PreferredApp {
using PreferredAppPtr = std::unique_ptr<PreferredApp>;
using PreferredApps = std::vector<PreferredAppPtr>;
// Represents changes which have been made to the preferred apps list, both
// adding new filters and removing existing filters.
struct COMPONENT_EXPORT(APP_TYPES) PreferredAppChanges {
PreferredAppChanges();
PreferredAppChanges(const PreferredAppChanges&) = delete;
PreferredAppChanges& operator=(const PreferredAppChanges&) = delete;
~PreferredAppChanges();
std::unique_ptr<PreferredAppChanges> Clone() const;
base::flat_map<std::string, IntentFilters> added_filters;
base::flat_map<std::string, IntentFilters> removed_filters;
};
using PreferredAppChangesPtr = std::unique_ptr<PreferredAppChanges>;
// Represents a group of `app_ids` that is no longer preferred app of their
// corresponding `intent_filters`.
using ReplacedAppPreferences = base::flat_map<std::string, IntentFilters>;

@ -9,6 +9,7 @@
#include <utility>
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/json/json_string_value_serializer.h"
@ -203,8 +204,6 @@ void PreferredAppsImpl::ReadCompleted(std::string preferred_apps_string) {
WriteToJSON(profile_dir_, preferred_apps_list_);
}
host_->InitializePreferredAppsForAllSubscribers();
LogPreferredAppEntryCount(preferred_apps_list_.GetEntrySize());
while (!pending_preferred_apps_tasks_.empty()) {
@ -229,23 +228,16 @@ void PreferredAppsImpl::RemovePreferredAppImpl(const std::string& app_id) {
IntentFilters removed_filters = preferred_apps_list_.DeleteAppId(app_id);
if (!removed_filters.empty()) {
WriteToJSON(profile_dir_, preferred_apps_list_);
auto changes = std::make_unique<PreferredAppChanges>();
changes->removed_filters[app_id] = std::move(removed_filters);
host_->OnPreferredAppsChanged(std::move(changes));
}
}
void PreferredAppsImpl::SetSupportedLinksPreferenceImpl(
const std::string& app_id,
IntentFilters all_link_filters) {
auto changes = std::make_unique<PreferredAppChanges>();
auto& added = changes->added_filters;
auto& removed = changes->removed_filters;
base::flat_map<std::string, IntentFilters> removed;
for (auto& filter : all_link_filters) {
auto replaced_apps = preferred_apps_list_.AddPreferredApp(app_id, filter);
added[app_id].push_back(std::move(filter));
// If we removed overlapping supported links when adding the new app, those
// affected apps no longer handle all their Supported Links filters and so
@ -281,8 +273,6 @@ void PreferredAppsImpl::SetSupportedLinksPreferenceImpl(
WriteToJSON(profile_dir_, preferred_apps_list_);
host_->OnPreferredAppsChanged(changes->Clone());
// Notify publishers: The new app has been set to open links, and all removed
// apps no longer handle links.
host_->OnSupportedLinksPreferenceChanged(app_id,
@ -300,10 +290,6 @@ void PreferredAppsImpl::RemoveSupportedLinksPreferenceImpl(
if (!removed_filters.empty()) {
WriteToJSON(profile_dir_, preferred_apps_list_);
auto changes = std::make_unique<PreferredAppChanges>();
changes->removed_filters[app_id] = std::move(removed_filters);
host_->OnPreferredAppsChanged(std::move(changes));
}
host_->OnSupportedLinksPreferenceChanged(app_id,

@ -37,18 +37,6 @@ class PreferredAppsImpl {
Host& operator=(const Host&) = delete;
~Host() = default;
// Called when the PreferredAppsList has been loaded from disk, and can
// be used to initialize subscribers.
// Only implemented in Ash, to support initializing the Lacros copy of the
// PreferredAppsList.
virtual void InitializePreferredAppsForAllSubscribers() {}
// Called when changes have been made to the PreferredAppsList which should
// be propagated to subscribers.
// Only implemented in Ash, to support updating the Lacros copy of the
// PreferredAppsList.
virtual void OnPreferredAppsChanged(PreferredAppChangesPtr changes) {}
// Notifies the host that the supported links preference for a particular
// `app_id` was enabled/disabled. Used by the host to notify the app
// publisher (if any) of the change.

@ -7,7 +7,6 @@
#include <algorithm>
#include <utility>
#include "base/containers/contains.h"
#include "base/observer_list.h"
#include "base/strings/string_util.h"
#include "components/services/app_service/public/cpp/intent_filter_util.h"
@ -150,65 +149,6 @@ IntentFilters PreferredAppsList::DeleteSupportedLinks(
return out;
}
void PreferredAppsList::ApplyBulkUpdate(apps::PreferredAppChangesPtr changes) {
// Process removed filters first. There's no difference in behavior whether we
// handle removals or additions first, but doing removals first means there
// are fewer items in the list to search through when finding matches.
for (const auto& removed_filters : changes->removed_filters) {
const std::string& app_id = removed_filters.first;
const auto& filters = removed_filters.second;
// To process removals for an app, go through the current list and remove
// any filters which match the bulk update. Any items which exist in the
// bulk update but not in the current list will be silently ignored.
auto iter = preferred_apps_.begin();
while (iter != preferred_apps_.end()) {
if ((*iter)->app_id == app_id &&
Contains(filters, (*iter)->intent_filter)) {
iter = preferred_apps_.erase(iter);
} else {
iter++;
}
}
bool has_supported_link =
std::ranges::any_of(filters, [&app_id](const auto& filter) {
return apps_util::IsSupportedLinkForApp(app_id, filter);
});
// Notify observers if any of the removed filters were supported links.
// TODO(crbug.com/40791690): Notify observers about all changes, not just
// changes to supported links status.
if (has_supported_link) {
for (auto& obs : observers_) {
obs.OnPreferredAppChanged(app_id, false);
}
}
}
// Added filters are appended to the preferred app list with no changes.
for (auto& added_filters : changes->added_filters) {
const std::string& app_id = added_filters.first;
bool has_supported_link = false;
for (auto& filter : added_filters.second) {
if (EntryExists(app_id, filter)) {
continue;
}
has_supported_link = has_supported_link ||
apps_util::IsSupportedLinkForApp(app_id, filter);
preferred_apps_.push_back(
std::make_unique<PreferredApp>(std::move(filter), app_id));
}
// Notify observers if any of the added filters added were supported links.
if (has_supported_link) {
for (auto& obs : observers_) {
obs.OnPreferredAppChanged(app_id, true);
}
}
}
}
bool PreferredAppsList::IsInitialized() const {
return initialized_;
}

@ -52,14 +52,6 @@ class PreferredAppsList : public PreferredAppsListHandle {
// Returns the deleted filters, if any.
IntentFilters DeleteSupportedLinks(const std::string& app_id);
// Applies all of the |changes| in a single bulk update. This method is
// intended to only be called from |OnPreferredAppsChanged| App Service
// subscriber overrides.
// Note that removed filters are processed before new filters are added. If
// the same filter appears in both |changes->added_filters| and
// |changes->removed_filters|, it be removed and then immediately added back.
void ApplyBulkUpdate(apps::PreferredAppChangesPtr changes);
// PreferredAppsListHandler overrides:
bool IsInitialized() const override;
size_t GetEntrySize() const override;

@ -672,105 +672,6 @@ TEST_F(PreferredAppListTest, DeleteSupportedLinksForMultipleConditionValues) {
GURL("ftp://www.example.com")));
}
TEST_F(PreferredAppListTest, ApplyBulkUpdateAdditions) {
GURL filter_url_1 = GURL("https://www.google.com/abc");
auto intent_filter_1 = apps_util::MakeIntentFilterForUrlScope(filter_url_1);
GURL filter_url_2 = GURL("https://www.google.com/def");
auto intent_filter_2 = apps_util::MakeIntentFilterForUrlScope(filter_url_2);
GURL filter_url_3 = GURL("https://www.google.com/hij");
auto intent_filter_3 = apps_util::MakeIntentFilterForUrlScope(filter_url_3);
auto changes = std::make_unique<apps::PreferredAppChanges>();
changes->added_filters[kAppId1].push_back(intent_filter_1->Clone());
changes->added_filters[kAppId1].push_back(intent_filter_2->Clone());
changes->added_filters[kAppId2].push_back(intent_filter_3->Clone());
preferred_apps_.ApplyBulkUpdate(std::move(changes));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_1));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_2));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_3));
}
TEST_F(PreferredAppListTest, ApplyBulkUpdateDuplicateAdditions) {
GURL filter_url_1 = GURL("https://www.google.com/abc");
auto intent_filter_1 = apps_util::MakeIntentFilterForUrlScope(filter_url_1);
GURL filter_url_2 = GURL("https://www.google.com/def");
auto intent_filter_2 = apps_util::MakeIntentFilterForUrlScope(filter_url_2);
GURL filter_url_3 = GURL("https://www.google.com/hij");
auto intent_filter_3 = apps_util::MakeIntentFilterForUrlScope(filter_url_3);
auto changes = std::make_unique<apps::PreferredAppChanges>();
changes->added_filters[kAppId1].push_back(intent_filter_1->Clone());
changes->added_filters[kAppId1].push_back(intent_filter_2->Clone());
changes->added_filters[kAppId2].push_back(intent_filter_3->Clone());
preferred_apps_.ApplyBulkUpdate(changes->Clone());
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_1));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_2));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_3));
EXPECT_EQ(3U, preferred_apps_.GetEntrySize());
preferred_apps_.ApplyBulkUpdate(changes->Clone());
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_1));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_2));
EXPECT_EQ(kAppId2, preferred_apps_.FindPreferredAppForUrl(filter_url_3));
EXPECT_EQ(3U, preferred_apps_.GetEntrySize());
}
// Test that you can add and remove overlapping filters with a single call to
// ApplyBulkUpdate.
TEST_F(PreferredAppListTest, ApplyBulkUpdateAddAndRemove) {
GURL filter_url_base = GURL("https://www.google.com/foo");
auto intent_filter_base =
apps_util::MakeIntentFilterForUrlScope(filter_url_base);
GURL filter_url_ext = GURL("https://www.google.com/foo/bar");
auto intent_filter_ext =
apps_util::MakeIntentFilterForUrlScope(filter_url_ext);
preferred_apps_.AddPreferredApp(kAppId1, intent_filter_base);
auto changes = std::make_unique<apps::PreferredAppChanges>();
changes->added_filters[kAppId1].push_back(intent_filter_ext->Clone());
changes->removed_filters[kAppId1].push_back(intent_filter_base->Clone());
preferred_apps_.ApplyBulkUpdate(std::move(changes));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_ext));
EXPECT_EQ(std::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_base));
}
// Test that removing a filter using ApplyBulkUpdate only removes filters which
// match exactly, and not anything that overlaps.
TEST_F(PreferredAppListTest, ApplyBulkUpdateRemoveMatchesExactly) {
GURL filter_url_base = GURL("https://www.google.com/foo");
auto intent_filter_base =
apps_util::MakeIntentFilterForUrlScope(filter_url_base);
GURL filter_url_ext = GURL("https://www.google.com/foo/bar");
auto intent_filter_ext =
apps_util::MakeIntentFilterForUrlScope(filter_url_ext);
preferred_apps_.AddPreferredApp(kAppId1, intent_filter_ext);
auto changes = std::make_unique<apps::PreferredAppChanges>();
changes->removed_filters[kAppId1].push_back(intent_filter_base->Clone());
preferred_apps_.ApplyBulkUpdate(std::move(changes));
EXPECT_EQ(kAppId1, preferred_apps_.FindPreferredAppForUrl(filter_url_ext));
changes = std::make_unique<apps::PreferredAppChanges>();
changes->removed_filters[kAppId1].push_back(intent_filter_ext->Clone());
preferred_apps_.ApplyBulkUpdate(std::move(changes));
EXPECT_EQ(std::nullopt,
preferred_apps_.FindPreferredAppForUrl(filter_url_ext));
}
// Test that FindPreferredAppsForFilters() returns an empty flat_set if there
// are no matches.
TEST_F(PreferredAppListTest, FindNoPreferredApps) {