Bug 1675349: Replace plugin behavior with a basic fallback r=jmathies,mixedpuppy

The browser currently only enables plugin behavior for Flash and our internal test plugins.  This patch replaces support for those plugins with a simple fallback that shows a transparent region where the plugin would have been.  It removes the file system search(es) for the plugin dynamic libraries and short-circuits the logic to determine if plugins should do something special -- all implementations now behave the same in the presence of plugin elements.

The new behavior is:
1. If the <object> or <embed> element lists a type of something other than "x-shockwave-flash" or "x-test" then the behavior is unchanged.  This means that non-plugin types behave properly and unknown types (for example, typos) are also unaffected (they reduce to 0x0 elements).
2. If the <object> element has an HTML fallback in the DOM (see spec for <object> elements) then the fallback is always shown.
3. Otherwise, the element is shown as a transparent region with the size specified in attributes.

Differential Revision: https://phabricator.services.mozilla.com/D95902
This commit is contained in:
David Parks 2020-11-18 15:55:34 +00:00
Родитель e1be39b9e8
Коммит 1e71ef1cb8
20 изменённых файлов: 67 добавлений и 2063 удалений

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

@ -276,6 +276,11 @@ class PluginChild extends JSWindowActorChild {
overlay.removeAttribute("notext");
}
if (fallbackType == Ci.nsIObjectLoadingContent.PLUGIN_BLOCK_ALL) {
overlay.setAttribute("blockall", "blockall");
return OVERLAY_DISPLAY.HIDDEN;
}
// The hit test below only works with correct layout information,
// don't do it if layout needs flush.
// We also don't want to access scrollWidth/scrollHeight if
@ -384,6 +389,8 @@ class PluginChild extends JSWindowActorChild {
return "PluginVulnerableUpdatable";
case Ci.nsIObjectLoadingContent.PLUGIN_VULNERABLE_NO_UPDATE:
return "PluginVulnerableNoUpdate";
case Ci.nsIObjectLoadingContent.PLUGIN_BLOCK_ALL:
return "PluginBlockAll";
default:
// Not all states map to a handler
return null;
@ -475,6 +482,7 @@ class PluginChild extends JSWindowActorChild {
this.onPluginCrashed(pluginElement, event);
break;
case "PluginBlockAll":
case "PluginNotFound": {
/* NOP */
break;
@ -717,6 +725,7 @@ class PluginChild extends JSWindowActorChild {
event.originalTarget.getAttribute("anonid") != "closeIcon" &&
event.originalTarget.id != "closeIcon" &&
!overlay.hasAttribute("dismissed") &&
!overlay.hasAttribute("blockall") &&
event.button == 0 &&
event.isTrusted
) {

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

@ -9736,18 +9736,11 @@ uint32_t nsContentUtils::HtmlObjectContentTypeForMIMEType(
return nsIObjectLoadingContent::TYPE_DOCUMENT;
}
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
if (pluginHost) {
nsCOMPtr<nsIPluginTag> tag = PluginTagForType(aMIMEType, aNoFakePlugin);
if (tag) {
if (!aNoFakePlugin &&
nsCOMPtr<nsIFakePluginTag>(do_QueryInterface(tag))) {
return nsIObjectLoadingContent::TYPE_FAKE_PLUGIN;
}
// ShouldPlay will handle checking for disabled plugins
return nsIObjectLoadingContent::TYPE_PLUGIN;
}
bool isPlugin = nsPluginHost::GetSpecialType(aMIMEType) !=
nsPluginHost::eSpecialType_None;
if (isPlugin) {
// ShouldPlay will handle checking for disabled plugins
return nsIObjectLoadingContent::TYPE_PLUGIN;
}
return nsIObjectLoadingContent::TYPE_NULL;

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

@ -65,6 +65,9 @@ interface nsIObjectLoadingContent : nsISupports
const unsigned long PLUGIN_VULNERABLE_NO_UPDATE = 10;
// The plugin is click-to-play, but the user won't see overlays
const unsigned long PLUGIN_CLICK_TO_PLAY_QUIET = 11;
// Plugins are no longer supported. The plugin should not load and should
// be represented by a transparent element.
const unsigned long PLUGIN_BLOCK_ALL = 12;
// Plugins-specific permission indicating that we want to prompt the user
// to decide whether they want to allow a plugin, but to do so in a less

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

@ -96,6 +96,7 @@
#include "mozilla/net/UrlClassifierFeatureFactory.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/PresShell.h"
#include "mozilla/StaticPrefs_plugins.h"
#include "mozilla/StaticPrefs_security.h"
#include "nsChannelClassifier.h"
#include "nsFocusManager.h"
@ -1292,6 +1293,8 @@ EventStates nsObjectLoadingContent::ObjectState() const {
return NS_EVENT_STATE_VULNERABLE_UPDATABLE;
case eFallbackVulnerableNoUpdate:
return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
case eFallbackBlockAllPlugins:
return NS_EVENT_STATE_HANDLER_NOPLUGINS;
}
}
MOZ_ASSERT_UNREACHABLE("unknown type?");
@ -2081,11 +2084,11 @@ nsresult nsObjectLoadingContent::LoadObject(bool aNotify, bool aForceLoad,
// reason click-to-play instead. Items resolved as Image/Document
// will not be checked for previews, as well as invalid plugins
// (they will not have the mContentType set).
FallbackType clickToPlayReason;
if (!mActivated && IsPluginType(mType) && !ShouldPlay(clickToPlayReason)) {
LOG(("OBJLC [%p]: Marking plugin as click-to-play", this));
FallbackType noPlayReason;
if (!mActivated && IsPluginType(mType) && !ShouldPlay(noPlayReason)) {
LOG(("OBJLC [%p]: Marking plugin as do-not-play", this));
mType = eType_Null;
fallbackType = clickToPlayReason;
fallbackType = noPlayReason;
}
if (!mActivated && IsPluginType(mType)) {
@ -2233,8 +2236,9 @@ nsresult nsObjectLoadingContent::LoadObject(bool aNotify, bool aForceLoad,
NS_ASSERTION(!mFrameLoader && !mInstanceOwner,
"switched to type null but also loaded something");
// Don't fire error events if we're falling back to click-to-play; instead
// pretend like this is a really slow-loading plug-in instead.
// Don't fire error events if we're falling back to click-to-play or if we
// are blocking all plugins; pretend like this is a really slow-loading
// plug-in instead.
if (fallbackType != eFallbackClickToPlay &&
fallbackType != eFallbackClickToPlayQuiet) {
MaybeFireErrorEvent();
@ -2604,11 +2608,11 @@ void nsObjectLoadingContent::NotifyStateChanged(ObjectType aOldType,
}
// Create/destroy plugin problem UAWidget.
const EventStates pluginProblemState = NS_EVENT_STATE_HANDLER_BLOCKED |
NS_EVENT_STATE_HANDLER_CRASHED |
NS_EVENT_STATE_TYPE_CLICK_TO_PLAY |
NS_EVENT_STATE_VULNERABLE_UPDATABLE |
NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
const EventStates pluginProblemState =
NS_EVENT_STATE_HANDLER_BLOCKED | NS_EVENT_STATE_HANDLER_CRASHED |
NS_EVENT_STATE_TYPE_CLICK_TO_PLAY |
NS_EVENT_STATE_VULNERABLE_UPDATABLE |
NS_EVENT_STATE_VULNERABLE_NO_UPDATE | NS_EVENT_STATE_HANDLER_NOPLUGINS;
bool hadProblemState = !(aOldState & pluginProblemState).IsEmpty();
bool hasProblemState = !(newState & pluginProblemState).IsEmpty();
@ -2769,7 +2773,8 @@ nsNPAPIPluginInstance* nsObjectLoadingContent::ScriptRequestPluginInstance(
// an event. Fallback types >= eFallbackClickToPlay are plugin-replacement
// types, see header.
if (callerIsContentJS && !mScriptRequested && InActiveDocument(thisContent) &&
mType == eType_Null && mFallbackType >= eFallbackClickToPlay) {
mType == eType_Null && mFallbackType >= eFallbackClickToPlay &&
mFallbackType <= eFallbackClickToPlayQuiet) {
nsCOMPtr<nsIRunnable> ev =
new nsSimplePluginEvent(thisContent, u"PluginScripted"_ns);
nsresult rv = NS_DispatchToCurrentThread(ev);
@ -2875,7 +2880,8 @@ void nsObjectLoadingContent::LoadFallback(FallbackType aType, bool aNotify) {
nsTArray<nsINodeList*> childNodes;
if (thisContent->IsHTMLElement(nsGkAtoms::object) &&
(aType == eFallbackUnsupported || aType == eFallbackDisabled ||
aType == eFallbackBlocklisted || aType == eFallbackAlternate)) {
aType == eFallbackBlocklisted || aType == eFallbackAlternate ||
aType == eFallbackBlockAllPlugins)) {
for (nsIContent* child = thisContent->GetFirstChild(); child;) {
// When we advance to our next child, we don't want to traverse subtrees
// under descendant <object> and <embed> elements; those will handle
@ -3024,7 +3030,8 @@ void nsObjectLoadingContent::PlayPlugin(SystemCallerGuarantee,
// If we're in a click-to-play state, reload.
// Fallback types >= eFallbackClickToPlay are plugin-replacement types, see
// header
if (mType == eType_Null && mFallbackType >= eFallbackClickToPlay) {
if (mType == eType_Null && mFallbackType >= eFallbackClickToPlay &&
mFallbackType <= eFallbackClickToPlayQuiet) {
aRv = LoadObject(true, true);
}
}
@ -3131,162 +3138,11 @@ bool nsObjectLoadingContent::ShouldBlockContent() {
}
bool nsObjectLoadingContent::ShouldPlay(FallbackType& aReason) {
nsresult rv;
MOZ_ASSERT(!BrowserTabsRemoteAutostart() || !XRE_IsParentProcess());
if (BrowserTabsRemoteAutostart() && XRE_IsParentProcess()) {
// We no longer support loading plugins in the parent process.
aReason = eFallbackDisabled;
return false;
}
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
// Order of checks:
// * Assume a default of click-to-play
// * If globally disabled, per-site permissions cannot override.
// * If blocklisted, override the reason with the blocklist reason
// * Check if the flash blocking status for this page denies flash from
// loading.
// * Check per-site permissions and follow those if specified.
// * Honor per-plugin disabled permission
// * Blocklisted plugins are forced to CtP
// * Check per-plugin permission and follow that.
aReason = eFallbackClickToPlay;
uint32_t enabledState = nsIPluginTag::STATE_DISABLED;
pluginHost->GetStateForType(mContentType, nsPluginHost::eExcludeNone,
&enabledState);
if (nsIPluginTag::STATE_DISABLED == enabledState) {
aReason = eFallbackDisabled;
return false;
}
// Before we check permissions, get the blocklist state of this plugin to set
// the fallback reason correctly. In the content process this will involve
// an ipc call to chrome.
uint32_t blocklistState = nsIBlocklistService::STATE_BLOCKED;
pluginHost->GetBlocklistStateForType(mContentType, nsPluginHost::eExcludeNone,
&blocklistState);
if (blocklistState == nsIBlocklistService::STATE_BLOCKED) {
// no override possible
aReason = eFallbackBlocklisted;
return false;
}
if (blocklistState ==
nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE) {
aReason = eFallbackVulnerableUpdatable;
} else if (blocklistState ==
nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
aReason = eFallbackVulnerableNoUpdate;
}
// Document and window lookup
nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIObjectLoadingContent*>(this));
MOZ_ASSERT(thisContent);
Document* ownerDoc = thisContent->OwnerDoc();
nsCOMPtr<nsPIDOMWindowOuter> window = ownerDoc->GetWindow();
if (!window) {
return false;
}
nsCOMPtr<nsPIDOMWindowOuter> topWindow = window->GetInProcessTop();
NS_ENSURE_TRUE(topWindow, false);
nsCOMPtr<Document> topDoc = topWindow->GetDoc();
NS_ENSURE_TRUE(topDoc, false);
// Check the flash blocking status for this page (this applies to Flash only)
FlashClassification documentClassification = FlashClassification::Unknown;
if (IsFlashMIME(mContentType)) {
documentClassification = ownerDoc->DocumentFlashClassification();
}
if (documentClassification == FlashClassification::Denied) {
aReason = eFallbackDisabled;
return false;
}
// Check the permission manager for permission based on the principal of
// the toplevel content.
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
NS_ENSURE_TRUE(permissionManager, false);
// For now we always say that the system principal uses click-to-play since
// that maintains current behavior and we have tests that expect this. What
// we really should do is disable plugins entirely in pages that use the
// system principal, i.e. in chrome pages. That way the click-to-play code
// here wouldn't matter at all. Bug 775301 is tracking this.
if (!topDoc->NodePrincipal()->IsSystemPrincipal()) {
nsAutoCString permissionString;
rv = pluginHost->GetPermissionStringForType(
mContentType, nsPluginHost::eExcludeNone, permissionString);
NS_ENSURE_SUCCESS(rv, false);
uint32_t permission;
rv = permissionManager->TestPermissionFromPrincipal(
topDoc->NodePrincipal(), permissionString, &permission);
NS_ENSURE_SUCCESS(rv, false);
switch (permission) {
case nsIPermissionManager::ALLOW_ACTION:
if (PreferFallback(false /* isPluginClickToPlay */)) {
aReason = eFallbackAlternate;
return false;
}
return true;
case nsIPermissionManager::DENY_ACTION:
aReason = eFallbackDisabled;
return false;
case PLUGIN_PERMISSION_PROMPT_ACTION_QUIET:
if (PreferFallback(true /* isPluginClickToPlay */)) {
aReason = eFallbackAlternate;
} else {
aReason = eFallbackClickToPlayQuiet;
}
return false;
case nsIPermissionManager::PROMPT_ACTION:
if (PreferFallback(true /* isPluginClickToPlay */)) {
// False is already returned in this case, but
// it's important to correctly set aReason too.
aReason = eFallbackAlternate;
}
return false;
case nsIPermissionManager::UNKNOWN_ACTION:
break;
default:
MOZ_ASSERT(false);
return false;
}
}
// No site-specific permissions. Vulnerable plugins are automatically CtP
if (blocklistState ==
nsIBlocklistService::STATE_VULNERABLE_UPDATE_AVAILABLE ||
blocklistState == nsIBlocklistService::STATE_VULNERABLE_NO_UPDATE) {
return false;
}
if (PreferFallback(enabledState == nsIPluginTag::STATE_CLICKTOPLAY)) {
aReason = eFallbackAlternate;
return false;
}
// On the following switch we don't need to handle the case where
// documentClassification is FlashClassification::Denied because
// that's already handled above.
switch (enabledState) {
case nsIPluginTag::STATE_ENABLED:
return true;
case nsIPluginTag::STATE_CLICKTOPLAY:
if (documentClassification == FlashClassification::Allowed) {
return true;
}
return false;
}
MOZ_CRASH("Unexpected enabledState");
// We no longer support plugins. Always fall back to our placeholder.
aReason = eFallbackBlockAllPlugins;
return false;
}
bool nsObjectLoadingContent::FavorFallbackMode(bool aIsPluginClickToPlay) {

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

@ -104,6 +104,8 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
// The plugin is click-to-play, but the user won't see overlays
eFallbackClickToPlayQuiet =
nsIObjectLoadingContent::PLUGIN_CLICK_TO_PLAY_QUIET,
// Plugins are no longer supported. Content is just a transparent rect.
eFallbackBlockAllPlugins = nsIObjectLoadingContent::PLUGIN_BLOCK_ALL,
};
nsObjectLoadingContent();

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

@ -294,6 +294,9 @@ class EventStates {
#define NS_EVENT_STATE_MOZINERT NS_DEFINE_EVENT_STATE_MACRO(54)
// Topmost Modal <dialog> element in top layer
#define NS_EVENT_STATE_TOPMOST_MODAL_DIALOG NS_DEFINE_EVENT_STATE_MACRO(55)
// Handler for empty element that represents plugin instances in builds
// where plugin support is removed..
#define NS_EVENT_STATE_HANDLER_NOPLUGINS NS_DEFINE_EVENT_STATE_MACRO(56)
/**
* NOTE: do not go over 63 without updating EventStates::InternalType!
*/

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -1,126 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef PluginFinder_h_
#define PluginFinder_h_
#include "nsIRunnable.h"
#include "mozilla/RefPtr.h"
#include "nsCOMPtr.h"
#include "nsString.h"
#include "nsTArray.h"
#include "nsPluginTags.h"
#include "mozilla/StaticPrefs_dom.h"
#include "nsIAsyncShutdown.h"
class nsIFile;
class nsPluginHost;
class nsInvalidPluginTag : public nsISupports {
virtual ~nsInvalidPluginTag();
public:
explicit nsInvalidPluginTag(const char* aFullPath,
int64_t aLastModifiedTime = 0);
NS_DECL_THREADSAFE_ISUPPORTS
nsCString mFullPath;
int64_t mLastModifiedTime;
bool mSeen;
RefPtr<nsInvalidPluginTag> mPrev;
RefPtr<nsInvalidPluginTag> mNext;
};
static inline bool UnloadPluginsASAP() {
return mozilla::StaticPrefs::dom_ipc_plugins_unloadTimeoutSecs() == 0;
}
/**
* Class responsible for discovering plugins on disk, in part based
* on cached information stored in pluginreg.dat and in the prefs.
*
* This runnable is designed to be used as a one-shot. It's created
* when the pluginhost wants to find plugins, and the next time it
* wants to do so, it should create a new one.
*/
class PluginFinder final : public nsIRunnable, public nsIAsyncShutdownBlocker {
~PluginFinder() = default;
public:
explicit PluginFinder(bool aFlashOnly);
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSIASYNCSHUTDOWNBLOCKER
typedef std::function<void(
bool /* aPluginsChanged */, RefPtr<nsPluginTag> /* aNewPlugins */,
nsTArray<
std::pair<bool, RefPtr<nsPluginTag>>>&) /* aBlocklistRequestPairs */>
FoundPluginCallback;
typedef std::function<void(bool /* aPluginsChanged */)> PluginChangeCallback;
// The expectation is that one (and only one) of these gets called
// by the plugin host. We can't easily do the work in the constructor
// because in some cases we'll fail early (e.g. if we're called before
// the profile is ready) and want to signal that to the consumer via
// the nsresult return value, which we can't do in a constructor.
nsresult DoFullSearch(const FoundPluginCallback& aCallback);
nsresult HavePluginsChanged(const PluginChangeCallback& aCallback);
static nsresult WritePluginInfo(
bool aFlashOnly, nsPluginTag* aPlugins,
nsInvalidPluginTag* aInvalidPlugins = nullptr);
private:
nsPluginTag* FirstPluginWithPath(const nsCString& path);
bool ShouldAddPlugin(const nsPluginInfo& aInfo);
nsresult ReadFlashInfo();
static nsresult WriteFlashInfo(nsPluginTag* aPlugins);
static nsresult EnsurePluginReg();
nsresult ReadPluginInfo();
nsresult ReadPluginInfoFromDisk();
nsresult DeterminePluginDirs();
nsresult ScanPluginsDirectory(nsIFile* aPluginsDir, bool* aPluginsChanged);
nsresult FindPlugins();
void RemoveCachedPluginsInfo(const char* filePath, nsPluginTag** result);
nsTArray<nsCOMPtr<nsIFile>> mPluginDirs;
// The plugins we've found on disk (to be passed to the host)
RefPtr<nsPluginTag> mPlugins;
// The plugin whose metadata we found in cache
RefPtr<nsPluginTag> mCachedPlugins;
// Any invalid plugins our cache info made us aware of prior to actually
// examining the disk; this is a performance optimization to avoid trying
// to load files that aren't plugins on every browser startup.
RefPtr<nsInvalidPluginTag> mInvalidPlugins;
// The bool (shouldSoftBlock) indicates whether we should disable the plugin
// if it's soft-blocked in the blocklist
// The plugintag is a reference to the actual plugin whose blocklist state
// needs checking.
nsTArray<std::pair<bool, RefPtr<nsPluginTag>>> mPluginBlocklistRequests;
FoundPluginCallback mFoundPluginCallback;
PluginChangeCallback mChangeCallback;
RefPtr<nsPluginHost> mHost;
bool mFlashOnly;
bool mCreateList;
bool mPluginsChanged;
bool mFinishedFinding;
bool mCalledOnMainthread;
bool mShutdown;
};
#endif

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

@ -23,7 +23,6 @@ EXPORTS += [
"nptypes.h",
"nsJSNPRuntime.h",
"nsNPAPIPluginInstance.h",
"nsPluginDirServiceProvider.h",
"nsPluginHost.h",
"nsPluginInstanceOwner.h",
"nsPluginLogging.h",
@ -40,7 +39,6 @@ UNIFIED_SOURCES += [
"nsPluginInstanceOwner.cpp",
"nsPluginStreamListenerPeer.cpp",
"nsPluginTags.cpp",
"PluginFinder.cpp",
]
SOURCES += [
@ -50,7 +48,6 @@ SOURCES += [
if CONFIG["OS_ARCH"] == "WINNT":
UNIFIED_SOURCES += [
"nsPluginDirServiceProvider.cpp",
"nsPluginNativeWindowWin.cpp",
"nsPluginsDirWin.cpp",
]

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

@ -1,63 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsPluginDirServiceProvider.h"
#include "nsCRT.h"
#include "nsIFile.h"
#include <windows.h>
#include "nsIWindowsRegKey.h"
using namespace mozilla;
/* static */ nsresult GetPLIDDirectories(nsTArray<nsCOMPtr<nsIFile>>& aDirs) {
GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, aDirs);
GetPLIDDirectoriesWithRootKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
aDirs);
return NS_OK;
}
/* static */ nsresult GetPLIDDirectoriesWithRootKey(
uint32_t aKey, nsTArray<nsCOMPtr<nsIFile>>& aDirs) {
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1");
NS_ENSURE_TRUE(regKey, NS_ERROR_FAILURE);
nsresult rv = regKey->Open(aKey, u"Software\\MozillaPlugins"_ns,
nsIWindowsRegKey::ACCESS_READ);
if (NS_FAILED(rv)) {
return rv;
}
uint32_t childCount = 0;
regKey->GetChildCount(&childCount);
for (uint32_t index = 0; index < childCount; ++index) {
nsAutoString childName;
rv = regKey->GetChildName(index, childName);
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIWindowsRegKey> childKey;
rv = regKey->OpenChild(childName, nsIWindowsRegKey::ACCESS_QUERY_VALUE,
getter_AddRefs(childKey));
if (NS_SUCCEEDED(rv) && childKey) {
nsAutoString path;
rv = childKey->ReadStringValue(u"Path"_ns, path);
if (NS_SUCCEEDED(rv)) {
// We deliberately do not do any further checks here on whether
// these are actually directories, whether they even exist, or
// whether they are duplicates. The pluginhost code will do them.
// This allows the whole process to avoid mainthread IO.
nsCOMPtr<nsIFile> localFile;
rv = NS_NewLocalFile(path, true, getter_AddRefs(localFile));
if (NS_SUCCEEDED(rv) && localFile) {
aDirs.AppendElement(localFile);
}
}
}
}
}
return NS_OK;
}

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

@ -1,19 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsPluginDirServiceProvider_h_
#define nsPluginDirServiceProvider_h_
#ifdef XP_WIN
# include "nsCOMPtr.h"
# include "nsTArray.h"
static nsresult GetPLIDDirectories(nsTArray<nsCOMPtr<nsIFile>>& aDirs);
static nsresult GetPLIDDirectoriesWithRootKey(
uint32_t aKey, nsTArray<nsCOMPtr<nsIFile>>& aDirs);
#endif // XP_WIN
#endif // nsPluginDirServiceProvider_h_

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

@ -77,8 +77,6 @@
#include "mozilla/dom/Promise.h"
#include "PluginFinder.h"
#if defined(XP_WIN)
# include "nsIWindowMediator.h"
# include "nsIBaseWindow.h"
@ -182,14 +180,6 @@ class BlocklistPromiseHandler final
sPluginBlocklistStatesChangedSinceLastWrite = false;
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
// XXXgijs This will wipe invalid plugin info. That's unfortunate, but
// there's no easy way around this - re-running FindPlugins will only
// keep invalid plugin info around long enough to use it if we force
// it to re-create plugin tags, and in any case can cause re-entrancy
// because it would do more async blocklist lookups. Just make sure
// we write the blocklist info.
PluginFinder::WritePluginInfo(host->mFlashOnly, host->mPlugins);
// We update blocklist info in content processes asynchronously
// by just sending a new plugin list to content.
host->IncrementChromeEpoch();
@ -265,17 +255,11 @@ nsPluginHost::nsPluginHost()
: mPluginsLoaded(false),
mOverrideInternalTypes(false),
mPluginsDisabled(false),
mFlashOnly(true),
mDoReloadOnceFindingFinished(false),
mAddedFinderShutdownBlocker(false),
mPluginEpoch(0) {
// check to see if pref is set at startup to let plugins take over in
// full page mode for certain image mime types that we handle internally
mOverrideInternalTypes =
Preferences::GetBool("plugin.override_internal_types", false);
if (xpc::IsInAutomation()) {
mFlashOnly = Preferences::GetBool("plugin.load_flash_only", true);
}
bool waylandBackend = false;
#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
@ -366,56 +350,8 @@ bool nsPluginHost::IsRunningPlugin(nsPluginTag* aPluginTag) {
}
nsresult nsPluginHost::ReloadPlugins() {
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsPluginHost::ReloadPlugins Begin\n"));
// If we're calling this from a content process, forward the reload request to
// the parent process. If plugins actually changed, it will notify us
// asynchronously later.
if (XRE_IsContentProcess()) {
Unused
<< mozilla::dom::ContentChild::GetSingleton()->SendMaybeReloadPlugins();
// In content processes, always signal that plugins have not changed. We
// will never know if they changed here unless we make slow synchronous
// calls. This information will hopefully only be wrong once, as if there
// has been a plugin update, we expect to have gotten notification from the
// parent process and everything should be updated by the next time this is
// called. See Bug 1337058 for more info.
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
}
// this will create the initial plugin list out of cache
// if it was not created yet
if (!mPluginsLoaded) return LoadPlugins();
// We're already in the process of finding more plugins. Do it again once
// done (because maybe things have changed since we started looking).
if (mPendingFinder) {
mDoReloadOnceFindingFinished = true;
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
}
// we are re-scanning plugins. New plugins may have been added, also some
// plugins may have been removed, so we should probably shut everything down
// but don't touch running (active and not stopped) plugins
// check if plugins changed, no need to do anything else
// if no changes to plugins have been made
// We're doing this on the main thread, and we checked mPendingFinder
// above, so we don't need to do anything else to ensure we don't re-enter.
// Future work may make this asynchronous and do the finding away from
// the mainthread for the reload case, too, (in which case we should use
// mPendingFinder instead of a local copy, and update PluginFinder) but at
// the moment this is less important than the initial finding on startup.
RefPtr<PluginFinder> pf = new PluginFinder(mFlashOnly);
bool pluginschanged;
MOZ_TRY(pf->HavePluginsChanged([&pluginschanged](bool aPluginsChanged) {
pluginschanged = aPluginsChanged;
}));
pf->Run();
// if no changed detected, return an appropriate error code
if (!pluginschanged) return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
return ActuallyReloadPlugins();
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsPluginHost::ReloadPlugins\n"));
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
}
void nsPluginHost::ClearNonRunningPlugins() {
@ -637,35 +573,8 @@ void nsPluginHost::OnPluginInstanceDestroyed(nsPluginTag* aPluginTag) {
}
}
// We have some options for unloading plugins if they have no instances.
//
// Unloading plugins immediately can be bad - some plugins retain state
// between instances even when there are none. This is largely limited to
// going from one page to another, so state is retained without an instance
// for only a very short period of time. In order to allow this to work
// we don't unload plugins immediately by default. This is supported
// via a hidden user pref though.
//
// Another reason not to unload immediately is that loading is expensive,
// and it is better to leave popular plugins loaded.
//
// Our default behavior is to try to unload a plugin after a pref-controlled
// delay once its last instance is destroyed. This seems like a reasonable
// compromise that allows us to reclaim memory while allowing short state
// retention and avoid perf hits for loading popular plugins.
if (!hasInstance) {
if (UnloadPluginsASAP()) {
aPluginTag->TryUnloadPlugin(false);
} else {
if (aPluginTag->mUnloadTimer) {
aPluginTag->mUnloadTimer->Cancel();
} else {
aPluginTag->mUnloadTimer = NS_NewTimer();
}
uint32_t unloadTimeout = StaticPrefs::dom_ipc_plugins_unloadTimeoutSecs();
aPluginTag->mUnloadTimer->InitWithCallback(this, 1000 * unloadTimeout,
nsITimer::TYPE_ONE_SHOT);
}
aPluginTag->TryUnloadPlugin(false);
}
}
@ -1828,27 +1737,6 @@ void nsPluginHost::SetChromeEpochForContent(uint32_t aEpoch) {
mPluginEpoch = aEpoch;
}
#ifdef XP_WIN
static void WatchRegKey(uint32_t aRoot, nsCOMPtr<nsIWindowsRegKey>& aKey) {
if (aKey) {
return;
}
aKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
if (!aKey) {
return;
}
nsresult rv = aKey->Open(
aRoot, u"Software\\MozillaPlugins"_ns,
nsIWindowsRegKey::ACCESS_READ | nsIWindowsRegKey::ACCESS_NOTIFY);
if (NS_FAILED(rv)) {
aKey = nullptr;
return;
}
aKey->StartWatching(true);
}
#endif
already_AddRefed<nsIAsyncShutdownClient> GetProfileChangeTeardownPhase() {
nsCOMPtr<nsIAsyncShutdownService> asyncShutdownSvc =
services::GetAsyncShutdownService();
@ -1864,133 +1752,9 @@ already_AddRefed<nsIAsyncShutdownClient> GetProfileChangeTeardownPhase() {
return shutdownPhase.forget();
}
nsresult nsPluginHost::LoadPlugins() {
// This should only be run in the parent process. On plugin list change, we'll
// update observers in the content process as part of SetPluginsInContent
if (XRE_IsContentProcess()) {
return NS_OK;
}
// do not do anything if it is already done
// use ReloadPlugins() to enforce loading
if (mPluginsLoaded) return NS_OK;
nsresult nsPluginHost::LoadPlugins() { return NS_OK; }
// Uh oh, someone's forcing us to load plugins, but we're already in the
// process of doing so. Schedule a reload for when we're done:
if (mPendingFinder) {
mDoReloadOnceFindingFinished = true;
return NS_OK;
}
if (mPluginsDisabled) return NS_OK;
#ifdef XP_WIN
WatchRegKey(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE, mRegKeyHKLM);
WatchRegKey(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, mRegKeyHKCU);
#endif
// This is a runnable. The main part of its work will be done away from the
// main thread.
mPendingFinder = new PluginFinder(mFlashOnly);
mDoReloadOnceFindingFinished = false;
mAddedFinderShutdownBlocker = false;
RefPtr<nsPluginHost> self = this;
// Note that if we're in flash only mode, which is the default, then the
// callback will be called twice. Once for flash (or nothing, if we're not
// (yet) aware of flash being present), and then again after we've actually
// looked for it on disk.
nsresult rv = mPendingFinder->DoFullSearch(
[self](bool aPluginsChanged, RefPtr<nsPluginTag> aPlugins,
const nsTArray<std::pair<bool, RefPtr<nsPluginTag>>>&
aBlocklistRequests) {
MOZ_ASSERT(NS_IsMainThread(),
"Callback should only be called on the main thread.");
self->mPluginsLoaded = true;
if (aPluginsChanged) {
self->ClearNonRunningPlugins();
while (aPlugins) {
RefPtr<nsPluginTag> pluginTag = aPlugins;
aPlugins = aPlugins->mNext;
self->AddPluginTag(pluginTag);
}
self->IncrementChromeEpoch();
self->BroadcastPluginsToContent();
}
// Do blocklist queries immediately after.
for (auto pair : aBlocklistRequests) {
RefPtr<nsPluginTag> pluginTag = pair.second;
bool shouldSoftblock = pair.first;
self->UpdatePluginBlocklistState(pluginTag, shouldSoftblock);
}
if (aPluginsChanged) {
nsCOMPtr<nsIObserverService> obsService =
mozilla::services::GetObserverService();
if (obsService) {
obsService->NotifyObservers(nullptr, "plugins-list-updated",
nullptr);
}
}
});
// Deal with the profile not being ready yet by returning NS_OK - we'll get
// the data later.
if (NS_FAILED(rv)) {
mPendingFinder = nullptr;
if (rv == NS_ERROR_NOT_AVAILABLE) {
return NS_OK;
}
return rv;
}
bool dispatched = false;
// If we're only looking for flash (the default), try to do so away from
// the main thread. Note that in this case, the callback may have been called
// already, from the cached plugin info.
if (mFlashOnly) {
// First add the shutdown blocker, to avoid the potential for race
// conditions.
nsCOMPtr<nsIAsyncShutdownClient> shutdownPhase =
GetProfileChangeTeardownPhase();
if (shutdownPhase) {
rv = shutdownPhase->AddBlocker(mPendingFinder,
NS_LITERAL_STRING_FROM_CSTRING(__FILE__),
__LINE__, u""_ns);
mAddedFinderShutdownBlocker = NS_SUCCEEDED(rv);
}
nsCOMPtr<nsIEventTarget> target =
do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv)) {
rv = target->Dispatch(mPendingFinder, nsIEventTarget::DISPATCH_NORMAL);
dispatched = NS_SUCCEEDED(rv);
}
// If we somehow failed to dispatch, remove the shutdown blocker.
if (mAddedFinderShutdownBlocker && !dispatched) {
shutdownPhase->RemoveBlocker(mPendingFinder);
mAddedFinderShutdownBlocker = false;
}
}
if (!dispatched) {
mPendingFinder->Run();
// We're running synchronously, so just remove the pending finder now.
mPendingFinder = nullptr;
}
return NS_OK;
}
void nsPluginHost::FindingFinished() {
if (mAddedFinderShutdownBlocker) {
nsCOMPtr<nsIAsyncShutdownClient> shutdownPhase =
GetProfileChangeTeardownPhase();
shutdownPhase->RemoveBlocker(mPendingFinder);
mAddedFinderShutdownBlocker = false;
}
mPendingFinder = nullptr;
if (mDoReloadOnceFindingFinished) {
Unused << ReloadPlugins();
}
}
void nsPluginHost::FindingFinished() {}
nsresult nsPluginHost::SetPluginsInContent(
uint32_t aPluginEpoch, nsTArray<mozilla::plugins::PluginTag>& aPlugins,
@ -2889,9 +2653,7 @@ bool nsPluginHost::CanUsePluginForMIMEType(const nsACString& aMIMEType) {
if (nsPluginHost::GetSpecialType(aMIMEType) ==
nsPluginHost::eSpecialType_Flash ||
MimeTypeIsAllowedForFakePlugin(NS_ConvertUTF8toUTF16(aMIMEType)) ||
aMIMEType.LowerCaseEqualsLiteral("application/x-test") ||
aMIMEType.LowerCaseEqualsLiteral("application/x-second-test") ||
aMIMEType.LowerCaseEqualsLiteral("application/x-third-test")) {
aMIMEType.LowerCaseEqualsLiteral("application/x-test")) {
return true;
}

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

@ -59,8 +59,6 @@ struct _NPP;
typedef _NPP* NPP;
#endif
class PluginFinder;
class nsPluginHost final : public nsIPluginHost,
public nsIObserver,
public nsITimerCallback,
@ -68,7 +66,6 @@ class nsPluginHost final : public nsIPluginHost,
public nsINamed {
friend class nsPluginTag;
friend class nsFakePluginTag;
friend class PluginFinder;
virtual ~nsPluginHost();
public:
@ -315,7 +312,6 @@ class nsPluginHost final : public nsIPluginHost,
void ClearNonRunningPlugins();
nsresult ActuallyReloadPlugins();
// Callback into the host from PluginFinder once it's done.
void FindingFinished();
RefPtr<nsPluginTag> mPlugins;
@ -333,14 +329,6 @@ class nsPluginHost final : public nsIPluginHost,
// set by pref plugin.disable
bool mPluginsDisabled;
// set by pref plugin.load_flash_only
bool mFlashOnly;
// Only one plugin finding operation should be run at a time.
RefPtr<PluginFinder> mPendingFinder;
bool mDoReloadOnceFindingFinished;
bool mAddedFinderShutdownBlocker;
// Any instances in this array will have valid plugin objects via GetPlugin().
// When removing an instance it might not die - be sure to null out it's
// plugin.

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

@ -4,17 +4,9 @@
@namespace url(http://www.w3.org/1999/xhtml); /* set default namespace to HTML */
embed:-moz-handler-blocked,
embed:-moz-handler-crashed,
embed:-moz-handler-clicktoplay,
embed:-moz-handler-vulnerable-updatable,
embed:-moz-handler-vulnerable-no-update,
object:-moz-handler-blocked,
object:-moz-handler-crashed,
object:-moz-handler-clicktoplay,
object:-moz-handler-vulnerable-updatable,
object:-moz-handler-vulnerable-no-update {
embed:-moz-handler-noplugins,
object:-moz-handler-noplugins {
display: inline-block;
overflow: hidden;
opacity: 1 !important;
opacity: 0 !important;
}

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

@ -144,6 +144,8 @@ bitflags! {
const IN_MOZINERT_STATE = 1 << 54;
/// State for the topmost dialog element in top layer
const IN_TOPMOST_MODAL_DIALOG_STATE = 1 << 55;
/// Non-standard & undocumented.
const IN_HANDLER_NOPLUGINS = 1 << 56;
}
}

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

@ -72,6 +72,8 @@ macro_rules! apply_non_ts_list {
("-moz-handler-disabled", MozHandlerDisabled, IN_HANDLER_DISABLED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
("-moz-handler-blocked", MozHandlerBlocked, IN_HANDLER_BLOCKED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
("-moz-handler-crashed", MozHandlerCrashed, IN_HANDLER_CRASHED_STATE, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
("-moz-handler-noplugins", MozHandlerNoPlugins, IN_HANDLER_NOPLUGINS, PSEUDO_CLASS_ENABLED_IN_UA_SHEETS_AND_CHROME),
("-moz-math-increment-script-level", MozMathIncrementScriptLevel, IN_INCREMENT_SCRIPT_LEVEL_STATE, _),
("required", Required, IN_REQUIRED_STATE, _),

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

@ -2040,6 +2040,7 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
NonTSPseudoClass::MozHandlerClickToPlay |
NonTSPseudoClass::MozHandlerVulnerableUpdatable |
NonTSPseudoClass::MozHandlerVulnerableNoUpdate |
NonTSPseudoClass::MozHandlerNoPlugins |
NonTSPseudoClass::MozMathIncrementScriptLevel |
NonTSPseudoClass::InRange |
NonTSPseudoClass::OutOfRange |

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

@ -6,7 +6,8 @@
// This is a UA Widget. It runs in per-origin UA widget scope,
// to be loaded by UAWidgetsChild.jsm.
// This widget results in a hidden element that occupies room where the plugin
// would be if we still supported plugins.
this.PluginProblemWidget = class {
constructor(shadowRoot) {
this.shadowRoot = shadowRoot;
@ -21,57 +22,14 @@ this.PluginProblemWidget = class {
let parserDoc = parser.parseFromString(
`
<!DOCTYPE bindings [
<!ENTITY % pluginproblemDTD SYSTEM "chrome://pluginproblem/locale/pluginproblem.dtd">
<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
%pluginproblemDTD;
%globalDTD;
%brandDTD;
]>
<div xmlns="http://www.w3.org/1999/xhtml" class="mainBox" id="main" chromedir="&locale.dir;">
<link rel="stylesheet" type="text/css" href="chrome://pluginproblem/content/pluginProblemContent.css" />
<link rel="stylesheet" type="text/css" href="chrome://global/skin/plugins/pluginProblem.css" />
<div class="hoverBox">
<label>
<button class="icon" id="icon"/>
<div class="msg msgVulnerabilityStatus" id="vulnerabilityStatus"><!-- set at runtime --></div>
<div class="msg msgTapToPlay">&tapToPlayPlugin;</div>
<div class="msg msgClickToPlay" id="clickToPlay">&clickToActivatePlugin;</div>
</label>
<div class="msg msgBlocked">&blockedPlugin.label;</div>
<div class="msg msgCrashed">
<div class="msgCrashedText" id="crashedText"><!-- set at runtime --></div>
<!-- link href set at runtime -->
<div class="msgReload">&reloadPlugin.pre;<a class="reloadLink" id="reloadLink" href="">&reloadPlugin.middle;</a>&reloadPlugin.post;</div>
</div>
<div class="msg msgManagePlugins"><a class="action-link" id="managePluginsLink" href="">&managePlugins;</a></div>
<div class="submitStatus" id="submitStatus">
<div class="msg msgPleaseSubmit" id="pleaseSubmit">
<textarea class="submitComment"
id="submitComment"
placeholder="&report.comment;"/>
<div class="submitURLOptInBox">
<label><input class="submitURLOptIn" id="submitURLOptIn" type="checkbox"/> &report.pageURL;</label>
</div>
<div class="submitButtonBox">
<span class="helpIcon" id="helpIcon" role="link"/>
<input class="submitButton" type="button"
id="submitButton"
value="&report.please;"/>
</div>
</div>
<div class="msg msgSubmitting">&report.submitting;<span class="throbber"> </span></div>
<div class="msg msgSubmitted">&report.submitted;</div>
<div class="msg msgNotSubmitted">&report.disabled;</div>
<div class="msg msgSubmitFailed">&report.failed;</div>
<div class="msg msgNoCrashReport">&report.unavailable;</div>
</div>
<div class="msg msgCheckForUpdates"><a class="action-link" id="checkForUpdatesLink" href="">&checkForUpdates;</a></div>
</div>
<button class="closeIcon" id="closeIcon" title="&hidePluginBtn.label;"/>
</div>
`,
"application/xml"
);

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

@ -467,47 +467,15 @@ PluginWrapper.prototype = {
},
get permissions() {
let {
tags: [tag],
} = pluginFor(this);
let permissions = 0;
if (tag.isEnabledStateLocked) {
return permissions;
}
if (!this.appDisabled) {
if (this.userDisabled !== true) {
permissions |= AddonManager.PERM_CAN_DISABLE;
}
if (this.userDisabled !== AddonManager.STATE_ASK_TO_ACTIVATE) {
permissions |= AddonManager.PERM_CAN_ASK_TO_ACTIVATE;
}
let blocklistState = this.blocklistState;
let isCTPBlocklisted =
blocklistState == Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE ||
blocklistState ==
Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE;
if (
this.userDisabled !== false &&
!isCTPBlocklisted &&
!this.isFlashPlugin
) {
permissions |= AddonManager.PERM_CAN_ENABLE;
}
}
return permissions;
return 0;
},
get optionsType() {
return AddonManager.OPTIONS_TYPE_INLINE_BROWSER;
return null;
},
get optionsURL() {
return (
"chrome://mozapps/content/extensions/pluginPrefs.xhtml#id=" +
encodeURIComponent(this.id)
);
return null;
},
get updateDate() {

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

@ -14,97 +14,10 @@
height: 200px;
}
:host(:-moz-handler-clicktoplay) .mainBox,
:host(:-moz-handler-vulnerable-updatable) .mainBox,
:host(:-moz-handler-vulnerable-no-update) .mainBox,
:host(:-moz-handler-blocked) .mainBox {
-moz-user-focus: normal;
}
:host(:-moz-handler-clicktoplay) .mainBox:focus,
:host(:-moz-handler-vulnerable-updatable) .mainBox:focus,
:host(:-moz-handler-vulnerable-no-update) .mainBox:focus,
:host(:-moz-handler-blocked) .mainBox:focus {
outline: 1px dotted;
}
.mainBox {
width: inherit;
height: inherit;
overflow: hidden;
direction: ltr;
unicode-bidi: embed;
/* used to block inherited properties */
text-transform: none;
text-indent: 0;
cursor: initial;
white-space: initial;
word-spacing: initial;
letter-spacing: initial;
line-height: initial;
cursor: inherit;
visibility: hidden;
}
.visible {
visibility: visible;
}
/* Initialize the overlay with visibility:hidden to prevent flickering if
* the plugin is too small to show the overlay */
.mainBox > .hoverBox,
.mainBox > .closeIcon {
visibility: hidden;
}
.visible > .hoverBox,
.visible > .closeIcon {
visibility: visible;
}
.mainBox[chromedir="rtl"] {
direction: rtl;
}
:host(:-moz-handler-clicktoplay) .hoverBox,
:host(:-moz-handler-vulnerable-updatable) .hoverBox,
:host(:-moz-handler-vulnerable-no-update) .hoverBox {
cursor: pointer;
}
.hoverBox > label {
cursor: inherit;
}
.icon {
cursor: inherit;
}
.msg {
display: none;
}
:host(:-moz-handler-clicktoplay) .msgClickToPlay,
:host(:-moz-handler-vulnerable-updatable) .msgVulnerabilityStatus,
:host(:-moz-handler-vulnerable-updatable) .msgCheckForUpdates,
:host(:-moz-handler-vulnerable-updatable) .msgClickToPlay,
:host(:-moz-handler-vulnerable-no-update) .msgVulnerabilityStatus,
:host(:-moz-handler-vulnerable-no-update) .msgClickToPlay,
:host(:-moz-handler-blocked) .msgBlocked,
:host(:-moz-handler-crashed) .msgCrashed {
display: block;
}
.submitStatus[status] {
display: -moz-box;
-moz-box-align: center;
-moz-box-pack: center;
height: 160px;
}
.submitStatus[status="noReport"] .msgNoCrashReport,
.submitStatus[status="please"] .msgPleaseSubmit,
.submitStatus[status="noSubmit"] .msgNotSubmitted,
.submitStatus[status="submitting"] .msgSubmitting,
.submitStatus[status="success"] .msgSubmitted,
.submitStatus[status="failed"] .msgSubmitFailed {
display: block;
}