Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uBlock crashes on browser startup if Chromium is compiled without webrtc #533

Closed
lsfxz opened this issue Jul 26, 2015 · 27 comments
Closed

Comments

@lsfxz
Copy link

lsfxz commented Jul 26, 2015

uBlock crashes on startup if you try to load it with a Chromium version that's compiled without webrtc support ( -Denable_webrtc=0 ).

Removing 'webrtcIPAddress': !userSettings.webrtcIPAddressHidden from start.js makes it work again so I guess that's roughly where things go wrong.

@gorhill
Copy link
Owner

gorhill commented Jul 26, 2015

This needs to be reported to Chromium devs. uBlock is written in javascript, and it's not supposed to crash -- if a crash occurs due to specific javascript code, it's a browser bug.

(By "crash" I am assuming you refer to the "aww snap!" screen.)

@lsfxz
Copy link
Author

lsfxz commented Jul 26, 2015

If that's the case I'll report it there — I know too little about Chromium to tell which component is at fault.

By "crash" I mean this popup on start or on reloading the extension:

popup

And this is what I get in the terminal:

[18998:18998:0726/140701:ERROR:extension_function.cc(410)] Bad extension message types.ChromeSetting.set
[18998:18998:0726/140701:ERROR:extension_function_dispatcher.cc(112)] Terminating renderer because of malformed extension message.

@gorhill
Copy link
Owner

gorhill commented Jul 26, 2015

By "crash" I mean this popup on start or on reloading the extension:

Yes, that balloon indicates a browser crash.

Is this your own build of Chromium? If not, what is the origin of that special build? (Just want to understand how much people are possibly affected by this.)

@lsfxz
Copy link
Author

lsfxz commented Jul 26, 2015

It's a build called "Inox": https://bbs.archlinux.org/viewtopic.php?id=198763
So I guess it's not just me, but probably not too many who might be affected.

@gorhill
Copy link
Owner

gorhill commented Jul 26, 2015

I do test here if the WebRTC preference exists in the browser. However I wonder if chrome.privacy.network.webRTCMultipleRoutesEnabled is returned as null when the preference is not supported (I am assuming undefined is returned there), and if so this would trip uBlock because null is of type object.

Since your first comment suggests you modified uBlock, would you mind changing the line above from:

if ( typeof chrome.privacy.network.webRTCMultipleRoutesEnabled === 'object' ) {

To:

if (
    typeof chrome.privacy.network.webRTCMultipleRoutesEnabled === 'object' &&
    chrome.privacy.network.webRTCMultipleRoutesEnabled !== null
) {

And see if this helps?

@lsfxz
Copy link
Author

lsfxz commented Jul 26, 2015

Unfortunately it doesn't help, still crashes with the same symptoms.

@lewisje
Copy link

lewisje commented Jul 27, 2015

I thought the long-time idiom for testing non-function objects was typeof thing === 'object' && thing != null, or for all objects, typeof thing === 'function' || (typeof thing === 'object' && thing != null).

@user
Copy link

user commented Aug 7, 2015

Removing 'webrtcIPAddress': !userSettings.webrtcIPAddressHidden from start.js makes it work again

Confirm.

Same '-Denable_webrtc=0' :/

@gorhill
Copy link
Owner

gorhill commented Aug 15, 2015

If you type typeof webkitRTCPeerConnection (or RTCPeerConnection) in the console, what is the result? Maybe I could use this to detect whether I can safely use the chrome.privacy.network WebRTC API.

@lsfxz
Copy link
Author

lsfxz commented Aug 15, 2015

I get:

typeof RTCPeerConnection
"undefined"
typeof webkitRTCPeerConnection
"function"    

@williex
Copy link

williex commented Sep 20, 2015

Can confirm this problem when compiling chromium without webrtc. The fix from lsfxz works for me.

@Eloston
Copy link

Eloston commented Dec 13, 2015

I am running Chromium 47.0.2526.80 with enable_webrtc=0

Creating an instance of webkitRTCPeerConnection throws a DOMException with the following message:
Failed to construct 'RTCPeerConnection': No PeerConnection handler can be created, perhaps WebRTC is disabled?

Additionally, the name property of the exception object is NotSupportedError.

Using this, the following code fixes the problem for version 1.4.0, file vapi-background.js, line 112 (i.e. right under the statement case 'webIPAddress':):

try {
    var testRTC = new webkitRTCPeerConnection({ iceServers: [] });
    testRTC.close();
} catch(ex) {
    if ( ex instanceof DOMException && ex.name == 'NotSupportedError' ) {
        break;
    }
}

If you don't want to instantiate an instance of webkitRTCPeerConnection, you can also pass in an empty Object into the constructor. Then a TypeError will be thrown instead.

@gorhill
Copy link
Owner

gorhill commented Dec 13, 2015

Thank you very much for the solution, I will import it.

An empty object works fine on my side, including null, but no parameters causes a TypeError, in which case this would make the result unusable to find out whether WebRTC is supported or not. I will go with null -- it would be nice if you can confirm using null also causes an exception on your side.

@Eloston
Copy link

Eloston commented Dec 13, 2015

null exhibits the same behavior as { iceServers: [] } on my browser.

I also have a build of Chromium 41.0.2272.118 with WebRTC enabled. Using an empty object raises a TypeError, but null works. So it seems to be a good thing you chose to stick with null.

@qbit
Copy link
Contributor

qbit commented Dec 13, 2015

I can confirm the 1.4.1b1 release resolves this issue on OpenBSD

@gcarq
Copy link

gcarq commented Dec 14, 2015

1.4.1b1 resolves this issue for Inox compiled with enable_webrtc=0 (tested on Arch Linux).

@gorhill
Copy link
Owner

gorhill commented Dec 30, 2015

There are bad side-effects to this fix, as reported in the Chrome store:

I came home today to find my PC (Win10 x64) wasn't asleep. I checked powercfg -requests and saw Chrome reporting "WebRTC has active PeerConnections".

Looking in chrome://webrtc-internals/ the only entry is for:

chrome-extension://cjpalhdlnbpafiamejdnhcphjbkeiagm/background.html, { servers: [], iceTransportType: all, bundlePolicy: balanced, rtcpMuxPolicy: negotiate },

Which is this extension. What is uBlock doing to keep WebRTC hung up and thus prevent my PC from sleeping?

I took a dump of the WebRTC Internals page if you'd like it for any other info.

And:

With this extension enabled, Windows 10 not longer goes to sleep. POWERCFG /REQUESTS reports "WebRTC has active PeerConnections" from chrome.exe. Disabling this extension removes the request and allows Windows to sleep.

For now I will disable this fix and publish a 1.5.2 version to the Chrome store -- the side effects are too serious and affect way more users than those suffering the crash.

@Kline-
Copy link

Kline- commented Dec 30, 2015

Thanks for the quick revert on this. I'm the first post about this in the Chrome store. Glad to see someone else noticed the same behavior too so it's not just a quirk of my setup or something.

Something I've also just noticed is that if I disable uBo (1.5.1 still) then re-enable it I see the hung WebRTC connection. Clicking into the uBo options menu then clears the open connection and everything continues working well going forward.

@gorhill
Copy link
Owner

gorhill commented Dec 30, 2015

I pushed 1.5.2 to the Chrome store, but as usual it end up being in "Pending review" status, so hopefully it will be cleared tomorrow.

Clicking into the uBo options menu then clears the open connection

Maybe the solution can work but this will need more tuning/testing. When you say "clicking into the uBo options menu", do you mean toggling the option "Prevent WebRTC from leaking local IP addresses"?

@Kline-
Copy link

Kline- commented Dec 30, 2015

Sorry for being unclear. No, I mean from the chrome://extensions screen
literally clicking "options" on uBo's entry there, to where a new tab then
opens with the main uBo options screen.

I don't even toggle any settings after that point, simply having the
options menu open a tab seems to clear whatever gets hung up with the
WebRTC connection.

I can try to capture a video or something tomorrow if it would help to
better illustrate this behavior. I performed the same steps on both mine
and my wife's machine and was able to replicate the same outcome.
On Dec 29, 2015 10:47 PM, "Raymond Hill" notifications@github.com wrote:

I pushed 1.5.2 to the Chrome store, but as usual it end up being in
"Pending review" status, so hopefully it will be cleared tomorrow.

Clicking into the uBo options menu then clears the open connection

Maybe the solution can work but this will need more testing. When you say
"uBo options menu", do you mean toggling the option "Prevent WebRTC from
leaking local IP addresses"
?


Reply to this email directly or view it on GitHub
#533 (comment).

@Eloston
Copy link

Eloston commented Dec 30, 2015

Using 1.5.1 on Chrome 41.0.2272.118, I went to chrome://webrtc-internals right after I launched the browser. It shows an entry there, but it dissapears after a few seconds. The fact that the user on the Web Store saw a persistent entry sounds like a browser bug.

So, I came up with a solution to work-around this problem. When the browser is compiled without WebRTC, passing in an empty object into the constructor will cause a DOMException (the same exception as passing in null). However, on a browser with WebRTC support, the empty object will cause a TypeError.

So here's the new solution:

try {
    var PC = self.RTCPeerConnection || self.webkitRTCPeerConnection;
    if ( PC ) {
        new PC(new Object());
    }
} catch (ex) {
    if ( ex instanceof DOMException && ex.name == 'NotSupportedError' ) {
        console.error(ex);
        break;
    }
}

With this change, no WebRTC connection will be created.

@gorhill
Copy link
Owner

gorhill commented Dec 31, 2015

If I use the dev console of a web page (the current one in my case), and call var pc = new webkitRTCPeerConnection({}); then pc.close(); then pc = null;, the connection object still lingers in memory according to chrome://webrtc-internals/. I have to assume this workaround does not work, at least with Chromium 47:

var pc = new webkitRTCPeerConnection({});
pc.close();
pc = null;

a

@gorhill
Copy link
Owner

gorhill commented Dec 31, 2015

Well I suppose I could test whether WebRTC is supported from within a temporary iframe, which I expect would properly cleanup after itself when removed. This makes the code a bit more complicated but there is a good chance this could work.

The unused connection above disappears when I close the dev console in which it was created.

@gorhill gorhill reopened this Dec 31, 2015
@Eloston
Copy link

Eloston commented Dec 31, 2015

You're right. Testing for WebRTC support in a temporary iframe will make the WebRTC object get garbage collected when the iframe gets cleaned up.

Here's the code for the case 'webrtcIPAddress': statement that works for me (albeit a bit messy):

var rtc_iframe = document.createElement('iframe');
var rtc_js = "var PC = self.RTCPeerConnection || self.webkitRTCPeerConnection; var pc = null; try { pc = new PC(null); pc.close(); } catch (ex) { console.error(ex); }";
var rtc_blob = new Blob([rtc_js], { type: "application/javascript" });
var rtc_html = "<html><head><script src=\"" + URL.createObjectURL(rtc_blob) + "\"></script></head></html>";
document.head.appendChild(rtc_iframe);
rtc_iframe.contentWindow.document.open();
rtc_iframe.contentWindow.document.write(rtc_html);
rtc_iframe.contentWindow.document.close();
rtc_iframe.contentWindow.document.getElementsByTagName("script")[0].addEventListener("load", function() {
    if (!(rtc_iframe.contentWindow.pc instanceof rtc_iframe.contentWindow.PC)) {
        document.head.removeChild(rtc_iframe);
        return;
    };
    document.head.removeChild(rtc_iframe);

    // /~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);
        }
    }
});
break;

@gorhill
Copy link
Owner

gorhill commented Jan 4, 2016

I would like to have feedback about the latest fix, to confirm that ...

  • it does fix the crash for when chromium is compiled without WebRTC support.
  • it does not cause prevent the OS to go into sleep mode if Chrome is left opened.

Fix available in latest dev build.

@qbit
Copy link
Contributor

qbit commented Jan 4, 2016

1.5.3b2 solves the problem on OpenBSD, I can test some other platforms later today.

@uBlock-user
Copy link
Contributor

uBlock-user commented Apr 6, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants