dfindexeddb 20240402__py3-none-any.whl → 20240501__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,14 +13,340 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
  """Parsers for blink javascript serialized objects."""
16
+ from __future__ import annotations
17
+ from dataclasses import dataclass
16
18
  import io
17
- from typing import Any
19
+ from typing import Any, Optional, Union
18
20
 
21
+ from dfindexeddb import errors
19
22
  from dfindexeddb import utils
20
23
  from dfindexeddb.indexeddb.chromium import definitions
21
24
  from dfindexeddb.indexeddb.chromium import v8
22
25
 
23
26
 
27
+ _MS_PER_SECOND = 1000
28
+
29
+
30
+ @dataclass
31
+ class AudioData:
32
+ """A Javascript AudioData class.
33
+
34
+ Attributes:
35
+ audio_frame_index: the Audio Frame index.
36
+ """
37
+ audio_frame_index: int
38
+
39
+
40
+ @dataclass
41
+ class BaseIndex:
42
+ """A base index class."""
43
+ index: int
44
+
45
+
46
+ @dataclass
47
+ class BitMap:
48
+ """A Javascript BitMap."""
49
+
50
+
51
+ @dataclass
52
+ class Blob:
53
+ """A Javascript Blob class type.
54
+
55
+ Attributes:
56
+ uuid: the UUID of the Blob.
57
+ type: the type of the Blob.
58
+ size: the size of the Blob.
59
+ """
60
+ uuid: str
61
+ type: str
62
+ size: int
63
+
64
+
65
+ @dataclass
66
+ class BlobIndex(BaseIndex):
67
+ """A Javascript BlobIndex class type."""
68
+
69
+
70
+ @dataclass
71
+ class CryptoKey:
72
+ """A Javascript CryptoKey class type.
73
+
74
+ Attributes:
75
+ algorithm: the CryptoKey algorithm.
76
+ key_type: the CryptoKey type.
77
+ extractable: True if the CryptoKey is extractable.
78
+ usages: the CryptoKey usage.
79
+ key_data: the raw key data.
80
+ """
81
+ algorithm_parameters: dict[str, Any]
82
+ key_type: Union[
83
+ definitions.WebCryptoKeyType, definitions.AsymmetricCryptoKeyType]
84
+ extractable: bool
85
+ usages: definitions.CryptoKeyUsage
86
+ key_data: bytes
87
+
88
+
89
+ @dataclass
90
+ class DOMException:
91
+ """A Javascript DOMException.
92
+
93
+ Attributes:
94
+ name: the name.
95
+ message: the message.
96
+ stack_unused: the stack unused.
97
+ """
98
+ name: str
99
+ message: str
100
+ stack_unused: str
101
+
102
+
103
+ @dataclass
104
+ class DOMFileSystem:
105
+ """A Javascript DOMFileSystem.
106
+
107
+ Attributes:
108
+ raw_type: the raw type.
109
+ name: the name.
110
+ root_url: the root URL.
111
+ """
112
+ raw_type: int
113
+ name: str
114
+ root_url: str
115
+
116
+
117
+ @dataclass
118
+ class DOMMatrix2D:
119
+ """A Javascript DOMMatrix2D.
120
+
121
+ Attributes:
122
+ values: the values.
123
+ """
124
+ values: list[float]
125
+
126
+
127
+ @dataclass
128
+ class DOMMatrix2DReadOnly(DOMMatrix2D):
129
+ """A Javascript Read-Only DOMMatrix2D."""
130
+
131
+
132
+ @dataclass
133
+ class DOMMatrix:
134
+ """A Javascript DOMMatrix.
135
+
136
+ Attributes:
137
+ values: the values.
138
+ """
139
+ values: list[float]
140
+
141
+
142
+ @dataclass
143
+ class DOMMatrixReadOnly(DOMMatrix):
144
+ """A Javascript Read-Only DOMMatrix."""
145
+
146
+
147
+ @dataclass
148
+ class DOMPoint:
149
+ """A Javascript DOMPoint.
150
+
151
+ Attributes:
152
+ x: the X coordinate.
153
+ y: the Y coordinate.
154
+ z: the Z coordinate.
155
+ w: the W coordinate.
156
+ """
157
+ x: float
158
+ y: float
159
+ z: float
160
+ w: float
161
+
162
+
163
+ @dataclass
164
+ class DOMPointReadOnly(DOMPoint):
165
+ """A Javascript Read-Only DOMPoint."""
166
+
167
+
168
+ @dataclass
169
+ class DOMQuad:
170
+ """A Javascript DOMQuad.
171
+
172
+ Attributes:
173
+ p1: the first point.
174
+ p2: the second point.
175
+ p3: the third point.
176
+ p4: the fourth point.
177
+ """
178
+ p1: DOMPoint
179
+ p2: DOMPoint
180
+ p3: DOMPoint
181
+ p4: DOMPoint
182
+
183
+
184
+ @dataclass
185
+ class DOMRect:
186
+ """A Javascript DOMRect.
187
+
188
+ Attributes:
189
+ x: the X coordinate.
190
+ y: the Y coordinate.
191
+ width: the width.
192
+ height: the height.
193
+ """
194
+ x: float
195
+ y: float
196
+ width: float
197
+ height: float
198
+
199
+
200
+ @dataclass
201
+ class DOMRectReadOnly(DOMRect):
202
+ """A Javascript Read-only DOMRect."""
203
+
204
+
205
+ @dataclass
206
+ class EncodedAudioChunk(BaseIndex):
207
+ """A Javascript EncodedAudioChunk."""
208
+
209
+
210
+ @dataclass
211
+ class EncodedVideoChunk(BaseIndex):
212
+ """A Javascript EncodedVideoChunk."""
213
+
214
+
215
+ @dataclass
216
+ class File:
217
+ """A Javascript File.
218
+
219
+ Attributes:
220
+ path: the file path.
221
+ name: the file name.
222
+ relative_path: the file relative path.
223
+ uuid: the file UUID.
224
+ type: the file type.
225
+ has_snapshot: True if the file has a snapshot.
226
+ size: the file size.
227
+ last_modified_ms: the file last modified in milliseconds.
228
+ is_user_visible: True if the file is user visible.
229
+ """
230
+ path: str
231
+ name: Optional[str]
232
+ relative_path: Optional[str]
233
+ uuid: str
234
+ type: str
235
+ has_snapshot: int
236
+ size: Optional[int]
237
+ last_modified_ms: Optional[float]
238
+ is_user_visible: int
239
+
240
+
241
+ @dataclass
242
+ class FileIndex(BaseIndex):
243
+ """A Javascript FileIndex."""
244
+
245
+
246
+ @dataclass
247
+ class FileList:
248
+ """A Javascript FileList.
249
+
250
+ Attributes:
251
+ files: the list of files.
252
+ """
253
+ files: list[File]
254
+
255
+
256
+ @dataclass
257
+ class FileListIndex:
258
+ """A Javascript FileListIndex.
259
+
260
+ Attributes:
261
+ file_indexes: the list of file indexes.
262
+ """
263
+ file_indexes: list[FileIndex]
264
+
265
+
266
+ @dataclass
267
+ class FileSystemHandle:
268
+ """A Javascript FileSystemHandle.
269
+
270
+ Attributes:
271
+ name: the file system handle name.
272
+ token_index: the file system token index.
273
+ """
274
+ name: str
275
+ token_index: int
276
+
277
+
278
+ @dataclass
279
+ class ImageBitmapTransfer(BaseIndex):
280
+ """A Javascript ImageBitmapTransfer."""
281
+
282
+
283
+ @dataclass
284
+ class MediaSourceHandle(BaseIndex):
285
+ """A Javascript MediaSourceHandle."""
286
+
287
+
288
+ @dataclass
289
+ class MessagePort(BaseIndex):
290
+ """A Javascript MessagePort."""
291
+
292
+
293
+ @dataclass
294
+ class MojoHandle(BaseIndex):
295
+ """A Javascript MojoHandle."""
296
+
297
+
298
+ @dataclass
299
+ class ReadableStreamTransfer(BaseIndex):
300
+ """A Javascript ReadableStreamTransfer."""
301
+
302
+
303
+ @dataclass
304
+ class RTCEncodedAudioFrame(BaseIndex):
305
+ """A Javascript RTCEncodedAudioFrame."""
306
+
307
+
308
+ @dataclass
309
+ class RTCEncodedVideoFrame(BaseIndex):
310
+ """A Javascript RTCEncodedVideoFrame."""
311
+
312
+
313
+ @dataclass
314
+ class WriteableStreamTransfer(BaseIndex):
315
+ """A Javascript WriteableStreamTransfer."""
316
+
317
+
318
+ @dataclass
319
+ class TransformStreamTransfer(BaseIndex):
320
+ """A Javascript TransformStreamTransfer."""
321
+
322
+
323
+ @dataclass
324
+ class OffscreenCanvasTransfer:
325
+ """A Javascript Offscreen Canvas Transfer."""
326
+ width: int
327
+ height: int
328
+ canvas_id: int
329
+ client_id: int
330
+ sink_id: int
331
+ filter_quality: int
332
+
333
+
334
+ @dataclass
335
+ class UnguessableToken:
336
+ """A Javascript Unguessable Token.
337
+
338
+ Attributes:
339
+ high: the high part.
340
+ low: the low part.
341
+ """
342
+ high: int
343
+ low: int
344
+
345
+
346
+ @dataclass
347
+ class VideoFrame(BaseIndex):
348
+ """A Javascript VideoFrame."""
349
+
24
350
 
