gorhill
10 years ago
6 changed files with 535 additions and 10 deletions
-
118src/css/logger-ui.css
-
22src/css/popup.css
-
63src/js/browsercache.js
-
309src/js/logger-ui.js
-
25src/logger-ui.html
-
8src/popup.html
@ -0,0 +1,118 @@ |
|||
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 { |
|||
background-color: #fafafa; |
|||
} |
|||
#content table tr:nth-of-type(2n+1) { |
|||
background-color: #eee; |
|||
} |
|||
#content table tr.doc { |
|||
background-color: #666; |
|||
color: white; |
|||
text-align: center; |
|||
} |
|||
#content table tr.doc > td:nth-of-type(2) { |
|||
padding: 1em 0; |
|||
white-space: normal; |
|||
word-break: break-all; |
|||
word-wrap: break-word; |
|||
} |
|||
#content table tr.cat_info { |
|||
color: #00a; |
|||
} |
|||
#content table tr.blocked { |
|||
color: #c00; |
|||
} |
|||
/* |
|||
#content table tr.allowed { |
|||
background-color: rgba(0, 160, 0, 0.1); |
|||
} |
|||
#content table tr.allowed:nth-of-type(2n+1) { |
|||
background-color: rgba(0, 160, 0, 0.2); |
|||
} |
|||
body.colorBlind #content table tr.allowed { |
|||
background-color: rgba(255, 194, 57, 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) { |
|||
text-align: center; |
|||
white-space: pre; |
|||
width: 8em; |
|||
} |
|||
#content table tr td:nth-of-type(2) { |
|||
white-space: pre; |
|||
width: 2em; |
|||
} |
|||
#content table tr td:nth-of-type(3) { |
|||
white-space: pre; |
|||
width: 8em; |
|||
} |
|||
#content table tr td:nth-of-type(4) { |
|||
border-right: none; |
|||
white-space: normal; |
|||
word-break: break-all; |
|||
word-wrap: break-word; |
|||
} |
@ -0,0 +1,63 @@ |
|||
/******************************************************************************* |
|||
|
|||
uMatrix - a Chromium browser extension to black/white list requests. |
|||
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/uMatrix
|
|||
*/ |
|||
|
|||
/* global µMatrix */ |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
(function() { |
|||
|
|||
'use strict'; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
// Browser data jobs
|
|||
|
|||
var clearCache = function() { |
|||
setTimeout(clearCache, 15 * 60 * 1000); |
|||
|
|||
var µm = µMatrix; |
|||
if ( !µm.userSettings.clearBrowserCache ) { |
|||
return; |
|||
} |
|||
|
|||
µm.clearBrowserCacheCycle -= 15; |
|||
if ( µm.clearBrowserCacheCycle > 0 ) { |
|||
return; |
|||
} |
|||
|
|||
µm.clearBrowserCacheCycle = µm.userSettings.clearBrowserCacheAfter; |
|||
µm.browserCacheClearedCounter++; |
|||
|
|||
vAPI.browserCache.clearByTime(0); |
|||
|
|||
µm.logger.writeOne('', 'info', 'browser cache cleared'); |
|||
|
|||
//console.debug('clearBrowserCacheCallback()> vAPI.browserCache.clearByTime() called');
|
|||
}; |
|||
|
|||
setTimeout(clearCache, 15 * 60 * 1000); |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
})(); |
|||
|
|||
/******************************************************************************/ |
@ -0,0 +1,309 @@ |
|||
/******************************************************************************* |
|||
|
|||
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 inspectedTabId = ''; |
|||
var maxEntries = 0; |
|||
var doc = document; |
|||
var body = doc.body; |
|||
var tbody = doc.querySelector('#content tbody'); |
|||
var trJunkyard = []; |
|||
var tdJunkyard = []; |
|||
var firstVarDataCol = 1; |
|||
var lastVarDataCol = 3; |
|||
|
|||
var prettyRequestTypes = { |
|||
'main_frame': 'doc', |
|||
'stylesheet': 'css', |
|||
'sub_frame': 'frame', |
|||
'xmlhttprequest': 'xhr' |
|||
}; |
|||
|
|||
var timeOptions = { |
|||
month: 'short', |
|||
day: '2-digit', |
|||
hour: '2-digit', |
|||
minute: '2-digit', |
|||
second: '2-digit' |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
var createCell = function() { |
|||
var td = tdJunkyard.pop(); |
|||
if ( td ) { |
|||
return td; |
|||
} |
|||
return doc.createElement('td'); |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
var createRow = function(entry) { |
|||
var tr = trJunkyard.pop(); |
|||
if ( tr ) { |
|||
tr.className = ''; |
|||
} else { |
|||
tr = doc.createElement('tr'); |
|||
} |
|||
var td; |
|||
for ( var index = 0; index < firstVarDataCol; index++ ) { |
|||
td = tr.cells[index]; |
|||
if ( td === undefined ) { |
|||
td = createCell(); |
|||
tr.appendChild(td); |
|||
} |
|||
td.removeAttribute('colspan'); |
|||
} |
|||
var i = 1, span = 1; |
|||
for (;;) { |
|||
td = tr.cells[index]; |
|||
if ( td === undefined ) { |
|||
td = createCell(); |
|||
tr.appendChild(td); |
|||
} |
|||
if ( i === lastVarDataCol ) { |
|||
break; |
|||
} |
|||
if ( entry['d' + i] === undefined ) { |
|||
span += 1; |
|||
} else { |
|||
if ( span !== 1 ) { |
|||
td.setAttribute('colspan', span); |
|||
} else { |
|||
td.removeAttribute('colspan'); |
|||
} |
|||
index += 1; |
|||
span = 1; |
|||
} |
|||
i += 1; |
|||
} |
|||
if ( span !== 1 ) { |
|||
td.setAttribute('colspan', span); |
|||
} else { |
|||
td.removeAttribute('colspan'); |
|||
} |
|||
index += 1; |
|||
while ( td = tr.cells[index] ) { |
|||
tdJunkyard.push(tr.removeChild(td)); |
|||
} |
|||
return tr; |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
var createGap = function(url) { |
|||
var tr = createRow({ d0: '' }); |
|||
tr.classList.add('doc'); |
|||
tr.cells[firstVarDataCol].textContent = url; |
|||
tbody.insertBefore(tr, tbody.firstChild); |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
var renderLogEntry = function(entry) { |
|||
var tr = createRow(entry); |
|||
|
|||
tr.classList.add('tab_' + entry.tab); |
|||
tr.classList.add('cat_' + entry.cat); |
|||
|
|||
var time = new Date(entry.tstamp); |
|||
tr.cells[0].textContent = time.toLocaleString('fullwide', timeOptions); |
|||
|
|||
switch ( entry.cat ) { |
|||
case 'info': |
|||
tr.cells[firstVarDataCol].textContent = entry.d0; |
|||
break; |
|||
|
|||
case 'net': |
|||
// 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.d1 === 'doc' ) { |
|||
createGap(entry.d2); |
|||
} |
|||
if ( entry.d0 ) { |
|||
tr.classList.add('blocked'); |
|||
tr.cells[1].textContent = '---'; |
|||
} else { |
|||
tr.cells[1].textContent = ''; |
|||
} |
|||
tr.cells[2].textContent = (prettyRequestTypes[entry.d1] || entry.d1) + '\t'; |
|||
tr.cells[3].textContent = entry.d2 + '\t'; |
|||
break; |
|||
|
|||
default: |
|||
break; |
|||
} |
|||
|
|||
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 ) { |
|||
size = 25000; |
|||
} |
|||
size = Math.min(size, 25000); |
|||
var tr; |
|||
while ( tbody.childElementCount > size ) { |
|||
tr = tbody.lastElementChild; |
|||
trJunkyard.push(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: 'readMany', tabId: inspectedTabId }, onBufferRead); |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
var clearBuffer = function() { |
|||
var tr; |
|||
while ( tbody.firstChild !== null ) { |
|||
tr = tbody.lastElementChild; |
|||
trJunkyard.push(tbody.removeChild(tr)); |
|||
} |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
var reloadTab = function() { |
|||
messager.send({ what: 'reloadTab', tabId: inspectedTabId }); |
|||
}; |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
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('#maxEntries').on('change', onMaxEntriesChanged); |
|||
}); |
|||
|
|||
/******************************************************************************/ |
|||
|
|||
})(); |
@ -0,0 +1,25 @@ |
|||
<!DOCTYPE html> |
|||
<html> |
|||
<head> |
|||
<meta charset="utf-8"> |
|||
<link rel="stylesheet" type="text/css" href="css/common.css"> |
|||
<link rel="stylesheet" type="text/css" href="css/logger-ui.css"> |
|||
<title>uMatrix log</title> |
|||
</head> |
|||
<body> |
|||
<div id="toolbar"> |
|||
<span id="reload" class="button fa"></span> |
|||
<span id="clear" class="button fa"></span> |
|||
<span id="filterButton" class="button fa"></span><input id="filterExpression" type="text" placeholder="logFilterPrompt"> |
|||
<input id="maxEntries" type="text" size="5" title="logMaxEntriesTip"> |
|||
</div> |
|||
<div id="content"> |
|||
<table><tbody></tbody></table> |
|||
</div> |
|||
<script src="js/vapi-common.js"></script> |
|||
<script src="js/vapi-client.js"></script> |
|||
<script src="js/udom.js"></script> |
|||
<script src="js/i18n.js"></script> |
|||
<script src="js/logger-ui.js"></script> |
|||
</body> |
|||
</html> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue