| Index: lib/filterComposer.js | 
| diff --git a/lib/filterComposer.js b/lib/filterComposer.js | 
| index 77d1fa8a38e66f4521e4c2a66288daf91429fdd1..cc108a17bae3da85391e1503578967d3b495f82a 100644 | 
| --- a/lib/filterComposer.js | 
| +++ b/lib/filterComposer.js | 
| @@ -40,7 +40,8 @@ exports.isPageReady = page => | 
| return readyPages.has(page); | 
| }; | 
|  | 
| -function isValidString(s) { | 
| +function isValidString(s) | 
| +{ | 
| return s && s.indexOf("\0") == -1; | 
| } | 
|  | 
| @@ -52,7 +53,7 @@ function escapeChar(chr) | 
| // their char code in CSS. Moreover, curly brackets aren't allowed | 
| // in elemhide filters, and therefore must be escaped based on their | 
| // char code as well. | 
| -  if (code <= 0x1F || code == 0x7F || /[\d\{\}]/.test(chr)) | 
| +  if (code <= 0x1F || code == 0x7F || /[\d{}]/.test(chr)) | 
| return "\\" + code.toString(16) + " "; | 
|  | 
| return "\\" + chr; | 
| @@ -60,7 +61,8 @@ function escapeChar(chr) | 
|  | 
| let escapeCSS = | 
| /** | 
| - * Escapes a token (e.g. tag, id, class or attribute) to be used in CSS selectors. | 
| + * Escapes a token (e.g. tag, id, class or attribute) to be used in | 
| + * CSS selectors. | 
| * | 
| * @param {string} s | 
| * @return {string} | 
| @@ -68,7 +70,7 @@ let escapeCSS = | 
| */ | 
| exports.escapeCSS = s => | 
| { | 
| -  return s.replace(/^[\d\-]|[^\w\-\u0080-\uFFFF]/g, escapeChar); | 
| +  return s.replace(/^[\d-]|[^\w\-\u0080-\uFFFF]/g, escapeChar); | 
| }; | 
|  | 
| let quoteCSS = | 
| @@ -81,22 +83,21 @@ let quoteCSS = | 
| */ | 
| exports.quoteCSS = value => | 
| { | 
| -  return '"' + value.replace(/["\\\{\}\x00-\x1F\x7F]/g, escapeChar) + '"'; | 
| +  return '"' + value.replace(/["\\{}\x00-\x1F\x7F]/g, escapeChar) + '"'; | 
| }; | 
|  | 
| function composeFilters(details) | 
| { | 
| +  let {page, frame} = details; | 
| let filters = []; | 
| let selectors = []; | 
|  | 
| -  let page = details.page; | 
| -  let frame = details.frame; | 
| - | 
| if (!checkWhitelisted(page, frame)) | 
| { | 
| let typeMask = RegExpFilter.typeMap[details.type]; | 
| let docDomain = extractHostFromFrame(frame); | 
| -    let specificOnly = checkWhitelisted(page, frame, RegExpFilter.typeMap.GENERICBLOCK); | 
| +    let specificOnly = checkWhitelisted(page, frame, | 
| +                                        RegExpFilter.typeMap.GENERICBLOCK); | 
|  | 
| // Add a blocking filter for each URL of the element that can be blocked | 
| for (let url of details.urls) | 
| @@ -112,7 +113,7 @@ function composeFilters(details) | 
|  | 
| if (!filter) | 
| { | 
| -        let filterText = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); | 
| +        let filterText = url.replace(/^[\w-]+:\/+(?:www\.)?/, "||"); | 
|  | 
| if (specificOnly) | 
| filterText += "$domain=" + docDomain; | 
| @@ -123,10 +124,11 @@ function composeFilters(details) | 
| } | 
|  | 
| // If we couldn't generate any blocking filters, fallback to element hiding | 
| -    let selectors = []; | 
| -    if (filters.length == 0 && !checkWhitelisted(page, frame, RegExpFilter.typeMap.ELEMHIDE)) | 
| +    if (filters.length == 0 && !checkWhitelisted(page, frame, | 
| +                                                 RegExpFilter.typeMap.ELEMHIDE)) | 
| { | 
| -      // Generate CSS selectors based on the element's "id" and "class" attribute | 
| +      // Generate CSS selectors based on the element's "id" and | 
| +      // "class" attribute. | 
| if (isValidString(details.id)) | 
| selectors.push("#" + escapeCSS(details.id)); | 
|  | 
| @@ -137,12 +139,22 @@ function composeFilters(details) | 
| // If there is a "src" attribute, specifiying a URL that we can't block, | 
| // generate a CSS selector matching the "src" attribute | 
| if (isValidString(details.src)) | 
| -        selectors.push(escapeCSS(details.tagName) + "[src=" + quoteCSS(details.src) + "]"); | 
| +      { | 
| +        selectors.push( | 
| +          escapeCSS(details.tagName) + "[src=" + quoteCSS(details.src) + "]" | 
| +        ); | 
| +      } | 
|  | 
| -      // As last resort, if there is a "style" attribute, and we couldn't generate | 
| -      // any filters so far, generate a CSS selector matching the "style" attribute | 
| -      if (isValidString(details.style) && selectors.length == 0 && filters.length == 0) | 
| -        selectors.push(escapeCSS(details.tagName) + "[style=" + quoteCSS(details.style) + "]"); | 
| +      // As last resort, if there is a "style" attribute, and we | 
| +      // couldn't generate any filters so far, generate a CSS selector | 
| +      // matching the "style" attribute | 
| +      if (isValidString(details.style) && selectors.length == 0 && | 
| +          filters.length == 0) | 
| +      { | 
| +        selectors.push( | 
| +          escapeCSS(details.tagName) + "[style=" + quoteCSS(details.style) + "]" | 
| +        ); | 
| +      } | 
|  | 
| // Add an element hiding filter for each generated CSS selector | 
| for (let selector of selectors) | 
| @@ -150,7 +162,7 @@ function composeFilters(details) | 
| } | 
| } | 
|  | 
| -  return {filters: filters, selectors: selectors}; | 
| +  return {filters, selectors}; | 
| } | 
|  | 
| let contextMenuItem = { | 
| @@ -225,15 +237,15 @@ port.on("composer.getFilters", (message, sender) => | 
| { | 
| return composeFilters({ | 
| tagName: message.tagName, | 
| -    id:      message.id, | 
| -    src:     message.src, | 
| -    style:   message.style, | 
| +    id: message.id, | 
| +    src: message.src, | 
| +    style: message.style, | 
| classes: message.classes, | 
| -    urls:    message.urls, | 
| -    type:    message.mediatype, | 
| +    urls: message.urls, | 
| +    type: message.mediatype, | 
| baseURL: message.baseURL, | 
| -    page:    sender.page, | 
| -    frame:   sender.frame | 
| +    page: sender.page, | 
| +    frame: sender.frame | 
| }); | 
| }); | 
|  | 
|  |