TWB, using your test page, when I mark a given plugin "Never Activate" it is no longer detected by the "Plugins detected by enumeration:" section. The "MimeTypes detected by enumeration:" lists only the mimetypes mapped to the "EnabledPlugin.name" plugins... and revers mapping in "MimeTypes detected by checking 53 names:" For me, the result indicates that the browser is "leaking even less" than I expected. In preferences } Applications (iceweasel v31esr), brower has autodetected "xpdf" installed on the system and it is set as the default pdf handler... yet this isn't leaked (presence of the handler, ability to enumerate its name, nor the range of various mimetypes which are registerd to xpdf in the xdg mime database. If you are saying/worrying that a nebby script could embed a list of 3200 mimetypes and subtypes and poll to see (fingerprint? capitalize on a vulnerability)... I'm saying that the test results indicate that it would be able to glean a list of mimetypes which are registered to currently enabled PLUGINS. If your hardware-specific driver (or whatever) is not a PLUGIN, is just registered on your system as a mimetype handler, its presence (nor its associated mimetypes) is not leaked. I'm surprised noscript listens to DOMContentLoaded event. Foggy memory, I thought it was too late to intervene at that point (script parsing has already occurred). The "Mason" extension was one that I studied; IIRC, it intervened earlier than DOMContentLoaded. As you said, behavior may be different under windows. I tested in linux. To determine whether any "leakage" is occurring, I think you'll need to pare the number of enabled plugins and/or gather a definitive list of mimetypes registered to those. Only types outside that list would represent leakage, right?
Well, Applications reveals handler/application names (to the user). Whereas a navigator.mimeTypes['NonPluginAssociatedMimeType'] test seems to reveal (to content scripts) whether the browser thinks there is a handler for NonPluginAssociatedMimeType. I'm using NonPluginAssociatedMimeType here because that is what we need to focus on. The mimeTypesList built into my test page only checks for two PDF specific types: "application/pdf" and "application/vnd.adobe.pdfxml". Are those showing up in the "MimeTypes detected by checking names" table? These numbers are a bit off, but close enough for discussion purposes: Windows: MimeTypes detected by enumeration: 2 <-- Associated with plugins MimeTypes detected by checking 3215 names: 87 <-- 2 of these are associated with plugins Ubuntu LiveCD: MimeTypes detected by enumeration: 44 <-- Associated with plugins MimeTypes detected by checking 3215 names: 377 <-- 44 of these are associated with plugins IOW, virtually all of the results from testing navigator.mimeTypes[name] are not associated with plugins.
In my test results, "application/pdf" == nul, and "application/vnd.adobe.pdfxml" is entirely absent from the table. MimeTypes detected by enumeration: 50 (each maps to an emabled plugin) Plugins detected by checking 29 names: 1 (libflashplayer.so) I wouldn't have expected an Ubuntu system to differ significantly from my (debian-derived) antix15 in test results. I'm running fluxbox window manager here, no fullblown "desktop environment". Maybe the DE (thoroughness of its mime indexing) is the differentiator? Then again, I tested v31esr. Perhaps your newer (?) browser version performs more thorough sniffing.
That was an older version of Ubuntu. I just ran another set of tests, so might as well: Code: Firefox 41.0.1 + Flash Plugin on Windows 7... Plugins detected by enumeration: 1 Plugins detected by checking 48 names: 1 MimeTypes detected by enumeration: 2 MimeTypes detected by checking 3416 names: 89 Firefox 41.0.1 + Flash Plugin on Windows XP... Plugins detected by enumeration: 1 Plugins detected by checking 48 names: 1 MimeTypes detected by enumeration: 2 MimeTypes detected by checking 3416 names: 97 Firefox 37.0 + iTunes Application Detector Plugin on Ubuntu 15.04 LiveCD... Plugins detected by enumeration: 1 Plugins detected by checking 48 names: 1 MimeTypes detected by enumeration: 1 MimeTypes detected by checking 3416 names: 669 Oh, and: https://hackademix.net/2011/09/29/script-surrogates-quick-reference/
While reviewing the list of changes for 45.0.1, "Implement a PrefProvider for Remote New Tab Page" set off alarms and led me to: [Meta] Make about:newtab remote https://bugzilla.mozilla.org/show_bug.cgi?id=1176429 I can't remember if I heard of Remote New Tab Page before. Anyway, it appears the intention is to move the about:newtab page to a remote server: newtab.cdn.mozilla.net aka dj2m5z2blkx8x.cloudfront.net. and grant that page/server special privileges so that it can bypass content isolation mechanisms and interact with internal browser components and private data. I didn't dig too deep, but it appeared to me that the existing NewTabURL.override() mechanism, which can be invoked via extension or autoconfig, remains. This reminded me of: give access to about:support data to specific whitelisted Mozilla websites https://bugzilla.mozilla.org/show_bug.cgi?id=1079563 and "remote-troubleshooting" permissions granted to: input.mozilla.org support.mozilla.org Which also can be removed via extension or autoconfig. I don't recall those being accessible via the no longer supported about:permissions, but I'm too lazy to go back and check. There was also another bug or discussion, I can't remember where, about granting Mozilla servers the power to see actual user-agent information rather than the potentially overridden values that people setup. I don't know if they followed through on that. Point is: be aware that normal security/privacy protection mechanisms may not apply to Mozilla servers and perhaps partners.
TheWindBringeth, perhaps these will provide you with more info regarding the Remote New Tab, including Tiles: https://wiki.mozilla.org/ContentServices#Remote_New_Tab_ALL_Bugs Also: https://groups.google.com/forum/#!topic/mozilla.governance/HtnpXLX2QBQ
Pref Exporter 0.6 Used to export preferences from Gecko based applications (Firefox, Thunderbird, etc). Run this code via Scratchpad in browser context, Custom Buttons Addon, or other appropriate means. Export as TEXT and use a diff tool to compare files, or export as JSON and use my Pref Diff Tool to compare files. Code: (function() { let verInfoStr = "Pref Exporter 0.6" try { // Output format: either "TEXT" or "JSON" const format = "JSON"; // Default basename (to which .txt or .json will be appended) const defaultBasename = "ExportedPrefs"; // Use an application-specific prefix with default filename? const appSpecFilenamePrefix = true; // TEXT output only: Export a status field (locked, userset, default)? const exportStatusField = false; // TEXT output only: Export a type field (boolean, integer, string)? const exportTypeField = false; // TEXT output only: Separator between pref fields const sep = ";"; // TEXT output only: End of line separator const eol = "\r\n"; // Nothing below here should need adjusting unless you are improving the code let prefBranch = Cc["@mozilla.org/preferences-service;1"] .getService(Ci.nsIPrefService).getBranch(''); let filename; if(appSpecFilenamePrefix) { let app; let appVersion; if(prefBranch.getPrefType("torbrowser.version") == prefBranch.PREF_STRING) { app = "TorBrowser"; appVersion = prefBranch.getCharPref("torbrowser.version"); } else { let appInfo = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo); app = appInfo.name.replace(" ", "_"); appVersion = appInfo.version; } filename = app + "_" + appVersion + "_" + defaultBasename; } else filename = defaultBasename; let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker); fp.init(window, "Pref Exporter output file", Ci.nsIFilePicker.modeSave); if(format == "JSON") { fp.defaultString = filename + ".json"; fp.appendFilter("JSON", "*.json"); } else { fp.defaultString = filename + ".txt"; fp.appendFilters(Ci.nsIFilePicker.filterText); } fp.appendFilters(Ci.nsIFilePicker.filterAll); let rv = fp.show(); if ((rv == Ci.nsIFilePicker.returnOK) || (rv == Ci.nsIFilePicker.returnReplace)) { let invalidPrefTypes = 0; let unknownPrefTypes = 0; let prefList = []; let count = {value:0}; let children = prefBranch.getChildList("",count); for(let i=0; i<count.value; i++) { let pref = { name: "", status: "", type: "", value: "", }; pref.name = children[i]; if(prefBranch.prefIsLocked(pref.name)) pref.status = "locked"; else if(prefBranch.prefHasUserValue(pref.name)) pref.status = "userset"; else pref.status = "default"; switch(prefBranch.getPrefType(pref.name)) { case prefBranch.PREF_BOOL: pref.type = "boolean"; pref.value = prefBranch.getBoolPref(pref.name); break; case prefBranch.PREF_INT: pref.type = "integer"; pref.value = prefBranch.getIntPref(pref.name); break; case prefBranch.PREF_STRING: pref.type = "string"; pref.value = prefBranch.getComplexValue(pref.name, Ci.nsISupportsString).data; if((pref.status == "default") && (/^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.value))) { try { pref.value = prefBranch.getComplexValue(pref.name, Ci.nsIPrefLocalizedString).data; } catch(e) { // NOP } } break; case prefBranch.PREF_INVALID: pref.type = "invalid"; pref.value = "PrefTypeInvalid_ValueNotAvailable"; invalidPrefsTypes++; break; default: pref.type = "unknown"; pref.value = "PrefTypeUnknown_ValueNotAvailable"; unknownPrefTypes++; break; } prefList.push(pref); } prefList.sort(function(a, b) { if(a.name < b.name) return -1; if(a.name > b.name) return 1; return 0; }); let output = ""; if(format == "JSON") { let gcsdif = {}; gcsdif.dif = "GCSDIF"; gcsdif.version = "0.1"; gcsdif.prefList = prefList; output += JSON.stringify(gcsdif); } else { for(let i=0; i<prefList.length; i++) { output += prefList[i].name; if(exportStatusField) output += sep + prefList[i].status; if(exportTypeField) output += sep + prefList[i].type; output += sep + prefList[i].value.toString() + eol; } } let foStream = Cc["@mozilla.org/network/file-output-stream;1"] .createInstance(Ci.nsIFileOutputStream); foStream.init(fp.file, 0x02 | 0x08 | 0x20, parseInt("0666", 8), 0); let converter = Cc["@mozilla.org/intl/converter-output-stream;1"] .createInstance(Ci.nsIConverterOutputStream); converter.init(foStream, "UTF-8", 0, 0); converter.writeString(output); converter.close(); let resultMsg = "Exported " + prefList.length + " prefs.\n"; if(invalidPrefTypes) resultMsg += "\nInvalid pref types: " + invalidPrefTypes; if(unknownPrefTypes) resultMsg += "\nUnknown pref types: " + unknownPrefTypes; resultMsg += "\nYour export may contain sensitive information. " + "Please protect the file appropriately.\n" let promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"] .getService(Ci.nsIPromptService); promptSvc.alert(null, verInfoStr, resultMsg); } } catch(e) { let promptSvc = Cc["@mozilla.org/embedcomp/prompt-service;1"] .getService(Ci.nsIPromptService); promptSvc.alert(null, verInfoStr, e); } })(); Pref Diff Tool 0.2 Used to compare JSON export files created with Pref Exporter. Create an HTML file containing this code and load that in your browser. Then load the two JSON files you want to compare and Generate Results. Code: <!doctype html> <html> <head> <meta charset="utf-8"> <title>Pref Diff Tool</title> <style type="text/css"> body {font-family: "segoe ui"; font-size:12px;} table {width:99%;table-layout:fixed;} table, th, td {border-collapse:collapse; border:1px solid #999999;} table#footerTbl {border:none;} th {color:white; background-color:grey;} th, td {text-align:left; padding:2px; width:50%; word-wrap:break-word;} td {vertical-align:top;} td.label {color:white; background-color:grey; font-weight:bold; width:88px; word-wrap:normal;} td.expand {width:100%;} td.footerTd {border:none;} td#verInfoStr {text-align:right;} div.topgap {margin-top:6px;} div#helperDiv {display:none;} noscript {font-size:14px; font-weight:bold; color:red;} input.fileInput {width:90%;} span.prefName {font-weight:bold;} </style> <script type="text/javascript"> const verInfoStr = "Pref Diff Tool 0.2"; var resultsTable; var resultsFilter; var prefList1 = []; var prefList2 = []; var numMatchingRows = 0; var statusAvailable = false; function handleFileSelect(evt) { var id = this.id; var file = evt.target.files[0]; var reader = new FileReader(); reader.onerror = function(err) { alert("Error: " + err.toString()); } reader.onload = function (evt) { var gcsdif; try { try { gcsdif = JSON.parse(evt.target.result); } catch(e) { throw("File is not a JSON file or it has been corrupted.\n" + e.toString()); } if(gcsdif.dif != "GCSDIF") throw("File does not contain GCSDIF information."); if(gcsdif.version != "0.1") throw("GCSDIF version is not supported"); if(gcsdif.prefList.length <= 0) throw("File contains no preference entries"); if(id == "leftFile") prefList1 = gcsdif.prefList; else prefList2 = gcsdif.prefList; } catch(e) { alert("Error: " + e.toString()); } }; clearResults(); reader.readAsText(file, 'UTF-8'); } function generateResults() { var start = performance.now(); clearResults(); if((prefList1.length > 0) && (prefList2.length > 0)) { var stats = {prefCountTotal : 0, prefCountLeft : 0, prefCountRight : 0, inBoth : 0, inBothIdentical : 0, inBothDifferent : 0, inLeftOnly : 0, inRightOnly : 0, different : 0}; var name; var prefNameObj = {}; var prefList1Obj = {}; var prefList2Obj = {}; for(var i=0; i<prefList1.length; i++) { name = prefList1[i].name; prefNameObj[name] = 1; prefList1Obj[name] = prefList1[i]; } stats.prefCountLeft = prefList1.length; for(var i=0; i<prefList2.length; i++) { name = prefList2[i].name; prefNameObj[name] = 1; prefList2Obj[name] = prefList2[i]; } stats.prefCountRight = prefList2.length; var prefNames = []; for(var name in prefNameObj) prefNames.push(name); prefNames.sort(function(a, b) { a = a.toLowerCase(); b = b.toLowerCase(); if (a < b) return -1; if (a > b) return 1; return 0; }); stats.prefCountTotal = prefNames.length; var helperDiv = document.getElementById("helperDiv"); function HtmlEncode(s) { helperDiv.innerText = helperDiv.textContent = s; s = helperDiv.innerHTML; return s; } function insertRow(className, leftName, leftStr, rightName, rightStr) { var row = resultsTable.insertRow(-1); row.className = className; var cell0 = row.insertCell(0); var cell1 = row.insertCell(1); cell0.innerHTML = '<span class="prefName">' + leftName + "</span>" + HtmlEncode(leftStr); cell1.innerHTML = '<span class="prefName">' + rightName + "</span>" + HtmlEncode(rightStr); } var compareStatus = document.getElementById("compareStatusBox").checked; var compareType = document.getElementById("compareTypeBox").checked; var compareValue = document.getElementById("compareValueBox").checked; var outputStatus = document.getElementById("outputStatusBox").checked; var outputType = document.getElementById("outputTypeBox").checked; var outputValue = document.getElementById("outputValueBox").checked; const sep = ";"; function getOutputStr(pref) { var str = ""; if(outputStatus) str += sep + pref.status; if(outputType) str += sep + pref.type; if(outputValue) str += sep + pref.value; return str; } for(var i=0; i < prefNames.length; i++) { var name = prefNames[i]; var left = {pref:null, name:"", outputStr:""}; var right = {pref:null, name:"", outputStr:""}; var locationStr = ""; if(prefList1Obj.hasOwnProperty(name)) { left.pref = prefList1Obj[name]; left.name = name; left.outputStr = getOutputStr(left.pref); locationStr = "InLeftOnly"; } if(prefList2Obj.hasOwnProperty(name)) { right.pref = prefList2Obj[name]; right.name = name; right.outputStr = getOutputStr(right.pref); if(locationStr == "InLeftOnly") locationStr = "InBoth"; else locationStr = "InRightOnly"; } if(locationStr == "InLeftOnly") stats.inLeftOnly++; else if(locationStr == "InRightOnly") stats.inRightOnly++; else if(locationStr == "InBoth") stats.inBoth++; function isMatch(p1, p2) { if((p1 === null) || (p2 === null)) return false; if(compareStatus) { if(p1.status !== p2.status) return false; } if(compareType) { if(p1.type !== p2.type) return false; } if(compareValue) { if(p1.value !== p2.value) return false; } return true; } var resultStr; if(isMatch(left.pref, right.pref)) { resultStr = "Identical"; stats.inBothIdentical++; } else { resultStr = "Different"; if(locationStr == "InBoth") stats.inBothDifferent++; stats.different++; } var className = "All " + locationStr + " " + resultStr; insertRow(className, left.name, left.outputStr, right.name, right.outputStr); } statusAvailable = true; applyResultsFilter(); var statsHTML = "PrefCountTotal: " + stats.prefCountTotal + "<br />" + "PrefCountLeft: " + stats.prefCountLeft + "<br />" + "PrefCountRight: " + stats.prefCountRight + "<br />" + "InBoth: " + stats.inBoth + "<br />" + "InBothIdentical: " + stats.inBothIdentical + "<br />" + "InBothDifferent: " + stats.inBothDifferent + "<br />" + "InLeftOnly: " + stats.inLeftOnly + "<br />" + "InRightOnly: " + stats.inRightOnly + "<br />" + "Different: " + stats.different + "<br />"; document.getElementById("stats").innerHTML = statsHTML; } else { alert("Error: No preference data from one or both files. Were both selected and loaded OK?"); } var end = performance.now(); console.log("PrefDiffTool: generateResults() took " + (end - start) + " msecs"); } function applyResultsFilter() { resultsFilter = document.querySelector('input[name = "resultsFilter"]:checked').id; resultsFilter = resultsFilter.replace("-Filter", ""); resultsFilter = resultsFilter.replace("_", " "); numMatchingRows = 0; var row; // Leave first row alone for(var i=1; i<resultsTable.rows.length; i++) { row = resultsTable.rows[i]; if(row.className.indexOf(resultsFilter) == -1) { row.style.display = 'None'; } else { try { row.style.display = "table-row"; } catch(e) { row.style.display = "block"; } numMatchingRows++; } } updateStatus(); } function updateStatus() { var numPrefs1 = statusAvailable ? prefList1.length.toString() : "TBD"; var numPrefs2 = statusAvailable ? prefList2.length.toString() : "TBD"; var numRows = statusAvailable ? numMatchingRows.toString() : "TBD"; var cells = resultsTable.rows[0].cells; cells[0].innerHTML = "Prefs loaded from file: " + numPrefs1 + "<br />" + "Result table rows matching compare and filter: " + numRows; cells[1].innerHTML = "Prefs loaded from file: " + numPrefs2 + "<br />" + "Result table rows matching compare and filter: " + numRows; } function clearResults() { var rowCount = resultsTable.rows.length; // Leave first row alone for(var i=1; i<rowCount; i++) resultsTable.deleteRow(-1); document.getElementById("stats").innerHTML = ""; statusAvailable = false; updateStatus(); } function reset() { clearResults(); // Variables prefList1 = []; prefList2 = []; // Compare document.getElementById("compareStatusBox").checked = false; document.getElementById("compareTypeBox").checked = true; document.getElementById("compareValueBox").checked = true; // Output document.getElementById("outputStatusBox").checked = false; document.getElementById("outputTypeBox").checked = false; document.getElementById("outputValueBox").checked = true; // Filter document.getElementById("All-Filter").checked = false; document.getElementById("InBoth-Filter").checked = false; document.getElementById("InBoth_Identical-Filter").checked = false; document.getElementById("InBoth_Different-Filter").checked = false; document.getElementById("InLeftOnly-Filter").checked = false; document.getElementById("InRightOnly-Filter").checked = false; document.getElementById("Different-Filter").checked = true; var resultsFilters = document.getElementsByClassName("resultsFilter"); for(var i=0; i<resultsFilters.length; i++) resultsFilters[i].onclick = function() {applyResultsFilter();} // Files document.getElementById("filesForm").reset(); var fileInputs = document.getElementsByClassName("fileInput"); for(var i=0; i<fileInputs.length; i++) fileInputs[i].addEventListener('change', function(e){ handleFileSelect.call(this, e) }, false); } function init() { document.title = verInfoStr; document.getElementById("verInfoStr").innerHTML = verInfoStr; resultsTable = document.getElementById("resultsTable"); if(!window.FileReader) alert('Required File APIs were not detected... this tool will not work.'); reset(); } </script> </head> <body onload="init();"> <noscript>Error: This tool requires javascript</noscript> <div> <table> <tr> <td class="label">Compare:</td> <td class="expand"> <input id="compareStatusBox" type="checkbox" /><label for="compareStatusBox">Status</label> <input id="compareTypeBox" type="checkbox" /><label for="compareTypeBox">Type</label> <input id="compareValueBox" type="checkbox" /><label for="compareValueBox">Value</label> </td> </tr> <tr> <td class="label">Output:</td> <td class="expand"> <input id="outputStatusBox" type="checkbox" /><label for="outputStatusBox">Status</label> <input id="outputTypeBox" type="checkbox" /><label for="outputTypeBox">Type</label> <input id="outputValueBox" type="checkbox" /><label for="outputValueBox">Value</label> </td> </tr> <tr> <td class="label">Filter:</td> <td class="expand"> <form> <input type="radio" name="resultsFilter" class="resultsFilter" id="All-Filter" /> <label for="All-Filter">All</label> <input type="radio" name="resultsFilter" class="resultsFilter" id="InBoth-Filter" /> <label for="InBoth-Filter">InBoth</label> <input type="radio" name="resultsFilter" class="resultsFilter" id="InBoth_Identical-Filter" > <label for="InBoth_Identical-Filter">InBothIdentical</label> <input type="radio" name="resultsFilter" class="resultsFilter" id="InBoth_Different-Filter" /> <label for="InBoth_Different-Filter">InBothDifferent</label> <input type="radio" name="resultsFilter" class="resultsFilter" id="InLeftOnly-Filter" /> <label for="InLeftOnly-Filter">InLeftOnly</label> <input type="radio" name="resultsFilter" class="resultsFilter" id="InRightOnly-Filter" /> <label for="InRightOnly-Filter">InRightOnly</label> <input type="radio" name="resultsFilter" class="resultsFilter" id="Different-Filter" /> <label for="Different-Filter">Different</label> </form> </td> </tr> <tr> <td class="label">Operations:</td> <td class="expand"> <button onclick="generateResults();">Generate Results</button> <button onclick="reset();">Reset</button> </td> </tr> </table> </div> <div class="topgap"> <form id="filesForm"> <table id="files"> <tr> <td><input id="leftFile" class="fileInput" type="file" /></td> <td><input id="rightFile" class="fileInput" type="file" /></td> </tr> </table> </form> </div> <div class="topgap"> <table id="resultsTable"> <tr><th></th><th></th></tr> </table> </div> <div class="topgap"> <table id="footerTbl"> <tr> <td id="stats" class="footerTd"></td> <td id="verInfoStr" class="footerTd"></td> </tr> </table> </div> <div id="helperDiv"></div> </body> </html>
FYI: Mozilla decided to use a system addon to incrementally expose users to e10s. More info if you do, or don't, want to be a Guinea Pig... https://bugzilla.mozilla.org/show_bug.cgi?id=1249845 https://mxr.mozilla.org/mozilla-release/source/browser/extensions/e10srollout/bootstrap.js Given the use of a system addon for such purposes, it might be wise to keep an eye on them.
If you allow tiles (er, page thumbs) on newtab page, ff loads each not-yet cached (or you've cleared the cache) url in a hidden window to create a thumbnail image for each tile, with all extensions bypassed/disabled. Although it ignores requests to set cookies when loading, it loads all 3rd-party assests (css, scripts, imagefiles, etc). I haven't found anything in the newtabpage and related code to indicate that header directives are treated differently. Ajax/xhttp requests during pageload are permitted; I haven't tracked down whether websocket connections are disallowed.
Holy **** OK, so let's say that you're blocking WebGL in NoScript, using Canvas Blocker to prevent canvas fingerprinting, and blocking WebRTC with Disable WebRTC. So you're saying that Firefox loads visited pages with all that stuff allowed, just in order to generate a bloody thumbnail image? That is insane.
I think these can be blocked either with uBlock Origin or uMatrix. Both are designed to see behind-the-scene requests too! For Example, i can see requests made by the browser for safe browsing lists update etc..
Could you please list the steps necessary to demonstrate this through a test? I ask because I just ran a quick one and the results seem to conflict with your conclusion: Installed FF46 portable app Installed latest ABP and removed all subscriptions including non-intrusive advertising exception. Typed address http://foo.example to load a test page which embeds third party content from bar.example. Confirmed third party content was visible in that tab. Hit the home button so that page was closed. Typed about:newtab to load the new tab page, confirmed the thumbnail for foo.example included images from bar.example, then pinned that tile. Added a ||bar.example^ ABP rule, so a future load of foo.example would not pull third party images from bar.example. Cleared recent history with all checkboxes checked. Closed browser Found the thumbnails folder, the thumbnail png for foo.example was still there. It would appear that clear recent history doesn't remove those. So I manually deleted the thumbnail png. Edit: Later I thought to also try changing the time range from its default to Everything, and that did delete the thumbnails. Launched browser again Looked at new tab page. The thumbnail for foo.example was regenerated and no longer contains images from bar.example. Checked server log, confirmed that images weren't requested from bar.example during this phase. It appears that ABP was able to block the requests generated by new tab page related thumbnailing. Theoretically, the behavior could be dependent on build, extension, request type, caching/order, etc. So I'm not trying to dispute the idea that there are issues in this area. If there are, it would be nice to have a reproducible test case.
Maybe I can provide a summary of my own:- use of "browsers" is a higher level of risk against anonymity than exchange of medium latency messages, where you have an agreed xml schema for those messages which can be parsed (and firewalled) by a relatively simple open source program executing locally, with no server-supplied code. How you view/construct those messages can be decoupled from the parsing/encoding aspect. Of course, one could say that a very simple html DOM parser is just that. Problem being that modern browsers are way beyond that in ways that risk privacy in very unpredictable and untestable ways.
Yep, they're a form of html dom parser with basic text rendering, that's OK. But if you still have expectations of interactivity in the return direction, you have the timing and profiling issues of any interactive session, because your user entry is "on" a remote mainframe (aka web server), with all the exposure that that implies. The problem with modern browsers is that they have become graphically rich dumb terminals on a mainframe, and offer the ability to execute scripts, provide various inbuilt services with access to your real machine and environment and so on. You emphatically do not fully control what goes to/from the server - hence the problems.
WRT to the compatibility shims: So those above numbers aren't great. I've stumbled across a few cases where the situation as listed there was incorrect/outdated. So maybe things are a bit better(?). It wouldn't hurt if we each reviewed the status for the specific extensions we think are important. Test extensions (in VM, portable app, or other non-critical environment), get the list updated if necessary, see if the developer is awake and working on full compatibility, etc. This is something we could do on our own schedule and without coordination. https://developer.mozilla.org/en-US/Add-ons/Working_with_multiprocess_Firefox https://wiki.mozilla.org/Electrolysis
I've tested my favorite add-ons (like CanvasBlocker, Random Agent Spoofer and Masking Agent) on Firefox Nightly. Most seem to work when it's updated. For example lower version of RAS is incompatible. I'm concern cause I also modified Firefox's configurations and wondering whether e10s will void any functionality. Has anyone really drill into the privacy implication using e10s?
Yes. Also, extensions working with the help of shims should also be considered as no go. It will degrade firefox performance.