[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [snowflake/master] Reimagine the badge
commit e60f22833af9050cafef5ab00931c0c69867130a
Author: Arlo Breault <arlolra@xxxxxxxxx>
Date: Sun Jul 14 09:41:51 2019 +0200
Reimagine the badge
Trac 27385
---
.gitignore | 4 +
proxy/init-badge.js | 125 +++++++++++++++++----
proxy/init-testing.js | 83 ++++++++++++++
proxy/init-webext.js | 106 ++++++++++++++++-
proxy/make.js | 22 ++--
proxy/static/.htaccess | 1 -
proxy/{webext/popup.css => static/embed.css} | 7 +-
proxy/static/embed.html | 72 ++++--------
.../icons/arrowhead-right-12.svg | 0
proxy/{webext => static}/icons/status-off.png | Bin
proxy/{webext => static}/icons/status-off.svg | 0
proxy/{webext => static}/icons/status-off@xxxxxx | Bin
proxy/{webext => static}/icons/status-off@xxxxxx | Bin
proxy/{webext => static}/icons/status-on.png | Bin
proxy/{webext => static}/icons/status-on.svg | 0
proxy/{webext => static}/icons/status-on@xxxxxx | Bin
proxy/{webext => static}/icons/status-on@xxxxxx | Bin
proxy/{webext => static}/icons/status-running.png | Bin
proxy/{webext => static}/icons/status-running.svg | 0
proxy/static/index.css | 5 +
proxy/static/index.html | 11 ++
proxy/static/koch.jpg | Bin 131664 -> 0 bytes
proxy/static/popup.js | 28 +++++
proxy/static/snowflake.html | 60 ----------
proxy/ui.js | 118 -------------------
proxy/util.js | 24 ++--
proxy/webext/{popup.js => embed.js} | 29 +----
proxy/webext/manifest.json | 32 +++---
proxy/webext/popup.html | 25 -----
29 files changed, 401 insertions(+), 351 deletions(-)
diff --git a/.gitignore b/.gitignore
index a187011..315500c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/proxy/init-badge.js b/proxy/init-badge.js
index 8646bc4..f85be29 100644
--- a/proxy/init-badge.js
+++ b/proxy/init-badge.js
@@ -1,18 +1,71 @@
/* global TESTING, Util, 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 = new URLSearchParams(location.search);
@@ -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.get('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.
diff --git a/proxy/init-testing.js b/proxy/init-testing.js
new file mode 100644
index 0000000..003f2b6
--- /dev/null
+++ b/proxy/init-testing.js
@@ -0,0 +1,83 @@
+/* global TESTING, Util, 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 = new URLSearchParams(location.search);
+
+ 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;
+
+}());
diff --git a/proxy/init-webext.js b/proxy/init-webext.js
index c641621..df618e6 100644
--- a/proxy/init-webext.js
+++ b/proxy/init-webext.js
@@ -2,6 +2,110 @@
/* 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.
*/
@@ -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
diff --git a/proxy/make.js b/proxy/make.js
index 5d6e013..52ee098 100755
--- a/proxy/make.js
+++ b/proxy/make.js
@@ -26,14 +26,19 @@ var FILES_SPEC = [
'spec/websocket.spec.js'
];
-var OUTFILE = 'snowflake.js';
-
var STATIC = 'static';
-var concatJS = function(outDir, init) {
+var SHARED_FILES = [
+ 'embed.html',
+ 'embed.css',
+ 'popup.js',
+ 'icons'
+];
+
+var concatJS = function(outDir, init, outFile) {
var files;
files = FILES.concat(`init-${init}.js`);
- return exec(`cat ${files.join(' ')} > ${outDir}/${OUTFILE}`, function(err) {
+ return exec(`cat ${files.join(' ')} > ${outDir}/${outFile}`, function(err) {
if (err) {
throw err;
}
@@ -53,7 +58,7 @@ task('test', 'snowflake unit tests', function() {
exec('mkdir -p test');
exec('jasmine init >&-');
// Simply concat all the files because we're not using node exports.
- jasmineFiles = FILES.concat('init-badge.js', FILES_SPEC);
+ jasmineFiles = FILES.concat('init-testing.js', FILES_SPEC);
outFile = 'test/bundle.spec.js';
exec('echo "TESTING = true" > ' + outFile);
exec('cat ' + jasmineFiles.join(' ') + ' | cat >> ' + outFile);
@@ -68,19 +73,20 @@ task('test', 'snowflake unit tests', function() {
task('build', 'build the snowflake proxy', function() {
exec('rm -r build');
exec('cp -r ' + STATIC + '/ build/');
- concatJS('build', 'badge');
+ concatJS('build', 'badge', 'embed.js');
console.log('Snowflake prepared.');
});
task('webext', 'build the webextension', function() {
exec('mkdir -p webext');
- concatJS('webext', 'webext');
+ exec(`cp -r ${STATIC}/{${SHARED_FILES.join(',')}} webext/`);
+ concatJS('webext', 'webext', 'snowflake.js');
console.log('Webextension prepared.');
});
task('node', 'build the node binary', function() {
exec('mkdir -p build');
- concatJS('build', 'node');
+ concatJS('build', 'node', 'snowflake.js');
console.log('Node prepared.');
});
diff --git a/proxy/static/.htaccess b/proxy/static/.htaccess
index 3dd217d..f733194 100644
--- a/proxy/static/.htaccess
+++ b/proxy/static/.htaccess
@@ -1,4 +1,3 @@
<Files "embed.html">
Header always unset X-Frame-Options
</Files>
-Redirect permanent /options.html /index.html
diff --git a/proxy/webext/popup.css b/proxy/static/embed.css
similarity index 95%
rename from proxy/webext/popup.css
rename to proxy/static/embed.css
index 856e855..e6d8149 100644
--- a/proxy/webext/popup.css
+++ b/proxy/static/embed.css
@@ -2,7 +2,7 @@ body {
margin: 10px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
width: 300px;
- font-size:12px;
+ font-size: 12px;
}
#active {
@@ -27,14 +27,13 @@ body {
display: block;
position: absolute;
top: 12px;
- background-image: url(../icons/arrowhead-right-12.svg);
+ background-image: url('icons/arrowhead-right-12.svg');
width: 12px;
height: 12px;
opacity : 0.6;
z-index: 9999;
right: 0px;
margin-right: 10px;
-
}
/* Snowflake Status */
@@ -43,14 +42,12 @@ body {
-webkit-animation:spin 8s linear infinite;
-moz-animation:spin 8s linear infinite;
animation:spin 8s linear infinite;
-
fill: BlueViolet;
}
@-moz-keyframes spin { 100% { -moz-transform: rotate(360deg); } }
@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
@keyframes spin { 100% { -webkit-transform: rotate(360deg); transform:rotate(360deg); } }
-
/* Toggle */
.switch {
diff --git a/proxy/static/embed.html b/proxy/static/embed.html
index 32c26ca..a48daf3 100644
--- a/proxy/static/embed.html
+++ b/proxy/static/embed.html
@@ -1,52 +1,28 @@
<!doctype html>
<html>
-<head>
- <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
- <meta http-equiv="refresh" content="86400">
- <script type="text/javascript" src="snowflake.js"></script>
- <style>
- * {
- box-sizing: border-box;
- }
- body {
- position: absolute; width: 100%; height: 100%;
- top: 0; margin: 0 auto; padding: 0;
- background-color: #424;
- text-align: center; cursor: default;
- }
- #badge {
- margin: auto; padding: 0;
- width: 88px; height: 16px;
- background-image: url('koch.jpg');
- white-space: nowrap;
- color: #000;
- font-size: 12px; font-weight: 900;
- font-variant: small-caps;
- text-shadow: 0 0 5px #fef,
- 0 1px 2px #fef,
- 0 -1px 2px #fef,
- 1px 0px 3px #fef,
- -1px 0px 3px #fef;
- }
- .active {
- -webkit-animation: bgScroll 8s linear infinite;
- animation: bgScroll 8s linear infinite;
- }
- @-webkit-keyframes bgScroll {
- from {background-position: 0 -4%;}
- to {background-position: 0 104%;}
- }
- @keyframes bgScroll {
- from {background-position: 0 -4%;}
- to {background-position: 0 104%;}
- }
- </style>
-</head>
-<body>
- <a target="_blank" href="index.html">
- <div id="badge">
- Internet Freedom
+ <head>
+ <meta charset="utf-8" />
+ <!-- This should be essentially be a no-opt in the popup -->
+ <meta http-equiv="refresh" content="86400" />
+ <link rel="stylesheet" href="embed.css" />
+ <script src="popup.js"></script>
+ <script src="embed.js"></script>
+ </head>
+ <body>
+ <div id="active">
+ <img src="icons/status-off.png" />
+ <p>Snowflake is off</p>
+ <p></p>
</div>
- </a>
-</body>
+ <div class="b button">
+ <label id="toggle" for="enabled">Turn On</label>
+ <label class="switch">
+ <input id="enabled" type="checkbox" />
+ <span class="slider round"></span>
+ </label>
+ </div>
+ <div class="b learn">
+ <a target="_blank" href="https://snowflake.torproject.org/">Learn more</a>
+ </div>
+ </body>
</html>
diff --git a/proxy/webext/icons/arrowhead-right-12.svg b/proxy/static/icons/arrowhead-right-12.svg
similarity index 100%
rename from proxy/webext/icons/arrowhead-right-12.svg
rename to proxy/static/icons/arrowhead-right-12.svg
diff --git a/proxy/webext/icons/status-off.png b/proxy/static/icons/status-off.png
similarity index 100%
rename from proxy/webext/icons/status-off.png
rename to proxy/static/icons/status-off.png
diff --git a/proxy/webext/icons/status-off.svg b/proxy/static/icons/status-off.svg
similarity index 100%
rename from proxy/webext/icons/status-off.svg
rename to proxy/static/icons/status-off.svg
diff --git a/proxy/webext/icons/status-off@xxxxxx b/proxy/static/icons/status-off@xxxxxx
similarity index 100%
rename from proxy/webext/icons/status-off@xxxxxx
rename to proxy/static/icons/status-off@xxxxxx
diff --git a/proxy/webext/icons/status-off@xxxxxx b/proxy/static/icons/status-off@xxxxxx
similarity index 100%
rename from proxy/webext/icons/status-off@xxxxxx
rename to proxy/static/icons/status-off@xxxxxx
diff --git a/proxy/webext/icons/status-on.png b/proxy/static/icons/status-on.png
similarity index 100%
rename from proxy/webext/icons/status-on.png
rename to proxy/static/icons/status-on.png
diff --git a/proxy/webext/icons/status-on.svg b/proxy/static/icons/status-on.svg
similarity index 100%
rename from proxy/webext/icons/status-on.svg
rename to proxy/static/icons/status-on.svg
diff --git a/proxy/webext/icons/status-on@xxxxxx b/proxy/static/icons/status-on@xxxxxx
similarity index 100%
rename from proxy/webext/icons/status-on@xxxxxx
rename to proxy/static/icons/status-on@xxxxxx
diff --git a/proxy/webext/icons/status-on@xxxxxx b/proxy/static/icons/status-on@xxxxxx
similarity index 100%
rename from proxy/webext/icons/status-on@xxxxxx
rename to proxy/static/icons/status-on@xxxxxx
diff --git a/proxy/webext/icons/status-running.png b/proxy/static/icons/status-running.png
similarity index 100%
rename from proxy/webext/icons/status-running.png
rename to proxy/static/icons/status-running.png
diff --git a/proxy/webext/icons/status-running.svg b/proxy/static/icons/status-running.svg
similarity index 100%
rename from proxy/webext/icons/status-running.svg
rename to proxy/static/icons/status-running.svg
diff --git a/proxy/static/index.css b/proxy/static/index.css
index 70b5a24..9502a37 100644
--- a/proxy/static/index.css
+++ b/proxy/static/index.css
@@ -76,3 +76,8 @@ h3 {
.diagram img, .screenshot img {
max-width: 100%;
}
+
+textarea {
+ max-width: 100%;
+ width: 600px;
+}
diff --git a/proxy/static/index.html b/proxy/static/index.html
index e46c373..20fe5c8 100644
--- a/proxy/static/index.html
+++ b/proxy/static/index.html
@@ -77,6 +77,17 @@
Consider adding keywords <em>snowflake-webextension</em> or <em>snowflake-client</em>
to let us know how which part of the Snowflake system is experiencing
problems.</p>
+
+ <h3>EMBED</h3>
+
+ <p>It is now possible to embed the Snowflake badge on any website:</p>
+
+ <textarea readonly><iframe src="https://snowflake.torproject.org/embed.html" width="320px" height="200px" frameborder="0" scrolling="no"></iframe></textarea>
+
+ <p>Which looks like this:</p>
+
+ <iframe src="embed.html" width="320px" height="200px" frameborder="0" scrolling="no"></iframe>
+
</div>
</body>
</html>
diff --git a/proxy/static/koch.jpg b/proxy/static/koch.jpg
deleted file mode 100644
index 1a3c1e3..0000000
Binary files a/proxy/static/koch.jpg and /dev/null differ
diff --git a/proxy/static/popup.js b/proxy/static/popup.js
new file mode 100644
index 0000000..0995775
--- /dev/null
+++ b/proxy/static/popup.js
@@ -0,0 +1,28 @@
+/* exported Popup */
+
+class Popup {
+ constructor() {
+ this.div = document.getElementById('active');
+ this.ps = this.div.querySelectorAll('p');
+ this.img = this.div.querySelector('img');
+ }
+ setImgSrc(src) {
+ this.img.src = `icons/status-${src}.png`;
+ }
+ setStatusText(txt) {
+ this.ps[0].innerText = txt;
+ }
+ setStatusDesc(desc, color) {
+ this.ps[1].innerText = desc;
+ this.ps[1].style.color = color || 'black';
+ }
+ hideButton() {
+ document.querySelector('.button').style.display = 'none';
+ }
+ setChecked(checked) {
+ document.getElementById('enabled').checked = checked;
+ }
+ setToggleText(txt) {
+ document.getElementById('toggle').innerText = txt;
+ }
+}
diff --git a/proxy/static/snowflake.html b/proxy/static/snowflake.html
deleted file mode 100644
index 84790ed..0000000
--- a/proxy/static/snowflake.html
+++ /dev/null
@@ -1,60 +0,0 @@
-<!doctype html>
-<html>
-<head>
- <title>Snowflake</title>
- <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
- <script type="text/javascript" src="snowflake.js"></script>
- <style>
- * {
- box-sizing: border-box;
- -webkit-transition: all 0.3s;
- -moz-transition: all 0.3s;
- transition: all 0.3s;
- }
- body {
- position: absolute;
- width: 100%; height: 100%; top: 0; margin: 0 auto;
- background-color: #424;
- color: #000;
- text-align: center;
- font-size: 24px;
- font-family: monospace;
- background-image: url('koch.jpg');
- }
- textarea {
- background-color: rgba(0,0,0,0.8);
- color: #fff;
- resize: none;
- }
- .chatarea {
- position: relative; border: none;
- width: 50%; min-width: 40em;
- padding: 0.5em; margin: auto;
- }
- .active { background-color: rgba(0,50,0,0.8); }
- #msglog {
- display: block;
- width: 100%;
- min-height: 40em;
- margin-bottom: 1em;
- padding: 8px;
- }
- #status {
- background-color: rgba(0,0,0,0.9); color: #999;
- margin: 8px 0; padding: 8px 1em; cursor: default;
- font-size: 12px;
- text-align: left;
- }
- </style>
-</head>
-<body>
- <div class="chatarea">
- <div id="status">
- Timeout...
- </div>
- <textarea id="msglog" readonly>
- </textarea>
- </div>
-
-</body>
-</html>
diff --git a/proxy/ui.js b/proxy/ui.js
index 54e0897..f99affa 100644
--- a/proxy/ui.js
+++ b/proxy/ui.js
@@ -21,23 +21,6 @@ UI.prototype.active = false;
UI.prototype.enabled = true;
-class BadgeUI extends UI {
-
- constructor() {
- super();
- this.$badge = document.getElementById('badge');
- }
-
- setActive(connected) {
- super.setActive(connected);
- return this.$badge.className = connected ? 'active' : '';
- }
-
-}
-
-BadgeUI.prototype.$badge = null;
-
-
class DebugUI extends UI {
constructor() {
@@ -75,104 +58,3 @@ class DebugUI extends UI {
DebugUI.prototype.$msglog = null;
DebugUI.prototype.$status = null;
-
-
-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;
diff --git a/proxy/util.js b/proxy/util.js
index 387f0a1..88a9bf6 100644
--- a/proxy/util.js
+++ b/proxy/util.js
@@ -10,31 +10,21 @@ Contains helpers for parsing query strings and other utilities.
class Util {
static mightBeTBB() {
- return Util.TBB_UAS.indexOf(window.navigator.userAgent) > -1 && (window.navigator.mimeTypes && window.navigator.mimeTypes.length === 0);
+ return Util.TBB_UAS.indexOf(window.navigator.userAgent) > -1 && (
+ window.navigator.mimeTypes && window.navigator.mimeTypes.length === 0
+ );
}
static genSnowflakeID() {
return Math.random().toString(36).substring(2);
}
- static snowflakeIsDisabled(cookieName) {
- var cookies;
- cookies = Parse.cookie(document.cookie);
- // Do nothing if snowflake has not been opted in by user.
- if (cookies[cookieName] !== '1') {
- log('Not opted-in. Please click the badge to change options.');
- return true;
- }
- // Also do nothing if running in Tor Browser.
- if (Util.mightBeTBB()) {
- log('Will not run within Tor Browser.');
- return true;
- }
- return false;
+ static hasWebRTC() {
+ return typeof PeerConnection === 'function';
}
- static featureDetect() {
- return typeof PeerConnection === 'function';
+ static hasCookies() {
+ return navigator.cookieEnabled;
}
}
diff --git a/proxy/webext/popup.js b/proxy/webext/embed.js
similarity index 60%
rename from proxy/webext/popup.js
rename to proxy/webext/embed.js
index d8d6464..e1364bf 100644
--- a/proxy/webext/popup.js
+++ b/proxy/webext/embed.js
@@ -1,36 +1,9 @@
-/* global chrome */
+/* global chrome, Popup */
const port = chrome.runtime.connect({
name: "popup"
});
-class Popup {
- constructor() {
- this.div = document.getElementById('active');
- this.ps = this.div.querySelectorAll('p');
- this.img = this.div.querySelector('img');
- }
- setImgSrc(src) {
- this.img.src = `icons/status-${src}.png`;
- }
- setStatusText(txt) {
- this.ps[0].innerText = txt;
- }
- setStatusDesc(desc, color) {
- this.ps[1].innerText = desc;
- this.ps[1].style.color = color || 'black';
- }
- hideButton() {
- document.querySelector('.button').style.display = 'none';
- }
- setChecked(checked) {
- document.getElementById('enabled').checked = checked;
- }
- setToggleText(txt) {
- document.getElementById('toggle').innerText = txt;
- }
-}
-
port.onMessage.addListener((m) => {
const { active, enabled, total, missingFeature } = m;
const popup = new Popup();
diff --git a/proxy/webext/manifest.json b/proxy/webext/manifest.json
index 75475ae..3b96055 100644
--- a/proxy/webext/manifest.json
+++ b/proxy/webext/manifest.json
@@ -1,18 +1,18 @@
{
- "manifest_version": 2,
- "name": "Snowflake",
- "version": "0.0.8",
- "description": "Snowflake is a WebRTC pluggable transport for Tor.",
- "background": {
- "scripts": ["snowflake.js"],
- "persistent": true
- },
- "browser_action": {
- "default_icon": {
- "32": "icons/status-on.png"
- },
- "default_title": "Snowflake",
- "default_popup": "popup.html"
- },
- "permissions": ["storage"]
+ "manifest_version": 2,
+ "name": "Snowflake",
+ "version": "0.0.8",
+ "description": "Snowflake is a WebRTC pluggable transport for Tor.",
+ "background": {
+ "scripts": ["snowflake.js"],
+ "persistent": true
+ },
+ "browser_action": {
+ "default_icon": {
+ "32": "icons/status-on.png"
+ },
+ "default_title": "Snowflake",
+ "default_popup": "embed.html"
+ },
+ "permissions": ["storage"]
}
diff --git a/proxy/webext/popup.html b/proxy/webext/popup.html
deleted file mode 100644
index e3ba2f5..0000000
--- a/proxy/webext/popup.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!doctype html>
-<html>
- <head>
- <meta charset="utf-8" />
- <link rel="stylesheet" href="popup.css" />
- <script src="popup.js"></script>
- </head>
- <body>
- <div id="active">
- <img src="icons/status-on.png" />
- <p></p>
- <p></p>
- </div>
- <div class="b button">
- <label id="toggle" for="enabled">Turn On</label>
- <label class="switch">
- <input id="enabled" type="checkbox" checked/>
- <span class="slider round"></span>
- </label>
- </div>
- <div class="b learn">
- <a target="_blank" href="https://snowflake.torproject.org/">Learn more</a>
- </div>
- </body>
-</html>
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits