| Index: lib/abp2blocklist.js | 
| =================================================================== | 
| --- a/lib/abp2blocklist.js | 
| +++ b/lib/abp2blocklist.js | 
| @@ -137,17 +137,18 @@ | 
| function getURLSchemes(contentType) | 
| { | 
| // If the given content type includes all supported URL schemes, simply | 
| // return a single generic URL scheme pattern. This minimizes the size of the | 
| // generated rule set. The downside to this is that it will also match | 
| // schemes that we do not want to match (e.g. "ftp://"), but this can be | 
| // mitigated by adding exceptions for those schemes. | 
| - if (contentType & typeMap.WEBSOCKET && contentType & typeMap.WEBRTC && | 
| + if (contentType & typeMap.WEBSOCKET && | 
| + (!typeMap.WEBRTC || contentType & typeMap.WEBRTC) && | 
| contentType & httpRequestTypes) | 
| return ["[^:]+:(//)?"]; | 
| let urlSchemes = []; | 
| if (contentType & typeMap.WEBSOCKET) | 
| urlSchemes.push("wss?://"); | 
| @@ -414,17 +415,17 @@ | 
| // If WebSocket or WebRTC are given along with other options but not | 
| // including all three of WebSocket, WebRTC, and at least one HTTP raw type, | 
| // we must generate multiple rules. For example, for the filter | 
| // "foo$websocket,image", we must generate one rule with "^wss?://" and "raw" | 
| // and another rule with "^https?://" and "image". If we merge the two, we | 
| // end up blocking requests of all HTTP raw types (e.g. XMLHttpRequest) | 
| // inadvertently. | 
| if ((contentType & typeMap.WEBSOCKET && contentType != typeMap.WEBSOCKET && | 
| - !(contentType & typeMap.WEBRTC && | 
| + !((!typeMap.WEBRTC || contentType & typeMap.WEBRTC) && | 
| contentType & rawRequestTypes & httpRequestTypes)) || | 
| (contentType & typeMap.WEBRTC && contentType != typeMap.WEBRTC && | 
| !(contentType & typeMap.WEBSOCKET && | 
| contentType & rawRequestTypes & httpRequestTypes))) | 
| { | 
| if (contentType & typeMap.WEBSOCKET) | 
| { | 
| convertFilterAddRules(rules, filter, action, withResourceTypes, | 
| @@ -1225,19 +1226,21 @@ | 
| * Generate content blocker list for all filters that were added | 
| */ | 
| ContentBlockerList.prototype.generateRules = function() | 
| { | 
| let cssRules = []; | 
| let cssExceptionRules = []; | 
| let blockingRules = []; | 
| let blockingExceptionRules = []; | 
| + let urlSchemeExceptionRules = []; | 
| let ruleGroups = [cssRules, cssExceptionRules, | 
| - blockingRules, blockingExceptionRules]; | 
| + blockingRules, blockingExceptionRules, | 
| + urlSchemeExceptionRules]; | 
| let genericSelectors = []; | 
| let groupedElemhideFilters = new Map(); | 
| for (let filter of this.elemhideFilters) | 
| { | 
| let result = convertElemHideFilter(filter, this.elemhideSelectorExceptions); | 
| if (!result) | 
| @@ -1306,16 +1309,35 @@ | 
| } | 
| for (let filter of this.requestExceptions) | 
| { | 
| convertFilterAddRules(blockingExceptionRules, filter, | 
| "ignore-previous-rules", true); | 
| } | 
| + // If WebRTC is not supported, we still end up generating a lot of rules with | 
| + // a generic URL scheme pattern that covers WebRTC anyway. In order to avoid | 
| + // inadvertently blocking any WebRTC requests, we must add exceptions here | 
| + // for WebRTC URLs. This is not required when WebRTC is supported, because in | 
| + // that case we explicitly check if the filter covers WebRTC. | 
| + if (!typeMap.WEBRTC) | 
| + { | 
| + urlSchemeExceptionRules.push([ | 
| + { | 
| + trigger: {"url-filter": "^stuns?:"}, | 
| + action: {type: "ignore-previous-rules"} | 
| + }, | 
| + { | 
| + trigger: {"url-filter": "^turns?:"}, | 
| + action: {type: "ignore-previous-rules"} | 
| + } | 
| + ]); | 
| + } | 
| + | 
| return async(ruleGroups, (group, index) => () => | 
| { | 
| let next = () => | 
| { | 
| if (index == ruleGroups.length - 1) | 
| return ruleGroups.reduce((all, rules) => all.concat(rules), []); | 
| }; |