diff --git a/src/css/devtools.css b/src/css/devtools.css index c82e1f4a1..cc3d06149 100644 --- a/src/css/devtools.css +++ b/src/css/devtools.css @@ -3,6 +3,12 @@ body { overflow-y: hidden; padding: 0; } +button { + opacity: 0.25; + } +button:hover { + opacity: 0.75; + } #toolbar { background-color: #eee; border: none; @@ -28,7 +34,7 @@ body { vertical-align: middle; } #pageSelector { - max-width: 80%; + max-width: 70%; } #toolbar #refresh { margin-left: 4px; @@ -42,14 +48,56 @@ select { select option { max-width: 40em; } -#popupToggler { - opacity: 0.25; +#extras { + background-color: transparent; + border: 0; + margin: 0; + padding: 0; position: absolute; right: 0; } -body.popupEnabled #popupToggler { +#extras > span { + border: 0; + margin: 0; + padding: 0; + position: relative; + } +#extras > span > button { + margin-left: 0.2em; + } +#extras > span > div { + background-color: white; + border: 0; + display: none; + position: absolute; + right: 2px; + } +#extras > span > div > * { + border: 1px solid gray; + } +#extras > span > button.enabled { opacity: 1; } +#extras > span > button.enabled + div { + display: block; + } +#filterMatcher { + border: 0; + padding: 0.5em; + margin: 0; + } +#filteringResult { + background-color: #eee; + font-family: monospace; + } +#filteringResult.empty { + background-color: transparent; + } +#popup { + border: 0; + padding: 0; + margin: 0; + } #content { border: 0; box-sizing: border-box; @@ -60,13 +108,3 @@ body.popupEnabled #popupToggler { padding: 0; width: 100%; } -#popup { - border: 1px solid gray; - display: none; - position: fixed; - right: 2px; - top: calc(4em + 2px); - } -body.popupEnabled #popup[src^="popup.html"] { - display: initial; - } diff --git a/src/devtools.html b/src/devtools.html index 9f4832c0c..aebbff197 100644 --- a/src/devtools.html +++ b/src/devtools.html @@ -14,10 +14,31 @@
- + + + +
+
+


+ +


+ +


+ +


+   +

+
+
+ + +
+ +
+
+
- diff --git a/src/js/devtools.js b/src/js/devtools.js index 17a783a55..2e14efe0d 100644 --- a/src/js/devtools.js +++ b/src/js/devtools.js @@ -94,18 +94,65 @@ var selectPage = function() { /******************************************************************************/ -var togglePopup = function() { - var tabId = uDom('#pageSelector').val() || ''; - var body = uDom('body'); - body.toggleClass('popupEnabled'); - if ( body.hasClass('popupEnabled') === false ) { - tabId = ''; +var toggleTool = function() { + var button = uDom(this); + button.toggleClass('enabled', !button.hasClass('enabled')); + + // Special case: we want the frame of the popup to be filled-in if and + // only if the popup is visible. + if ( this.id === 'popupToggler' ) { + var tabId = uDom('#pageSelector').val() || ''; + var body = uDom('body'); + body.toggleClass('popupEnabled'); + if ( body.hasClass('popupEnabled') === false ) { + tabId = ''; + } + uDom('#popup').attr( + 'src', + button.hasClass('enabled') && tabId ? 'popup.html?tabId=' + tabId : '' + ); } - uDom('#popup').attr('src', tabId ? 'popup.html?tabId=' + tabId : ''); }; /******************************************************************************/ +var evaluateStaticFiltering = (function() { + var onResultReceived = function(response) { + var result = response && response.result.slice(3); + uDom('#filteringResult') + .text(result || '\u00A0') + .toggleClass('empty', result === ''); + + var input = uDom('#filterMatcher input').at(0); + if ( input.val().trim() === '' ) { + input.val(response && response.contextURL || ''); + } + }; + + var timer = null; + var onTimerElapsed = function() { + timer = null; + + var inputs = uDom('#filterMatcher input'); + + messager.send({ + what: 'evaluateStaticFiltering', + tabId: uDom('#pageSelector').val() || '', + contextURL: inputs.at(0).val().trim(), + requestURL: inputs.at(1).val().trim(), + requestType: inputs.at(2).val().trim(), + }, onResultReceived); + }; + + return function() { + if ( timer === null ) { + setTimeout(onTimerElapsed, 750); + } + }; +})(); + +/******************************************************************************/ + var resizePopup = function() { var popup = document.getElementById('popup'); popup.style.width = popup.contentWindow.document.body.clientWidth + 'px'; @@ -160,13 +207,14 @@ uDom.onLoad(function() { tabId = matches[1]; } - uDom('#popupToggler').on('click', togglePopup); + uDom('.toolToggler').on('click', toggleTool); uDom('#popup').on('load', onPopupLoaded); renderPageSelector(tabId); uDom('#pageSelector').on('change', pageSelectorChanged); - uDom('#refresh').on('click', function() { renderPageSelector(); } ); + uDom('#refresh').on('click', function() { renderPageSelector(); }); + uDom('#filterMatcher input').on('input', evaluateStaticFiltering); }); /******************************************************************************/ diff --git a/src/js/messaging.js b/src/js/messaging.js index 37ce13e0a..44b1a271f 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -1067,23 +1067,58 @@ var getPageDetails = function(callback) { /******************************************************************************/ +var evaluateStaticFiltering = function(details) { + // URL of context not provided, try to use the one for the given tab id. + var contextURL = details.contextURL; + if ( contextURL === '' ) { + var tabContext = µb.tabContextManager.lookup(details.tabId || 0); + if ( tabContext ) { + contextURL = tabContext.rawURL; + } + } + + var pageHostname = µb.URI.hostnameFromURI(contextURL); + var pageDomain = µb.URI.domainFromHostname(pageHostname); + + var context = { + rootHostname: pageHostname, + rootDomain: pageDomain, + pageHostname: pageHostname, + pageDomain: pageDomain, + requestURL: details.requestURL, + requestHostname: µb.URI.hostnameFromURI(details.requestURL), + requestType: details.requestType + }; + + return { + contextURL: contextURL, + result: µb.staticNetFilteringEngine.matchString(context) + }; +}; + +/******************************************************************************/ + var onMessage = function(request, sender, callback) { // Async switch ( request.what ) { - case 'getPageDetails': - getPageDetails(callback); - return; + case 'getPageDetails': + getPageDetails(callback); + return; - default: - break; + default: + break; } // Sync var response; switch ( request.what ) { - default: - return vAPI.messaging.UNHANDLED; + case 'evaluateStaticFiltering': + response = evaluateStaticFiltering(request); + break; + + default: + return vAPI.messaging.UNHANDLED; } callback(response);