Skip to content

Commit

Permalink
Reimagine the badge
Browse files Browse the repository at this point in the history
Trac 27385
  • Loading branch information
arlolra committed Jul 14, 2019
1 parent d6d42e8 commit 12e7b92
Show file tree
Hide file tree
Showing 29 changed files with 402 additions and 352 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -15,5 +15,9 @@ proxy/build
proxy/node_modules
proxy/spec/support
proxy/webext/snowflake.js
proxy/webext/popup.js
proxy/webext/embed.html
proxy/webext/embed.css
proxy/webext/icons/
ignore/
npm-debug.log
125 changes: 101 additions & 24 deletions proxy/init-badge.js
@@ -1,18 +1,71 @@
/* global TESTING, Util, Query, Params, Config, DebugUI, BadgeUI, UI, Broker, Snowflake */

/*
Entry point.
UI
*/

var snowflake, query, debug, silenceNotifications, log, dbg, init;
class BadgeUI extends UI {

(function() {
constructor() {
super();
this.popup = new Popup();
}

setStatus() {}

missingFeature(missing) {
this.popup.setImgSrc('off');
this.popup.setStatusText("Snowflake is off");
this.popup.setStatusDesc(missing, 'firebrick');
this.popup.hideButton();
}

if (((typeof TESTING === "undefined" || TESTING === null) || !TESTING) && !Util.featureDetect()) {
console.log('webrtc feature not detected. shutting down');
return;
turnOn() {
const clients = this.active ? 1 : 0;
this.popup.setChecked(true);
this.popup.setToggleText('Turn Off');
this.popup.setStatusText(`${clients} client${(clients !== 1) ? 's' : ''} connected.`);
// FIXME: Share stats from webext
const total = 0;
this.popup.setStatusDesc(`Your snowflake has helped ${total} user${(total !== 1) ? 's' : ''} circumvent censorship in the last 24 hours.`);
this.popup.setImgSrc(this.active ? "running" : "on");
}

turnOff() {
this.popup.setChecked(false);
this.popup.setToggleText('Turn On');
this.popup.setStatusText("Snowflake is off");
this.popup.setStatusDesc("");
this.popup.setImgSrc("off");
}

setActive(connected) {
super.setActive(connected);
turnOn();
}

}

BadgeUI.prototype.popup = null;


/*
Entry point.
*/

// Defaults to opt-in.
var COOKIE_NAME = "snowflake-allow";
var COOKIE_LIFETIME = "Thu, 01 Jan 2038 00:00:00 GMT";
var COOKIE_EXPIRE = "Thu, 01 Jan 1970 00:00:01 GMT";

function setSnowflakeCookie(val, expires) {
document.cookie = `${COOKIE_NAME}=${val}; path=/; expires=${expires};`;
}

var debug, snowflake, config, broker, ui, log, dbg, init, update, silenceNotifications, query;

(function() {

snowflake = null;

query = Query.parse(location.search.substr(1));
Expand All @@ -35,32 +88,56 @@ var snowflake, query, debug, silenceNotifications, log, dbg, init;
}
};

update = function() {
const cookies = Parse.cookie(document.cookie);
if (cookies[COOKIE_NAME] === '1') {
ui.turnOn();
dbg('Contacting Broker at ' + broker.url);
log('Starting snowflake');
snowflake.setRelayAddr(config.relayAddr);
snowflake.beginWebRTC();
} else {
ui.turnOff();
snowflake.disable();
log('Currently not active.');
}
};

init = function() {
var broker, config, ui;
ui = new BadgeUI();

if (!Util.hasWebRTC()) {
ui.missingFeature("WebRTC feature is not detected.");
return;
}

if (!Util.hasCookies()) {
ui.missingFeature("Cookies are not enabled.");
return;
}

if (Util.mightBeTBB()) {
ui.missingFeature("Will not run within Tor Browser.");
return;
}

config = new Config;
if ('off' !== query['ratelimit']) {
config.rateLimitBytes = Params.getByteCount(query, 'ratelimit', config.rateLimitBytes);
}
ui = null;
if (document.getElementById('badge') !== null) {
ui = new BadgeUI();
} else if (document.getElementById('status') !== null) {
ui = new DebugUI();
} else {
ui = new UI();
}
broker = new Broker(config.brokerUrl);
snowflake = new Snowflake(config, ui, broker);
log('== snowflake proxy ==');
if (Util.snowflakeIsDisabled(config.cookieName)) {
// Do not activate the proxy if any number of conditions are true.
log('Currently not active.');
return;
}
// Otherwise, begin setting up WebRTC and acting as a proxy.
dbg('Contacting Broker at ' + broker.url);
snowflake.setRelayAddr(config.relayAddr);
return snowflake.beginWebRTC();
update();

document.getElementById('enabled').addEventListener('change', (event) => {
if (event.target.checked) {
setSnowflakeCookie('1', COOKIE_LIFETIME);
} else {
setSnowflakeCookie('', COOKIE_EXPIRE);
}
update();
})
};

// Notification of closing tab with active proxy.
Expand Down
83 changes: 83 additions & 0 deletions proxy/init-testing.js
@@ -0,0 +1,83 @@
/* global TESTING, Util, Query, Params, Config, DebugUI, UI, Broker, Snowflake */

/*
Entry point.
*/

var snowflake, query, debug, silenceNotifications, log, dbg, init;

(function() {

if (((typeof TESTING === "undefined" || TESTING === null) || !TESTING) && !Util.featureDetect()) {
console.log('webrtc feature not detected. shutting down');
return;
}

snowflake = null;

query = Query.parse(location.search.substr(1));

debug = Params.getBool(query, 'debug', false);

silenceNotifications = Params.getBool(query, 'silent', false);

// Log to both console and UI if applicable.
// Requires that the snowflake and UI objects are hooked up in order to
// log to console.
log = function(msg) {
console.log('Snowflake: ' + msg);
return snowflake != null ? snowflake.ui.log(msg) : void 0;
};

dbg = function(msg) {
if (debug || ((snowflake != null ? snowflake.ui : void 0) instanceof DebugUI)) {
return log(msg);
}
};

init = function() {
var broker, config, ui;
config = new Config;
if ('off' !== query['ratelimit']) {
config.rateLimitBytes = Params.getByteCount(query, 'ratelimit', config.rateLimitBytes);
}
ui = null;
if (document.getElementById('status') !== null) {
ui = new DebugUI();
} else {
ui = new UI();
}
broker = new Broker(config.brokerUrl);
snowflake = new Snowflake(config, ui, broker);
log('== snowflake proxy ==');
if (Util.snowflakeIsDisabled(config.cookieName)) {
// Do not activate the proxy if any number of conditions are true.
log('Currently not active.');
return;
}
// Otherwise, begin setting up WebRTC and acting as a proxy.
dbg('Contacting Broker at ' + broker.url);
snowflake.setRelayAddr(config.relayAddr);
return snowflake.beginWebRTC();
};

// Notification of closing tab with active proxy.
window.onbeforeunload = function() {
if (
!silenceNotifications &&
snowflake !== null &&
Snowflake.MODE.WEBRTC_READY === snowflake.state
) {
return Snowflake.MESSAGE.CONFIRMATION;
}
return null;
};

window.onunload = function() {
if (snowflake !== null) { snowflake.disable(); }
return null;
};

window.onload = init;

}());
106 changes: 105 additions & 1 deletion proxy/init-webext.js
@@ -1,6 +1,110 @@
/* global Util, chrome, Config, WebExtUI, Broker, Snowflake */
/* eslint no-unused-vars: 0 */

/*
UI
*/

class WebExtUI extends UI {

constructor() {
super();
this.onConnect = this.onConnect.bind(this);
this.onMessage = this.onMessage.bind(this);
this.onDisconnect = this.onDisconnect.bind(this);
this.initStats();
chrome.runtime.onConnect.addListener(this.onConnect);
}

initStats() {
this.stats = [0];
return setInterval((() => {
this.stats.unshift(0);
this.stats.splice(24);
return this.postActive();
}), 60 * 60 * 1000);
}

initToggle() {
chrome.storage.local.get("snowflake-enabled", (result) => {
if (result['snowflake-enabled'] !== void 0) {
this.enabled = result['snowflake-enabled'];
} else {
log("Toggle state not yet saved");
}
this.setEnabled(this.enabled);
});
}

postActive() {
var ref;
return (ref = this.port) != null ? ref.postMessage({
active: this.active,
total: this.stats.reduce((function(t, c) {
return t + c;
}), 0),
enabled: this.enabled
}) : void 0;
}

onConnect(port) {
this.port = port;
port.onDisconnect.addListener(this.onDisconnect);
port.onMessage.addListener(this.onMessage);
return this.postActive();
}

onMessage(m) {
this.enabled = m.enabled;
this.setEnabled(this.enabled);
this.postActive();
chrome.storage.local.set({
"snowflake-enabled": this.enabled
}, function() {
log("Stored toggle state");
});
}

onDisconnect() {
this.port = null;
}

setActive(connected) {
super.setActive(connected);
if (connected) {
this.stats[0] += 1;
}
this.postActive();
if (this.active) {
return chrome.browserAction.setIcon({
path: {
32: "icons/status-running.png"
}
});
} else {
return chrome.browserAction.setIcon({
path: {
32: "icons/status-on.png"
}
});
}
}

setEnabled(enabled) {
update();
return chrome.browserAction.setIcon({
path: {
32: "icons/status-" + (enabled ? "on" : "off") + ".png"
}
});
}

}

WebExtUI.prototype.port = null;

WebExtUI.prototype.stats = null;

/*
Entry point.
*/
Expand Down Expand Up @@ -30,7 +134,7 @@ var debug, snowflake, config, broker, ui, log, dbg, init, update, silenceNotific
}
};

if (!Util.featureDetect()) {
if (!Util.hasWebRTC()) {
chrome.runtime.onConnect.addListener(function(port) {
return port.postMessage({
missingFeature: true
Expand Down

0 comments on commit 12e7b92

Please sign in to comment.