feat: serialize NativeImage over ipc (#30729)

This commit is contained in:
Jeremy Rose 2021-09-07 10:37:45 -07:00 committed by GitHub
parent ee33374675
commit 55c57808fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 79 additions and 157 deletions

View file

@ -8,14 +8,17 @@
#include <vector>
#include "gin/converter.h"
#include "shell/common/api/electron_api_native_image.h"
#include "shell/common/gin_helper/microtasks_scope.h"
#include "skia/public/mojom/bitmap.mojom.h"
#include "third_party/blink/public/common/messaging/cloneable_message.h"
#include "ui/gfx/image/image_skia.h"
#include "v8/include/v8.h"
namespace electron {
namespace {
const uint8_t kVersionTag = 0xFF;
enum SerializationTag { kNativeImageTag = 'i', kVersionTag = 0xFF };
} // namespace
class V8Serializer : public v8::ValueSerializer::Delegate {
@ -62,12 +65,35 @@ class V8Serializer : public v8::ValueSerializer::Delegate {
data_ = {};
}
v8::Maybe<bool> WriteHostObject(v8::Isolate* isolate,
v8::Local<v8::Object> object) override {
api::NativeImage* native_image;
if (gin::ConvertFromV8(isolate, object, &native_image)) {
// Serialize the NativeImage
WriteTag(kNativeImageTag);
gfx::ImageSkia image = native_image->image().AsImageSkia();
std::vector<gfx::ImageSkiaRep> image_reps = image.image_reps();
serializer_.WriteUint32(image_reps.size());
for (const auto& rep : image_reps) {
serializer_.WriteDouble(rep.scale());
const SkBitmap& bitmap = rep.GetBitmap();
std::vector<uint8_t> bytes =
skia::mojom::InlineBitmap::Serialize(&bitmap);
serializer_.WriteUint32(bytes.size());
serializer_.WriteRawBytes(bytes.data(), bytes.size());
}
return v8::Just(true);
} else {
return v8::ValueSerializer::Delegate::WriteHostObject(isolate, object);
}
}
void ThrowDataCloneError(v8::Local<v8::String> message) override {
isolate_->ThrowException(v8::Exception::Error(message));
}
private:
void WriteTag(uint8_t tag) { serializer_.WriteRawBytes(&tag, 1); }
void WriteTag(SerializationTag tag) { serializer_.WriteRawBytes(&tag, 1); }
void WriteBlinkEnvelope(uint32_t blink_version) {
// Write a dummy blink version envelope for compatibility with
@ -107,6 +133,20 @@ class V8Deserializer : public v8::ValueDeserializer::Delegate {
return scope.Escape(value);
}
v8::MaybeLocal<v8::Object> ReadHostObject(v8::Isolate* isolate) override {
uint8_t tag = 0;
if (!ReadTag(&tag))
return v8::ValueDeserializer::Delegate::ReadHostObject(isolate);
switch (tag) {
case kNativeImageTag:
if (api::NativeImage* native_image = ReadNativeImage(isolate))
return native_image->GetWrapper(isolate);
break;
}
// Throws an exception.
return v8::ValueDeserializer::Delegate::ReadHostObject(isolate);
}
private:
bool ReadTag(uint8_t* tag) {
const void* tag_bytes = nullptr;
@ -127,6 +167,31 @@ class V8Deserializer : public v8::ValueDeserializer::Delegate {
return true;
}
api::NativeImage* ReadNativeImage(v8::Isolate* isolate) {
gfx::ImageSkia image_skia;
uint32_t num_reps = 0;
if (!deserializer_.ReadUint32(&num_reps))
return nullptr;
for (uint32_t i = 0; i < num_reps; i++) {
double scale = 0.0;
if (!deserializer_.ReadDouble(&scale))
return nullptr;
uint32_t bitmap_size_bytes = 0;
if (!deserializer_.ReadUint32(&bitmap_size_bytes))
return nullptr;
const void* bitmap_data = nullptr;
if (!deserializer_.ReadRawBytes(bitmap_size_bytes, &bitmap_data))
return nullptr;
SkBitmap bitmap;
if (!skia::mojom::InlineBitmap::Deserialize(bitmap_data,
bitmap_size_bytes, &bitmap))
return nullptr;
image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
}
gfx::Image image(image_skia);
return new api::NativeImage(isolate, image);
}
v8::Isolate* isolate_;
v8::ValueDeserializer deserializer_;
};