25
351
  class V8ScriptValueDecoder:
26
352
  """A Blink V8 Serialized Script Value (SSV) decoder.
@@ -40,6 +366,8 @@ class V8ScriptValueDecoder:
40
366
  self.deserializer = None
41
367
  self.raw_data = raw_data
42
368
  self.version = 0
369
+ self.trailer_offset = None
370
+ self.trailer_size = None
43
371
 
44
372
  def _ReadVersionEnvelope(self) -> int:
45
373
  """Reads the Blink version envelope.
@@ -52,42 +380,600 @@ class V8ScriptValueDecoder:
52
380
  return 0
53
381
 
54
382
  decoder = utils.StreamDecoder(io.BytesIO(self.raw_data))
55
- _, tag_value = decoder.DecodeUint8()
56
- tag = definitions.BlinkSerializationTag(tag_value)
383
+ _, tag = decoder.DecodeUint8()
57
384
  if tag != definitions.BlinkSerializationTag.VERSION:
58
385
  return 0
59
386
 
60
- _, version = decoder.DecodeUint32Varint()
61
- if version < self._MIN_VERSION_FOR_SEPARATE_ENVELOPE:
387
+ _, self.version = decoder.DecodeUint32Varint()
388
+ if self.version < self._MIN_VERSION_FOR_SEPARATE_ENVELOPE:
62
389
  return 0
