summaryrefslogtreecommitdiffstats
path: root/dom/media/test/test_imagecapture.html
blob: d61dd358bb870b62159b0f2e73880c2b1f01ced9 (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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1041393
-->
<head>
  <meta charset="utf-8">
  <title>ImageCapture tests</title>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <script type="text/javascript" src="gUM_support.js"></script>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1041393">ImageCapture tests</a>
<script type="application/javascript">

// Check if the callback returns even no JS reference on it.
async function gcTest(track) {
  const repeat = 100;
  const promises = [];
  for (let i = 0; i < repeat; ++i) {
    const imageCapture = new ImageCapture(track);
    promises.push(new Promise((resolve, reject) => {
      imageCapture.onphoto = resolve;
      imageCapture.onerror = () =>
        reject(new Error(`takePhoto gcTest failure for capture ${i}`));
    }));
    imageCapture.takePhoto();
  }
  info("Call gc ");
  SpecialPowers.gc();
  await Promise.all(promises);
}

// Continue calling takePhoto() in rapid succession.
async function rapidTest(track) {
  const repeat = 100;
  const imageCapture = new ImageCapture(track);
  // "error" can fire synchronously in `takePhoto`
  const errorPromise = new Promise(r => imageCapture.onerror = r);
  for (let i = 0; i < repeat; ++i) {
    imageCapture.takePhoto();
  }
  for (let i = 0; i < repeat; ++i) {
    await Promise.race([
      new Promise(r => imageCapture.onphoto = r),
      errorPromise.then(() => Promise.reject(new Error("Capture failed"))),
    ]);
  }
}

// Check if the blob is decodable.
async function blobTest(track) {
  const imageCapture = new ImageCapture(track);
  // "error" can fire synchronously in `takePhoto`
  const errorPromise = new Promise(r => imageCapture.onerror = r);
  imageCapture.takePhoto();
  const blob = await Promise.race([
    new Promise(r => imageCapture.onphoto = r),
    errorPromise.then(() => Promise.reject(new Error("Capture failed"))),
  ]);

  const img = new Image();
  img.src = URL.createObjectURL(blob.data);
  await new Promise((resolve, reject) => {
    img.onload = resolve;
    img.onerror = () => reject(new Error("Decode failed"));
  });
}

// It should return an error event after disabling video track.
async function trackTest(track) {
  const imageCapture = new ImageCapture(track);
  track.enabled = false;
  try {
    const errorPromise = new Promise(r => imageCapture.onerror = r);
    imageCapture.takePhoto();
    const error = await Promise.race([
      errorPromise,
      new Promise(r => imageCapture.onphoto = r).then(
        () => Promise.reject(new Error("Disabled video track should fail"))),
    ]);
    is(error.imageCaptureError.code, error.imageCaptureError.PHOTO_ERROR,
      "Expected error code")
  } finally {
    track.enabled = true;
  }
}

async function init() {
  // Use loopback camera if available, otherwise fake.
  // MediaTrackGraph will be the backend of ImageCapture.
  await setupGetUserMediaTestPrefs();
  let stream = await navigator.mediaDevices.getUserMedia({video: true});
  return stream.getVideoTracks()[0];
}

async function start() {
  try {
    const track = await init();
    info("ImageCapture track disable test.");
    await trackTest(track);
    info("ImageCapture blob test.");
    await blobTest(track);
    info("ImageCapture rapid takePhoto() test.");
    await rapidTest(track);
    info("ImageCapture multiple instances test.");
    await gcTest(track);
  } catch (e) {
    ok(false, "Unexpected error during test: " + e);
  } finally {
    SimpleTest.finish();
  }
}

SimpleTest.requestCompleteLog();
SimpleTest.waitForExplicitFinish();

SpecialPowers.pushPrefEnv({
  "set": [
    ["dom.imagecapture.enabled", true],
    ["media.navigator.permission.disabled", true],
  ],
}, start);
</script>
</pre>
</body>
</html>