Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: chrome/test/data/webrtc/peerconnection_getstats.js

Issue 2489673003: RTCPeerConnection.getStats: Whitelist of stats in unittest. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/media/webrtc/webrtc_browsertest_base.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /** 1 /**
2 * Copyright 2016 The Chromium Authors. All rights reserved. 2 * Copyright 2016 The Chromium Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 /**
8 * Maps "RTCStats.type" values to descriptions of whitelisted (allowed to be
9 * exposed to the web) RTCStats-derived dictionaries described below.
10 * @private
11 */
12 var gStatsWhitelist = new Map();
13
14 /**
15 * RTCRTPStreamStats
16 * https://w3c.github.io/webrtc-stats/#streamstats-dict*
17 * @private
18 */
19 var kRTCRTPStreamStats = new RTCStats_(null, {
20 ssrc: 'string',
21 associateStatsId: 'string',
22 isRemote: 'boolean',
23 mediaType: 'string',
24 mediaTrackId: 'string',
25 transportId: 'string',
26 codecId: 'string',
27 firCount: 'number',
28 pliCount: 'number',
29 nackCount: 'number',
30 sliCount: 'number',
31 });
32
33 /*
34 * RTCCodecStats
35 * https://w3c.github.io/webrtc-stats/#codec-dict*
36 * @private
37 */
38 var kRTCCodecStats = new RTCStats_(null, {
39 payloadType: 'number',
40 codec: 'string',
41 clockRate: 'number',
42 channels: 'number',
43 parameters: 'string',
44 implementation: 'string',
45 });
46 gStatsWhitelist.set('codec', kRTCCodecStats);
47
48 /*
49 * RTCInboundRTPStreamStats
50 * https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
51 * @private
52 */
53 var kRTCInboundRTPStreamStats = new RTCStats_(kRTCRTPStreamStats, {
54 packetsReceived: 'number',
55 bytesReceived: 'number',
56 packetsLost: 'number',
57 jitter: 'number',
58 fractionLost: 'number',
59 packetsDiscarded: 'number',
60 packetsRepaired: 'number',
61 burstPacketsLost: 'number',
62 burstPacketsDiscarded: 'number',
63 burstLossCount: 'number',
64 burstDiscardCount: 'number',
65 burstLossRate: 'number',
66 burstDiscardRate: 'number',
67 gapLossRate: 'number',
68 gapDiscardRate: 'number',
69 });
70 gStatsWhitelist.set('inbound-rtp', kRTCInboundRTPStreamStats);
71
72 /*
73 * RTCOutboundRTPStreamStats
74 * https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict*
75 * @private
76 */
77 var kRTCOutboundRTPStreamStats = new RTCStats_(kRTCRTPStreamStats, {
78 packetsSent: 'number',
79 bytesSent: 'number',
80 targetBitrate: 'number',
81 roundTripTime: 'number',
82 });
83 gStatsWhitelist.set('outbound-rtp', kRTCOutboundRTPStreamStats);
84
85 /*
86 * RTCPeerConnectionStats
87 * https://w3c.github.io/webrtc-stats/#pcstats-dict*
88 * @private
89 */
90 var kRTCPeerConnectionStats = new RTCStats_(null, {
91 dataChannelsOpened: 'number',
92 dataChannelsClosed: 'number',
93 });
94 gStatsWhitelist.set('peer-connection', kRTCPeerConnectionStats);
95
96 /*
97 * RTCMediaStreamStats
98 * https://w3c.github.io/webrtc-stats/#msstats-dict*
99 * @private
100 */
101 var kRTCMediaStreamStats = new RTCStats_(null, {
102 streamIdentifier: 'string',
103 trackIds: 'sequence_string',
104 });
105 gStatsWhitelist.set('stream', kRTCMediaStreamStats);
106
107 /*
108 * RTCMediaStreamTrackStats
109 * https://w3c.github.io/webrtc-stats/#mststats-dict*
110 * @private
111 */
112 var kRTCMediaStreamTrackStats = new RTCStats_(null, {
113 trackIdentifier: 'string',
114 remoteSource: 'boolean',
115 ended: 'boolean',
116 detached: 'boolean',
117 ssrcIds: 'sequence_string',
118 frameWidth: 'number',
119 frameHeight: 'number',
120 framesPerSecond: 'number',
121 framesSent: 'number',
122 framesReceived: 'number',
123 framesDecoded: 'number',
124 framesDropped: 'number',
125 framesCorrupted: 'number',
126 partialFramesLost: 'number',
127 fullFramesLost: 'number',
128 audioLevel: 'number',
129 echoReturnLoss: 'number',
130 echoReturnLossEnhancement: 'number',
131 });
132 gStatsWhitelist.set('track', kRTCMediaStreamTrackStats);
133
134 /*
135 * RTCDataChannelStats
136 * https://w3c.github.io/webrtc-stats/#dcstats-dict*
137 * @private
138 */
139 var kRTCDataChannelStats = new RTCStats_(null, {
140 label: 'string',
141 protocol: 'string',
142 datachannelid: 'number',
143 state: 'string',
144 messagesSent: 'number',
145 bytesSent: 'number',
146 messagesReceived: 'number',
147 bytesReceived: 'number',
148 });
149 gStatsWhitelist.set('data-channel', kRTCDataChannelStats);
150
151 /*
152 * RTCTransportStats
153 * https://w3c.github.io/webrtc-stats/#transportstats-dict*
154 * @private
155 */
156 var kRTCTransportStats = new RTCStats_(null, {
157 bytesSent: 'number',
158 bytesReceived: 'number',
159 rtcpTransportStatsId: 'string',
160 activeConnection: 'boolean',
161 selectedCandidatePairId: 'string',
162 localCertificateId: 'string',
163 remoteCertificateId: 'string',
164 });
165 gStatsWhitelist.set('transport', kRTCTransportStats);
166
167 /*
168 * RTCIceCandidateStats
169 * https://w3c.github.io/webrtc-stats/#icecandidate-dict*
170 * @private
171 */
172 var kRTCIceCandidateStats = new RTCStats_(null, {
173 ip: 'string',
174 port: 'number',
175 protocol: 'string',
176 candidateType: 'string',
177 priority: 'number',
178 url: 'string',
179 });
180 gStatsWhitelist.set('local-candidate', kRTCIceCandidateStats);
181 gStatsWhitelist.set('remote-candidate', kRTCIceCandidateStats);
182
183 /*
184 * RTCIceCandidatePairStats
185 * https://w3c.github.io/webrtc-stats/#candidatepair-dict*
186 * @private
187 */
188 var kRTCIceCandidatePairStats = new RTCStats_(null, {
189 transportId: 'string',
190 localCandidateId: 'string',
191 remoteCandidateId: 'string',
192 state: 'string',
193 priority: 'number',
194 nominated: 'boolean',
195 writable: 'boolean',
196 readable: 'boolean',
197 bytesSent: 'number',
198 bytesReceived: 'number',
199 totalRtt: 'number',
200 currentRtt: 'number',
201 availableOutgoingBitrate: 'number',
202 availableIncomingBitrate: 'number',
203 requestsReceived: 'number',
204 requestsSent: 'number',
205 responsesReceived: 'number',
206 responsesSent: 'number',
207 retransmissionsReceived: 'number',
208 retransmissionsSent: 'number',
209 consentRequestsReceived: 'number',
210 consentRequestsSent: 'number',
211 consentResponsesReceived: 'number',
212 consentResponsesSent: 'number',
213 });
214 gStatsWhitelist.set('candidate-pair', kRTCIceCandidatePairStats);
215
216 /*
217 * RTCCertificateStats
218 * https://w3c.github.io/webrtc-stats/#certificatestats-dict*
219 * @private
220 */
221 var kRTCCertificateStats = new RTCStats_(null, {
222 fingerprint: 'string',
223 fingerprintAlgorithm: 'string',
224 base64Certificate: 'string',
225 issuerCertificateId: 'string',
226 });
227 gStatsWhitelist.set('certificate', kRTCCertificateStats);
228
7 // Public interface to tests. These are expected to be called with 229 // Public interface to tests. These are expected to be called with
8 // ExecuteJavascript invocations from the browser tests and will return answers 230 // ExecuteJavascript invocations from the browser tests and will return answers
9 // through the DOM automation controller. 231 // through the DOM automation controller.
10 232
11 /** 233 /**
12 * Verifies that the promise-based |RTCPeerConnection.getStats| returns stats. 234 * Verifies that the promise-based |RTCPeerConnection.getStats| returns stats.
13 * 235 *
14 * Returns ok-got-stats on success. 236 * Returns to test "ok-" followed by a list of "RTCStats.type" values as a
237 * string of semicolon separated values, these being the different types of
238 * stats that was returned by getStats.
15 */ 239 */
16 function verifyStatsGeneratedPromise() { 240 function verifyStatsGeneratedPromise() {
17 peerConnection_().getStats() 241 peerConnection_().getStats()
18 .then(function(report) { 242 .then(function(report) {
19 if (report == null || report.size == 0) 243 if (report == null || report.size == 0)
20 throw new failTest('report is null or empty.'); 244 throw new failTest('report is null or empty.');
21 // Sanity check that applies to all stats. 245 let statsTypes = new Set();
22 var ids = new Set(); 246 let ids = new Set();
23 report.forEach(function(stats) { 247 for (let stats of report.values()) {
24 if (typeof(stats.id) !== 'string') 248 verifyStatsIsWhitelisted_(stats);
25 throw failTest('stats.id is not a string.'); 249 statsTypes.add(stats.type);
26 if (ids.has(stats.id)) 250 if (ids.has(stats.id))
27 throw failTest('stats.id is not a unique identifier.'); 251 throw failTest('stats.id is not a unique identifier.');
28 ids.add(stats.id); 252 ids.add(stats.id);
29 if (typeof(stats.timestamp) !== 'number' || stats.timestamp <= 0) 253 }
30 throw failTest('stats.timestamp is not a positive number.'); 254 returnToTest('ok-' + iterableToSemicolonList(statsTypes.values()));
phoglund_chromium 2016/11/09 15:50:10 I'd recommend using JSON.stringify here instead of
hbos_chromium 2016/11/09 17:24:32 Done. (The referenced JSON is being returned to C+
31 if (typeof(stats.type) !== 'string')
32 throw failTest('stats.type is not a string.');
33 });
34 // TODO(hbos): When the new stats collection API is more mature (and
35 // certainly before unflagging the new stats API) add a whitelist of
36 // allowed stats to prevent accidentally exposing stats to the web that
37 // are not in the spec and that verifies type information. Status at
38 // crbug.com/627816. Stats collection is tested in the WebRTC repo and
39 // automatically surfaced to Blink, but there should be a process of
40 // having to land a Blink CL in order to expose a new RTCStats dictionary.
41 returnToTest('ok-got-stats');
42 }, 255 },
43 function(e) { 256 function(e) {
44 throw failTest('Promise was rejected: ' + e); 257 throw failTest('Promise was rejected: ' + e);
45 }); 258 });
46 } 259 }
260
261 /**
262 * Returns to test a complete list of whitelisted "RTCStats.type" values as a
263 * string of semicolon separated values.
264 */
265 function getWhitelistedStatsTypes() {
266 returnToTest(iterableToSemicolonList(gStatsWhitelist.keys()));
267 }
268
269 // Internals.
270
271 /** @private */
272 function RTCStats_(parent, membersObject) {
273 if (parent != null) {
274 for (let member in parent) {
275 this[member] = parent[member];
276 }
277 }
278 for (let member in membersObject) {
279 this[member] = membersObject[member];
280 }
281 }
282
283 /**
284 * Checks if |stats| correctly maps to a a whitelisted RTCStats-derived
285 * dictionary, throwing |failTest| if it doesn't. See |gStatsWhitelist|.
286 *
287 * The "RTCStats.type" must map to a known dictionary description. Every member
288 * is optional, but if present it must be present in the whitelisted dictionary
289 * description and its type must match.
290 * @private
291 */
292 function verifyStatsIsWhitelisted_(stats) {
293 if (stats == null)
294 throw failTest('stats is null or undefined: ' + stats);
295 if (typeof(stats.id) !== 'string')
296 throw failTest('stats.id is not a string:' + stats.id);
297 if (typeof(stats.timestamp) !== 'number' || !isFinite(stats.timestamp) ||
298 stats.timestamp <= 0) {
299 throw failTest('stats.timestamp is not a positive finite number: ' +
300 stats.timestamp);
301 }
302 if (typeof(stats.type) !== 'string')
303 throw failTest('stats.type is not a string: ' + stats.type);
304 let whitelistedStats = gStatsWhitelist.get(stats.type);
305 if (whitelistedStats == null)
306 throw failTest('stats.type is not a whitelisted type: ' + stats.type);
307 for (let propertyName in stats) {
308 if (propertyName === 'id' || propertyName === 'timestamp' ||
309 propertyName === 'type') {
310 continue;
311 }
312 if (!whitelistedStats.hasOwnProperty(propertyName)) {
313 throw failTest('stats.' + propertyName + ' is not a whitelisted ' +
314 'member: ' + stats[propertyName]);
315 }
316 if (!whitelistedStats[propertyName].startsWith('sequence_')) {
317 if (typeof(stats[propertyName]) !== whitelistedStats[propertyName]) {
318 throw failTest('stats.' + propertyName + ' should have a different ' +
319 'type according to the whitelist: ' + stats[propertyName] + ' vs ' +
320 whitelistedStats[propertyName]);
321 }
322 } else {
323 if (!Array.isArray(stats[propertyName])) {
324 throw failTest('stats.' + propertyName + ' should have a different ' +
325 'type according to the whitelist (should be an array): ' +
326 JSON.stringify(stats[propertyName]) + ' vs ' +
327 whitelistedStats[propertyName]);
328 }
329 let elementType = whitelistedStats[propertyName].substring(9);
330 for (let element in stats[propertyName]) {
331 if (typeof(element) !== elementType) {
332 throw failTest('stats.' + propertyName + ' should have a different ' +
333 'type according to the whitelist (an element of the array has ' +
334 'the incorrect type): ' + JSON.stringify(stats[propertyName]) +
335 ' vs ' + whitelistedStats[propertyName]);
336 }
337 }
338 }
339 }
340 }
341
342 /** @private */
343 function iterableToSemicolonList(iterable) {
344 let str = '';
345 for (let element of iterable) {
346 if (str.length > 0)
347 str += ';';
348 str += element;
349 }
350 return str;
351 }
OLDNEW
« no previous file with comments | « chrome/browser/media/webrtc/webrtc_browsertest_base.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698