Skip to content
This repository has been archived by the owner on Nov 15, 2017. It is now read-only.

Commit

Permalink
make extension opera--compatible + other odds and ends
Browse files Browse the repository at this point in the history
  • Loading branch information
gorhill committed Dec 7, 2013
1 parent 3c0ceb8 commit a8693d2
Show file tree
Hide file tree
Showing 14 changed files with 213 additions and 155 deletions.
2 changes: 1 addition & 1 deletion background.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
<script src="js/httpsb.js"></script>
<script src="js/reqstats.js"></script>
<script src="js/cookies.js"></script>
<script src="js/inject.js"></script>
<script src="js/profiler.js"></script>
<script src="js/storage.js"></script>
<script src="js/tab.js"></script>
<script src="js/traffic.js"></script>
<script src="js/contextmenu.js"></script>
<script src="js/contentscripthandlers.js"></script>
<script src="js/start.js"></script>
</body>
</html>
Binary file added icon_64.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 9 additions & 11 deletions js/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ function updateBadgeCallback(pageUrl) {
}

function updateBadge(pageUrl) {
asyncJobQueue.add('updateBadge ' + pageUrl, pageUrl, updateBadgeCallback, 250);
asyncJobQueue.add('updateBadge ' + pageUrl, pageUrl, updateBadgeCallback, 500);
}

/******************************************************************************/
Expand Down Expand Up @@ -192,23 +192,21 @@ function onMessageHandler(request, sender, callback) {
}
break;

case 'contentHasLocalStorage':
// `blocked` aka `response`
response = HTTPSB.blacklisted(request.url, 'cookie', uriTools.hostnameFromURI(request.url));
recordFromPageUrl(request.url, 'cookie', uriTools.rootURLFromURI(request.url) + '/{localStorage}', response);
response = response && HTTPSB.userSettings.deleteLocalStorage;
if ( response ) {
HTTPSB.localStorageRemovedCounter++;
}
case 'contentScriptHasLocalStorage':
response = contentScriptLocalStorageHandler(request.url)
break;

case 'contentScriptSummary':
contentScriptSummaryHandler(request.details);
break;

default:
default:
// console.error('HTTP Switchboard > onMessage > unknown request: %o', request);
break;
}
}

if ( response && callback ) {
if ( response !== undefined && callback ) {
callback(response);
}
}
Expand Down
55 changes: 36 additions & 19 deletions js/inject.js → js/contentscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,24 @@

