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: