blob: 157bcc2155b412467ea9964d868de324f50a47bf [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include <utility>
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
#include "third_party/blink/public/web/web_dom_message_event.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/blink/renderer/platform/blob/blob_data.h"
#include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
namespace blink {
// static
BlinkTransferableMessage BlinkTransferableMessage::FromMessageEvent(
MessageEvent* message_event,
base::Optional<base::UnguessableToken> cluster_id) {
BlinkTransferableMessage result;
SerializedScriptValue* serialized_script_value =
message_event->DataAsSerializedScriptValue();
// Message data and cluster ID (optional).
base::span<const uint8_t> message_wire_data =
serialized_script_value->GetWireData();
result.message = SerializedScriptValue::Create(
reinterpret_cast<const char*>(message_wire_data.data()),
message_wire_data.size());
result.locked_agent_cluster_id = cluster_id;
// Ports
Vector<MessagePortChannel> ports = message_event->ReleaseChannels();
result.ports.AppendRange(ports.begin(), ports.end());
// User activation
UserActivation* user_activation = message_event->userActivation();
if (user_activation) {
result.user_activation = mojom::blink::UserActivationSnapshot::New(
user_activation->hasBeenActive(), user_activation->isActive());
}
// Capability delegation
result.delegate_payment_request = message_event->delegatePaymentRequest();
// Blobs.
for (const auto& blob : serialized_script_value->BlobDataHandles()) {
result.message->BlobDataHandles().Set(
blob.value->Uuid(),
BlobDataHandle::Create(blob.value->Uuid(), blob.value->GetType(),
blob.value->size(),
blob.value->CloneBlobRemote()));
}
// Stream channels.
for (auto& stream : serialized_script_value->GetStreams()) {
result.message->GetStreams().push_back(std::move(stream));
}
// Array buffer contents array.
auto& source_array_buffer_contents_array =
serialized_script_value->GetArrayBufferContentsArray();
if (!source_array_buffer_contents_array.IsEmpty()) {
SerializedScriptValue::ArrayBufferContentsArray array_buffer_contents_array;
array_buffer_contents_array.ReserveInitialCapacity(
base::checked_cast<wtf_size_t>(
source_array_buffer_contents_array.size()));
for (auto& source_contents : source_array_buffer_contents_array) {
uint8_t* allocation_start = static_cast<uint8_t*>(source_contents.Data());
mojo_base::BigBuffer buffer(
base::make_span(allocation_start, source_contents.DataLength()));
ArrayBufferContents contents(buffer.size(), 1,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
// Check if we allocated the backing store of the ArrayBufferContents
// correctly.
CHECK_EQ(contents.DataLength(), buffer.size());
memcpy(contents.Data(), buffer.data(), buffer.size());
array_buffer_contents_array.push_back(std::move(contents));
}
result.message->SetArrayBufferContentsArray(
std::move(array_buffer_contents_array));
}
// Image bitmap contents array.
auto& source_image_bitmap_contents_array =
serialized_script_value->GetImageBitmapContentsArray();
if (!source_image_bitmap_contents_array.IsEmpty()) {
SerializedScriptValue::ImageBitmapContentsArray image_bitmap_contents_array;
image_bitmap_contents_array.ReserveInitialCapacity(
base::checked_cast<wtf_size_t>(
source_image_bitmap_contents_array.size()));
for (auto& contents : image_bitmap_contents_array) {
base::Optional<SkBitmap> sk_bitmap = ToSkBitmap(contents);
if (!sk_bitmap)
continue;
const scoped_refptr<StaticBitmapImage> bitmap_contents =
ToStaticBitmapImage(sk_bitmap.value());
if (!bitmap_contents)
continue;
image_bitmap_contents_array.push_back(bitmap_contents);
}
result.message->SetImageBitmapContentsArray(
std::move(image_bitmap_contents_array));
}
// File System Access transfer tokens.
for (auto& token : serialized_script_value->FileSystemAccessTokens()) {
result.message->FileSystemAccessTokens().push_back(std::move(token));
}
return result;
}
// static
BlinkTransferableMessage BlinkTransferableMessage::FromTransferableMessage(
TransferableMessage message) {
BlinkTransferableMessage result;
result.message = SerializedScriptValue::Create(
reinterpret_cast<const char*>(message.encoded_message.data()),
message.encoded_message.size());
for (auto& blob : message.blobs) {
result.message->BlobDataHandles().Set(
String::FromUTF8(blob->uuid),
BlobDataHandle::Create(String::FromUTF8(blob->uuid),
String::FromUTF8(blob->content_type), blob->size,
ToCrossVariantMojoType(std::move(blob->blob))));
}
if (message.sender_origin) {
result.sender_origin =
blink::SecurityOrigin::CreateFromUrlOrigin(*message.sender_origin);
}
result.sender_stack_trace_id = v8_inspector::V8StackTraceId(
static_cast<uintptr_t>(message.stack_trace_id),
std::make_pair(message.stack_trace_debugger_id_first,
message.stack_trace_debugger_id_second),
message.stack_trace_should_pause);
result.locked_agent_cluster_id = message.locked_agent_cluster_id;
result.ports.AppendRange(message.ports.begin(), message.ports.end());
for (auto& channel : message.stream_channels) {
result.message->GetStreams().push_back(
SerializedScriptValue::Stream(channel.ReleaseHandle()));
}
if (message.user_activation) {
result.user_activation = mojom::blink::UserActivationSnapshot::New(
message.user_activation->has_been_active,
message.user_activation->was_active);
}
result.delegate_payment_request = message.delegate_payment_request;
if (!message.array_buffer_contents_array.empty()) {
SerializedScriptValue::ArrayBufferContentsArray array_buffer_contents_array;
array_buffer_contents_array.ReserveInitialCapacity(
base::checked_cast<wtf_size_t>(
message.array_buffer_contents_array.size()));
for (auto& item : message.array_buffer_contents_array) {
mojo_base::BigBuffer& big_buffer = item->contents;
ArrayBufferContents contents(big_buffer.size(), 1,
ArrayBufferContents::kNotShared,
ArrayBufferContents::kDontInitialize);
// Check if we allocated the backing store of the ArrayBufferContents
// correctly.
CHECK_EQ(contents.DataLength(), big_buffer.size());
memcpy(contents.Data(), big_buffer.data(), big_buffer.size());
array_buffer_contents_array.push_back(std::move(contents));
}
result.message->SetArrayBufferContentsArray(
std::move(array_buffer_contents_array));
}
if (!message.image_bitmap_contents_array.empty()) {
SerializedScriptValue::ImageBitmapContentsArray image_bitmap_contents_array;
image_bitmap_contents_array.ReserveInitialCapacity(
base::checked_cast<wtf_size_t>(
message.image_bitmap_contents_array.size()));
for (auto& sk_bitmap : message.image_bitmap_contents_array) {
const scoped_refptr<StaticBitmapImage> bitmap_contents =
ToStaticBitmapImage(sk_bitmap);
if (!bitmap_contents)
continue;
image_bitmap_contents_array.push_back(bitmap_contents);
}
result.message->SetImageBitmapContentsArray(
std::move(image_bitmap_contents_array));
}
// Convert the PendingRemote<FileSystemAccessTransferToken> from the
// blink::mojom namespace to the blink::mojom::blink namespace.
for (auto& token : message.file_system_access_tokens) {
result.message->FileSystemAccessTokens().push_back(
ToCrossVariantMojoType(std::move(token)));
}
return result;
}
BlinkTransferableMessage::BlinkTransferableMessage() = default;
BlinkTransferableMessage::~BlinkTransferableMessage() = default;
BlinkTransferableMessage::BlinkTransferableMessage(BlinkTransferableMessage&&) =
default;
BlinkTransferableMessage& BlinkTransferableMessage::operator=(
BlinkTransferableMessage&&) = default;
scoped_refptr<StaticBitmapImage> ToStaticBitmapImage(
const SkBitmap& sk_bitmap) {
sk_sp<SkImage> image = SkImage::MakeFromBitmap(sk_bitmap);
if (!image)
return nullptr;
return UnacceleratedStaticBitmapImage::Create(std::move(image));
}
base::Optional<SkBitmap> ToSkBitmap(
const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image) {
const sk_sp<SkImage> image =
static_bitmap_image->PaintImageForCurrentFrame().GetSwSkImage();
SkBitmap result;
if (image && image->asLegacyBitmap(
&result, SkImage::LegacyBitmapMode::kRO_LegacyBitmapMode)) {
return result;
}
return base::nullopt;
}
} // namespace blink