diff --git a/src/css/devtool-log.css b/src/css/devtool-log.css
index f2e79221e..d3ea119ab 100644
--- a/src/css/devtool-log.css
+++ b/src/css/devtool-log.css
@@ -37,6 +37,15 @@ body {
body.filterOff #toolbar #filterButton {
opacity: 0.25;
}
+#filterExpression.bad {
+ background-color: #fee;
+ }
+#maxEntries {
+ margin-left: 3em;
+ }
+input:focus {
+ background-color: #ffe;
+ }
#content {
margin-top: 36px;
}
diff --git a/src/css/devtools.css b/src/css/devtools.css
index 4f29fb19f..44a5892fc 100644
--- a/src/css/devtools.css
+++ b/src/css/devtools.css
@@ -27,6 +27,9 @@ body {
margin: 0 0 0 1em;
vertical-align: middle;
}
+#pageSelector {
+ max-width: 80%;
+ }
#toolbar #refresh {
margin-left: 4px;
}
diff --git a/src/devtool-log.html b/src/devtool-log.html
index 8733ee939..cd6ae644c 100644
--- a/src/devtool-log.html
+++ b/src/devtool-log.html
@@ -10,7 +10,8 @@
diff --git a/src/js/background.js b/src/js/background.js
index c640a3cb2..5beaff723 100644
--- a/src/js/background.js
+++ b/src/js/background.js
@@ -63,6 +63,7 @@ return {
externalLists: defaultExternalLists,
firewallPaneMinimized: true,
parseAllABPHideFilters: true,
+ requestLogMaxEntries: 0,
showIconBadge: true
},
diff --git a/src/js/devtool-log.js b/src/js/devtool-log.js
index c36e12a02..c2398678a 100644
--- a/src/js/devtool-log.js
+++ b/src/js/devtool-log.js
@@ -37,6 +37,15 @@ var body = doc.body;
var tbody = doc.querySelector('#content tbody');
var rowJunkyard = [];
var reFilter = null;
+var filterTargetTestResult = true;
+var maxEntries = 0;
+
+var prettyRequestTypes = {
+ 'main_frame': 'doc',
+ 'stylesheet': 'css',
+ 'sub_frame': 'frame',
+ 'xmlhttprequest': 'xhr'
+};
/******************************************************************************/
@@ -102,7 +111,7 @@ var renderLogEntry = function(entry) {
var tr = createRow();
if ( entry.result.charAt(1) === 'b' ) {
tr.classList.add('blocked');
- tr.cells[0].textContent = ' \u2212\u00A0';
+ tr.cells[0].textContent = ' -\u00A0';
} else if ( entry.result.charAt(1) === 'a' ) {
tr.classList.add('allowed');
if ( entry.result.charAt(0) === 'm' ) {
@@ -110,7 +119,7 @@ var renderLogEntry = function(entry) {
}
tr.cells[0].textContent = ' +\u00A0';
} else {
- tr.cells[0].textContent = ' ';
+ tr.cells[0].textContent = '';
}
if ( entry.type === 'main_frame' ) {
tr.classList.add('maindoc');
@@ -119,8 +128,8 @@ var renderLogEntry = function(entry) {
if ( entry.result.lastIndexOf('sa', 0) === 0 ) {
filterText = '@@' + filterText;
}
- tr.cells[1].textContent = filterText + ' ';
- tr.cells[2].textContent = entry.type + ' ';
+ 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);
@@ -144,9 +153,7 @@ var renderLogBuffer = function(buffer) {
// Prevent logger from growing infinitely and eating all memory. For
// instance someone could forget that it is left opened for some
// dynamically refreshed pages.
- while ( tbody.childElementCount > 25000 ) {
- rowJunkyard.push(tbody.removeChild(tbody.lastElementChild));
- }
+ truncateLog(maxEntries);
var yDelta = tbody.offsetHeight - height;
if ( yDelta === 0 ) {
@@ -172,6 +179,18 @@ var renderLogBuffer = function(buffer) {
/******************************************************************************/
+var truncateLog = function(size) {
+ if ( size === 0 ) {
+ size = 25000;
+ }
+ size = Math.min(size, 25000);
+ while ( tbody.childElementCount > size ) {
+ rowJunkyard.push(tbody.removeChild(tbody.lastElementChild));
+ }
+};
+
+/******************************************************************************/
+
var onBufferRead = function(buffer) {
if ( Array.isArray(buffer) ) {
renderLogBuffer(buffer);
@@ -207,7 +226,7 @@ var reloadTab = function() {
var applyFilterToRow = function(row) {
var re = reFilter;
- if ( re === null || re.test(row.textContent) ) {
+ if ( re === null || re.test(row.textContent) === filterTargetTestResult ) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
@@ -226,8 +245,9 @@ var applyFilter = function() {
return;
}
var re = reFilter;
+ var target = filterTargetTestResult;
while ( row !== null ) {
- if ( re.test(row.textContent) ) {
+ if ( re.test(row.textContent) === target ) {
row.classList.remove('hidden');
} else {
row.classList.add('hidden');
@@ -253,31 +273,50 @@ var unapplyFilter = function() {
var onFilterButton = function() {
uDom('body').toggleClass('filterOff');
- uDom('#filterExpression').nodeAt(0).focus();
};
/******************************************************************************/
var onFilterChanged = function() {
- var filterRaw = uDom('#filterExpression').val().trim();
+ 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;
- unapplyFilter();
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(/\s+/);
+ .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+.*'));
-
- applyFilter();
};
/******************************************************************************/
@@ -288,6 +327,7 @@ var onFilterChangedAsync = (function() {
var commit = function() {
timer = null;
onFilterChanged();
+ applyFilter();
};
var changed = function() {
@@ -302,6 +342,28 @@ var onFilterChangedAsync = (function() {
/******************************************************************************/
+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=([^&]+)/);
@@ -309,12 +371,19 @@ uDom.onLoad(function() {
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);
});
/******************************************************************************/