2014-06-24 00:42:43 +02:00
|
|
|
/*******************************************************************************
|
|
|
|
|
|
|
|
µBlock - a Chromium browser extension to block requests.
|
|
|
|
Copyright (C) 2014 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/uBlock
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* global chrome, µBlock */
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
|
|
|
|
A PageRequestStore object is used to store net requests in two ways:
|
|
|
|
|
|
|
|
To record distinct net requests
|
|
|
|
To create a log of net requests
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
µBlock.PageStore = (function() {
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
var µb = µBlock;
|
2014-07-30 07:05:35 +02:00
|
|
|
var frameStoreJunkyard = [];
|
2014-06-24 00:42:43 +02:00
|
|
|
var pageStoreJunkyard = [];
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-07-30 07:05:35 +02:00
|
|
|
var frameStoreFactory = function(frameURL) {
|
|
|
|
var entry = frameStoreJunkyard.pop();
|
|
|
|
if ( entry ) {
|
|
|
|
return entry.init(frameURL);
|
|
|
|
}
|
|
|
|
return new FrameStore(frameURL);
|
|
|
|
};
|
|
|
|
|
|
|
|
var disposeFrameStores = function(map) {
|
|
|
|
for ( var k in map ) {
|
|
|
|
if ( map.hasOwnProperty(k) === false ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if ( frameStoreJunkyard.length > 50 ) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
frameStoreJunkyard.push(map[k].dispose());
|
|
|
|
}
|
|
|
|
return {};
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
var FrameStore = function(frameURL) {
|
|
|
|
this.init(frameURL);
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
FrameStore.prototype.init = function(frameURL) {
|
|
|
|
var µburi = µb.URI;
|
|
|
|
this.pageHostname = µburi.hostnameFromURI(frameURL);
|
|
|
|
this.pageDomain = µburi.domainFromHostname(this.pageHostname);
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
FrameStore.prototype.dispose = function() {
|
|
|
|
this.pageHostname = this.pageDomain = '';
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-06-24 00:42:43 +02:00
|
|
|
var pageStoreFactory = function(tabId, pageURL) {
|
|
|
|
var entry = pageStoreJunkyard.pop();
|
|
|
|
if ( entry ) {
|
|
|
|
return entry.init(tabId, pageURL);
|
|
|
|
}
|
|
|
|
return new PageStore(tabId, pageURL);
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-07-30 07:05:35 +02:00
|
|
|
var PageStore = function(tabId, pageURL) {
|
2014-06-24 00:42:43 +02:00
|
|
|
this.init(tabId, pageURL);
|
2014-07-30 07:05:35 +02:00
|
|
|
};
|
2014-06-24 00:42:43 +02:00
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
PageStore.prototype.init = function(tabId, pageURL) {
|
|
|
|
this.tabId = tabId;
|
2014-07-14 17:24:59 +02:00
|
|
|
this.previousPageURL = '';
|
|
|
|
this.pageURL = pageURL;
|
|
|
|
this.pageHostname = µb.URI.hostnameFromURI(pageURL);
|
|
|
|
this.pageDomain = µb.URI.domainFromHostname(this.pageHostname);
|
2014-07-30 07:05:35 +02:00
|
|
|
this.frames = disposeFrameStores(this.frames);
|
2014-08-02 17:40:27 +02:00
|
|
|
this.netFiltering = true;
|
|
|
|
this.netFilteringReadTime = 0;
|
2014-07-14 17:24:59 +02:00
|
|
|
this.perLoadBlockedRequestCount = 0;
|
|
|
|
this.perLoadAllowedRequestCount = 0;
|
|
|
|
this.blockedRequests = {};
|
|
|
|
this.allowedRequests = {};
|
|
|
|
this.disposeTime = 0;
|
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
PageStore.prototype.reuse = function(pageURL) {
|
2014-08-02 17:40:27 +02:00
|
|
|
var previousPageURL = this.pageURL;
|
|
|
|
this.init(this.tabId, pageURL);
|
|
|
|
this.previousPageURL = previousPageURL;
|
2014-06-24 00:42:43 +02:00
|
|
|
return this;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
PageStore.prototype.dispose = function() {
|
|
|
|
// rhill 2013-11-07: Even though at init time these are reset, I still
|
|
|
|
// need to release the memory taken by these, which can amount to
|
|
|
|
// sizeable enough chunks (especially requests, through the request URL
|
|
|
|
// used as a key).
|
|
|
|
this.pageURL = '';
|
|
|
|
this.pageHostname = '';
|
|
|
|
this.pageDomain = '';
|
2014-07-07 01:14:32 +02:00
|
|
|
if ( pageStoreJunkyard.length < 8 ) {
|
2014-06-24 00:42:43 +02:00
|
|
|
pageStoreJunkyard.push(this);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-07-30 07:05:35 +02:00
|
|
|
PageStore.prototype.addFrame = function(frameId, frameURL) {
|
|
|
|
var frameStore = this.frames[frameId];
|
|
|
|
if ( frameStore === undefined ) {
|
|
|
|
this.frames[frameId] = frameStore = frameStoreFactory(frameURL);
|
|
|
|
//console.debug('µBlock> PageStore.addFrame(%d, "%s")', frameId, frameURL);
|
|
|
|
}
|
|
|
|
return frameStore;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
PageStore.prototype.getFrame = function(frameId) {
|
|
|
|
return this.frames[frameId];
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-08-02 17:40:27 +02:00
|
|
|
PageStore.prototype.getNetFilteringSwitch = function() {
|
|
|
|
if ( this.netFilteringReadTime < µb.netWhitelistModifyTime ) {
|
|
|
|
this.netFiltering = µb.getNetFilteringSwitch(this.pageURL, this.pageDomain);
|
|
|
|
this.netFilteringReadTime = Date.now();
|
|
|
|
}
|
|
|
|
return this.netFiltering;
|
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-07-02 18:02:29 +02:00
|
|
|
PageStore.prototype.recordRequest = function(type, url, reason) {
|
2014-07-07 01:14:32 +02:00
|
|
|
var blocked = reason !== false && reason.slice(0, 2) !== '@@';
|
2014-06-24 00:42:43 +02:00
|
|
|
|
2014-07-07 01:14:32 +02:00
|
|
|
if ( !blocked ) {
|
2014-06-24 00:42:43 +02:00
|
|
|
this.perLoadAllowedRequestCount++;
|
|
|
|
µb.localSettings.allowedRequestCount++;
|
2014-07-07 01:14:32 +02:00
|
|
|
if ( µb.userSettings.logAllowedRequests ) {
|
|
|
|
this.allowedRequests[url] = type + '\t' + (reason || '');
|
|
|
|
}
|
2014-06-27 23:06:42 +02:00
|
|
|
return;
|
2014-06-24 00:42:43 +02:00
|
|
|
}
|
2014-06-27 23:06:42 +02:00
|
|
|
|
2014-07-07 01:14:32 +02:00
|
|
|
µb.updateBadgeAsync(this.tabId);
|
|
|
|
|
2014-06-27 23:06:42 +02:00
|
|
|
this.perLoadBlockedRequestCount++;
|
|
|
|
µb.localSettings.blockedRequestCount++;
|
|
|
|
|
|
|
|
// https://github.com/gorhill/uBlock/issues/7
|
|
|
|
// https://github.com/gorhill/uBlock/issues/12
|
2014-07-03 14:28:15 +02:00
|
|
|
|
|
|
|
// No need to record blocked requests which are not image or frame, as
|
|
|
|
// these are the only ones we try to hide when they are blocked.
|
|
|
|
if ( µb.userSettings.logBlockedRequests === false ) {
|
|
|
|
if ( type === 'image' || type === 'sub_frame' ) {
|
|
|
|
this.blockedRequests[url] = true;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.blockedRequests[url] = type + '\t' + reason;
|
2014-06-24 00:42:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************/
|
|
|
|
|
2014-08-04 14:42:57 +02:00
|
|
|
PageStore.prototype.updateBadgeFromTab = function(tab) {
|
|
|
|
if ( !tab ) {
|
|
|
|
return;
|
|
|
|
}
|
2014-08-02 17:40:27 +02:00
|
|
|
var netFiltering = this.getNetFilteringSwitch();
|
|
|
|
var iconPath = netFiltering ? 'img/browsericons/icon19.png' : 'img/browsericons/icon19-off.png';
|
2014-06-24 00:42:43 +02:00
|
|
|
|
2014-08-04 14:42:57 +02:00
|
|
|
chrome.browserAction.setIcon({ tabId: tab.id, path: iconPath });
|
2014-06-24 00:42:43 +02:00
|
|
|
|
|
|
|
var iconStr = '';
|
2014-08-02 17:40:27 +02:00
|
|
|
if ( µb.userSettings.showIconBadge && netFiltering && this.perLoadBlockedRequestCount ) {
|
2014-07-25 22:12:20 +02:00
|
|
|
iconStr = this.perLoadBlockedRequestCount.toLocaleString();
|
2014-06-24 00:42:43 +02:00
|
|
|
}
|
2014-08-04 14:42:57 +02:00
|
|
|
chrome.browserAction.setBadgeText({ tabId: tab.id, text: iconStr });
|
2014-06-24 00:42:43 +02:00
|
|
|
|
|
|
|
if ( iconStr !== '' ) {
|
2014-08-04 14:42:57 +02:00
|
|
|
chrome.browserAction.setBadgeBackgroundColor({ tabId: tab.id, color: '#666' });
|
2014-06-24 00:42:43 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-08-04 14:42:57 +02:00
|
|
|
PageStore.prototype.updateBadge = function() {
|
|
|
|
// https://github.com/gorhill/uBlock/issues/19
|
|
|
|
// Since we may be called asynchronously, the tab id may not exist
|
|
|
|
// anymore, so this ensures it does still exist.
|
|
|
|
chrome.tabs.get(this.tabId, this.updateBadgeFromTab.bind(this));
|
|
|
|
};
|
|
|
|
|
2014-06-24 00:42:43 +02:00
|
|
|
/******************************************************************************/
|
|
|
|
|
|
|
|
return {
|
|
|
|
factory: pageStoreFactory
|
|
|
|
};
|
|
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
/******************************************************************************/
|