// rhill 2013-11-09: Weird... This code is executed from HTTP Switchboard
// context first time extension is launched. Avoid this.
if ( window.location.href.match(/^https?:\/\//) ) {
if ( /^https?:\/\/./.test(window.location.href) ) {

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

function localStorageHandler(mustRemove) {
if ( mustRemove ) {
window.localStorage.clear();
// console.debug('HTTP Switchboard > found and removed non-empty localStorage');
}
}

/*----------------------------------------------------------------------------*/

// This is to take care of
// https://code.google.com/p/chromium/issues/detail?id=232410
// We look up noscript tags and force the DOM parser to parse
// them.
(function() {
function fixNoscriptTags() {
var a = document.querySelectorAll('noscript');
var i = a.length;
var html;
Expand All @@ -20,17 +29,13 @@ if ( window.location.href.match(/^https?:\/\//) ) {
html = html.replace(/&gt;/g, '>');
a[i].innerHTML = html;
}
})();
}

// Can extension remove localStorage of pages (like when cookies for
// page are blacklisted)? Need to investigate. (Well at least when
// scripts are blocked, localStorage won't happen..)
/*----------------------------------------------------------------------------*/

// This must be last, so that result is returned to extension.
// This is used so that inline script tags and preemptively blocked scripts
// (which won't generate web requests) are logged in the stats.
(function() {
function collectExternalResources() {
var r = {
refCounter: 0,
pageUrl: window.location.href,
scriptSources: {}, // to avoid duplicates
pluginSources: {}, // to avoid duplicates
Expand All @@ -50,6 +55,7 @@ if ( window.location.href.match(/^https?:\/\//) ) {
r.scriptSources[elem.src.trim()] = true;
}
}

// https://github.com/gorhill/httpswitchboard/issues/25
elems = document.querySelectorAll('object');
i = elems.length;
Expand All @@ -59,6 +65,7 @@ if ( window.location.href.match(/^https?:\/\//) ) {
r.pluginSources[elem.data.trim()] = true;
}
}

// https://github.com/gorhill/httpswitchboard/issues/25
elems = document.querySelectorAll('embed');
i = elems.length;
Expand All @@ -68,25 +75,23 @@ if ( window.location.href.match(/^https?:\/\//) ) {
r.pluginSources[elem.src.trim()] = true;
}
}

// Check for non-empty localStorage
if ( window.localStorage && window.localStorage.length ) {
r.localStorage = true;
chrome.runtime.sendMessage({
what: 'contentHasLocalStorage',
what: 'contentScriptHasLocalStorage',
url: r.pageUrl
}, function(mustRemove) {
if ( mustRemove ) {
window.localStorage.clear();
// console.debug('HTTP Switchboard > found and removed non-empty localStorage');
}
});
}, localStorageHandler);
}

// TODO: indexedDB
if ( window.indexedDB && !!window.indexedDB.webkitGetDatabaseNames ) {
// var db = window.indexedDB.webkitGetDatabaseNames().onsuccess = function(sender) {
// console.debug('webkitGetDatabaseNames(): result=%o', sender.target.result);
// };
}

// TODO: Web SQL
if ( window.openDatabase ) {
// Sad:
Expand All @@ -95,8 +100,20 @@ if ( window.location.href.match(/^https?:\/\//) ) {
}

// Important!!
return r;
})();
chrome.runtime.sendMessage({
what: 'contentScriptSummary',
details: r
});
}

/*----------------------------------------------------------------------------*/

function loadHandler() {
fixNoscriptTags();
collectExternalResources();
}

window.addEventListener('load', loadHandler);

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

Expand Down
79 changes: 79 additions & 0 deletions js/contentscripthandlers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*******************************************************************************
httpswitchboard - a Chromium browser extension to black/white list requests.
Copyright (C) 2013 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/httpswitchboard
*/

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

function contentScriptSummaryHandler(details) {
// TODO: Investigate "Error in response to tabs.executeScript: TypeError:
// Cannot read property 'pageUrl' of null" (2013-11-12). When can this
// happens?
if ( !details || !details.pageUrl ) {
return;
}
var ut = uriTools;
var httpsb = HTTPSB;
var pageUrl = ut.normalizeURI(details.pageUrl);
var pageHostname = ut.hostnameFromURI(pageUrl);
var sources, i;
var url, domain, block;

// scripts
// https://github.com/gorhill/httpswitchboard/issues/25
sources = Object.keys(details.scriptSources);
i = sources.length;
while ( i-- ) {
url = sources[i];
if ( url === '{inline_script}' ) {
domain = pageHostname;
url = pageUrl + '{inline_script}';
} else {
url = ut.normalizeURI(url);
domain = ut.hostnameFromURI(url);
}
block = httpsb.blacklisted(pageUrl, 'script', domain);
recordFromPageUrl(pageUrl, 'script', url, block);
}

// plugins
// https://github.com/gorhill/httpswitchboard/issues/25
sources = Object.keys(details.pluginSources);
i = sources.length;
while ( i-- ) {
url = ut.normalizeURI(sources[i]);
domain = ut.hostnameFromURI(url);
block = httpsb.blacklisted(pageUrl, 'object', domain);
recordFromPageUrl(pageUrl, 'object', url, block);
}
}

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

function contentScriptLocalStorageHandler(pageURL) {
var httpsb = HTTPSB;
var response = httpsb.blacklisted(pageURL, 'cookie', uriTools.hostnameFromURI(pageURL));
recordFromPageUrl(pageURL, 'cookie', uriTools.rootURLFromURI(pageURL) + '/{localStorage}', response);
response = response && httpsb.userSettings.deleteLocalStorage;
if ( response ) {
httpsb.localStorageRemovedCounter++;
}
return response;
}

2 changes: 1 addition & 1 deletion js/contextmenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function updateContextMenuHandler(tabs) {
var pageDomain = uriTools.domainFromURI(pageUrl);
var color = HTTPSB.evaluate(pageUrl, '*', pageDomain);
chrome.contextMenus.update('gdt-group0', {
title: 'Temporarily whitelist *.' + pageDomain,
title: 'Temporarily whitelist *.' + punycode.toUnicode(pageDomain),
enabled: color.charAt(0) !== 'g' && !HTTPSB.off
});
chrome.contextMenus.update('revertPermissions', {
Expand Down
31 changes: 31 additions & 0 deletions js/httpsb.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ HTTPSB.evaluate = function(src, type, hostname) {
if ( this.off ) {
return 'gpt';
}
// rhill 2013-12-07:
// stylesheets are evaluated as `main_frame`.
if ( type === 'stylesheet' ) {
type = 'main_frame';
}
return this.temporaryScopes.evaluate(src, type, hostname);
};

Expand Down Expand Up @@ -278,3 +283,29 @@ HTTPSB.savePermissions = function() {

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

HTTPSB.turnOff = function() {
this.off = true;
// rhill 2013-12-07:
// Relinquish control over javascript execution to the user.
// https://github.com/gorhill/httpswitchboard/issues/74
chrome.contentSettings.javascript.clear({});
}

HTTPSB.turnOn = function() {
chrome.contentSettings.javascript.clear({});

// rhill 2013-12-07:
// Tell Chromium to all javascript: HTTPSB will control whether
// javascript execute through `Content-Policy-Directive` and webRequest.
// https://github.com/gorhill/httpswitchboard/issues/74
chrome.contentSettings.javascript.set({
primaryPattern: 'https://*/*',
setting: 'allow'
});
chrome.contentSettings.javascript.set({
primaryPattern: 'http://*/*',
setting: 'allow'
});

this.off = false;
}
16 changes: 9 additions & 7 deletions js/lists.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ PermissionScope.prototype.assign = function(other) {
// otherwise.

PermissionScope.prototype.evaluate = function(type, hostname) {
var blacklistReadonly = this.httpsb.blacklistReadonly;
var blacklistReadonly = HTTPSB.blacklistReadonly;
var blacklist = this.black.list;
var whitelist = this.white.list;
var graylist = this.gray.list;
Expand All @@ -245,6 +245,8 @@ PermissionScope.prototype.evaluate = function(type, hostname) {
// indirect: any type, specific hostname
cellKey = '*|' + hostname;

var strictBlocking = HTTPSB.userSettings.strictBlocking;

// rhill 2013-10-26: Whitelist MUST be checked before blacklist,
// because read-only blacklists are, hum... read-only? (which means
// they can only be overriden through occultation, which means
Expand All @@ -253,7 +255,7 @@ PermissionScope.prototype.evaluate = function(type, hostname) {
// https://github.com/gorhill/httpswitchboard/issues/29
// The cell is indirectly whitelisted because of hostname, type
// must NOT be blacklisted.
if ( this.httpsb.userSettings.strictBlocking && blacklist[typeKey] ) {
if ( strictBlocking && blacklist[typeKey] ) {
return 'rpt';
}
return 'gpt';
Expand Down Expand Up @@ -286,7 +288,7 @@ PermissionScope.prototype.evaluate = function(type, hostname) {
// https://github.com/gorhill/httpswitchboard/issues/29
// The cell is indirectly whitelisted because of hostname, type
// must NOT be blacklisted.
if ( this.httpsb.userSettings.strictBlocking && blacklist[typeKey] ) {
if ( strictBlocking && blacklist[typeKey] ) {
return 'rpt';
}
return 'gpt';
Expand Down Expand Up @@ -383,7 +385,7 @@ PermissionScope.prototype.blacklist = function(type, hostname) {
// which is already in read-only blacklist (after graylisting or
// whitelisting it), user expects entry to still be blacklisted if ever
// same entry is removed from read-only blacklist.
if ( type !== '*' || !this.httpsb.blacklistReadonly[hostname] ) {
if ( type !== '*' || !HTTPSB.blacklistReadonly[hostname] ) {
changed = this.black.addOne(key) || changed;
}
return changed;
Expand All @@ -402,7 +404,7 @@ PermissionScope.prototype.graylist = function(type, hostname) {
// rhill 2013-10-25: special case, we expressly graylist only if the
// key is '*' and hostname is found in read-only blacklist, so that the
// express graylisting occults the read-only blacklist status.
if ( type === '*' && this.httpsb.blacklistReadonly[hostname] ) {
if ( type === '*' && HTTPSB.blacklistReadonly[hostname] ) {
changed = this.gray.addOne(key) || changed;
}
return changed;
Expand Down Expand Up @@ -441,7 +443,7 @@ PermissionScopes.prototype.fromString = function(s) {
var i = bin.scopes.length;
var scope, scopeBin;
while ( i-- ) {
scope = new PermissionScope(this.httpsb);
scope = new PermissionScope();
scopeBin = bin.scopes[i];
scope.fromString(scopeBin.scopeStr);
this.scopes[scopeBin.scopeKey] = scope;
Expand Down Expand Up @@ -472,7 +474,7 @@ PermissionScopes.prototype.assign = function(other) {
while ( i-- ) {
scopeKey = scopeKeys[i];
if ( !this.scopes[scopeKey] ) {
this.scopes[scopeKey] = new PermissionScope(this.httpsb);
this.scopes[scopeKey] = new PermissionScope();
this.scopes[scopeKey].assign(other.scopes[scopeKey]);
}
}
Expand Down
Loading

0 comments on commit a8693d2

Please sign in to comment.