| Left: | ||
| Right: |
| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 | 21 |
| 22 const {defaultMatcher} = require("../adblockpluscore/lib/matcher"); | 22 const {defaultMatcher} = require("../adblockpluscore/lib/matcher"); |
| 23 const {RegExpFilter} = require("../adblockpluscore/lib/filterClasses"); | 23 const {RegExpFilter} = require("../adblockpluscore/lib/filterClasses"); |
| 24 const {filterNotifier} = require("../adblockpluscore/lib/filterNotifier"); | 24 const {filterNotifier} = require("../adblockpluscore/lib/filterNotifier"); |
| 25 const {Prefs} = require("./prefs"); | 25 const {Prefs} = require("./prefs"); |
| 26 const {extractHostFromFrame, isThirdParty} = require("./url"); | 26 const {extractHostFromFrame, isThirdParty} = require("./url"); |
| 27 const {getKey, checkWhitelisted} = require("./whitelisting"); | 27 const {getKey, checkWhitelisted} = require("./whitelisting"); |
| 28 const {port} = require("./messaging"); | 28 const {port} = require("./messaging"); |
| 29 const info = require("info"); | 29 const info = require("info"); |
| 30 | 30 |
| 31 let readyPages = new ext.PageMap(); | |
| 32 | |
| 33 /** | |
| 34 * Checks whether the given page is ready to use the filter composer | |
| 35 * | |
| 36 * @param {Page} page | |
| 37 * @return {boolean} | |
| 38 */ | |
| 39 exports.isPageReady = page => | |
|
kzar
2018/09/28 15:37:34
I coudln't see where `isPageReady` was being used
| |
| 40 { | |
| 41 return readyPages.has(page); | |
| 42 }; | |
| 43 | |
| 44 function isValidString(s) | 31 function isValidString(s) |
| 45 { | 32 { |
| 46 return s && s.indexOf("\0") == -1; | 33 return s && s.indexOf("\0") == -1; |
| 47 } | 34 } |
| 48 | 35 |
| 49 function escapeChar(chr) | 36 function escapeChar(chr) |
| 50 { | 37 { |
| 51 let code = chr.charCodeAt(0); | 38 let code = chr.charCodeAt(0); |
| 52 | 39 |
| 53 // Control characters and leading digits must be escaped based on | 40 // Control characters and leading digits must be escaped based on |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 | 144 |
| 158 // Add an element hiding filter for each generated CSS selector | 145 // Add an element hiding filter for each generated CSS selector |
| 159 for (let selector of selectors) | 146 for (let selector of selectors) |
| 160 filters.push(docDomain.replace(/^www\./, "") + "##" + selector); | 147 filters.push(docDomain.replace(/^www\./, "") + "##" + selector); |
| 161 } | 148 } |
| 162 } | 149 } |
| 163 | 150 |
| 164 return {filters, selectors}; | 151 return {filters, selectors}; |
| 165 } | 152 } |
| 166 | 153 |
| 167 let contextMenuItem = { | |
| 168 title: browser.i18n.getMessage("block_element"), | |
| 169 contexts: ["image", "video", "audio"], | |
| 170 onclick(page) | |
| 171 { | |
| 172 page.sendMessage({type: "composer.content.contextMenuClicked"}); | |
| 173 } | |
| 174 }; | |
| 175 | |
| 176 function updateContextMenu(page, filter) | |
| 177 { | |
| 178 page.contextMenus.remove(contextMenuItem); | |
| 179 | |
| 180 if (typeof filter == "undefined") | |
| 181 filter = checkWhitelisted(page); | |
| 182 | |
| 183 // We don't support the filter composer on Firefox for Android, because the | |
| 184 // user experience on mobile is quite different. | |
| 185 if (info.application != "fennec" && | |
| 186 !filter && Prefs.shouldShowBlockElementMenu && readyPages.has(page)) | |
| 187 { | |
| 188 page.contextMenus.create(contextMenuItem); | |
| 189 } | |
| 190 } | |
| 191 | |
| 192 filterNotifier.on("page.WhitelistingStateRevalidate", updateContextMenu); | |
| 193 | |
| 194 Prefs.on("shouldShowBlockElementMenu", () => | |
| 195 { | |
| 196 browser.tabs.query({}, tabs => | |
| 197 { | |
| 198 for (let tab of tabs) | |
| 199 updateContextMenu(new ext.Page(tab)); | |
| 200 }); | |
| 201 }); | |
| 202 | |
| 203 port.on("composer.isPageReady", (message, sender) => | |
| 204 { | |
| 205 return readyPages.has(new ext.Page({id: message.pageId})); | |
| 206 }); | |
| 207 | |
| 208 port.on("composer.ready", (message, sender) => | |
| 209 { | |
| 210 readyPages.set(sender.page, null); | |
| 211 updateContextMenu(sender.page); | |
| 212 }); | |
| 213 | |
| 214 port.on("composer.openDialog", (message, sender) => | 154 port.on("composer.openDialog", (message, sender) => |
| 215 { | 155 { |
| 216 return browser.windows.create({ | 156 return browser.windows.create({ |
| 217 url: browser.extension.getURL("composer.html"), | 157 url: browser.extension.getURL("composer.html"), |
| 218 left: 50, | 158 left: 50, |
| 219 top: 50, | 159 top: 50, |
| 220 width: 420, | 160 width: 420, |
| 221 height: 200, | 161 height: 200, |
| 222 type: "popup" | 162 type: "popup" |
| 223 }).then(window => | 163 }).then(window => |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 // When tabs start loading we send them a message to ensure that the state | 271 // When tabs start loading we send them a message to ensure that the state |
| 332 // of the "block element" tool is reset. This is necessary since Firefox will | 272 // of the "block element" tool is reset. This is necessary since Firefox will |
| 333 // sometimes cache the state of a tab when the user navigates back / forward, | 273 // sometimes cache the state of a tab when the user navigates back / forward, |
| 334 // which includes the state of the "block element" tool. | 274 // which includes the state of the "block element" tool. |
| 335 // Since sending this message will often fail (e.g. for new tabs which have | 275 // Since sending this message will often fail (e.g. for new tabs which have |
| 336 // just been opened) we catch and ignore any exception thrown. | 276 // just been opened) we catch and ignore any exception thrown. |
| 337 browser.tabs.sendMessage( | 277 browser.tabs.sendMessage( |
| 338 page.id, {type: "composer.content.finished"} | 278 page.id, {type: "composer.content.finished"} |
| 339 ).catch(() => {}); | 279 ).catch(() => {}); |
| 340 }); | 280 }); |
| 281 | |
| 282 | |
| 283 /* Context menu and popup button */ | |
| 284 | |
| 285 let readyActivePages = new ext.PageMap(); | |
| 286 let showingContextMenu = false; | |
| 287 | |
| 288 function showOrHideContextMenu(activePage) | |
| 289 { | |
| 290 // Firefox for Android does not support browser.contextMenus. | |
| 291 // https://bugzilla.mozilla.org/show_bug.cgi?id=1269062 | |
| 292 if (!("contextMenus" in browser)) | |
| 293 return; | |
| 294 | |
| 295 let shouldShowContextMenu = Prefs.shouldShowBlockElementMenu && | |
| 296 readyActivePages.get(activePage); | |
| 297 | |
| 298 if (shouldShowContextMenu && !showingContextMenu) | |
|
kzar
2018/09/28 15:37:34
The previous logic wasn't great, I noticed it was
| |
| 299 { | |
| 300 browser.contextMenus.create({ | |
|
kzar
2018/09/28 15:37:34
I originally kept the `contextMenuItem` variable,
| |
| 301 id: "block_element", | |
| 302 title: browser.i18n.getMessage("block_element"), | |
| 303 contexts: ["image", "video", "audio"], | |
| 304 onclick(itemInfo, tab) | |
| 305 { | |
| 306 let page = new ext.Page(tab); | |
| 307 page.sendMessage({type: "composer.content.contextMenuClicked"}); | |
| 308 } | |
| 309 }); | |
| 310 showingContextMenu = true; | |
| 311 } | |
| 312 else if (!shouldShowContextMenu && showingContextMenu) | |
| 313 { | |
| 314 browser.contextMenus.remove("block_element"); | |
| 315 showingContextMenu = false; | |
| 316 } | |
| 317 } | |
| 318 | |
| 319 function updateContextMenu(updatedPage) | |
| 320 { | |
| 321 browser.tabs.query({active: true, lastFocusedWindow: true}).then(tabs => | |
| 322 { | |
| 323 if (tabs.length > 0 && (!updatedPage || updatedPage.id == tabs[0].id)) | |
| 324 showOrHideContextMenu(updatedPage || new ext.Page(tabs[0])); | |
| 325 }); | |
| 326 } | |
| 327 | |
| 328 browser.tabs.onActivated.addListener(activeInfo => | |
| 329 { | |
| 330 showOrHideContextMenu(new ext.Page({id: activeInfo.tabId})); | |
| 331 }); | |
| 332 | |
| 333 // Firefox for Android does not support browser.windows. | |
|
kzar
2018/09/28 15:37:34
Like we discussed, it's kind of pointless to worry
| |
| 334 // https://issues.adblockplus.org/ticket/5347 | |
| 335 if ("windows" in browser) | |
| 336 { | |
| 337 browser.windows.onFocusChanged.addListener(windowId => | |
| 338 { | |
| 339 if (windowId != browser.windows.WINDOW_ID_NONE) | |
| 340 updateContextMenu(); | |
| 341 }); | |
| 342 } | |
| 343 | |
| 344 filterNotifier.on("page.WhitelistingStateRevalidate", (page, filter) => | |
| 345 { | |
| 346 if (readyActivePages.has(page)) | |
| 347 { | |
| 348 readyActivePages.set(page, !filter); | |
| 349 updateContextMenu(page); | |
| 350 } | |
| 351 }); | |
| 352 | |
| 353 Prefs.on("shouldShowBlockElementMenu", () => | |
| 354 { | |
| 355 updateContextMenu(); | |
| 356 }); | |
| 357 | |
| 358 port.on("composer.isPageReady", (message, sender) => | |
| 359 { | |
| 360 return readyActivePages.has(new ext.Page({id: message.pageId})); | |
| 361 }); | |
| 362 | |
| 363 port.on("composer.ready", (message, sender) => | |
| 364 { | |
| 365 readyActivePages.set(sender.page, !checkWhitelisted(sender.page)); | |
| 366 updateContextMenu(sender.page); | |
| 367 }); | |
| OLD | NEW |