Commit 6fa8d815 authored by Dave Tapuska's avatar Dave Tapuska Committed by Commit Bot

Add UserActivation member to MessageEvent

Add an API to query user activation state on a posted message event.
Add includeUserActivation attribute on the WindowPostMessageOptions so
that indication of user gesture behavior can be opted in.

https://github.com/dtapuska/useractivation
https://github.com/whatwg/html/issues/1983

BUG=846858
TBR=mkwst@chromium.org

Change-Id: I2459b21004afbe00c41ddf992533c60728768bb4
Reviewed-on: https://chromium-review.googlesource.com/1131558
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: default avatarKen Buchanan <kenrb@chromium.org>
Reviewed-by: default avatarMarijn Kruisselbrink <mek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579398}
parent 1a99205d
......@@ -211,6 +211,11 @@ void ParamTraits<scoped_refptr<base::RefCountedData<
WriteParam(m, p->data.stack_trace_debugger_id_second);
WriteParam(m, p->data.ports);
WriteParam(m, p->data.has_user_gesture);
WriteParam(m, !!p->data.user_activation);
if (p->data.user_activation) {
WriteParam(m, p->data.user_activation->has_been_active);
WriteParam(m, p->data.user_activation->was_active);
}
}
bool ParamTraits<
......@@ -229,14 +234,27 @@ bool ParamTraits<
// returned message.
(*r)->data.encoded_message =
base::make_span(reinterpret_cast<const uint8_t*>(data), length);
bool has_activation = false;
if (!ReadParam(m, iter, &(*r)->data.blobs) ||
!ReadParam(m, iter, &(*r)->data.stack_trace_id) ||
!ReadParam(m, iter, &(*r)->data.stack_trace_debugger_id_first) ||
!ReadParam(m, iter, &(*r)->data.stack_trace_debugger_id_second) ||
!ReadParam(m, iter, &(*r)->data.ports) ||
!ReadParam(m, iter, &(*r)->data.has_user_gesture)) {
!ReadParam(m, iter, &(*r)->data.has_user_gesture) ||
!ReadParam(m, iter, &has_activation)) {
return false;
}
if (has_activation) {
bool has_been_active;
bool was_active;
if (!ReadParam(m, iter, &has_been_active) ||
!ReadParam(m, iter, &was_active)) {
return false;
}
(*r)->data.user_activation =
blink::mojom::UserActivationSnapshot::New(has_been_active, was_active);
}
return true;
}
......
<!DOCTYPE html>
<!--
Tentative due to:
https://github.com/whatwg/html/issues/3739
-->
<html>
<head>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
</head>
<body>
<h1>Clicking in iframe has activation state in child via MessageEvent</h1>
<ol id="instructions">
<li>Click inside the red area.
</ol>
<iframe id="child" width="200" height="200"></iframe>
<script>
async_test(function(t) {
var child = document.getElementById("child");
assert_false(navigator.userActivation.isActive);
assert_false(navigator.userActivation.hasBeenActive);
window.addEventListener("message", t.step_func(event => {
if (event.data == 'child-three-loaded') {
// values have false after load
assert_true(event.userActivation != null);
assert_false(event.userActivation.isActive);
assert_false(event.userActivation.hasBeenActive);
test_driver.click(child);
} else if (event.data == 'child-three-clicked') {
// values have activation state on click
assert_true(navigator.userActivation.hasBeenActive);
assert_true(event.userActivation != null);
assert_true(event.userActivation.isActive);
assert_true(event.userActivation.hasBeenActive);
child.contentWindow.postMessage('report', "*");
} else if (event.data == 'child-three-report') {
assert_false(navigator.userActivation.isActive);
assert_true(navigator.userActivation.hasBeenActive);
assert_true(event.userActivation != null);
assert_false(event.userActivation.isActive);
assert_true(event.userActivation.hasBeenActive);
child.contentWindow.postMessage('report-no-activation', "*");
} else if (event.data == 'child-three-report-no-activation') {
assert_true(event.userActivation === null);
t.done();
}
}));
child.src = "http://{{domains[www]}}:{{ports[http][0]}}/html/user-activation/resources/child-three.html";
}, "Message propagates values on post");
</script>
</body>
</html>
<!DOCTYPE html>
<title>MessageEvent constructor</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {
var ev = new MessageEvent("test", { userActivation: navigator.userActivation })
assert_equals(ev.userActivation, navigator.userActivation, "userActivation attribute")
}, "MessageEventInit user activation set")
test(function() {
var ev = new MessageEvent("test")
assert_equals(ev.userActivation, null, "userActivation attribute")
}, "MessageEventInit user activation not set")
</script>
<!DOCTYPE html>
<body style="background: red;">
<script>
window.parent.postMessage("child-three-loaded", {targetOrigin: "*", includeUserActivation: true});
window.addEventListener("click", event => {
window.parent.postMessage("child-three-clicked", {targetOrigin: "*", includeUserActivation: true});
var win = window.open('404.html');
win.close();
});
window.addEventListener("message", event => {
if (event.data == "report")
window.parent.postMessage("child-three-report", {targetOrigin: "*", includeUserActivation: true});
if (event.data == "report-no-activation")
window.parent.postMessage("child-three-report-no-activation", {targetOrigin: "*", includeUserActivation: false});
});
</script>
</body>
......@@ -4456,6 +4456,7 @@ interface MessageEvent : Event
getter origin
getter ports
getter source
getter userActivation
method constructor
method initMessageEvent
interface MessagePort : EventTarget
......
......@@ -17,7 +17,8 @@ bool StructTraits<blink::mojom::TransferableMessage::DataView,
if (!data.ReadMessage(static_cast<blink::CloneableMessage*>(out)) ||
!data.ReadArrayBufferContentsArray(&out->array_buffer_contents_array) ||
!data.ReadImageBitmapContentsArray(&out->image_bitmap_contents_array) ||
!data.ReadPorts(&ports)) {
!data.ReadPorts(&ports) ||
!data.ReadUserActivation(&out->user_activation)) {
return false;
}
......
......@@ -40,6 +40,11 @@ struct BLINK_COMMON_EXPORT
return input.has_user_gesture;
}
static const blink::mojom::UserActivationSnapshotPtr& user_activation(
blink::TransferableMessage& input) {
return input.user_activation;
}
static bool Read(blink::mojom::TransferableMessage::DataView data,
blink::TransferableMessage* out);
};
......
......@@ -13,6 +13,7 @@
#include "third_party/blink/public/common/message_port/cloneable_message.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom.h"
#include "third_party/blink/public/mojom/message_port/user_activation_snapshot.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace blink {
......@@ -37,6 +38,9 @@ struct BLINK_COMMON_EXPORT TransferableMessage : public CloneableMessage {
// message.
bool has_user_gesture = false;
// The state of user activation.
mojom::UserActivationSnapshotPtr user_activation;
private:
DISALLOW_COPY_AND_ASSIGN(TransferableMessage);
};
......
......@@ -102,6 +102,7 @@ mojom("speech_recognition_error_code") {
mojom("mojom_core") {
sources = [
"message_port/message_port.mojom",
"message_port/user_activation_snapshot.mojom",
"portal/portal.mojom",
"service_worker/service_worker.mojom",
"service_worker/service_worker_object.mojom",
......
......@@ -7,6 +7,7 @@ module blink.mojom;
import "mojo/public/mojom/base/big_buffer.mojom";
import "third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom";
import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
import "third_party/blink/public/mojom/message_port/user_activation_snapshot.mojom";
import "skia/public/interfaces/bitmap.mojom";
// A MessagePort is represented as a raw mojo message pipe, as such no interface
......@@ -45,4 +46,6 @@ struct TransferableMessage {
// Whether the recipient should have a user gesture when it processes this
// message.
bool has_user_gesture;
// The user activation state, null if the frame isn't providing it.
UserActivationSnapshot? user_activation;
};
// Copyright 2018 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.
module blink.mojom;
// This struct represents the UserActivation state at the time which the message
// was sent.
struct UserActivationSnapshot {
bool has_been_active;
bool was_active;
};
......@@ -30,6 +30,7 @@
#include <memory>
#include "third_party/blink/renderer/bindings/core/v8/v8_array_buffer.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
......@@ -78,6 +79,8 @@ MessageEvent::MessageEvent(const AtomicString& type,
source_ = initializer.source();
if (initializer.hasPorts())
ports_ = new MessagePortArray(initializer.ports());
if (initializer.hasUserActivation())
user_activation_ = initializer.userActivation();
DCHECK(IsValidSource(source_.Get()));
}
......@@ -114,7 +117,8 @@ MessageEvent::MessageEvent(scoped_refptr<SerializedScriptValue> data,
const String& origin,
const String& last_event_id,
EventTarget* source,
Vector<MessagePortChannel> channels)
Vector<MessagePortChannel> channels,
UserActivation* user_activation)
: Event(EventTypeNames::message, Bubbles::kNo, Cancelable::kNo),
data_type_(kDataTypeSerializedScriptValue),
data_as_serialized_script_value_(
......@@ -122,7 +126,8 @@ MessageEvent::MessageEvent(scoped_refptr<SerializedScriptValue> data,
origin_(origin),
last_event_id_(last_event_id),
source_(source),
channels_(std::move(channels)) {
channels_(std::move(channels)),
user_activation_(user_activation) {
DCHECK(IsValidSource(source_.Get()));
}
......@@ -186,7 +191,8 @@ void MessageEvent::initMessageEvent(const AtomicString& type,
const String& origin,
const String& last_event_id,
EventTarget* source,
MessagePortArray* ports) {
MessagePortArray* ports,
UserActivation* user_activation) {
if (IsBeingDispatched())
return;
......@@ -200,6 +206,7 @@ void MessageEvent::initMessageEvent(const AtomicString& type,
source_ = source;
ports_ = ports;
is_ports_dirty_ = true;
user_activation_ = user_activation;
}
void MessageEvent::initMessageEvent(const AtomicString& type,
......@@ -248,6 +255,7 @@ void MessageEvent::Trace(blink::Visitor* visitor) {
visitor->Trace(data_as_array_buffer_);
visitor->Trace(source_);
visitor->Trace(ports_);
visitor->Trace(user_activation_);
Event::Trace(visitor);
}
......
......@@ -43,6 +43,8 @@
namespace blink {
class UserActivation;
class CORE_EXPORT MessageEvent final : public Event {
DEFINE_WRAPPERTYPEINFO();
......@@ -66,9 +68,10 @@ class CORE_EXPORT MessageEvent final : public Event {
scoped_refptr<SerializedScriptValue> data,
const String& origin = String(),
const String& last_event_id = String(),
EventTarget* source = nullptr) {
EventTarget* source = nullptr,
UserActivation* user_activation = nullptr) {
return new MessageEvent(std::move(data), origin, last_event_id, source,
std::move(channels));
std::move(channels), user_activation);
}
static MessageEvent* Create(const String& data,
const String& origin = String()) {
......@@ -101,7 +104,8 @@ class CORE_EXPORT MessageEvent final : public Event {
const String& origin,
const String& last_event_id,
EventTarget* source,
MessagePortArray*);
MessagePortArray*,
UserActivation* user_activation);
void initMessageEvent(const AtomicString& type,
bool bubbles,
bool cancelable,
......@@ -116,6 +120,7 @@ class CORE_EXPORT MessageEvent final : public Event {
EventTarget* source() const { return source_.Get(); }
MessagePortArray ports();
bool isPortsDirty() const { return is_ports_dirty_; }
UserActivation* userActivation() const { return user_activation_; }
Vector<MessagePortChannel> ReleaseChannels() { return std::move(channels_); }
......@@ -196,7 +201,8 @@ class CORE_EXPORT MessageEvent final : public Event {
const String& origin,
const String& last_event_id,
EventTarget* source,
Vector<MessagePortChannel>);
Vector<MessagePortChannel>,
UserActivation* user_activation);
MessageEvent(const String& data, const String& origin);
MessageEvent(Blob* data, const String& origin);
......@@ -217,6 +223,7 @@ class CORE_EXPORT MessageEvent final : public Event {
Member<MessagePortArray> ports_;
bool is_ports_dirty_ = true;
Vector<MessagePortChannel> channels_;
Member<UserActivation> user_activation_;
};
} // namespace blink
......
......@@ -38,6 +38,7 @@
// TODO(bashi): |source| should be (WindowProxy or MessagePort)?
readonly attribute EventTarget? source;
[CachedAttribute=isPortsDirty] readonly attribute FrozenArray<MessagePort> ports;
[Exposed=Window, RuntimeEnabled=UserActivationAPI] readonly attribute UserActivation? userActivation;
// TODO(foolip): none of the arguments should have [Default=Undefined] (they
// have other default values in the spec) and |sourceArg|'s type is wrong.
......
......@@ -11,4 +11,5 @@ dictionary MessageEventInit : EventInit {
// TODO(bashi): |source| should be (WindowProxy or MessagePort)?
EventTarget? source;
sequence<MessagePort> ports = [];
[Exposed=Window, RuntimeEnabled=UserActivationAPI] UserActivation? userActivation = null;
};
......@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/messaging/blink_transferable_message.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
......@@ -60,9 +61,9 @@ WebDOMMessageEvent::WebDOMMessageEvent(
}
// TODO(esprehn): Chromium always passes empty string for lastEventId, is that
// right?
Unwrap<MessageEvent>()->initMessageEvent("message", false, false,
message_data, origin,
"" /*lastEventId*/, window, ports);
Unwrap<MessageEvent>()->initMessageEvent(
"message", false, false, message_data, origin, "" /*lastEventId*/, window,
ports, nullptr /*user_activation*/);
}
WebDOMMessageEvent::WebDOMMessageEvent(TransferableMessage message,
......@@ -79,11 +80,19 @@ WebDOMMessageEvent::WebDOMMessageEvent(TransferableMessage message,
Document* core_document = target_document;
ports = MessagePort::EntanglePorts(*core_document, std::move(msg.ports));
}
UserActivation* user_activation = nullptr;
if (msg.user_activation) {
user_activation =
new UserActivation(msg.user_activation->has_been_active,
msg.user_activation->was_active);
}
// TODO(esprehn): Chromium always passes empty string for lastEventId, is that
// right?
Unwrap<MessageEvent>()->initMessageEvent("message", false, false,
std::move(msg.message), origin,
"" /*lastEventId*/, window, ports);
Unwrap<MessageEvent>()->initMessageEvent(
"message", false, false, std::move(msg.message), origin,
"" /*lastEventId*/, window, ports, user_activation);
}
WebString WebDOMMessageEvent::Origin() const {
......@@ -94,7 +103,13 @@ TransferableMessage WebDOMMessageEvent::AsMessage() {
BlinkTransferableMessage msg;
msg.message = Unwrap<MessageEvent>()->DataAsSerializedScriptValue();
msg.ports = Unwrap<MessageEvent>()->ReleaseChannels();
return ToTransferableMessage(std::move(msg));
UserActivation* user_activation = Unwrap<MessageEvent>()->userActivation();
TransferableMessage transferable_msg = ToTransferableMessage(std::move(msg));
if (user_activation) {
transferable_msg.user_activation = mojom::UserActivationSnapshot::New(
user_activation->hasBeenActive(), user_activation->isActive());
}
return transferable_msg;
}
} // namespace blink
......@@ -19,6 +19,7 @@
#include "third_party/blink/renderer/core/frame/location.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/use_counter.h"
#include "third_party/blink/renderer/core/frame/user_activation.h"
#include "third_party/blink/renderer/core/frame/window_post_message_options.h"
#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
......@@ -151,7 +152,7 @@ void DOMWindow::postMessage(LocalDOMWindow* incumbent_window,
serialized_message->UnregisterMemoryAllocatedWithCurrentScriptContext();
DoPostMessage(std::move(serialized_message), transferables.message_ports,
options.targetOrigin(), incumbent_window, exception_state);
options, incumbent_window, exception_state);
}
DOMWindow* DOMWindow::AnonymousIndexedGetter(uint32_t index) const {
......@@ -406,13 +407,14 @@ void DOMWindow::PostMessageForTesting(
const String& target_origin,
LocalDOMWindow* source,
ExceptionState& exception_state) {
DoPostMessage(std::move(message), ports, target_origin, source,
exception_state);
WindowPostMessageOptions options;
options.setTargetOrigin(target_origin);
DoPostMessage(std::move(message), ports, options, source, exception_state);
}
void DOMWindow::DoPostMessage(scoped_refptr<SerializedScriptValue> message,
const MessagePortArray& ports,
const String& target_origin,
const WindowPostMessageOptions& options,
LocalDOMWindow* source,
ExceptionState& exception_state) {
if (!IsCurrentlyDisplayedInFrame())
......@@ -420,6 +422,8 @@ void DOMWindow::DoPostMessage(scoped_refptr<SerializedScriptValue> message,
Document* source_document = source->document();
const String& target_origin = options.targetOrigin();
// Compute the target origin. We need to do this synchronously in order
// to generate the SyntaxError exception correctly.
scoped_refptr<const SecurityOrigin> target;
......@@ -484,9 +488,13 @@ void DOMWindow::DoPostMessage(scoped_refptr<SerializedScriptValue> message,
source->GetFrame(),
WebFeature::kPostMessageOutgoingWouldBeBlockedByConnectSrc);
}
UserActivation* user_activation = nullptr;
if (options.includeUserActivation())
user_activation = UserActivation::CreateSnapshot(source);
MessageEvent* event = MessageEvent::Create(
std::move(channels), std::move(message), source_origin, String(), source);
MessageEvent* event =
MessageEvent::Create(std::move(channels), std::move(message),
source_origin, String(), source, user_activation);
SchedulePostMessage(event, std::move(target), source_document);
}
......
......@@ -136,7 +136,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData,
private:
void DoPostMessage(scoped_refptr<SerializedScriptValue> message,
const MessagePortArray&,
const String& target_origin,
const WindowPostMessageOptions& options,
LocalDOMWindow* source,
ExceptionState&);
......
......@@ -36,7 +36,7 @@ void NavigatorUserActivation::Trace(blink::Visitor* visitor) {
}
NavigatorUserActivation::NavigatorUserActivation(Navigator& navigator) {
user_activation_ = new UserActivation(navigator.DomWindow());
user_activation_ = UserActivation::CreateLive(navigator.DomWindow());
}
} // namespace blink
......@@ -8,6 +8,19 @@
namespace blink {
UserActivation* UserActivation::CreateSnapshot(LocalDOMWindow* window) {
LocalFrame* frame = window->GetFrame();
return new UserActivation(frame ? frame->HasBeenActivated() : false,
Frame::HasTransientUserActivation(frame));
}
UserActivation* UserActivation::CreateLive(LocalDOMWindow* window) {
return new UserActivation(window);
}
UserActivation::UserActivation(bool has_been_active, bool is_active)
: has_been_active_(has_been_active), is_active_(is_active) {}
UserActivation::UserActivation(LocalDOMWindow* window) : window_(window) {}
UserActivation::~UserActivation() = default;
......@@ -20,14 +33,14 @@ void UserActivation::Trace(blink::Visitor* visitor) {
bool UserActivation::hasBeenActive() const {
LocalFrame* frame = window_ ? window_->GetFrame() : nullptr;
if (!frame)
return false;
return has_been_active_;
return frame->HasBeenActivated();
}
bool UserActivation::isActive() const {
LocalFrame* frame = window_ ? window_->GetFrame() : nullptr;
if (!frame)
return false;
return is_active_;
return Frame::HasTransientUserActivation(frame);
}
......
......@@ -15,8 +15,14 @@ class UserActivation final : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
explicit UserActivation(LocalDOMWindow* window);
// Creates an instance that is a snapshot of the current state of this
// LocalDOMWindow.
static UserActivation* CreateSnapshot(LocalDOMWindow* window);
// Creates an instance that represents the live state of this LocalDOMWindow.
static UserActivation* CreateLive(LocalDOMWindow* window);
UserActivation(bool has_been_active, bool is_active);
~UserActivation() override;
void Trace(blink::Visitor*) override;
......@@ -25,7 +31,11 @@ class UserActivation final : public ScriptWrappable {
bool isActive() const;
private:
explicit UserActivation(LocalDOMWindow* window);
Member<LocalDOMWindow> window_;
bool has_been_active_ = false;
bool is_active_ = false;
};
} // namespace blink
......
......@@ -7,4 +7,5 @@
dictionary WindowPostMessageOptions {
USVString targetOrigin = "/";
sequence<object> transfer = [];
[RuntimeEnabled=UserActivationAPI] boolean includeUserActivation = false;
};
......@@ -38,6 +38,11 @@ BlinkTransferableMessage ToBlinkTransferableMessage(
message.stack_trace_debugger_id_second));
result.ports.AppendRange(message.ports.begin(), message.ports.end());
result.has_user_gesture = message.has_user_gesture;
if (message.user_activation) {
result.user_activation = mojom::blink::UserActivationSnapshot::New(
message.user_activation->has_been_active,
message.user_activation->was_active);
}
return result;
}
......@@ -60,6 +65,11 @@ TransferableMessage ToTransferableMessage(BlinkTransferableMessage message) {
message.sender_stack_trace_id.debugger_id.second;
result.ports.assign(message.ports.begin(), message.ports.end());
result.has_user_gesture = message.has_user_gesture;
if (message.user_activation) {
result.user_activation = mojom::UserActivationSnapshot::New(
message.user_activation->has_been_active,
message.user_activation->was_active);
}
return result;
}
......
......@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "third_party/blink/public/common/message_port/message_port_channel.h"
#include "third_party/blink/public/common/message_port/transferable_message.h"
#include "third_party/blink/public/mojom/message_port/user_activation_snapshot.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/messaging/blink_cloneable_message.h"
......@@ -29,6 +30,8 @@ struct CORE_EXPORT BlinkTransferableMessage : BlinkCloneableMessage {
bool has_user_gesture = false;
mojom::blink::UserActivationSnapshotPtr user_activation;
private:
DISALLOW_COPY_AND_ASSIGN(BlinkTransferableMessage);
};
......
......@@ -5,6 +5,7 @@
#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/public/mojom/message_port/message_port.mojom-blink.h"
#include "third_party/blink/renderer/core/imagebitmap/image_bitmap.h"
#include "third_party/skia/include/core/SkBitmap.h"
......@@ -71,7 +72,7 @@ bool StructTraits<blink::mojom::blink::TransferableMessage::DataView,
if (!data.ReadMessage(static_cast<blink::BlinkCloneableMessage*>(out)) ||
!data.ReadArrayBufferContentsArray(&array_buffer_contents_array) ||
!data.ReadImageBitmapContentsArray(&sk_bitmaps) ||
!data.ReadPorts(&ports)) {
!data.ReadPorts(&ports) || !data.ReadUserActivation(&out->user_activation)) {
return false;
}
......@@ -98,7 +99,6 @@ bool StructTraits<blink::mojom::blink::TransferableMessage::DataView,
image_bitmap_contents_array.push_back(bitmap_contents);
}
out->message->SetImageBitmapContentsArray(image_bitmap_contents_array);
return true;
}
......
......@@ -46,6 +46,11 @@ struct CORE_EXPORT
return input.has_user_gesture;
}
static const blink::mojom::blink::UserActivationSnapshotPtr& user_activation(
const blink::BlinkTransferableMessage& input) {
return input.user_activation;
}
static bool Read(blink::mojom::blink::TransferableMessage::DataView,
blink::BlinkTransferableMessage* out);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment