diff --git a/platform/chromium/vapi-background.js b/platform/chromium/vapi-background.js index b7f9a2b1c..b32e8af9a 100644 --- a/platform/chromium/vapi-background.js +++ b/platform/chromium/vapi-background.js @@ -384,32 +384,33 @@ vAPI.tabs.registerListeners = function() { /******************************************************************************/ -vAPI.tabs.get = function(tabId, callback) { - var onTabReady = function(tab) { - // https://code.google.com/p/chromium/issues/detail?id=410868#c8 - if ( chrome.runtime.lastError ) { - /* noop */ - } - // Caller must be prepared to deal with nil tab value - callback(tab); - }; +// Caller must be prepared to deal with nil tab argument. - if ( tabId !== null ) { - tabId = toChromiumTabId(tabId); - if ( tabId === 0 ) { - onTabReady(null); - } else { - chrome.tabs.get(tabId, onTabReady); - } +// https://code.google.com/p/chromium/issues/detail?id=410868#c8 + +vAPI.tabs.get = function(tabId, callback) { + if ( tabId === null ) { + chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { + if ( chrome.runtime.lastError ) { /* noop */ } + var tab = tabs && tabs[0]; + if ( tab ) { + tab.id = tab.id.toString(); + } + callback(tab); + }); return; } - var onTabReceived = function(tabs) { - // https://code.google.com/p/chromium/issues/detail?id=410868#c8 - void chrome.runtime.lastError; - callback(tabs[0]); - }; - chrome.tabs.query({ active: true, currentWindow: true }, onTabReceived); + tabId = toChromiumTabId(tabId); + if ( tabId === 0 ) { + callback(null); + return; + } + + chrome.tabs.get(tabId, function(tab) { + if ( chrome.runtime.lastError ) { /* noop */ } + callback(tab); + }); }; /******************************************************************************/ diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index 0d0222411..c0716de42 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -511,6 +511,10 @@ "message":"Behind the scene", "description":"Pretty name for behind-the-scene network requests" }, + "loggerCurrentTab":{ + "message":"Current tab", + "description":"Appears in the logger's tab selector" + }, "logFilterPrompt":{ "message":"filter log entries", "description": "English: filter log entries" diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css index f68c05055..5a90028af 100644 --- a/src/css/logger-ui.css +++ b/src/css/logger-ui.css @@ -207,6 +207,7 @@ body #netInspector td { } #netInspector tr td:nth-of-type(1) { + cursor: default; text-align: right; white-space: nowrap; } diff --git a/src/js/logger-ui-inspector.js b/src/js/logger-ui-inspector.js index a1471eb3a..2cceec1f3 100644 --- a/src/js/logger-ui-inspector.js +++ b/src/js/logger-ui-inspector.js @@ -50,7 +50,6 @@ var inspectedURL = ''; var inspectedHostname = ''; var inspector = uDom.nodeFromId('domInspector'); var domTree = uDom.nodeFromId('domTree'); -var tabSelector = uDom.nodeFromId('pageSelector'); var uidGenerator = 1; var filterToIdMap = new Map(); @@ -562,7 +561,7 @@ var onMouseOver = (function() { var currentTabId = function() { if ( showdomButton.classList.contains('active') === false ) { return ''; } - var tabId = logger.tabIdFromClassName(tabSelector.value) || ''; + var tabId = logger.tabIdFromPageSelector(); return tabId !== 'bts' ? tabId : ''; }; @@ -636,7 +635,7 @@ var revert = function() { var toggleOn = function() { window.addEventListener('beforeunload', toggleOff); - tabSelector.addEventListener('change', onTabIdChanged); + document.addEventListener('tabIdChanged', onTabIdChanged); domTree.addEventListener('click', onClicked, true); domTree.addEventListener('mouseover', onMouseOver, true); uDom.nodeFromSelector('#domInspector .vCompactToggler').addEventListener('click', toggleVCompactView); @@ -652,7 +651,7 @@ var toggleOn = function() { var toggleOff = function() { shutdownInspector(); window.removeEventListener('beforeunload', toggleOff); - tabSelector.removeEventListener('change', onTabIdChanged); + document.removeEventListener('tabIdChanged', onTabIdChanged); domTree.removeEventListener('click', onClicked, true); domTree.removeEventListener('mouseover', onMouseOver, true); uDom.nodeFromSelector('#domInspector .vCompactToggler').removeEventListener('click', toggleVCompactView); @@ -680,5 +679,3 @@ showdomButton.addEventListener('click', toggle); /******************************************************************************/ })(); - - diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js index 7a0a2a2af..b3cad3b51 100644 --- a/src/js/logger-ui.js +++ b/src/js/logger-ui.js @@ -29,9 +29,12 @@ /******************************************************************************/ -var logger = self.logger = {}; +var logger = self.logger = { + ownerId: Date.now() +}; + var messaging = vAPI.messaging; -var ownerId = Date.now(); +var activeTabId; /******************************************************************************/ @@ -44,11 +47,16 @@ var removeAllChildren = logger.removeAllChildren = function(node) { /******************************************************************************/ var tabIdFromClassName = logger.tabIdFromClassName = function(className) { - var matches = className.match(/(?:^| )tab_([^ ]+)(?: |$)/); - if ( matches === null ) { - return ''; - } - return matches[1]; + var matches = className.match(/\btab_([^ ]+)\b/); + return matches !== null ? matches[1] : ''; +}; + +var tabIdFromPageSelector = logger.tabIdFromPageSelector = function() { + var tabClass = uDom.nodeFromId('pageSelector').value; + if ( tabClass === '' ) { return ''; } + if ( tabClass === 'tab_bts' ) { return noTabId; } + if ( tabClass === 'tab_active' ) { return activeTabId; } + return tabClass.slice(4); }; /******************************************************************************/ @@ -408,15 +416,17 @@ var renderLogEntries = function(response) { /******************************************************************************/ var synchronizeTabIds = function(newTabIds) { + var select = uDom.nodeFromId('pageSelector'); + var selectValue = select.value; + var oldTabIds = allTabIds; - var autoDeleteVoidRows = !!vAPI.localStorage.getItem('loggerAutoDeleteVoidRows'); + var autoDeleteVoidRows = selectValue === 'tab_active'; var rowVoided = false; - var trs; for ( var tabId in oldTabIds ) { if ( oldTabIds.hasOwnProperty(tabId) === false ) { continue; } if ( newTabIds.hasOwnProperty(tabId) ) { continue; } // Mark or remove voided rows - trs = uDom('.tab_' + tabId); + var trs = uDom('.tab_' + tabId); if ( autoDeleteVoidRows ) { toJunkyard(trs); } else { @@ -429,13 +439,11 @@ var synchronizeTabIds = function(newTabIds) { } } - var select = uDom.nodeFromId('pageSelector'); - var selectValue = select.value; var tabIds = Object.keys(newTabIds).sort(function(a, b) { return newTabIds[a].localeCompare(newTabIds[b]); }); var option; - for ( var i = 0, j = 2; i < tabIds.length; i++ ) { + for ( var i = 0, j = 3; i < tabIds.length; i++ ) { tabId = tabIds[i]; if ( tabId === noTabId ) { continue; } option = select.options[j]; @@ -495,6 +503,11 @@ var onLogBufferRead = function(response) { // This tells us the behind-the-scene tab id noTabId = response.noTabId; + // Tab id of currently active tab + if ( response.activeTabId ) { + activeTabId = response.activeTabId; + } + // This may have changed meanwhile if ( response.maxEntries !== maxEntries ) { maxEntries = response.maxEntries; @@ -537,62 +550,70 @@ var onLogBufferRead = function(response) { // require a bit more code to ensure no multi time out events. var readLogBuffer = function() { - if ( ownerId === undefined ) { return; } + if ( logger.ownerId === undefined ) { return; } vAPI.messaging.send( 'loggerUI', - { what: 'readAll', ownerId: ownerId }, + { what: 'readAll', ownerId: logger.ownerId }, onLogBufferRead ); }; var readLogBufferAsync = function() { - if ( ownerId === undefined ) { return; } + if ( logger.ownerId === undefined ) { return; } vAPI.setTimeout(readLogBuffer, 1200); }; /******************************************************************************/ var pageSelectorChanged = function() { - window.location.replace('#' + uDom.nodeFromId('pageSelector').value); + var select = uDom.nodeFromId('pageSelector'); + window.location.replace('#' + select.value); pageSelectorFromURLHash(); }; -/******************************************************************************/ - var pageSelectorFromURLHash = (function() { - var lastHash = ''; + var lastTabClass = ''; + var lastEffectiveTabClass = ''; - return function() { - var hash = window.location.hash; - if ( hash === lastHash ) { - return; + var selectRows = function(tabClass) { + if ( tabClass === 'tab_active' ) { + if ( activeTabId === undefined ) { return; } + tabClass = 'tab_' + activeTabId; } + if ( tabClass === lastEffectiveTabClass ) { return; } + lastEffectiveTabClass = tabClass; - var tabClass = hash.slice(1); - var select = uDom.nodeFromId('pageSelector'); - var option = select.querySelector('option[value="' + tabClass + '"]'); - if ( option === null ) { - hash = window.location.hash = ''; - tabClass = ''; - option = select.options[0]; - } - - lastHash = hash; - - select.selectedIndex = option.index; - select.value = option.value; + document.dispatchEvent(new Event('tabIdChanged')); var style = uDom.nodeFromId('tabFilterer'); var sheet = style.sheet; while ( sheet.cssRules.length !== 0 ) { sheet.deleteRule(0); } - if ( tabClass !== '' ) { - sheet.insertRule( - '#netInspector tr:not(.' + tabClass + ') { display: none; }', - 0 - ); + if ( tabClass === '' ) { return; } + sheet.insertRule( + '#netInspector tr:not(.' + tabClass + '):not(.tab_bts) ' + + '{display:none;}' + ); + }; + + return function() { + var tabClass = window.location.hash.slice(1); + selectRows(tabClass); + if ( tabClass === lastTabClass ) { return; } + lastTabClass = tabClass; + + var select = uDom.nodeFromId('pageSelector'); + var option = select.querySelector('option[value="' + tabClass + '"]'); + if ( option === null ) { + window.location.hash = ''; + tabClass = ''; + option = select.options[0]; } + + select.selectedIndex = option.index; + select.value = option.value; + uDom('.needtab').toggleClass( 'disabled', tabClass === '' || tabClass === 'tab_bts' @@ -603,11 +624,8 @@ var pageSelectorFromURLHash = (function() { /******************************************************************************/ var reloadTab = function() { - var tabClass = uDom.nodeFromId('pageSelector').value; - var tabId = tabIdFromClassName(tabClass); - if ( tabId === 'bts' || tabId === '' ) { - return; - } + var tabId = tabIdFromPageSelector(); + if ( tabId === '' || tabId === noTabId ) { return; } messaging.send('loggerUI', { what: 'reloadTab', tabId: tabId }); }; @@ -1491,13 +1509,13 @@ var toJunkyard = function(trs) { /******************************************************************************/ var clearBuffer = function() { - var tabId = uDom.nodeFromId('pageSelector').value || null; + var tabClass = uDom.nodeFromId('pageSelector').value || ''; var tbody = document.querySelector('#netInspector tbody'); var tr = tbody.lastElementChild; var trPrevious; while ( tr !== null ) { trPrevious = tr.previousElementSibling; - if ( tabId === null || tr.classList.contains(tabId) ) { + if ( tabClass === '' || tr.classList.contains(tabClass) ) { trJunkyard.push(tbody.removeChild(tr)); } tr = trPrevious; @@ -1656,19 +1674,19 @@ var popupManager = (function() { /******************************************************************************/ var grabView = function() { - if ( ownerId === undefined ) { - ownerId = Date.now(); + if ( logger.ownerId === undefined ) { + logger.ownerId = Date.now(); } readLogBufferAsync(); }; var releaseView = function() { - if ( ownerId === undefined ) { return; } + if ( logger.ownerId === undefined ) { return; } vAPI.messaging.send( 'loggerUI', - { what: 'releaseView', ownerId: ownerId } + { what: 'releaseView', ownerId: logger.ownerId } ); - ownerId = undefined; + logger.ownerId = undefined; }; window.addEventListener('pagehide', releaseView); diff --git a/src/js/messaging.js b/src/js/messaging.js index ced2781e6..73801ffc9 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -1015,6 +1015,31 @@ var µb = µBlock, /******************************************************************************/ +var getLoggerData = function(ownerId, tab, callback) { + var tabIds = {}; + for ( var tabId in µb.pageStores ) { + var pageStore = µb.pageStoreFromTabId(tabId); + if ( pageStore === null ) { continue; } + if ( pageStore.rawURL.startsWith(extensionPageURL) ) { continue; } + tabIds[tabId] = pageStore.title; + } + var activeTabId; + if ( tabIds.hasOwnProperty(tab.id) ) { + activeTabId = tab.id; + } + callback({ + colorBlind: µb.userSettings.colorBlindFriendly, + entries: µb.logger.readAll(ownerId), + maxEntries: µb.userSettings.requestLogMaxEntries, + noTabId: vAPI.noTabId, + activeTabId: activeTabId, + tabIds: tabIds, + tabIdsToken: µb.pageStoresToken + }); +}; + +/******************************************************************************/ + var getURLFilteringData = function(details) { var colors = {}; var response = { @@ -1049,6 +1074,19 @@ var getURLFilteringData = function(details) { var onMessage = function(request, sender, callback) { // Async switch ( request.what ) { + case 'readAll': + if ( + µb.logger.ownerId !== undefined && + µb.logger.ownerId !== request.ownerId + ) { + callback({ unavailable: true }); + return; + } + vAPI.tabs.get(null, function(tab) { + getLoggerData(request.ownerId, tab, callback); + }); + return; + default: break; } @@ -1057,31 +1095,6 @@ var onMessage = function(request, sender, callback) { var response; switch ( request.what ) { - case 'readAll': - if ( - µb.logger.ownerId !== undefined && - µb.logger.ownerId !== request.ownerId - ) { - response = { unavailable: true }; - break; - } - var tabIds = {}; - for ( var tabId in µb.pageStores ) { - var pageStore = µb.pageStoreFromTabId(tabId); - if ( pageStore === null ) { continue; } - if ( pageStore.rawURL.startsWith(extensionPageURL) ) { continue; } - tabIds[tabId] = pageStore.title; - } - response = { - colorBlind: µb.userSettings.colorBlindFriendly, - entries: µb.logger.readAll(request.ownerId), - maxEntries: µb.userSettings.requestLogMaxEntries, - noTabId: vAPI.noTabId, - tabIds: tabIds, - tabIdsToken: µb.pageStoresToken - }; - break; - case 'releaseView': if ( request.ownerId === µb.logger.ownerId ) { µb.logger.ownerId = undefined; diff --git a/src/logger-ui.html b/src/logger-ui.html index 9539f44a9..804a1363f 100644 --- a/src/logger-ui.html +++ b/src/logger-ui.html @@ -15,6 +15,7 @@