Bug 1422365 - Introduce nsIClearDataService - part 3 - plugin data, r=johannh

This commit is contained in:
Andrea Marchesini 2018-06-01 14:29:59 +02:00
Родитель f42b9d4e33
Коммит 7a1184f9d6
5 изменённых файлов: 99 добавлений и 108 удалений

Просмотреть файл

@ -14,7 +14,6 @@ XPCOMUtils.defineLazyModuleGetters(this, {
FormHistory: "resource://gre/modules/FormHistory.jsm",
Downloads: "resource://gre/modules/Downloads.jsm",
TelemetryStopwatch: "resource://gre/modules/TelemetryStopwatch.jsm",
setTimeout: "resource://gre/modules/Timer.jsm",
ServiceWorkerCleanUp: "resource://gre/modules/ServiceWorkerCleanUp.jsm",
OfflineAppCacheHelper: "resource://gre/modules/offlineAppCache.jsm",
ContextualIdentityService: "resource://gre/modules/ContextualIdentityService.jsm",
@ -325,33 +324,18 @@ var Sanitizer = {
cookies: {
async clear(range) {
let seenException;
let refObj = {};
// Clear cookies.
// Clear cookies and plugin data.
TelemetryStopwatch.start("FX_SANITIZE_COOKIES_2", refObj);
await clearData(range, Ci.nsIClearDataService.CLEAR_COOKIES);
await clearData(range, Ci.nsIClearDataService.CLEAR_COOKIES |
Ci.nsIClearDataService.CLEAR_PLUGIN_DATA);
TelemetryStopwatch.finish("FX_SANITIZE_COOKIES_2", refObj);
// Clear deviceIds. Done asynchronously (returns before complete).
try {
let mediaMgr = Cc["@mozilla.org/mediaManagerService;1"]
.getService(Ci.nsIMediaManagerService);
mediaMgr.sanitizeDeviceIds(range && range[0]);
} catch (ex) {
seenException = ex;
}
// Clear plugin data.
try {
await clearPluginData(range);
} catch (ex) {
seenException = ex;
}
if (seenException) {
throw seenException;
}
},
},
@ -772,7 +756,7 @@ var Sanitizer = {
pluginData: {
async clear(range) {
await clearPluginData(range);
await clearData(range, Ci.nsIClearDataService.CLEAR_PLUGIN_DATA);
},
},
},
@ -862,70 +846,6 @@ async function sanitizeInternal(items, aItemsToClear, progress, options = {}) {
}
}
async function clearPluginData(range) {
// Clear plugin data.
// As evidenced in bug 1253204, clearing plugin data can sometimes be
// very, very long, for mysterious reasons. Unfortunately, this is not
// something actionable by Mozilla, so crashing here serves no purpose.
//
// For this reason, instead of waiting for sanitization to always
// complete, we introduce a soft timeout. Once this timeout has
// elapsed, we proceed with the shutdown of Firefox.
let seenException;
let promiseClearPluginData = async function() {
const FLAG_CLEAR_ALL = Ci.nsIPluginHost.FLAG_CLEAR_ALL;
let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
// Determine age range in seconds. (-1 means clear all.) We don't know
// that range[1] is actually now, so we compute age range based
// on the lower bound. If range results in a negative age, do nothing.
let age = range ? (Date.now() / 1000 - range[0] / 1000000) : -1;
if (!range || age >= 0) {
let tags = ph.getPluginTags();
for (let tag of tags) {
try {
let rv = await new Promise(resolve =>
ph.clearSiteData(tag, null, FLAG_CLEAR_ALL, age, resolve)
);
// If the plugin doesn't support clearing by age, clear everything.
if (rv == Cr.NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED) {
await new Promise(resolve =>
ph.clearSiteData(tag, null, FLAG_CLEAR_ALL, -1, resolve)
);
}
} catch (ex) {
// Ignore errors from plug-ins
}
}
}
};
try {
// We don't want to wait for this operation to complete...
promiseClearPluginData = promiseClearPluginData(range);
// ... at least, not for more than 10 seconds.
await Promise.race([
promiseClearPluginData,
new Promise(resolve => setTimeout(resolve, 10000 /* 10 seconds */))
]);
} catch (ex) {
seenException = ex;
}
// Detach waiting for plugin data to be cleared.
promiseClearPluginData.catch(() => {
// If this exception is raised before the soft timeout, it
// will appear in `seenException`. Otherwise, it's too late
// to do anything about it.
});
if (seenException) {
throw seenException;
}
}
async function sanitizeOnShutdown(progress) {
if (Sanitizer.shouldSanitizeOnShutdown) {
// Need to sanitize upon shutdown

Просмотреть файл

@ -89,6 +89,88 @@ const ImageCacheCleaner = {
},
};
const PluginDataCleaner = {
deleteByHost(aHost, aOriginAttributes) {
return this._deleteInternal((aPh, aTag) => {
return new Promise(aResolve => {
try {
aPh.clearSiteData(aTag, aHost,
Ci.nsIPluginHost.FLAG_CLEAR_ALL,
-1, aResolve);
} catch (e) {
// Ignore errors from the plugin, but resolve the promise
// We cannot check if something is a bailout or an error
aResolve();
}
});
});
},
deleteByRange(aFrom, aTo) {
let age = Date.now() / 1000 - aFrom / 1000000;
return this._deleteInternal((aPh, aTag) => {
return new Promise(aResolve => {
try {
aPh.clearSiteData(aTag, null, Ci.nsIPluginHost.FLAG_CLEAR_ALL,
age, aResolve);
} catch (e) {
aResolve(Cr.NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED);
}
}).then(aRv => {
// If the plugin doesn't support clearing by age, clear everything.
if (aRv == Cr.NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED) {
return new Promise(aResolve => {
try {
aPh.clearSiteData(aTag, null, Ci.nsIPluginHost.FLAG_CLEAR_ALL,
-1, aResolve);
} catch (e) {
aResolve();
}
});
}
return true;
});
});
},
deleteAll() {
return this._deleteInternal((aPh, aTag) => {
return new Promise(aResolve => {
try {
aPh.clearSiteData(aTag, null, Ci.nsIPluginHost.FLAG_CLEAR_ALL, -1,
aResolve);
} catch (e) {
aResolve();
}
});
});
},
_deleteInternal(aCb) {
let ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
let promises = [];
let tags = ph.getPluginTags();
for (let tag of tags) {
promises.push(aCb(ph, tag));
}
// As evidenced in bug 1253204, clearing plugin data can sometimes be
// very, very long, for mysterious reasons. Unfortunately, this is not
// something actionable by Mozilla, so crashing here serves no purpose.
//
// For this reason, instead of waiting for sanitization to always
// complete, we introduce a soft timeout. Once this timeout has
// elapsed, we proceed with the shutdown of Firefox.
return Promise.race([
Promise.all(promises),
new Promise(aResolve => setTimeout(aResolve, 10000 /* 10 seconds */))
]);
},
};
// Here the map of Flags-Cleaner.
const FLAGS_MAP = [
{ flag: Ci.nsIClearDataService.CLEAR_COOKIES,
@ -99,6 +181,9 @@ const FLAGS_MAP = [
{ flag: Ci.nsIClearDataService.CLEAR_IMAGE_CACHE,
cleaner: ImageCacheCleaner, },
{ flag: Ci.nsIClearDataService.CLEAR_PLUGIN_DATA,
cleaner: PluginDataCleaner, },
];
this.ClearDataService = function() {};

Просмотреть файл

@ -98,9 +98,13 @@ interface nsIClearDataService : nsISupports
*/
const uint32_t CLEAR_IMAGE_CACHE = 1 << 2;
/**
* Data stored by external plugins.
*/
const uint32_t CLEAR_PLUGIN_DATA = 1 << 3;
/* TODO
const uint32_t CLEAR_EME = 1 << 3;
const uint32_t CLEAR_PLUGIN_DATA = 1 << 4;
const uint32_t CLEAR_EME = 1 << 4;
const uint32_t CLEAR_DOWNLOADS = 1 << 5;
const uint32_t CLEAR_PASSWORDS = 1 << 6;
const uint32_t CLEAR_PERMISSIONS = 1 << 7;

Просмотреть файл

@ -13,8 +13,7 @@ add_task(async function test_basic() {
Assert.ok(!!service);
await new Promise(aResolve => {
service.deleteData(Ci.nsIClearDataService.CLEAR_IMAGE_CACHE |
Ci.nsIClearDataService.CLEAR_COOKIES, value => {
service.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => {
Assert.equal(value, 0);
aResolve();
});

Просмотреть файл

@ -64,23 +64,6 @@ var ForgetAboutSite = {
}));
// Plugin data
const phInterface = Ci.nsIPluginHost;
const FLAG_CLEAR_ALL = phInterface.FLAG_CLEAR_ALL;
let ph = Cc["@mozilla.org/plugin/host;1"].getService(phInterface);
let tags = ph.getPluginTags();
for (let i = 0; i < tags.length; i++) {
promises.push(new Promise(resolve => {
try {
ph.clearSiteData(tags[i], aDomain, FLAG_CLEAR_ALL, -1, resolve);
} catch (e) {
// Ignore errors from the plugin, but resolve the promise
// We cannot check if something is a bailout or an error
resolve();
}
}));
}
// Downloads
promises.push((async function() {
let list = await Downloads.getList(Downloads.ALL);