Skip to content
Open
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Smart-HTTPS
# Smart-HTTPS with Mixed Content Upgrade
Automatically changes HTTP addresses to the secure HTTPS, and if loading encounters error, reverts it back to HTTP.

* Firefox: https://addons.mozilla.org/en-US/firefox/addon/smart-https/
Expand Down
49 changes: 49 additions & 0 deletions lib/chrome/MixedContentUpgrade.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
Modify the CSP
Copyright (C) 2016 Pascal Ernster
Copyright (C) 2017 ghost

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
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/>.
*/
'use strict';
let blacklist = localStorage;
function modifyCSP(e) {
//Look up backlist
let uri = document.createElement('a');
uri.href = e.url;

if (Number(blacklist[uri.hostname]) === 1) {
return;
}

let CSPMissing = true;
for (let header of e.responseHeaders) {
if (header.name.toLowerCase() === 'content-security-policy') {
if (typeof header.value === 'string') {
if (header.value.search('upgrade-insecure-requests') === -1) {
header.value += ';upgrade-insecure-requests';
CSPMissing = false;
}
}
}
}
if (CSPMissing) {
e.responseHeaders.push({name: 'content-security-policy', value: 'upgrade-insecure-requests'});
}
return {responseHeaders: e.responseHeaders};
}

chrome.webRequest.onHeadersReceived.addListener(modifyCSP,
{urls: ['https://*/*'], types: ['main_frame', 'sub_frame']},
['blocking', 'responseHeaders']);
3 changes: 2 additions & 1 deletion lib/chrome/background.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<head><meta charset="utf-8"></head>
<body>
<script src="../config.js"></script>
<script src="chrome.js"></script>
<script src="chrome.js"></script>
<script src="MixedContentUpgrade.js"></script>
<script id="common"></script>
</body>
</html>
2 changes: 0 additions & 2 deletions lib/chrome/chrome.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ app.loadReason = "startup";
var onBeforeRequest, onHeadersReceived, onCompleted;
app.XMLHttpRequest = function () {return new XMLHttpRequest()};
app.version = function () {return chrome.runtime.getManifest().version};
if (chrome.runtime.onInstalled) chrome.runtime.onInstalled.addListener(function (e) {app.loadReason = e.reason});
if (chrome.runtime.setUninstallURL) chrome.runtime.setUninstallURL(config.welcome.url + "?v=" + app.version() + "&type=uninstall", function () {});

