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

Disable per site #16546

Merged
merged 3 commits into from
Sep 17, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 128 additions & 22 deletions chromium/background-scripts/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,23 @@ async function initializeAllRules() {
var httpNowhereOn = false;
var showCounter = true;
var isExtensionEnabled = true;
let disabledList = new Set();

function initializeStoredGlobals(){
return new Promise(resolve => {
store.get({
httpNowhere: false,
showCounter: true,
globalEnabled: true,
enableMixedRulesets: false
enableMixedRulesets: false,
disabledList: [],
}, function(item) {
httpNowhereOn = item.httpNowhere;
showCounter = item.showCounter;
isExtensionEnabled = item.globalEnabled;
for (let disabledSite of item.disabledList) {
disabledList.add(disabledSite);
}
updateState();

rules.settings.enableMixedRulesets = item.enableMixedRulesets;
Expand Down Expand Up @@ -147,14 +152,6 @@ function updateState () {
iconState = 'blocking';
}

if ('setIcon' in chrome.browserAction) {
chrome.browserAction.setIcon({
path: {
38: 'images/icons/icon-' + iconState + '-38.png'
}
});
}

chrome.browserAction.setTitle({
title: 'HTTPS Everywhere' + ((iconState === 'active') ? '' : ' (' + iconState + ')')
});
Expand All @@ -164,16 +161,37 @@ function updateState () {
return;
}
const tabId = tabs[0].id;
const activeCount = appliedRulesets.getActiveRulesetCount(tabId);
const tabUrl = new URL(tabs[0].url);

if ('setBadgeBackgroundColor' in chrome.browserAction) {
chrome.browserAction.setBadgeBackgroundColor({ color: '#666666', tabId });
}
if (disabledList.has(tabUrl.host) || iconState == "disabled") {
if ('setIcon' in chrome.browserAction) {
chrome.browserAction.setIcon({
path: {
38: 'images/icons/icon-disabled-38.png'
}
});
}
} else {

const showBadge = activeCount > 0 && isExtensionEnabled && showCounter;
if ('setIcon' in chrome.browserAction) {
chrome.browserAction.setIcon({
path: {
38: 'images/icons/icon-' + iconState + '-38.png'
}
});
}

const activeCount = appliedRulesets.getActiveRulesetCount(tabId);

if ('setBadgeBackgroundColor' in chrome.browserAction) {
chrome.browserAction.setBadgeBackgroundColor({ color: '#666666', tabId });
}

const showBadge = activeCount > 0 && isExtensionEnabled && showCounter;

if ('setBadgeText' in chrome.browserAction) {
chrome.browserAction.setBadgeText({ text: showBadge ? String(activeCount) : '', tabId });
if ('setBadgeText' in chrome.browserAction) {
chrome.browserAction.setBadgeText({ text: showBadge ? String(activeCount) : '', tabId });
}
}
});
}
Expand Down Expand Up @@ -277,10 +295,18 @@ var urlBlacklist = new Set();
// TODO: Remove this code if they ever give us a real counter
var redirectCounter = new Map();

// Create a map to indicate whether a given request has been subject to a simple
// HTTP Nowhere redirect.
let simpleHTTPNowhereRedirect = new Map();

const cancelUrl = chrome.extension.getURL("/pages/cancel/index.html");

function redirectOnCancel(shouldCancel){
return shouldCancel ? {redirectUrl: cancelUrl} : {cancel: false};
function redirectOnCancel(shouldCancel, originURL){
return shouldCancel ? {redirectUrl: newCancelUrl(originURL)} : {cancel: false};
}

function newCancelUrl(originURL){
return cancelUrl + "?originURL=" + encodeURI(originURL);
}

/**
Expand All @@ -296,6 +322,27 @@ function onBeforeRequest(details) {

let uri = new URL(details.url);

// Check if a user has disabled HTTPS Everywhere on this site. We should
// ensure that all subresources are not run through HTTPS Everywhere as well.
let firstPartyHost;
if (details.type == "main_frame") {
firstPartyHost = uri.host;
} else {
// In Firefox, documentUrl is preferable here, since it will always be the
// URL in the URL bar, but it was only introduced in FF 54. We should get
// rid of `originUrl` at some point.
if ('documentUrl' in details) { // Firefox 54+
firstPartyHost = new URL(details.documentUrl).host;
} else if ('originUrl' in details) { // Firefox < 54
firstPartyHost = new URL(details.originUrl).host;
} else if('initiator' in details) { // Chrome
firstPartyHost = new URL(details.initiator).host;
}
}
if (disabledList.has(firstPartyHost)) {
return;
}

// Normalise hosts with tailing dots, e.g. "www.example.com."
while (uri.hostname[uri.hostname.length - 1] === '.' && uri.hostname !== '.') {
uri.hostname = uri.hostname.slice(0, -1);
Expand Down Expand Up @@ -330,7 +377,7 @@ function onBeforeRequest(details) {
" changed before processing to " + uri.href);
}
if (urlBlacklist.has(uri.href)) {
return redirectOnCancel(shouldCancel);
return redirectOnCancel(shouldCancel, details.url);
}

if (details.type == "main_frame") {
Expand All @@ -344,7 +391,7 @@ function onBeforeRequest(details) {
urlBlacklist.add(uri.href);
rules.settings.domainBlacklist.add(uri.hostname);
util.log(util.WARN, "Domain blacklisted " + uri.hostname);
return redirectOnCancel(shouldCancel);
return redirectOnCancel(shouldCancel, details.url);
}

// whether to use mozilla's upgradeToSecure BlockingResponse if available
Expand Down Expand Up @@ -398,6 +445,7 @@ function onBeforeRequest(details) {
if (shouldCancel) {
if (!newuristr) {
newuristr = uri.href.replace(/^http:/, "https:");
simpleHTTPNowhereRedirect.set(details.requestId, true);
upgradeToSecure = true;
} else {
newuristr = newuristr.replace(/^http:/, "https:");
Expand All @@ -411,7 +459,7 @@ function onBeforeRequest(details) {
)
) {
// Abort early if we're about to redirect to HTTP or FTP in HTTP Nowhere mode
return {redirectUrl: cancelUrl};
return {redirectUrl: newCancelUrl(newuristr)};
}
}

Expand All @@ -423,7 +471,7 @@ function onBeforeRequest(details) {
return {redirectUrl: newuristr};
} else {
util.log(util.INFO, 'onBeforeRequest returning shouldCancel: ' + shouldCancel);
return redirectOnCancel(shouldCancel);
return redirectOnCancel(shouldCancel, details.url);
}
}

Expand Down Expand Up @@ -579,16 +627,54 @@ function onCompleted(details) {
if (redirectCounter.has(details.requestId)) {
redirectCounter.delete(details.requestId);
}
if (simpleHTTPNowhereRedirect.has(details.requestId)) {
simpleHTTPNowhereRedirect.delete(details.requestId);
}
}

/**
* handle webrequest.onErrorOccurred, cleanup redirectCounter
* @param details details for the chrome.webRequest (see chrome doc)
*/
function onErrorOccurred(details) {
if (httpNowhereOn &&
details.type == "main_frame" &&
simpleHTTPNowhereRedirect.get(details.requestId) &&
( // Enumerate a class of errors that are likely due to HTTPS misconfigurations
details.error.indexOf("net::ERR_SSL_") == 0 ||
details.error.indexOf("net::ERR_CERT_") == 0 ||
details.error.indexOf("net::ERR_CONNECTION_") == 0 ||
details.error.indexOf("net::ERR_ABORTED") == 0 ||
details.error.indexOf("NS_ERROR_CONNECTION_REFUSED") == 0 ||
details.error.indexOf("NS_ERROR_UNKNOWN_HOST") == 0 ||
details.error.indexOf("NS_ERROR_NET_TIMEOUT") == 0 ||
details.error.indexOf("NS_ERROR_NET_ON_TLS_HANDSHAKE_ENDED") == 0 ||
details.error.indexOf("NS_BINDING_ABORTED") == 0 ||
details.error.indexOf("SSL received a record that exceeded the maximum permissible length.") == 0 ||
details.error.indexOf("Peer’s Certificate has expired.") == 0 ||
details.error.indexOf("Unable to communicate securely with peer: requested domain name does not match the server’s certificate.") == 0 ||
details.error.indexOf("Peer’s Certificate issuer is not recognized.") == 0 ||
details.error.indexOf("Peer’s Certificate has been revoked.") == 0 ||
details.error.indexOf("The server uses key pinning (HPKP) but no trusted certificate chain could be constructed that matches the pinset. Key pinning violations cannot be overridden.") == 0 ||
details.error.indexOf("SSL received a weak ephemeral Diffie-Hellman key in Server Key Exchange handshake message.") == 0 ||
details.error.indexOf("The certificate was signed using a signature algorithm that is disabled because it is not secure.") == 0 ||
details.error.indexOf("Unable to communicate securely with peer: requested domain name does not match the server’s certificate.") == 0 ||
details.error.indexOf("Cannot communicate securely with peer: no common encryption algorithm(s).") == 0
))
{
let url = new URL(details.url);
if (url.protocol == "https:") {
url.protocol = "http:";
}
chrome.tabs.update(details.tabId, {url: newCancelUrl(url.toString())});
}

if (redirectCounter.has(details.requestId)) {
redirectCounter.delete(details.requestId);
}
if (simpleHTTPNowhereRedirect.has(details.requestId)) {
simpleHTTPNowhereRedirect.delete(details.requestId);
}
}

/**
Expand Down Expand Up @@ -744,6 +830,14 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
});
}

function storeDisabledList() {
const disabledListArray = Array.from(disabledList);
store.set({disabledList: disabledListArray}, () => {
sendResponse(true);
});
return true;
}

const responses = {
get_option: () => {
store.get(message.object, sendResponse);
Expand Down Expand Up @@ -890,6 +984,18 @@ chrome.runtime.onMessage.addListener(function(message, sender, sendResponse){
sendResponse(item['last-checked']);
});
return true;
},
disable_on_site: () => {
disabledList.add(message.object);
return storeDisabledList();
},
enable_on_site: () => {
disabledList.delete(message.object);
return storeDisabledList();
},
check_if_site_disabled: () => {
sendResponse(disabledList.has(message.object));
return true;
}
};
if (message.type in responses) {
Expand Down
2 changes: 2 additions & 0 deletions chromium/pages/cancel/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
<body>
<h1 id="https-everywhere"><img src="../../images/banner-red.png" alt="HTTPS Everywhere" /></h1>
<p data-i18n="cancel_he_blocking_explainer"></p>
<p id="url-paragraph"><span id="url-label">URL: </span><a href="#" id="originURL"></a></p>
<script src="../translation.js"></script>
<script src="../util.js"></script>
<script src="ux.js"></script>
</body>
</html>
19 changes: 19 additions & 0 deletions chromium/pages/cancel/ux.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/* global sendMessage */

"use strict";

let observer;
Expand All @@ -9,6 +11,7 @@ document.addEventListener("DOMContentLoaded", () => {
} else {
observer.observe(explainer, {childList: true});
}
displayURL();
});

function replaceLink(explainer){
Expand All @@ -19,3 +22,19 @@ function replaceLink(explainer){
link.innerText = linkText;
explainer.innerHTML = explainer.innerHTML.replace(linkText, link.outerHTML);
}

function displayURL() {
const cancelURL = new URL(window.location.href);
const originURL = decodeURI(cancelURL.searchParams.get('originURL'));
const originURLLink = document.getElementById('originURL');
originURLLink.innerText = originURL;

originURLLink.addEventListener("click", function() {
if (confirm(chrome.i18n.getMessage("chrome_disable_on_this_site"))) {
const url = new URL(originURL);
sendMessage("disable_on_site", url.host, () => {
window.location = originURL;
});
}
});
}
2 changes: 1 addition & 1 deletion chromium/pages/debugging-rulesets/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<textarea id="codemirror-textarea"></textarea>
<button type="button" id="save-button">Save</button>
<div id="saved-text">Saved!</div>
<script src="../send-message.js"></script>
<script src="../util.js"></script>
<script src="ux.js"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion chromium/pages/devtools/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8">
<title></title>
<script src="../send-message.js"></script>
<script src="../util.js"></script>
<script src="ux.js"></script>
</head>
<body></body>
Expand Down
5 changes: 4 additions & 1 deletion chromium/pages/options/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<input type="checkbox" id="autoUpdateRulesets">
<label for="autoUpdateRulesets" data-i18n="options_autoUpdateRulesets"></label>
</div>
<div id="disabled-rules-wrapper">
<p class="disabled-rules-wrapper-header" data-i18n="options_disabledUrlsListed"></p>
</div>
</div>

<div class="section-wrapper" id="advanced-settings-wrapper">
Expand Down Expand Up @@ -49,6 +52,6 @@

<script src="ux.js"></script>
<script src="../translation.js"></script>
<script src="../send-message.js"></script>
<script src="../util.js"></script>
</body>
</html>
25 changes: 25 additions & 0 deletions chromium/pages/options/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,31 @@ body{
margin-bottom: 20px;
}

/** Disabled Sites Option**/
.disabled-rules-wrapper-header {
font-weight: bold;
padding-left: 5px;
}
img.remove{
cursor: pointer;
float: right;
height: 15px;
margin: 10px 0 0 8%;
width: 15px;
}
.disabled-rule-list-item:last-of-type {
border-bottom: none;
}
.disabled-rule-list-item {
border-bottom: 1px solid #ccc;
display: inline-flex;
margin-left: 5%;
width: 80%;
}
.disabled-rule-list-item p {
width: 100%;
}

.section-header{
margin-bottom: 10px;
}
Expand Down
Loading