Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
<#3436>: a new per-site switch
has been added, no-scripting, which purpose is to wholly disable/enable
javascript for a given site. This new switch has precedence over all
other ways javascript can be disabled, including precedence over dynamic
filtering rules.

The popup panel will report the number of script resources which have
been seen by uBO for the current page. There is a minor inaccuracy to
be fixed regarding the count, and which fix requires to extend request
journaling.

<#308>: the `noscript` tags will
now be respected when the new no-scripting switch is in effect on a given
site.

A default setting has been added to the _Settings_ pane to
disable/enable globally the new no-script switch, such that one can
work in default-deny mode regarding javascript execution.

<uBlockOrigin/uBlock-issues#155>: a new
hidden setting, `requestJournalProcessPeriod`, has been added to
allow controlling the delay before uBO internally process it's
network request journal queue. Default to 1000 (milliseconds).
  • Loading branch information
gorhill committed Aug 31, 2018
1 parent cae7484 commit 3c85c03
Show file tree
Hide file tree
Showing 16 changed files with 347 additions and 131 deletions.
12 changes: 12 additions & 0 deletions src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@
"message":"Click to no longer block remote fonts on this site",
"description":"Tooltip for the no-remote-fonts per-site switch"
},
"popupTipNoScripting1":{
"message":"Click to wholly disable javascript on this site",
"description":"Tooltip for the no-scripting per-site switch"
},
"popupTipNoScripting2":{
"message":"Click to no longer wholly disable javascript on this site",
"description":"Tooltip for the no-remote-fonts per-site switch"

This comment has been minimized.

Copy link
@gwarser

gwarser Aug 31, 2018

Contributor

"no-remote-fonts" wrong copy-paste.

},
"popupTipGlobalRules":{
"message":"Global rules: this column is for rules which apply to all sites.",
"description":"Tooltip when hovering the top-most cell of the global-rules column."
Expand Down Expand Up @@ -299,6 +307,10 @@
"message":"Block remote fonts",
"description": ""
},
"settingsNoScriptingPrompt":{
"message":"Disable javascript",
"description": "The default state for the per-site no-scripting switch"
},
"settingsNoCSPReportsPrompt":{
"message":"Block CSP reports",
"description": "background information: https://github.com/gorhill/uBlock/issues/3150"
Expand Down
4 changes: 2 additions & 2 deletions src/css/dashboard-common.css
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ input[type="checkbox"][disabled] + label {
width: 40em;
}
.synopsis {
font-size: small;
opacity: 0.8;
display: inline-block;
padding: 0.25em 0;
}
.whatisthis {
margin: 0 0 0 8px;
Expand Down
12 changes: 6 additions & 6 deletions src/css/popup.css
Original file line number Diff line number Diff line change
Expand Up @@ -146,28 +146,28 @@ body.off #switch .fa {
#extraTools {
background-color: #eee;
border: 0;
color: #aaa;
color: #888;
margin: 0.8em 0 0 0;
padding: 4px 0;
padding: 4px 0 4px 0.8em;
text-align: center;
}
#extraTools > span {
cursor: pointer;
font-size: 1.2em;
margin: 0 0.4em;
margin: 0 0.8em 0 0;
position: relative;
}
#extraTools > span > span.badge {
color: #222;
bottom: -1px;
bottom: -2px;
font: x-small sans-serif;
position: absolute;
}
body[dir="ltr"] #extraTools > span > span.badge {
left: 100%;
/* left: 100%; */
}
body[dir="rtl"] #extraTools > span > span.badge {
right: 100%;
/* right: 100%; */
}
#extraTools > span > span:last-of-type {
color: #e00;
Expand Down
1 change: 1 addition & 0 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var µBlock = (function() { // jshint ignore:line
ignoreScriptInjectFilters: false,
manualUpdateAssetFetchPeriod: 500,
popupFontSize: 'unset',
requestJournalProcessPeriod: 1000,
suspendTabsUntilReady: false,
userResourcesLocation: 'unset'
};
Expand Down
5 changes: 5 additions & 0 deletions src/js/contentscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,11 @@ vAPI.domSurveyor = (function() {
return;
}

vAPI.messaging.send(
'contentscript',
{ what: 'shouldRenderNoscriptTags' }
);

if ( vAPI.domWatcher instanceof Object ) {
vAPI.domWatcher.start();
}
Expand Down
5 changes: 3 additions & 2 deletions src/js/hnswitches.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*******************************************************************************
uBlock Origin - a Chromium browser extension to black/white list requests.
Copyright (C) 2015-2018 Raymond Hill
Copyright (C) 2015-present 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
Expand Down Expand Up @@ -42,7 +42,8 @@ var switchBitOffsets = {
'no-cosmetic-filtering': 4,
'no-remote-fonts': 6,
'no-large-media': 8,
'no-csp-reports': 10
'no-csp-reports': 10,
'no-scripting': 12,
};

var switchStateToNameMap = {
Expand Down
81 changes: 50 additions & 31 deletions src/js/messaging.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ var onMessage = function(request, sender, callback) {
break;
}

// The concatenation with the empty string ensure that the resulting value
// is a string. This is important since tab id values are assumed to be
// of string type.
var tabId = sender && sender.tab ? sender.tab.id : 0;

// Sync
Expand Down Expand Up @@ -335,6 +332,7 @@ var popupDataFromTabId = function(tabId, tabTitle) {
r.largeMediaCount = pageStore.largeMediaCount;
r.noRemoteFonts = µb.hnSwitches.evaluateZ('no-remote-fonts', rootHostname);
r.remoteFontCount = pageStore.remoteFontCount;
r.noScripting = µb.hnSwitches.evaluateZ('no-scripting', rootHostname);
} else {
r.hostnameDict = {};
r.firewallRules = getFirewallRules();
Expand Down Expand Up @@ -374,14 +372,6 @@ var onMessage = function(request, sender, callback) {

// Async
switch ( request.what ) {
case 'getPopupLazyData':
pageStore = µb.pageStoreFromTabId(request.tabId);
if ( pageStore !== null ) {
pageStore.hiddenElementCount = 0;
µb.scriptlets.injectDeep(request.tabId, 'cosmetic-survey');
}
return;

case 'getPopupData':
popupDataFromRequest(request, callback);
return;
Expand All @@ -394,6 +384,15 @@ var onMessage = function(request, sender, callback) {
var response;

switch ( request.what ) {
case 'getPopupLazyData':
pageStore = µb.pageStoreFromTabId(request.tabId);
if ( pageStore !== null ) {
pageStore.hiddenElementCount = 0;
pageStore.inlineScriptCount = 0;
µb.scriptlets.injectDeep(request.tabId, 'dom-survey');
}
break;

case 'hasPopupContentChanged':
pageStore = µb.pageStoreFromTabId(request.tabId);
var lastModified = pageStore ? pageStore.contentLastModified : 0;
Expand Down Expand Up @@ -491,6 +490,22 @@ var onMessage = function(request, sender, callback) {
}
break;

case 'shouldRenderNoscriptTags':
if ( pageStore === null ) { break; }
let tabContext = µb.tabContextManager.lookup(tabId);
if ( tabContext === null ) { break; }
if ( pageStore.filterScripting(tabContext.rootHostname) ) {
vAPI.tabs.injectScript(
tabId,
{
file: '/js/scriptlets/noscript-spoof.js',
frameId: frameId,
runAt: 'document_end'
}
);
}
break;

case 'retrieveContentScriptParameters':
if (
pageStore === null ||
Expand Down Expand Up @@ -1233,23 +1248,22 @@ vAPI.messaging.listen('documentBlocked', onMessage);

/******************************************************************************/

var µb = µBlock;
var broadcastTimers = Object.create(null);
let µb = µBlock;
let broadcastTimers = new Map();

/******************************************************************************/

var cosmeticallyFilteredElementCountChanged = function(tabId) {
delete broadcastTimers[tabId + '-cosmeticallyFilteredElementCountChanged'];
var domSurveyFinalReport = function(tabId) {
broadcastTimers.delete(tabId + '-domSurveyReport');

var pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) {
return;
}
let pageStore = µb.pageStoreFromTabId(tabId);
if ( pageStore === null ) { return; }

vAPI.messaging.broadcast({
what: 'cosmeticallyFilteredElementCountChanged',
what: 'domSurveyFinalReport',
tabId: tabId,
count: pageStore.hiddenElementCount
affectedElementCount: pageStore.hiddenElementCount,
scriptCount: pageStore.scriptCount + pageStore.inlineScriptCount,
});
};

Expand Down Expand Up @@ -1280,8 +1294,8 @@ var logCosmeticFilters = function(tabId, details) {
/******************************************************************************/

var onMessage = function(request, sender, callback) {
var tabId = sender && sender.tab ? sender.tab.id : 0;
var pageStore = µb.pageStoreFromTabId(tabId);
let tabId = sender && sender.tab ? sender.tab.id : 0;
let pageStore = µb.pageStoreFromTabId(tabId);

// Async
switch ( request.what ) {
Expand All @@ -1293,15 +1307,20 @@ var onMessage = function(request, sender, callback) {
var response;

switch ( request.what ) {
case 'cosmeticallyFilteredElementCount':
if ( pageStore !== null && request.filteredElementCount ) {
pageStore.hiddenElementCount += request.filteredElementCount;
var broadcastKey = tabId + '-cosmeticallyFilteredElementCountChanged';
if ( broadcastTimers[broadcastKey] === undefined ) {
broadcastTimers[broadcastKey] = vAPI.setTimeout(
cosmeticallyFilteredElementCountChanged.bind(null, tabId),
case 'domSurveyTransientReport':
if ( pageStore !== null ) {
if ( request.filteredElementCount ) {
pageStore.hiddenElementCount += request.filteredElementCount;
}
if ( request.inlineScriptCount ) {
pageStore.inlineScriptCount += request.inlineScriptCount;
}
let broadcastKey = tabId + '-domSurveyReport';
if ( broadcastTimers.has(broadcastKey) === false ) {
broadcastTimers.set(broadcastKey, vAPI.setTimeout(
( ) => { domSurveyFinalReport(tabId); },
250
);
));
}
}
break;
Expand Down
47 changes: 38 additions & 9 deletions src/js/pagestore.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ PageStore.prototype.init = function(tabId, context) {
this.perLoadAllowedRequestCount = 0;
this.hiddenElementCount = ''; // Empty string means "unknown"
this.remoteFontCount = 0;
this.scriptCount = 0;
this.inlineScriptCount = 0;
this.popupBlockedCount = 0;
this.largeMediaCount = 0;
this.largeMediaTimer = null;
Expand Down Expand Up @@ -517,7 +519,10 @@ PageStore.prototype.journalAddRequest = function(hostname, result) {
result === 1 ? 0x00000001 : 0x00010000
);
if ( this.journalTimer === null ) {
this.journalTimer = vAPI.setTimeout(this.journalProcess.bind(this, true), 1000);
this.journalTimer = vAPI.setTimeout(
( ) => { this.journalProcess(true); },
µb.hiddenSettings.requestJournalProcessPeriod
);
}
};

Expand All @@ -539,7 +544,10 @@ PageStore.prototype.journalAddRootFrame = function(type, url) {
if ( this.journalTimer !== null ) {
clearTimeout(this.journalTimer);
}
this.journalTimer = vAPI.setTimeout(this.journalProcess.bind(this, true), 1000);
this.journalTimer = vAPI.setTimeout(
( ) => { this.journalProcess(true); },
µb.hiddenSettings.requestJournalProcessPeriod
);
};

PageStore.prototype.journalProcess = function(fromTimer) {
Expand All @@ -549,21 +557,20 @@ PageStore.prototype.journalProcess = function(fromTimer) {
this.journalTimer = null;

var journal = this.journal,
i, n = journal.length,
hostname, count, hostnameCounts,
n = journal.length,
aggregateCounts = 0,
now = Date.now(),
pivot = this.journalLastCommitted || 0;

// Everything after pivot originates from current page.
for ( i = pivot; i < n; i += 2 ) {
hostname = journal[i];
hostnameCounts = this.hostnameToCountMap.get(hostname);
for ( let i = pivot; i < n; i += 2 ) {
let hostname = journal[i];
let hostnameCounts = this.hostnameToCountMap.get(hostname);
if ( hostnameCounts === undefined ) {
hostnameCounts = 0;
this.contentLastModified = now;
}
count = journal[i+1];
let count = journal[i+1];
this.hostnameToCountMap.set(hostname, hostnameCounts + count);
aggregateCounts += count;
}
Expand All @@ -579,7 +586,7 @@ PageStore.prototype.journalProcess = function(fromTimer) {

// Everything before pivot does not originate from current page -- we still
// need to bump global blocked/allowed counts.
for ( i = 0; i < pivot; i += 2 ) {
for ( let i = 0; i < pivot; i += 2 ) {
aggregateCounts += journal[i+1];
}
if ( aggregateCounts !== 0 ) {
Expand Down Expand Up @@ -609,6 +616,13 @@ PageStore.prototype.filterRequest = function(context) {
return 1;
}

if ( requestType === 'script' ) {
this.scriptCount += 1;
if ( this.filterScripting(context.rootHostname) === 1 ) {
return 1;
}
}

var cacheableResult = this.cacheableResults[requestType] === true;

if ( cacheableResult ) {
Expand Down Expand Up @@ -706,6 +720,21 @@ PageStore.prototype.filterFont = function(context) {

/******************************************************************************/

PageStore.prototype.filterScripting = function(rootHostname) {
if (
this.getNetFilteringSwitch() === false ||
µb.hnSwitches.evaluateZ('no-scripting', rootHostname) === false
) {
return 0;
}
if ( µb.logger.isEnabled() ) {
this.logData = µb.hnSwitches.toLogData();
}
return 1;
};

/******************************************************************************/

// The caller is responsible to check whether filtering is enabled or not.

PageStore.prototype.filterLargeMediaElement = function(size) {
Expand Down
Loading

0 comments on commit 3c85c03

Please sign in to comment.