63
390
 
64
391
  consumed_bytes = decoder.stream.tell()
65
392
 
66
- if version >= self._MIN_WIRE_FORMAT_VERSION:
393
+ if self.version >= self._MIN_WIRE_FORMAT_VERSION:
394
+ _, trailer_offset_tag = decoder.DecodeUint8()
395
+ if (trailer_offset_tag !=
396
+ definitions.BlinkSerializationTag.TRAILER_OFFSET):
397
+ raise errors.ParserError('Trailer offset not found')
398
+ _, self.trailer_offset = decoder.DecodeInt(
399
+ byte_count=8, byte_order='big', signed=False)
400
+ _, self.trailer_size = decoder.DecodeInt(
401
+ byte_count=4, byte_order='big', signed=False)
67
402
  trailer_offset_data_size = 1 + 8 + 4 # 1 + sizeof(uint64) + sizeof(uint32)
68
403
  consumed_bytes += trailer_offset_data_size
69
404
  if consumed_bytes >= len(self.raw_data):
70
405
  return 0
71
406
  return consumed_bytes
72
407
 
408
+ def _ReadAESKey(self) -> tuple[definitions.WebCryptoKeyType, dict[str, Any]]:
409
+ """Reads an AES CryptoKey.
410
+
411
+ Returns:
412
+ The AES key algorithm parameters
413
+ """
414
+ _, raw_id = self.deserializer.decoder.DecodeUint32Varint()
415
+ crypto_key_algorithm_id = definitions.CryptoKeyAlgorithm(raw_id)
416
+
417
+ _, length_bytes = self.deserializer.decoder.DecodeUint32Varint()
418
+
419
+ algorithm_parameters = {
420
+ 'id': crypto_key_algorithm_id,
421
+ 'length_bits': length_bytes*8
422
+ }
423
+
424
+ return definitions.WebCryptoKeyType.SECRET, algorithm_parameters
425
+
426
+ def _ReadHMACKey(self) -> tuple[definitions.WebCryptoKeyType, dict[str, Any]]:
427
+ """Reads a HMAC CryptoKey.
428
+
429
+ Returns:
430
+ The HMAC key algorithm parameters
431
+ """
432
+ _, length_bytes = self.deserializer.decoder.DecodeUint32Varint()
433
+ _, raw_hash = self.deserializer.decoder.DecodeUint32Varint()
434
+ crypto_key_algorithm = definitions.CryptoKeyAlgorithm(raw_hash)
435
+
436
+ algorithm_parameters = {
437
+ 'id': crypto_key_algorithm,
438
+ 'length_bits': length_bytes*8
439
+ }
440
+
441
+ return definitions.WebCryptoKeyType.SECRET, algorithm_parameters
442
+
443
+ def _ReadRSAHashedKey(
444
+ self
445
+ ) -> tuple[definitions.AsymmetricCryptoKeyType, dict[str, Any]]:
446
+ """Reads an RSA Hashed CryptoKey.
447
+
448
+ Returns:
449
+ The RSA Hashed key algorithm parameters
450
+ """
451
+ _, raw_id = self.deserializer.decoder.DecodeUint32Varint()
452
+ crypto_key_algorithm = definitions.CryptoKeyAlgorithm(raw_id)
453
+
454
+ _, raw_key_type = self.deserializer.decoder.DecodeUint32Varint()
455
+ key_type = definitions.AsymmetricCryptoKeyType(raw_key_type)
456
+
457
+ _, modulus_length_bits = self.deserializer.decoder.DecodeUint32Varint()
458
+ _, public_exponent_size = self.deserializer.decoder.DecodeUint32Varint()
459
+ _, public_exponent_bytes = self.deserializer.decoder.ReadBytes(
460
+ count=public_exponent_size)
461
+
462
+ _, raw_hash = self.deserializer.decoder.DecodeUint32Varint()
463
+ hash_algorithm = definitions.CryptoKeyAlgorithm(raw_hash)
464
+
465
+ algorithm_parameters = {
466
+ 'id': crypto_key_algorithm,
467
+ 'modulus_length_bits': modulus_length_bits,
468
+ 'public_exponent_size': public_exponent_size,
469
+ 'public_exponent_bytes': public_exponent_bytes,
470
+ 'hash': hash_algorithm
471
+ }
472
+
473
+ return key_type, algorithm_parameters
474
+
475
+ def _ReadECKey(
476
+ self
477
+ ) -> tuple[definitions.AsymmetricCryptoKeyType, dict[str, Any]]:
478
+ """Reads an EC Key parameters from the current decoder position.
479
+
480
+ Returns:
481
+ The EC Key algorithm parameters.
482
+ """
483
+ _, raw_id = self.deserializer.decoder.DecodeUint32Varint()
484
+ crypto_key_algorithm = definitions.CryptoKeyAlgorithm(raw_id)
485
+
486
+ _, raw_key_type = self.deserializer.decoder.DecodeUint32Varint()
487
+ key_type = definitions.AsymmetricCryptoKeyType(raw_key_type)
488
+
489
+ _, raw_named_curve = self.deserializer.decoder.DecodeUint32Varint()
490
+ named_curve_type = definitions.NamedCurve(raw_named_curve)
491
+
492
+ algorithm_parameters = {
493
+ 'crypto_key_algorithm': crypto_key_algorithm,
494
+ 'named_curve_type': named_curve_type
495
+ }
496
+
497
+ return key_type, algorithm_parameters
498
+
499
+ def _ReadED25519Key(
500
+ self
501
+ ) -> tuple[definitions.AsymmetricCryptoKeyType, dict[str, Any]]:
502
+ """Reads a ED25519 CryptoKey from the current decoder position.
503
+
504
+ Returns:
505
+ The ED25519 key algorithm parameters.
506
+ """
507
+ _, raw_id = self.deserializer.decoder.DecodeUint32Varint()
508
+ crypto_key_algorithm = definitions.CryptoKeyAlgorithm(raw_id)
509
+
510
+ _, raw_key_type = self.deserializer.decoder.DecodeUint32Varint()
511
+ key_type = definitions.AsymmetricCryptoKeyType(
512
+ raw_key_type)
513
+
514
+ algorithm_parameters = {
515
+ 'crypto_key_algorithm': crypto_key_algorithm
516
+ }
517
+
518
+ return key_type, algorithm_parameters
519
+
520
+ def ReadNoParamsKey(
521
+ self
522
+ ) -> tuple[definitions.WebCryptoKeyType, dict[str, Any]]:
523
+ """Reads a No Params CryptoKey from the current decoder position.
524
+
525
+ Returns:
526
+ The No Parameters key algorithm parameters.
527
+ """
528
+ _, raw_id = self.deserializer.decoder.DecodeUint32Varint()
529
+ crypto_key_algorithm = definitions.CryptoKeyAlgorithm(raw_id)
530
+
531
+ algorithm_parameters = {
532
+ 'crypto_key_algorithm': crypto_key_algorithm
533
+ }
534
+
535
+ return definitions.WebCryptoKeyType.SECRET, algorithm_parameters
536
+
537
+ def _ReadBlob(self) -> Optional[Blob]:
538
+ """Reads a Blob from the current position.
539
+
540
+ Returns:
541
+ A Blob if the version is less then 3, None otherwise.
542
+ """
543
+ if self.version and self.version < 3:
544
+ return None
545
+
546
+ uuid = self.deserializer.ReadUTF8String()
547
+ blob_type = self.deserializer.ReadUTF8String()
548
+ _, size = self.deserializer.decoder.DecodeUint64Varint()
549
+ return Blob(uuid=uuid, type=blob_type, size=size)
550
+
551
+ def _ReadBlobIndex(self) -> Optional[BlobIndex]:
552
+ """Reads a BlobIndex from the current decoder position.
553
+
554
+ Returns:
555
+ A parsed BlobIndex if the version is greater than 6, None otherwise.
556
+ """
557
+ if self.version < 6:
558
+ return None
559
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
560
+ return BlobIndex(index=index)
561
+
562
+ def _ReadFile(self) -> Optional[File]:
563
+ """Reads a Javascript File from the current position.
564
+
565
+ Returns:
566
+ A File instance, None if the version is less than 3.
567
+ """
568
+ if self.version < 3:
569
+ return None
570
+
571
+ path = self.deserializer.ReadUTF8String()
572
+ name = self.deserializer.ReadUTF8String() if self.version >= 4 else None
573
+ relative_path = (
574
+ self.deserializer.ReadUTF8String() if self.version >= 4 else None)
575
+ uuid = self.deserializer.ReadUTF8String()
576
+ file_type = self.deserializer.ReadUTF8String()
577
+ has_snapshot = (
578
+ self.deserializer.decoder.DecodeUint32Varint()[1]
579
+ if self.version >= 4 else 0)
580
+
581
+ if has_snapshot:
582
+ _, size = self.deserializer.decoder.DecodeUint64Varint()
583
+ _, last_modified_ms = self.deserializer.decoder.DecodeDouble()
584
+ if self.version < 8:
585
+ last_modified_ms *= _MS_PER_SECOND
586
+ else:
587
+ size = None
588
+ last_modified_ms = None
589
+
590
+ is_user_visible = (
591
+ self.deserializer.decoder.DecodeUint32Varint()[1]
592
+ if self.version >= 7 else 1)
593
+
594
+ return File(
595
+ path=path,
596
+ name=name,
597
+ relative_path=relative_path,
598
+ uuid=uuid,
599
+ type=file_type,
600
+ has_snapshot=has_snapshot,
601
+ size=size,
602
+ last_modified_ms=last_modified_ms,
603
+ is_user_visible=is_user_visible)
604
+
605
+ def _ReadFileIndex(self) -> Optional[FileIndex]:
606
+ """Reads a FileIndex from the current position.
607
+
608
+ Returns:
609
+ A FileIndex, or None if the version is less than 6.
610
+ """
611
+ if self.version < 6:
612
+ return None
613
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
614
+ return FileIndex(index=index)
615
+
616
+ def _ReadFileList(self) -> Optional[FileList]:
617
+ """Reads a Javascript FileList from the current position.
618
+
619
+ Returns:
620
+ A FileList, or None if a File could not be read.
621
+ """
622
+ _, length = self.deserializer.decoder.DecodeUint32Varint()
623
+ files = []
624
+ for _ in range(length):
625
+ decoded_file = self._ReadFile()
626
+ if not decoded_file:
627
+ return None
628
+ files.append(decoded_file)
629
+ return FileList(files=files)
630
+
631
+ def _ReadFileListIndex(self) -> Optional[FileListIndex]:
632
+ """Reads a Javascript FileListIndex from the current position.
633
+
634
+ Returns:
635
+ A FileListIndex, or None if a FileIndex could not be read.
636
+ """
637
+ _, length = self.deserializer.decoder.DecodeUint32Varint()
638
+ file_indexes = []
639
+ for _ in range(length):
640
+ decoded_file_index = self._ReadFileIndex()
641
+ if not decoded_file_index:
642
+ return None
643
+ file_indexes.append(decoded_file_index)
644
+ return FileListIndex(file_indexes=file_indexes)
645
+
646
+ def _ReadImageBitmap(self):
647
+ """Reads an ImageBitmap."""
648
+ raise NotImplementedError('V8ScriptValueDecoder._ReadImageBitmap')
649
+
650
+ def _ReadImageBitmapTransfer(self) -> ImageBitmapTransfer:
651
+ """Reads an ImageBitmapTransfer."""
652
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
653
+ return ImageBitmapTransfer(index=index)
654
+
655
+ def _ReadImageData(self):
656
+ """Reads an ImageData from the current position."""
657
+ raise NotImplementedError('V8ScriptValueDecoder._ReadImageData')
658
+
659
+ def _ReadDOMPoint(self) -> DOMPoint:
660
+ """Reads a DOMPoint from the current position."""
661
+ _, x = self.deserializer.decoder.DecodeDouble()
662
+ _, y = self.deserializer.decoder.DecodeDouble()
663
+ _, z = self.deserializer.decoder.DecodeDouble()
664
+ _, w = self.deserializer.decoder.DecodeDouble()
665
+ return DOMPoint(x=x, y=y, z=z, w=w)
666
+
667
+ def _ReadDOMPointReadOnly(self) -> DOMPointReadOnly:
668
+ """Reads a DOMPointReadOnly from the current position."""
669
+ _, x = self.deserializer.decoder.DecodeDouble()
670
+ _, y = self.deserializer.decoder.DecodeDouble()
671
+ _, z = self.deserializer.decoder.DecodeDouble()
672
+ _, w = self.deserializer.decoder.DecodeDouble()
673
+ return DOMPointReadOnly(x=x, y=y, z=z, w=w)
674
+
675
+ def _ReadDOMRect(self) -> DOMRect:
676
+ """Reads a DOMRect from the current position."""
677
+ _, x = self.deserializer.decoder.DecodeDouble()
678
+ _, y = self.deserializer.decoder.DecodeDouble()
679
+ _, width = self.deserializer.decoder.DecodeDouble()
680
+ _, height = self.deserializer.decoder.DecodeDouble()
681
+ return DOMRect(x=x, y=y, width=width, height=height)
682
+
683
+ def _ReadDOMRectReadOnly(self) -> DOMRectReadOnly:
684
+ """Reads a DOMRectReadOnly from the current position."""
685
+ _, x = self.deserializer.decoder.DecodeDouble()
686
+ _, y = self.deserializer.decoder.DecodeDouble()
687
+ _, width = self.deserializer.decoder.DecodeDouble()
688
+ _, height = self.deserializer.decoder.DecodeDouble()
689
+ return DOMRectReadOnly(x=x, y=y, width=width, height=height)
690
+
691
+ def _ReadDOMQuad(self) -> DOMQuad:
692
+ """Reads a DOMQuad from the current position."""
693
+ p1 = self._ReadDOMPoint()
694
+ p2 = self._ReadDOMPoint()
695
+ p3 = self._ReadDOMPoint()
696
+ p4 = self._ReadDOMPoint()
697
+ return DOMQuad(p1=p1, p2=p2, p3=p3, p4=p4)
698
+
699
+ def _ReadDOMMatrix2D(self) -> DOMMatrix2D:
700
+ """Reads a Javascript DOMMatrix2D from the current position."""
701
+ values = [self.deserializer.decoder.DecodeDouble()[1] for _ in range(6)]
702
+ return DOMMatrix2D(values=values)
703
+
704
+ def _ReadDOMMatrix2DReadOnly(self) -> DOMMatrix2DReadOnly:
705
+ """Reads a Javascript Read-Only DOMMatrix2D from the current position."""
706
+ values = [self.deserializer.decoder.DecodeDouble()[1] for _ in range(6)]
707
+ return DOMMatrix2DReadOnly(values=values)
708
+
709
+ def _ReadDOMMatrix(self) -> DOMMatrix:
710
+ """Reads a Javascript DOMMatrix from the current position."""
711
+ values = [self.deserializer.decoder.DecodeDouble()[1] for _ in range(16)]
712
+ return DOMMatrix(values=values)
713
+
714
+ def _ReadDOMMatrixReadOnly(self) -> DOMMatrixReadOnly:
715
+ """Reads a Javascript Read-Only DOMMatrix from the current position."""
716
+ values = [self.deserializer.decoder.DecodeDouble()[1] for _ in range(16)]
717
+ return DOMMatrixReadOnly(values=values)
718
+
719
+ def _ReadMessagePort(self) -> MessagePort:
720
+ """Reads a MessagePort from the current position."""
721
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
722
+ return MessagePort(index=index)
723
+
724
+ def _ReadMojoHandle(self) -> MojoHandle:
725
+ """Reads a MojoHandle from the current position."""
726
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
727
+ return MojoHandle(index=index)
728
+
729
+ def _ReadOffscreenCanvasTransfer(self):
730
+ """Reads a Offscreen Canvas Transfer from the current position."""
731
+ _, width = self.deserializer.decoder.DecodeUint32Varint()
732
+ _, height = self.deserializer.decoder.DecodeUint32Varint()
733
+ _, canvas_id = self.deserializer.decoder.DecodeUint32Varint()
734
+ _, client_id = self.deserializer.decoder.DecodeUint32Varint()
735
+ _, sink_id = self.deserializer.decoder.DecodeUint32Varint()
736
+ _, filter_quality = self.deserializer.decoder.DecodeUint32Varint()
737
+
738
+ return OffscreenCanvasTransfer(
739
+ width=width,
740
+ height=height,
741
+ canvas_id=canvas_id,
742
+ client_id=client_id,
743
+ sink_id=sink_id,
744
+ filter_quality=filter_quality)
745
+
746
+ def _ReadReadableStreamTransfer(self) -> ReadableStreamTransfer:
747
+ """Reads a Readable Stream Transfer from the current position."""
748
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
749
+ return ReadableStreamTransfer(index=index)
750
+
751
+ def _ReadWriteableStreamTransfer(self) -> WriteableStreamTransfer:
752
+ """Reads a Writeable Stream Transfer from the current position."""
753
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
754
+ return WriteableStreamTransfer(index=index)
755
+
756
+ def _ReadTransformStreamTransfer(self) -> TransformStreamTransfer:
757
+ """Reads a TransformStreamTransfer from the current position."""
758
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
759
+ return TransformStreamTransfer(index=index)
760
+
761
+ def _ReadDOMException(self) -> DOMException:
762
+ """Reads a DOMException from the current position."""
763
+ name = self.deserializer.ReadUTF8String()
764
+ message = self.deserializer.ReadUTF8String()
765
+ stack_unused = self.deserializer.ReadUTF8String()
766
+ return DOMException(name=name, message=message, stack_unused=stack_unused)
767
+
768
+ def _ReadRTCEncodedAudioFrame(self) -> RTCEncodedAudioFrame:
769
+ """Reads a RTC Encoded Audio Frame from the current position."""
770
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
771
+ return RTCEncodedAudioFrame(index=index)
772
+
773
+ def _ReadRTCEncodedVideoFrame(self) -> RTCEncodedVideoFrame:
774
+ """Reads a RTC Encoded Video Frame from the current position."""
775
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
776
+ return RTCEncodedVideoFrame(index=index)
777
+
778
+ def _ReadCryptoKey(self) -> CryptoKey:
779
+ """Reads a CryptoKey from the current position.
780
+
781
+ Returns:
782
+ A parsed CryptoKey.
783
+ """
784
+ _, raw_key_byte = self.deserializer.decoder.DecodeUint8()
785
+ key_byte = definitions.CryptoKeySubTag(raw_key_byte)
786
+ if key_byte == definitions.CryptoKeySubTag.AES_KEY:
787
+ key_type, algorithm_parameters = self._ReadAESKey()
788
+ elif key_byte == definitions.CryptoKeySubTag.HMAC_KEY:
789
+ key_type, algorithm_parameters = self._ReadHMACKey()
790
+ elif key_byte == definitions.CryptoKeySubTag.RSA_HASHED_KEY:
791
+ key_type, algorithm_parameters = self._ReadRSAHashedKey()
792
+ elif key_byte == definitions.CryptoKeySubTag.EC_KEY:
793
+ key_type, algorithm_parameters = self._ReadECKey()
794
+ elif key_byte == definitions.CryptoKeySubTag.ED25519_KEY:
795
+ key_type, algorithm_parameters = self._ReadED25519Key()
796
+ elif key_byte == definitions.CryptoKeySubTag.NO_PARAMS_KEY:
797
+ key_type, algorithm_parameters = self.ReadNoParamsKey()
798
+
799
+ _, raw_usages = self.deserializer.decoder.DecodeUint32Varint()
800
+ usages = definitions.CryptoKeyUsage(raw_usages)
801
+
802
+ extractable = bool(raw_usages & definitions.CryptoKeyUsage.EXTRACTABLE)
803
+ _, key_data_length = self.deserializer.decoder.DecodeUint32Varint()
804
+
805
+ _, key_data = self.deserializer.decoder.ReadBytes(count=key_data_length)
806
+
807
+ return CryptoKey(
808
+ key_type=key_type,
809
+ algorithm_parameters=algorithm_parameters,
810
+ extractable=extractable,
811
+ usages=usages,
812
+ key_data=key_data
813
+ )
814
+
815
+ def _ReadAudioData(self) -> AudioData:
816
+ """Reads an AudioData from the current position."""
817
+ _, audio_frame_index = self.deserializer.decoder.DecodeUint32Varint()
818
+ return AudioData(audio_frame_index=audio_frame_index)
819
+
820
+ def _ReadDomFileSystem(self) -> DOMFileSystem:
821
+ """Reads an DOMFileSystem from the current position."""
822
+ _, raw_type = self.deserializer.decoder.DecodeUint32Varint()
823
+ name = self.deserializer.ReadUTF8String()
824
+ root_url = self.deserializer.ReadUTF8String()
825
+ return DOMFileSystem(raw_type=raw_type, name=name, root_url=root_url)
826
+
827
+ def _ReadFileSystemFileHandle(self) -> FileSystemHandle:
828
+ """Reads a FileSystemHandle from the current position."""
829
+ name = self.deserializer.ReadUTF8String()
830
+ _, token_index = self.deserializer.decoder.DecodeUint32Varint()
831
+ return FileSystemHandle(name=name, token_index=token_index)
832
+
833
+ def _ReadVideoFrame(self) -> VideoFrame:
834
+ """Reads the video frame from the current position."""
835
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
836
+ return VideoFrame(index=index)
837
+
838
+ def _ReadEncodedAudioChunk(self) -> EncodedAudioChunk:
839
+ """Reads the encoded audio chunk from the current position."""
840
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
841
+ return EncodedAudioChunk(index=index)
842
+
843
+ def _ReadEncodedVideoChunk(self) -> EncodedVideoChunk:
844
+ """Reads the encoded video chunk from the current position."""
845
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
846
+ return EncodedVideoChunk(index=index)
847
+
848
+ def _ReadMediaStreamTrack(self):
849
+ """Reads the media stream track from the current position."""
850
+ raise NotImplementedError('V8ScriptValueDecoder._ReadMediaStreamTrack')
851
+
852
+ def _ReadCropTarget(self):
853
+ """Reads the crop target from the current position."""
854
+ raise NotImplementedError('V8ScriptValueDecoder._ReadCropTarget')
855
+
856
+ def _ReadRestrictionTarget(self):
857
+ """Reads the restriction target from the current position."""
858
+ raise NotImplementedError('V8ScriptValueDecoder._ReadRestrictionTarget')
859
+
860
+ def _ReadMediaSourceHandle(self) -> MediaSourceHandle:
861
+ """Reads the media source handle from the current position."""
862
+ _, index = self.deserializer.decoder.DecodeUint32Varint()
863
+ return MediaSourceHandle(index=index)
864
+
865
+ def _ReadFencedFrameConfig(self):
866
+ """Reads the fenced frame target from the current position."""
867
+ raise NotImplementedError('V8ScriptValueDecoder._ReadFencedFrameConfig')
868
+
73
869
  def ReadTag(self) -> definitions.BlinkSerializationTag:
