From 72c930ddffc18de4d5cd6c59d945ba04ad0b323f Mon Sep 17 00:00:00 2001 From: gorhill Date: Sun, 24 May 2015 18:50:09 -0400 Subject: [PATCH] logger: UI work on URL-based dynamic filtering --- platform/chromium/vapi-background.js | 21 ++ src/css/common.css | 2 +- src/css/logger-ui.css | 244 +++++++++++++-------- src/js/background.js | 5 +- src/js/logger-ui.js | 132 +++++++---- src/js/messaging.js | 175 +++++++-------- src/js/pagestore.js | 12 +- src/js/popup.js | 7 +- src/js/{ => scriptlets}/cosmetic-logger.js | 4 +- src/js/{ => scriptlets}/cosmetic-off.js | 0 src/js/{ => scriptlets}/cosmetic-on.js | 0 src/js/{ => scriptlets}/cosmetic-survey.js | 4 +- src/js/{ => scriptlets}/element-picker.js | 7 + src/js/ublock.js | 24 +- src/logger-ui.html | 32 ++- 15 files changed, 428 insertions(+), 241 deletions(-) rename src/js/{ => scriptlets}/cosmetic-logger.js (96%) rename src/js/{ => scriptlets}/cosmetic-off.js (100%) rename src/js/{ => scriptlets}/cosmetic-on.js (100%) rename src/js/{ => scriptlets}/cosmetic-survey.js (96%) rename src/js/{ => scriptlets}/element-picker.js (99%) diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index 9c9f23106..9381cb84d 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -392,6 +392,27 @@ vAPI.tabs.reload = function(tabId /*, flags*/) { /******************************************************************************/ +// Select a specific tab. + +vAPI.tabs.select = function(tabId) { + tabId = toChromiumTabId(tabId); + if ( tabId === 0 ) { + return; + } + + chrome.tabs.update(tabId, { active: true }, function(tab) { + if ( chrome.runtime.lastError ) { + /* noop */ + } + if ( !tab ) { + return; + } + chrome.windows.update(tab.windowId, { focused: true }); + }); +}; + +/******************************************************************************/ + vAPI.tabs.injectScript = function(tabId, details, callback) { var onScriptExecuted = function() { // https://code.google.com/p/chromium/issues/detail?id=410868#c8 diff --git a/src/css/common.css b/src/css/common.css index f4ed7653a..31eec4550 100644 --- a/src/css/common.css +++ b/src/css/common.css @@ -10,7 +10,7 @@ font-style: normal; font-weight: normal; line-height: 1; - vertical-align: baseline; + vertical-align: middle; } body { background-color: white; diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css index cb0d6cd4c..7ad418de4 100644 --- a/src/css/logger-ui.css +++ b/src/css/logger-ui.css @@ -91,10 +91,10 @@ input:focus { width: 2.5em; } #content table > colgroup > col:nth-of-type(3) { - width: 2.5em; + width: 20%; } #content table > colgroup > col:nth-of-type(4) { - width: 20%; + width: 2.5em; } #content table > colgroup > col:nth-of-type(5) { width: 6em; @@ -102,7 +102,7 @@ input:focus { #content table > colgroup > col:nth-of-type(6) { width: calc(100% - 16em - 20%); } -body.f table tr.f { +body.f #content table tr.f { display: none; } @@ -115,6 +115,12 @@ body.f table tr.f { body.colorBlind #content tr.blocked { background-color: rgba(0, 19, 110, 0.1); } +#content tr.nooped { + background-color: rgba(108, 108, 108, 0.1); + } +body.colorBlind #content tr.nooped { + background-color: rgba(96, 96, 96, 0.1); + } #content tr.allowed { background-color: rgba(0, 160, 0, 0.1); } @@ -183,17 +189,17 @@ body:not(.popupOn) #content tr.canMtx td:nth-of-type(2) { body:not(.popupOn) #content tr.canMtx td:nth-of-type(2):hover { background: #ccc; } -#content tr.cat_net td:nth-of-type(3), -#content tr.cat_cosmetic td:nth-of-type(3) { +#content tr.cat_net td:nth-of-type(4), +#content tr.cat_cosmetic td:nth-of-type(4) { font: 12px monospace; text-align: center; white-space: nowrap; } -#content tr.cat_net td:nth-of-type(3) { +#content tr.cat_net td:nth-of-type(4) { cursor: pointer; position: relative; } -#content tr.cat_net td:nth-of-type(3):hover { +#content tr.cat_net td:nth-of-type(4):hover { background: #ccc; } #content tr.cat_net td:nth-of-type(6) > span > b { @@ -208,6 +214,12 @@ body:not(.popupOn) #content tr.canMtx td:nth-of-type(2):hover { body.colorBlind #content tr.blocked td:nth-of-type(6) b { background-color: rgba(0, 19, 110, 0.2); } +#content tr.nooped td:nth-of-type(6) b { + background-color: rgba(108, 108, 108, 0.2); + } +body.colorBlind #content tr.nooped td:nth-of-type(6) b { + background-color: rgba(96, 96, 96, 0.2); + } #content tr.allowed td:nth-of-type(6) b { background-color: rgba(0, 160, 0, 0.2); } @@ -272,107 +284,125 @@ body[dir="rtl"] #popupContainer > div { position: fixed; right: 0; top: 0; - z-index: 100; + z-index: 400; } #urlFilteringMenu .dialog { background-color: white; - border: 1px solid gray; - max-width: 70%; - padding: 0.2em; - position: fixed; + border: 2px solid white; + left: 10%; + position: absolute; + top: 50%; + transform: translate(0, -50%); + transform-style: preserve-3d; + width: 80%; } -#urlFilteringMenu .dialog > div:first-child { - padding: 0.2em 0.2em 0.4em 0.2em; +#urlFilteringMenu .dialog table { + border: 0; + border-collapse: collapse; + table-layout: fixed; + width: 100%; } -#urlFilteringMenu .dialog > div:first-child > * { - display: inline-block; +#urlFilteringMenu .dialog table > colgroup > col:nth-of-type(1) { + width: 3.8em; + } +#urlFilteringMenu .dialog table > colgroup > col:nth-of-type(2) { + } + +#urlFilteringMenu .dialog td { + border: 0; vertical-align: middle; } -#urlFilteringMenu .save { +#urlFilteringMenu .dialog > table.toolbar td.preview { + /* http://lea.verou.me/css3patterns/ */ + background-color: #aaa; + background-image: + linear-gradient( + 45deg, + #666 25%, + transparent 25%, + transparent 75%, + #666 75%, + #666 + ), + linear-gradient( + 45deg, + #666 25%, + transparent 25%, + transparent 75%, + #666 75%, + #666 + ); + background-position:0 0, 9px 9px; + background-size: 18px 18px; + text-align: center; + } +#urlFilteringMenu .dialog > table.toolbar td.preview > * { + max-width: 100%; + max-height: 40vh; + } +#urlFilteringMenu .dialog > table.toolbar select { + font: 14px; + height: 1.8em; + } +#urlFilteringMenu .dialog > table.toolbar .fa { + cursor: pointer; + font-size: 1.2em; + text-align: center; + } +#urlFilteringMenu .dialog > table.toolbar .fa.save { background-color: #ffe; border: 1px solid #ddc; border-radius: 4px; color: #888; - cursor: pointer; font-size: 1.8em; - margin-right: 0.1em; - padding: 0.1em 0.5em; + margin: 0.1em; + padding: 0.25em 0.5em; visibility: hidden; } -body.dirty #urlFilteringMenu .save { +body.dirty #urlFilteringMenu .dialog > table.toolbar .fa.save { visibility: visible; } -#urlFilteringMenu .save:hover { +#urlFilteringMenu .dialog > table.toolbar .fa.save:hover { color: black; } -#urlFilteringMenu select { - font: inherit; +#urlFilteringMenu .dialog > table.toolbar tr.entry { + display: none; } -#urlFilteringMenu .entries { - font-size: 13px; - max-height: 12em; +#urlFilteringMenu .dialog > div.entries { + max-height: 30vh; + overflow: hidden; overflow-y: auto; } -#urlFilteringMenu .entries > div { +#urlFilteringMenu .dialog > div.header { + background-color: #666; + color: white; + font-size: smaller; + padding: 2px; + text-align: center; + } +#urlFilteringMenu .dialog > div.entries tr.entry { background-color: #e6e6e6; border: 0; - line-height: 2em; - margin: 0; - margin-top: 1px; - overflow: hidden; - padding: 0; - white-space: nowrap; - width: 100%; + border-bottom: 1px solid white; + font-size: 13px; } -#urlFilteringMenu .entries > div:first-child { - margin-top: 0; - } -#urlFilteringMenu .entries > div:hover { +#urlFilteringMenu .dialog > div.entries tr.entry:hover { background-color: #f0f0f0; } -#urlFilteringMenu .entries > div > .action { - background-color: transparent; +#urlFilteringMenu .dialog > div.entries tr.entry > td:first-of-type { border: 0; border-right: 1px solid white; + padding: 0; + text-align: center; + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action { + background-color: transparent; + border: 0; cursor: pointer; - display: inline-block; - height: 100%; - width: 3.8em; + height: 2em; + width: 100%; } -#urlFilteringMenu .entries > div > .action.allow { - background-color: rgba(0, 160, 0, 0.3); - } -body.colorBlind #urlFilteringMenu .entries > div > .action.allow { - background-color: rgba(255, 194, 57, 0.4); - } -#urlFilteringMenu .entries > div > .action.noop { - background-color: rgba(108, 108, 108, 0.3); - } -body.colorBlind #urlFilteringMenu .entries > div > .action.noop { - background-color: rgba(96, 96, 96, 0.4); - } -#urlFilteringMenu .entries > div > .action.block { - background-color: rgba(192, 0, 0, 0.3); - } -body.colorBlind #urlFilteringMenu .entries > div > .action.block { - background-color: rgba(0, 19, 110, 0.4); - } -#urlFilteringMenu .entries > div > .action.allow.own { - background-color: rgba(0, 160, 0, 1); - } -body.colorBlind #urlFilteringMenu .entries > div > .action.allow.own { - background-color: rgba(255, 194, 57, 1); - } -#urlFilteringMenu .entries > div > .action.noop.own { - background-color: rgba(108, 108, 108, 1); - } -#urlFilteringMenu .entries > div > .action.block.own { - background-color: rgba(192, 0, 0, 1); - } -body.colorBlind #urlFilteringMenu .entries > div > .action.block.own { - background-color: rgba(0, 19, 110, 1); - } -#urlFilteringMenu .entries > div > .action > span { +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action > span { background-color: transparent; border: 0; display: inline-block; @@ -381,31 +411,67 @@ body.colorBlind #urlFilteringMenu .entries > div > .action.block.own { visibility: hidden; width: 33.33%; } -#urlFilteringMenu .entries > div > .action > span:before { - content: '\00A0'; +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.allow { + background-color: rgba(0, 160, 0, 0.3); } -#urlFilteringMenu .entries > div > .action:not(.own):hover > span { +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.allow { + background-color: rgba(255, 194, 57, 0.4); + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.noop { + background-color: rgba(108, 108, 108, 0.3); + } +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.noop { + background-color: rgba(96, 96, 96, 0.4); + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.block { + background-color: rgba(192, 0, 0, 0.3); + } +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.block { + background-color: rgba(0, 19, 110, 0.4); + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.own.allow { + background-color: rgba(0, 160, 0, 1); + } +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.own.allow { + background-color: rgba(255, 194, 57, 1); + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.own.noop { + background-color: rgba(108, 108, 108, 1); + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.own.block { + background-color: rgba(192, 0, 0, 1); + } +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action.own.block { + background-color: rgba(0, 19, 110, 1); + } +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action:not(.own):hover > span { opacity: 0.2; visibility: visible; } -#urlFilteringMenu .entries > div > .action:not(.own):hover > span:hover { +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action:not(.own):hover > span:hover { opacity: 0.75; } -#urlFilteringMenu .entries > div > .action > .allow { +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action > span.allow { background-color: rgb(0, 160, 0); } -body.colorBlind #urlFilteringMenu .entries > div > .action > .allow { +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action > span.allow { background-color: rgb(255, 194, 57); } -#urlFilteringMenu .entries > div > .action > .noop { +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action > span.noop { background-color: rgb(108, 108, 108); } -#urlFilteringMenu .entries > div > .action > .block { +#urlFilteringMenu .dialog > div.entries tr.entry > td > div.action > span.block { background-color: rgb(192, 0, 0); } -body.colorBlind #urlFilteringMenu .entries > div > .action > .block { +body.colorBlind #urlFilteringMenu .dialog > div.entries tr.entry > td > div.action > span.block { background-color: rgb(0, 19, 110); } -#urlFilteringMenu .entries > div > .url { - padding: 0 0.25em; +#urlFilteringMenu .dialog > div.entries tr.entry > td.url { + overflow: hidden; + padding-left: 4px; + text-overflow: ellipsis; + white-space: nowrap; + } +.hide { + display: none; } diff --git a/src/js/background.js b/src/js/background.js index 30f419e03..30539c3bc 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -144,13 +144,14 @@ return { noopFunc: function(){}, apiErrorCount: 0, - contextMenuTarget: '', contextMenuClientX: -1, contextMenuClientY: -1, - epickerTarget: '', epickerEprom: null, + scriptlets: { + }, + // so that I don't have to care for last comma dummy: 0 }; diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js index c889537d1..a13e2928b 100644 --- a/src/js/logger-ui.js +++ b/src/js/logger-ui.js @@ -92,6 +92,16 @@ var classNameFromTabId = function(tabId) { /******************************************************************************/ +var tabIdFromClassName = function(className) { + var matches = className.match(/(?:^| )tab_([^ ]+)(?: |$)/); + if ( matches === null ) { + return ''; + } + return matches[1]; +}; + +/******************************************************************************/ + var retextFromStaticFilteringResult = function(result) { var retext = result.slice(3); var pos = retext.indexOf('$'); @@ -267,23 +277,26 @@ var renderNetLogEntry = function(tr, entry) { tr.classList.add(filterCat.slice(0, 2)); } - td = tr.cells[2]; + var filterText = filter.slice(3); + if ( filter.lastIndexOf('sa', 0) === 0 ) { + filterText = '@@' + filterText; + } + tr.cells[2].textContent = filterText; + + td = tr.cells[3]; if ( filter.charAt(1) === 'b' ) { tr.classList.add('blocked'); td.textContent = '--'; } else if ( filter.charAt(1) === 'a' ) { tr.classList.add('allowed'); td.textContent = '++'; + } else if ( filter.charAt(1) === 'n' ) { + tr.classList.add('nooped'); + td.textContent = '**'; } else { td.textContent = ''; } - var filterText = filter.slice(3); - if ( filter.lastIndexOf('sa', 0) === 0 ) { - filterText = '@@' + filterText; - } - - tr.cells[3].textContent = filterText; tr.cells[4].textContent = (prettyRequestTypes[type] || type); tr.cells[5].appendChild(nodeFromURL(url, filter)); }; @@ -540,14 +553,11 @@ var pageSelectorChanged = function() { var reloadTab = function() { var tabClass = document.getElementById('pageSelector').value; - var matches = tabClass.match(/^tab_(.+)$/); - if ( matches === null ) { + var tabId = tabIdFromClassName(tabClass); + if ( tabId === 'bts' || tabId === '' ) { return; } - if ( matches[1] === 'bts' ) { - return; - } - messager.send({ what: 'reloadTab', tabId: matches[1] }); + messager.send({ what: 'reloadTab', tabId: tabId }); }; /******************************************************************************/ @@ -577,11 +587,11 @@ var onMaxEntriesChanged = function() { var urlFilteringMenu = (function() { var menu = document.querySelector('#urlFilteringMenu'); - var menuDialog = menu.querySelector('.dialog'); - var selectContext = menuDialog.querySelector('.context'); - var selectType = menuDialog.querySelector('.type'); - var menuEntries = menu.querySelector('.entries'); + var dialog = menu.querySelector('.dialog'); + var selectContext = dialog.querySelector('.context'); + var selectType = dialog.querySelector('.type'); var menuURLs = []; + var tabId = ''; var removeAllChildren = function(node) { while ( node.firstChild ) { @@ -603,7 +613,7 @@ var urlFilteringMenu = (function() { continue; } colorEntry = colorEntries[url]; - node = menu.querySelector('.entries [data-url="' + url + '"]'); + node = menu.querySelector('.entry .action[data-url="' + url + '"]'); if ( node === null ) { continue; } @@ -698,6 +708,45 @@ var urlFilteringMenu = (function() { }, colorize); return; } + + // Force a reload of the tab + if ( target.classList.contains('reload') ) { + messager.send({ + what: 'reloadTab', + tabId: tabId + }); + return; + } + + // Hightlight corresponding element in target web page + if ( target.classList.contains('picker') ) { + messager.send({ + what: 'launchElementPicker', + tabId: tabId, + targetURL: 'img\t' + menuURLs[0], + select: true + }); + return; + } + }; + + // Enable interactive tools if resource was not blocked + var createPreviewIf = function(type, url) { + var preview = null; + + if ( type === 'image' ) { + preview = document.createElement('img'); + preview.setAttribute('src', url); + } + + // More... + + var container = dialog.querySelector('table.toolbar td.preview'); + container.classList.toggle('hide', preview === null); + if ( preview === null ) { + return; + } + container.appendChild(preview); }; var toggleOn = function(ev) { @@ -715,6 +764,8 @@ var urlFilteringMenu = (function() { return; } + tabId = tabIdFromClassName(tr.className); + var pos, option; // Fill context selector @@ -747,9 +798,14 @@ var urlFilteringMenu = (function() { return; } + uDom(dialog).descendants('.picker').toggleClass( + 'hide', + type !== 'image' || /(?:^| )[dlsu]b(?: |$)/.test(tr.className) + ); + // Shortest URL which for a valid URL filtering rule var candidateRootURL = matches[1] + matches[2]; - menuURLs.push(candidateRootURL); + menuURLs.unshift(candidateRootURL); var candidatePath = matches[3] || ''; pos = candidatePath.charAt(0) === '/' ? 1 : 0; while ( pos < candidatePath.length ) { @@ -757,34 +813,33 @@ var urlFilteringMenu = (function() { if ( pos === -1 ) { pos = candidatePath.length; } - menuURLs.push(candidateRootURL + candidatePath.slice(0, pos)); + menuURLs.unshift(candidateRootURL + candidatePath.slice(0, pos)); } var candidateQuery = matches[4] || ''; if ( candidateQuery !== '') { - menuURLs.push(candidateRootURL + candidatePath + candidateQuery); + menuURLs.unshift(candidateRootURL + candidatePath + candidateQuery); } + // Create preview whenever possible + createPreviewIf(type, menuURLs[0]); + // Fill menu - var menuEntryTemplate = document.querySelector('#templates .urlFilteringMenuEntry'); + var menuEntryTemplate = dialog.querySelector('table.toolbar tr.entry'); + var tbody = dialog.querySelector('div.entries tbody'); // Adding URL filtering rules - var i = menuURLs.length; var url, menuEntry; - while ( i-- ) { + for ( var i = 0; i < menuURLs.length; i++ ) { url = menuURLs[i]; menuEntry = menuEntryTemplate.cloneNode(true); - menuEntry.children[0].setAttribute('data-url', url); - menuEntry.children[1].textContent = url; - menuEntries.appendChild(menuEntry); + menuEntry.cells[0].children[0].setAttribute('data-url', url); + menuEntry.cells[1].textContent = url; + tbody.appendChild(menuEntry); } colorize(); - var rect = td.getBoundingClientRect(); - menuDialog.style.setProperty('left', rect.left + 'px'); - menuDialog.style.setProperty('top', rect.bottom + 'px'); document.body.appendChild(menu); - menu.addEventListener('click', onClick, true); selectContext.addEventListener('change', colorize); selectType.addEventListener('change', colorize); @@ -794,7 +849,8 @@ var urlFilteringMenu = (function() { if ( menu.parentNode === null ) { return; } - removeAllChildren(menuEntries); + uDom('table.toolbar td.preview > *').remove(); + uDom(dialog).descendants('div.entries tr').remove(); selectContext.removeEventListener('change', colorize); selectType.removeEventListener('change', colorize); menu.removeEventListener('click', onClick, true); @@ -845,8 +901,7 @@ var rowFilterer = (function() { continue; } // https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions - reStr = rawPart.replace(/[.+?^${}()|[\]\\]/g, '\\$&') - .replace(/\*/g, '.*'); + reStr = rawPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); if ( hardBeg ) { reStr = '(?:^|\\s)' + reStr; } @@ -1003,7 +1058,7 @@ var popupManager = (function() { var popupObserver = null; var style = null; var styleTemplate = [ - 'tr:not(.tab_{{tabId}}) {', + '#content tr:not(.tab_{{tabId}}) {', 'cursor: not-allowed;', 'opacity: 0.2;', '}' @@ -1036,11 +1091,10 @@ var popupManager = (function() { var toggleOn = function(td) { var tr = td.parentNode; - var matches = tr.className.match(/(?:^| )tab_([^ ]+)/); - if ( matches === null ) { + realTabId = localTabId = tabIdFromClassName(tr.className); + if ( realTabId === '' ) { return; } - realTabId = localTabId = matches[1]; if ( localTabId === 'bts' ) { realTabId = noTabId; } @@ -1115,7 +1169,7 @@ uDom.onLoad(function() { uDom('#clear').on('click', clearBuffer); uDom('#maxEntries').on('change', onMaxEntriesChanged); uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn); - uDom('#content').on('click', 'tr.cat_net > td:nth-of-type(3)', urlFilteringMenu.toggleOn); + uDom('#content').on('click', 'tr.cat_net > td:nth-of-type(4)', urlFilteringMenu.toggleOn); }); /******************************************************************************/ diff --git a/src/js/messaging.js b/src/js/messaging.js index 0dc9af7d7..f9c050d5a 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -83,10 +83,20 @@ var onMessage = function(request, sender, callback) { response = µb.userSettings; break; + case 'launchElementPicker': + // Launched from some auxiliary pages, clear context menu coords. + µb.contextMenuClientX = µb.contextMenuClientY = -1; + µb.elementPickerExec(request.tabId, request.targetURL); + break; + case 'gotoURL': vAPI.tabs.open(request.details); break; + case 'scriptletGotoImageURL': + µb.scriptletGotoImageURL(request); + break; + case 'reloadTab': if ( vAPI.isBehindTheSceneTabId(request.tabId) === false ) { vAPI.tabs.reload(request.tabId); @@ -322,16 +332,6 @@ var onMessage = function(request, sender, callback) { var response; switch ( request.what ) { - case 'gotoPick': - // Picker launched from popup: clear context menu args - µb.contextMenuClientX = -1; - µb.contextMenuClientY = -1; - µb.elementPickerExec(request.tabId); - if ( request.select && vAPI.tabs.select ) { - vAPI.tabs.select(request.tabId); - } - break; - case 'hasPopupContentChanged': pageStore = µb.pageStoreFromTabId(request.tabId); var lastModified = pageStore ? pageStore.contentLastModified : 0; @@ -542,80 +542,6 @@ vAPI.messaging.listen('contentscript-end.js', onMessage); /******************************************************************************/ /******************************************************************************/ -// cosmetic-*.js - -(function() { - -'use strict'; - -/******************************************************************************/ - -var µb = µBlock; - -/******************************************************************************/ - -var logCosmeticFilters = function(tabId, details) { - if ( µb.logger.isEnabled() === false ) { - return; - } - - var selectors = details.matchedSelectors; - - selectors.sort(); - - for ( var i = 0; i < selectors.length; i++ ) { - µb.logger.writeOne( - tabId, - 'cosmetic', - 'cb:##' + selectors[i], - 'dom', - details.pageURL - ); - } -}; - -/******************************************************************************/ - -var onMessage = function(request, sender, callback) { - // Async - switch ( request.what ) { - default: - break; - } - - // Sync - var response; - - var tabId = sender && sender.tab ? sender.tab.id : 0; - - switch ( request.what ) { - case 'liveCosmeticFilteringData': - var pageStore = µb.pageStoreFromTabId(tabId); - if ( pageStore ) { - pageStore.hiddenElementCount = request.filteredElementCount; - } - break; - - case 'logCosmeticFilteringData': - logCosmeticFilters(tabId, request); - break; - - default: - return vAPI.messaging.UNHANDLED; - } - - callback(response); -}; - -vAPI.messaging.listen('cosmetic-*.js', onMessage); - -/******************************************************************************/ - -})(); - -/******************************************************************************/ -/******************************************************************************/ - // element-picker.js (function() { @@ -654,13 +580,13 @@ var onMessage = function(request, sender, callback) { callback({ frameContent: this.responseText.replace(reStrings, replacer), - target: µb.contextMenuTarget, + target: µb.epickerTarget, clientX: µb.contextMenuClientX, clientY: µb.contextMenuClientY, eprom: µb.epickerEprom }); - µb.contextMenuTarget = ''; + µb.epickerTarget = ''; µb.contextMenuClientX = -1; µb.contextMenuClientY = -1; }; @@ -1363,3 +1289,80 @@ vAPI.messaging.listen('document-blocked.js', onMessage); })(); /******************************************************************************/ +/******************************************************************************/ + +// scriptlets + +(function() { + +'use strict'; + +/******************************************************************************/ + +var µb = µBlock; + +/******************************************************************************/ + +var logCosmeticFilters = function(tabId, details) { + if ( µb.logger.isEnabled() === false ) { + return; + } + + var selectors = details.matchedSelectors; + + selectors.sort(); + + for ( var i = 0; i < selectors.length; i++ ) { + µb.logger.writeOne( + tabId, + 'cosmetic', + 'cb:##' + selectors[i], + 'dom', + details.pageURL + ); + } +}; + +/******************************************************************************/ + +var onMessage = function(request, sender, callback) { + // Async + switch ( request.what ) { + default: + break; + } + + // Sync + var response; + var tabId = sender && sender.tab ? sender.tab.id : 0; + + switch ( request.what ) { + case 'gotoImageURL': + response = µb.scriptlets.gotoImageURL; + break; + + case 'liveCosmeticFilteringData': + var pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore ) { + pageStore.hiddenElementCount = request.filteredElementCount; + } + break; + + case 'logCosmeticFilteringData': + logCosmeticFilters(tabId, request); + break; + + default: + return vAPI.messaging.UNHANDLED; + } + + callback(response); +}; + +vAPI.messaging.listen('scriptlets', onMessage); + +/******************************************************************************/ + +})(); + +/******************************************************************************/ diff --git a/src/js/pagestore.js b/src/js/pagestore.js index 0d19baa58..5bc93fda2 100644 --- a/src/js/pagestore.js +++ b/src/js/pagestore.js @@ -508,12 +508,14 @@ PageStore.prototype.filterRequest = function(context) { // evaluation of static filtering. if ( result === '' && µb.userSettings.advancedUserEnabled ) { µb.sessionFirewall.evaluateCellZY( context.rootHostname, context.requestHostname, context.requestType); - result = µb.sessionFirewall.toFilterString(); + if ( µb.sessionFirewall.mustBlockOrAllow() ) { + result = µb.sessionFirewall.toFilterString(); + } } // Static filtering never override dynamic filtering if ( result === '' || result.charAt(1) === 'n' ) { - result = µb.staticNetFilteringEngine.matchString(context); + result = µb.staticNetFilteringEngine.matchString(context) || result; } //console.debug('cache MISS: PageStore.filterRequest("%s")', context.requestURL); @@ -546,12 +548,14 @@ PageStore.prototype.filterRequestNoCache = function(context) { // evaluation of static filtering. if ( result === '' && µb.userSettings.advancedUserEnabled ) { µb.sessionFirewall.evaluateCellZY(context.rootHostname, context.requestHostname, context.requestType); - result = µb.sessionFirewall.toFilterString(); + if ( µb.sessionFirewall.mustBlockOrAllow() ) { + result = µb.sessionFirewall.toFilterString(); + } } // Static filtering never override dynamic filtering if ( result === '' || result.charAt(1) === 'n' ) { - result = µb.staticNetFilteringEngine.matchString(context); + result = µb.staticNetFilteringEngine.matchString(context) || result; } return result; diff --git a/src/js/popup.js b/src/js/popup.js index 7046841f2..a46287eec 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -504,10 +504,9 @@ var toggleNetFilteringSwitch = function(ev) { var gotoPick = function() { messager.send({ - what: 'gotoPick', - tabId: popupData.tabId, - select: true -}); + what: 'launchElementPicker', + tabId: popupData.tabId + }); vAPI.closePopup(); }; diff --git a/src/js/cosmetic-logger.js b/src/js/scriptlets/cosmetic-logger.js similarity index 96% rename from src/js/cosmetic-logger.js rename to src/js/scriptlets/cosmetic-logger.js index d038d1af6..62f6b29a5 100644 --- a/src/js/cosmetic-logger.js +++ b/src/js/scriptlets/cosmetic-logger.js @@ -36,7 +36,7 @@ if ( document instanceof HTMLDocument === false ) { } // This can happen -if ( !vAPI ) { +if ( typeof vAPI !== 'object' ) { //console.debug('cosmetic-logger.js > vAPI not found'); return; } @@ -79,7 +79,7 @@ vAPI.loggedSelectors = loggedSelectors; /******************************************************************************/ -var localMessager = vAPI.messaging.channel('cosmetic-*.js'); +var localMessager = vAPI.messaging.channel('scriptlets'); localMessager.send({ what: 'logCosmeticFilteringData', diff --git a/src/js/cosmetic-off.js b/src/js/scriptlets/cosmetic-off.js similarity index 100% rename from src/js/cosmetic-off.js rename to src/js/scriptlets/cosmetic-off.js diff --git a/src/js/cosmetic-on.js b/src/js/scriptlets/cosmetic-on.js similarity index 100% rename from src/js/cosmetic-on.js rename to src/js/scriptlets/cosmetic-on.js diff --git a/src/js/cosmetic-survey.js b/src/js/scriptlets/cosmetic-survey.js similarity index 96% rename from src/js/cosmetic-survey.js rename to src/js/scriptlets/cosmetic-survey.js index 532bf9b65..f3e0890f8 100644 --- a/src/js/cosmetic-survey.js +++ b/src/js/scriptlets/cosmetic-survey.js @@ -36,7 +36,7 @@ if ( document instanceof HTMLDocument === false ) { } // This can happen -if ( !vAPI ) { +if ( typeof vAPI !== 'object' ) { //console.debug('cosmetic-survey.js > vAPI not found'); return; } @@ -63,7 +63,7 @@ if ( injectedSelectors.length !== 0 ) { /******************************************************************************/ -var localMessager = vAPI.messaging.channel('cosmetic-*.js'); +var localMessager = vAPI.messaging.channel('scriptlets'); localMessager.send({ what: 'liveCosmeticFilteringData', diff --git a/src/js/element-picker.js b/src/js/scriptlets/element-picker.js similarity index 99% rename from src/js/element-picker.js rename to src/js/scriptlets/element-picker.js index 46d0bee65..bb77b0c0e 100644 --- a/src/js/element-picker.js +++ b/src/js/scriptlets/element-picker.js @@ -917,10 +917,17 @@ var startPicker = function(details) { if ( src !== url ) { continue; } + elem.scrollIntoView({ + behavior: 'smooth', + block: 'start' + }); filtersFromElement(elem); showDialog({ modifier: true }); return; } + + // A target was specified, but it wasn't found: abort. + stopPicker(); }; /******************************************************************************/ diff --git a/src/js/ublock.js b/src/js/ublock.js index 053c9391f..e501d707b 100644 --- a/src/js/ublock.js +++ b/src/js/ublock.js @@ -283,8 +283,14 @@ var matchWhitelistDirective = function(url, hostname, directive) { /******************************************************************************/ µBlock.elementPickerExec = function(tabId, targetElement) { + if ( vAPI.isBehindTheSceneTabId(tabId) ) { + return; + } this.epickerTarget = targetElement || ''; - vAPI.tabs.injectScript(tabId, { file: 'js/element-picker.js' }); + vAPI.tabs.injectScript(tabId, { file: 'js/scriptlets/element-picker.js' }); + if ( typeof vAPI.tabs.select === 'function' ) { + vAPI.tabs.select(tabId); + } }; /******************************************************************************/ @@ -364,7 +370,7 @@ var matchWhitelistDirective = function(url, hostname, directive) { // Take action if needed if ( details.name === 'no-cosmetic-filtering' ) { vAPI.tabs.injectScript(details.tabId, { - file: 'js/cosmetic-' + (details.state ? 'off' : 'on') + '.js', + file: 'js/scriptlets/cosmetic-' + (details.state ? 'off' : 'on') + '.js', allFrames: true }); return; @@ -382,7 +388,7 @@ var matchWhitelistDirective = function(url, hostname, directive) { callback(); return; } - vAPI.tabs.injectScript(tabId, { file: 'js/cosmetic-survey.js' }, callback); + vAPI.tabs.injectScript(tabId, { file: 'js/scriptlets/cosmetic-survey.js' }, callback); }; /******************************************************************************/ @@ -392,7 +398,7 @@ var matchWhitelistDirective = function(url, hostname, directive) { var injectNow = function(tabId) { delete tabIdToTimerMap[tabId]; - vAPI.tabs.injectScript(tabId, { file: 'js/cosmetic-logger.js' }); + vAPI.tabs.injectScript(tabId, { file: 'js/scriptlets/cosmetic-logger.js' }); }; var injectAsync = function(tabId) { @@ -410,4 +416,14 @@ var matchWhitelistDirective = function(url, hostname, directive) { /******************************************************************************/ +µBlock.scriptletGotoImageURL = function(details) { + if ( vAPI.isBehindTheSceneTabId(details.tabId) ) { + return; + } + this.scriptlets.gotoImageURL = details.url; + vAPI.tabs.injectScript(details.tabId, { file: 'js/scriptlets/goto-img.js' }); +}; + +/******************************************************************************/ + })(); diff --git a/src/logger-ui.html b/src/logger-ui.html index 85cfe30cb..9db6201bb 100644 --- a/src/logger-ui.html +++ b/src/logger-ui.html @@ -26,8 +26,8 @@
- - + + @@ -43,15 +43,31 @@
-
- -   - +
+ + + + + + +
+
+   +   + +
   
+
+
+
Dynamic URL filtering
+
+ + + +
-
+
-