summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/media-source/dedicated-worker/mediasource-worker-detach-element.js
blob: 54b1d815f2529932a153440db3cb3f1033fd84a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
// This is similar to mediasource-worker-play.js, except that the buffering is
// longer and done in tiny chunks to enable a better chance of the main thread
// detaching the element while interesting buffering work is still occurring. To
// assist the main thread understanding when the buffering has started already
// or has completed already, we also perform extra messaging.
importScripts("mediasource-worker-util.js");

onmessage = function(evt) {
  postMessage({ subject: messageSubject.ERROR, info: "No message expected by Worker" });
};

let util = new MediaSourceWorkerUtil();

let sentStartedBufferingMessage = false;

util.mediaSource.addEventListener("sourceopen", () => {
  let sourceBuffer;
  try {
    sourceBuffer = util.mediaSource.addSourceBuffer(util.mediaMetadata.type);
  }  catch(e) {
    // Detachment may have already begun, so allow exception here.
    // TODO(https://crbug.com/878133): Consider a distinct readyState for the case
    // where exception occurs due to "Worker MediaSource attachment is closing".
    // That would assist API users and narrow the exception handling here.
    return;
  }

  sourceBuffer.onerror = (err) => {
    postMessage({ subject: messageSubject.ERROR, info: err });
  };
  util.mediaLoadPromise.then(mediaData => bufferInto(sourceBuffer, mediaData, 100, 0),
                             err => { postMessage({ subject: messageSubject.ERROR, info: err }) } );
}, { once : true });

let handle = util.mediaSource.handle;

postMessage({ subject: messageSubject.HANDLE, info: handle }, { transfer: [handle] } );

// Append increasingly large pieces at a time, starting/continuing at |position|.
// This allows buffering the test media without timeout, but also with enough
// operations to gain coverage on detachment concurrency with append.
function bufferInto(sourceBuffer, mediaData, appendSize, position) {
  if (position >= mediaData.byteLength) {
    postMessage({ subject: messageSubject.FINISHED_BUFFERING });
    try {
      util.mediaSource.endOfStream();
    }  catch(e) {
      // Detachment may have already begun, so allow exception here.
      // TODO(https://crbug.com/878133): Consider a distinct readyState for the case
      // where exception occurs due to "Worker MediaSource attachment is closing".
      // That would assist API users and narrow the exception handling here.
      // FALL-THROUGH - return.
    }
    return;
  }

  var nextPosition = position + appendSize;
  const pieceToAppend = mediaData.slice(position, nextPosition);
  position = nextPosition;
  appendSize += 100;

  sourceBuffer.addEventListener("updateend", () => {
    if (!sentStartedBufferingMessage) {
      postMessage({ subject: messageSubject.STARTED_BUFFERING});
      sentStartedBufferingMessage = true;
    }
    bufferInto(sourceBuffer, mediaData, appendSize, position);
  }, { once : true });

  try {
    sourceBuffer.appendBuffer(pieceToAppend);
  }  catch(e) {
    // Detachment may have already begun, so allow exception here.
    // TODO(https://crbug.com/878133): Consider a distinct readyState for the case
    // where exception occurs due to "Worker MediaSource attachment is closing".
    // That would assist API users and narrow the exception handling here.
    // FALL-THROUGH - return.
  }
}