blob: dc26a9b4867d0bebc3aa0f61e5851525bb3768c0 [file] [log] [blame]
// Copyright 2025 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/api/messaging/message.h"
#include "base/check.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "extensions/common/extension_features.h"
namespace extensions {
Message::Message() = default;
Message::Message(MessageData data,
mojom::SerializationFormat format,
bool user_gesture,
bool from_privileged_context)
: data_(std::move(data)),
format_(format),
user_gesture_(user_gesture),
from_privileged_context_(from_privileged_context) {
if (format_ == mojom::SerializationFormat::kJson) {
CHECK(std::holds_alternative<std::string>(data_));
} else if (format_ == mojom::SerializationFormat::kStructuredClone) {
CHECK(std::holds_alternative<StructuredCloneMessageWireData>(data_));
CHECK(base::FeatureList::IsEnabled(
extensions_features::kStructuredCloningForMessaging));
}
}
Message::Message(const Message& other)
: format_(other.format_),
user_gesture_(other.user_gesture_),
from_privileged_context_(other.from_privileged_context_) {
if (std::holds_alternative<std::string>(other.data_)) {
data_ = std::get<std::string>(other.data_);
} else {
data_ = std::get<StructuredCloneMessageWireData>(other.data_).Clone();
}
}
Message::Message(Message&& other) = default;
Message::~Message() = default;
Message& Message::operator=(const Message& other) {
format_ = other.format_;
user_gesture_ = other.user_gesture_;
from_privileged_context_ = other.from_privileged_context_;
if (std::holds_alternative<std::string>(other.data_)) {
data_ = std::get<std::string>(other.data_);
} else {
data_ = std::get<StructuredCloneMessageWireData>(other.data_).Clone();
}
return *this;
}
Message& Message::operator=(Message&& other) = default;
bool Message::operator==(const Message& other) const {
if (format_ != other.format()) {
return false;
}
bool message_data_equal = false;
switch (format_) {
case mojom::SerializationFormat::kJson:
message_data_equal = std::get<std::string>(data_) == other.data();
break;
case mojom::SerializationFormat::kStructuredClone:
CHECK(base::FeatureList::IsEnabled(
extensions_features::kStructuredCloningForMessaging));
// `mojo_base::BigBuffer` does not have a comparison operator so we
// convert to comparable `base::span`s.
message_data_equal =
base::span<const uint8_t>(std::get<StructuredCloneMessageWireData>(
data_)) == base::span<const uint8_t>(other.structured_data());
break;
default:
// We only support JSON or structured cloning serialization formats.
NOTREACHED();
}
return message_data_equal && user_gesture_ == other.user_gesture_;
}
const std::string& Message::data() const {
CHECK(std::holds_alternative<std::string>(data_));
return std::get<std::string>(data_);
}
const StructuredCloneMessageWireData& Message::structured_data() const {
CHECK(std::holds_alternative<StructuredCloneMessageWireData>(data_));
return std::get<StructuredCloneMessageWireData>(data_);
}
} // namespace extensions