OLD | NEW |
(Empty) | |
| 1 #include "config.h" |
| 2 #include "bindings/core/v8/SerializedScriptValueFactory.h" |
| 3 #include "bindings/core/v8/V8MessagePort.h" |
| 4 #include "core/dom/DOMArrayBuffer.h" |
| 5 #include "core/dom/ExceptionCode.h" |
| 6 |
| 7 namespace blink { |
| 8 |
| 9 static void acculumateArrayBuffersForAllWorlds(v8::Isolate* isolate, DOMArrayBuf
fer* object, Vector<v8::Local<v8::ArrayBuffer>, 4>& buffers) |
| 10 { |
| 11 if (isMainThread()) { |
| 12 Vector<RefPtr<DOMWrapperWorld>> worlds; |
| 13 DOMWrapperWorld::allWorldsInMainThread(worlds); |
| 14 for (size_t i = 0; i < worlds.size(); i++) { |
| 15 v8::Local<v8::Object> wrapper = worlds[i]->domDataStore().get(object
, isolate); |
| 16 if (!wrapper.IsEmpty()) |
| 17 buffers.append(v8::Local<v8::ArrayBuffer>::Cast(wrapper)); |
| 18 } |
| 19 } else { |
| 20 v8::Local<v8::Object> wrapper = DOMWrapperWorld::current(isolate).domDat
aStore().get(object, isolate); |
| 21 if (!wrapper.IsEmpty()) |
| 22 buffers.append(v8::Local<v8::ArrayBuffer>::Cast(wrapper)); |
| 23 } |
| 24 } |
| 25 |
| 26 typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; |
| 27 |
| 28 static PassOwnPtr<ArrayBufferContentsArray> neuterTransferableArrayBuffers(v8::I
solate* isolate, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState) |
| 29 { |
| 30 OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContents
Array(arrayBuffers.size())); |
| 31 |
| 32 HashSet<DOMArrayBufferBase*> visited; |
| 33 for (size_t i = 0; i < arrayBuffers.size(); i++) { |
| 34 if (visited.contains(arrayBuffers[i].get())) |
| 35 continue; |
| 36 visited.add(arrayBuffers[i].get()); |
| 37 |
| 38 if (arrayBuffers[i]->isShared()) { |
| 39 // Don't have to neuter SharedArrayBuffer. |
| 40 continue; |
| 41 } |
| 42 |
| 43 Vector<v8::Local<v8::ArrayBuffer>, 4> bufferHandles; |
| 44 v8::HandleScope handleScope(isolate); |
| 45 acculumateArrayBuffersForAllWorlds(isolate, static_pointer_cast<DOMArray
Buffer>(arrayBuffers[i]).get(), bufferHandles); |
| 46 bool isNeuterable = true; |
| 47 for (size_t j = 0; j < bufferHandles.size(); j++) |
| 48 isNeuterable &= bufferHandles[j]->IsNeuterable(); |
| 49 |
| 50 RefPtr<DOMArrayBufferBase> toTransfer = arrayBuffers[i]; |
| 51 if (!isNeuterable) |
| 52 continue; |
| 53 |
| 54 bool result = toTransfer->transfer(contents->at(i)); |
| 55 if (!result) { |
| 56 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at ind
ex " + String::number(i) + " could not be transferred."); |
| 57 return nullptr; |
| 58 } |
| 59 |
| 60 for (size_t j = 0; j < bufferHandles.size(); j++) |
| 61 bufferHandles[j]->Neuter(); |
| 62 } |
| 63 |
| 64 return contents.release(); |
| 65 } |
| 66 |
| 67 void V8MessagePort::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::V
alue>& info) |
| 68 { |
| 69 ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage
", "MessagePort", info.Holder(), info.GetIsolate()); |
| 70 if (UNLIKELY(info.Length() < 1)) { |
| 71 setMinimumArityTypeError(exceptionState, 1, info.Length()); |
| 72 exceptionState.throwIfNeeded(); |
| 73 return; |
| 74 } |
| 75 MessagePort* messagePort = V8MessagePort::toImpl(info.Holder()); |
| 76 OwnPtrWillBeRawPtr<MessagePortArray> ports = adoptPtrWillBeNoop(new MessageP
ortArray); |
| 77 ArrayBufferArray arrayBuffers; |
| 78 if (info.Length() > 1) { |
| 79 const int transferablesArgIndex = 1; |
| 80 if (!SerializedScriptValue::extractTransferables(info.GetIsolate(), info
[transferablesArgIndex], transferablesArgIndex, *ports, arrayBuffers, exceptionS
tate)) { |
| 81 exceptionState.throwIfNeeded(); |
| 82 return; |
| 83 } |
| 84 } |
| 85 |
| 86 for (size_t i = 0; i < arrayBuffers.size(); i++) { |
| 87 if (arrayBuffers[i]->isNeutered()) { |
| 88 exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at ind
ex " + String::number(i) + " is already neutered."); |
| 89 return; |
| 90 } |
| 91 } |
| 92 |
| 93 // TODO(nhiroki) |
| 94 RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instan
ce().create(info.GetIsolate(), info[0], ports.get(), nullptr /* arrayBuffers */,
exceptionState); |
| 95 if (exceptionState.throwIfNeeded()) |
| 96 return; |
| 97 |
| 98 if (!arrayBuffers.isEmpty()) { |
| 99 neuterTransferableArrayBuffers(info.GetIsolate(), arrayBuffers, exceptio
nState); |
| 100 if (exceptionState.throwIfNeeded()) |
| 101 return; |
| 102 } |
| 103 |
| 104 // FIXME: Only pass context/exceptionState if instance really requires it. |
| 105 ExecutionContext* context = currentExecutionContext(info.GetIsolate()); |
| 106 messagePort->postMessage(context, message.release(), ports.get(), exceptionS
tate); |
| 107 exceptionState.throwIfNeeded(); |
| 108 } |
| 109 |
| 110 } // namespace blink |
OLD | NEW |