summaryrefslogtreecommitdiffstats
path: root/dom/media/test/test_eme_requestMediaKeySystemAccess_with_app_approval.html
blob: ceba459dae14eee13fed6213a8d17aa1a76287ff (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
<!DOCTYPE HTML>
<html>
<head>
  <title>Test Encrypted Media Extensions access can be gated by application</title>
  <script src="/tests/SimpleTest/SimpleTest.js"></script>
  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
  <script type="text/javascript" src="manifest.js"></script>
  <script type="text/javascript" src="eme.js"></script>
</head>
<body>
<pre id="test">
<script class="testbody" type="text/javascript">

// These test cases should be used to make a request to
// requestMediaKeySystemAccess and have the following members:
// name: a name describing the test.
// askAppApproval: used to set prefs such so that Gecko will ask for app
// approval for EME if true, or not if false.
// appApproves: used to set prefs to simulate app approval of permission
// request, true if the app approves the request, false if not.
// expectedKeySystemAccess: true if we expect to be granted key system access,
// false if not.
const testCases = [
  {
    name: "Don't check for app approval",
    askAppApproval: false,
    expectedKeySystemAccess: true,
  },
  {
    name: "Check for app approval and app denies request",
    askAppApproval: true,
    appApproves: false,
    expectedKeySystemAccess: false,
  },
  {
    name: "Check for app approval and app allows request",
    askAppApproval: true,
    appApproves: true,
    expectedKeySystemAccess: true,
  },
];

// Options for requestMediaKeySystemAccess that are expected to work.
const options = [{
  initDataTypes: ['webm'],
  audioCapabilities: [
    { contentType: 'audio/webm; codecs="opus"' },
  ],
  videoCapabilities: [
    { contentType: 'video/webm; codecs="vp8"' }
  ]
}];

async function setTestPrefs({askAppApproval, appApproves}) {
  if (!askAppApproval) {
    // Test doesn't want app approval, set pref so we don't ask and unset prefs
    // used to determine permission response as we don't need them.
    await SpecialPowers.pushPrefEnv({
      set: [["media.eme.require-app-approval", false]],
      clear: [
        ["media.eme.require-app-approval.prompt.testing"],
        ["media.eme.require-app-approval.prompt.testing.allow"],
      ]
    });
    return;
  }

  // Test wants app approval, and will approve deny requests per appApproces
  // value, set prefs accordingly.
  await SpecialPowers.pushPrefEnv({
    set: [
      ["media.eme.require-app-approval", true],
      ["media.eme.require-app-approval.prompt.testing", true],
      ["media.eme.require-app-approval.prompt.testing.allow", appApproves],
    ],
  });
}

// Run a test case that makes a single requestMediaKeySystemAccess call. The
// outcome of such a test run should depend on the test case's setting of
// preferences controlling the eme app approval.
async function testSingleRequest(testCase) {
  await setTestPrefs(testCase);

  try {
    await navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, options);
    ok(testCase.expectedKeySystemAccess,
       `testSingleRequest ${testCase.name}: allowed media key system access.`);
  } catch(e) {
    is(e.name,
       "NotSupportedError",
       "Should get NotSupportedError when request is blocked.");
    is(e.message,
       "The application embedding this user agent has blocked MediaKeySystemAccess",
       "Should get blocked error message.");
    ok(!testCase.expectedKeySystemAccess,
       `testSingleRequest ${testCase.name}: denied media key system access.`);
  }
}

// Run a test case that, but using invalid arguments for
// requestMediaKeySystemAccess. Because we expect the args to be checked
// before requesting app approval, this test ensures that we always fail when
// using bad args, regardless of the app approval prefs set.
async function testRequestWithInvalidArgs(testCase) {
  const badOptions = [{
    initDataTypes: ['badType'],
    audioCapabilities: [
      { contentType: 'audio/webm; codecs="notACodec"' },
    ],
    videoCapabilities: [
      { contentType: 'video/webm; codecs="notACodec"' }
    ]
  }];

  await setTestPrefs(testCase);

  // Check that calls with a bad key system fail.
  try {
    await navigator.requestMediaKeySystemAccess("BadKeySystem", options);
    ok(false,
       `testRequestWithInvalidArgs ${testCase.name}: should not get access when using bad key system.`);
  } catch(e) {
    is(e.name,
       "NotSupportedError",
       "Should get NotSupportedError using bad key system.");
    is(e.message,
       "Key system is unsupported",
       "Should get not supported key system error message.");
  }

  // Check that calls with the bad options fail.
  try {
    await navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, badOptions);
    ok(false,
       `testRequestWithInvalidArgs ${testCase.name}: should not get access when using bad options.`);
  } catch(e) {
    is(e.name,
       "NotSupportedError",
       "Should get NotSupportedError using bad options.");
    is(e.message,
       "Key system configuration is not supported",
       "Should get not supported config error message.");
  }
}

// Run a test case and make multiple requests with the same case. Check that
// all requests are resolved with the expected outcome.
async function testMultipleRequests(testCase) {
  // Number of requests to concurrently make.
  const NUM_REQUESTS = 5;

  await setTestPrefs(testCase);

  let resolveHandler = () => {
    ok(testCase.expectedKeySystemAccess,
       `testMultipleRequests ${testCase.name}: allowed media key system access.`);
  }

  let rejectHandler = e => {
    is(e.name,
       "NotSupportedError",
       "Should get NotSupportedError when request is blocked.");
    is(e.message,
       "The application embedding this user agent has blocked MediaKeySystemAccess",
       "Should get blocked error message.");
    ok(!testCase.expectedKeySystemAccess,
       `testMultipleRequests ${testCase.name}: denied media key system access.`);
  }

  let accessPromises = [];
  for(let i = 0; i < NUM_REQUESTS; i++) {
    // Request access then chain to our resolve and reject handlers. The
    // handlers assert test state then resolve the promise chain. Ensuring the
    // chain is always resolved allows us to correctly await all outstanding
    // requests -- otherwise rejects short circuit the Promise.all call below.
    let accessPromise = navigator.requestMediaKeySystemAccess(CLEARKEY_KEYSYSTEM, options)
      .then(resolveHandler, rejectHandler);
    accessPromises.push(accessPromise);
  }
  // Wait for all promises to be resolved. If not, we'll time out. Because
  // our reject handler chains back into a resolved promise, this should wait
  // for all requests to be serviced, even when requestMediaKeySystemAccess's
  // promise is rejected.
  await Promise.all(accessPromises);
}

// The tests rely on prefs being set, so run them in sequence. If we run in
// parallel the tests break each other by overriding prefs.
for (const testCase of testCases) {
  add_task(() => testSingleRequest(testCase));
}
for (const testCase of testCases) {
  add_task(() => testRequestWithInvalidArgs(testCase));
}
for (const testCase of testCases) {
  add_task(() => testMultipleRequests(testCase));
}
</script>
</pre>
</body>
</html>