summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/messaging/blink_transferable_message_struct_traits.cc
blob: a223c52a0989a97095d6fe6afd307c69c7ee30a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// 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_struct_traits.h"

#include "mojo/public/cpp/base/big_buffer_mojom_traits.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace mojo {

namespace {

scoped_refptr<blink::StaticBitmapImage> ToStaticBitmapImage(
    const SkBitmap& sk_bitmap) {
  auto handle = WTF::ArrayBufferContents::CreateDataHandle(
      sk_bitmap.computeByteSize(), WTF::ArrayBufferContents::kZeroInitialize);
  if (!handle)
    return nullptr;

  WTF::ArrayBufferContents array_buffer_contents(
      std::move(handle), WTF::ArrayBufferContents::kNotShared);
  if (!array_buffer_contents.Data())
    return nullptr;

  SkImageInfo info = sk_bitmap.info();
  if (!sk_bitmap.readPixels(info, array_buffer_contents.Data(),
                            info.minRowBytes(), 0, 0))
    return nullptr;

  return blink::StaticBitmapImage::Create(array_buffer_contents, info);
}

bool ToSkBitmap(
    const scoped_refptr<blink::StaticBitmapImage>& static_bitmap_image,
    SkBitmap& dest) {
  const sk_sp<SkImage> image =
      static_bitmap_image->PaintImageForCurrentFrame().GetSkImage();
  return image && image->asLegacyBitmap(
                      &dest, SkImage::LegacyBitmapMode::kRO_LegacyBitmapMode);
}

}  // namespace

Vector<SkBitmap>
StructTraits<blink::mojom::blink::TransferableMessage::DataView,
             blink::BlinkTransferableMessage>::
    image_bitmap_contents_array(const blink::BlinkCloneableMessage& input) {
  Vector<SkBitmap> out;
  out.ReserveInitialCapacity(
      input.message->GetImageBitmapContentsArray().size());
  for (auto& bitmap_contents : input.message->GetImageBitmapContentsArray()) {
    SkBitmap bitmap;
    if (!ToSkBitmap(bitmap_contents, bitmap)) {
      return Vector<SkBitmap>();
    }
    out.push_back(std::move(bitmap));
  }
  return out;
}

bool StructTraits<blink::mojom::blink::TransferableMessage::DataView,
                  blink::BlinkTransferableMessage>::
    Read(blink::mojom::blink::TransferableMessage::DataView data,
         blink::BlinkTransferableMessage* out) {
  Vector<mojo::ScopedMessagePipeHandle> ports;
  blink::SerializedScriptValue::ArrayBufferContentsArray
      array_buffer_contents_array;
  Vector<SkBitmap> sk_bitmaps;
  if (!data.ReadMessage(static_cast<blink::BlinkCloneableMessage*>(out)) ||
      !data.ReadArrayBufferContentsArray(&array_buffer_contents_array) ||
      !data.ReadImageBitmapContentsArray(&sk_bitmaps) ||
      !data.ReadPorts(&ports)) {
    return false;
  }

  out->ports.ReserveInitialCapacity(ports.size());
  out->ports.AppendRange(std::make_move_iterator(ports.begin()),
                         std::make_move_iterator(ports.end()));
  out->has_user_gesture = data.has_user_gesture();

  out->message->SetArrayBufferContentsArray(
      std::move(array_buffer_contents_array));
  array_buffer_contents_array.clear();

  // Bitmaps are serialized in mojo as SkBitmaps to leverage existing
  // serialization logic, but SerializedScriptValue uses StaticBitmapImage, so
  // the SkBitmaps need to be converted to StaticBitmapImages.
  blink::SerializedScriptValue::ImageBitmapContentsArray
      image_bitmap_contents_array;
  for (auto& sk_bitmap : sk_bitmaps) {
    const scoped_refptr<blink::StaticBitmapImage> bitmap_contents =
        ToStaticBitmapImage(sk_bitmap);
    if (!bitmap_contents) {
      return false;
    }
    image_bitmap_contents_array.push_back(bitmap_contents);
  }
  out->message->SetImageBitmapContentsArray(image_bitmap_contents_array);

  return true;
}

bool StructTraits<blink::mojom::blink::SerializedArrayBufferContents::DataView,
                  WTF::ArrayBufferContents>::
    Read(blink::mojom::blink::SerializedArrayBufferContents::DataView data,
         WTF::ArrayBufferContents* out) {
  mojo_base::BigBufferView contents_view;
  if (!data.ReadContents(&contents_view))
    return false;
  auto contents_data = contents_view.data();
  auto handle = WTF::ArrayBufferContents::CreateDataHandle(
      contents_data.size(), WTF::ArrayBufferContents::kZeroInitialize);
  if (!handle)
    return false;

  WTF::ArrayBufferContents array_buffer_contents(
      std::move(handle), WTF::ArrayBufferContents::kNotShared);
  memcpy(array_buffer_contents.Data(), contents_data.data(),
         contents_data.size());
  *out = std::move(array_buffer_contents);
  return true;
}

}  // namespace mojo