| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 /* | 
|  | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
|  | 3  * Copyright (C) 2006-present eyeo GmbH | 
|  | 4  * | 
|  | 5  * Adblock Plus is free software: you can redistribute it and/or modify | 
|  | 6  * it under the terms of the GNU General Public License version 3 as | 
|  | 7  * published by the Free Software Foundation. | 
|  | 8  * | 
|  | 9  * Adblock Plus is distributed in the hope that it will be useful, | 
|  | 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 12  * GNU General Public License for more details. | 
|  | 13  * | 
|  | 14  * You should have received a copy of the GNU General Public License | 
|  | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|  | 16  */ | 
|  | 17 | 
|  | 18 /** @module hitLogger */ | 
|  | 19 | 
|  | 20 "use strict"; | 
|  | 21 | 
|  | 22 const {desc} = require("../adblockpluscore/lib/coreUtils"); | 
|  | 23 const {extractHostFromFrame} = require("./url"); | 
|  | 24 const {EventEmitter} = require("../adblockpluscore/lib/events"); | 
|  | 25 const {FilterStorage} = require("../adblockpluscore/lib/filterStorage"); | 
|  | 26 const {port} = require("./messaging"); | 
|  | 27 const {RegExpFilter, | 
|  | 28        ElemHideFilter} = require("../adblockpluscore/lib/filterClasses"); | 
|  | 29 | 
|  | 30 const nonRequestTypes = exports.nonRequestTypes = [ | 
|  | 31   "DOCUMENT", "ELEMHIDE", "GENERICBLOCK", "GENERICHIDE", "CSP" | 
|  | 32 ]; | 
|  | 33 | 
|  | 34 let HitLogger = exports.HitLogger = Object.create(new EventEmitter(), desc({ | 
|  | 35   off(tabId, listener) | 
|  | 36   { | 
|  | 37     Object.getPrototypeOf(this).off(tabId, listener); | 
|  | 38 | 
|  | 39     // EventEmitter leaves an empty array once the last listener for an event | 
|  | 40     // is removed. Usually that's fine, but in this case we need _listeners.size | 
|  | 41     // and _listeners.has to be accurate. | 
|  | 42     let listeners = this._listeners.get(tabId); | 
|  | 43     if (listeners && listeners.length == 0) | 
|  | 44       this._listeners.delete(tabId); | 
|  | 45   } | 
|  | 46 })); | 
|  | 47 | 
|  | 48 /** | 
|  | 49  * Checks whether a tab is inspected by anything. | 
|  | 50  * | 
|  | 51  * @param {number} tabId | 
|  | 52  * @return {boolean} | 
|  | 53  */ | 
|  | 54 let hasListener = exports.hasListener = function(tabId) | 
|  | 55 { | 
|  | 56   return HitLogger._listeners.has(tabId); | 
|  | 57 }; | 
|  | 58 | 
|  | 59 /** | 
|  | 60  * Logs a request associated with a tab or multiple tabs. | 
|  | 61  * | 
|  | 62  * @param {number[]} tabIds        The tabIds associated with the request | 
|  | 63  * @param {string}   url           The URL of the request | 
|  | 64  * @param {string}   type          The request type | 
|  | 65  * @param {string}   docDomain     The IDN-decoded hostname of the document | 
|  | 66  * @param {boolean}  thirdParty    Whether the origin of the request and | 
|  | 67  *                                 document differs | 
|  | 68  * @param {?string}  sitekey       The active sitekey if there is any | 
|  | 69  * @param {?boolean} specificOnly  Whether generic filters should be ignored | 
|  | 70  * @param {?BlockingFilter} filter The matched filter or null if there is no | 
|  | 71  *                                 match | 
|  | 72  */ | 
|  | 73 exports.logRequest = function(tabIds, url, type, docDomain, | 
|  | 74                               thirdParty, sitekey, | 
|  | 75                               specificOnly, filter) | 
|  | 76 { | 
|  | 77   for (let tabId of tabIds) | 
|  | 78   { | 
|  | 79     if (hasListener(tabId)) | 
|  | 80     { | 
|  | 81       let request = {url, type, docDomain, thirdParty, sitekey, specificOnly}; | 
|  | 82       HitLogger.emit(tabId, request, filter); | 
|  | 83     } | 
|  | 84   } | 
|  | 85 }; | 
|  | 86 | 
|  | 87 /** | 
|  | 88  * Logs active element hiding filters for a tab. | 
|  | 89  * | 
|  | 90  * @param {number}   tabId      The ID of the tab, the elements were hidden in | 
|  | 91  * @param {string[]} selectors  The selectors of applied ElemHideFilters | 
|  | 92  * @param {string[]} filters    The text of applied ElemHideEmulationFilters | 
|  | 93  * @param {string}   docDomain  The IDN-decoded hostname of the document | 
|  | 94  */ | 
|  | 95 function logHiddenElements(tabId, selectors, filters, docDomain) | 
|  | 96 { | 
|  | 97   if (hasListener(tabId)) | 
|  | 98   { | 
|  | 99     for (let subscription of FilterStorage.subscriptions) | 
|  | 100     { | 
|  | 101       if (subscription.disabled) | 
|  | 102         continue; | 
|  | 103 | 
|  | 104       for (let filter of subscription.filters) | 
|  | 105       { | 
|  | 106         // We only know the exact filter in case of element hiding emulation. | 
|  | 107         // For regular element hiding filters, the content script only knows | 
|  | 108         // the selector, so we have to find a filter that has an identical | 
|  | 109         // selector and is active on the domain the match was reported from. | 
|  | 110         let isActiveElemHideFilter = filter instanceof ElemHideFilter && | 
|  | 111                                      selectors.includes(filter.selector) && | 
|  | 112                                      filter.isActiveOnDomain(docDomain); | 
|  | 113 | 
|  | 114         if (isActiveElemHideFilter || filters.includes(filter.text)) | 
|  | 115           HitLogger.emit(tabId, {type: "ELEMHIDE", docDomain}, filter); | 
|  | 116       } | 
|  | 117     } | 
|  | 118   } | 
|  | 119 } | 
|  | 120 | 
|  | 121 /** | 
|  | 122  * Logs a whitelisting filter that disables (some kind of) | 
|  | 123  * blocking for a particular document. | 
|  | 124  * | 
|  | 125  * @param {number}       tabId     The tabId the whitelisting is active for | 
|  | 126  * @param {string}       url       The url of the whitelisted document | 
|  | 127  * @param {number}       typeMask  The bit mask of whitelisting types checked | 
|  | 128  *                                 for | 
|  | 129  * @param {string}       docDomain The IDN-decoded hostname of the parent | 
|  | 130  *                                 document | 
|  | 131  * @param {WhitelistFilter} filter The matched whitelisting filter | 
|  | 132  */ | 
|  | 133 exports.logWhitelistedDocument = function(tabId, url, typeMask, docDomain, | 
|  | 134                                           filter) | 
|  | 135 { | 
|  | 136   if (hasListener(tabId)) | 
|  | 137   { | 
|  | 138     for (let type of nonRequestTypes) | 
|  | 139     { | 
|  | 140       if (typeMask & filter.contentType & RegExpFilter.typeMap[type]) | 
|  | 141         HitLogger.emit(tabId, {url, type, docDomain}, filter); | 
|  | 142     } | 
|  | 143   } | 
|  | 144 }; | 
|  | 145 | 
|  | 146 port.on("hitLogger.traceElemHide", (message, sender) => | 
|  | 147 { | 
|  | 148   logHiddenElements( | 
|  | 149     sender.page.id, message.selectors, message.filters, | 
|  | 150     extractHostFromFrame(sender.frame) | 
|  | 151   ); | 
|  | 152 }); | 
| OLD | NEW | 
|---|