зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1371888 - cache plugin information in pluginreg.dat to avoid sync startup load, r=florian,mossop
This changes the pluginreg.dat format to include the blocklist state. There is now only the saved blocklist state in a plugin tag instance, rather than looking it up from in there using the blocklist service, so it was renamed from mCachedBlocklistState to mBlocklistState. We pass the 'right' state to the plugin instance when the plugintag is constructed. If we don't have state, we mark it as unblocked. mCachedBlocklistStateChanged was never read so it's being removed. Bug 1439519 adds a 'blocklist-loaded' notification that is fired once the blocklist is loaded. The plugin host implementation will listen to this in the parent process and update the blocklist state of all the plugins, and broadcast changes to the child process, just like when we update the blocklist from the server. We now also avoid re-sending plugin content to the content processes if the plugin state hasn't changed as a result of the blocklist having been loaded. Finally, because new plugins should still get an up-to-date blocklist state, and telemetry should get up-to-date data about which plugins are and aren't enabled once we have that data, we ensure that once we've loaded the blocklist async, we schedule an idle task to parse it and consider it loaded. All this means that plugin blocklist information could be mistaken between the points where a new plugin is installed and we first run Firefox with the new plugin, and the point where we load the blocklist. Given the trade-offs, that size of window (tiny) seems OK, also given that there's already a much larger window in blocklist updates (which only happen once every 24h). MozReview-Commit-ID: 1gsojRkUzTw --HG-- extra : rebase_source : 4709916b4674ada54f8a495fd2d16fcef8c58d20
This commit is contained in:
Родитель
ff2e63c19e
Коммит
ca508d989b
|
@ -807,22 +807,18 @@ nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading)
|
|||
pluginHost->GetPluginTagForInstance(pluginInstance,
|
||||
getter_AddRefs(pluginTag));
|
||||
|
||||
nsCOMPtr<nsIBlocklistService> blocklist =
|
||||
do_GetService("@mozilla.org/extensions/blocklist;1");
|
||||
if (blocklist) {
|
||||
uint32_t blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
|
||||
EmptyString(), &blockState);
|
||||
if (blockState == nsIBlocklistService::STATE_OUTDATED) {
|
||||
// Fire plugin outdated event if necessary
|
||||
LOG(("OBJLC [%p]: Dispatching plugin outdated event for content\n",
|
||||
this));
|
||||
nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(thisContent,
|
||||
NS_LITERAL_STRING("PluginOutdated"));
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsSimplePluginEvent");
|
||||
}
|
||||
|
||||
uint32_t blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
pluginTag->GetBlocklistState(&blockState);
|
||||
if (blockState == nsIBlocklistService::STATE_OUTDATED) {
|
||||
// Fire plugin outdated event if necessary
|
||||
LOG(("OBJLC [%p]: Dispatching plugin outdated event for content\n",
|
||||
this));
|
||||
nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(thisContent,
|
||||
NS_LITERAL_STRING("PluginOutdated"));
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsSimplePluginEvent");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -397,7 +397,8 @@ nsPluginArray::EnsurePlugins()
|
|||
|
||||
if (mPlugins.Length() == 0 && mCTPPlugins.Length() != 0) {
|
||||
nsCOMPtr<nsPluginTag> hiddenTag = new nsPluginTag("Hidden Plugin", nullptr, "dummy.plugin", nullptr, nullptr,
|
||||
nullptr, nullptr, nullptr, 0, 0, false);
|
||||
nullptr, nullptr, nullptr, 0, 0, false,
|
||||
nsIBlocklistService::STATE_NOT_BLOCKED);
|
||||
mPlugins.AppendElement(new nsPluginElement(mWindow, hiddenTag));
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ static const char *kPrefDisableFullPage = "plugin.disable_full_page_plugin_for_t
|
|||
static const char *kPrefUnloadPluginTimeoutSecs = "dom.ipc.plugins.unloadTimeoutSecs";
|
||||
static const uint32_t kDefaultPluginUnloadingTimeout = 30;
|
||||
|
||||
static const char *kPluginRegistryVersion = "0.18";
|
||||
static const char *kPluginRegistryVersion = "0.19";
|
||||
|
||||
static const char kDirectoryServiceContractID[] = "@mozilla.org/file/directory_service;1";
|
||||
|
||||
|
@ -266,7 +266,10 @@ nsPluginHost::nsPluginHost()
|
|||
mozilla::services::GetObserverService();
|
||||
if (obsService) {
|
||||
obsService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
obsService->AddObserver(this, "blocklist-updated", false);
|
||||
if (XRE_IsParentProcess()) {
|
||||
obsService->AddObserver(this, "blocklist-updated", false);
|
||||
obsService->AddObserver(this, "blocklist-loaded", false);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
|
@ -1999,6 +2002,13 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
|||
nsCOMArray<nsIFile> extensionDirs;
|
||||
GetExtensionDirectories(extensionDirs);
|
||||
|
||||
nsCOMPtr<nsIBlocklistService> blocklist =
|
||||
do_GetService("@mozilla.org/extensions/blocklist;1");
|
||||
|
||||
bool isBlocklistLoaded = false;
|
||||
if (blocklist && NS_FAILED(blocklist->GetIsLoaded(&isBlocklistLoaded))) {
|
||||
isBlocklistLoaded = false;
|
||||
}
|
||||
for (int32_t i = (pluginFiles.Length() - 1); i >= 0; i--) {
|
||||
nsCOMPtr<nsIFile>& localfile = pluginFiles[i];
|
||||
|
||||
|
@ -2090,12 +2100,17 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile *pluginsDir,
|
|||
continue;
|
||||
}
|
||||
|
||||
pluginTag = new nsPluginTag(&info, fileModTime, fromExtension);
|
||||
pluginFile.FreePluginInfo(info);
|
||||
uint32_t state = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
pluginTag = new nsPluginTag(&info, fileModTime, fromExtension, state);
|
||||
pluginTag->mLibrary = library;
|
||||
uint32_t state;
|
||||
rv = pluginTag->GetBlocklistState(&state);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// If the blocklist is loaded, get the blocklist state now.
|
||||
// If it isn't loaded yet, we'll update it once it loads.
|
||||
if (isBlocklistLoaded &&
|
||||
NS_SUCCEEDED(blocklist->GetPluginBlocklistState(pluginTag, EmptyString(),
|
||||
EmptyString(), &state))) {
|
||||
pluginTag->SetBlocklistState(state);
|
||||
}
|
||||
pluginFile.FreePluginInfo(info);
|
||||
|
||||
// If the blocklist says it is risky and we have never seen this
|
||||
// plugin before, then disable it.
|
||||
|
@ -2744,8 +2759,8 @@ nsPluginHost::WritePluginInfo()
|
|||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
|
||||
|
||||
// lastModifiedTimeStamp|canUnload|tag->mFlags|fromExtension
|
||||
PR_fprintf(fd, "%lld%c%d%c%lu%c%d%c%c\n",
|
||||
// lastModifiedTimeStamp|canUnload|tag->mFlags|fromExtension|blocklistState
|
||||
PR_fprintf(fd, "%lld%c%d%c%lu%c%d%c%d%c%c\n",
|
||||
tag->mLastModifiedTime,
|
||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||
false, // did store whether or not to unload in-process plugins
|
||||
|
@ -2754,6 +2769,8 @@ nsPluginHost::WritePluginInfo()
|
|||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||
tag->IsFromExtension(),
|
||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||
tag->BlocklistState(),
|
||||
PLUGIN_REGISTRY_FIELD_DELIMITER,
|
||||
PLUGIN_REGISTRY_END_OF_LINE_MARKER);
|
||||
|
||||
//description, name & mtypecount are on separate line
|
||||
|
@ -2974,12 +2991,13 @@ nsPluginHost::ReadPluginInfo()
|
|||
if (!reader.NextLine())
|
||||
return rv;
|
||||
|
||||
// lastModifiedTimeStamp|canUnload|tag.mFlag|fromExtension
|
||||
if (4 != reader.ParseLine(values, 4))
|
||||
// lastModifiedTimeStamp|canUnload|tag.mFlag|fromExtension|blocklistState
|
||||
if (5 != reader.ParseLine(values, 5))
|
||||
return rv;
|
||||
|
||||
int64_t lastmod = nsCRT::atoll(values[0]);
|
||||
bool fromExtension = atoi(values[3]);
|
||||
uint16_t blocklistState = atoi(values[4]);
|
||||
if (!reader.NextLine())
|
||||
return rv;
|
||||
|
||||
|
@ -3040,7 +3058,7 @@ nsPluginHost::ReadPluginInfo()
|
|||
(const char* const*)mimetypes,
|
||||
(const char* const*)mimedescriptions,
|
||||
(const char* const*)extensions,
|
||||
mimetypecount, lastmod, fromExtension, true);
|
||||
mimetypecount, lastmod, fromExtension, blocklistState, true);
|
||||
|
||||
delete [] heapalloced;
|
||||
|
||||
|
@ -3389,15 +3407,32 @@ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
|
|||
LoadPlugins();
|
||||
}
|
||||
}
|
||||
if (!strcmp("blocklist-updated", aTopic)) {
|
||||
if (XRE_IsParentProcess() &&
|
||||
(!strcmp("blocklist-updated", aTopic) || !strcmp("blocklist-loaded", aTopic))) {
|
||||
nsCOMPtr<nsIBlocklistService> blocklist =
|
||||
do_GetService("@mozilla.org/extensions/blocklist;1");
|
||||
if (!blocklist) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsPluginTag* plugin = mPlugins;
|
||||
bool blocklistAlteredPlugins = false;
|
||||
while (plugin) {
|
||||
plugin->InvalidateBlocklistState();
|
||||
uint32_t blocklistState = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
nsresult rv = blocklist->GetPluginBlocklistState(plugin, EmptyString(),
|
||||
EmptyString(), &blocklistState);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
uint32_t oldBlocklistState;
|
||||
plugin->GetBlocklistState(&oldBlocklistState);
|
||||
plugin->SetBlocklistState(blocklistState);
|
||||
blocklistAlteredPlugins |= (oldBlocklistState != blocklistState);
|
||||
plugin = plugin->mNext;
|
||||
}
|
||||
// We update blocklists asynchronously by just sending a new plugin list to
|
||||
// content.
|
||||
if (XRE_IsParentProcess()) {
|
||||
if (blocklistAlteredPlugins) {
|
||||
// Write the changed list to disk:
|
||||
WritePluginInfo();
|
||||
|
||||
// We update blocklists asynchronously by just sending a new plugin list to
|
||||
// content.
|
||||
// We'll need to repack our tags and send them to content again.
|
||||
IncrementChromeEpoch();
|
||||
SendPluginsToContent();
|
||||
|
|
|
@ -223,7 +223,8 @@ uint32_t nsPluginTag::sNextId;
|
|||
|
||||
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
|
||||
int64_t aLastModifiedTime,
|
||||
bool fromExtension)
|
||||
bool fromExtension,
|
||||
uint32_t aBlocklistState)
|
||||
: nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription,
|
||||
aPluginInfo->fFileName, aPluginInfo->fVersion),
|
||||
mId(sNextId++),
|
||||
|
@ -236,9 +237,8 @@ nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
|
|||
mLastModifiedTime(aLastModifiedTime),
|
||||
mSandboxLevel(0),
|
||||
mIsSandboxLoggingEnabled(false),
|
||||
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
||||
mCachedBlocklistStateValid(false),
|
||||
mIsFromExtension(fromExtension)
|
||||
mIsFromExtension(fromExtension),
|
||||
mBlocklistState(aBlocklistState)
|
||||
{
|
||||
InitMime(aPluginInfo->fMimeTypeArray,
|
||||
aPluginInfo->fMimeDescriptionArray,
|
||||
|
@ -260,6 +260,7 @@ nsPluginTag::nsPluginTag(const char* aName,
|
|||
int32_t aVariants,
|
||||
int64_t aLastModifiedTime,
|
||||
bool fromExtension,
|
||||
uint32_t aBlocklistState,
|
||||
bool aArgsAreUTF8)
|
||||
: nsIInternalPluginTag(aName, aDescription, aFileName, aVersion),
|
||||
mId(sNextId++),
|
||||
|
@ -272,9 +273,8 @@ nsPluginTag::nsPluginTag(const char* aName,
|
|||
mLastModifiedTime(aLastModifiedTime),
|
||||
mSandboxLevel(0),
|
||||
mIsSandboxLoggingEnabled(false),
|
||||
mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
|
||||
mCachedBlocklistStateValid(false),
|
||||
mIsFromExtension(fromExtension)
|
||||
mIsFromExtension(fromExtension),
|
||||
mBlocklistState(aBlocklistState)
|
||||
{
|
||||
InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
|
||||
static_cast<uint32_t>(aVariants));
|
||||
|
@ -298,7 +298,7 @@ nsPluginTag::nsPluginTag(uint32_t aId,
|
|||
int64_t aLastModifiedTime,
|
||||
bool aFromExtension,
|
||||
int32_t aSandboxLevel,
|
||||
uint16_t aBlocklistState)
|
||||
uint32_t aBlocklistState)
|
||||
: nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
|
||||
aMimeDescriptions, aExtensions),
|
||||
mId(aId),
|
||||
|
@ -310,9 +310,8 @@ nsPluginTag::nsPluginTag(uint32_t aId,
|
|||
mSandboxLevel(aSandboxLevel),
|
||||
mIsSandboxLoggingEnabled(false),
|
||||
mNiceFileName(),
|
||||
mCachedBlocklistState(aBlocklistState),
|
||||
mCachedBlocklistStateValid(true),
|
||||
mIsFromExtension(aFromExtension)
|
||||
mIsFromExtension(aFromExtension),
|
||||
mBlocklistState(aBlocklistState)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -548,9 +547,7 @@ nsPluginTag::GetDisabled(bool* aDisabled)
|
|||
bool
|
||||
nsPluginTag::IsBlocklisted()
|
||||
{
|
||||
uint32_t blocklistState;
|
||||
nsresult rv = GetBlocklistState(&blocklistState);
|
||||
return NS_FAILED(rv) || blocklistState == nsIBlocklistService::STATE_BLOCKED;
|
||||
return mBlocklistState == nsIBlocklistService::STATE_BLOCKED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -722,48 +719,20 @@ nsPluginTag::GetNiceName(nsACString & aResult)
|
|||
NS_IMETHODIMP
|
||||
nsPluginTag::GetBlocklistState(uint32_t *aResult)
|
||||
{
|
||||
// If we're in the content process, assume our cache state to always be valid,
|
||||
// as the only way it can be updated is via a plugin list push from the
|
||||
// parent process.
|
||||
if (!XRE_IsParentProcess()) {
|
||||
*aResult = mCachedBlocklistState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBlocklistService> blocklist =
|
||||
do_GetService("@mozilla.org/extensions/blocklist;1");
|
||||
|
||||
if (!blocklist) {
|
||||
*aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
}
|
||||
// The EmptyString()s are so we use the currently running application
|
||||
// and toolkit versions
|
||||
else if (NS_FAILED(blocklist->GetPluginBlocklistState(this, EmptyString(),
|
||||
EmptyString(), aResult))) {
|
||||
*aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(*aResult <= UINT16_MAX);
|
||||
mCachedBlocklistState = (uint16_t) *aResult;
|
||||
mCachedBlocklistStateValid = true;
|
||||
*aResult = mBlocklistState;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginTag::SetBlocklistState(uint16_t aBlocklistState)
|
||||
nsPluginTag::SetBlocklistState(uint32_t aBlocklistState)
|
||||
{
|
||||
// We should only ever call this on content processes. Any calls in the parent
|
||||
// process should route through GetBlocklistState since we'll have the
|
||||
// blocklist service there.
|
||||
MOZ_ASSERT(!XRE_IsParentProcess());
|
||||
mCachedBlocklistState = aBlocklistState;
|
||||
mCachedBlocklistStateValid = true;
|
||||
mBlocklistState = aBlocklistState;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginTag::InvalidateBlocklistState()
|
||||
uint32_t
|
||||
nsPluginTag::BlocklistState()
|
||||
{
|
||||
mCachedBlocklistStateValid = false;
|
||||
return mBlocklistState;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIBlocklistService.h"
|
||||
#include "nsIPluginTag.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsString.h"
|
||||
|
@ -108,7 +109,8 @@ public:
|
|||
|
||||
nsPluginTag(nsPluginInfo* aPluginInfo,
|
||||
int64_t aLastModifiedTime,
|
||||
bool fromExtension);
|
||||
bool fromExtension,
|
||||
uint32_t aBlocklistState);
|
||||
nsPluginTag(const char* aName,
|
||||
const char* aDescription,
|
||||
const char* aFileName,
|
||||
|
@ -120,6 +122,7 @@ public:
|
|||
int32_t aVariants,
|
||||
int64_t aLastModifiedTime,
|
||||
bool fromExtension,
|
||||
uint32_t aBlocklistState,
|
||||
bool aArgsAreUTF8 = false);
|
||||
nsPluginTag(uint32_t aId,
|
||||
const char* aName,
|
||||
|
@ -135,7 +138,7 @@ public:
|
|||
int64_t aLastModifiedTime,
|
||||
bool aFromExtension,
|
||||
int32_t aSandboxLevel,
|
||||
uint16_t aBlocklistState);
|
||||
uint32_t aBlocklistState);
|
||||
|
||||
void TryUnloadPlugin(bool inShutdown);
|
||||
|
||||
|
@ -146,10 +149,11 @@ public:
|
|||
void SetEnabled(bool enabled);
|
||||
bool IsClicktoplay();
|
||||
bool IsBlocklisted();
|
||||
uint32_t BlocklistState();
|
||||
|
||||
PluginState GetPluginState();
|
||||
void SetPluginState(PluginState state);
|
||||
void SetBlocklistState(uint16_t aBlocklistState);
|
||||
void SetBlocklistState(uint32_t aBlocklistState);
|
||||
|
||||
bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
|
||||
const nsCString& GetNiceFileName() override;
|
||||
|
@ -175,15 +179,12 @@ public:
|
|||
int32_t mSandboxLevel;
|
||||
bool mIsSandboxLoggingEnabled;
|
||||
|
||||
void InvalidateBlocklistState();
|
||||
|
||||
private:
|
||||
virtual ~nsPluginTag();
|
||||
|
||||
nsCString mNiceFileName; // UTF-8
|
||||
uint16_t mCachedBlocklistState;
|
||||
bool mCachedBlocklistStateValid;
|
||||
bool mIsFromExtension;
|
||||
uint32_t mBlocklistState;
|
||||
|
||||
void InitMime(const char* const* aMimeTypes,
|
||||
const char* const* aMimeDescriptions,
|
||||
|
|
|
@ -377,7 +377,7 @@ PluginWrapper.prototype = {
|
|||
|
||||
get blocklistState() {
|
||||
let { tags: [tag] } = pluginFor(this);
|
||||
return Services.blocklist.getPluginBlocklistState(tag);
|
||||
return tag.blocklistState;
|
||||
},
|
||||
|
||||
get blocklistURL() {
|
||||
|
|
|
@ -628,9 +628,6 @@ Blocklist.prototype = {
|
|||
|
||||
var oldAddonEntries = this._addonEntries;
|
||||
var oldPluginEntries = this._pluginEntries;
|
||||
this._addonEntries = [];
|
||||
this._gfxEntries = [];
|
||||
this._pluginEntries = [];
|
||||
|
||||
this._loadBlocklistFromXML(responseXML);
|
||||
// We don't inform the users when the graphics blocklist changed at runtime.
|
||||
|
@ -675,13 +672,6 @@ Blocklist.prototype = {
|
|||
this._gfxEntries = [];
|
||||
this._pluginEntries = [];
|
||||
|
||||
if (this._isBlocklistPreloaded()) {
|
||||
Services.telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(false);
|
||||
this._loadBlocklistFromString(this._preloadedBlocklistContent);
|
||||
delete this._preloadedBlocklistContent;
|
||||
return;
|
||||
}
|
||||
|
||||
Services.telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(true);
|
||||
|
||||
var profFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_BLOCKLIST]);
|
||||
|
@ -806,16 +796,11 @@ Blocklist.prototype = {
|
|||
return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null;
|
||||
},
|
||||
|
||||
_isBlocklistPreloaded() {
|
||||
return this._preloadedBlocklistContent != null;
|
||||
},
|
||||
|
||||
/* Used for testing */
|
||||
_clear() {
|
||||
this._addonEntries = null;
|
||||
this._gfxEntries = null;
|
||||
this._pluginEntries = null;
|
||||
this._preloadedBlocklistContent = null;
|
||||
},
|
||||
|
||||
async _preloadBlocklist() {
|
||||
|
@ -851,10 +836,15 @@ Blocklist.prototype = {
|
|||
|
||||
let text = await OS.File.read(path, { encoding: "utf-8" });
|
||||
|
||||
if (!this._addonEntries) {
|
||||
// Store the content only if a sync load has not been performed in the meantime.
|
||||
this._preloadedBlocklistContent = text;
|
||||
}
|
||||
await new Promise(resolve => {
|
||||
Services.tm.idleDispatchToMainThread(() => {
|
||||
if (!this.isLoaded) {
|
||||
Services.telemetry.getHistogramById("BLOCKLIST_SYNC_FILE_LOAD").add(false);
|
||||
this._loadBlocklistFromString(text);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
_loadBlocklistFromString(text) {
|
||||
|
@ -876,6 +866,9 @@ Blocklist.prototype = {
|
|||
},
|
||||
|
||||
_loadBlocklistFromXML(doc) {
|
||||
this._addonEntries = [];
|
||||
this._gfxEntries = [];
|
||||
this._pluginEntries = [];
|
||||
try {
|
||||
var childNodes = doc.documentElement.childNodes;
|
||||
for (let element of childNodes) {
|
||||
|
|
|
@ -7,34 +7,41 @@ add_task(async function() {
|
|||
getService().wrappedJSObject;
|
||||
let scope = ChromeUtils.import("resource://gre/modules/osfile.jsm", {});
|
||||
|
||||
// sync -> async
|
||||
// sync -> async. Check that async code doesn't try to read the file
|
||||
// once it's already been read synchronously.
|
||||
let read = scope.OS.File.read;
|
||||
let triedToRead = false;
|
||||
scope.OS.File.read = () => triedToRead = true;
|
||||
blocklist._loadBlocklist();
|
||||
Assert.ok(blocklist.isLoaded);
|
||||
await blocklist._preloadBlocklist();
|
||||
Assert.ok(!blocklist._isBlocklistPreloaded());
|
||||
Assert.ok(!triedToRead);
|
||||
scope.OS.File.read = read;
|
||||
blocklist._clear();
|
||||
|
||||
// async -> sync
|
||||
info("sync -> async complete");
|
||||
|
||||
// async first. Check that once we preload the content, that is sufficient.
|
||||
await blocklist._preloadBlocklist();
|
||||
Assert.ok(!blocklist.isLoaded);
|
||||
Assert.ok(blocklist._isBlocklistPreloaded());
|
||||
blocklist._loadBlocklist();
|
||||
Assert.ok(blocklist.isLoaded);
|
||||
Assert.ok(!blocklist._isBlocklistPreloaded());
|
||||
// Calling _loadBlocklist now would just re-load the list sync.
|
||||
|
||||
info("async test complete");
|
||||
blocklist._clear();
|
||||
|
||||
// async -> sync -> async
|
||||
let read = scope.OS.File.read;
|
||||
scope.OS.File.read = function(...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
executeSoon(() => {
|
||||
blocklist._loadBlocklist();
|
||||
// Now do the async bit after all:
|
||||
resolve(read(...args));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
await blocklist._preloadBlocklist();
|
||||
// We're mostly just checking this doesn't error out.
|
||||
Assert.ok(blocklist.isLoaded);
|
||||
Assert.ok(!blocklist._isBlocklistPreloaded());
|
||||
info("mixed async/sync test complete");
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче