46
46
#include " mozilla/dom/MessagePortBinding.h"
47
47
#include " mozilla/dom/OffscreenCanvas.h"
48
48
#include " mozilla/dom/OffscreenCanvasBinding.h"
49
+ #include " mozilla/dom/ReadableStream.h"
50
+ #include " mozilla/dom/ReadableStreamBinding.h"
49
51
#include " mozilla/dom/ScriptSettings.h"
50
52
#include " mozilla/dom/StructuredCloneBlob.h"
51
53
#include " mozilla/dom/StructuredCloneHolderBinding.h"
52
54
#include " mozilla/dom/StructuredCloneTags.h"
53
55
#include " mozilla/dom/ToJSValue.h"
56
+ #include " mozilla/dom/TransformStream.h"
57
+ #include " mozilla/dom/TransformStreamBinding.h"
54
58
#include " mozilla/dom/WebIDLSerializable.h"
59
+ #include " mozilla/dom/WritableStream.h"
60
+ #include " mozilla/dom/WritableStreamBinding.h"
55
61
#include " mozilla/dom/WorkerCommon.h"
56
62
#include " mozilla/dom/WorkerPrivate.h"
57
63
#include " mozilla/fallible.h"
@@ -1115,7 +1121,26 @@ bool StructuredCloneHolder::CustomWriteHandler(
1115
1121
return WriteFullySerializableObjects (aCx, aWriter, aObj);
1116
1122
}
1117
1123
1118
- bool StructuredCloneHolder::CustomReadTransferHandler (
1124
+ already_AddRefed<MessagePort> StructuredCloneHolder::ReceiveMessagePort (
1125
+ uint64_t aIndex) {
1126
+ if (NS_WARN_IF(aIndex >= mPortIdentifiers .Length ())) {
1127
+ return nullptr ;
1128
+ }
1129
+ UniqueMessagePortId portId (mPortIdentifiers [aIndex]);
1130
+
1131
+ ErrorResult rv;
1132
+ RefPtr<MessagePort> port = MessagePort::Create (mGlobal , portId, rv);
1133
+ if (NS_WARN_IF(rv.Failed ())) {
1134
+ rv.SuppressException ();
1135
+ return nullptr ;
1136
+ }
1137
+
1138
+ return port.forget ();
1139
+ }
1140
+
1141
+ // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
1142
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY bool
1143
+ StructuredCloneHolder::CustomReadTransferHandler (
1119
1144
JSContext* aCx, JSStructuredCloneReader* aReader, uint32_t aTag,
1120
1145
void * aContent, uint64_t aExtraData,
1121
1146
JS::MutableHandleObject aReturnObject) {
@@ -1127,16 +1152,10 @@ bool StructuredCloneHolder::CustomReadTransferHandler(
1127
1152
return false ;
1128
1153
}
1129
1154
#endif
1130
- MOZ_ASSERT (aExtraData < mPortIdentifiers .Length ());
1131
- UniqueMessagePortId portIdentifier (mPortIdentifiers [aExtraData]);
1132
-
1133
- ErrorResult rv;
1134
- RefPtr<MessagePort> port = MessagePort::Create (mGlobal , portIdentifier, rv);
1135
- if (NS_WARN_IF(rv.Failed ())) {
1136
- rv.SuppressException ();
1155
+ RefPtr<MessagePort> port = ReceiveMessagePort (aExtraData);
1156
+ if (!port) {
1137
1157
return false ;
1138
1158
}
1139
-
1140
1159
mTransferredPorts .AppendElement (port);
1141
1160
1142
1161
JS::Rooted<JS::Value> value (aCx);
@@ -1186,10 +1205,56 @@ bool StructuredCloneHolder::CustomReadTransferHandler(
1186
1205
return true ;
1187
1206
}
1188
1207
1208
+ if (aTag == SCTAG_DOM_READABLESTREAM) {
1209
+ #ifdef FUZZING
1210
+ if (aExtraData >= mPortIdentifiers .Length ()) {
1211
+ return false ;
1212
+ }
1213
+ #endif
1214
+ RefPtr<MessagePort> port = ReceiveMessagePort (aExtraData);
1215
+ if (!port) {
1216
+ return false ;
1217
+ }
1218
+ nsCOMPtr<nsIGlobalObject> global = mGlobal ;
1219
+ return ReadableStream::ReceiveTransfer (aCx, global, *port, aReturnObject);
1220
+ }
1221
+
1222
+ if (aTag == SCTAG_DOM_WRITABLESTREAM) {
1223
+ #ifdef FUZZING
1224
+ if (aExtraData >= mPortIdentifiers .Length ()) {
1225
+ return false ;
1226
+ }
1227
+ #endif
1228
+ RefPtr<MessagePort> port = ReceiveMessagePort (aExtraData);
1229
+ if (!port) {
1230
+ return false ;
1231
+ }
1232
+ nsCOMPtr<nsIGlobalObject> global = mGlobal ;
1233
+ return WritableStream::ReceiveTransfer (aCx, global, *port, aReturnObject);
1234
+ }
1235
+
1236
+ if (aTag == SCTAG_DOM_TRANSFORMSTREAM) {
1237
+ #ifdef FUZZING
1238
+ if (aExtraData + 1 >= mPortIdentifiers .Length ()) {
1239
+ return false ;
1240
+ }
1241
+ #endif
1242
+ RefPtr<MessagePort> port1 = ReceiveMessagePort (aExtraData);
1243
+ RefPtr<MessagePort> port2 = ReceiveMessagePort (aExtraData + 1 );
1244
+ if (!port1 || !port2) {
1245
+ return false ;
1246
+ }
1247
+ nsCOMPtr<nsIGlobalObject> global = mGlobal ;
1248
+ return TransformStream::ReceiveTransfer (aCx, global, *port1, *port2,
1249
+ aReturnObject);
1250
+ }
1251
+
1189
1252
return false ;
1190
1253
}
1191
1254
1192
- bool StructuredCloneHolder::CustomWriteTransferHandler (
1255
+ // TODO: Convert this to MOZ_CAN_RUN_SCRIPT (bug 1415230)
1256
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY bool
1257
+ StructuredCloneHolder::CustomWriteTransferHandler (
1193
1258
JSContext* aCx, JS::Handle <JSObject*> aObj, uint32_t * aTag,
1194
1259
JS::TransferableOwnership* aOwnership, void ** aContent,
1195
1260
uint64_t * aExtraData) {
@@ -1263,6 +1328,68 @@ bool StructuredCloneHolder::CustomWriteTransferHandler(
1263
1328
return true ;
1264
1329
}
1265
1330
}
1331
+
1332
+ {
1333
+ RefPtr<ReadableStream> stream;
1334
+ rv = UNWRAP_OBJECT (ReadableStream, &obj, stream);
1335
+ if (NS_SUCCEEDED(rv)) {
1336
+ MOZ_ASSERT (stream);
1337
+
1338
+ *aTag = SCTAG_DOM_READABLESTREAM;
1339
+ *aOwnership = JS::SCTAG_TMO_CUSTOM;
1340
+ *aContent = nullptr ;
1341
+
1342
+ UniqueMessagePortId id;
1343
+ if (!stream->Transfer (aCx, id)) {
1344
+ return false ;
1345
+ }
1346
+ *aExtraData = mPortIdentifiers .Length ();
1347
+ mPortIdentifiers .AppendElement (id.release ());
1348
+ return true ;
1349
+ }
1350
+ }
1351
+
1352
+ {
1353
+ RefPtr<WritableStream> stream;
1354
+ rv = UNWRAP_OBJECT (WritableStream, &obj, stream);
1355
+ if (NS_SUCCEEDED(rv)) {
1356
+ MOZ_ASSERT (stream);
1357
+
1358
+ *aTag = SCTAG_DOM_WRITABLESTREAM;
1359
+ *aOwnership = JS::SCTAG_TMO_CUSTOM;
1360
+ *aContent = nullptr ;
1361
+
1362
+ UniqueMessagePortId id;
1363
+ if (!stream->Transfer (aCx, id)) {
1364
+ return false ;
1365
+ }
1366
+ *aExtraData = mPortIdentifiers .Length ();
1367
+ mPortIdentifiers .AppendElement (id.release ());
1368
+ return true ;
1369
+ }
1370
+ }
1371
+
1372
+ {
1373
+ RefPtr<TransformStream> stream;
1374
+ rv = UNWRAP_OBJECT (TransformStream, &obj, stream);
1375
+ if (NS_SUCCEEDED(rv)) {
1376
+ MOZ_ASSERT (stream);
1377
+
1378
+ *aTag = SCTAG_DOM_TRANSFORMSTREAM;
1379
+ *aOwnership = JS::SCTAG_TMO_CUSTOM;
1380
+ *aContent = nullptr ;
1381
+
1382
+ UniqueMessagePortId id1;
1383
+ UniqueMessagePortId id2;
1384
+ if (!stream->Transfer (aCx, id1, id2)) {
1385
+ return false ;
1386
+ }
1387
+ *aExtraData = mPortIdentifiers .Length ();
1388
+ mPortIdentifiers .AppendElement (id1.release ());
1389
+ mPortIdentifiers .AppendElement (id2.release ());
1390
+ return true ;
1391
+ }
1392
+ }
1266
1393
}
1267
1394
1268
1395
return false ;
@@ -1301,6 +1428,31 @@ void StructuredCloneHolder::CustomFreeTransferHandler(
1301
1428
delete data;
1302
1429
return ;
1303
1430
}
1431
+
1432
+ if (aTag == SCTAG_DOM_READABLESTREAM || aTag == SCTAG_DOM_WRITABLESTREAM) {
1433
+ MOZ_ASSERT (!aContent);
1434
+ #ifdef FUZZING
1435
+ if (aExtraData >= mPortIdentifiers .Length ()) {
1436
+ return ;
1437
+ }
1438
+ #endif
1439
+ MOZ_ASSERT (aExtraData < mPortIdentifiers .Length ());
1440
+ MessagePort::ForceClose (mPortIdentifiers [aExtraData]);
1441
+ return ;
1442
+ }
1443
+
1444
+ if (aTag == SCTAG_DOM_TRANSFORMSTREAM) {
1445
+ MOZ_ASSERT (!aContent);
1446
+ #ifdef FUZZING
1447
+ if (aExtraData + 1 >= mPortIdentifiers .Length ()) {
1448
+ return ;
1449
+ }
1450
+ #endif
1451
+ MOZ_ASSERT (aExtraData + 1 < mPortIdentifiers .Length ());
1452
+ MessagePort::ForceClose (mPortIdentifiers [aExtraData]);
1453
+ MessagePort::ForceClose (mPortIdentifiers [aExtraData + 1 ]);
1454
+ return ;
1455
+ }
1304
1456
}
1305
1457
1306
1458
bool StructuredCloneHolder::CustomCanTransferHandler (
@@ -1342,6 +1494,40 @@ bool StructuredCloneHolder::CustomCanTransferHandler(
1342
1494
}
1343
1495
}
1344
1496
1497
+ {
1498
+ ReadableStream* stream = nullptr ;
1499
+ nsresult rv = UNWRAP_OBJECT (ReadableStream, &obj, stream);
1500
+ if (NS_SUCCEEDED(rv)) {
1501
+ // https://streams.spec.whatwg.org/#ref-for-transfer-steps
1502
+ // Step 1: If ! IsReadableStreamLocked(value) is true, throw a
1503
+ // "DataCloneError" DOMException.
1504
+ return !IsReadableStreamLocked (stream);
1505
+ }
1506
+ }
1507
+
1508
+ {
1509
+ WritableStream* stream = nullptr ;
1510
+ nsresult rv = UNWRAP_OBJECT (WritableStream, &obj, stream);
1511
+ if (NS_SUCCEEDED(rv)) {
1512
+ // https://streams.spec.whatwg.org/#ref-for-transfer-steps①
1513
+ // Step 1: If ! IsWritableStreamLocked(value) is true, throw a
1514
+ // "DataCloneError" DOMException.
1515
+ return !IsWritableStreamLocked (stream);
1516
+ }
1517
+ }
1518
+
1519
+ {
1520
+ TransformStream* stream = nullptr ;
1521
+ nsresult rv = UNWRAP_OBJECT (TransformStream, &obj, stream);
1522
+ if (NS_SUCCEEDED(rv)) {
1523
+ // https://streams.spec.whatwg.org/#ref-for-transfer-steps②
1524
+ // Step 3 + 4: If ! Is{Readable,Writable}StreamLocked(value) is true,
1525
+ // throw a "DataCloneError" DOMException.
1526
+ return !IsReadableStreamLocked (stream->Readable ()) &&
1527
+ !IsWritableStreamLocked (stream->Writable ());
1528
+ }
1529
+ }
1530
+
1345
1531
return false ;
1346
1532
}
1347
1533
0 commit comments