From 6b73b8c38cfbdd5c5cd65b58fe65f4c9a74894ce Mon Sep 17 00:00:00 2001 From: gorhill Date: Thu, 31 Dec 2015 09:24:55 -0500 Subject: [PATCH] this fixes https://github.com/gorhill/uBlock/issues/533#issuecomment-167931681 --- platform/chromium/is-webrtc-supported.html | 8 ++ platform/chromium/is-webrtc-supported.js | 52 ++++++++++++ platform/chromium/vapi-background.js | 98 +++++++++++++++------- 3 files changed, 126 insertions(+), 32 deletions(-) create mode 100644 platform/chromium/is-webrtc-supported.html create mode 100644 platform/chromium/is-webrtc-supported.js diff --git a/platform/chromium/is-webrtc-supported.html b/platform/chromium/is-webrtc-supported.html new file mode 100644 index 000000000..a0956fcdf --- /dev/null +++ b/platform/chromium/is-webrtc-supported.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/platform/chromium/is-webrtc-supported.js b/platform/chromium/is-webrtc-supported.js new file mode 100644 index 000000000..5a3eea1e7 --- /dev/null +++ b/platform/chromium/is-webrtc-supported.js @@ -0,0 +1,52 @@ +/******************************************************************************* + + uBlock Origin - a browser extension to block requests. + Copyright (C) 2015 Raymond Hill + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see {http://www.gnu.org/licenses/}. + + Home: https://github.com/gorhill/uBlock +*/ + +// https://github.com/gorhill/uBlock/issues/533#issuecomment-164292868 +// If WebRTC is supported, there won't be an exception if we +// try to instanciate a peer connection object. + +// https://github.com/gorhill/uBlock/issues/533#issuecomment-168097594 +// Because Chromium leaks WebRTC connections after they have been closed +// and forgotten, we need to test for WebRTC support inside an iframe, this +// way the closed and forgottetn WebRTC connections are properly garbage +// collected. + +(function() { + 'use strict'; + + var pc = null; + try { + var PC = self.RTCPeerConnection || self.webkitRTCPeerConnection; + if ( PC ) { + pc = new PC(null); + } + } catch (ex) { + console.error(ex); + } + if ( pc !== null ) { + pc.close(); + } + + window.top.postMessage( + pc !== null ? 'webRTCSupported' : 'webRTCNotSupported', + window.location.origin + ); +})(); diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 78fb9605e..1028f0808 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -19,8 +19,6 @@ Home: https://github.com/gorhill/uBlock */ -/* global self, µBlock */ - // For background page /******************************************************************************/ @@ -74,6 +72,71 @@ vAPI.storage = chrome.storage.local; // API threw an exception. vAPI.browserSettings = { + webRTCSupported: undefined, + + // https://github.com/gorhill/uBlock/issues/533 + // We must first check wether this Chromium-based browser was compiled + // with WebRTC support. To do this, we use an iframe, this way the + // empty RTCPeerConnection object we create to test for support will + // be properly garbage collected. This prevents issues such as + // a computer unable to enter into sleep mode, as reported in the + // Chrome store: + // https://github.com/gorhill/uBlock/issues/533#issuecomment-167931681 + setWebrtcIPAddress: function(setting) { + // We don't know yet whether this browser supports WebRTC: find out. + if ( this.webRTCSupported === undefined ) { + this.webRTCSupported = { setting: setting }; + var iframe = document.createElement('iframe'); + var me = this; + var messageHandler = function(ev) { + if ( ev.origin !== self.location.origin ) { + return; + } + window.removeEventListener('message', messageHandler); + var setting = me.webRTCSupported.setting; + me.webRTCSupported = ev.data === 'webRTCSupported'; + me.setWebrtcIPAddress(setting); + iframe.parentNode.removeChild(iframe); + iframe = null; + }; + window.addEventListener('message', messageHandler); + iframe.src = 'is-webrtc-supported.html'; + document.body.appendChild(iframe); + return; + } + + // We are waiting for a response from our iframe. This makes the code + // safe to re-entrancy. + if ( typeof this.webRTCSupported === 'object' ) { + this.webRTCSupported.setting = setting; + return; + } + + // https://github.com/gorhill/uBlock/issues/533 + // WebRTC not supported: `webRTCMultipleRoutesEnabled` can NOT be + // safely accessed. Accessing the property will cause full browser + // crash. + if ( this.webRTCSupported !== true ) { + return; + } + + // Older version of Chromium do not support this setting. + if ( typeof chrome.privacy.network.webRTCMultipleRoutesEnabled !== 'object' ) { + return; + } + + try { + chrome.privacy.network.webRTCMultipleRoutesEnabled.set({ + value: !!setting, + scope: 'regular' + }, function() { + void chrome.runtime.lastError; + }); + } catch(ex) { + console.error(ex); + } + }, + set: function(details) { // https://github.com/gorhill/uBlock/issues/875 // Must not leave `lastError` unchecked. @@ -109,36 +172,7 @@ vAPI.browserSettings = { break; case 'webrtcIPAddress': - // https://github.com/gorhill/uBlock/issues/533#issuecomment-164292868 - // If WebRTC is supported, there won't be an exception if we - // try to instanciate a peer connection object. - //var pc = null; - //try { - // var PC = self.RTCPeerConnection || self.webkitRTCPeerConnection; - // if ( PC ) { - // pc = new PC(null); - // } - //} catch (ex) { - // console.error(ex); - //} - //if ( pc === null ) { - // break; - //} - //pc.close(); - - // https://github.com/gorhill/uBlock/issues/533 - // If we reach this point, the property - // `webRTCMultipleRoutesEnabled` can be safely accessed. - if ( typeof chrome.privacy.network.webRTCMultipleRoutesEnabled === 'object' ) { - try { - chrome.privacy.network.webRTCMultipleRoutesEnabled.set({ - value: !!details[setting], - scope: 'regular' - }, callback); - } catch(ex) { - console.error(ex); - } - } + this.setWebrtcIPAddress(details[setting]); break; default: