2 * Copyright (C) 2007 Henry Mason (hmason@mac.com)
3 * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "core/events/MessageEvent.h"
31 #include "bindings/core/v8/ExceptionMessages.h"
32 #include "bindings/core/v8/ExceptionState.h"
33 #include "bindings/core/v8/V8ArrayBuffer.h"
37 static inline bool isValidSource(EventTarget
* source
)
39 return !source
|| source
->toDOMWindow() || source
->toMessagePort();
42 MessageEvent::MessageEvent()
43 : m_dataType(DataTypeScriptValue
)
47 MessageEvent::MessageEvent(const AtomicString
& type
, const MessageEventInit
& initializer
)
48 : Event(type
, initializer
)
49 , m_dataType(DataTypeScriptValue
)
52 if (initializer
.hasData())
53 m_dataAsScriptValue
= initializer
.data();
54 if (initializer
.hasOrigin())
55 m_origin
= initializer
.origin();
56 if (initializer
.hasLastEventId())
57 m_lastEventId
= initializer
.lastEventId();
58 if (initializer
.hasSource() && isValidSource(initializer
.source().get()))
59 m_source
= initializer
.source();
60 if (initializer
.hasPorts())
61 m_ports
= new MessagePortArray(initializer
.ports());
62 ASSERT(isValidSource(m_source
.get()));
65 MessageEvent::MessageEvent(const String
& origin
, const String
& lastEventId
, PassRefPtrWillBeRawPtr
<EventTarget
> source
, MessagePortArray
* ports
)
66 : Event(EventTypeNames::message
, false, false)
67 , m_dataType(DataTypeScriptValue
)
69 , m_lastEventId(lastEventId
)
73 ASSERT(isValidSource(m_source
.get()));
76 MessageEvent::MessageEvent(PassRefPtr
<SerializedScriptValue
> data
, const String
& origin
, const String
& lastEventId
, PassRefPtrWillBeRawPtr
<EventTarget
> source
, MessagePortArray
* ports
)
77 : Event(EventTypeNames::message
, false, false)
78 , m_dataType(DataTypeSerializedScriptValue
)
79 , m_dataAsSerializedScriptValue(data
)
81 , m_lastEventId(lastEventId
)
85 if (m_dataAsSerializedScriptValue
)
86 m_dataAsSerializedScriptValue
->registerMemoryAllocatedWithCurrentScriptContext();
87 ASSERT(isValidSource(m_source
.get()));
90 MessageEvent::MessageEvent(PassRefPtr
<SerializedScriptValue
> data
, const String
& origin
, const String
& lastEventId
, PassRefPtrWillBeRawPtr
<EventTarget
> source
, PassOwnPtr
<MessagePortChannelArray
> channels
)
91 : Event(EventTypeNames::message
, false, false)
92 , m_dataType(DataTypeSerializedScriptValue
)
93 , m_dataAsSerializedScriptValue(data
)
95 , m_lastEventId(lastEventId
)
97 , m_channels(channels
)
99 if (m_dataAsSerializedScriptValue
)
100 m_dataAsSerializedScriptValue
->registerMemoryAllocatedWithCurrentScriptContext();
101 ASSERT(isValidSource(m_source
.get()));
104 MessageEvent::MessageEvent(const String
& data
, const String
& origin
)
105 : Event(EventTypeNames::message
, false, false)
106 , m_dataType(DataTypeString
)
107 , m_dataAsString(data
)
112 MessageEvent::MessageEvent(Blob
* data
, const String
& origin
)
113 : Event(EventTypeNames::message
, false, false)
114 , m_dataType(DataTypeBlob
)
120 MessageEvent::MessageEvent(PassRefPtr
<DOMArrayBuffer
> data
, const String
& origin
)
121 : Event(EventTypeNames::message
, false, false)
122 , m_dataType(DataTypeArrayBuffer
)
123 , m_dataAsArrayBuffer(data
)
128 MessageEvent::~MessageEvent()
132 PassRefPtrWillBeRawPtr
<MessageEvent
> MessageEvent::create(const AtomicString
& type
, const MessageEventInit
& initializer
, ExceptionState
& exceptionState
)
134 if (initializer
.source().get() && !isValidSource(initializer
.source().get())) {
135 exceptionState
.throwTypeError("The optional 'source' property is neither a Window nor MessagePort.");
138 return adoptRefWillBeNoop(new MessageEvent(type
, initializer
));
141 void MessageEvent::initMessageEvent(const AtomicString
& type
, bool canBubble
, bool cancelable
, ScriptValue data
, const String
& origin
, const String
& lastEventId
, DOMWindow
* source
, MessagePortArray
* ports
)
146 initEvent(type
, canBubble
, cancelable
);
148 m_dataType
= DataTypeScriptValue
;
149 m_dataAsScriptValue
= data
;
151 m_lastEventId
= lastEventId
;
156 void MessageEvent::initMessageEvent(const AtomicString
& type
, bool canBubble
, bool cancelable
, PassRefPtr
<SerializedScriptValue
> data
, const String
& origin
, const String
& lastEventId
, DOMWindow
* source
, MessagePortArray
* ports
)
161 initEvent(type
, canBubble
, cancelable
);
163 m_dataType
= DataTypeSerializedScriptValue
;
164 m_dataAsSerializedScriptValue
= data
;
166 m_lastEventId
= lastEventId
;
170 if (m_dataAsSerializedScriptValue
)
171 m_dataAsSerializedScriptValue
->registerMemoryAllocatedWithCurrentScriptContext();
174 const AtomicString
& MessageEvent::interfaceName() const
176 return EventNames::MessageEvent
;
179 MessagePortArray
MessageEvent::ports(bool& isNull
) const
181 // TODO(bashi): Currently we return a copied array because the binding
182 // layer could modify the content of the array while executing JS callbacks.
183 // Avoid copying once we can make sure that the binding layer won't
184 // modify the content.
190 return MessagePortArray();
193 MessagePortArray
MessageEvent::ports() const
196 return ports(unused
);
199 void MessageEvent::entangleMessagePorts(ExecutionContext
* context
)
201 m_ports
= MessagePort::entanglePorts(*context
, m_channels
.release());
204 DEFINE_TRACE(MessageEvent
)
206 visitor
->trace(m_dataAsBlob
);
207 visitor
->trace(m_source
);
209 visitor
->trace(m_ports
);
211 Event::trace(visitor
);
214 v8::Local
<v8::Object
> MessageEvent::associateWithWrapper(v8::Isolate
* isolate
, const WrapperTypeInfo
* wrapperType
, v8::Local
<v8::Object
> wrapper
)
216 wrapper
= Event::associateWithWrapper(isolate
, wrapperType
, wrapper
);
218 // Ensures a wrapper is created for the data to return now so that V8 knows how
219 // much memory is used via the wrapper. To keep the wrapper alive, it's set to
220 // the wrapper of the MessageEvent as a hidden value.
221 switch (dataType()) {
222 case MessageEvent::DataTypeScriptValue
:
223 case MessageEvent::DataTypeSerializedScriptValue
:
225 case MessageEvent::DataTypeString
:
226 V8HiddenValue::setHiddenValue(isolate
, wrapper
, V8HiddenValue::stringData(isolate
), v8String(isolate
, dataAsString()));
228 case MessageEvent::DataTypeBlob
:
230 case MessageEvent::DataTypeArrayBuffer
:
231 V8HiddenValue::setHiddenValue(isolate
, wrapper
, V8HiddenValue::arrayBufferData(isolate
), toV8(dataAsArrayBuffer(), wrapper
, isolate
));