Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(577)

Side by Side Diff: third_party/WebKit/Source/bindings/core/v8/SerializedScriptValue.cpp

Issue 2414333003: WebMessaging: Send transferable ArrayBuffers by copy-and-neuter semantics (Closed)
Patch Set: fix tests Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 const LChar* src = m_data.characters8(); 142 const LChar* src = m_data.characters8();
143 for (size_t i = 0; i < length; i++) 143 for (size_t i = 0; i < length; i++)
144 dst[i] = htons(static_cast<UChar>(src[i])); 144 dst[i] = htons(static_cast<UChar>(src[i]));
145 } else { 145 } else {
146 const UChar* src = m_data.characters16(); 146 const UChar* src = m_data.characters16();
147 for (size_t i = 0; i < length; i++) 147 for (size_t i = 0; i < length; i++)
148 dst[i] = htons(src[i]); 148 dst[i] = htons(src[i]);
149 } 149 }
150 } 150 }
151 151
152 static void acculumateArrayBuffersForAllWorlds( 152 static void accumulateArrayBuffersForAllWorlds(
153 v8::Isolate* isolate, 153 v8::Isolate* isolate,
154 DOMArrayBuffer* object, 154 DOMArrayBuffer* object,
155 Vector<v8::Local<v8::ArrayBuffer>, 4>& buffers) { 155 Vector<v8::Local<v8::ArrayBuffer>, 4>& buffers) {
156 if (isMainThread()) { 156 if (isMainThread()) {
157 Vector<RefPtr<DOMWrapperWorld>> worlds; 157 Vector<RefPtr<DOMWrapperWorld>> worlds;
158 DOMWrapperWorld::allWorldsInMainThread(worlds); 158 DOMWrapperWorld::allWorldsInMainThread(worlds);
159 for (size_t i = 0; i < worlds.size(); i++) { 159 for (size_t i = 0; i < worlds.size(); i++) {
160 v8::Local<v8::Object> wrapper = 160 v8::Local<v8::Object> wrapper =
161 worlds[i]->domDataStore().get(object, isolate); 161 worlds[i]->domDataStore().get(object, isolate);
162 if (!wrapper.IsEmpty()) 162 if (!wrapper.IsEmpty())
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 223 }
224 visited.add(offscreenCanvases[i].get()); 224 visited.add(offscreenCanvases[i].get());
225 offscreenCanvases[i].get()->setNeutered(); 225 offscreenCanvases[i].get()->setNeutered();
226 } 226 }
227 } 227 }
228 228
229 void SerializedScriptValue::transferArrayBuffers( 229 void SerializedScriptValue::transferArrayBuffers(
230 v8::Isolate* isolate, 230 v8::Isolate* isolate,
231 const ArrayBufferArray& arrayBuffers, 231 const ArrayBufferArray& arrayBuffers,
232 ExceptionState& exceptionState) { 232 ExceptionState& exceptionState) {
233 if (!arrayBuffers.size()) 233 m_arrayBufferContentsArray =
234 return; 234 transferArrayBufferContents(isolate, arrayBuffers, exceptionState);
235
236 for (size_t i = 0; i < arrayBuffers.size(); ++i) {
237 if (arrayBuffers[i]->isNeutered()) {
238 exceptionState.throwDOMException(
239 DataCloneError, "ArrayBuffer at index " + String::number(i) +
240 " is already neutered.");
241 return;
242 }
243 }
244
245 std::unique_ptr<ArrayBufferContentsArray> contents =
246 wrapUnique(new ArrayBufferContentsArray(arrayBuffers.size()));
247
248 HeapHashSet<Member<DOMArrayBufferBase>> visited;
249 for (size_t i = 0; i < arrayBuffers.size(); ++i) {
250 if (visited.contains(arrayBuffers[i]))
251 continue;
252 visited.add(arrayBuffers[i]);
253
254 if (arrayBuffers[i]->isShared()) {
255 bool result = arrayBuffers[i]->shareContentsWith(contents->at(i));
256 if (!result) {
257 exceptionState.throwDOMException(
258 DataCloneError, "SharedArrayBuffer at index " + String::number(i) +
259 " could not be transferred.");
260 return;
261 }
262 } else {
263 Vector<v8::Local<v8::ArrayBuffer>, 4> bufferHandles;
264 v8::HandleScope handleScope(isolate);
265 acculumateArrayBuffersForAllWorlds(
266 isolate, static_cast<DOMArrayBuffer*>(arrayBuffers[i].get()),
267 bufferHandles);
268 bool isNeuterable = true;
269 for (size_t j = 0; j < bufferHandles.size(); ++j)
270 isNeuterable &= bufferHandles[j]->IsNeuterable();
271
272 DOMArrayBufferBase* toTransfer = arrayBuffers[i];
273 if (!isNeuterable)
274 toTransfer =
275 DOMArrayBuffer::create(arrayBuffers[i]->buffer()->data(),
276 arrayBuffers[i]->buffer()->byteLength());
277 bool result = toTransfer->transfer(contents->at(i));
278 if (!result) {
279 exceptionState.throwDOMException(
280 DataCloneError, "ArrayBuffer at index " + String::number(i) +
281 " could not be transferred.");
282 return;
283 }
284
285 if (isNeuterable)
286 for (size_t j = 0; j < bufferHandles.size(); ++j)
287 bufferHandles[j]->Neuter();
288 }
289 }
290 m_arrayBufferContentsArray = std::move(contents);
291 } 235 }
292 236
293 v8::Local<v8::Value> SerializedScriptValue::deserialize( 237 v8::Local<v8::Value> SerializedScriptValue::deserialize(
294 MessagePortArray* messagePorts) { 238 MessagePortArray* messagePorts) {
295 return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0); 239 return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0);
296 } 240 }
297 241
298 v8::Local<v8::Value> SerializedScriptValue::deserialize( 242 v8::Local<v8::Value> SerializedScriptValue::deserialize(
299 v8::Isolate* isolate, 243 v8::Isolate* isolate,
300 MessagePortArray* messagePorts, 244 MessagePortArray* messagePorts,
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 transferables.offscreenCanvases.append(offscreenCanvas); 339 transferables.offscreenCanvases.append(offscreenCanvas);
396 } else { 340 } else {
397 exceptionState.throwTypeError("Value at index " + String::number(i) + 341 exceptionState.throwTypeError("Value at index " + String::number(i) +
398 " does not have a transferable type."); 342 " does not have a transferable type.");
399 return false; 343 return false;
400 } 344 }
401 } 345 }
402 return true; 346 return true;
403 } 347 }
404 348
349 std::unique_ptr<ArrayBufferContentsArray>
350 SerializedScriptValue::transferArrayBufferContents(
351 v8::Isolate* isolate,
352 const ArrayBufferArray& arrayBuffers,
353 ExceptionState& exceptionState) {
354 if (!arrayBuffers.size())
355 return nullptr;
356
357 for (auto it = arrayBuffers.begin(); it != arrayBuffers.end(); ++it) {
358 DOMArrayBufferBase* arrayBuffer = *it;
359 if (arrayBuffer->isNeutered()) {
360 size_t index = std::distance(arrayBuffers.begin(), it);
361 exceptionState.throwDOMException(
362 DataCloneError, "ArrayBuffer at index " + String::number(index) +
363 " is already neutered.");
364 return nullptr;
365 }
366 }
367
368 std::unique_ptr<ArrayBufferContentsArray> contents =
369 wrapUnique(new ArrayBufferContentsArray(arrayBuffers.size()));
370
371 HeapHashSet<Member<DOMArrayBufferBase>> visited;
372 for (auto it = arrayBuffers.begin(); it != arrayBuffers.end(); ++it) {
373 DOMArrayBufferBase* arrayBuffer = *it;
374 if (visited.contains(arrayBuffer))
375 continue;
376 visited.add(arrayBuffer);
377
378 size_t index = std::distance(arrayBuffers.begin(), it);
379 if (arrayBuffer->isShared()) {
380 if (!arrayBuffer->shareContentsWith(contents->at(index))) {
381 exceptionState.throwDOMException(DataCloneError,
382 "SharedArrayBuffer at index " +
383 String::number(index) +
384 " could not be transferred.");
385 return nullptr;
386 }
387 } else {
388 Vector<v8::Local<v8::ArrayBuffer>, 4> bufferHandles;
389 v8::HandleScope handleScope(isolate);
390 accumulateArrayBuffersForAllWorlds(
391 isolate, static_cast<DOMArrayBuffer*>(it->get()), bufferHandles);
392 bool isNeuterable = true;
393 for (const auto& bufferHandle : bufferHandles)
394 isNeuterable &= bufferHandle->IsNeuterable();
395
396 DOMArrayBufferBase* toTransfer = arrayBuffer;
397 if (!isNeuterable) {
398 toTransfer = DOMArrayBuffer::create(
399 arrayBuffer->buffer()->data(), arrayBuffer->buffer()->byteLength());
400 }
401 if (!toTransfer->transfer(contents->at(index))) {
402 exceptionState.throwDOMException(
403 DataCloneError, "ArrayBuffer at index " + String::number(index) +
404 " could not be transferred.");
405 return nullptr;
406 }
407
408 if (isNeuterable) {
409 for (const auto& bufferHandle : bufferHandles)
410 bufferHandle->Neuter();
411 }
412 }
413 }
414 return contents;
415 }
416
405 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext() { 417 void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext() {
406 if (m_externallyAllocatedMemory) 418 if (m_externallyAllocatedMemory)
407 return; 419 return;
408 m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length()); 420 m_externallyAllocatedMemory = static_cast<intptr_t>(m_data.length());
409 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory( 421 v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(
410 m_externallyAllocatedMemory); 422 m_externallyAllocatedMemory);
411 } 423 }
412 424
413 bool SerializedScriptValue::containsTransferableArrayBuffer() const {
414 return m_arrayBufferContentsArray && !m_arrayBufferContentsArray->isEmpty();
415 }
416
417 } // namespace blink 425 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698