Bug 1350640 - Send blocklist state on plugin list update; r?bsmedberg
Instead of synchronously checking the blocklist, package each plugin's
blocklist state with it when sending the information to the content
process. Whenever the blocklist is changed, just resend the whole
plugin list.
MozReview-Commit-ID: 1AX1EDdTRqb
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -657,17 +657,19 @@ public:
bool aExistenceCheck, bool aIsFromNsIFile);
typedef std::function<void(PRFileDesc*)> AnonymousTemporaryFileCallback;
nsresult AsyncOpenAnonymousTemporaryFile(const AnonymousTemporaryFileCallback& aCallback);
virtual already_AddRefed<nsIEventTarget> GetEventTargetFor(TabChild* aTabChild) override;
mozilla::ipc::IPCResult
- RecvSetPluginList(const uint32_t& aPluginEpoch, nsTArray<PluginTag>&& aPluginTags, nsTArray<FakePluginTag>&& aFakePluginTags) override;
+ RecvSetPluginList(const uint32_t& aPluginEpoch,
+ nsTArray<PluginTag>&& aPluginTags,
+ nsTArray<FakePluginTag>&& aFakePluginTags) override;
private:
static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure);
void StartForceKillTimer();
virtual void ActorDestroy(ActorDestroyReason why) override;
virtual void ProcessingError(Result aCode, const char* aReason) override;
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -2360,16 +2360,17 @@ nsPluginHost::SetPluginsInContent(uint32
SetChromeEpochForContent(aPluginEpoch);
for (auto tag : aPlugins) {
// Don't add the same plugin again.
if (nsPluginTag* existing = PluginWithId(tag.id())) {
UpdateInMemoryPluginInfo(existing);
+ existing->SetBlocklistState(tag.blocklistState());
continue;
}
nsPluginTag *pluginTag = new nsPluginTag(tag.id(),
tag.name().get(),
tag.description().get(),
tag.filename().get(),
"", // aFullPath
@@ -2377,17 +2378,18 @@ nsPluginHost::SetPluginsInContent(uint32
nsTArray<nsCString>(tag.mimeTypes()),
nsTArray<nsCString>(tag.mimeDescriptions()),
nsTArray<nsCString>(tag.extensions()),
tag.isJavaPlugin(),
tag.isFlashPlugin(),
tag.supportsAsyncRender(),
tag.lastModifiedTime(),
tag.isFromExtension(),
- tag.sandboxLevel());
+ tag.sandboxLevel(),
+ tag.blocklistState());
AddPluginTag(pluginTag);
}
for (const auto& tag : aFakePlugins) {
// Don't add the same plugin again.
for (const auto& existingTag : mFakePlugins) {
if (existingTag->Id() == tag.id()) {
continue;
@@ -2606,30 +2608,36 @@ nsPluginHost::SendPluginsToContent()
tag->SandboxScript()));
continue;
}
/// FIXME-jsplugins - We need to cleanup the various plugintag classes
/// to be more sane and avoid this dance
nsPluginTag *tag = static_cast<nsPluginTag *>(basetag.get());
+ uint32_t blocklistState;
+ if (NS_WARN_IF(NS_FAILED(tag->GetBlocklistState(&blocklistState)))) {
+ return NS_ERROR_FAILURE;
+ }
+
pluginTags.AppendElement(PluginTag(tag->mId,
tag->Name(),
tag->Description(),
tag->MimeTypes(),
tag->MimeDescriptions(),
tag->Extensions(),
tag->mIsJavaPlugin,
tag->mIsFlashPlugin,
tag->mSupportsAsyncRender,
tag->FileName(),
tag->Version(),
tag->mLastModifiedTime,
tag->IsFromExtension(),
- tag->mSandboxLevel));
+ tag->mSandboxLevel,
+ blocklistState));
}
nsTArray<dom::ContentParent*> parents;
dom::ContentParent::GetAll(parents);
for (auto p : parents)
{
Unused << p->SendSetPluginList(newPluginEpoch, pluginTags, fakePluginTags);
}
return NS_OK;
@@ -3484,16 +3492,23 @@ NS_IMETHODIMP nsPluginHost::Observe(nsIS
}
}
if (!strcmp("blocklist-updated", aTopic)) {
nsPluginTag* plugin = mPlugins;
while (plugin) {
plugin->InvalidateBlocklistState();
plugin = plugin->mNext;
}
+ // We update blocklists asynchronously by just sending a new plugin list to
+ // content.
+ if (XRE_IsParentProcess()) {
+ // We'll need to repack our tags and send them to content again.
+ IncrementChromeEpoch();
+ SendPluginsToContent();
+ }
}
#ifdef MOZ_WIDGET_ANDROID
if (!strcmp("application-background", aTopic)) {
for(uint32_t i = 0; i < mInstances.Length(); i++) {
mInstances[i]->NotifyForeground(false);
}
}
if (!strcmp("application-foreground", aTopic)) {
--- a/dom/plugins/base/nsPluginTags.cpp
+++ b/dom/plugins/base/nsPluginTags.cpp
@@ -293,30 +293,31 @@ nsPluginTag::nsPluginTag(uint32_t aId,
nsTArray<nsCString> aMimeTypes,
nsTArray<nsCString> aMimeDescriptions,
nsTArray<nsCString> aExtensions,
bool aIsJavaPlugin,
bool aIsFlashPlugin,
bool aSupportsAsyncRender,
int64_t aLastModifiedTime,
bool aFromExtension,
- int32_t aSandboxLevel)
+ int32_t aSandboxLevel,
+ uint16_t aBlocklistState)
: nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
aMimeDescriptions, aExtensions),
mId(aId),
mContentProcessRunningCount(0),
mLibrary(nullptr),
mIsJavaPlugin(aIsJavaPlugin),
mIsFlashPlugin(aIsFlashPlugin),
mSupportsAsyncRender(aSupportsAsyncRender),
mLastModifiedTime(aLastModifiedTime),
mSandboxLevel(aSandboxLevel),
mNiceFileName(),
- mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
- mCachedBlocklistStateValid(false),
+ mCachedBlocklistState(aBlocklistState),
+ mCachedBlocklistStateValid(true),
mIsFromExtension(aFromExtension)
{
}
nsPluginTag::~nsPluginTag()
{
NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
}
@@ -705,53 +706,57 @@ nsPluginTag::GetNiceName(nsACString & aR
NS_IMETHODIMP
nsPluginTag::GetBlocklistState(uint32_t *aResult)
{
#if defined(MOZ_WIDGET_ANDROID)
*aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
return NS_OK;
#else
- if (mCachedBlocklistStateValid) {
+
+ // 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;
}
- if (!XRE_IsParentProcess()) {
- *aResult = nsIBlocklistService::STATE_BLOCKED;
- dom::ContentChild* cp = dom::ContentChild::GetSingleton();
- if (!cp->SendGetBlocklistState(mId, aResult)) {
- return NS_OK;
- }
- } else {
- nsCOMPtr<nsIBlocklistService> blocklist =
- do_GetService("@mozilla.org/extensions/blocklist;1");
+ nsCOMPtr<nsIBlocklistService> blocklist =
+ do_GetService("@mozilla.org/extensions/blocklist;1");
- if (!blocklist) {
- *aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
- return NS_OK;
- }
-
- // The EmptyString()s are so we use the currently running application
- // and toolkit versions
- if (NS_FAILED(blocklist->GetPluginBlocklistState(this, EmptyString(),
- EmptyString(), aResult))) {
- *aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
- return NS_OK;
- }
+ 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;
return NS_OK;
#endif // defined(MOZ_WIDGET_ANDROID)
}
void
+nsPluginTag::SetBlocklistState(uint16_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;
+}
+
+void
nsPluginTag::InvalidateBlocklistState()
{
mCachedBlocklistStateValid = false;
}
NS_IMETHODIMP
nsPluginTag::GetLastModifiedTime(PRTime* aLastModifiedTime)
{
--- a/dom/plugins/base/nsPluginTags.h
+++ b/dom/plugins/base/nsPluginTags.h
@@ -130,30 +130,32 @@ public:
nsTArray<nsCString> aMimeTypes,
nsTArray<nsCString> aMimeDescriptions,
nsTArray<nsCString> aExtensions,
bool aIsJavaPlugin,
bool aIsFlashPlugin,
bool aSupportsAsyncRender,
int64_t aLastModifiedTime,
bool aFromExtension,
- int32_t aSandboxLevel);
+ int32_t aSandboxLevel,
+ uint16_t aBlocklistState);
void TryUnloadPlugin(bool inShutdown);
// plugin is enabled and not blocklisted
bool IsActive();
bool IsEnabled() override;
void SetEnabled(bool enabled);
bool IsClicktoplay();
bool IsBlocklisted();
PluginState GetPluginState();
void SetPluginState(PluginState state);
+ void SetBlocklistState(uint16_t aBlocklistState);
bool HasSameNameAndMimes(const nsPluginTag *aPluginTag) const;
const nsCString& GetNiceFileName() override;
bool IsFromExtension() const;
RefPtr<nsPluginTag> mNext;
uint32_t mId;
--- a/dom/plugins/ipc/PluginTypes.ipdlh
+++ b/dom/plugins/ipc/PluginTypes.ipdlh
@@ -19,16 +19,17 @@ struct PluginTag
bool isJavaPlugin;
bool isFlashPlugin;
bool supportsAsyncRender; // flash specific
nsCString filename;
nsCString version;
int64_t lastModifiedTime;
bool isFromExtension;
int32_t sandboxLevel;
+ uint16_t blocklistState;
};
struct FakePluginTag
{
uint32_t id;
URIParams handlerURI;
nsCString name;
nsCString description;