From 0622a5dbb22a79c5becf96cfbbf310432f8f961f Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Thu, 13 Jun 2013 15:40:22 -0700 Subject: [PATCH 1/6] Issue #217. Connections collected in Private Mode will not be stored in storage or uploaded to the database --- data/collusion.js | 8 ++++---- data/content-script.js | 20 +++++++++++++++----- data/ui.js | 10 +++++++++- lib/connection.js | 23 +++++++++++++---------- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/data/collusion.js b/data/collusion.js index 3e75556..ba07ecc 100644 --- a/data/collusion.js +++ b/data/collusion.js @@ -21,6 +21,7 @@ const TARGET_SUB = 10; const METHOD = 11; const STATUS = 12; const CACHEABLE = 13; +const FROM_PRIVATE_MODE = 14; window.addEventListener('load', function(evt){ // Wire up events @@ -45,7 +46,6 @@ function initCap(str){ function switchVisualization(name){ console.log('switchVisualizations(' + name + ')'); - saveConnections(allConnections); if (currentVisualization){ if (currentVisualization === visualizations[name]) return; currentVisualization.emit('remove'); @@ -67,14 +67,14 @@ function switchVisualization(name){ function saveConnections(){ if ( localStorage.connections && localStorage.connections != "[]" ){ var lastSaved = localStorage.lastSaved || 0; - var connections = allConnections.filter(function(connection){ - return ( connection[TIMESTAMP] ) > lastSaved; + var connections = excludePrivateConnection(allConnections).filter(function(connection){ + return ( connection[TIMESTAMP] > lastSaved); }); if ( connections.length > 0 ){ localStorage.connections = localStorage.connections.slice(0,-1) + "," + JSON.stringify(connections).slice(1); } }else{ - localStorage.connections = JSON.stringify(allConnections); + localStorage.connections = JSON.stringify( excludePrivateConnection(allConnections) ); } localStorage.lastSaved = Date.now(); localStorage.totalNumConnections = JSON.parse(localStorage.connections).length; diff --git a/data/content-script.js b/data/content-script.js index 2d7c669..5e3814c 100644 --- a/data/content-script.js +++ b/data/content-script.js @@ -28,19 +28,29 @@ self.port.on('init', function(collusionToken){ } }); +const FROM_PRIVATE_MODE = 14; + self.port.on("passTempConnections", function(message){ + // message can be an empty array [] or an array of connection arrays [ [], [], [] ] localStorage.tempConnections = JSON.stringify(message); self.port.emit("tempConnectionTransferred", true); localStorage.lastSaved = Date.now(); if ( localStorage.connections && localStorage.connections != "[]" ){ var allConnectionsAsString = localStorage.connections.slice(0,-1) + "," + localStorage.tempConnections.slice(1); - localStorage.connections = allConnectionsAsString; - unsafeWindow.allConnections = JSON.parse(allConnectionsAsString); + var allConnectionsAsArray = JSON.parse(allConnectionsAsString); + var allNonPrivateConnections = allConnectionsAsArray.filter(function(connection){ + return (connection[FROM_PRIVATE_MODE] == null); + }); + + localStorage.connections = JSON.stringify(allNonPrivateConnections); // do not store connections collected in private mode + unsafeWindow.allConnections = allConnectionsAsArray; }else{ - var parsedTempConnections = localStorage.tempConnections ? JSON.parse(localStorage.tempConnections) : [ [] ] ; - localStorage.connections = localStorage.tempConnections; - unsafeWindow.allConnections = parsedTempConnections; + var allNonPrivateConnections = message.filter(function(connection){ + return (connection[FROM_PRIVATE_MODE] == null); + }); + localStorage.connections = JSON.stringify(allNonPrivateConnections); // do not store connections collected in private mode + unsafeWindow.allConnections = message; } localStorage.totalNumConnections = unsafeWindow.allConnections.length; }); diff --git a/data/ui.js b/data/ui.js index 959689f..3c0e738 100644 --- a/data/ui.js +++ b/data/ui.js @@ -427,9 +427,17 @@ function exportFormat(connections){ format: 'Collusion Save File', version: '1.1', token: localStorage.collusionToken, - connections: connections + connections: excludePrivateConnection(connections) }); } + +/* Filter out connections collected in Private Mode */ +function excludePrivateConnection(connections){ + return connections.filter(function(connection){ + return (connection[FROM_PRIVATE_MODE] == null); + }) +} + /* Info Panel Connections List ===================================== */ document.querySelector(".connections-list ul").addEventListener("click", function(event){ diff --git a/lib/connection.js b/lib/connection.js index 828935a..3029752 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -46,16 +46,12 @@ console.log('Current capacity is %s% of quota', Math.round(ss.quotaUsage * 100)) /* END FLAG PERSISTENCE */ function addConnection(connection){ -// console.error("=== addConnection isPrivate = " + connection._sourceTab.isPrivate); Connection.emit("connection", connection.toLog()); // pass connection as array - - if ( ! connection._sourceTab.isPrivate ){ // add it to the simple storage - if ( !storage.tempConnections ) storage.tempConnections = []; - if ( captureAndStoreConnections ){ - storage.tempConnections.push(connection.toLog()); - console.error("====="); - console.error(connection.toLog()); - } + if ( !storage.tempConnections ) storage.tempConnections = []; + if ( captureAndStoreConnections ){ + storage.tempConnections.push(connection.toLog()); + console.error("====="); + console.error(connection.toLog()); } } @@ -228,6 +224,7 @@ Connection.TARGET_SUB = 10; Connection.METHOD = 11; Connection.STATUS = 12; Connection.CACHEABLE = 13; +Connection.FROM_PRIVATE_MODE = 14; // FIXME: Move data shaping into its own library? /* BEGIN FLAG SERIALIZATION */ @@ -235,7 +232,7 @@ Connection.prototype.toLog = function(){ if (!this.valid){ throw new Error('Do not log invalid connections: ' + this); } - return [ + var connectionAsArray = [ this.source, this.target, this.timestamp.valueOf(), @@ -251,6 +248,12 @@ Connection.prototype.toLog = function(){ this.status, this.cacheable ]; + + if ( this._sourceTab.isPrivate ){ + connectionAsArray.push("fromPrivateMode"); + } + + return connectionAsArray; }; /* END FLAG SERIALIZATION */ From 7320b065f764c00be00c2b271e85ccd71b388956 Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Thu, 13 Jun 2013 16:25:47 -0700 Subject: [PATCH 2/6] code cleanup for summary block on list view --- data/list.js | 28 +++++++++++++--------------- data/ui.js | 15 --------------- 2 files changed, 13 insertions(+), 30 deletions(-) diff --git a/data/list.js b/data/list.js index a4e1ccd..ba97eac 100644 --- a/data/list.js +++ b/data/list.js @@ -107,22 +107,20 @@ function setUnfilteredBreadcrumb(){ var text = document.createTextNode("All"); link.appendChild(text); breadcrumb.appendChild(link); - getSummary(function(result){ - var summaryDiv = document.createElement("div"); - var timeSinceText = "Based on the data we have gathered since " + result.localTimeSince + ", "; - var timeSinceTextNode = document.createTextNode(timeSinceText); - var timeSinceDiv = document.createElement("div"); - timeSinceDiv.appendChild(timeSinceTextNode); - summaryDiv.appendChild(timeSinceDiv); - var detailText = result.numConnections + " connections were set between " + (result.numVisited+result.numBoth) + " visited sites and " + (result.numThird+result.numBoth) + " third party sites"; - var detailTextNode = document.createTextNode(detailText); - var detailDiv = document.createElement("div"); - detailDiv.appendChild(detailTextNode); - summaryDiv.appendChild(detailDiv); - - header.appendChild(summaryDiv); - }); + + var summaryDiv = document.createElement("div"); + var timeSinceText = "Based on the data we have gathered since " + new Date(allConnections[0][TIMESTAMP]) + ", "; + var timeSinceTextNode = document.createTextNode(timeSinceText); + var timeSinceDiv = document.createElement("div"); + timeSinceDiv.appendChild(timeSinceTextNode); + summaryDiv.appendChild(timeSinceDiv); + var detailText = allConnections.length + " connections were made between " + (aggregate.sitenodes.length+aggregate.bothnodes.length) + " visited sites and " + (aggregate.thirdnodes.length+aggregate.bothnodes.length) + " third party sites"; + var detailTextNode = document.createTextNode(detailText); + var detailDiv = document.createElement("div"); + detailDiv.appendChild(detailTextNode); + summaryDiv.appendChild(detailDiv); + header.appendChild(summaryDiv); } diff --git a/data/ui.js b/data/ui.js index 3c0e738..82b0c08 100644 --- a/data/ui.js +++ b/data/ui.js @@ -353,21 +353,6 @@ document.querySelector(".settings-page").addEventListener("click", function(even },false); -/* Get data summary =============================== */ - -// to be fixed -function getSummary(callback){ - var summary = {}; - summary.localTimeSince = "(to be fixed)"; - summary.numConnections = allConnections.length; - summary.numAllSites = aggregate.allnodes.length; - summary.numVisited = aggregate.sitenodes.length; - summary.numThird = aggregate.thirdnodes.length; - summary.numBoth = aggregate.bothnodes.length; - callback(summary); -} - - /* Clock View ===================================== */ function highlightColludedNode(selection){ From a0ef7bd99084523e87e499408aa9ba309ef202a6 Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Thu, 13 Jun 2013 16:47:44 -0700 Subject: [PATCH 3/6] summary block on list view --- data/list.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/data/list.js b/data/list.js index ba97eac..206b24f 100644 --- a/data/list.js +++ b/data/list.js @@ -109,17 +109,21 @@ function setUnfilteredBreadcrumb(){ breadcrumb.appendChild(link); var summaryDiv = document.createElement("div"); - var timeSinceText = "Based on the data we have gathered since " + new Date(allConnections[0][TIMESTAMP]) + ", "; - var timeSinceTextNode = document.createTextNode(timeSinceText); - var timeSinceDiv = document.createElement("div"); - timeSinceDiv.appendChild(timeSinceTextNode); - summaryDiv.appendChild(timeSinceDiv); - var detailText = allConnections.length + " connections were made between " + (aggregate.sitenodes.length+aggregate.bothnodes.length) + " visited sites and " + (aggregate.thirdnodes.length+aggregate.bothnodes.length) + " third party sites"; - var detailTextNode = document.createTextNode(detailText); - var detailDiv = document.createElement("div"); - detailDiv.appendChild(detailTextNode); - summaryDiv.appendChild(detailDiv); - + if ( allConnections.length > 0 ){ + var timeSinceText = "Based on the data we have gathered since " + new Date(allConnections[0][TIMESTAMP]) + ", "; + var timeSinceTextNode = document.createTextNode(timeSinceText); + var timeSinceDiv = document.createElement("div"); + timeSinceDiv.appendChild(timeSinceTextNode); + summaryDiv.appendChild(timeSinceDiv); + var detailText = allConnections.length + " connections were made between " + (aggregate.sitenodes.length+aggregate.bothnodes.length) + " visited sites and " + (aggregate.thirdnodes.length+aggregate.bothnodes.length) + " third party sites"; + var detailTextNode = document.createTextNode(detailText); + var detailDiv = document.createElement("div"); + detailDiv.appendChild(detailTextNode); + summaryDiv.appendChild(detailDiv); + }else{ + var msg = document.createTextNode("No data has been collected yet."); + summaryDiv.appendChild(msg); + } header.appendChild(summaryDiv); } From bd6bdd45c06d8deefaef4946983afa643615a1a6 Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Thu, 13 Jun 2013 17:49:22 -0700 Subject: [PATCH 4/6] code cleanup for handling connections on the UI layer --- data/collusion.js | 1 + data/content-script.js | 30 +++++++++++++----------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/data/collusion.js b/data/collusion.js index ba07ecc..794ad41 100644 --- a/data/collusion.js +++ b/data/collusion.js @@ -46,6 +46,7 @@ function initCap(str){ function switchVisualization(name){ console.log('switchVisualizations(' + name + ')'); + saveConnections(allConnections); if (currentVisualization){ if (currentVisualization === visualizations[name]) return; currentVisualization.emit('remove'); diff --git a/data/content-script.js b/data/content-script.js index 5e3814c..7b4c2b1 100644 --- a/data/content-script.js +++ b/data/content-script.js @@ -19,7 +19,8 @@ self.port.on('init', function(collusionToken){ localStorage.collusionToken = collusionToken; if (unsafeWindow && unsafeWindow.currentVisualization){ - if ( localStorage.connections && localStorage.connections != "[]" ){ + if ( unsafeWindow.allConnections.length == 0 ){ // when the addon is initialized + localStorage.connections = localStorage.connections || "[]"; unsafeWindow.allConnections = JSON.parse(localStorage.connections); } unsafeWindow.currentVisualization.emit('init', unsafeWindow.allConnections); @@ -30,29 +31,24 @@ self.port.on('init', function(collusionToken){ const FROM_PRIVATE_MODE = 14; -self.port.on("passTempConnections", function(message){ - // message can be an empty array [] or an array of connection arrays [ [], [], [] ] - localStorage.tempConnections = JSON.stringify(message); +self.port.on("passTempConnections", function(connReceived){ + // connReceived can be an empty array [] or an array of connection arrays [ [], [], [] ] + localStorage.tempConnections = JSON.stringify(connReceived); self.port.emit("tempConnectionTransferred", true); + var allConnectionsAsArray = connReceived; localStorage.lastSaved = Date.now(); + if ( localStorage.connections && localStorage.connections != "[]" ){ var allConnectionsAsString = localStorage.connections.slice(0,-1) + "," + localStorage.tempConnections.slice(1); - var allConnectionsAsArray = JSON.parse(allConnectionsAsString); - var allNonPrivateConnections = allConnectionsAsArray.filter(function(connection){ - return (connection[FROM_PRIVATE_MODE] == null); - }); - - localStorage.connections = JSON.stringify(allNonPrivateConnections); // do not store connections collected in private mode - unsafeWindow.allConnections = allConnectionsAsArray; - }else{ - var allNonPrivateConnections = message.filter(function(connection){ - return (connection[FROM_PRIVATE_MODE] == null); - }); - localStorage.connections = JSON.stringify(allNonPrivateConnections); // do not store connections collected in private mode - unsafeWindow.allConnections = message; + allConnectionsAsArray = JSON.parse(allConnectionsAsString); } + var allNonPrivateConnections = allConnectionsAsArray.filter(function(connection){ + return (connection[FROM_PRIVATE_MODE] == null); + }); + localStorage.connections = JSON.stringify(allNonPrivateConnections); // do not store connections collected in private mode localStorage.totalNumConnections = unsafeWindow.allConnections.length; + unsafeWindow.allConnections = allConnectionsAsArray; }); From 94b1597fa473b378f8e799995e9b39c20c3c77cb Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Fri, 14 Jun 2013 11:04:58 -0700 Subject: [PATCH 5/6] added Private Browsing Window notification --- data/collusion.js | 7 +++++++ lib/ui.js | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/data/collusion.js b/data/collusion.js index 794ad41..2a0e240 100644 --- a/data/collusion.js +++ b/data/collusion.js @@ -24,6 +24,7 @@ const CACHEABLE = 13; const FROM_PRIVATE_MODE = 14; window.addEventListener('load', function(evt){ + addon.emit("privateWindowCheck"); // Wire up events document.querySelector('.btn_group.visualization').click(); document.querySelector('[data-value=' + (localStorage.visualization || 'Graph') + ']').click(); @@ -39,6 +40,12 @@ window.addEventListener('beforeunload', function(){ }, false); +addon.on("isPrivateWindow", function(isPrivate){ + if ( isPrivate ){ + alert("You've launched Collusion in a Private Browsing Window. Connections collected under Private Browsing Windows will not be perserved. They won't appear again once the Window is close."); + } +}); + function initCap(str){ return str[0].toUpperCase() + str.slice(1); } diff --git a/lib/ui.js b/lib/ui.js index 0b2be92..73da775 100644 --- a/lib/ui.js +++ b/lib/ui.js @@ -109,6 +109,11 @@ function attachToCollusionPage(worker) { Connection.on('tempConnections', onTempConnections); + worker.port.on("privateWindowCheck", function(){ + var isPrivate = require("private-browsing").isPrivate( getCollusionTab() ); + worker.port.emit("isPrivateWindow", isPrivate); + }); + worker.port.on('uiready', function(){ worker.port.emit('log', 'addon received uiready'); Connection.on('restored', onRestored); From 25e2b32d2f3e4c4573f781d69302dbf95bf38435 Mon Sep 17 00:00:00 2001 From: Mavis Ou Date: Fri, 14 Jun 2013 11:51:19 -0700 Subject: [PATCH 6/6] changed Private Browsing notification messages --- data/collusion.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/data/collusion.js b/data/collusion.js index 2a0e240..5ffb6f3 100644 --- a/data/collusion.js +++ b/data/collusion.js @@ -41,9 +41,15 @@ window.addEventListener('beforeunload', function(){ addon.on("isPrivateWindow", function(isPrivate){ - if ( isPrivate ){ - alert("You've launched Collusion in a Private Browsing Window. Connections collected under Private Browsing Windows will not be perserved. They won't appear again once the Window is close."); + if ( !localStorage.privateBrowsingMsgShown ){ + if ( isPrivate ){ + alert("You've launched Collusion in a Private Browsing Window. Data collected under Private Browsing Windows will not be perserved or stored. It will not appear again once the Window is close."); + }else{ + alert("Data collected under Private Browsing Windows will not be perserved or stored. It will not appear again once the Collusion tab is close."); + } } + + localStorage.privateBrowsingMsgShown = true; }); function initCap(str){