Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: inject.preload.js

Issue 29607555: Issue 6030 - Ensure RTCPeerConnection exists before wrapping it (Closed)
Patch Set: Wrap WebRTC wrapping code in the if block Created Nov. 14, 2017, 11:32 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | 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 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-present eyeo GmbH 3 * Copyright (C) 2006-present eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 218
219 /* 219 /*
220 * RTCPeerConnection wrapper 220 * RTCPeerConnection wrapper
221 * 221 *
222 * The webRequest API in Chrome does not yet allow the blocking of 222 * The webRequest API in Chrome does not yet allow the blocking of
223 * WebRTC connections. 223 * WebRTC connections.
224 * See https://bugs.chromium.org/p/chromium/issues/detail?id=707683 224 * See https://bugs.chromium.org/p/chromium/issues/detail?id=707683
225 */ 225 */
226 let RealRTCPeerConnection = window.RTCPeerConnection || 226 let RealRTCPeerConnection = window.RTCPeerConnection ||
227 window.webkitRTCPeerConnection; 227 window.webkitRTCPeerConnection;
228 let closeRTCPeerConnection = Function.prototype.call.bind(
229 RealRTCPeerConnection.prototype.close
230 );
231 let RealArray = Array;
232 let RealString = String;
233 let {create: createObject, defineProperty} = Object;
234 228
235 function normalizeUrl(url) 229 // Firefox has the option (media.peerconnection.enabled) to disable WebRTC
230 // in which case RealRTCPeerConnection is undefined.
231 if (typeof RealRTCPeerConnection != "undefined")
236 { 232 {
237 if (typeof url != "undefined") 233 let closeRTCPeerConnection = Function.prototype.call.bind(
238 return RealString(url); 234 RealRTCPeerConnection.prototype.close
239 } 235 );
236 let RealArray = Array;
237 let RealString = String;
238 let {create: createObject, defineProperty} = Object;
240 239
241 function safeCopyArray(originalArray, transform) 240 let normalizeUrl = url =>
kzar 2017/11/14 11:36:35 This change - and several like it below - are nece
242 { 241 {
243 if (originalArray == null || typeof originalArray != "object") 242 if (typeof url != "undefined")
244 return originalArray; 243 return RealString(url);
244 };
245 245
246 let safeArray = RealArray(originalArray.length); 246 let safeCopyArray = (originalArray, transform) =>
247 for (let i = 0; i < safeArray.length; i++)
248 { 247 {
249 defineProperty(safeArray, i, { 248 if (originalArray == null || typeof originalArray != "object")
250 configurable: false, enumerable: false, writable: false, 249 return originalArray;
251 value: transform(originalArray[i])
252 });
253 }
254 defineProperty(safeArray, "length", {
255 configurable: false, enumerable: false, writable: false,
256 value: safeArray.length
257 });
258 return safeArray;
259 }
260 250
261 // It would be much easier to use the .getConfiguration method to obtain 251 let safeArray = RealArray(originalArray.length);
262 // the normalized and safe configuration from the RTCPeerConnection 252 for (let i = 0; i < safeArray.length; i++)
263 // instance. Unfortunately its not implemented as of Chrome unstable 59.
264 // See https://www.chromestatus.com/feature/5271355306016768
265 function protectConfiguration(configuration)
266 {
267 if (configuration == null || typeof configuration != "object")
268 return configuration;
269
270 let iceServers = safeCopyArray(
271 configuration.iceServers,
272 iceServer =>
273 { 253 {
274 let {url, urls} = iceServer; 254 defineProperty(safeArray, i, {
275 255 configurable: false, enumerable: false, writable: false,
276 // RTCPeerConnection doesn't iterate through pseudo Arrays of urls. 256 value: transform(originalArray[i])
277 if (typeof urls != "undefined" && !(urls instanceof RealArray))
278 urls = [urls];
279
280 return createObject(iceServer, {
281 url: {
282 configurable: false, enumerable: false, writable: false,
283 value: normalizeUrl(url)
284 },
285 urls: {
286 configurable: false, enumerable: false, writable: false,
287 value: safeCopyArray(urls, normalizeUrl)
288 }
289 }); 257 });
290 } 258 }
291 ); 259 defineProperty(safeArray, "length", {
260 configurable: false, enumerable: false, writable: false,
261 value: safeArray.length
262 });
263 return safeArray;
264 };
292 265
293 return createObject(configuration, { 266 // It would be much easier to use the .getConfiguration method to obtain
294 iceServers: { 267 // the normalized and safe configuration from the RTCPeerConnection
295 configurable: false, enumerable: false, writable: false, 268 // instance. Unfortunately its not implemented as of Chrome unstable 59.
296 value: iceServers 269 // See https://www.chromestatus.com/feature/5271355306016768
297 } 270 let protectConfiguration = configuration =>
298 }); 271 {
299 } 272 if (configuration == null || typeof configuration != "object")
273 return configuration;
300 274
301 function checkUrl(peerconnection, url) 275 let iceServers = safeCopyArray(
302 { 276 configuration.iceServers,
303 checkRequest("webrtc", url, blocked => 277 iceServer =>
278 {
279 let {url, urls} = iceServer;
280
281 // RTCPeerConnection doesn't iterate through pseudo Arrays of urls.
282 if (typeof urls != "undefined" && !(urls instanceof RealArray))
283 urls = [urls];
284
285 return createObject(iceServer, {
286 url: {
287 configurable: false, enumerable: false, writable: false,
288 value: normalizeUrl(url)
289 },
290 urls: {
291 configurable: false, enumerable: false, writable: false,
292 value: safeCopyArray(urls, normalizeUrl)
293 }
294 });
295 }
296 );
297
298 return createObject(configuration, {
299 iceServers: {
300 configurable: false, enumerable: false, writable: false,
301 value: iceServers
302 }
303 });
304 };
305
306 let checkUrl = (peerconnection, url) =>
304 { 307 {
305 if (blocked) 308 checkRequest("webrtc", url, blocked =>
306 { 309 {
307 // Calling .close() throws if already closed. 310 if (blocked)
308 try
309 { 311 {
310 closeRTCPeerConnection(peerconnection); 312 // Calling .close() throws if already closed.
313 try
314 {
315 closeRTCPeerConnection(peerconnection);
316 }
317 catch (e) {}
311 } 318 }
312 catch (e) {} 319 });
313 } 320 };
314 });
315 }
316 321
317 function checkConfiguration(peerconnection, configuration) 322 let checkConfiguration = (peerconnection, configuration) =>
318 {
319 if (configuration && configuration.iceServers)
320 { 323 {
321 for (let i = 0; i < configuration.iceServers.length; i++) 324 if (configuration && configuration.iceServers)
322 { 325 {
323 let iceServer = configuration.iceServers[i]; 326 for (let i = 0; i < configuration.iceServers.length; i++)
324 if (iceServer)
325 { 327 {
326 if (iceServer.url) 328 let iceServer = configuration.iceServers[i];
327 checkUrl(peerconnection, iceServer.url); 329 if (iceServer)
330 {
331 if (iceServer.url)
332 checkUrl(peerconnection, iceServer.url);
328 333
329 if (iceServer.urls) 334 if (iceServer.urls)
330 { 335 {
331 for (let j = 0; j < iceServer.urls.length; j++) 336 for (let j = 0; j < iceServer.urls.length; j++)
332 checkUrl(peerconnection, iceServer.urls[j]); 337 checkUrl(peerconnection, iceServer.urls[j]);
338 }
333 } 339 }
334 } 340 }
335 } 341 }
342 };
343
344 // Chrome unstable (tested with 59) has already implemented
345 // setConfiguration, so we need to wrap that if it exists too.
346 // https://www.chromestatus.com/feature/5596193748942848
347 if (RealRTCPeerConnection.prototype.setConfiguration)
348 {
349 let realSetConfiguration = Function.prototype.call.bind(
350 RealRTCPeerConnection.prototype.setConfiguration
351 );
352
353 RealRTCPeerConnection.prototype.setConfiguration = function(configuration)
354 {
355 configuration = protectConfiguration(configuration);
356
357 // Call the real method first, so that validates the configuration for
358 // us. Also we might as well since checkRequest is asynchronous anyway.
359 realSetConfiguration(this, configuration);
360 checkConfiguration(this, configuration);
361 };
336 } 362 }
363
364 let WrappedRTCPeerConnection = function(...args)
365 {
366 if (!(this instanceof WrappedRTCPeerConnection))
367 return RealRTCPeerConnection();
368
369 let configuration = protectConfiguration(args[0]);
370
371 // Since the old webkitRTCPeerConnection constructor takes an optional
372 // second argument we need to take care to pass that through. Necessary
373 // for older versions of Chrome such as 49.
374 let constraints = undefined;
375 if (args.length > 1)
376 constraints = args[1];
377
378 let peerconnection = new RealRTCPeerConnection(configuration,
379 constraints);
380 checkConfiguration(peerconnection, configuration);
381 return peerconnection;
382 };
383
384 WrappedRTCPeerConnection.prototype = RealRTCPeerConnection.prototype;
385
386 let boundWrappedRTCPeerConnection = WrappedRTCPeerConnection.bind();
387 copyProperties(RealRTCPeerConnection, boundWrappedRTCPeerConnection,
388 ["generateCertificate", "name", "prototype"]);
389 RealRTCPeerConnection.prototype.constructor = boundWrappedRTCPeerConnection;
390
391 if ("RTCPeerConnection" in window)
392 window.RTCPeerConnection = boundWrappedRTCPeerConnection;
393 if ("webkitRTCPeerConnection" in window)
394 window.webkitRTCPeerConnection = boundWrappedRTCPeerConnection;
337 } 395 }
338
339 // Chrome unstable (tested with 59) has already implemented
340 // setConfiguration, so we need to wrap that if it exists too.
341 // https://www.chromestatus.com/feature/5596193748942848
342 if (RealRTCPeerConnection.prototype.setConfiguration)
343 {
344 let realSetConfiguration = Function.prototype.call.bind(
345 RealRTCPeerConnection.prototype.setConfiguration
346 );
347
348 RealRTCPeerConnection.prototype.setConfiguration = function(configuration)
349 {
350 configuration = protectConfiguration(configuration);
351
352 // Call the real method first, so that validates the configuration for
353 // us. Also we might as well since checkRequest is asynchronous anyway.
354 realSetConfiguration(this, configuration);
355 checkConfiguration(this, configuration);
356 };
357 }
358
359 function WrappedRTCPeerConnection(...args)
360 {
361 if (!(this instanceof WrappedRTCPeerConnection))
362 return RealRTCPeerConnection();
363
364 let configuration = protectConfiguration(args[0]);
365
366 // Since the old webkitRTCPeerConnection constructor takes an optional
367 // second argument we need to take care to pass that through. Necessary
368 // for older versions of Chrome such as 49.
369 let constraints = undefined;
370 if (args.length > 1)
371 constraints = args[1];
372
373 let peerconnection = new RealRTCPeerConnection(configuration, constraints);
374 checkConfiguration(peerconnection, configuration);
375 return peerconnection;
376 }
377
378 WrappedRTCPeerConnection.prototype = RealRTCPeerConnection.prototype;
379
380 let boundWrappedRTCPeerConnection = WrappedRTCPeerConnection.bind();
381 copyProperties(RealRTCPeerConnection, boundWrappedRTCPeerConnection,
382 ["generateCertificate", "name", "prototype"]);
383 RealRTCPeerConnection.prototype.constructor = boundWrappedRTCPeerConnection;
384
385 if ("RTCPeerConnection" in window)
386 window.RTCPeerConnection = boundWrappedRTCPeerConnection;
387 if ("webkitRTCPeerConnection" in window)
388 window.webkitRTCPeerConnection = boundWrappedRTCPeerConnection;
389 } 396 }
390 397
391 if (document instanceof HTMLDocument) 398 if (document instanceof HTMLDocument)
392 { 399 {
393 let sandbox = window.frameElement && 400 let sandbox = window.frameElement &&
394 window.frameElement.getAttribute("sandbox"); 401 window.frameElement.getAttribute("sandbox");
395 402
396 if (typeof sandbox != "string" || /(^|\s)allow-scripts(\s|$)/i.test(sandbox)) 403 if (typeof sandbox != "string" || /(^|\s)allow-scripts(\s|$)/i.test(sandbox))
397 { 404 {
398 let script = document.createElement("script"); 405 let script = document.createElement("script");
399 script.type = "application/javascript"; 406 script.type = "application/javascript";
400 script.async = false; 407 script.async = false;
401 script.textContent = "(" + injected + ")('" + randomEventName + "');"; 408 script.textContent = "(" + injected + ")('" + randomEventName + "');";
402 document.documentElement.appendChild(script); 409 document.documentElement.appendChild(script);
403 document.documentElement.removeChild(script); 410 document.documentElement.removeChild(script);
404 } 411 }
405 } 412 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld