blob: bcf48a8ac15019518c179dad6aa0e09ae8c5b9a2 [file] [log] [blame]
// Copyright 2014 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/automation.h"
#include <memory>
#include <utility>
#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/api/extensions_manifest_types.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extensions_client.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/permissions/api_permission_set.h"
#include "extensions/common/permissions/manifest_permission.h"
#include "extensions/common/permissions/permission_message_util.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_utils.h"
using extensions::mojom::APIPermissionID;
namespace extensions {
namespace errors = manifest_errors;
namespace keys = extensions::manifest_keys;
using api::extensions_manifest_types::Automation;
class AutomationManifestPermission : public ManifestPermission {
public:
explicit AutomationManifestPermission(
std::unique_ptr<const AutomationInfo> automation_info)
: automation_info_(std::move(automation_info)) {}
// extensions::ManifestPermission overrides.
std::string name() const override;
std::string id() const override;
PermissionIDSet GetPermissions() const override;
bool FromValue(const base::Value* value) override;
std::unique_ptr<base::Value> ToValue() const override;
std::unique_ptr<ManifestPermission> Diff(
const ManifestPermission* rhs) const override;
std::unique_ptr<ManifestPermission> Union(
const ManifestPermission* rhs) const override;
std::unique_ptr<ManifestPermission> Intersect(
const ManifestPermission* rhs) const override;
bool RequiresManagementUIWarning() const override;
private:
std::unique_ptr<const AutomationInfo> automation_info_;
};
std::string AutomationManifestPermission::name() const {
return keys::kAutomation;
}
std::string AutomationManifestPermission::id() const {
return keys::kAutomation;
}
PermissionIDSet AutomationManifestPermission::GetPermissions() const {
// Meant to mimic the behavior of GetMessages().
PermissionIDSet permissions;
if (automation_info_->desktop) {
permissions.insert(APIPermissionID::kFullAccess);
}
return permissions;
}
bool AutomationManifestPermission::FromValue(const base::Value* value) {
std::u16string error;
automation_info_.reset(
AutomationInfo::FromValue(*value, nullptr /* install_warnings */, &error)
.release());
return error.empty();
}
std::unique_ptr<base::Value> AutomationManifestPermission::ToValue() const {
return AutomationInfo::ToValue(*automation_info_);
}
std::unique_ptr<ManifestPermission> AutomationManifestPermission::Diff(
const ManifestPermission* rhs) const {
const AutomationManifestPermission* other =
static_cast<const AutomationManifestPermission*>(rhs);
bool desktop = automation_info_->desktop && !other->automation_info_->desktop;
return std::make_unique<AutomationManifestPermission>(
base::WrapUnique(new const AutomationInfo(desktop)));
}
std::unique_ptr<ManifestPermission> AutomationManifestPermission::Union(
const ManifestPermission* rhs) const {
const AutomationManifestPermission* other =
static_cast<const AutomationManifestPermission*>(rhs);
bool desktop = automation_info_->desktop || other->automation_info_->desktop;
return std::make_unique<AutomationManifestPermission>(
base::WrapUnique(new const AutomationInfo(desktop)));
}
std::unique_ptr<ManifestPermission> AutomationManifestPermission::Intersect(
const ManifestPermission* rhs) const {
const AutomationManifestPermission* other =
static_cast<const AutomationManifestPermission*>(rhs);
bool desktop = automation_info_->desktop && other->automation_info_->desktop;
return std::make_unique<AutomationManifestPermission>(
base::WrapUnique(new const AutomationInfo(desktop)));
}
bool AutomationManifestPermission::RequiresManagementUIWarning() const {
return automation_info_->desktop;
}
AutomationHandler::AutomationHandler() = default;
AutomationHandler::~AutomationHandler() = default;
bool AutomationHandler::Parse(Extension* extension, std::u16string* error) {
const base::Value* automation =
extension->manifest()->FindPath(keys::kAutomation);
CHECK(automation != nullptr);
std::vector<InstallWarning> install_warnings;
std::unique_ptr<AutomationInfo> info =
AutomationInfo::FromValue(*automation, &install_warnings, error);
if (!error->empty()) {
return false;
}
extension->AddInstallWarnings(std::move(install_warnings));
if (!info) {
return true;
}
extension->SetManifestData(keys::kAutomation, std::move(info));
return true;
}
base::span<const char* const> AutomationHandler::Keys() const {
static constexpr const char* kKeys[] = {keys::kAutomation};
return kKeys;
}
ManifestPermission* AutomationHandler::CreatePermission() {
return new AutomationManifestPermission(
base::WrapUnique(new const AutomationInfo));
}
ManifestPermission* AutomationHandler::CreateInitialRequiredPermission(
const Extension* extension) {
const AutomationInfo* info = AutomationInfo::Get(extension);
if (info) {
return new AutomationManifestPermission(
base::WrapUnique(new const AutomationInfo(info->desktop)));
}
return nullptr;
}
// static
const AutomationInfo* AutomationInfo::Get(const Extension* extension) {
return static_cast<AutomationInfo*>(
extension->GetManifestData(keys::kAutomation));
}
// static
std::unique_ptr<AutomationInfo> AutomationInfo::FromValue(
const base::Value& value,
std::vector<InstallWarning>* install_warnings,
std::u16string* error) {
auto automation = Automation::FromValue(value);
if (!automation.has_value()) {
*error = std::move(automation).error();
return nullptr;
}
if (automation->as_boolean) {
if (*automation->as_boolean) {
return base::WrapUnique(new AutomationInfo());
}
return nullptr;
}
const Automation::Object& automation_object = *automation->as_object;
bool desktop = false;
if (automation_object.desktop && *automation_object.desktop) {
desktop = true;
}
return base::WrapUnique(new AutomationInfo(desktop));
}
// static
std::unique_ptr<base::Value> AutomationInfo::ToValue(
const AutomationInfo& info) {
return base::Value::ToUniquePtrValue(AsManifestType(info)->ToValue());
}
// static
std::unique_ptr<Automation> AutomationInfo::AsManifestType(
const AutomationInfo& info) {
std::unique_ptr<Automation> automation(new Automation);
if (!info.desktop) {
automation->as_boolean = true;
return automation;
}
automation->as_object.emplace();
automation->as_object->desktop = info.desktop;
return automation;
}
AutomationInfo::AutomationInfo() : desktop(false) {}
AutomationInfo::AutomationInfo(bool desktop) : desktop(desktop) {}
AutomationInfo::~AutomationInfo() = default;
} // namespace extensions