app.storage = (function () {
var objs = {};
Expand Down
51 changes: 23 additions & 28 deletions lib/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

const HTTP_PROTOCOL="http:"
const HTTPS_PROTOCOL="https:"

var httpObject = config.http.object, httpsObject = config.https.object;

window.setTimeout(function () {
var version = config.welcome.version;
if (version !== app.version()) {
if (app.loadReason === "install" || app.loadReason === "startup") {
if (config.welcome.open) {
app.tabs.open(config.welcome.url + "?version=" + app.version() + (version ? "&p=" + version + "&type=upgrade" : "&type=install"));
}
config.welcome.version = app.version();
}
}
}, config.welcome.timeout);

var setToolbarIcon = function (state) {
app.button.label = 'Smart HTTPS is ' + state.toUpperCase();
Expand Down Expand Up @@ -58,36 +50,34 @@ app.popup.receive("type", function (type) {
if (type === "whitelist") {
app.tabs.getActive(function (tab) {
if (tab.url.indexOf("http://") === 0 || tab.url.indexOf("https://") === 0) {
var OLD = tab.url.replace("https://", "http://");
var domain = app.toHostname(OLD);
var domain = new URL(tab.url).hostname;
/* */
httpObject = config.http.object;
config.http.proxy[domain] = {"url": OLD, "error": true, "smart": false};
config.http.proxy[domain] = {"url": domain, "error": true, "smart": false};
config.http.object = httpObject;
/* */
httpsObject = config.https.object;
delete config.https.proxy[domain];
config.https.object = httpsObject;
/* */
app.tabs.update(tab, OLD, true);
app.tabs.update(tab, domain, true);
}
});
}
if (type === "blacklist") {
app.tabs.getActive(function (tab) {
if (tab.url.indexOf("http://") === 0 || tab.url.indexOf("https://") === 0) {
var OLD = tab.url.replace("http://", "https://");
var domain = app.toHostname(OLD);
var domain = new URL(tab.url).hostname;
/* */
httpsObject = config.https.object;
config.https.proxy[domain] = {"url": OLD, "error": true, "smart": false};
config.https.proxy[domain] = {"url": domain, "error": true, "smart": false};
config.https.object = httpsObject;
/* */
httpObject = config.http.object;
delete config.http.proxy[domain];
config.http.object = httpObject;
/* */
app.tabs.update(tab, OLD, true);
app.tabs.update(tab, domain, true);
}
});
}
Expand Down Expand Up @@ -169,12 +159,12 @@ var errorHandler = function (error, details, force, host) {
window.setTimeout(function () {
app.tabQuery(details, function (tab) {
if (tab) {
if (force || /^https:\/\//i.test(details.url)) {
if (force || new URL(details.url).protocol==HTTPS_PROTOCOL) {
config.http.proxy[domain].error = true;
config.http.proxy[domain].incognito = tab.incognito;
config.http.object = httpObject;
if (config.log.print) console.error(error + " - Reverting back to HTTP: ", config.http.proxy[domain].url);
app.tabs.update(tab, config.http.proxy[domain].url, false);
app.tabs.update(tab, top, false);
}
} else if (config.log.print) console.error(" - Couldn't find tab with url: ", details.url);
});
Expand Down Expand Up @@ -211,7 +201,7 @@ var handleExtraErrors = function (top, details) {
else callback({"error": ('net::ERR_XHR_STATUS_' + xhr.status), "details": xhr._details});
}
else { /* if the response URL is HTTP, we still have the error */
if (/^http:\/\//i.test(xhr.responseURL)) callback({"error": 'net::ERR_XHR_REDIRECT', "details": xhr._details});
if (new URL(xhr.responseURL).protocol==HTTP_PROTOCOL) callback({"error": 'net::ERR_XHR_REDIRECT', "details": xhr._details});
else callback({"error": '', "details": xhr._details});
}
}
Expand All @@ -234,16 +224,19 @@ var handleExtraErrors = function (top, details) {
};

app.onBeforeRequest(function (details) {
var top = details.url;
if (/^http:\/\//i.test(top)) {
var newURL = top.replace(/^http:\/\//i, 'https://');
let top = details.url;
let urlObj=new URL(details.url);
if (urlObj.protocol==HTTP_PROTOCOL) {
urlObj.protocol=HTTPS_PROTOCOL;
let newURL= urlObj.toString();
// var newURL = top.replace(/^http:\/\//i, 'https://');
httpObject = config.http.object;
httpsObject = config.https.object;
var domain = app.toHostname(top);
/* */
if (!config.http.proxy[domain]) {
if (!config.https.proxy[domain]) {
config.http.proxy[domain] = {"url": top, "error": false, "smart": true};
config.http.proxy[domain] = {"url": domain, "error": false, "smart": true};
config.http.object = httpObject;
if (config.log.print) console.error(" - Smart switch to HTTPS: ", newURL);
} else {
Expand All @@ -259,7 +252,8 @@ app.onBeforeRequest(function (details) {

app.onHeadersReceived(function (domain, details) {
if (config.addon.typemissmatch) {
if (/^http:\/\//i.test(details.url)) {
let urlObj=new URL(details.url);
if (urlObj.protocol==HTTP_PROTOCOL) {
if (config.http.proxy[domain]) {
if (!config.http.proxy[domain].error) {
errorHandler("net::ERR_TYPE_MISMATCH", details, true, domain);
Expand All @@ -272,6 +266,7 @@ app.onHeadersReceived(function (domain, details) {
app.onCompleted(function (e) {
var _check = function (details) {
var top = details.url;
let urlObj = new URL(details.url);
var domain = app.toHostname(top);
var msg1 = " - HTTPS is OK (" + domain + "), cleaning whitelist table";
var msg2 = " - HTTPS had Error (" + domain + "), but removed from whitelist because whitelisting is disabled";
Expand All @@ -289,7 +284,7 @@ app.onCompleted(function (e) {
httpsObject = config.https.object;
if (config.http.proxy[domain]) {
if (!details.error || config.https.proxy[domain]) {
var flag = /^https:\/\//i.test(details.url) && !config.http.proxy[domain].error;
var flag = urlObj.protocol==HTTPS_PROTOCOL && !config.http.proxy[domain].error;
if (flag) _clean(domain, msg1);
else if (config.addon.dwhitelisting) _clean(domain, msg2);
else if (config.http.proxy[domain].incognito && config.addon.incognito) _clean(domain, msg4);
Expand Down
2 changes: 1 addition & 1 deletion lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ config.addon = {
set dwhitelisting (val) {app.storage.write('dwhitelisting', val)},
set typemissmatch (val) {app.storage.write('typemissmatch', val)},
get regexp () {return app.storage.read('regexp') === "true" ? true : false},
get incognito () {return app.storage.read('incognito') === "true" ? true : false},
get incognito () {return true},
get dwhitelisting () {return app.storage.read('dwhitelisting') === "true" ? true : false},
get typemissmatch () {return app.storage.read('typemissmatch') === "true" ? true : false}
};
Expand Down
13 changes: 9 additions & 4 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"version": "0.2.0",
"name": "Smart HTTPS",
"version": "0.2.1.3",
"name": "Smart HTTPS with Mixed Content Upgrade",
"manifest_version": 2,
"short_name": "smarthttps",
"background": {"page": "lib/chrome/background.html"},
"homepage_url": "http://mybrowseraddon.com/smart-https.html",
"options_ui": {"chrome_style": true, "page": "data/options/options.html"},
"options_ui": {"chrome_style": true, "page": "data/options/options.html", "open_in_tab": true},
"description": "Automatically changes HTTP addresses to the secure HTTPS, and if loading encounters error, reverts it back to HTTP.",
"permissions": [
"tabs",
Expand All @@ -15,6 +15,11 @@
"webNavigation",
"webRequestBlocking"
],
"applications": {
"gecko": {
"id": "{f6c29eb6-2588-4872-a80a-5eff0d801e9c}"
}
},
"browser_action": {
"default_title": "Smart HTTPS",
"default_popup": "data/popup/popup.html",
Expand All @@ -30,4 +35,4 @@
"64": "data/icons/enabled/64.png",
"128": "data/icons/enabled/128.png"
}
}
}