зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
e1be39b9e8
Коммит
1e71ef1cb8
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче