2015-05-04 17:01:07 +12:00
|
|
|
/*******************************************************************************
|
|
|
|
|
|
|
|
uMatrix - a browser extension to benchmark browser session.
|
|
|
|
Copyright (C) 2015 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
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* jshint boss: true */
|
|
|
|
/* global vAPI, uDom */
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
var messager = vAPI.messaging.channel('logger-ui.js');
|
|
|
|
|
|
|
|
var doc = document;
|
|
|
|
var body = doc.body;
|
|
|
|
var tbody = doc.querySelector('#content tbody');
|
|
|
|
var trJunkyard = [];
|
|
|
|
var tdJunkyard = [];
|
2015-05-05 02:50:44 +12:00
|
|
|
var firstVarDataCol = 2; // currently, column 2 (0-based index)
|
|
|
|
var lastVarDataIndex = 3; // currently, d0-d3
|
2015-05-06 16:30:45 +12:00
|
|
|
var maxEntries = 5000;
|
2015-05-05 02:50:44 +12:00
|
|
|
var noTabId = '';
|
2015-05-07 05:01:02 +12:00
|
|
|
var allTabIds = {};
|
2015-05-04 17:01:07 +12:00
|
|
|
|
|
|
|
var prettyRequestTypes = {
|
|
|
|
'main_frame': 'doc',
|
|
|
|
'stylesheet': 'css',
|
|
|
|
'sub_frame': 'frame',
|
|
|
|
'xmlhttprequest': 'xhr'
|
|
|
|
};
|
|
|
|
|
|
|
|
var timeOptions = {
|
|
|
|
hour: '2-digit',
|
|
|
|
minute: '2-digit',
|
2015-05-06 16:30:45 +12:00
|
|
|
second: '2-digit',
|
|
|
|
hour12: false
|
|
|
|
};
|
|
|
|
|
|
|
|
var dateOptions = {
|
|
|
|
month: 'short',
|
|
|
|
day: '2-digit'
|
2015-05-04 17:01:07 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
var escapeHTML = function(s) {
|
|
|
|
return s.replace(reEscapeLeftBracket, '<')
|
|
|
|
.replace(reEscapeRightBracket, '>');
|
|
|
|
};
|
|
|
|
|
|
|
|
var reEscapeLeftBracket = /</g;
|
|
|
|
var reEscapeRightBracket = />/g;
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
// Emphasize hostname in URL, as this is what matters in uMatrix's rules.
|
|
|
|
|
|
|
|
var nodeFromURL = function(url) {
|
|
|
|
var hnbeg = url.indexOf('://');
|
|
|
|
if ( hnbeg === -1 ) {
|
|
|
|
return document.createTextNode(url);
|
|
|
|
}
|
|
|
|
hnbeg += 3;
|
|
|
|
|
|
|
|
var hnend = url.indexOf('/', hnbeg);
|
|
|
|
if ( hnend === -1 ) {
|
|
|
|
hnend = url.slice(hnbeg).search(/\?#/);
|
|
|
|
if ( hnend !== -1 ) {
|
|
|
|
hnend += hnbeg;
|
|
|
|
} else {
|
|
|
|
hnend = url.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var node = renderedURLTemplate.cloneNode(true);
|
|
|
|
node.childNodes[0].textContent = url.slice(0, hnbeg);
|
|
|
|
node.childNodes[1].textContent = url.slice(hnbeg, hnend);
|
|
|
|
node.childNodes[2].textContent = url.slice(hnend);
|
|
|
|
return node;
|
|
|
|
};
|
|
|
|
|
|
|
|
var renderedURLTemplate = document.querySelector('#renderedURLTemplate > span');
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-05 02:50:44 +12:00
|
|
|
var createCellAt = function(tr, index) {
|
|
|
|
var td = tr.cells[index];
|
|
|
|
var mustAppend = !td;
|
|
|
|
if ( mustAppend ) {
|
|
|
|
td = tdJunkyard.pop();
|
|
|
|
}
|
2015-05-04 17:01:07 +12:00
|
|
|
if ( td ) {
|
2015-05-05 02:50:44 +12:00
|
|
|
td.removeAttribute('colspan');
|
|
|
|
td.textContent = '';
|
|
|
|
} else {
|
|
|
|
td = doc.createElement('td');
|
2015-05-04 17:01:07 +12:00
|
|
|
}
|
2015-05-05 02:50:44 +12:00
|
|
|
if ( mustAppend ) {
|
|
|
|
tr.appendChild(td);
|
|
|
|
}
|
|
|
|
return td;
|
2015-05-04 17:01:07 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
var createRow = function(layout) {
|
2015-05-04 17:01:07 +12:00
|
|
|
var tr = trJunkyard.pop();
|
|
|
|
if ( tr ) {
|
|
|
|
tr.className = '';
|
|
|
|
} else {
|
|
|
|
tr = doc.createElement('tr');
|
|
|
|
}
|
|
|
|
for ( var index = 0; index < firstVarDataCol; index++ ) {
|
2015-05-05 02:50:44 +12:00
|
|
|
createCellAt(tr, index);
|
2015-05-04 17:01:07 +12:00
|
|
|
}
|
2015-05-05 02:50:44 +12:00
|
|
|
var i = 1, span = 1, td;
|
2015-05-04 17:01:07 +12:00
|
|
|
for (;;) {
|
2015-05-05 02:50:44 +12:00
|
|
|
td = createCellAt(tr, index);
|
|
|
|
if ( i === lastVarDataIndex ) {
|
2015-05-04 17:01:07 +12:00
|
|
|
break;
|
|
|
|
}
|
2015-05-06 16:30:45 +12:00
|
|
|
if ( layout.charAt(i) !== '1' ) {
|
2015-05-04 17:01:07 +12:00
|
|
|
span += 1;
|
|
|
|
} else {
|
|
|
|
if ( span !== 1 ) {
|
|
|
|
td.setAttribute('colspan', span);
|
|
|
|
}
|
|
|
|
index += 1;
|
|
|
|
span = 1;
|
|
|
|
}
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
if ( span !== 1 ) {
|
|
|
|
td.setAttribute('colspan', span);
|
|
|
|
}
|
|
|
|
index += 1;
|
|
|
|
while ( td = tr.cells[index] ) {
|
|
|
|
tdJunkyard.push(tr.removeChild(td));
|
|
|
|
}
|
|
|
|
return tr;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-07 02:04:49 +12:00
|
|
|
var createGap = function(tabId, url) {
|
2015-05-06 16:30:45 +12:00
|
|
|
var tr = createRow('1');
|
2015-05-04 17:01:07 +12:00
|
|
|
tr.classList.add('doc');
|
2015-05-07 05:01:02 +12:00
|
|
|
tr.classList.add('tab');
|
|
|
|
tr.classList.add('canMtx');
|
2015-05-07 02:04:49 +12:00
|
|
|
tr.classList.add('tab_' + tabId);
|
2015-05-04 17:01:07 +12:00
|
|
|
tr.cells[firstVarDataCol].textContent = url;
|
|
|
|
tbody.insertBefore(tr, tbody.firstChild);
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
var renderLogEntry = function(entry) {
|
2015-05-06 16:30:45 +12:00
|
|
|
var tr;
|
2015-05-05 02:50:44 +12:00
|
|
|
var fvdc = firstVarDataCol;
|
2015-05-04 17:01:07 +12:00
|
|
|
|
|
|
|
switch ( entry.cat ) {
|
2015-05-05 02:50:44 +12:00
|
|
|
case 'error':
|
2015-05-04 17:01:07 +12:00
|
|
|
case 'info':
|
2015-05-06 16:30:45 +12:00
|
|
|
tr = createRow('1');
|
2015-05-05 02:50:44 +12:00
|
|
|
tr.cells[fvdc].textContent = entry.d0;
|
2015-05-04 17:01:07 +12:00
|
|
|
break;
|
|
|
|
|
|
|
|
case 'net':
|
2015-05-06 16:30:45 +12:00
|
|
|
tr = createRow('111');
|
2015-05-07 05:01:02 +12:00
|
|
|
tr.classList.add('canMtx');
|
2015-05-04 17:01:07 +12:00
|
|
|
// If the request is that of a root frame, insert a gap in the table
|
|
|
|
// in order to visually separate entries for different documents.
|
2015-05-07 02:04:49 +12:00
|
|
|
if ( entry.d2 === 'doc' && entry.tab !== noTabId ) {
|
|
|
|
createGap(entry.tab, entry.d1);
|
2015-05-04 17:01:07 +12:00
|
|
|
}
|
2015-05-06 16:30:45 +12:00
|
|
|
if ( entry.d3 ) {
|
2015-05-04 17:01:07 +12:00
|
|
|
tr.classList.add('blocked');
|
2015-05-05 02:50:44 +12:00
|
|
|
tr.cells[fvdc].textContent = '---';
|
2015-05-04 17:01:07 +12:00
|
|
|
} else {
|
2015-05-05 02:50:44 +12:00
|
|
|
tr.cells[fvdc].textContent = '';
|
2015-05-04 17:01:07 +12:00
|
|
|
}
|
2015-05-06 16:30:45 +12:00
|
|
|
tr.cells[fvdc+1].textContent = (prettyRequestTypes[entry.d2] || entry.d2);
|
|
|
|
tr.cells[fvdc+2].appendChild(nodeFromURL(entry.d1));
|
2015-05-04 17:01:07 +12:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2015-05-06 16:30:45 +12:00
|
|
|
tr = createRow('1');
|
2015-05-05 02:50:44 +12:00
|
|
|
tr.cells[fvdc].textContent = entry.d0;
|
2015-05-04 17:01:07 +12:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
// Fields common to all rows.
|
|
|
|
var time = new Date(entry.tstamp);
|
|
|
|
tr.cells[0].textContent = time.toLocaleTimeString('fullwide', timeOptions);
|
|
|
|
tr.cells[0].title = time.toLocaleDateString('fullwide', dateOptions);
|
|
|
|
|
2015-05-07 05:01:02 +12:00
|
|
|
if ( entry.tab ) {
|
|
|
|
tr.classList.add('tab');
|
|
|
|
if ( entry.tab === noTabId ) {
|
|
|
|
tr.classList.add('tab_bts');
|
|
|
|
} else if ( entry.tab !== '' ) {
|
|
|
|
tr.classList.add('tab_' + entry.tab);
|
|
|
|
}
|
2015-05-06 16:30:45 +12:00
|
|
|
}
|
|
|
|
if ( entry.cat !== '' ) {
|
|
|
|
tr.classList.add('cat_' + entry.cat);
|
|
|
|
}
|
|
|
|
|
2015-05-04 17:01:07 +12:00
|
|
|
tbody.insertBefore(tr, tbody.firstChild);
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
var renderLogBuffer = function(response) {
|
|
|
|
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 ) {
|
2015-05-06 16:30:45 +12:00
|
|
|
size = 5000;
|
2015-05-04 17:01:07 +12:00
|
|
|
}
|
2015-05-07 05:01:02 +12:00
|
|
|
size = Math.min(size, 10000);
|
2015-05-04 17:01:07 +12:00
|
|
|
var tr;
|
|
|
|
while ( tbody.childElementCount > size ) {
|
|
|
|
tr = tbody.lastElementChild;
|
|
|
|
trJunkyard.push(tbody.removeChild(tr));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-07 05:01:02 +12:00
|
|
|
var onLogBufferRead = function(response) {
|
|
|
|
// This tells us the behind-the-scene tab id
|
|
|
|
noTabId = response.noTabId;
|
|
|
|
|
|
|
|
// This may have changed meanwhile
|
2015-05-06 16:30:45 +12:00
|
|
|
if ( response.maxLoggedRequests !== maxEntries ) {
|
|
|
|
maxEntries = response.maxLoggedRequests;
|
|
|
|
uDom('#maxEntries').val(maxEntries || '');
|
|
|
|
}
|
2015-05-07 05:01:02 +12:00
|
|
|
|
|
|
|
// Neuter rows for which a tab does not exist anymore
|
|
|
|
// TODO: sort to avoid using indexOf
|
|
|
|
var targetTabId;
|
|
|
|
var i = allTabIds.length;
|
|
|
|
while ( i-- ) {
|
|
|
|
targetTabId = allTabIds[i];
|
|
|
|
if ( targetTabId === noTabId ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( response.allTabIds.indexOf(targetTabId) !== -1 ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
uDom('.tab_' + targetTabId).removeClass('canMtx');
|
|
|
|
// Close popup if it is currently inspecting this tab
|
|
|
|
if ( targetTabId === popupManager.tabId ) {
|
|
|
|
popupManager.toggleOff();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
allTabIds = response.allTabIds;
|
|
|
|
|
2015-05-04 17:01:07 +12:00
|
|
|
renderLogBuffer(response);
|
2015-05-07 05:01:02 +12:00
|
|
|
setTimeout(readLogBuffer, 1200);
|
2015-05-04 17:01:07 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
// 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() {
|
2015-05-07 05:01:02 +12:00
|
|
|
messager.send({ what: 'readMany' }, onLogBufferRead);
|
2015-05-04 17:01:07 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
var clearBuffer = function() {
|
|
|
|
var tr;
|
|
|
|
while ( tbody.firstChild !== null ) {
|
|
|
|
tr = tbody.lastElementChild;
|
|
|
|
trJunkyard.push(tbody.removeChild(tr));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
var toggleCompactView = function() {
|
|
|
|
body.classList.toggle(
|
|
|
|
'compactView',
|
|
|
|
body.classList.contains('compactView') === false
|
|
|
|
);
|
2015-05-04 17:01:07 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-07 05:01:02 +12:00
|
|
|
var popupManager = (function() {
|
2015-05-07 02:04:49 +12:00
|
|
|
var realTabId = null;
|
|
|
|
var localTabId = null;
|
2015-05-06 16:30:45 +12:00
|
|
|
var container = null;
|
|
|
|
var movingOverlay = null;
|
|
|
|
var popup = null;
|
|
|
|
var popupObserver = null;
|
|
|
|
var style = null;
|
2015-05-07 02:04:49 +12:00
|
|
|
var styleTemplate = [
|
|
|
|
'tr:not(.tab_{{tabId}}) {',
|
|
|
|
'cursor: not-allowed;',
|
2015-05-07 05:01:02 +12:00
|
|
|
'opacity: 0.2;',
|
2015-05-07 02:04:49 +12:00
|
|
|
'}'
|
|
|
|
].join('\n');
|
|
|
|
|
|
|
|
// Related to moving the popup around
|
|
|
|
var xnormal, ynormal, crect, dx, dy, vw, vh;
|
|
|
|
|
|
|
|
// Viewport data assumed to be properly set up
|
|
|
|
var positionFromNormal = function(x, y) {
|
|
|
|
if ( typeof x === 'number' ) {
|
|
|
|
if ( x < 0.5 ) {
|
|
|
|
container.style.setProperty('left', (x * vw) + 'px');
|
|
|
|
container.style.removeProperty('right');
|
|
|
|
} else {
|
|
|
|
container.style.removeProperty('left');
|
|
|
|
container.style.setProperty('right', ((1 - x) * vw) + 'px');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( typeof y === 'number' ) {
|
|
|
|
if ( y < 0.5 ) {
|
|
|
|
container.style.setProperty('top', (y * vh) + 'px');
|
|
|
|
container.style.removeProperty('bottom');
|
|
|
|
} else {
|
|
|
|
container.style.removeProperty('top');
|
|
|
|
container.style.setProperty('bottom', ((1 - y) * vh) + 'px');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// TODO: adjust size
|
|
|
|
};
|
|
|
|
var updateViewportData = function() {
|
|
|
|
crect = container.getBoundingClientRect();
|
|
|
|
vw = document.documentElement.clientWidth - crect.width;
|
|
|
|
vh = document.documentElement.clientHeight - crect.height;
|
|
|
|
};
|
|
|
|
var toNormalX = function(x) {
|
|
|
|
return xnormal = Math.max(Math.min(x / vw, 1), 0);
|
|
|
|
};
|
|
|
|
var toNormalY = function(y) {
|
|
|
|
return ynormal = Math.max(Math.min(y / vh, 1), 0);
|
2015-05-06 16:30:45 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
var onMouseMove = function(ev) {
|
2015-05-07 02:04:49 +12:00
|
|
|
updateViewportData();
|
|
|
|
positionFromNormal(
|
|
|
|
toNormalX(ev.clientX + dx),
|
|
|
|
toNormalY(ev.clientY + dy)
|
|
|
|
);
|
2015-05-06 16:30:45 +12:00
|
|
|
ev.stopPropagation();
|
|
|
|
ev.preventDefault();
|
|
|
|
};
|
|
|
|
|
|
|
|
var onMouseUp = function(ev) {
|
2015-05-07 02:04:49 +12:00
|
|
|
updateViewportData();
|
|
|
|
positionFromNormal(
|
|
|
|
toNormalX(ev.clientX + dx),
|
|
|
|
toNormalY(ev.clientY + dy)
|
|
|
|
);
|
2015-05-06 16:30:45 +12:00
|
|
|
movingOverlay.removeEventListener('mouseup', onMouseUp);
|
|
|
|
movingOverlay.removeEventListener('mousemove', onMouseMove);
|
|
|
|
movingOverlay = null;
|
|
|
|
container.classList.remove('moving');
|
|
|
|
vAPI.localStorage.setItem('popupLastPosition', JSON.stringify({
|
2015-05-07 02:04:49 +12:00
|
|
|
xnormal: xnormal,
|
|
|
|
ynormal: ynormal
|
2015-05-06 16:30:45 +12:00
|
|
|
}));
|
|
|
|
ev.stopPropagation();
|
|
|
|
ev.preventDefault();
|
|
|
|
};
|
|
|
|
|
2015-05-07 02:04:49 +12:00
|
|
|
var onMouseDown = function(ev) {
|
|
|
|
if ( ev.target !== ev.currentTarget ) {
|
|
|
|
return;
|
|
|
|
}
|
2015-05-06 16:30:45 +12:00
|
|
|
container.classList.add('moving');
|
2015-05-07 02:04:49 +12:00
|
|
|
updateViewportData();
|
|
|
|
dx = crect.left - ev.clientX;
|
|
|
|
dy = crect.top - ev.clientY;
|
2015-05-06 16:30:45 +12:00
|
|
|
movingOverlay = document.getElementById('movingOverlay');
|
|
|
|
movingOverlay.addEventListener('mousemove', onMouseMove, true);
|
|
|
|
movingOverlay.addEventListener('mouseup', onMouseUp, true);
|
|
|
|
ev.stopPropagation();
|
|
|
|
ev.preventDefault();
|
|
|
|
};
|
|
|
|
|
|
|
|
var resizePopup = function() {
|
|
|
|
var popupBody = popup.contentWindow.document.body;
|
|
|
|
if ( popupBody.clientWidth !== 0 && container.clientWidth !== popupBody.clientWidth ) {
|
|
|
|
container.style.width = popupBody.clientWidth + 'px';
|
|
|
|
}
|
|
|
|
if ( popupBody.clientHeight !== 0 && popup.clientHeight !== popupBody.clientHeight ) {
|
|
|
|
popup.style.height = popupBody.clientHeight + 'px';
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
var onLoad = function() {
|
|
|
|
resizePopup();
|
|
|
|
popupObserver.observe(popup.contentDocument.body, {
|
|
|
|
subtree: true,
|
|
|
|
attributes: true
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
var toggleOn = function(td) {
|
|
|
|
var tr = td.parentNode;
|
|
|
|
var matches = tr.className.match(/(?:^| )tab_([^ ]+)/);
|
|
|
|
if ( matches === null ) {
|
|
|
|
return;
|
|
|
|
}
|
2015-05-07 02:04:49 +12:00
|
|
|
realTabId = localTabId = matches[1];
|
|
|
|
if ( localTabId === 'bts' ) {
|
|
|
|
realTabId = noTabId;
|
2015-05-06 16:30:45 +12:00
|
|
|
}
|
|
|
|
|
2015-05-07 02:04:49 +12:00
|
|
|
// Use last normalized position if one is defined.
|
|
|
|
// Default to top-right.
|
|
|
|
var x = 1, y = 0;
|
2015-05-06 16:30:45 +12:00
|
|
|
var json = vAPI.localStorage.getItem('popupLastPosition');
|
|
|
|
if ( json ) {
|
|
|
|
try {
|
|
|
|
var popupLastPosition = JSON.parse(json);
|
2015-05-07 02:04:49 +12:00
|
|
|
x = popupLastPosition.xnormal;
|
|
|
|
y = popupLastPosition.ynormal;
|
2015-05-06 16:30:45 +12:00
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
container = document.getElementById('popupContainer');
|
2015-05-07 02:04:49 +12:00
|
|
|
updateViewportData();
|
|
|
|
positionFromNormal(x, y);
|
|
|
|
|
|
|
|
// Window controls
|
|
|
|
container.querySelector('div > span:first-child').addEventListener('click', toggleOff);
|
|
|
|
container.querySelector('div').addEventListener('mousedown', onMouseDown);
|
|
|
|
|
|
|
|
popup = document.createElement('iframe');
|
2015-05-06 16:30:45 +12:00
|
|
|
popup.addEventListener('load', onLoad);
|
2015-05-07 02:04:49 +12:00
|
|
|
popup.setAttribute('src', 'popup.html?tabId=' + realTabId);
|
2015-05-06 16:30:45 +12:00
|
|
|
popupObserver = new MutationObserver(resizePopup);
|
2015-05-07 02:04:49 +12:00
|
|
|
container.appendChild(popup);
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
style = document.querySelector('#content > style');
|
2015-05-07 02:04:49 +12:00
|
|
|
style.textContent = styleTemplate.replace('{{tabId}}', localTabId);
|
|
|
|
|
|
|
|
document.body.classList.add('popupOn');
|
2015-05-06 16:30:45 +12:00
|
|
|
};
|
|
|
|
|
|
|
|
var toggleOff = function() {
|
2015-05-07 02:04:49 +12:00
|
|
|
document.body.classList.remove('popupOn');
|
|
|
|
|
|
|
|
// Just in case
|
|
|
|
if ( movingOverlay !== null ) {
|
|
|
|
movingOverlay.removeEventListener('mousemove', onMouseMove, true);
|
|
|
|
movingOverlay.removeEventListener('mouseup', onMouseUp, true);
|
|
|
|
movingOverlay = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Window controls
|
|
|
|
container.querySelector('div > span:first-child').removeEventListener('click', toggleOff);
|
|
|
|
container.querySelector('div').removeEventListener('mousedown', onMouseDown);
|
|
|
|
|
|
|
|
popup.removeEventListener('load', onLoad);
|
2015-05-06 16:30:45 +12:00
|
|
|
popupObserver.disconnect();
|
|
|
|
popupObserver = null;
|
|
|
|
popup.setAttribute('src', '');
|
2015-05-07 02:04:49 +12:00
|
|
|
container.removeChild(popup);
|
2015-05-06 16:30:45 +12:00
|
|
|
popup = null;
|
2015-05-07 02:04:49 +12:00
|
|
|
|
|
|
|
style.textContent = '';
|
|
|
|
style = null;
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
container = null;
|
2015-05-07 02:04:49 +12:00
|
|
|
realTabId = null;
|
2015-05-06 16:30:45 +12:00
|
|
|
};
|
|
|
|
|
2015-05-07 05:01:02 +12:00
|
|
|
var exports = {
|
|
|
|
toggleOn: function(ev) {
|
|
|
|
if ( realTabId === null ) {
|
|
|
|
toggleOn(ev.target);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
toggleOff: function() {
|
|
|
|
if ( realTabId !== null ) {
|
|
|
|
toggleOff();
|
|
|
|
}
|
2015-05-06 16:30:45 +12:00
|
|
|
}
|
|
|
|
};
|
2015-05-07 05:01:02 +12:00
|
|
|
|
|
|
|
Object.defineProperty(exports, 'tabId', {
|
|
|
|
get: function() { return realTabId || 0; }
|
|
|
|
});
|
|
|
|
|
|
|
|
return exports;
|
2015-05-06 16:30:45 +12:00
|
|
|
})();
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2015-05-04 17:01:07 +12:00
|
|
|
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',
|
2015-05-06 16:30:45 +12:00
|
|
|
name: 'maxLoggedRequests',
|
2015-05-04 17:01:07 +12:00
|
|
|
value: maxEntries
|
|
|
|
});
|
|
|
|
|
|
|
|
truncateLog(maxEntries);
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
uDom.onLoad(function() {
|
|
|
|
readLogBuffer();
|
|
|
|
|
2015-05-06 16:30:45 +12:00
|
|
|
uDom('#compactViewToggler').on('click', toggleCompactView);
|
2015-05-04 17:01:07 +12:00
|
|
|
uDom('#clear').on('click', clearBuffer);
|
|
|
|
uDom('#maxEntries').on('change', onMaxEntriesChanged);
|
2015-05-07 05:01:02 +12:00
|
|
|
uDom('#content table').on('click', 'tr.canMtx > td:nth-of-type(2)', popupManager.toggleOn);
|
2015-05-04 17:01:07 +12:00
|
|
|
});
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
})();
|