/* * This file is part of Privacy Badger * Copyright (C) 2014 Electronic Frontier Foundation * * Privacy Badger is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as * published by the Free Software Foundation. * * Privacy Badger 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 Privacy Badger. If not, see . */ require.scopes.migrations = (function () { let utils = require("utils"); let constants = require("constants"); let noop = function () {}; let exports = {}; exports.Migrations= { changePrivacySettings: noop, migrateAbpToStorage: noop, migrateBlockedSubdomainsToCookieblock: function(badger) { setTimeout(function() { console.log('MIGRATING BLOCKED SUBDOMAINS THAT ARE ON COOKIE BLOCK LIST'); let ylist = badger.storage.getStore('cookieblock_list'); badger.storage.getAllDomainsByPresumedAction(constants.BLOCK).forEach(fqdn => { utils.explodeSubdomains(fqdn, true).forEach(domain => { if (ylist.hasItem(domain)) { console.log('moving', fqdn, 'from block to cookie block'); badger.storage.setupHeuristicAction(fqdn, constants.COOKIEBLOCK); } }); }); }, 1000 * 30); }, migrateLegacyFirefoxData: noop, migrateDntRecheckTimes: function(badger) { var action_map = badger.storage.getStore('action_map'); for (var domain in action_map.getItemClones()) { if (badger.storage.getNextUpdateForDomain(domain) === 0) { // Recheck at a random time in the next week var recheckTime = _.random(Date.now(), utils.nDaysFromNow(7)); badger.storage.touchDNTRecheckTime(domain, recheckTime); } } }, // Fixes https://github.com/EFForg/privacybadger/issues/1181 migrateDntRecheckTimes2: function(badger) { console.log('fixing DNT check times'); var action_map = badger.storage.getStore('action_map'); for (var domain in action_map.getItemClones()) { // Recheck at a random time in the next week var recheckTime = _.random(utils.oneDayFromNow(), utils.nDaysFromNow(7)); badger.storage.touchDNTRecheckTime(domain, recheckTime); } }, forgetMistakenlyBlockedDomains: function (badger) { console.log("Running migration to forget mistakenly flagged domains ..."); const MISTAKES = new Set([ '2mdn.net', 'akamaized.net', 'bootcss.com', 'cloudinary.com', 'edgesuite.net', 'ehowcdn.com', 'ewscloud.com', 'fncstatic.com', 'fontawesome.com', 'hgmsites.net', 'hsforms.net', 'hubspot.com', 'jsdelivr.net', 'jwplayer.com', 'jwpsrv.com', 'kinja-img.com', 'kxcdn.com', 'ldwgroup.com', 'metapix.net', 'optnmstr.com', 'parastorage.com', 'polyfill.io', 'qbox.me', 'rfdcontent.com', 'scene7.com', 'sinaimg.cn', 'slidesharecdn.com', 'staticworld.net', 'taleo.net', 'techhive.com', 'unpkg.com', 'uvcdn.com', 'washingtonpost.com', 'wixstatic.com', 'ykimg.com', ]); const actionMap = badger.storage.getStore("action_map"), actions = actionMap.getItemClones(), snitchMap = badger.storage.getStore("snitch_map"); for (let domain in actions) { const base = window.getBaseDomain(domain); if (!MISTAKES.has(base)) { continue; } // remove only if // user did not set an override // and domain was seen tracking const map = actions[domain]; if (map.userAction != "" || ( map.heuristicAction != constants.ALLOW && map.heuristicAction != constants.BLOCK && map.heuristicAction != constants.COOKIEBLOCK )) { continue; } console.log("Removing %s ...", domain); actionMap.deleteItem(domain); snitchMap.deleteItem(base); } }, unblockIncorrectlyBlockedDomains: function (badger) { console.log("Running migration to unblock likely incorrectly blocked domains ..."); let action_map = badger.storage.getStore("action_map"), snitch_map = badger.storage.getStore("snitch_map"); // for every blocked domain for (let domain in action_map.getItemClones()) { if (action_map.getItem(domain).heuristicAction != constants.BLOCK) { continue; } let base_domain = window.getBaseDomain(domain); // let's check snitch map // to see what state the blocked domain should be in instead let sites = snitch_map.getItem(base_domain); // default to "no tracking" // using "" and not constants.NO_TRACKING to match current behavior let action = ""; if (sites && sites.length) { if (sites.length >= constants.TRACKING_THRESHOLD) { // tracking domain over threshold, set it to cookieblock or block badger.heuristicBlocking.blocklistOrigin(base_domain, domain); continue; } else { // tracking domain below threshold action = constants.ALLOW; } } badger.storage.setupHeuristicAction(domain, action); } }, forgetBlockedDNTDomains: function(badger) { console.log('Running migration to forget mistakenly blocked DNT domains'); let action_map = badger.storage.getStore("action_map"), snitch_map = badger.storage.getStore("snitch_map"), domainsToFix = new Set(['eff.org', 'medium.com']); for (let domain in action_map.getItemClones()) { let base = window.getBaseDomain(domain); if (domainsToFix.has(base)) { action_map.deleteItem(domain); snitch_map.deleteItem(base); } } }, reapplyYellowlist: function (badger) { console.log("(Re)applying yellowlist ..."); let blocked = badger.storage.getAllDomainsByPresumedAction( constants.BLOCK); // reblock all blocked domains to trigger yellowlist logic for (let i = 0; i < blocked.length; i++) { let domain = blocked[i]; badger.heuristicBlocking.blocklistOrigin( window.getBaseDomain(domain), domain); } }, forgetNontrackingDomains: function (badger) { console.log("Forgetting non-tracking domains ..."); const actionMap = badger.storage.getStore("action_map"), actions = actionMap.getItemClones(); for (let domain in actions) { const map = actions[domain]; if (map.userAction == "" && map.heuristicAction == "") { actionMap.deleteItem(domain); } } }, resetWebRTCIPHandlingPolicy: noop, enableShowNonTrackingDomains: function (badger) { console.log("Enabling showNonTrackingDomains for some users"); let actionMap = badger.storage.getStore("action_map"), actions = actionMap.getItemClones(); // if we have any customized sliders if (Object.keys(actions).some(domain => actions[domain].userAction != "")) { // keep showing non-tracking domains in the popup badger.getSettings().setItem("showNonTrackingDomains", true); } }, forgetFirstPartySnitches: function (badger) { console.log("Removing first parties from snitch map..."); let snitchMap = badger.storage.getStore("snitch_map"), actionMap = badger.storage.getStore("action_map"), snitchClones = snitchMap.getItemClones(), actionClones = actionMap.getItemClones(), correctedSites = {}; for (let domain in snitchClones) { // creates new array of domains checking against the isThirdParty utility let newSnitches = snitchClones[domain].filter( item => utils.isThirdPartyDomain(item, domain)); if (newSnitches.length) { correctedSites[domain] = newSnitches; } } // clear existing maps and then use mergeUserData to rebuild them actionMap.updateObject({}); snitchMap.updateObject({}); 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); }, forgetCloudflare: function (badger) { let config = { name: '__cfduid' }; if (badger.firstPartyDomainPotentiallyRequired) { config.firstPartyDomain = null; } chrome.cookies.getAll(config, function (cookies) { console.log("Forgetting Cloudflare domains ..."); let actionMap = badger.storage.getStore("action_map"), actionClones = actionMap.getItemClones(), snitchMap = badger.storage.getStore("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)); }); for (let domain in snitchClones) { let newSnitches = snitchClones[domain].filter( item => !cfduidFirstParties.has(item)); if (newSnitches.length) { correctedSites[domain] = newSnitches; } } // clear existing maps and then use mergeUserData to rebuild them actionMap.updateObject({}); snitchMap.updateObject({}); 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); }); }, // https://github.com/EFForg/privacybadger/pull/2245#issuecomment-545545717 forgetConsensu: (badger) => { console.log("Forgetting consensu.org domains (GDPR consent provider) ..."); badger.storage.forget("consensu.org"); }, resetWebRTCIPHandlingPolicy2: function (badger) { if (!badger.webRTCAvailable) { return; } const cpn = chrome.privacy.network; cpn.webRTCIPHandlingPolicy.get({}, function (result) { if (!result.levelOfControl.endsWith('_by_this_extension')) { return; } // 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' }); } }); } }; return exports; })(); //require scopes