Skip to content

Commit

Permalink
Wait for widget definitions and async migrations
Browse files Browse the repository at this point in the history
Upon Badger initialization.
  • Loading branch information
ghostwords committed Jul 20, 2020
1 parent a63402c commit f07b883
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 85 deletions.
50 changes: 33 additions & 17 deletions src/js/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ function Badger() {
self.setPrivacyOverrides();

self.widgetList = [];
widgetLoader.loadWidgetsFromFile("data/socialwidgets.json", (response) => {
self.widgetList = response;
let widgetListPromise = widgetLoader.loadWidgetsFromFile(
"data/socialwidgets.json").catch(console.error);
widgetListPromise.then(widgets => {
self.widgetList = widgets;
});

self.storage = new pbStorage.BadgerPen(async function (thisStorage) {
self.initializeDefaultSettings();
self.heuristicBlocking = new HeuristicBlocking.HeuristicBlocker(thisStorage);

// TODO there are async migrations
// TODO is this the right place for migrations?
self.runMigrations();
let migrationsPromise = self.runMigrations();

// kick off async initialization steps
let seedDataPromise = self.loadFirstRunSeedData().catch(console.error),
Expand All @@ -77,6 +78,8 @@ function Badger() {
});

// wait for async functions (seed data, yellowlist, ...) to resolve
await widgetListPromise;
await migrationsPromise;
await seedDataPromise;
await ylistPromise;
await dntHashesPromise;
Expand Down Expand Up @@ -687,13 +690,18 @@ Badger.prototype = {
}
},

runMigrations: function() {
var self = this;
var settings = self.getSettings();
var migrationLevel = settings.getItem('migrationLevel');
/**
* @return {Promise}
*/
runMigrations: function () {
let self = this,
settings = self.getSettings(),
migrationLevel = settings.getItem('migrationLevel'),
promises = [];

// TODO do not remove any migration methods
// TODO w/o refactoring migrationLevel handling to work differently
var migrations = [
const MIGRATIONS = [
Migrations.changePrivacySettings,
Migrations.migrateAbpToStorage,
Migrations.migrateBlockedSubdomainsToCookieblock,
Expand All @@ -715,11 +723,15 @@ Badger.prototype = {
Migrations.resetWebRTCIPHandlingPolicy2,
];

for (var i = migrationLevel; i < migrations.length; i++) {
migrations[i].call(Migrations, self);
for (let i = migrationLevel; i < MIGRATIONS.length; i++) {
let value = MIGRATIONS[i].call(Migrations, self);
if (value) {
promises.push(value);
}
settings.setItem('migrationLevel', i+1);
}

return Promise.all(promises);
},

/**
Expand Down Expand Up @@ -999,22 +1011,26 @@ Badger.prototype = {
*
* @param {Object} data the user data to merge in
* @param {Boolean} [from_migration=false] set when running from a migration to avoid infinite loop
* @returns {Promise}
*/
mergeUserData: function(data, from_migration) {
mergeUserData: function (data, from_migration) {
let self = this;

// The order of these keys is also the order in which they should be imported.
// It's important that snitch_map be imported before action_map (#1972)
["snitch_map", "action_map", "settings_map"].forEach(function(key) {
["snitch_map", "action_map", "settings_map"].forEach(function (key) {
if (data.hasOwnProperty(key)) {
let storageMap = self.storage.getBadgerStorageObject(key);
storageMap.merge(data[key]);
}
});

// for exports from older Privacy Badger versions:
// fix yellowlist getting out of sync, remove non-tracking domains, etc.
if (!from_migration) {
self.runMigrations();
if (from_migration) {
return Promise.resolve();
} else {
// for exports from older Privacy Badger versions:
// fix yellowlist getting out of sync, remove non-tracking domains, etc.
return self.runMigrations();
}
}

Expand Down
124 changes: 68 additions & 56 deletions src/js/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ exports.Migrations= {
changePrivacySettings: noop,
migrateAbpToStorage: noop,

// TODO blank out this migration?
migrateBlockedSubdomainsToCookieblock: function(badger) {
setTimeout(function() {
console.log('MIGRATING BLOCKED SUBDOMAINS THAT ARE ON COOKIE BLOCK LIST');
Expand Down Expand Up @@ -267,49 +268,54 @@ exports.Migrations= {
},

forgetCloudflare: function (badger) {
let config = {
name: '__cfduid'
};
if (badger.firstPartyDomainPotentiallyRequired) {
config.firstPartyDomain = null;
}
return new Promise(function (resolve) {
let config = {
name: '__cfduid'
};
if (badger.firstPartyDomainPotentiallyRequired) {
config.firstPartyDomain = null;
}

chrome.cookies.getAll(config, function (cookies) {
console.log("Forgetting Cloudflare domains ...");
chrome.cookies.getAll(config, function (cookies) {
console.log("Forgetting Cloudflare domains ...");

let actionMap = badger.storage.getBadgerStorageObject("action_map"),
actionClones = actionMap.getItemClones(),
snitchMap = badger.storage.getBadgerStorageObject("snitch_map"),
snitchClones = snitchMap.getItemClones(),
correctedSites = {},
// assume the tracking domains seen on these sites are all Cloudflare
cfduidFirstParties = new Set();
let actionMap = badger.storage.getBadgerStorageObject("action_map"),
actionClones = actionMap.getItemClones(),
snitchMap = badger.storage.getBadgerStorageObject("snitch_map"),
snitchClones = snitchMap.getItemClones(),
correctedSites = {},
// assume the tracking domains seen on these sites are all Cloudflare
cfduidFirstParties = new Set();

cookies.forEach(function (cookie) {
// get the base domain (also removes the leading dot)
cfduidFirstParties.add(window.getBaseDomain(cookie.domain));
});
cookies.forEach(function (cookie) {
// get the base domain (also removes the leading dot)
cfduidFirstParties.add(window.getBaseDomain(cookie.domain));
});

for (let domain in snitchClones) {
let newSnitches = snitchClones[domain].filter(
item => !cfduidFirstParties.has(item));
for (let domain in snitchClones) {
let newSnitches = snitchClones[domain].filter(
item => !cfduidFirstParties.has(item));

if (newSnitches.length) {
correctedSites[domain] = newSnitches;
if (newSnitches.length) {
correctedSites[domain] = newSnitches;
}
}
}

// clear existing maps and then use mergeUserData to rebuild them
actionMap.updateObject({});
snitchMap.updateObject({});
// clear existing maps and then use mergeUserData to rebuild them
actionMap.updateObject({});
snitchMap.updateObject({});

const data = {
snitch_map: correctedSites,
action_map: actionClones
};
const data = {
snitch_map: correctedSites,
action_map: actionClones
};

// pass in boolean 2nd parameter to flag that it's run in a migration,
// preventing infinite loop
badger.mergeUserData(data, true);

// pass in boolean 2nd parameter to flag that it's run in a migration, preventing infinite loop
badger.mergeUserData(data, true);
resolve();
});
});
},

Expand All @@ -320,31 +326,37 @@ exports.Migrations= {
},

resetWebRTCIPHandlingPolicy2: function (badger) {
if (!badger.webRTCAvailable) {
return;
}
return new Promise(function (resolve) {
if (!badger.webRTCAvailable) {
return resolve();
}

const cpn = chrome.privacy.network;
const cpn = chrome.privacy.network;

cpn.webRTCIPHandlingPolicy.get({}, function (result) {
if (!result.levelOfControl.endsWith('_by_this_extension')) {
return;
}
cpn.webRTCIPHandlingPolicy.get({}, function (result) {
if (!result.levelOfControl.endsWith('_by_this_extension')) {
return resolve();
}

// migrate default (disabled) setting for old Badger versions
// from Mode 3 to Mode 1
if (result.value == 'default_public_interface_only') {
console.log("Resetting webRTCIPHandlingPolicy ...");
cpn.webRTCIPHandlingPolicy.clear({});

// migrate enabled setting for more recent Badger versions
// from Mode 4 to Mode 3
} else if (result.value == 'disable_non_proxied_udp') {
console.log("Updating WebRTC IP leak protection setting ...");
cpn.webRTCIPHandlingPolicy.set({
value: 'default_public_interface_only'
});
}
// migrate default (disabled) setting for old Badger versions
// from Mode 3 to Mode 1
if (result.value == 'default_public_interface_only') {
console.log("Resetting webRTCIPHandlingPolicy ...");
cpn.webRTCIPHandlingPolicy.clear({}, function () {
resolve();
});

// migrate enabled setting for more recent Badger versions
// from Mode 4 to Mode 3
} else if (result.value == 'disable_non_proxied_udp') {
console.log("Updating WebRTC IP leak protection setting ...");
cpn.webRTCIPHandlingPolicy.set({
value: 'default_public_interface_only'
}, function () {
resolve();
});
}
});
});
}

Expand Down
15 changes: 8 additions & 7 deletions src/js/socialwidgetloader.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,15 @@ function getFileContents(filePath, callback) {

/**
* @param {String} filePath the path to the JSON file
* @param {Function} callback callback(socialwidgets)
* @returns {Array} array of SocialWidget objects
* @returns {Promise}
*/
function loadWidgetsFromFile(filePath, callback) {
getFileContents(filePath, function (contents) {
let widgets = initializeWidgets(JSON.parse(contents));
log("Initialized widgets from disk");
callback(widgets);
function loadWidgetsFromFile(filePath) {
return new Promise(function (resolve) {
getFileContents(filePath, function (contents) {
let widgets = initializeWidgets(JSON.parse(contents));
log("Initialized widgets from disk");
resolve(widgets);
});
});
}

Expand Down
12 changes: 7 additions & 5 deletions src/js/webrequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -1045,12 +1045,14 @@ function dispatcher(request, sender, sendResponse) {

case "mergeUserData": {
// called when a user uploads data exported from another Badger instance
badger.mergeUserData(request.data);
sendResponse({
disabledSites: badger.getDisabledSites(),
origins: badger.storage.getTrackingDomains(),
badger.mergeUserData(request.data).then(() => {
sendResponse({
disabledSites: badger.getDisabledSites(),
origins: badger.storage.getTrackingDomains(),
});
});
break;
// indicate this is an async response to chrome.runtime.onMessage
return true;
}

case "updateSettings": {
Expand Down

0 comments on commit f07b883

Please sign in to comment.