74
- """Reads a blink serialization tag.
870
+ """Reads a blink serialization tag from the current position.
75
871
 
76
872
  Returns:
77
873
  The blink serialization tag.
874
+
875
+ Raises:
876
+ ParserError: if an invalid blink tag is read.
78
877
  """
79
878
  _, tag_value = self.deserializer.decoder.DecodeUint8()
80
- return definitions.BlinkSerializationTag(tag_value)
879
+ try:
880
+ return definitions.BlinkSerializationTag(tag_value)
881
+ except ValueError as err:
882
+ offset = self.deserializer.decoder.stream.tell()
883
+ raise errors.ParserError(
884
+ f'Invalid blink tag encountered at offset {offset}') from err
81
885
 
82
886
  def ReadHostObject(self) -> Any:
83
- """Reads a host DOM object.
887
+ """Reads a host object from the current position.
84
888
 
85
- Raises:
86
- NotImplementedError: when called.
889
+ Returns:
890
+ The Host Object.
87
891
  """
88
892
  tag = self.ReadTag()
89
- raise NotImplementedError(
90
- f'V8ScriptValueDecoder.ReadHostObject - {tag.name}')
893
+ dom_object = None
894
+
895
+ # V8ScriptValueDeserializer
896
+ if tag == definitions.BlinkSerializationTag.BLOB:
897
+ dom_object = self._ReadBlob()
898
+ elif tag == definitions.BlinkSerializationTag.BLOB_INDEX:
899
+ dom_object = self._ReadBlobIndex()
900
+ elif tag == definitions.BlinkSerializationTag.FILE:
901
+ dom_object = self._ReadFile()
902
+ elif tag == definitions.BlinkSerializationTag.FILE_INDEX:
903
+ dom_object = self._ReadFileIndex()
904
+ elif tag == definitions.BlinkSerializationTag.FILE_LIST:
905
+ dom_object = self._ReadFileList()
906
+ elif tag == definitions.BlinkSerializationTag.FILE_LIST_INDEX:
907
+ dom_object = self._ReadFileListIndex()
908
+ elif tag == definitions.BlinkSerializationTag.IMAGE_BITMAP:
909
+ dom_object = self._ReadImageBitmap()
910
+ elif tag == definitions.BlinkSerializationTag.IMAGE_BITMAP_TRANSFER:
911
+ dom_object = self._ReadImageBitmapTransfer()
912
+ elif tag == definitions.BlinkSerializationTag.IMAGE_DATA:
913
+ dom_object = self._ReadImageData()
914
+ elif tag == definitions.BlinkSerializationTag.DOM_POINT:
915
+ dom_object = self._ReadDOMPoint()
916
+ elif tag == definitions.BlinkSerializationTag.DOM_POINT_READ_ONLY:
917
+ dom_object = self._ReadDOMPointReadOnly()
918
+ elif tag == definitions.BlinkSerializationTag.DOM_RECT:
919
+ dom_object = self._ReadDOMRect()
920
+ elif tag == definitions.BlinkSerializationTag.DOM_RECT_READ_ONLY:
921
+ dom_object = self._ReadDOMRectReadOnly()
922
+ elif tag == definitions.BlinkSerializationTag.DOM_QUAD:
923
+ dom_object = self._ReadDOMQuad()
924
+ elif tag == definitions.BlinkSerializationTag.DOM_MATRIX2D:
925
+ dom_object = self._ReadDOMMatrix2D()
926
+ elif tag == definitions.BlinkSerializationTag.DOM_MATRIX2D_READ_ONLY:
927
+ dom_object = self._ReadDOMMatrix2DReadOnly()
928
+ elif tag == definitions.BlinkSerializationTag.DOM_MATRIX:
929
+ dom_object = self._ReadDOMMatrix()
930
+ elif tag == definitions.BlinkSerializationTag.DOM_MATRIX_READ_ONLY:
931
+ dom_object = self._ReadDOMMatrixReadOnly()
932
+ elif tag == definitions.BlinkSerializationTag.MESSAGE_PORT:
933
+ dom_object = self._ReadMessagePort()
934
+ elif tag == definitions.BlinkSerializationTag.MOJO_HANDLE:
935
+ dom_object = self._ReadMojoHandle()
936
+ elif tag == definitions.BlinkSerializationTag.OFFSCREEN_CANVAS_TRANSFER:
937
+ dom_object = self._ReadOffscreenCanvasTransfer()
938
+ elif tag == definitions.BlinkSerializationTag.READABLE_STREAM_TRANSFER:
939
+ dom_object = self._ReadReadableStreamTransfer()
940
+ elif tag == definitions.BlinkSerializationTag.WRITABLE_STREAM_TRANSFER:
941
+ dom_object = self._ReadWriteableStreamTransfer()
942
+ elif tag == definitions.BlinkSerializationTag.TRANSFORM_STREAM_TRANSFER:
943
+ dom_object = self._ReadTransformStreamTransfer()
944
+ elif tag == definitions.BlinkSerializationTag.DOM_EXCEPTION:
945
+ dom_object = self._ReadDOMException()
946
+
947
+ # V8ScriptValueDeserializerForModules
948
+ elif tag == definitions.BlinkSerializationTag.CRYPTO_KEY:
949
+ dom_object = self._ReadCryptoKey()
950
+ elif tag == definitions.BlinkSerializationTag.DOM_FILE_SYSTEM:
951
+ dom_object = self._ReadDomFileSystem()
952
+ elif tag == definitions.BlinkSerializationTag.FILE_SYSTEM_FILE_HANDLE:
953
+ dom_object = self._ReadFileSystemFileHandle()
954
+ elif tag == definitions.BlinkSerializationTag.RTC_ENCODED_AUDIO_FRAME:
955
+ dom_object = self._ReadRTCEncodedAudioFrame()
956
+ elif tag == definitions.BlinkSerializationTag.RTC_ENCODED_VIDEO_FRAME:
957
+ dom_object = self._ReadRTCEncodedVideoFrame()
958
+ elif tag == definitions.BlinkSerializationTag.AUDIO_DATA:
959
+ dom_object = self._ReadAudioData()
960
+ elif tag == definitions.BlinkSerializationTag.VIDEO_FRAME:
961
+ dom_object = self._ReadVideoFrame()
962
+ elif tag == definitions.BlinkSerializationTag.ENCODED_AUDIO_CHUNK:
963
+ dom_object = self._ReadEncodedAudioChunk()
964
+ elif tag == definitions.BlinkSerializationTag.ENCODED_VIDEO_CHUNK:
965
+ dom_object = self._ReadEncodedVideoChunk()
966
+ elif tag == definitions.BlinkSerializationTag.MEDIA_STREAM_TRACK:
967
+ dom_object = self._ReadMediaStreamTrack()
968
+ elif tag == definitions.BlinkSerializationTag.CROP_TARGET:
969
+ dom_object = self._ReadCropTarget()
970
+ elif tag == definitions.BlinkSerializationTag.RESTRICTION_TARGET:
971
+ dom_object = self._ReadRestrictionTarget()
972
+ elif tag == definitions.BlinkSerializationTag.MEDIA_SOURCE_HANDLE:
973
+ dom_object = self._ReadMediaSourceHandle()
974
+ elif tag == definitions.BlinkSerializationTag.FENCED_FRAME_CONFIG:
975
+ dom_object = self._ReadFencedFrameConfig()
976
+ return dom_object
91
977
 
92
978
  def Deserialize(self) -> Any:
93
979
  """Deserializes a Blink SSV.
@@ -97,13 +983,24 @@ class V8ScriptValueDecoder:
97
983
 
98
984
  Returns:
99
985
  The deserialized script value.
986
+
987
+ Raises:
988
+ ParserError: if an unsupported header version was found.
100
989
  """
101
990
  version_envelope_size = self._ReadVersionEnvelope()
102
- self.deserializer = v8.ValueDeserializer(
103
- io.BytesIO(self.raw_data[version_envelope_size:]), delegate=self)
104
- v8_version = self.deserializer.ReadHeader()
105
- if not self.version:
106
- self.version = v8_version
991
+ if self.trailer_size:
992
+ self.deserializer = v8.ValueDeserializer(
993
+ io.BytesIO(
994
+ self.raw_data[version_envelope_size:self.trailer_offset]),
995
+ delegate=self)
996
+ else:
997
+ self.deserializer = v8.ValueDeserializer(
998
+ io.BytesIO(
999
+ self.raw_data[version_envelope_size:]),
1000
+ delegate=self)
1001
+ is_supported = self.deserializer.ReadHeader()
1002
+ if not is_supported:
1003
+ raise errors.ParserError('Unsupported header')
107
1004
  return self.deserializer.ReadValue()
108
1005
 
109
1006
  @classmethod