diff --git a/platform/firefox/vapi-background.js b/platform/firefox/vapi-background.js index 8446a1a0d..147ed66fb 100644 --- a/platform/firefox/vapi-background.js +++ b/platform/firefox/vapi-background.js @@ -1908,7 +1908,7 @@ var optionsObserver = { } this.setupOptionsButton(doc, 'showDashboardButton', 'dashboard.html'); - this.setupOptionsButton(doc, 'showNetworkLogButton', 'devtools.html'); + this.setupOptionsButton(doc, 'showNetworkLogButton', 'logger-ui.html'); } }; diff --git a/src/css/devtool-log.css b/src/css/devtool-log.css deleted file mode 100644 index 5f53a0b65..000000000 --- a/src/css/devtool-log.css +++ /dev/null @@ -1,130 +0,0 @@ -body { - border: 0; - box-sizing: border-box; - -moz-box-sizing: border-box; - margin: 0; - overflow-x: hidden; - padding: 0; - white-space: nowrap; - width: 100%; - } -#toolbar { - background-color: white; - border: 0; - box-sizing: border-box; - height: 40px; - left: 0; - margin: 0; - padding: 0 1em; - position: fixed; - top: 0; - width: 100%; - } -#toolbar .button { - background-color: white; - border: none; - box-sizing: border-box; - cursor: pointer; - display: inline-block; - font-size: 20px; - margin: 0; - padding: 8px; - } -#toolbar .button:hover { - background-color: #eee; - } -body.filterOff #toolbar #filterButton { - opacity: 0.25; - } -#filterExpression.bad { - background-color: #fee; - } -#maxEntries { - margin-left: 3em; - } -input:focus { - background-color: #ffe; - } -#content { - margin-top: 40px; - } -#content table { - border: 0; - border-collapse: collapse; - direction: ltr; - font: 12px monospace; - width: 100%; - } -#content table tr.docBoundary { - background-color: #666; - color: white; - text-align: center; - } -#content table tr.docBoundary > td:first-child { - padding: 1em 0; - white-space: normal; - word-break: break-all; - word-wrap: break-word; - } -#content table tr.blocked { - background-color: rgba(192, 0, 0, 0.1); - } -body.colorBlind #content table tr.blocked { - background-color: rgba(0, 19, 110, 0.1); - } -#content table tr.allowed { - background-color: rgba(0, 160, 0, 0.1); - } -body.colorBlind #content table tr.allowed { - background-color: rgba(255, 194, 57, 0.1) - } -#content table tr.maindoc { - } -#content table tr.cosmetic { - background-color: rgba(255, 255, 0, 0.1); - } -body:not(.filterOff) #content table tr.hidden { - display: none; - } -#content table tr td { - border: 1px solid #ccc; - padding: 3px; - vertical-align: top; - } -#content table tr td:nth-of-type(1) { - padding: 3px 0; - text-align: center; - white-space: pre; - width: 1em; - } -#content table tr td:nth-of-type(2) { - white-space: normal; - width: 25%; - word-break: break-all; - word-wrap: break-word; - } -#content table tr td:nth-of-type(3) { - white-space: nowrap; - } -#content table tr td:nth-of-type(4) { - border-right: none; - white-space: normal; - width: 60%; - word-break: break-all; - word-wrap: break-word; - } -#content table tr td:nth-of-type(4) b { - font-weight: normal; - } -#content table tr.blocked td:nth-of-type(4) b { - background-color: rgba(192, 0, 0, 0.2); - } -body.colorBlind #content table tr.blocked td:nth-of-type(4) b { - background-color: rgba(0, 19, 110, 0.2); - } -#content table tr.allowed td:nth-of-type(4) b { - background-color: rgba(0, 160, 0, 0.2); - } -body.colorBlind #content table tr.allowed td:nth-of-type(4) b { - background-color: rgba(255, 194, 57, 0.2); - } diff --git a/src/css/devtools.css b/src/css/devtools.css deleted file mode 100644 index cc3d06149..000000000 --- a/src/css/devtools.css +++ /dev/null @@ -1,110 +0,0 @@ -body { - margin: 0; - overflow-y: hidden; - padding: 0; - } -button { - opacity: 0.25; - } -button:hover { - opacity: 0.75; - } -#toolbar { - background-color: #eee; - border: none; - box-sizing: border-box; - -moz-box-sizing: border-box; - height: 4em; - padding: 1em; - position: fixed; - top: 0; - width: 100%; - } -#toolbar > * { - display: inline-block; - position: relative; - vertical-align: middle; - } -#toolbar button { - background-color: transparent; - border: none; - cursor: pointer; - font-size: 2em; - margin: 0 0 0 1em; - vertical-align: middle; - } -#pageSelector { - max-width: 70%; - } -#toolbar #refresh { - margin-left: 4px; - } -select { - padding: 2px 0; - font-size: 14px; - min-width: 20em; - max-width: 40em; - } -select option { - max-width: 40em; - } -#extras { - background-color: transparent; - border: 0; - margin: 0; - padding: 0; - position: absolute; - right: 0; - } -#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; - -moz-box-sizing: border-box; - height: calc(100vh - 4em); - margin-top: 4em; - overflow-y: auto; - padding: 0; - width: 100%; - } diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css new file mode 100644 index 000000000..080c211bc --- /dev/null +++ b/src/css/logger-ui.css @@ -0,0 +1,251 @@ +body { + background-color: white; + border: 0; + box-sizing: border-box; + color: black; + -moz-box-sizing: border-box; + margin: 0; + overflow-x: hidden; + padding: 0; + white-space: nowrap; + width: 100%; + } +#toolbar { + background-color: white; + border: 0; + box-sizing: border-box; + left: 0; + margin: 0; + padding: 0 1em; + position: fixed; + top: 0; + width: 100%; + z-index: 10; + } +#toolbar .button { + background-color: white; + border: none; + box-sizing: border-box; + cursor: pointer; + display: inline-block; + font-size: 20px; + margin: 0; + padding: 8px; + } +#toolbar .button.disabled { + opacity: 0.2; + pointer-events: none; + } +#toolbar .button:hover { + background-color: #eee; + } +body #compactViewToggler.button:before { + content: '\f102'; + } +body.compactView #compactViewToggler.button:before { + content: '\f103'; + } +#filterButton { + opacity: 0.25; + } +body.f #filterButton { + opacity: 1; + } +#filterInput.bad { + background-color: #fee; + } +#maxEntries { + margin-left: 3em; + } +input:focus { + background-color: #ffe; + } +#content { + font: 13px sans-serif; + margin-top: 3.5em; + width: 100%; + } + +#content table { + border: 0; + border-collapse: collapse; + direction: ltr; + table-layout: fixed; + width: 100%; + } +#content table > colgroup > col:nth-of-type(1) { + width: 5em; + } +#content table > colgroup > col:nth-of-type(2) { + width: 2.5em; + } +#content table > colgroup > col:nth-of-type(3) { + width: 2.5em; + } +#content table > colgroup > col:nth-of-type(4) { + width: 20%; + } +#content table > colgroup > col:nth-of-type(5) { + width: 6em; + } +#content table > colgroup > col:nth-of-type(6) { + width: calc(100% - 16em - 20%); + } +body.f table tr.f { + display: none; + } + +#content table tr.cat_info { + color: #00f; + } +#content table tr.blocked { + background-color: rgba(192, 0, 0, 0.1); + } +body.colorBlind #content table tr.blocked { + background-color: rgba(0, 19, 110, 0.1); + } +#content table tr.allowed { + background-color: rgba(0, 160, 0, 0.1); + } +body.colorBlind #content table tr.allowed { + background-color: rgba(255, 194, 57, 0.1) + } +#content table tr.cosmetic { + background-color: rgba(255, 255, 0, 0.1); + } +#content table tr.maindoc { + background-color: #666; + color: white; + text-align: center; + } + +body #content td { + border: 1px solid #ccc; + border-top: none; + min-width: 0.5em; + padding: 3px; + vertical-align: top; + white-space: normal; + word-break: break-all; + word-wrap: break-word; + } +#content table tr td { + border-top: 1px solid #ccc; + } +#content table tr td:first-of-type { + border-left: none; + } +#content table tr td:last-of-type { + border-right: none; + } +body.compactView #content td { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + +#content table tr td:nth-of-type(1) { + text-align: center; + white-space: nowrap; + } +#content table tr td:nth-of-type(2) { + text-align: center; + white-space: nowrap; + } +#content table tr.tab_bts > td:nth-of-type(2):before { + content: '\f070'; + font: 1em FontAwesome; + } +#content table tr.tab:not(.canMtx) { + opacity: 0.2; + } +#content table tr.tab:not(.canMtx) > td:nth-of-type(2):before { + content: '\f00d'; + font: 1em FontAwesome; + } +body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2) { + cursor: zoom-in; + } +body:not(.popupOn) #content table tr.canMtx td:nth-of-type(2):hover { + background: white; + } +#content table tr.cat_net td:nth-of-type(3), +#content table tr.cat_cosmetic td:nth-of-type(3) { + font: 12px monospace; + text-align: center; + white-space: nowrap; + } +#content table tr.cat_net td:nth-of-type(6) > span > b { + font-weight: bold; + } +#content table tr td:nth-of-type(6) b { + font-weight: normal; + } +#content table tr.blocked td:nth-of-type(6) b { + background-color: rgba(192, 0, 0, 0.2); + } +body.colorBlind #content table tr.blocked td:nth-of-type(6) b { + background-color: rgba(0, 19, 110, 0.2); + } +#content table tr.allowed td:nth-of-type(6) b { + background-color: rgba(0, 160, 0, 0.2); + } +body.colorBlind #content table tr.allowed td:nth-of-type(6) b { + background-color: rgba(255, 194, 57, 0.2); + } + +#popupContainer { + background: white; + border: 1px solid gray; + border-radius: 3px; + display: none; + overflow: hidden; + position: fixed; + z-index: 200; + } +body.popupOn #popupContainer { + display: block; + } +#popupContainer > div { + background: #aaa; + border: 0; + cursor: -webkit-grab; + cursor: grab; + height: 1.2em; + } +body[dir="ltr"] #popupContainer > div { + direction: rtl; + } +body[dir="rtl"] #popupContainer > div { + direction: ltr; + } +#popupContainer > div > span { + color: #eee; + cursor: pointer; + display: inline-block; + font: 14px FontAwesome; + padding: 0 3px; + } +#popupContainer > div > span:hover { + color: white; + } +#popupContainer > iframe { + border: 0; + padding: 0; + margin: 0; + width: 100%; + } +#movingOverlay { + bottom: 0; + display: none; + left: 0; + position: fixed; + right: 0; + top: 0; + z-index: 300; + } +#popupContainer.moving ~ #movingOverlay { + cursor: -webkit-grabbing; + cursor: grabbing; + display: block; + } diff --git a/src/devtool-log.html b/src/devtool-log.html deleted file mode 100644 index 61c9e3c4b..000000000 --- a/src/devtool-log.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - -uBlock log - - -
- - - - -
-
-
-
- - - - - - - diff --git a/src/devtools.html b/src/devtools.html deleted file mode 100644 index aebbff197..000000000 --- a/src/devtools.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - -
- - - - - -
-
-


- -


- -


- -


-   -

-
-
- - -
- -
-
-
-
- - - - - - - - - - diff --git a/src/js/contentscript-end.js b/src/js/contentscript-end.js index 486a57b07..f7234d513 100644 --- a/src/js/contentscript-end.js +++ b/src/js/contentscript-end.js @@ -34,7 +34,12 @@ // https://github.com/chrisaljoudi/uBlock/issues/464 if ( document instanceof HTMLDocument === false ) { //console.debug('contentscript-end.js > not a HTLMDocument'); - return false; + return; +} + +// I've seen this happens on Firefox +if ( window.location === null ) { + return; } // This can happen diff --git a/src/js/devtool-log.js b/src/js/devtool-log.js deleted file mode 100644 index 312902320..000000000 --- a/src/js/devtool-log.js +++ /dev/null @@ -1,448 +0,0 @@ -/******************************************************************************* - - sessbench - a browser extension to benchmark browser session. - Copyright (C) 2013 Raymond Hill - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see {http://www.gnu.org/licenses/}. - - Home: https://github.com/gorhill/sessbench - - TODO: cleanup/refactor -*/ - -/* global vAPI, uDom */ - -/******************************************************************************/ - -(function() { - -'use strict'; - -/******************************************************************************/ - -var messager = vAPI.messaging.channel('devtool-log.js'); - -var inspectedTabId = ''; -var doc = document; -var body = doc.body; -var tbody = doc.querySelector('#content tbody'); -var row1Junkyard = []; -var row4Junkyard = []; -var reFilter = null; -var filterTargetTestResult = true; -var maxEntries = 0; - -var prettyRequestTypes = { - 'main_frame': 'doc', - 'stylesheet': 'css', - 'sub_frame': 'frame', - 'xmlhttprequest': 'xhr' -}; - -/******************************************************************************/ - -var escapeHTML = function(s) { - return s.replace(reEscapeLeftBracket, '<') - .replace(reEscapeRightBracket, '>'); -}; - -var reEscapeLeftBracket = //g; - -/******************************************************************************/ - -var renderURL = function(url, filter) { - if ( filter.charAt(0) !== 's' ) { - return escapeHTML(url); - } - // make a regex out of the filter - var reText = filter.slice(3); - var pos = reText.indexOf('$'); - if ( pos > 0 ) { - reText = reText.slice(0, pos); - } - if ( reText === '*' ) { - reText = '\\*'; - } else if ( reText.charAt(0) === '/' && reText.slice(-1) === '/' ) { - reText = reText.slice(1, -1); - } else { - reText = reText - .replace(/\./g, '\\.') - .replace(/\?/g, '\\?') - .replace('||', '') - .replace(/\^/g, '.') - .replace(/^\|/g, '^') - .replace(/\|$/g, '$') - .replace(/\*/g, '.*') - ; - } - var re = new RegExp(reText, 'gi'); - var matches = re.exec(url); - var renderedURL = url; - - if ( matches && matches[0].length ) { - renderedURL = escapeHTML(url.slice(0, matches.index)) + - '' + - escapeHTML(url.slice(matches.index, re.lastIndex)) + - '' + - escapeHTML(url.slice(re.lastIndex)); - } else { - renderedURL = escapeHTML(renderedURL); - } - - return renderedURL; -}; - -/******************************************************************************/ - -var createRow = function() { - var tr = row4Junkyard.pop(); - if ( tr ) { - tr.className = ''; - return tr; - } - tr = doc.createElement('tr'); - tr.appendChild(doc.createElement('td')); - tr.appendChild(doc.createElement('td')); - tr.appendChild(doc.createElement('td')); - tr.appendChild(doc.createElement('td')); - return tr; -}; - -/******************************************************************************/ - -var createGap = function(url) { - var tr = row1Junkyard.pop(); - if ( !tr ) { - tr = doc.createElement('tr'); - tr.classList.add('docBoundary'); - tr.appendChild(doc.createElement('td')); - tr.cells[0].setAttribute('colspan', '4'); - } - tr.cells[0].textContent = url; - tbody.insertBefore(tr, tbody.firstChild); -}; - -/******************************************************************************/ - -var renderLogEntry = function(entry) { - var tr = createRow(); - - // If the request is that of a root frame, insert a gap in the table - // in order to visually separate entries for different documents. - if ( entry.type === 'main_frame' ) { - createGap(entry.url); - tr.classList.add('maindoc'); - } - - // Cosmetic filter? - if ( entry.result.charAt(0) === 'c' ) { - tr.classList.add('cosmetic'); - } - - if ( entry.result.charAt(1) === 'b' ) { - tr.classList.add('blocked'); - tr.cells[0].textContent = ' -\u00A0'; - } else if ( entry.result.charAt(1) === 'a' ) { - tr.classList.add('allowed'); - tr.cells[0].textContent = ' +\u00A0'; - } else { - tr.cells[0].textContent = ''; - } - - var filterText = entry.result.slice(3); - if ( entry.result.lastIndexOf('sa', 0) === 0 ) { - filterText = '@@' + filterText; - } - - tr.cells[1].textContent = filterText + '\t'; - tr.cells[2].textContent = (prettyRequestTypes[entry.type] || entry.type) + '\t'; - vAPI.insertHTML(tr.cells[3], renderURL(entry.url, entry.result)); - applyFilterToRow(tr); - tbody.insertBefore(tr, tbody.firstChild); -}; - -/******************************************************************************/ - -var renderLogBuffer = function(response) { - body.classList.toggle('colorBlind', response.colorBlind); - - var buffer = response.entries; - if ( buffer.length === 0 ) { - return; - } - - // Preserve scroll position - var height = tbody.offsetHeight; - - var n = buffer.length; - for ( var i = 0; i < n; i++ ) { - renderLogEntry(buffer[i]); - } - - // Prevent logger from growing infinitely and eating all memory. For - // instance someone could forget that it is left opened for some - // dynamically refreshed pages. - truncateLog(maxEntries); - - var yDelta = tbody.offsetHeight - height; - if ( yDelta === 0 ) { - return; - } - - // Chromium: - // body.scrollTop = good value - // body.parentNode.scrollTop = 0 - if ( body.scrollTop !== 0 ) { - body.scrollTop += yDelta; - return; - } - - // Firefox: - // body.scrollTop = 0 - // body.parentNode.scrollTop = good value - var parentNode = body.parentNode; - if ( parentNode && parentNode.scrollTop !== 0 ) { - parentNode.scrollTop += yDelta; - } -}; - -/******************************************************************************/ - -var truncateLog = function(size) { - if ( size === 0 ) { - size = 25000; - } - size = Math.min(size, 25000); - var tr; - while ( tbody.childElementCount > size ) { - tr = tbody.lastElementChild; - // https://github.com/gorhill/uBlock/issues/123 - // Triage according to row type. - if ( tr.cells.length === 1 ) { - row1Junkyard.push(tr); - } else { - row4Junkyard.push(tr); - } - tbody.removeChild(tr); - } -}; - -/******************************************************************************/ - -var onBufferRead = function(response) { - renderLogBuffer(response); - setTimeout(readLogBuffer, 1000); -}; - -/******************************************************************************/ - -// This can be called only once, at init time. After that, this will be called -// automatically. If called after init time, this will be messy, and this would -// require a bit more code to ensure no multi time out events. - -var readLogBuffer = function() { - messager.send({ what: 'readLogBuffer', tabId: inspectedTabId }, onBufferRead); -}; - -/******************************************************************************/ - -var clearBuffer = function() { - var tr; - while ( tbody.firstChild !== null ) { - tr = tbody.lastElementChild; - // https://github.com/gorhill/uBlock/issues/123 - // Triage according to row type. - if ( tr.cells.length === 1 ) { - row1Junkyard.push(tr); - } else { - row4Junkyard.push(tr); - } - tbody.removeChild(tr); - } -}; - -/******************************************************************************/ - -var reloadTab = function() { - messager.send({ what: 'reloadTab', tabId: inspectedTabId }); -}; - -/******************************************************************************/ - -var applyFilterToRow = function(row) { - var re = reFilter; - if ( re === null || re.test(row.textContent) === filterTargetTestResult ) { - row.classList.remove('hidden'); - } else { - row.classList.add('hidden'); - } -}; - -/******************************************************************************/ - -var applyFilter = function() { - if ( reFilter === null ) { - unapplyFilter(); - return; - } - var row = document.querySelector('#content tr'); - if ( row === null ) { - return; - } - var re = reFilter; - var target = filterTargetTestResult; - while ( row !== null ) { - if ( re.test(row.textContent) === target ) { - row.classList.remove('hidden'); - } else { - row.classList.add('hidden'); - } - row = row.nextSibling; - } -}; - -/******************************************************************************/ - -var unapplyFilter = function() { - var row = document.querySelector('#content tr'); - if ( row === null ) { - return; - } - while ( row !== null ) { - row.classList.remove('hidden'); - row = row.nextSibling; - } -}; - -/******************************************************************************/ - -var onFilterButton = function() { - uDom('body').toggleClass('filterOff'); -}; - -/******************************************************************************/ - -var onFilterChanged = function() { - var filterExpression = uDom('#filterExpression'); - var filterRaw = filterExpression.val().trim(); - - // Assume good filter expression - filterExpression.removeClass('bad'); - - // Invert resultset? - filterTargetTestResult = filterRaw.charAt(0) !== '!'; - if ( filterTargetTestResult === false ) { - filterRaw = filterRaw.slice(1); - } - - // No filter - if ( filterRaw === '') { - reFilter = null; - return; - } - - // Regex? - if ( filterRaw.length > 1 && filterRaw.charAt(0) === '/' && filterRaw.slice(-1) === '/' ) { - try { - reFilter = new RegExp(filterRaw.slice(1, -1)); - } catch (e) { - reFilter = null; - filterExpression.addClass('bad'); - } - return; - } - - // Plain filtering - var filterParts = filterRaw - .replace(/^\s*-(\s+|$)/, '-\xA0 ') - .replace(/^\s*\\+(\s+|$)/, '+\xA0 ') - .split(/[ \f\n\r\t\v​]+/); - var n = filterParts.length; - for ( var i = 0; i < n; i++ ) { - filterParts[i] = filterParts[i].replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); - } - reFilter = new RegExp(filterParts.join('.*\\s+.*')); -}; - -/******************************************************************************/ - -var onFilterChangedAsync = (function() { - var timer = null; - - var commit = function() { - timer = null; - onFilterChanged(); - applyFilter(); - }; - - var changed = function() { - if ( timer !== null ) { - clearTimeout(timer); - } - timer = setTimeout(commit, 750); - }; - - return changed; -})(); - -/******************************************************************************/ - -var onMaxEntriesChanged = function() { - var raw = uDom(this).val(); - try { - maxEntries = parseInt(raw, 10); - if ( isNaN(maxEntries) ) { - maxEntries = 0; - } - } catch (e) { - maxEntries = 0; - } - - messager.send({ - what: 'userSettings', - name: 'requestLogMaxEntries', - value: maxEntries - }); - - truncateLog(maxEntries); -}; - -/******************************************************************************/ - -uDom.onLoad(function() { - // Extract the tab id of the page we need to pull the log - var matches = window.location.search.match(/[\?&]tabId=([^&]+)/); - if ( matches && matches.length === 2 ) { - inspectedTabId = matches[1]; - } - - var onSettingsReady = function(settings) { - maxEntries = settings.requestLogMaxEntries || 0; - uDom('#maxEntries').val(maxEntries || ''); - }; - messager.send({ what: 'getUserSettings' }, onSettingsReady); - - readLogBuffer(); - - uDom('#reload').on('click', reloadTab); - uDom('#clear').on('click', clearBuffer); - uDom('#filterButton').on('click', onFilterButton); - uDom('#filterExpression').on('input', onFilterChangedAsync); - uDom('#maxEntries').on('change', onMaxEntriesChanged); -}); - -/******************************************************************************/ - -})(); diff --git a/src/js/devtools.js b/src/js/devtools.js deleted file mode 100644 index e73fca89d..000000000 --- a/src/js/devtools.js +++ /dev/null @@ -1,231 +0,0 @@ -/******************************************************************************* - - µBlock - a browser extension to block requests. - Copyright (C) 2014 Raymond Hill - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see {http://www.gnu.org/licenses/}. - - Home: https://github.com/gorhill/uBlock -*/ - -/* jshint bitwise: false */ -/* global vAPI, uDom */ - -/******************************************************************************/ - -(function() { - -'use strict'; - -/******************************************************************************/ - -var messager = vAPI.messaging.channel('devtools.js'); - -/******************************************************************************/ - -var renderPageSelector = function(targetTabId) { - var selectedTabId = targetTabId || uDom('#pageSelector').val(); - var onDataReceived = function(pageTitles) { - if ( pageTitles.hasOwnProperty(selectedTabId) === false ) { - selectedTabId = pageTitles[0]; - } - var select = uDom('#pageSelector').empty(); - var option; - for ( var tabId in pageTitles ) { - if ( pageTitles.hasOwnProperty(tabId) === false ) { - continue; - } - option = uDom('