mirror of https://github.com/gorhill/uBlock.git
parent
ee1f861deb
commit
759a156e24
|
@ -61,6 +61,14 @@ vAPI.tabs = {};
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.isNoTabId = function(tabId) {
|
||||
return tabId.toString() === '-1';
|
||||
};
|
||||
|
||||
vAPI.noTabId = '-1';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.registerListeners = function() {
|
||||
if ( typeof this.onNavigation === 'function' ) {
|
||||
chrome.webNavigation.onCommitted.addListener(this.onNavigation);
|
||||
|
|
|
@ -329,6 +329,14 @@ vAPI.tabs = {};
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.isNoTabId = function(tabId) {
|
||||
return tabId.toString() === '_';
|
||||
};
|
||||
|
||||
vAPI.noTabId = '_';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.registerListeners = function() {
|
||||
// onNavigation and onUpdated handled with tabsProgressListener
|
||||
// onClosed - handled in windowWatcher.onTabClose
|
||||
|
|
|
@ -187,6 +187,14 @@ vAPI.tabs = {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.isNoTabId = function(tabId) {
|
||||
return tabId.toString() === '-1';
|
||||
};
|
||||
|
||||
vAPI.noTabId = '-1';
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
vAPI.tabs.registerListeners = function() {
|
||||
var onNavigation = this.onNavigation;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>µBlock — Statistics</title>
|
||||
<title data-i18n="statsPageName"></title>
|
||||
<link rel="stylesheet" type="text/css" href="css/common.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/devtools.css">
|
||||
</head>
|
||||
|
|
|
@ -187,7 +187,7 @@ return asyncJobManager;
|
|||
};
|
||||
|
||||
var updateBadgeAsync = function(tabId) {
|
||||
if ( tabId < 0 ) {
|
||||
if ( vAPI.isNoTabId(tabId) ) {
|
||||
return;
|
||||
}
|
||||
µb.asyncJobs.add('updateBadge-' + tabId, tabId, updateBadge, 250);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var messager = vAPI.messaging.channel('stats.js');
|
||||
var messager = vAPI.messaging.channel('devtools.js');
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -74,9 +74,21 @@ var selectPage = function() {
|
|||
var inspector = uDom('#content');
|
||||
var currentSrc = inspector.attr('src');
|
||||
var targetSrc = 'devtool-log.html?tabId=' + tabId;
|
||||
if ( targetSrc !== currentSrc ) {
|
||||
inspector.attr('src', targetSrc);
|
||||
if ( targetSrc === currentSrc ) {
|
||||
return;
|
||||
}
|
||||
inspector.attr('src', targetSrc);
|
||||
|
||||
// This is useful for when the user force-refresh the page: this will
|
||||
// prevent a reset to the original request log.
|
||||
// This is also useful for an outside observer to find out which tab is
|
||||
// being logged, i.e. the popup menu can initialize itself according to
|
||||
// what tab is currently being logged.
|
||||
window.history.pushState(
|
||||
{},
|
||||
'',
|
||||
window.location.href.replace(/^(.+[\?&])tabId=([^&]+)(.*)$/, '$1tabId=' + tabId + '$3')
|
||||
);
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -72,7 +72,9 @@ var onMessage = function(request, sender, callback) {
|
|||
break;
|
||||
|
||||
case 'reloadTab':
|
||||
if ( vAPI.isNoTabId(request.tabId) === false ) {
|
||||
vAPI.tabs.reload(request.tabId);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'userSettings':
|
||||
|
@ -204,12 +206,35 @@ var getStats = function(tabId) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var getTargetTabId = function(tab) {
|
||||
if ( !tab ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// If the URL is that of the network request logger, fill the popup with
|
||||
// the data from the tab being observed by the logger.
|
||||
// This allows a user to actually modify filtering profile for
|
||||
// behind-the-scene requests.
|
||||
if ( tab.url.indexOf(vAPI.getURL('devtools.html')) !== 0 ) {
|
||||
return tab.id;
|
||||
}
|
||||
|
||||
// Extract the target tab id from the URL
|
||||
var matches = tab.url.match(/[\?&]tabId=([^&]+)/);
|
||||
if ( matches && matches.length === 2 ) {
|
||||
return matches[1];
|
||||
}
|
||||
return tab.id;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
var onMessage = function(request, sender, callback) {
|
||||
// Async
|
||||
switch ( request.what ) {
|
||||
case 'getPopupData':
|
||||
vAPI.tabs.get(null, function(tab) {
|
||||
var tabId = tab && tab.id;
|
||||
var tabId = getTargetTabId(tab);
|
||||
callback(getStats(tabId));
|
||||
});
|
||||
return;
|
||||
|
@ -751,7 +776,7 @@ vAPI.messaging.listen('whitelist.js', onMessage);
|
|||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
// stats.js
|
||||
// devtools.js
|
||||
|
||||
(function() {
|
||||
|
||||
|
@ -767,26 +792,42 @@ var getPageDetails = function(callback) {
|
|||
var out = {};
|
||||
var tabIds = Object.keys(µb.pageStores);
|
||||
|
||||
var countdown = tabIds.length;
|
||||
if ( countdown === 0 ) {
|
||||
// Just in case... I expect there will always be a behind-the-scene page
|
||||
// store, but just to be safe.
|
||||
if ( tabIds.length === 0 ) {
|
||||
callback(out);
|
||||
return;
|
||||
}
|
||||
|
||||
var onTabDetails = function(tab) {
|
||||
if ( tab ) {
|
||||
out[tab.id] = tab.title;
|
||||
}
|
||||
var countdown = tabIds.length;
|
||||
var doCountdown = function() {
|
||||
countdown -= 1;
|
||||
if ( countdown === 0 ) {
|
||||
callback(out);
|
||||
}
|
||||
};
|
||||
|
||||
// Let's not populate the page selector with reference itself
|
||||
var devtoolsURL = vAPI.getURL('devtools.html');
|
||||
var devtoolsURLLen = devtoolsURL.length;
|
||||
|
||||
var onTabDetails = function(tab) {
|
||||
if ( tab && tab.url.slice(0, devtoolsURLLen) !== devtoolsURL ) {
|
||||
out[tab.id] = tab.title;
|
||||
}
|
||||
doCountdown();
|
||||
};
|
||||
|
||||
var i = countdown;
|
||||
while ( i-- ) {
|
||||
// Special case: behind-the-scene virtual tab (does not really exist)
|
||||
if ( vAPI.isNoTabId(tabIds[i]) ) {
|
||||
out[vAPI.noTabId] = vAPI.i18n('logBehindTheScene');
|
||||
doCountdown();
|
||||
} else {
|
||||
vAPI.tabs.get(tabIds[i], onTabDetails);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -813,7 +854,7 @@ var onMessage = function(request, sender, callback) {
|
|||
callback(response);
|
||||
};
|
||||
|
||||
vAPI.messaging.listen('stats.js', onMessage);
|
||||
vAPI.messaging.listen('devtools.js', onMessage);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ var metadata = {
|
|||
};
|
||||
|
||||
var hashToContentMap = {};
|
||||
var urlKeyPendingMap = {};
|
||||
|
||||
var loaded = false;
|
||||
|
||||
|
@ -377,8 +378,14 @@ var cacheAsset = function(url) {
|
|||
if ( metadataExists(urlKey) ) {
|
||||
return;
|
||||
}
|
||||
// Avoid re-entrancy
|
||||
if ( urlKeyPendingMap.hasOwnProperty(urlKey) ) {
|
||||
return;
|
||||
}
|
||||
urlKeyPendingMap[urlKey] = true;
|
||||
|
||||
var onRemoteAssetLoaded = function() {
|
||||
delete urlKeyPendingMap[urlKey];
|
||||
this.onload = this.onerror = null;
|
||||
if ( this.status !== 200 ) {
|
||||
return;
|
||||
|
@ -410,6 +417,7 @@ var cacheAsset = function(url) {
|
|||
};
|
||||
|
||||
var onRemoteAssetError = function() {
|
||||
delete urlKeyPendingMap[urlKey];
|
||||
this.onload = this.onerror = null;
|
||||
};
|
||||
|
||||
|
@ -422,7 +430,11 @@ var cacheAsset = function(url) {
|
|||
|
||||
/******************************************************************************/
|
||||
|
||||
var toURL = function(url, cache) {
|
||||
var toURL = function(url, type, cache) {
|
||||
// Unsupported types
|
||||
if ( type === 'font' ) {
|
||||
return '';
|
||||
}
|
||||
exports.tryCount += 1;
|
||||
var urlKey = toUrlKey(url);
|
||||
if ( urlKey === '' ) {
|
||||
|
|
|
@ -121,12 +121,21 @@ vAPI.tabs.registerListeners();
|
|||
// hostname. This way, for a specific scheme you can create scope with
|
||||
// rules which will apply only to that scheme.
|
||||
|
||||
µb.normalizePageURL = function(pageURL) {
|
||||
µb.normalizePageURL = function(tabId, pageURL) {
|
||||
if ( vAPI.isNoTabId(tabId) ) {
|
||||
return 'http://behind-the-scene/';
|
||||
}
|
||||
var uri = this.URI.set(pageURL);
|
||||
if ( uri.scheme === 'https' || uri.scheme === 'http' ) {
|
||||
var scheme = uri.scheme;
|
||||
if ( scheme === 'https' || scheme === 'http' ) {
|
||||
return uri.normalizedURI();
|
||||
}
|
||||
return '';
|
||||
|
||||
if ( uri.hostname !== '' ) {
|
||||
return 'http://' + scheme + '-' + uri.hostname + uri.path;
|
||||
}
|
||||
|
||||
return 'http://' + scheme + '-scheme/';
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
@ -138,7 +147,7 @@ vAPI.tabs.registerListeners();
|
|||
|
||||
// https://github.com/gorhill/httpswitchboard/issues/303
|
||||
// Normalize page URL
|
||||
pageURL = this.normalizePageURL(pageURL);
|
||||
pageURL = this.normalizePageURL(tabId, pageURL);
|
||||
|
||||
// Do not create a page store for URLs which are of no interests
|
||||
if ( pageURL === '' ) {
|
||||
|
@ -194,6 +203,15 @@ vAPI.tabs.registerListeners();
|
|||
return this.pageStores[tabId];
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
// Permanent page store for behind-the-scene requests. Must never be removed.
|
||||
|
||||
µb.pageStores[vAPI.noTabId] = µb.PageStore.factory(
|
||||
vAPI.noTabId,
|
||||
µb.normalizePageURL(vAPI.noTabId)
|
||||
);
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -218,9 +236,15 @@ var pageStoreJanitor = function() {
|
|||
if ( pageStoreJanitorSampleAt >= tabIds.length ) {
|
||||
pageStoreJanitorSampleAt = 0;
|
||||
}
|
||||
var tabId;
|
||||
var n = Math.min(pageStoreJanitorSampleAt + pageStoreJanitorSampleSize, tabIds.length);
|
||||
for ( var i = pageStoreJanitorSampleAt; i < n; i++ ) {
|
||||
checkTab(tabIds[i]);
|
||||
tabId = tabIds[i];
|
||||
// Do not remove behind-the-scene page store
|
||||
if ( vAPI.isNoTabId(tabId) ) {
|
||||
continue;
|
||||
}
|
||||
checkTab(tabId);
|
||||
}
|
||||
pageStoreJanitorSampleAt = n;
|
||||
|
||||
|
|
|
@ -38,11 +38,6 @@ var onBeforeRequest = function(details) {
|
|||
|
||||
// Do not block behind the scene requests.
|
||||
var tabId = details.tabId;
|
||||
if ( tabId < 0 ) {
|
||||
// TODO: logging behind-the-scene requests could be nice..
|
||||
return;
|
||||
}
|
||||
|
||||
var µb = µBlock;
|
||||
var requestURL = details.url;
|
||||
var requestType = details.type;
|
||||
|
@ -120,7 +115,7 @@ var onBeforeRequest = function(details) {
|
|||
|
||||
// https://code.google.com/p/chromium/issues/detail?id=387198
|
||||
// Not all redirects will succeed, until bug above is fixed.
|
||||
var redirectURL = pageStore.toMirrorURL(requestURL);
|
||||
var redirectURL = pageStore.toMirrorURL(requestURL, requestType);
|
||||
if ( redirectURL !== '' ) {
|
||||
pageStore.logBuffer.writeOne(requestContext, 'ma:');
|
||||
|
||||
|
|
|
@ -288,10 +288,10 @@ var matchWhitelistDirective = function(url, hostname, directive) {
|
|||
return type;
|
||||
}
|
||||
var ext = path.slice(pos) + '.';
|
||||
if ( '.css.eot.ttf.otf.svg.woff.woff2.'.indexOf(ext) !== -1 ) {
|
||||
return 'stylesheet';
|
||||
if ( '.eot.ttf.otf.svg.woff.woff2.'.indexOf(ext) !== -1 ) {
|
||||
return 'font';
|
||||
}
|
||||
if ( '.ico.png.gif.jpg.jpeg.'.indexOf(ext) !== -1 ) {
|
||||
if ( '.ico.'.indexOf(ext) !== -1 ) {
|
||||
return 'image';
|
||||
}
|
||||
return type;
|
||||
|
|
Loading…
Reference in New Issue