0

Remove lock screen app [CL#6]: ActionData and action handlers.

They're added for and used only by lock screen apps.

Bug: 376354347, 379562630

Change-Id: I46df0399300565afc8b9fc0c799a002a43c69eda
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5986568
Reviewed-by: Finnur Thorarinsson <finnur@chromium.org>
Commit-Queue: Mitsuru Oshima <oshima@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1421155}
This commit is contained in:
Mitsuru Oshima 2025-02-17 14:02:03 -08:00 committed by Chromium LUCI CQ
parent 934fc529da
commit 966fa8774c
27 changed files with 10 additions and 598 deletions

@ -129,15 +129,6 @@ class PlatformAppPathLauncher
PlatformAppPathLauncher(const PlatformAppPathLauncher&) = delete;
PlatformAppPathLauncher& operator=(const PlatformAppPathLauncher&) = delete;
void set_action_data(std::optional<app_runtime::ActionData> action_data) {
#if BUILDFLAG(IS_CHROMEOS)
if (base::FeatureList::IsEnabled(
extensions_features::kApiRuntimeActionData)) {
action_data_ = std::move(action_data);
}
#endif
}
void set_launch_source(extensions::AppLaunchSource launch_source) {
launch_source_ = launch_source;
}
@ -222,13 +213,6 @@ class PlatformAppPathLauncher
app_runtime::LaunchData launch_data;
// TODO(crbug.com/40235429): This conditional block is being added here
// temporarily, and should be removed once the underlying type of
// |launch_data.action_data| is wrapped with std::optional<T>.
if (action_data_) {
launch_data.action_data = std::move(*action_data_);
action_data_.reset();
}
if (!handler_id_.empty())
launch_data.id = handler_id_;
@ -344,8 +328,7 @@ class PlatformAppPathLauncher
}
AppRuntimeEventRouter::DispatchOnLaunchedEventWithFileEntries(
context_, app, launch_source_, handler_id_, entries_, granted_entries,
std::move(action_data_));
context_, app, launch_source_, handler_id_, entries_, granted_entries);
}
const Extension* GetExtension() const {
@ -361,7 +344,6 @@ class PlatformAppPathLauncher
const extensions::ExtensionId extension_id;
extensions::AppLaunchSource launch_source_ =
extensions::AppLaunchSource::kSourceFileHandler;
std::optional<app_runtime::ActionData> action_data_;
// A list of files and directories to be passed through to the app.
std::vector<base::FilePath> entry_paths_;
// A corresponding list with EntryInfo for every base::FilePath in
@ -452,11 +434,9 @@ void LaunchPlatformAppWithFilePaths(
}
void LaunchPlatformAppWithAction(content::BrowserContext* context,
const extensions::Extension* app,
app_runtime::ActionData action_data) {
const extensions::Extension* app) {
scoped_refptr<PlatformAppPathLauncher> launcher =
new PlatformAppPathLauncher(context, app, base::FilePath());
launcher->set_action_data(std::move(action_data));
launcher->set_launch_source(extensions::AppLaunchSource::kSourceUntracked);
launcher->Launch();
}

@ -25,11 +25,6 @@ class BrowserContext;
namespace extensions {
class Extension;
namespace api {
namespace app_runtime {
struct ActionData;
}
}
}
namespace apps {
@ -69,10 +64,8 @@ void LaunchPlatformAppWithFilePaths(
const std::vector<base::FilePath>& file_paths);
// Launches the platform app |app| with the specific |action_data|.
void LaunchPlatformAppWithAction(
content::BrowserContext* context,
const extensions::Extension* app,
extensions::api::app_runtime::ActionData action_data);
void LaunchPlatformAppWithAction(content::BrowserContext* context,
const extensions::Extension* app);
// Launches the platform app |app|. |source| tells us how the app is launched.
void LaunchPlatformApp(content::BrowserContext* context,

@ -56,7 +56,6 @@
#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 "extensions/common/manifest_handlers/action_handlers_handler.h"
#include "storage/browser/file_system/file_system_url.h"
#endif // BUILDFLAG(IS_CHROMEOS)
@ -366,13 +365,6 @@ apps::IntentFilters CreateIntentFiltersForChromeApp(
return filters;
}
#if BUILDFLAG(IS_CHROMEOS)
if (extensions::ActionHandlersInfo::HasActionHandler(
extension, extensions::api::app_runtime::ActionType::kNewNote)) {
filters.push_back(CreateNoteTakingFilter());
}
#endif
const extensions::FileHandlersInfo* file_handlers =
extensions::FileHandlers::GetFileHandlers(extension);
if (!file_handlers) {

@ -309,37 +309,6 @@ TEST_F(IntentUtilsTest, CreateIntentFiltersForChromeApp_FileHandlers) {
}
#if BUILDFLAG(IS_CHROMEOS)
TEST_F(IntentUtilsTest, CreateIntentFiltersForChromeApp_NoteTaking) {
const std::string note_action_handler =
extensions::api::app_runtime::ToString(
extensions::api::app_runtime::ActionType::kNewNote);
// Foo app has a note-taking action handler.
extensions::ExtensionBuilder foo_app("Foo");
std::string manifest = base::StringPrintf(R"(
"manifest_version": 2,
"version": "1.0.0",
"action_handlers": ["%s"],
"app": {"background": {"scripts": ["background.js"]}}
)",
note_action_handler.c_str());
foo_app.AddJSON(manifest).BuildManifest();
scoped_refptr<const extensions::Extension> foo = foo_app.Build();
IntentFilters filters = apps_util::CreateIntentFiltersForChromeApp(foo.get());
ASSERT_EQ(filters.size(), 1u);
const IntentFilterPtr& filter = filters[0];
ASSERT_EQ(filter->conditions.size(), 1u);
const Condition& condition = *filter->conditions[0];
EXPECT_EQ(condition.condition_type, ConditionType::kAction);
ASSERT_EQ(condition.condition_values.size(), 1u);
EXPECT_EQ(condition.condition_values[0]->value,
apps_util::kIntentActionCreateNote);
apps::IntentPtr intent = apps_util::CreateCreateNoteIntent();
EXPECT_TRUE(intent->MatchFilter(filter));
}
TEST_F(IntentUtilsTest, CreateIntentFiltersForExtension_FileHandlers) {
// Foo extension provides file_browser_handlers for html and anything.
extensions::ExtensionBuilder foo_ext("Foo");

@ -64,7 +64,6 @@
#include "extensions/common/api/app_runtime.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_handlers/action_handlers_handler.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "ui/display/display.h"
#include "ui/display/util/display_util.h"
@ -274,8 +273,6 @@ void NoteTakingHelper::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
// TODO(crbug.com/40227659): Remove this method and observe LockScreenHelper for
// app updates instead.
void NoteTakingHelper::NotifyAppUpdated(Profile* profile,
const std::string& app_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@ -640,9 +637,7 @@ NoteTakingHelper::LaunchResult NoteTakingHelper::LaunchAppInternal(
LOG(WARNING) << "Failed to find note-taking app " << app_id;
return LaunchResult::CHROME_APP_MISSING;
}
app_runtime::ActionData action_data;
action_data.action_type = app_runtime::ActionType::kNewNote;
launch_chrome_app_callback_.Run(profile, app, std::move(action_data));
launch_chrome_app_callback_.Run(profile, app);
return LaunchResult::CHROME_SUCCESS;
}

@ -35,11 +35,6 @@ class BrowserContext;
namespace extensions {
class Extension;
namespace api {
namespace app_runtime {
struct ActionData;
} // namespace app_runtime
} // namespace api
} // namespace extensions
namespace ash {
@ -114,8 +109,7 @@ class NoteTakingHelper : public arc::ArcIntentHelperObserver,
// Callback used to launch a Chrome app.
using LaunchChromeAppCallback =
base::RepeatingCallback<void(content::BrowserContext* context,
const extensions::Extension*,
extensions::api::app_runtime::ActionData)>;
const extensions::Extension*)>;
// Intent action used to launch Android apps.
static const char kIntentAction[];

@ -340,34 +340,6 @@ class NoteTakingHelperTest : public BrowserWithTestWindowTest {
extensions::UninstallReason::UNINSTALL_REASON_FOR_TESTING, &error);
}
scoped_refptr<const extensions::Extension> CreateAndInstallLockScreenApp(
const std::string& id,
const std::string& app_name,
Profile* profile) {
return CreateAndInstallLockScreenAppWithPermissions(
id, app_name, base::Value::List().Append("lockScreen"), profile);
}
scoped_refptr<const extensions::Extension>
CreateAndInstallLockScreenAppWithPermissions(
const std::string& id,
const std::string& app_name,
std::optional<base::Value::List> permissions,
Profile* profile) {
base::Value::List lock_enabled_action_handler = base::Value::List().Append(
base::Value::Dict()
.Set("action",
app_runtime::ToString(app_runtime::ActionType::kNewNote))
.Set("enabled_on_lock_screen", true));
scoped_refptr<const extensions::Extension> keep_extension =
CreateExtension(id, app_name, std::move(permissions),
std::move(lock_enabled_action_handler));
InstallExtension(keep_extension.get(), profile);
return keep_extension;
}
// BrowserWithTestWindowTest:
std::optional<std::string> GetDefaultProfileName() override {
return kTestProfileName;
@ -470,10 +442,8 @@ class NoteTakingHelperTest : public BrowserWithTestWindowTest {
private:
// Callback registered with the helper to record Chrome app launch requests.
void LaunchChromeApp(content::BrowserContext* passed_context,
const extensions::Extension* extension,
app_runtime::ActionData action_data) {
const extensions::Extension* extension) {
EXPECT_EQ(profile(), passed_context);
EXPECT_EQ(app_runtime::ActionType::kNewNote, action_data.action_type);
launched_chrome_apps_.push_back(ChromeAppLaunchInfo{extension->id()});
}
@ -546,70 +516,6 @@ TEST_F(NoteTakingHelperTest, ListChromeApps) {
EXPECT_EQ(helper()->GetPreferredAppId(profile()), kProdKeepExtensionId);
}
TEST_F(NoteTakingHelperTest, ListChromeAppsWithLockScreenNotesSupported) {
Init(ENABLE_PALETTE);
ASSERT_FALSE(helper()->IsAppAvailable(profile()));
ASSERT_TRUE(helper()->GetAvailableApps(profile()).empty());
base::Value::List lock_disabled_action_handler = base::Value::List().Append(
app_runtime::ToString(app_runtime::ActionType::kNewNote));
// Install Keep app that does not support lock screen note taking - it should
// be reported not to support lock screen note taking.
scoped_refptr<const extensions::Extension> prod_extension = CreateExtension(
kProdKeepExtensionId, kProdKeepAppName, /*permissions=*/std::nullopt,
std::move(lock_disabled_action_handler));
InstallExtension(prod_extension.get(), profile());
EXPECT_TRUE(helper()->IsAppAvailable(profile()));
EXPECT_TRUE(AvailableAppsMatch(
profile(),
{{kProdKeepAppName, kProdKeepExtensionId, false /*preferred*/}}));
EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty());
// Install additional Keep app - one that supports lock screen note taking.
// This app should be reported to support note taking.
scoped_refptr<const extensions::Extension> dev_extension =
CreateAndInstallLockScreenApp(kDevKeepExtensionId, kDevKeepAppName,
profile());
EXPECT_TRUE(AvailableAppsMatch(
profile(),
{{kDevKeepAppName, kDevKeepExtensionId, false /*preferred*/},
{kProdKeepAppName, kProdKeepExtensionId, false /*preferred*/}}));
EXPECT_TRUE(helper()->GetPreferredAppId(profile()).empty());
}
// Verify the note helper detects apps with "new_note" "action_handler" manifest
// entries.
TEST_F(NoteTakingHelperTest, CustomChromeApps) {
Init(ENABLE_PALETTE);
const extensions::ExtensionId kNewNoteId = crx_file::id_util::GenerateId("a");
const extensions::ExtensionId kEmptyArrayId =
crx_file::id_util::GenerateId("b");
const extensions::ExtensionId kEmptyId = crx_file::id_util::GenerateId("c");
const std::string kName = "Some App";
// "action_handlers": ["new_note"]
scoped_refptr<const extensions::Extension> has_new_note = CreateExtension(
kNewNoteId, kName, /*permissions=*/std::nullopt,
base::Value::List().Append(
app_runtime::ToString(app_runtime::ActionType::kNewNote)));
InstallExtension(has_new_note.get(), profile());
// "action_handlers": []
scoped_refptr<const extensions::Extension> empty_array = CreateExtension(
kEmptyArrayId, kName, /*permissions=*/std::nullopt, base::Value::List());
InstallExtension(empty_array.get(), profile());
// (no action handler entry)
scoped_refptr<const extensions::Extension> none =
CreateExtension(kEmptyId, kName);
InstallExtension(none.get(), profile());
// Only the "new_note" extension is returned from GetAvailableApps.
EXPECT_TRUE(AvailableAppsMatch(profile(),
{{kName, kNewNoteId, false /*preferred*/}}));
}
// Web apps with a note_taking_new_note_url show as available note-taking apps.
TEST_F(NoteTakingHelperTest, NoteTakingWebAppsListed) {
Init(ENABLE_PALETTE);
@ -723,33 +629,6 @@ TEST_F(NoteTakingHelperTest_WebLockScreenApiEnabled, LockScreenWebAppsListed) {
{"Web App 2", app2_id, /*preferred=*/false}}));
}
// Verify that non-allowlisted apps cannot be enabled on lock screen.
TEST_F(NoteTakingHelperTest, CustomLockScreenEnabledApps) {
Init(ENABLE_PALETTE);
const extensions::ExtensionId kNewNoteId = crx_file::id_util::GenerateId("a");
const std::string kName = "Some App";
scoped_refptr<const extensions::Extension> extension =
CreateAndInstallLockScreenApp(kNewNoteId, kName, profile());
EXPECT_TRUE(AvailableAppsMatch(profile(),
{{kName, kNewNoteId, false /*preferred*/}}));
}
TEST_F(NoteTakingHelperTest, AllowlistedAndCustomAppsShowOnlyOnce) {
Init(ENABLE_PALETTE);
scoped_refptr<const extensions::Extension> extension = CreateExtension(
kProdKeepExtensionId, "Keep", /*permissions=*/std::nullopt,
base::Value::List().Append(
app_runtime::ToString(app_runtime::ActionType::kNewNote)));
InstallExtension(extension.get(), profile());
EXPECT_TRUE(AvailableAppsMatch(
profile(), {{"Keep", kProdKeepExtensionId, false /*preferred*/}}));
}
TEST_F(NoteTakingHelperTest, LaunchChromeApp) {
Init(ENABLE_PALETTE);
scoped_refptr<const extensions::Extension> extension =

@ -50,7 +50,6 @@ group("browser_tests") {
testonly = true
deps = [
"//chrome/browser/chromeos/extensions/action_handlers:browser_tests",
"//chrome/browser/chromeos/extensions/contact_center_insights:browser_tests",
"//chrome/browser/chromeos/extensions/echo_private:browser_tests",
"//chrome/browser/chromeos/extensions/file_system_provider:browser_tests",

@ -1,24 +0,0 @@
# Copyright 2024 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
assert(is_chromeos)
source_set("browser_tests") {
testonly = true
defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
sources = [ "action_handlers_apitest.cc" ]
deps = [
"//apps",
"//base",
"//chrome/browser/profiles:profile",
"//chrome/common:constants",
"//chrome/test:test_support",
"//content/test:test_support",
"//extensions:test_support",
"//extensions/common",
]
}

@ -1,17 +0,0 @@
include_rules = [
# ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for
# details.
"-chrome",
# This directory is in //chrome, which violates the rule above. Allow this
# directory to #include its own files.
"+chrome/browser/chromeos/extensions/action_handlers",
# Existing dependencies within //chrome. There is an active effort to
# refactor chromeos codes in //chrome to break these dependencies; see
# b/332804822. Whenever possible, avoid adding new //chrome dependencies to
# this list.
"+chrome/browser/extensions/extension_apitest.h",
"+chrome/browser/profiles/profile.h",
"+chrome/common",
]

@ -1,41 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "apps/launcher.h"
#include "base/feature_list.h"
#include "base/path_service.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "content/public/test/browser_test.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/manifest_handlers/action_handlers_handler.h"
#include "extensions/test/extension_test_message_listener.h"
namespace app_runtime = extensions::api::app_runtime;
using ActionHandlersBrowserTest = extensions::ExtensionApiTest;
IN_PROC_BROWSER_TEST_F(ActionHandlersBrowserTest, LaunchAppWithNewNote) {
if (!base::FeatureList::IsEnabled(
extensions_features::kApiRuntimeActionData)) {
return;
}
// Load the app. Make sure to wait until it is done loading.
ExtensionTestMessageListener loader("loaded");
base::FilePath path =
test_data_dir_.AppendASCII("action_handlers").AppendASCII("new_note");
const extensions::Extension* app = LoadExtension(path);
ASSERT_TRUE(app);
EXPECT_TRUE(extensions::ActionHandlersInfo::HasActionHandler(
app, app_runtime::ActionType::kNewNote));
EXPECT_TRUE(loader.WaitUntilSatisfied());
// Fire a "new_note" action type, assert that app has received it.
ExtensionTestMessageListener new_note("hasNewNote = true");
app_runtime::ActionData action_data;
action_data.action_type = app_runtime::ActionType::kNewNote;
apps::LaunchPlatformAppWithAction(profile(), app, std::move(action_data));
EXPECT_TRUE(new_note.WaitUntilSatisfied());
}

@ -406,12 +406,6 @@ void ChromeAppDelegate::OnShow() {
}
}
bool ChromeAppDelegate::TakeFocus(content::WebContents* web_contents,
bool reverse) {
// TODO(crbug.com/376354347): Remove this method.
return false;
}
content::PictureInPictureResult ChromeAppDelegate::EnterPictureInPicture(
content::WebContents* web_contents) {
return PictureInPictureWindowManager::GetInstance()

@ -75,7 +75,6 @@ class ChromeAppDelegate : public extensions::AppDelegate {
void SetTerminatingCallback(base::OnceClosure callback) override;
void OnHide() override;
void OnShow() override;
bool TakeFocus(content::WebContents* web_contents, bool reverse) override;
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents) override;
void ExitPictureInPicture() override;

@ -125,9 +125,6 @@ class COMPONENT_EXPORT(ASH_BROWSER_CONTEXT_HELPER) BrowserContextHelper {
// this loads the BrowserContext instance, instead of returning nullptr.
content::BrowserContext* DeprecatedGetOrCreateSigninBrowserContext();
// Returns the path of lock-screen-app browser context.
base::FilePath GetLockScreenAppBrowserContextPath() const;
// Returns the path of lock-screen browser context.
base::FilePath GetLockScreenBrowserContextPath() const;

@ -205,8 +205,7 @@ void AppRuntimeEventRouter::DispatchOnLaunchedEventWithFileEntries(
extensions::AppLaunchSource source,
const std::string& handler_id,
const std::vector<EntryInfo>& entries,
const std::vector<GrantedFileEntry>& file_entries,
std::optional<app_runtime::ActionData> action_data) {
const std::vector<GrantedFileEntry>& file_entries) {
app_runtime::LaunchSource source_enum = GetLaunchSourceEnum(source);
// TODO(sergeygs): Use the same way of creating an event (using the generated
@ -218,10 +217,6 @@ void AppRuntimeEventRouter::DispatchOnLaunchedEventWithFileEntries(
launch_data.Set("source", app_runtime::ToString(source_enum));
}
if (action_data) {
launch_data.Set("actionData", action_data->ToValue());
}
base::Value::List items;
DCHECK(file_entries.size() == entries.size());
for (size_t i = 0; i < file_entries.size(); ++i) {

@ -21,7 +21,6 @@ class BrowserContext;
namespace extensions {
namespace api::app_runtime {
struct ActionData;
struct LaunchData;
} // namespace api::app_runtime
@ -70,8 +69,7 @@ class AppRuntimeEventRouter {
AppLaunchSource source,
const std::string& handler_id,
const std::vector<EntryInfo>& entries,
const std::vector<GrantedFileEntry>& file_entries,
std::optional<api::app_runtime::ActionData> action_data);
const std::vector<GrantedFileEntry>& file_entries);
// |handler_id| corresponds to the id of the url_handlers item
// in the manifest that resulted in a match which triggered this launch.

@ -97,11 +97,6 @@ class AppDelegate {
virtual void OnHide() = 0;
virtual void OnShow() = 0;
// Called when app web contents finishes focus traversal - gives the delegate
// a chance to handle the focus change.
// Return whether focus has been handled.
virtual bool TakeFocus(content::WebContents* web_contents, bool reverse) = 0;
// Notifies the Picture-in-Picture controller that there is a new player
// entering Picture-in-Picture.
// Returns the result of the enter request.

@ -465,10 +465,6 @@ bool AppWindow::PreHandleGestureEvent(WebContents* source,
return AppWebContentsHelper::ShouldSuppressGestureEvent(event);
}
bool AppWindow::TakeFocus(WebContents* source, bool reverse) {
return app_delegate_->TakeFocus(source, reverse);
}
content::PictureInPictureResult AppWindow::EnterPictureInPicture(
content::WebContents* web_contents) {
return app_delegate_->EnterPictureInPicture(web_contents);

@ -456,7 +456,6 @@ class AppWindow : public content::WebContentsDelegate,
bool last_unlocked_by_target) override;
bool PreHandleGestureEvent(content::WebContents* source,
const blink::WebGestureEvent& event) override;
bool TakeFocus(content::WebContents* source, bool reverse) override;
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents) override;
void ExitPictureInPicture() override;

@ -564,8 +564,6 @@ static_library("common") {
if (is_chromeos) {
sources += [
"manifest_handlers/action_handlers_handler.cc",
"manifest_handlers/action_handlers_handler.h",
"manifest_handlers/input_components_handler.cc",
"manifest_handlers/input_components_handler.h",
]
@ -716,10 +714,7 @@ source_set("unit_tests") {
]
if (is_chromeos) {
sources += [
"manifest_handlers/action_handlers_handler_unittest.cc",
"manifest_handlers/file_handler_manifest_unittest.cc",
]
sources += [ "manifest_handlers/file_handler_manifest_unittest.cc" ]
}
data = [

@ -51,20 +51,6 @@ namespace app.runtime {
sparky
};
// An app can be launched with a specific action in mind, for example, to
// create a new note. The type of action the app was launched
// with is available inside of the |actionData| field from the LaunchData
// instance.
enum ActionType {
// The user wants to quickly take a new note.
new_note
};
// Optional data that includes action-specific launch information.
dictionary ActionData {
ActionType actionType;
};
// Optional data for the launch. Either <code>items</code>, or
// the pair (<code>url, referrerUrl</code>) can be present for any given
// launch.
@ -102,11 +88,6 @@ namespace app.runtime {
// Where the app is launched from.
LaunchSource? source;
// Contains data that specifies the <code>ActionType</code> this app was
// launched with. This is null if the app was not launched with a specific
// action intent.
ActionData? actionData;
};
// This object specifies details and operations to perform on the embedding

@ -46,7 +46,6 @@
#include "extensions/common/manifest_url_handlers.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "extensions/common/manifest_handlers/action_handlers_handler.h"
#include "extensions/common/manifest_handlers/input_components_handler.h"
#endif
@ -57,9 +56,6 @@ void RegisterCommonManifestHandlers() {
ManifestHandlerRegistry* registry = ManifestHandlerRegistry::Get();
registry->RegisterHandler(std::make_unique<AboutPageHandler>());
#if BUILDFLAG(IS_CHROMEOS)
registry->RegisterHandler(std::make_unique<ActionHandlersHandler>());
#endif
registry->RegisterHandler(std::make_unique<AutomationHandler>());
registry->RegisterHandler(std::make_unique<AppDisplayManifestHandler>());
registry->RegisterHandler(std::make_unique<BackgroundManifestHandler>());

@ -1,87 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "extensions/common/manifest_handlers/action_handlers_handler.h"
#include <memory>
#include <utility>
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/manifest_constants.h"
namespace extensions {
namespace app_runtime = api::app_runtime;
namespace errors = manifest_errors;
namespace keys = manifest_keys;
// static
bool ActionHandlersInfo::HasActionHandler(
const Extension* extension,
api::app_runtime::ActionType action_type) {
ActionHandlersInfo* info = static_cast<ActionHandlersInfo*>(
extension->GetManifestData(keys::kActionHandlers));
return info && info->action_handlers.count(action_type) > 0;
}
ActionHandlersInfo::ActionHandlersInfo() = default;
ActionHandlersInfo::~ActionHandlersInfo() = default;
ActionHandlersHandler::ActionHandlersHandler() = default;
ActionHandlersHandler::~ActionHandlersHandler() = default;
bool ActionHandlersHandler::Parse(Extension* extension, std::u16string* error) {
const base::Value* entries = nullptr;
if (!extension->manifest()->GetList(keys::kActionHandlers, &entries)) {
*error = errors::kInvalidActionHandlersType;
return false;
}
auto info = std::make_unique<ActionHandlersInfo>();
for (const base::Value& wrapped_value : entries->GetList()) {
std::string value;
if (wrapped_value.is_dict()) {
const base::Value::Dict& wrapped_dict = wrapped_value.GetDict();
const std::string* action =
wrapped_dict.FindString(keys::kActionHandlerActionKey);
if (!action) {
*error = errors::kInvalidActionHandlerDictionary;
return false;
}
value = *action;
} else if (wrapped_value.is_string()) {
value = wrapped_value.GetString();
} else {
*error = errors::kInvalidActionHandlersType;
return false;
}
app_runtime::ActionType action_type = app_runtime::ParseActionType(value);
if (action_type == app_runtime::ActionType::kNone) {
*error = ErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidActionHandlersActionType, value);
return false;
}
if (info->action_handlers.count(action_type) > 0) {
*error = ErrorUtils::FormatErrorMessageUTF16(
errors::kDuplicateActionHandlerFound, value);
return false;
}
info->action_handlers.insert(action_type);
}
extension->SetManifestData(keys::kActionHandlers, std::move(info));
return true;
}
base::span<const char* const> ActionHandlersHandler::Keys() const {
static constexpr const char* kKeys[] = {keys::kActionHandlers};
return kKeys;
}
} // namespace extensions

@ -1,48 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef EXTENSIONS_COMMON_MANIFEST_HANDLERS_ACTION_HANDLERS_HANDLER_H_
#define EXTENSIONS_COMMON_MANIFEST_HANDLERS_ACTION_HANDLERS_HANDLER_H_
#include <set>
#include <string>
#include <vector>
#include "extensions/common/api/app_runtime.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_handler.h"
namespace extensions {
struct ActionHandlersInfo : public Extension::ManifestData {
// Returns true if the given |extension| has an action handler for
// |action_type|.
static bool HasActionHandler(const Extension* extension,
api::app_runtime::ActionType action_type);
ActionHandlersInfo();
~ActionHandlersInfo() override;
std::set<api::app_runtime::ActionType> action_handlers;
};
// Parses the "action_handlers" manifest key.
class ActionHandlersHandler : public ManifestHandler {
public:
ActionHandlersHandler();
ActionHandlersHandler(const ActionHandlersHandler&) = delete;
ActionHandlersHandler& operator=(const ActionHandlersHandler&) = delete;
~ActionHandlersHandler() override;
bool Parse(Extension* extension, std::u16string* error) override;
private:
base::span<const char* const> Keys() const override;
};
} // namespace extensions
#endif // EXTENSIONS_COMMON_MANIFEST_HANDLERS_ACTION_HANDLERS_HANDLER_H_

@ -1,111 +0,0 @@
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <utility>
#include "base/test/values_test_util.h"
#include "components/version_info/version_info.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/action_handlers_handler.h"
#include "extensions/common/manifest_test.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace extensions {
namespace app_runtime = api::app_runtime;
namespace {
class ActionHandlersManifestTest : public ManifestTest {
protected:
ManifestData CreateManifest(const std::string& action_handlers) {
base::Value manifest = base::test::ParseJson(R"json({
"name": "test",
"version": "1",
"app": {
"background": {
"scripts": ["background.js"]
}
},
"manifest_version": 2,
"action_handlers": )json" +
action_handlers + "}");
return ManifestData(std::move(manifest).TakeDict());
}
// Returns all action handlers associated with |extension|.
std::set<app_runtime::ActionType> GetActionHandlers(
const Extension* extension) {
ActionHandlersInfo* info = static_cast<ActionHandlersInfo*>(
extension->GetManifestData(manifest_keys::kActionHandlers));
return info ? info->action_handlers : std::set<app_runtime::ActionType>();
}
};
} // namespace
TEST_F(ActionHandlersManifestTest, InvalidType) {
LoadAndExpectError(CreateManifest("32"),
manifest_errors::kInvalidActionHandlersType);
LoadAndExpectError(CreateManifest("[true]"),
manifest_errors::kInvalidActionHandlersType);
LoadAndExpectError(CreateManifest(R"(["invalid_handler"])"),
manifest_errors::kInvalidActionHandlersActionType);
LoadAndExpectError(CreateManifest(R"(["invalid_handler"])"),
manifest_errors::kInvalidActionHandlersActionType);
LoadAndExpectError(CreateManifest("[{}]"),
manifest_errors::kInvalidActionHandlerDictionary);
LoadAndExpectError(CreateManifest(R"([{"action": "invalid_handler"}])"),
manifest_errors::kInvalidActionHandlersActionType);
}
TEST_F(ActionHandlersManifestTest, VerifyParse) {
scoped_refptr<Extension> none = LoadAndExpectSuccess(CreateManifest("[]"));
EXPECT_TRUE(GetActionHandlers(none.get()).empty());
EXPECT_FALSE(ActionHandlersInfo::HasActionHandler(
none.get(), app_runtime::ActionType::kNewNote));
scoped_refptr<Extension> new_note =
LoadAndExpectSuccess(CreateManifest("[\"new_note\"]"));
EXPECT_EQ(
std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
GetActionHandlers(new_note.get()));
EXPECT_TRUE(ActionHandlersInfo::HasActionHandler(
new_note.get(), app_runtime::ActionType::kNewNote));
}
TEST_F(ActionHandlersManifestTest, ParseDictionaryActionValues) {
scoped_refptr<Extension> new_note_key =
LoadAndExpectSuccess(CreateManifest(R"([{"action": "new_note"}])"));
EXPECT_EQ(
std::set<app_runtime::ActionType>{app_runtime::ActionType::kNewNote},
GetActionHandlers(new_note_key.get()));
EXPECT_TRUE(ActionHandlersInfo::HasActionHandler(
new_note_key.get(), app_runtime::ActionType::kNewNote));
scoped_refptr<Extension> no_new_note_key =
LoadAndExpectSuccess(CreateManifest(R"([])"));
EXPECT_TRUE(GetActionHandlers(no_new_note_key.get()).empty());
}
TEST_F(ActionHandlersManifestTest, DuplicateHandlers) {
LoadAndExpectError(CreateManifest(R"(["new_note", {"action": "new_note"}])"),
manifest_errors::kDuplicateActionHandlerFound);
LoadAndExpectError(CreateManifest(
R"(["new_note", {
"action": "new_note",
}])"),
manifest_errors::kDuplicateActionHandlerFound);
LoadAndExpectError(CreateManifest(
R"([{
"action": "new_note"
}, {
"action": "new_note",
}])"),
manifest_errors::kDuplicateActionHandlerFound);
}
} // namespace extensions

@ -107,11 +107,6 @@ void ShellAppDelegate::SetTerminatingCallback(base::OnceClosure callback) {
// manually or should it use a browser termination callback like Chrome?
}
bool ShellAppDelegate::TakeFocus(content::WebContents* web_contents,
bool reverse) {
return false;
}
content::PictureInPictureResult ShellAppDelegate::EnterPictureInPicture(
content::WebContents* web_contents) {
NOTREACHED();

@ -56,7 +56,6 @@ class ShellAppDelegate : public AppDelegate {
void SetTerminatingCallback(base::OnceClosure callback) override;
void OnHide() override {}
void OnShow() override {}
bool TakeFocus(content::WebContents* web_contents, bool reverse) override;
content::PictureInPictureResult EnterPictureInPicture(
content::WebContents* web_contents) override;
void ExitPictureInPicture() override;