зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1682030 - Remove some dead NPAPI code from dom/plugins and related spots. r=jmathies,mconley,ipc-reviewers,mccr8
This is the first of two patches in this series that removes a large amount of now dead code from dom/plugins as part of removing all NPAPI plugin support. This patch removes re-entrancy guards we have for Windows OnPaint messages, as the guards were only needed for windowed plugins. Differential Revision: https://phabricator.services.mozilla.com/D107144
This commit is contained in:
Родитель
a6245e18b9
Коммит
3987158be1
|
@ -94,7 +94,6 @@
|
|||
@BINPATH@/@MOZ_CHILD_PROCESS_NAME@
|
||||
#endif
|
||||
#ifdef XP_WIN
|
||||
@BINPATH@/plugin-hang-ui@BIN_SUFFIX@
|
||||
#if MOZ_PACKAGE_MSVC_DLLS
|
||||
@BINPATH@/@MSVC_C_RUNTIME_DLL@
|
||||
@BINPATH@/@MSVC_CXX_RUNTIME_DLL@
|
||||
|
|
|
@ -23,10 +23,9 @@
|
|||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIOService.h"
|
||||
#include "nsIPermissionManager.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsJSNPRuntime.h"
|
||||
#include "nsINestedURI.h"
|
||||
#include "nsScriptSecurityManager.h"
|
||||
#include "nsIURILoader.h"
|
||||
|
@ -108,8 +107,6 @@
|
|||
# endif
|
||||
#endif // XP_WIN
|
||||
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
|
||||
static const char kPrefYoutubeRewrite[] = "plugins.rewrite_youtube_embeds";
|
||||
static const char kPrefFavorFallbackMode[] = "plugins.favorfallback.mode";
|
||||
static const char kPrefFavorFallbackRules[] = "plugins.favorfallback.rules";
|
||||
|
@ -497,26 +494,7 @@ void nsObjectLoadingContent::QueueCheckPluginStopEvent() {
|
|||
|
||||
// Tedious syntax to create a plugin stream listener with checks and put it in
|
||||
// mFinalListener
|
||||
bool nsObjectLoadingContent::MakePluginListener() {
|
||||
if (!mInstanceOwner) {
|
||||
MOZ_ASSERT_UNREACHABLE("expecting a spawned plugin");
|
||||
return false;
|
||||
}
|
||||
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
if (!pluginHost) {
|
||||
MOZ_ASSERT_UNREACHABLE("No pluginHost");
|
||||
return false;
|
||||
}
|
||||
NS_ASSERTION(!mFinalListener, "overwriting a final listener");
|
||||
nsresult rv;
|
||||
RefPtr<nsNPAPIPluginInstance> inst = mInstanceOwner->GetInstance();
|
||||
nsCOMPtr<nsIStreamListener> finalListener;
|
||||
rv = pluginHost->NewPluginStreamListener(mURI, inst,
|
||||
getter_AddRefs(finalListener));
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
mFinalListener = finalListener;
|
||||
return true;
|
||||
}
|
||||
bool nsObjectLoadingContent::MakePluginListener() { return false; }
|
||||
|
||||
// Helper to spawn the frameloader.
|
||||
void nsObjectLoadingContent::SetupFrameLoader(int32_t aJSPluginId) {
|
||||
|
@ -580,15 +558,7 @@ void nsObjectLoadingContent::UnbindFromTree(bool aNullParent) {
|
|||
Document* ownerDoc = thisElement->OwnerDoc();
|
||||
ownerDoc->RemovePlugin(this);
|
||||
|
||||
/// XXX(johns): Do we want to somehow propogate the reparenting behavior to
|
||||
/// FakePlugin types as well?
|
||||
if (mType == eType_Plugin && (mInstanceOwner || mInstantiating)) {
|
||||
// we'll let the plugin continue to run at least until we get back to
|
||||
// the event loop. If we get back to the event loop and the node
|
||||
// has still not been added back to the document then we tear down the
|
||||
// plugin
|
||||
QueueCheckPluginStopEvent();
|
||||
} else if (mType != eType_Image) {
|
||||
if (mType != eType_Image) {
|
||||
// nsImageLoadingContent handles the image case.
|
||||
// Reset state and clear pending events
|
||||
/// XXX(johns): The implementation for GenericFrame notes that ideally we
|
||||
|
@ -632,7 +602,7 @@ nsObjectLoadingContent::~nsObjectLoadingContent() {
|
|||
"Should not be tearing down frame loaders at this point");
|
||||
mFrameLoader->Destroy();
|
||||
}
|
||||
if (mInstanceOwner || mInstantiating) {
|
||||
if (mInstantiating) {
|
||||
// This is especially bad as delayed stop will try to hold on to this
|
||||
// object...
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
|
@ -643,137 +613,7 @@ nsObjectLoadingContent::~nsObjectLoadingContent() {
|
|||
}
|
||||
|
||||
nsresult nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading) {
|
||||
if (mInstanceOwner || mType != eType_Plugin || (mIsLoading != aIsLoading) ||
|
||||
mInstantiating) {
|
||||
// If we hit this assertion it's probably because LoadObject re-entered :(
|
||||
//
|
||||
// XXX(johns): This hackiness will go away in bug 767635
|
||||
NS_ASSERTION(mIsLoading || !aIsLoading,
|
||||
"aIsLoading should only be true inside LoadObject");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mInstantiating = true;
|
||||
AutoSetInstantiatingToFalse autoInstantiating(this);
|
||||
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
nsCOMPtr<Document> doc = thisContent->GetComposedDoc();
|
||||
if (!doc || !InActiveDocument(thisContent)) {
|
||||
NS_ERROR(
|
||||
"Shouldn't be calling "
|
||||
"InstantiatePluginInstance without an active document");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Instantiating an instance can result in script execution, which
|
||||
// can destroy this DOM object. Don't allow that for the scope
|
||||
// of this method.
|
||||
nsCOMPtr<nsIObjectLoadingContent> kungFuDeathGrip = this;
|
||||
|
||||
// Flush layout so that the frame is created if possible and the plugin is
|
||||
// initialized with the latest information.
|
||||
doc->FlushPendingNotifications(FlushType::Layout);
|
||||
// Flushing layout may have re-entered and loaded something underneath us
|
||||
NS_ENSURE_TRUE(mInstantiating, NS_OK);
|
||||
|
||||
if (!thisContent->GetPrimaryFrame()) {
|
||||
LOG(("OBJLC [%p]: Not instantiating plugin with no frame", this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
|
||||
if (!pluginHost) {
|
||||
MOZ_ASSERT_UNREACHABLE("No pluginhost");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// If you add early return(s), be sure to balance this call to
|
||||
// appShell->SuspendNative() with additional call(s) to
|
||||
// appShell->ReturnNative().
|
||||
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
|
||||
if (appShell) {
|
||||
appShell->SuspendNative();
|
||||
}
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> newOwner;
|
||||
nsresult rv = pluginHost->InstantiatePluginInstance(
|
||||
mContentType, mURI.get(), this, getter_AddRefs(newOwner));
|
||||
|
||||
// XXX(johns): We don't suspend native inside stopping plugins...
|
||||
if (appShell) {
|
||||
appShell->ResumeNative();
|
||||
}
|
||||
|
||||
if (!mInstantiating || NS_FAILED(rv)) {
|
||||
LOG(
|
||||
("OBJLC [%p]: Plugin instantiation failed or re-entered, "
|
||||
"killing old instance",
|
||||
this));
|
||||
// XXX(johns): This needs to be de-duplicated with DoStopPlugin, but we
|
||||
// don't want to touch the protochain or delayed stop.
|
||||
// (Bug 767635)
|
||||
if (newOwner) {
|
||||
RefPtr<nsNPAPIPluginInstance> inst = newOwner->GetInstance();
|
||||
if (inst) {
|
||||
pluginHost->StopPluginInstance(inst);
|
||||
}
|
||||
newOwner->Destroy();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mInstanceOwner = newOwner;
|
||||
|
||||
if (mInstanceOwner) {
|
||||
RefPtr<nsNPAPIPluginInstance> inst = mInstanceOwner->GetInstance();
|
||||
|
||||
rv = inst->GetRunID(&mRunID);
|
||||
mHasRunID = NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
// Set up scripting interfaces.
|
||||
NotifyContentObjectWrapper();
|
||||
|
||||
RefPtr<nsNPAPIPluginInstance> pluginInstance = GetPluginInstance();
|
||||
if (pluginInstance) {
|
||||
nsCOMPtr<nsIPluginTag> pluginTag;
|
||||
pluginHost->GetPluginTagForInstance(pluginInstance,
|
||||
getter_AddRefs(pluginTag));
|
||||
|
||||
uint32_t blockState = nsIBlocklistService::STATE_NOT_BLOCKED;
|
||||
pluginTag->GetBlocklistState(&blockState);
|
||||
if (blockState == nsIBlocklistService::STATE_OUTDATED) {
|
||||
// Fire plugin outdated event if necessary
|
||||
LOG(("OBJLC [%p]: Dispatching plugin outdated event for content\n",
|
||||
this));
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsSimplePluginEvent(thisContent, u"PluginOutdated"_ns);
|
||||
nsresult rv = NS_DispatchToCurrentThread(ev);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("failed to dispatch nsSimplePluginEvent");
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a URI but didn't open a channel yet (eAllowPluginSkipChannel)
|
||||
// or we did load with a channel but are re-instantiating, re-open the
|
||||
// channel. OpenChannel() performs security checks, and this plugin has
|
||||
// already passed content policy in LoadObject.
|
||||
if ((mURI && !mChannelLoaded) || (mChannelLoaded && !aIsLoading)) {
|
||||
NS_ASSERTION(!mChannel, "should not have an existing channel here");
|
||||
// We intentionally ignore errors here, leaving it up to the plugin to
|
||||
// deal with not having an initial stream.
|
||||
OpenChannel();
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> ev =
|
||||
new nsSimplePluginEvent(thisContent, doc, u"PluginInstantiated"_ns);
|
||||
NS_DispatchToCurrentThread(ev);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsObjectLoadingContent::GetPluginAttributes(
|
||||
|
@ -898,7 +738,7 @@ void nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged() {
|
|||
|
||||
// If we have a plugin we want to queue an event to stop it unless we are
|
||||
// moved into an active document before returning to the event loop.
|
||||
if (mInstanceOwner || mInstantiating) {
|
||||
if (mInstantiating) {
|
||||
QueueCheckPluginStopEvent();
|
||||
}
|
||||
nsImageLoadingContent::NotifyOwnerDocumentActivityChanged();
|
||||
|
@ -916,25 +756,6 @@ nsObjectLoadingContent::OnStartRequest(nsIRequest* aRequest) {
|
|||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
// If we already switched to type plugin, this channel can just be passed to
|
||||
// the final listener.
|
||||
if (mType == eType_Plugin) {
|
||||
if (!mInstanceOwner) {
|
||||
// We drop mChannel when stopping plugins, so something is wrong
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Opened a channel in plugin mode, but don't have "
|
||||
"a plugin");
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
if (MakePluginListener()) {
|
||||
return mFinalListener->OnStartRequest(aRequest);
|
||||
}
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Failed to create PluginStreamListener, aborting "
|
||||
"channel");
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
|
||||
NS_ASSERTION(chan, "Why is our request not a channel?");
|
||||
|
||||
|
@ -1097,11 +918,7 @@ nsObjectLoadingContent::GetDisplayedType(uint32_t* aType) {
|
|||
}
|
||||
|
||||
nsNPAPIPluginInstance* nsObjectLoadingContent::GetPluginInstance() {
|
||||
if (!mInstanceOwner) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return mInstanceOwner->GetInstance();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -2023,7 +1840,7 @@ nsresult nsObjectLoadingContent::LoadObject(bool aNotify, bool aForceLoad,
|
|||
|
||||
// Sanity check: We shouldn't have any loaded resources, pending events, or
|
||||
// a final listener at this point
|
||||
if (mFrameLoader || mPendingInstantiateEvent || mInstanceOwner ||
|
||||
if (mFrameLoader || mPendingInstantiateEvent ||
|
||||
mPendingCheckPluginStopEvent || mFinalListener) {
|
||||
MOZ_ASSERT_UNREACHABLE("Trying to load new plugin with existing content");
|
||||
return NS_OK;
|
||||
|
@ -2157,7 +1974,7 @@ nsresult nsObjectLoadingContent::LoadObject(bool aNotify, bool aForceLoad,
|
|||
// If we didn't load anything, handle switching to fallback state
|
||||
if (mType == eType_Null) {
|
||||
LOG(("OBJLC [%p]: Loading fallback, type %u", this, fallbackType));
|
||||
NS_ASSERTION(!mFrameLoader && !mInstanceOwner,
|
||||
NS_ASSERTION(!mFrameLoader,
|
||||
"switched to type null but also loaded something");
|
||||
|
||||
// Don't fire error events if we're falling back to click-to-play or if we
|
||||
|
@ -2426,7 +2243,7 @@ void nsObjectLoadingContent::Destroy() {
|
|||
mFrameLoader = nullptr;
|
||||
}
|
||||
|
||||
if (mInstanceOwner || mInstantiating) {
|
||||
if (mInstantiating) {
|
||||
QueueCheckPluginStopEvent();
|
||||
}
|
||||
|
||||
|
@ -2479,13 +2296,7 @@ void nsObjectLoadingContent::UnloadObject(bool aResetState) {
|
|||
|
||||
mScriptRequested = false;
|
||||
|
||||
if (mIsStopping) {
|
||||
// The protochain is normally thrown out after a plugin stops, but if we
|
||||
// re-enter while stopping a plugin and try to load something new, we need
|
||||
// to throw away the old protochain in the nested unload.
|
||||
TeardownProtoChain();
|
||||
mIsStopping = false;
|
||||
}
|
||||
|
||||
mCachedAttributes.Clear();
|
||||
mCachedParameters.Clear();
|
||||
|
@ -2595,17 +2406,7 @@ void nsObjectLoadingContent::CreateStaticClone(
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::PluginDestroyed() {
|
||||
// Called when our plugin is destroyed from under us, usually when reloading
|
||||
// plugins in plugin host. Invalidate instance owner / prototype but otherwise
|
||||
// don't take any action.
|
||||
TeardownProtoChain();
|
||||
if (mInstanceOwner) {
|
||||
mInstanceOwner->Destroy();
|
||||
mInstanceOwner = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
nsObjectLoadingContent::PluginDestroyed() { return NS_OK; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
|
||||
|
@ -2674,7 +2475,7 @@ nsNPAPIPluginInstance* nsObjectLoadingContent::ScriptRequestPluginInstance(
|
|||
MOZ_ASSERT_UNREACHABLE("failed to dispatch PluginScripted event");
|
||||
}
|
||||
mScriptRequested = true;
|
||||
} else if (callerIsContentJS && mType == eType_Plugin && !mInstanceOwner &&
|
||||
} else if (callerIsContentJS && mType == eType_Plugin &&
|
||||
nsContentUtils::IsSafeToRunScript() &&
|
||||
InActiveDocument(thisContent)) {
|
||||
// If we're configured as a plugin in an active document and it's safe to
|
||||
|
@ -2682,10 +2483,6 @@ nsNPAPIPluginInstance* nsObjectLoadingContent::ScriptRequestPluginInstance(
|
|||
SyncStartPluginInstance();
|
||||
}
|
||||
|
||||
if (mInstanceOwner) {
|
||||
return mInstanceOwner->GetInstance();
|
||||
}
|
||||
|
||||
// Note that returning a null plugin is expected (and happens often)
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -2713,8 +2510,7 @@ nsObjectLoadingContent::SyncStartPluginInstance() {
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::AsyncStartPluginInstance() {
|
||||
// OK to have an instance already or a pending spawn.
|
||||
if (mInstanceOwner || mPendingInstantiateEvent) {
|
||||
if (mPendingInstantiateEvent) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2746,7 +2542,7 @@ void nsObjectLoadingContent::LoadFallback(FallbackType aType, bool aNotify) {
|
|||
ObjectType oldType = mType;
|
||||
FallbackType oldFallbackType = mFallbackType;
|
||||
|
||||
NS_ASSERTION(!mInstanceOwner && !mFrameLoader && !mChannel,
|
||||
NS_ASSERTION(!mFrameLoader && !mChannel,
|
||||
"LoadFallback called with loaded content");
|
||||
|
||||
//
|
||||
|
@ -2813,49 +2609,6 @@ void nsObjectLoadingContent::LoadFallback(FallbackType aType, bool aNotify) {
|
|||
NotifyStateChanged(oldType, oldState, oldFallbackType, false, true);
|
||||
}
|
||||
|
||||
void nsObjectLoadingContent::DoStopPlugin(
|
||||
nsPluginInstanceOwner* aInstanceOwner) {
|
||||
// DoStopPlugin can process events -- There may be pending
|
||||
// CheckPluginStopEvent events which can drop in underneath us and destroy the
|
||||
// instance we are about to destroy. We prevent that with the mIsStopping
|
||||
// flag.
|
||||
if (mIsStopping) {
|
||||
return;
|
||||
}
|
||||
mIsStopping = true;
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> kungFuDeathGrip(aInstanceOwner);
|
||||
if (mType == eType_FakePlugin) {
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
} else {
|
||||
RefPtr<nsNPAPIPluginInstance> inst = aInstanceOwner->GetInstance();
|
||||
if (inst) {
|
||||
#if defined(XP_MACOSX)
|
||||
aInstanceOwner->HidePluginWindow();
|
||||
#endif
|
||||
|
||||
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
NS_ASSERTION(pluginHost, "No plugin host?");
|
||||
pluginHost->StopPluginInstance(inst);
|
||||
}
|
||||
}
|
||||
|
||||
aInstanceOwner->Destroy();
|
||||
|
||||
// If we re-enter in plugin teardown UnloadObject will tear down the
|
||||
// protochain -- the current protochain could be from a new, unrelated, load.
|
||||
if (!mIsStopping) {
|
||||
LOG(("OBJLC [%p]: Re-entered in plugin teardown", this));
|
||||
return;
|
||||
}
|
||||
|
||||
TeardownProtoChain();
|
||||
mIsStopping = false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsObjectLoadingContent::StopPluginInstance() {
|
||||
AUTO_PROFILER_LABEL("nsObjectLoadingContent::StopPluginInstance", OTHER);
|
||||
|
@ -2867,26 +2620,6 @@ nsObjectLoadingContent::StopPluginInstance() {
|
|||
// InstantiatePluginInstance's re-entrance check to destroy the created plugin
|
||||
mInstantiating = false;
|
||||
|
||||
if (!mInstanceOwner) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mChannel) {
|
||||
// The plugin has already used data from this channel, we'll need to
|
||||
// re-open it to handle instantiating again, even if we don't invalidate
|
||||
// our loaded state.
|
||||
/// XXX(johns): Except currently, we don't, just leaving re-opening channels
|
||||
/// to plugins...
|
||||
LOG(("OBJLC [%p]: StopPluginInstance - Closing used channel", this));
|
||||
CloseChannel();
|
||||
}
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> ownerGrip(mInstanceOwner);
|
||||
mInstanceOwner = nullptr;
|
||||
|
||||
// This can/will re-enter
|
||||
DoStopPlugin(ownerGrip);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3318,52 +3051,6 @@ nsresult nsObjectLoadingContent::GetPluginJSObject(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsObjectLoadingContent::TeardownProtoChain() {
|
||||
nsCOMPtr<nsIContent> thisContent =
|
||||
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
|
||||
|
||||
NS_ENSURE_TRUE_VOID(thisContent->GetWrapper());
|
||||
|
||||
// We don't init the AutoJSAPI with our wrapper because we don't want it
|
||||
// reporting errors to our window's onerror listeners.
|
||||
AutoJSAPI jsapi;
|
||||
jsapi.Init();
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JSObject*> obj(cx, thisContent->GetWrapper());
|
||||
MOZ_ASSERT(obj);
|
||||
|
||||
JS::Rooted<JSObject*> proto(cx);
|
||||
JSAutoRealm ar(cx, obj);
|
||||
|
||||
// Loop over the DOM element's JS object prototype chain and remove
|
||||
// all JS objects of the class sNPObjectJSWrapperClass
|
||||
DebugOnly<bool> removed = false;
|
||||
while (obj) {
|
||||
if (!::JS_GetPrototype(cx, obj, &proto)) {
|
||||
return;
|
||||
}
|
||||
if (!proto) {
|
||||
break;
|
||||
}
|
||||
// Unwrap while checking the class - if the prototype is a wrapper for
|
||||
// an NP object, that counts too.
|
||||
if (nsNPObjWrapper::IsWrapper(js::UncheckedUnwrap(proto))) {
|
||||
// We found an NPObject on the proto chain, get its prototype...
|
||||
if (!::JS_GetPrototype(cx, proto, &proto)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!removed, "more than one NPObject in prototype chain");
|
||||
removed = true;
|
||||
|
||||
// ... and pull it out of the chain.
|
||||
::JS_SetPrototype(cx, obj, proto);
|
||||
}
|
||||
|
||||
obj = proto;
|
||||
}
|
||||
}
|
||||
|
||||
bool nsObjectLoadingContent::DoResolve(
|
||||
JSContext* aCx, JS::Handle<JSObject*> aObject, JS::Handle<jsid> aId,
|
||||
JS::MutableHandle<JS::PropertyDescriptor> aDesc) {
|
||||
|
|
|
@ -29,7 +29,6 @@ class nsStopPluginRunnable;
|
|||
class AutoSetInstantiatingToFalse;
|
||||
class nsIPrincipal;
|
||||
class nsFrameLoader;
|
||||
class nsPluginInstanceOwner;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -174,9 +173,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
|
|||
// Helper for WebIDL node wrapping
|
||||
void SetupProtoChain(JSContext* aCx, JS::Handle<JSObject*> aObject);
|
||||
|
||||
// Remove plugin from protochain
|
||||
void TeardownProtoChain();
|
||||
|
||||
// Helper for WebIDL NeedResolve
|
||||
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
|
||||
JS::Handle<jsid> aId,
|
||||
|
@ -214,7 +210,7 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
|
|||
uint32_t DefaultFallbackType();
|
||||
|
||||
uint32_t PluginFallbackType() const { return mFallbackType; }
|
||||
bool HasRunningPlugin() const { return !!mInstanceOwner; }
|
||||
|
||||
// FIXME rename this
|
||||
void SkipFakePlugins(mozilla::ErrorResult& aRv) { aRv = SkipFakePlugins(); }
|
||||
void SwapFrameLoaders(mozilla::dom::HTMLIFrameElement& aOtherLoaderOwner,
|
||||
|
@ -328,8 +324,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
|
|||
|
||||
void CreateStaticClone(nsObjectLoadingContent* aDest) const;
|
||||
|
||||
void DoStopPlugin(nsPluginInstanceOwner* aInstanceOwner);
|
||||
|
||||
nsresult BindToTree(mozilla::dom::BindContext&, nsINode& aParent);
|
||||
void UnbindFromTree(bool aNullParent = true);
|
||||
|
||||
|
@ -700,7 +694,6 @@ class nsObjectLoadingContent : public nsImageLoadingContent,
|
|||
bool mPreferFallback : 1;
|
||||
bool mPreferFallbackKnown : 1;
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> mInstanceOwner;
|
||||
nsTArray<mozilla::dom::MozPluginParameter> mCachedAttributes;
|
||||
nsTArray<mozilla::dom::MozPluginParameter> mCachedParameters;
|
||||
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
# define Comment _Comment
|
||||
#endif
|
||||
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
# undef TextRange
|
||||
# undef TextRangeArray
|
||||
|
@ -149,8 +147,6 @@ void TextComposition::DispatchEvent(
|
|||
WidgetCompositionEvent* aDispatchEvent, nsEventStatus* aStatus,
|
||||
EventDispatchingCallback* aCallBack,
|
||||
const WidgetCompositionEvent* aOriginalEvent) {
|
||||
nsPluginInstanceOwner::GeneratePluginEvent(aOriginalEvent, aDispatchEvent);
|
||||
|
||||
if (aDispatchEvent->mMessage == eCompositionChange) {
|
||||
aDispatchEvent->mFlags.mOnlySystemGroupDispatchInContent = true;
|
||||
}
|
||||
|
|
|
@ -108,8 +108,6 @@
|
|||
#include "mozilla/net/DocumentChannelChild.h"
|
||||
#include "mozilla/net/HttpChannelChild.h"
|
||||
#include "mozilla/net/NeckoChild.h"
|
||||
#include "mozilla/plugins/PluginInstanceParent.h"
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
#include "mozilla/widget/RemoteLookAndFeel.h"
|
||||
#include "mozilla/widget/ScreenManager.h"
|
||||
#include "mozilla/widget/WidgetMessageUtils.h"
|
||||
|
@ -144,6 +142,7 @@
|
|||
# include "mozilla/SandboxInfo.h"
|
||||
# elif defined(XP_MACOSX)
|
||||
# include "mozilla/Sandbox.h"
|
||||
# include "mozilla/gfx/QuartzSupport.h"
|
||||
# elif defined(__OpenBSD__)
|
||||
# include <err.h>
|
||||
# include <sys/stat.h>
|
||||
|
@ -2920,26 +2919,10 @@ void ContentChild::ShutdownInternal() {
|
|||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvUpdateWindow(
|
||||
const uintptr_t& aChildId) {
|
||||
#if defined(XP_WIN)
|
||||
NS_ASSERTION(aChildId,
|
||||
"Expected child hwnd value for remote plugin instance.");
|
||||
mozilla::plugins::PluginInstanceParent* parentInstance =
|
||||
mozilla::plugins::PluginInstanceParent::LookupPluginInstanceByID(
|
||||
aChildId);
|
||||
if (parentInstance) {
|
||||
// sync! update call to the plugin instance that forces the
|
||||
// plugin to paint its child window.
|
||||
if (!parentInstance->CallUpdateWindow()) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
#else
|
||||
MOZ_ASSERT(
|
||||
false,
|
||||
"ContentChild::RecvUpdateWindow calls unexpected on this platform.");
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
PContentPermissionRequestChild*
|
||||
|
@ -3305,14 +3288,6 @@ mozilla::ipc::IPCResult ContentChild::RecvRefreshScreens(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvSetPluginList(
|
||||
const uint32_t& aPluginEpoch, nsTArray<plugins::PluginTag>&& aPluginTags,
|
||||
nsTArray<plugins::FakePluginTag>&& aFakePluginTags) {
|
||||
RefPtr<nsPluginHost> host = nsPluginHost::GetInst();
|
||||
host->SetPluginsInContent(aPluginEpoch, aPluginTags, aFakePluginTags);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvShareCodeCoverageMutex(
|
||||
const CrossProcessMutexHandle& aHandle) {
|
||||
#ifdef MOZ_CODE_COVERAGE
|
||||
|
|
|
@ -610,10 +610,6 @@ class ContentChild final : public PContentChild,
|
|||
nsresult AsyncOpenAnonymousTemporaryFile(
|
||||
const AnonymousTemporaryFileCallback& aCallback);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetPluginList(
|
||||
const uint32_t& aPluginEpoch, nsTArray<PluginTag>&& aPluginTags,
|
||||
nsTArray<FakePluginTag>&& aFakePluginTags);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSaveRecording(const FileDescriptor& aFile);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCrossProcessRedirect(
|
||||
|
|
|
@ -155,7 +155,6 @@
|
|||
#include "mozilla/net/NeckoMessageUtils.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
#include "mozilla/net/PCookieServiceParent.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/TelemetryComms.h"
|
||||
#include "mozilla/TelemetryEventEnums.h"
|
||||
|
@ -1265,16 +1264,6 @@ mozilla::ipc::IPCResult ContentParent::RecvCreateGMPService() {
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvLoadPlugin(
|
||||
const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID,
|
||||
Endpoint<PPluginModuleParent>* aEndpoint) {
|
||||
*aRv = NS_OK;
|
||||
if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, aRunID, aEndpoint)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvUngrabPointer(
|
||||
const uint32_t& aTime) {
|
||||
#if !defined(MOZ_WIDGET_GTK)
|
||||
|
@ -1444,20 +1433,6 @@ mozilla::ipc::IPCResult ContentParent::RecvRemovePermission(
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvConnectPluginBridge(
|
||||
const uint32_t& aPluginId, nsresult* aRv,
|
||||
Endpoint<PPluginModuleParent>* aEndpoint) {
|
||||
*aRv = NS_OK;
|
||||
// We don't need to get the run ID for the plugin, since we already got it
|
||||
// in the first call to SetupBridge in RecvLoadPlugin, so we pass in a dummy
|
||||
// pointer and just throw it away.
|
||||
uint32_t dummy = 0;
|
||||
if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, &dummy, aEndpoint)) {
|
||||
return IPC_FAIL(this, "SetupBridge failed");
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
/*static*/
|
||||
already_AddRefed<RemoteBrowser> ContentParent::CreateBrowser(
|
||||
const TabContext& aContext, Element* aFrameElement,
|
||||
|
|
|
@ -337,16 +337,8 @@ class ContentParent final
|
|||
|
||||
mozilla::ipc::IPCResult RecvCreateGMPService();
|
||||
|
||||
mozilla::ipc::IPCResult RecvLoadPlugin(
|
||||
const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID,
|
||||
Endpoint<PPluginModuleParent>* aEndpoint);
|
||||
|
||||
mozilla::ipc::IPCResult RecvMaybeReloadPlugins();
|
||||
|
||||
mozilla::ipc::IPCResult RecvConnectPluginBridge(
|
||||
const uint32_t& aPluginId, nsresult* aRv,
|
||||
Endpoint<PPluginModuleParent>* aEndpoint);
|
||||
|
||||
mozilla::ipc::IPCResult RecvUngrabPointer(const uint32_t& aTime);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRemovePermission(const IPC::Principal& aPrincipal,
|
||||
|
|
|
@ -25,7 +25,6 @@ include protocol PNecko;
|
|||
include protocol PStreamFilter;
|
||||
include protocol PGMPContent;
|
||||
include protocol PGMPService;
|
||||
include protocol PPluginModule;
|
||||
include protocol PGMP;
|
||||
include protocol PPrinting;
|
||||
include protocol PChildToParentStream;
|
||||
|
@ -52,7 +51,6 @@ include WindowGlobalTypes;
|
|||
include IPCBlob;
|
||||
include IPCStream;
|
||||
include PTabContext;
|
||||
include PluginTypes;
|
||||
include ProtocolTypes;
|
||||
include PBackgroundSharedTypes;
|
||||
include PContentPermission;
|
||||
|
@ -781,18 +779,6 @@ child:
|
|||
|
||||
async PRemoteLazyInputStream(nsID aID, uint64_t aSize);
|
||||
|
||||
/**
|
||||
* This call takes the set of plugins loaded in the chrome process, and
|
||||
* sends them to the content process. However, in many cases this set will
|
||||
* not have changed since the last SetPluginList message. To keep track of
|
||||
* this, the chrome process increments an epoch number every time the set of
|
||||
* plugins changes. The chrome process sends up the last epoch it observed.
|
||||
* If the epoch last seen by the content process is the same, the content
|
||||
* process ignores the update. Otherwise the content process updates its
|
||||
* list and reloads its plugins.
|
||||
**/
|
||||
async SetPluginList(uint32_t pluginEpoch, PluginTag[] plugins, FakePluginTag[] fakePlugins);
|
||||
|
||||
async ShareCodeCoverageMutex(CrossProcessMutexHandle handle);
|
||||
async FlushCodeCoverageCounters() returns (bool unused);
|
||||
|
||||
|
@ -977,23 +963,6 @@ parent:
|
|||
async InitStreamFilter(uint64_t channelId, nsString addonId)
|
||||
returns (Endpoint<PStreamFilterChild> aEndpoint);
|
||||
|
||||
/**
|
||||
* This call connects the content process to a plugin process. This call
|
||||
* returns an endpoint for a new PluginModuleParent. The corresponding
|
||||
* PluginModuleChild will be started up in the plugin process.
|
||||
*/
|
||||
sync LoadPlugin(uint32_t aPluginId)
|
||||
returns (nsresult aResult, uint32_t aRunID, Endpoint<PPluginModuleParent> aEndpoint);
|
||||
|
||||
/**
|
||||
* This call is used by asynchronous plugin instantiation to notify the
|
||||
* content parent that it is now safe to initiate the plugin bridge for
|
||||
* the specified plugin id. The endpoint for the content process part of the
|
||||
* bridge is returned.
|
||||
*/
|
||||
sync ConnectPluginBridge(uint32_t aPluginId)
|
||||
returns (nsresult rv, Endpoint<PPluginModuleParent> aEndpoint);
|
||||
|
||||
async PRemoteSpellcheckEngine();
|
||||
|
||||
async InitCrashReporter(NativeThreadId tid);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "mozilla/ipc/Endpoint.h"
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs_browser.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
|
@ -824,18 +823,10 @@ void HangMonitorParent::SendHangNotification(const HangData& aHangData,
|
|||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsString dumpId;
|
||||
if ((aHangData.type() == HangData::TPluginHangData) && aTakeMinidump) {
|
||||
// We've been handed a partial minidump; complete it with plugin and
|
||||
// content process dumps.
|
||||
const PluginHangData& phd = aHangData.get_PluginHangData();
|
||||
MOZ_ASSERT(aHangData.type() != HangData::TPluginHangData);
|
||||
|
||||
plugins::TakeFullMinidump(phd.pluginId(), phd.contentProcessId(),
|
||||
aBrowserDumpId, dumpId);
|
||||
UpdateMinidump(phd.pluginId(), dumpId);
|
||||
} else {
|
||||
// We already have a full minidump; go ahead and use it.
|
||||
dumpId = aBrowserDumpId;
|
||||
}
|
||||
|
||||
mProcess->SetHangData(aHangData, dumpId);
|
||||
|
||||
|
@ -1140,23 +1131,7 @@ HangMonitoredProcess::EndStartingDebugger() {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HangMonitoredProcess::TerminatePlugin() {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
if (mHangData.type() != HangData::TPluginHangData) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Use the multi-process crash report generated earlier.
|
||||
uint32_t id = mHangData.get_PluginHangData().pluginId();
|
||||
base::ProcessId contentPid =
|
||||
mHangData.get_PluginHangData().contentProcessId();
|
||||
plugins::TerminatePlugin(id, contentPid, "HangMonitor"_ns, mDumpId);
|
||||
|
||||
if (mActor) {
|
||||
mActor->CleanupPluginHang(id, false);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
HangMonitoredProcess::TerminatePlugin() { return NS_ERROR_UNEXPECTED; }
|
||||
|
||||
NS_IMETHODIMP
|
||||
HangMonitoredProcess::IsReportForBrowserOrChildren(nsFrameLoader* aFrameLoader,
|
||||
|
|
|
@ -72,7 +72,6 @@ DIRS += [
|
|||
"network",
|
||||
"permission",
|
||||
"plugins/base",
|
||||
"plugins/ipc",
|
||||
"prototype",
|
||||
"indexedDB",
|
||||
"system",
|
||||
|
@ -110,9 +109,6 @@ DIRS += [
|
|||
"l10n",
|
||||
]
|
||||
|
||||
if CONFIG["OS_ARCH"] == "WINNT":
|
||||
DIRS += ["plugins/ipc/hangui"]
|
||||
|
||||
TEST_DIRS += [
|
||||
"tests",
|
||||
"imptests",
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
"nsIHTTPHeaderListener.idl",
|
||||
"nsIPluginDocument.idl",
|
||||
"nsIPluginHost.idl",
|
||||
"nsIPluginInputStream.idl",
|
||||
"nsIPluginInstanceOwner.idl",
|
||||
"nsIPluginTag.idl",
|
||||
"nspluginroot.idl",
|
||||
]
|
||||
|
@ -18,59 +15,28 @@ XPIDL_MODULE = "plugin"
|
|||
|
||||
EXPORTS += [
|
||||
"npapi.h",
|
||||
"npfunctions.h",
|
||||
"npruntime.h",
|
||||
"nptypes.h",
|
||||
"nsJSNPRuntime.h",
|
||||
"nsNPAPIPluginInstance.h",
|
||||
"nsPluginHost.h",
|
||||
"nsPluginInstanceOwner.h",
|
||||
"nsPluginLogging.h",
|
||||
"nsPluginNativeWindow.h",
|
||||
"nsPluginsCID.h",
|
||||
"nsPluginsDir.h",
|
||||
"nsPluginTags.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"nsJSNPRuntime.cpp",
|
||||
"nsNPAPIPluginInstance.cpp",
|
||||
"nsNPAPIPluginStreamListener.cpp",
|
||||
"nsPluginInstanceOwner.cpp",
|
||||
"nsPluginStreamListenerPeer.cpp",
|
||||
"nsPluginTags.cpp",
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
"nsNPAPIPlugin.cpp", # Conflict with X11 headers
|
||||
"nsPluginHost.cpp", # Conflict with NS_NPAPIPLUGIN_CALLBACK
|
||||
]
|
||||
|
||||
if CONFIG["OS_ARCH"] == "WINNT":
|
||||
UNIFIED_SOURCES += [
|
||||
"nsPluginNativeWindowWin.cpp",
|
||||
"nsPluginsDirWin.cpp",
|
||||
]
|
||||
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
|
||||
UNIFIED_SOURCES += [
|
||||
"nsPluginNativeWindow.cpp",
|
||||
]
|
||||
SOURCES += [
|
||||
"nsPluginsDirDarwin.cpp", # conflict with mozilla::EventPriority
|
||||
]
|
||||
else:
|
||||
UNIFIED_SOURCES += [
|
||||
"nsPluginNativeWindow.cpp",
|
||||
"nsPluginsDirUnix.cpp",
|
||||
]
|
||||
|
||||
XPCOM_MANIFESTS += [
|
||||
"components.conf",
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
"/dom/base",
|
||||
"/dom/plugins/ipc",
|
||||
"/layout/generic",
|
||||
"/layout/xul",
|
||||
"/netwerk/base",
|
||||
|
|
|
@ -1,356 +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 npfunctions_h_
|
||||
#define npfunctions_h_
|
||||
|
||||
#include "npapi.h"
|
||||
#include "npruntime.h"
|
||||
|
||||
typedef NPError (*NPP_NewProcPtr)(NPMIMEType pluginType, NPP instance,
|
||||
uint16_t mode, int16_t argc, char* argn[],
|
||||
char* argv[], NPSavedData* saved);
|
||||
typedef NPError (*NPP_DestroyProcPtr)(NPP instance, NPSavedData** save);
|
||||
typedef NPError (*NPP_SetWindowProcPtr)(NPP instance, NPWindow* window);
|
||||
typedef NPError (*NPP_NewStreamProcPtr)(NPP instance, NPMIMEType type,
|
||||
NPStream* stream, NPBool seekable,
|
||||
uint16_t* stype);
|
||||
typedef NPError (*NPP_DestroyStreamProcPtr)(NPP instance, NPStream* stream,
|
||||
NPReason reason);
|
||||
typedef int32_t (*NPP_WriteReadyProcPtr)(NPP instance, NPStream* stream);
|
||||
typedef int32_t (*NPP_WriteProcPtr)(NPP instance, NPStream* stream,
|
||||
int32_t offset, int32_t len, void* buffer);
|
||||
typedef void (*NPP_StreamAsFileProcPtr)(NPP instance, NPStream* stream,
|
||||
const char* fname);
|
||||
typedef void (*NPP_PrintProcPtr)(NPP instance, NPPrint* platformPrint);
|
||||
typedef int16_t (*NPP_HandleEventProcPtr)(NPP instance, void* event);
|
||||
typedef void (*NPP_URLNotifyProcPtr)(NPP instance, const char* url,
|
||||
NPReason reason, void* notifyData);
|
||||
/* Any NPObjects returned to the browser via NPP_GetValue should be retained
|
||||
by the plugin on the way out. The browser is responsible for releasing. */
|
||||
typedef NPError (*NPP_GetValueProcPtr)(NPP instance, NPPVariable variable,
|
||||
void* ret_value);
|
||||
typedef NPError (*NPP_SetValueProcPtr)(NPP instance, NPNVariable variable,
|
||||
void* value);
|
||||
typedef NPBool (*NPP_GotFocusPtr)(NPP instance, NPFocusDirection direction);
|
||||
typedef void (*NPP_LostFocusPtr)(NPP instance);
|
||||
typedef void (*NPP_URLRedirectNotifyPtr)(NPP instance, const char* url,
|
||||
int32_t status, void* notifyData);
|
||||
typedef NPError (*NPP_ClearSiteDataPtr)(const char* site, uint64_t flags,
|
||||
uint64_t maxAge);
|
||||
typedef char** (*NPP_GetSitesWithDataPtr)(void);
|
||||
typedef void (*NPP_DidCompositePtr)(NPP instance);
|
||||
|
||||
typedef NPError (*NPN_GetValueProcPtr)(NPP instance, NPNVariable variable,
|
||||
void* ret_value);
|
||||
typedef NPError (*NPN_SetValueProcPtr)(NPP instance, NPPVariable variable,
|
||||
void* value);
|
||||
typedef NPError (*NPN_GetURLNotifyProcPtr)(NPP instance, const char* url,
|
||||
const char* window,
|
||||
void* notifyData);
|
||||
typedef NPError (*NPN_PostURLNotifyProcPtr)(NPP instance, const char* url,
|
||||
const char* window, uint32_t len,
|
||||
const char* buf, NPBool file,
|
||||
void* notifyData);
|
||||
typedef NPError (*NPN_GetURLProcPtr)(NPP instance, const char* url,
|
||||
const char* window);
|
||||
typedef NPError (*NPN_PostURLProcPtr)(NPP instance, const char* url,
|
||||
const char* window, uint32_t len,
|
||||
const char* buf, NPBool file);
|
||||
typedef NPError (*NPN_RequestReadProcPtr)(NPStream* stream,
|
||||
NPByteRange* rangeList);
|
||||
typedef NPError (*NPN_NewStreamProcPtr)(NPP instance, NPMIMEType type,
|
||||
const char* window, NPStream** stream);
|
||||
typedef int32_t (*NPN_WriteProcPtr)(NPP instance, NPStream* stream, int32_t len,
|
||||
void* buffer);
|
||||
typedef NPError (*NPN_DestroyStreamProcPtr)(NPP instance, NPStream* stream,
|
||||
NPReason reason);
|
||||
typedef void (*NPN_StatusProcPtr)(NPP instance, const char* message);
|
||||
/* Browser manages the lifetime of the buffer returned by NPN_UserAgent, don't
|
||||
depend on it sticking around and don't free it. */
|
||||
typedef const char* (*NPN_UserAgentProcPtr)(NPP instance);
|
||||
typedef void* (*NPN_MemAllocProcPtr)(uint32_t size);
|
||||
typedef void (*NPN_MemFreeProcPtr)(void* ptr);
|
||||
typedef uint32_t (*NPN_MemFlushProcPtr)(uint32_t size);
|
||||
typedef void (*NPN_ReloadPluginsProcPtr)(NPBool reloadPages);
|
||||
typedef void* (*NPN_GetJavaEnvProcPtr)(void);
|
||||
typedef void* (*NPN_GetJavaPeerProcPtr)(NPP instance);
|
||||
typedef void (*NPN_InvalidateRectProcPtr)(NPP instance, NPRect* rect);
|
||||
typedef void (*NPN_InvalidateRegionProcPtr)(NPP instance, NPRegion region);
|
||||
typedef void (*NPN_ForceRedrawProcPtr)(NPP instance);
|
||||
typedef NPIdentifier (*NPN_GetStringIdentifierProcPtr)(const NPUTF8* name);
|
||||
typedef void (*NPN_GetStringIdentifiersProcPtr)(const NPUTF8** names,
|
||||
int32_t nameCount,
|
||||
NPIdentifier* identifiers);
|
||||
typedef NPIdentifier (*NPN_GetIntIdentifierProcPtr)(int32_t intid);
|
||||
typedef bool (*NPN_IdentifierIsStringProcPtr)(NPIdentifier identifier);
|
||||
typedef NPUTF8* (*NPN_UTF8FromIdentifierProcPtr)(NPIdentifier identifier);
|
||||
typedef int32_t (*NPN_IntFromIdentifierProcPtr)(NPIdentifier identifier);
|
||||
typedef NPObject* (*NPN_CreateObjectProcPtr)(NPP npp, NPClass* aClass);
|
||||
typedef NPObject* (*NPN_RetainObjectProcPtr)(NPObject* obj);
|
||||
typedef void (*NPN_ReleaseObjectProcPtr)(NPObject* obj);
|
||||
typedef bool (*NPN_InvokeProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier methodName,
|
||||
const NPVariant* args, uint32_t argCount,
|
||||
NPVariant* result);
|
||||
typedef bool (*NPN_InvokeDefaultProcPtr)(NPP npp, NPObject* obj,
|
||||
const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
typedef bool (*NPN_EvaluateProcPtr)(NPP npp, NPObject* obj, NPString* script,
|
||||
NPVariant* result);
|
||||
typedef bool (*NPN_GetPropertyProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier propertyName,
|
||||
NPVariant* result);
|
||||
typedef bool (*NPN_SetPropertyProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier propertyName,
|
||||
const NPVariant* value);
|
||||
typedef bool (*NPN_RemovePropertyProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier propertyName);
|
||||
typedef bool (*NPN_HasPropertyProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier propertyName);
|
||||
typedef bool (*NPN_HasMethodProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier propertyName);
|
||||
typedef void (*NPN_ReleaseVariantValueProcPtr)(NPVariant* variant);
|
||||
typedef void (*NPN_SetExceptionProcPtr)(NPObject* obj, const NPUTF8* message);
|
||||
typedef void (*NPN_PushPopupsEnabledStateProcPtr)(NPP npp, NPBool enabled);
|
||||
typedef void (*NPN_PopPopupsEnabledStateProcPtr)(NPP npp);
|
||||
typedef bool (*NPN_EnumerateProcPtr)(NPP npp, NPObject* obj,
|
||||
NPIdentifier** identifier,
|
||||
uint32_t* count);
|
||||
typedef void (*NPN_PluginThreadAsyncCallProcPtr)(NPP instance,
|
||||
void (*func)(void*),
|
||||
void* userData);
|
||||
typedef bool (*NPN_ConstructProcPtr)(NPP npp, NPObject* obj,
|
||||
const NPVariant* args, uint32_t argCount,
|
||||
NPVariant* result);
|
||||
typedef NPError (*NPN_GetValueForURLPtr)(NPP npp, NPNURLVariable variable,
|
||||
const char* url, char** value,
|
||||
uint32_t* len);
|
||||
typedef NPError (*NPN_SetValueForURLPtr)(NPP npp, NPNURLVariable variable,
|
||||
const char* url, const char* value,
|
||||
uint32_t len);
|
||||
typedef NPError (*NPN_GetAuthenticationInfoPtr)(
|
||||
NPP npp, const char* protocol, const char* host, int32_t port,
|
||||
const char* scheme, const char* realm, char** username, uint32_t* ulen,
|
||||
char** password, uint32_t* plen);
|
||||
typedef uint32_t (*NPN_ScheduleTimerPtr)(NPP instance, uint32_t interval,
|
||||
NPBool repeat,
|
||||
void (*timerFunc)(NPP npp,
|
||||
uint32_t timerID));
|
||||
typedef void (*NPN_UnscheduleTimerPtr)(NPP instance, uint32_t timerID);
|
||||
typedef NPError (*NPN_PopUpContextMenuPtr)(NPP instance, NPMenu* menu);
|
||||
typedef NPBool (*NPN_ConvertPointPtr)(NPP instance, double sourceX,
|
||||
double sourceY,
|
||||
NPCoordinateSpace sourceSpace,
|
||||
double* destX, double* destY,
|
||||
NPCoordinateSpace destSpace);
|
||||
typedef NPBool (*NPN_HandleEventPtr)(NPP instance, void* event, NPBool handled);
|
||||
typedef NPBool (*NPN_UnfocusInstancePtr)(NPP instance,
|
||||
NPFocusDirection direction);
|
||||
typedef void (*NPN_URLRedirectResponsePtr)(NPP instance, void* notifyData,
|
||||
NPBool allow);
|
||||
typedef NPError (*NPN_InitAsyncSurfacePtr)(NPP instance, NPSize* size,
|
||||
NPImageFormat format, void* initData,
|
||||
NPAsyncSurface* surface);
|
||||
typedef NPError (*NPN_FinalizeAsyncSurfacePtr)(NPP instance,
|
||||
NPAsyncSurface* surface);
|
||||
typedef void (*NPN_SetCurrentAsyncSurfacePtr)(NPP instance,
|
||||
NPAsyncSurface* surface,
|
||||
NPRect* changed);
|
||||
|
||||
typedef void (*NPN_DummyPtr)(void);
|
||||
|
||||
typedef struct _NPPluginFuncs {
|
||||
uint16_t size;
|
||||
uint16_t version;
|
||||
NPP_NewProcPtr newp;
|
||||
NPP_DestroyProcPtr destroy;
|
||||
NPP_SetWindowProcPtr setwindow;
|
||||
NPP_NewStreamProcPtr newstream;
|
||||
NPP_DestroyStreamProcPtr destroystream;
|
||||
NPP_StreamAsFileProcPtr asfile;
|
||||
NPP_WriteReadyProcPtr writeready;
|
||||
NPP_WriteProcPtr write;
|
||||
NPP_PrintProcPtr print;
|
||||
NPP_HandleEventProcPtr event;
|
||||
NPP_URLNotifyProcPtr urlnotify;
|
||||
void* javaClass;
|
||||
NPP_GetValueProcPtr getvalue;
|
||||
NPP_SetValueProcPtr setvalue;
|
||||
NPP_GotFocusPtr gotfocus;
|
||||
NPP_LostFocusPtr lostfocus;
|
||||
NPP_URLRedirectNotifyPtr urlredirectnotify;
|
||||
NPP_ClearSiteDataPtr clearsitedata;
|
||||
NPP_GetSitesWithDataPtr getsiteswithdata;
|
||||
NPP_DidCompositePtr didComposite;
|
||||
} NPPluginFuncs;
|
||||
|
||||
typedef struct _NPNetscapeFuncs {
|
||||
uint16_t size;
|
||||
uint16_t version;
|
||||
NPN_GetURLProcPtr geturl;
|
||||
NPN_PostURLProcPtr posturl;
|
||||
NPN_RequestReadProcPtr requestread;
|
||||
NPN_NewStreamProcPtr newstream;
|
||||
NPN_WriteProcPtr write;
|
||||
NPN_DestroyStreamProcPtr destroystream;
|
||||
NPN_StatusProcPtr status;
|
||||
NPN_UserAgentProcPtr uagent;
|
||||
NPN_MemAllocProcPtr memalloc;
|
||||
NPN_MemFreeProcPtr memfree;
|
||||
NPN_MemFlushProcPtr memflush;
|
||||
NPN_ReloadPluginsProcPtr reloadplugins;
|
||||
NPN_GetJavaEnvProcPtr getJavaEnv;
|
||||
NPN_GetJavaPeerProcPtr getJavaPeer;
|
||||
NPN_GetURLNotifyProcPtr geturlnotify;
|
||||
NPN_PostURLNotifyProcPtr posturlnotify;
|
||||
NPN_GetValueProcPtr getvalue;
|
||||
NPN_SetValueProcPtr setvalue;
|
||||
NPN_InvalidateRectProcPtr invalidaterect;
|
||||
NPN_InvalidateRegionProcPtr invalidateregion;
|
||||
NPN_ForceRedrawProcPtr forceredraw;
|
||||
NPN_GetStringIdentifierProcPtr getstringidentifier;
|
||||
NPN_GetStringIdentifiersProcPtr getstringidentifiers;
|
||||
NPN_GetIntIdentifierProcPtr getintidentifier;
|
||||
NPN_IdentifierIsStringProcPtr identifierisstring;
|
||||
NPN_UTF8FromIdentifierProcPtr utf8fromidentifier;
|
||||
NPN_IntFromIdentifierProcPtr intfromidentifier;
|
||||
NPN_CreateObjectProcPtr createobject;
|
||||
NPN_RetainObjectProcPtr retainobject;
|
||||
NPN_ReleaseObjectProcPtr releaseobject;
|
||||
NPN_InvokeProcPtr invoke;
|
||||
NPN_InvokeDefaultProcPtr invokeDefault;
|
||||
NPN_EvaluateProcPtr evaluate;
|
||||
NPN_GetPropertyProcPtr getproperty;
|
||||
NPN_SetPropertyProcPtr setproperty;
|
||||
NPN_RemovePropertyProcPtr removeproperty;
|
||||
NPN_HasPropertyProcPtr hasproperty;
|
||||
NPN_HasMethodProcPtr hasmethod;
|
||||
NPN_ReleaseVariantValueProcPtr releasevariantvalue;
|
||||
NPN_SetExceptionProcPtr setexception;
|
||||
NPN_PushPopupsEnabledStateProcPtr pushpopupsenabledstate;
|
||||
NPN_PopPopupsEnabledStateProcPtr poppopupsenabledstate;
|
||||
NPN_EnumerateProcPtr enumerate;
|
||||
NPN_PluginThreadAsyncCallProcPtr pluginthreadasynccall;
|
||||
NPN_ConstructProcPtr construct;
|
||||
NPN_GetValueForURLPtr getvalueforurl;
|
||||
NPN_SetValueForURLPtr setvalueforurl;
|
||||
NPN_GetAuthenticationInfoPtr getauthenticationinfo;
|
||||
NPN_ScheduleTimerPtr scheduletimer;
|
||||
NPN_UnscheduleTimerPtr unscheduletimer;
|
||||
NPN_PopUpContextMenuPtr popupcontextmenu;
|
||||
NPN_ConvertPointPtr convertpoint;
|
||||
NPN_HandleEventPtr handleevent;
|
||||
NPN_UnfocusInstancePtr unfocusinstance;
|
||||
NPN_URLRedirectResponsePtr urlredirectresponse;
|
||||
NPN_InitAsyncSurfacePtr initasyncsurface;
|
||||
NPN_FinalizeAsyncSurfacePtr finalizeasyncsurface;
|
||||
NPN_SetCurrentAsyncSurfacePtr setcurrentasyncsurface;
|
||||
} NPNetscapeFuncs;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
/*
|
||||
* Mac OS X version(s) of NP_GetMIMEDescription(const char *)
|
||||
* These can be called to retreive MIME information from the plugin dynamically
|
||||
*
|
||||
* Note: For compatibility with Quicktime, BPSupportedMIMEtypes is another way
|
||||
* to get mime info from the plugin only on OSX and may not be supported
|
||||
* in furture version -- use NP_GetMIMEDescription instead
|
||||
*/
|
||||
enum { kBPSupportedMIMETypesStructVers_1 = 1 };
|
||||
typedef struct _BPSupportedMIMETypes {
|
||||
SInt32 structVersion; /* struct version */
|
||||
Handle typeStrings; /* STR# formated handle, allocated by plug-in */
|
||||
Handle infoStrings; /* STR# formated handle, allocated by plug-in */
|
||||
} BPSupportedMIMETypes;
|
||||
OSErr BP_GetSupportedMIMETypes(BPSupportedMIMETypes* mimeInfo, UInt32 flags);
|
||||
# define NP_GETMIMEDESCRIPTION_NAME "NP_GetMIMEDescription"
|
||||
typedef const char* (*NP_GetMIMEDescriptionProcPtr)(void);
|
||||
typedef OSErr (*BP_GetSupportedMIMETypesProcPtr)(BPSupportedMIMETypes*, UInt32);
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define OSCALL WINAPI
|
||||
#else
|
||||
# define OSCALL
|
||||
#endif
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
/* GCC 3.3 and later support the visibility attribute. */
|
||||
# if defined(__GNUC__) && \
|
||||
((__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3))
|
||||
# define NP_VISIBILITY_DEFAULT __attribute__((visibility("default")))
|
||||
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# define NP_VISIBILITY_DEFAULT __global
|
||||
# else
|
||||
# define NP_VISIBILITY_DEFAULT
|
||||
# endif
|
||||
# define NP_EXPORT(__type) NP_VISIBILITY_DEFAULT __type
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
/* plugin meta member functions */
|
||||
typedef NPError(OSCALL* NP_GetEntryPointsFunc)(NPPluginFuncs*);
|
||||
NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs);
|
||||
typedef NPError(OSCALL* NP_InitializeFunc)(NPNetscapeFuncs*);
|
||||
NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs);
|
||||
typedef NPError(OSCALL* NP_ShutdownFunc)(void);
|
||||
NPError OSCALL NP_Shutdown(void);
|
||||
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
|
||||
const char* NP_GetMIMEDescription(void);
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef XP_UNIX
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
typedef char* (*NP_GetPluginVersionFunc)(void);
|
||||
NP_EXPORT(char*) NP_GetPluginVersion(void);
|
||||
typedef const char* (*NP_GetMIMEDescriptionFunc)(void);
|
||||
NP_EXPORT(const char*) NP_GetMIMEDescription(void);
|
||||
# ifdef XP_MACOSX
|
||||
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*);
|
||||
NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs);
|
||||
typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*);
|
||||
NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs);
|
||||
# else
|
||||
typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*);
|
||||
NP_EXPORT(NPError)
|
||||
NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs);
|
||||
# endif
|
||||
typedef NPError (*NP_ShutdownFunc)(void);
|
||||
NP_EXPORT(NPError) NP_Shutdown(void);
|
||||
typedef NPError (*NP_GetValueFunc)(void*, NPPVariable, void*);
|
||||
NP_EXPORT(NPError)
|
||||
NP_GetValue(void* future, NPPVariable aVariable, void* aValue);
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// clang-format off
|
||||
// See bug 1431030
|
||||
#if defined(XP_WIN)
|
||||
#define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
|
||||
#else
|
||||
#define NS_NPAPIPLUGIN_CALLBACK(_type, _name) _type (* _name)
|
||||
#endif
|
||||
// clang-format on
|
||||
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(NPError,
|
||||
NP_GETENTRYPOINTS)(NPPluginFuncs* pCallbacks);
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGININIT)(
|
||||
const NPNetscapeFuncs* pCallbacks);
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINUNIXINIT)(
|
||||
const NPNetscapeFuncs* pCallbacks, NPPluginFuncs* fCallbacks);
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN)(void);
|
||||
|
||||
#endif /* npfunctions_h_ */
|
|
@ -1,382 +0,0 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/*
|
||||
* Copyright (c) 2004, Apple Computer, Inc. and The Mozilla Foundation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the names of Apple Computer, Inc. ("Apple") or The Mozilla
|
||||
* Foundation ("Mozilla") nor the names of their contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY APPLE, MOZILLA AND THEIR CONTRIBUTORS "AS
|
||||
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE, MOZILLA OR
|
||||
* THEIR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifndef _NP_RUNTIME_H_
|
||||
#define _NP_RUNTIME_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nptypes.h"
|
||||
|
||||
/*
|
||||
This API is used to facilitate binding code written in C to script
|
||||
objects. The API in this header does not assume the presence of a
|
||||
user agent. That is, it can be used to bind C code to scripting
|
||||
environments outside of the context of a user agent.
|
||||
|
||||
However, the normal use of the this API is in the context of a
|
||||
scripting environment running in a browser or other user agent.
|
||||
In particular it is used to support the extended Netscape
|
||||
script-ability API for plugins (NP-SAP). NP-SAP is an extension
|
||||
of the Netscape plugin API. As such we have adopted the use of
|
||||
the "NP" prefix for this API.
|
||||
|
||||
The following NP{N|P}Variables were added to the Netscape plugin
|
||||
API (in npapi.h):
|
||||
|
||||
NPNVWindowNPObject
|
||||
NPNVPluginElementNPObject
|
||||
NPPVpluginScriptableNPObject
|
||||
|
||||
These variables are exposed through NPN_GetValue() and
|
||||
NPP_GetValue() (respectively) and are used to establish the
|
||||
initial binding between the user agent and native code. The DOM
|
||||
objects in the user agent can be examined and manipulated using
|
||||
the NPN_ functions that operate on NPObjects described in this
|
||||
header.
|
||||
|
||||
To the extent possible the assumptions about the scripting
|
||||
language used by the scripting environment have been minimized.
|
||||
*/
|
||||
|
||||
#define NP_BEGIN_MACRO do {
|
||||
#define NP_END_MACRO \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/*
|
||||
Objects (non-primitive data) passed between 'C' and script is
|
||||
always wrapped in an NPObject. The 'interface' of an NPObject is
|
||||
described by an NPClass.
|
||||
*/
|
||||
typedef struct NPObject NPObject;
|
||||
typedef struct NPClass NPClass;
|
||||
|
||||
typedef char NPUTF8;
|
||||
typedef struct _NPString {
|
||||
const NPUTF8* UTF8Characters;
|
||||
uint32_t UTF8Length;
|
||||
} NPString;
|
||||
|
||||
typedef enum {
|
||||
NPVariantType_Void,
|
||||
NPVariantType_Null,
|
||||
NPVariantType_Bool,
|
||||
NPVariantType_Int32,
|
||||
NPVariantType_Double,
|
||||
NPVariantType_String,
|
||||
NPVariantType_Object
|
||||
} NPVariantType;
|
||||
|
||||
typedef struct _NPVariant {
|
||||
NPVariantType type;
|
||||
union {
|
||||
bool boolValue;
|
||||
int32_t intValue;
|
||||
double doubleValue;
|
||||
NPString stringValue;
|
||||
NPObject* objectValue;
|
||||
} value;
|
||||
} NPVariant;
|
||||
|
||||
/*
|
||||
NPN_ReleaseVariantValue is called on all 'out' parameters
|
||||
references. Specifically it is to be called on variants that own
|
||||
their value, as is the case with all non-const NPVariant*
|
||||
arguments after a successful call to any methods (except this one)
|
||||
in this API.
|
||||
|
||||
After calling NPN_ReleaseVariantValue, the type of the variant
|
||||
will be NPVariantType_Void.
|
||||
*/
|
||||
void NPN_ReleaseVariantValue(NPVariant* variant);
|
||||
|
||||
#define NPVARIANT_IS_VOID(_v) ((_v).type == NPVariantType_Void)
|
||||
#define NPVARIANT_IS_NULL(_v) ((_v).type == NPVariantType_Null)
|
||||
#define NPVARIANT_IS_BOOLEAN(_v) ((_v).type == NPVariantType_Bool)
|
||||
#define NPVARIANT_IS_INT32(_v) ((_v).type == NPVariantType_Int32)
|
||||
#define NPVARIANT_IS_DOUBLE(_v) ((_v).type == NPVariantType_Double)
|
||||
#define NPVARIANT_IS_STRING(_v) ((_v).type == NPVariantType_String)
|
||||
#define NPVARIANT_IS_OBJECT(_v) ((_v).type == NPVariantType_Object)
|
||||
|
||||
#define NPVARIANT_TO_BOOLEAN(_v) ((_v).value.boolValue)
|
||||
#define NPVARIANT_TO_INT32(_v) ((_v).value.intValue)
|
||||
#define NPVARIANT_TO_DOUBLE(_v) ((_v).value.doubleValue)
|
||||
#define NPVARIANT_TO_STRING(_v) ((_v).value.stringValue)
|
||||
#define NPVARIANT_TO_OBJECT(_v) ((_v).value.objectValue)
|
||||
|
||||
#define VOID_TO_NPVARIANT(_v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_Void; \
|
||||
(_v).value.objectValue = NULL; \
|
||||
NP_END_MACRO
|
||||
|
||||
#define NULL_TO_NPVARIANT(_v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_Null; \
|
||||
(_v).value.objectValue = NULL; \
|
||||
NP_END_MACRO
|
||||
|
||||
#define BOOLEAN_TO_NPVARIANT(_val, _v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_Bool; \
|
||||
(_v).value.boolValue = !!(_val); \
|
||||
NP_END_MACRO
|
||||
|
||||
#define INT32_TO_NPVARIANT(_val, _v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_Int32; \
|
||||
(_v).value.intValue = _val; \
|
||||
NP_END_MACRO
|
||||
|
||||
#define DOUBLE_TO_NPVARIANT(_val, _v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_Double; \
|
||||
(_v).value.doubleValue = _val; \
|
||||
NP_END_MACRO
|
||||
|
||||
#define STRINGZ_TO_NPVARIANT(_val, _v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_String; \
|
||||
NPString str = {_val, (uint32_t)(strlen(_val))}; \
|
||||
(_v).value.stringValue = str; \
|
||||
NP_END_MACRO
|
||||
|
||||
#define STRINGN_TO_NPVARIANT(_val, _len, _v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_String; \
|
||||
NPString str = {_val, (uint32_t)(_len)}; \
|
||||
(_v).value.stringValue = str; \
|
||||
NP_END_MACRO
|
||||
|
||||
#define OBJECT_TO_NPVARIANT(_val, _v) \
|
||||
NP_BEGIN_MACRO(_v).type = NPVariantType_Object; \
|
||||
(_v).value.objectValue = _val; \
|
||||
NP_END_MACRO
|
||||
|
||||
/*
|
||||
Type mappings (JavaScript types have been used for illustration
|
||||
purposes):
|
||||
|
||||
JavaScript to C (NPVariant with type:)
|
||||
undefined NPVariantType_Void
|
||||
null NPVariantType_Null
|
||||
Boolean NPVariantType_Bool
|
||||
Number NPVariantType_Double or NPVariantType_Int32
|
||||
String NPVariantType_String
|
||||
Object NPVariantType_Object
|
||||
|
||||
C (NPVariant with type:) to JavaScript
|
||||
NPVariantType_Void undefined
|
||||
NPVariantType_Null null
|
||||
NPVariantType_Bool Boolean
|
||||
NPVariantType_Int32 Number
|
||||
NPVariantType_Double Number
|
||||
NPVariantType_String String
|
||||
NPVariantType_Object Object
|
||||
*/
|
||||
|
||||
typedef void* NPIdentifier;
|
||||
|
||||
/*
|
||||
NPObjects have methods and properties. Methods and properties are
|
||||
identified with NPIdentifiers. These identifiers may be reflected
|
||||
in script. NPIdentifiers can be either strings or integers, IOW,
|
||||
methods and properties can be identified by either strings or
|
||||
integers (i.e. foo["bar"] vs foo[1]). NPIdentifiers can be
|
||||
compared using ==. In case of any errors, the requested
|
||||
NPIdentifier(s) will be NULL. NPIdentifier lifetime is controlled
|
||||
by the browser. Plugins do not need to worry about memory management
|
||||
with regards to NPIdentifiers.
|
||||
*/
|
||||
NPIdentifier NPN_GetStringIdentifier(const NPUTF8* name);
|
||||
void NPN_GetStringIdentifiers(const NPUTF8** names, int32_t nameCount,
|
||||
NPIdentifier* identifiers);
|
||||
NPIdentifier NPN_GetIntIdentifier(int32_t intid);
|
||||
bool NPN_IdentifierIsString(NPIdentifier identifier);
|
||||
|
||||
/*
|
||||
The NPUTF8 returned from NPN_UTF8FromIdentifier SHOULD be freed.
|
||||
*/
|
||||
NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier identifier);
|
||||
|
||||
/*
|
||||
Get the integer represented by identifier. If identifier is not an
|
||||
integer identifier, the behaviour is undefined.
|
||||
*/
|
||||
int32_t NPN_IntFromIdentifier(NPIdentifier identifier);
|
||||
|
||||
/*
|
||||
NPObject behavior is implemented using the following set of
|
||||
callback functions.
|
||||
|
||||
The NPVariant *result argument of these functions (where
|
||||
applicable) should be released using NPN_ReleaseVariantValue().
|
||||
*/
|
||||
typedef NPObject* (*NPAllocateFunctionPtr)(NPP npp, NPClass* aClass);
|
||||
typedef void (*NPDeallocateFunctionPtr)(NPObject* npobj);
|
||||
typedef void (*NPInvalidateFunctionPtr)(NPObject* npobj);
|
||||
typedef bool (*NPHasMethodFunctionPtr)(NPObject* npobj, NPIdentifier name);
|
||||
typedef bool (*NPInvokeFunctionPtr)(NPObject* npobj, NPIdentifier name,
|
||||
const NPVariant* args, uint32_t argCount,
|
||||
NPVariant* result);
|
||||
typedef bool (*NPInvokeDefaultFunctionPtr)(NPObject* npobj,
|
||||
const NPVariant* args,
|
||||
uint32_t argCount,
|
||||
NPVariant* result);
|
||||
typedef bool (*NPHasPropertyFunctionPtr)(NPObject* npobj, NPIdentifier name);
|
||||
typedef bool (*NPGetPropertyFunctionPtr)(NPObject* npobj, NPIdentifier name,
|
||||
NPVariant* result);
|
||||
typedef bool (*NPSetPropertyFunctionPtr)(NPObject* npobj, NPIdentifier name,
|
||||
const NPVariant* value);
|
||||
typedef bool (*NPRemovePropertyFunctionPtr)(NPObject* npobj, NPIdentifier name);
|
||||
typedef bool (*NPEnumerationFunctionPtr)(NPObject* npobj, NPIdentifier** value,
|
||||
uint32_t* count);
|
||||
typedef bool (*NPConstructFunctionPtr)(NPObject* npobj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
|
||||
/*
|
||||
NPObjects returned by create, retain, invoke, and getProperty pass
|
||||
a reference count to the caller. That is, the callee adds a
|
||||
reference count which passes to the caller. It is the caller's
|
||||
responsibility to release the returned object.
|
||||
|
||||
NPInvokeFunctionPtr function may return 0 to indicate a void
|
||||
result.
|
||||
|
||||
NPInvalidateFunctionPtr is called by the scripting environment
|
||||
when the native code is shutdown. Any attempt to message a
|
||||
NPObject instance after the invalidate callback has been
|
||||
called will result in undefined behavior, even if the native code
|
||||
is still retaining those NPObject instances. (The runtime
|
||||
will typically return immediately, with 0 or NULL, from an
|
||||
attempt to dispatch to a NPObject, but this behavior should not
|
||||
be depended upon.)
|
||||
|
||||
The NPEnumerationFunctionPtr function may pass an array of
|
||||
NPIdentifiers back to the caller. The callee allocs the memory of
|
||||
the array using NPN_MemAlloc(), and it's the caller's responsibility
|
||||
to release it using NPN_MemFree().
|
||||
*/
|
||||
struct NPClass {
|
||||
uint32_t structVersion;
|
||||
NPAllocateFunctionPtr allocate;
|
||||
NPDeallocateFunctionPtr deallocate;
|
||||
NPInvalidateFunctionPtr invalidate;
|
||||
NPHasMethodFunctionPtr hasMethod;
|
||||
NPInvokeFunctionPtr invoke;
|
||||
NPInvokeDefaultFunctionPtr invokeDefault;
|
||||
NPHasPropertyFunctionPtr hasProperty;
|
||||
NPGetPropertyFunctionPtr getProperty;
|
||||
NPSetPropertyFunctionPtr setProperty;
|
||||
NPRemovePropertyFunctionPtr removeProperty;
|
||||
NPEnumerationFunctionPtr enumerate;
|
||||
NPConstructFunctionPtr construct;
|
||||
};
|
||||
|
||||
#define NP_CLASS_STRUCT_VERSION 3
|
||||
|
||||
#define NP_CLASS_STRUCT_VERSION_ENUM 2
|
||||
#define NP_CLASS_STRUCT_VERSION_CTOR 3
|
||||
|
||||
#define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \
|
||||
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM)
|
||||
|
||||
#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \
|
||||
((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR)
|
||||
|
||||
struct NPObject {
|
||||
NPClass* _class;
|
||||
uint32_t referenceCount;
|
||||
/*
|
||||
* Additional space may be allocated here by types of NPObjects
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
If the class has an allocate function, NPN_CreateObject invokes
|
||||
that function, otherwise a NPObject is allocated and
|
||||
returned. This method will initialize the referenceCount member of
|
||||
the NPObject to 1.
|
||||
*/
|
||||
NPObject* NPN_CreateObject(NPP npp, NPClass* aClass);
|
||||
|
||||
/*
|
||||
Increment the NPObject's reference count.
|
||||
*/
|
||||
NPObject* NPN_RetainObject(NPObject* npobj);
|
||||
|
||||
/*
|
||||
Decremented the NPObject's reference count. If the reference
|
||||
count goes to zero, the class's destroy function is invoke if
|
||||
specified, otherwise the object is freed directly.
|
||||
*/
|
||||
void NPN_ReleaseObject(NPObject* npobj);
|
||||
|
||||
/*
|
||||
Functions to access script objects represented by NPObject.
|
||||
|
||||
Calls to script objects are synchronous. If a function returns a
|
||||
value, it will be supplied via the result NPVariant
|
||||
argument. Successful calls will return true, false will be
|
||||
returned in case of an error.
|
||||
|
||||
Calls made from plugin code to script must be made from the thread
|
||||
on which the plugin was initialized.
|
||||
*/
|
||||
|
||||
bool NPN_Invoke(NPP npp, NPObject* npobj, NPIdentifier methodName,
|
||||
const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
bool NPN_InvokeDefault(NPP npp, NPObject* npobj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
bool NPN_Evaluate(NPP npp, NPObject* npobj, NPString* script,
|
||||
NPVariant* result);
|
||||
bool NPN_GetProperty(NPP npp, NPObject* npobj, NPIdentifier propertyName,
|
||||
NPVariant* result);
|
||||
bool NPN_SetProperty(NPP npp, NPObject* npobj, NPIdentifier propertyName,
|
||||
const NPVariant* value);
|
||||
bool NPN_RemoveProperty(NPP npp, NPObject* npobj, NPIdentifier propertyName);
|
||||
bool NPN_HasProperty(NPP npp, NPObject* npobj, NPIdentifier propertyName);
|
||||
bool NPN_HasMethod(NPP npp, NPObject* npobj, NPIdentifier methodName);
|
||||
bool NPN_Enumerate(NPP npp, NPObject* npobj, NPIdentifier** identifier,
|
||||
uint32_t* count);
|
||||
bool NPN_Construct(NPP npp, NPObject* npobj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
|
||||
/*
|
||||
NPN_SetException may be called to trigger a script exception upon
|
||||
return from entry points into NPObjects. Typical usage:
|
||||
|
||||
NPN_SetException (npobj, message);
|
||||
*/
|
||||
void NPN_SetException(NPObject* npobj, const NPUTF8* message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,29 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* The nsIHTTPHeaderListener interface allows plugin authors to
|
||||
* access HTTP Response headers after issuing an
|
||||
* nsIPluginHost::{GetURL,PostURL}() call. <P>
|
||||
*/
|
||||
|
||||
[scriptable, uuid(ea51e0b8-871c-4b85-92da-6f400394c5ec)]
|
||||
interface nsIHTTPHeaderListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Called for each HTTP Response header.
|
||||
* NOTE: You must copy the values of the params.
|
||||
*/
|
||||
void newResponseHeader(in string headerName, in string headerValue);
|
||||
|
||||
/**
|
||||
* Called once for the HTTP Response status line.
|
||||
* Value does NOT include a terminating newline.
|
||||
* NOTE: You must copy this value.
|
||||
*/
|
||||
void statusLine(in string line);
|
||||
};
|
|
@ -1,20 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 "nsIInputStream.idl"
|
||||
#include "nspluginroot.idl"
|
||||
|
||||
/**
|
||||
* The nsIPluginInputStream interface ...
|
||||
*/
|
||||
[uuid(af160530-542a-11d2-8164-006008119d7a)]
|
||||
interface nsIPluginInputStream : nsIInputStream {
|
||||
/**
|
||||
* Corresponds to NPStream's lastmodified field.)
|
||||
*/
|
||||
void getLastModified(out unsigned long aResult);
|
||||
|
||||
void requestRead(out NPByteRange aRangeList);
|
||||
};
|
|
@ -1,121 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* 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 "nsISupports.idl"
|
||||
#include "nspluginroot.idl"
|
||||
#include "nsIInputStream.idl"
|
||||
|
||||
webidl Document;
|
||||
|
||||
%{C++
|
||||
#include "npapi.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
class nsNPAPIPluginInstance;
|
||||
|
||||
enum nsPluginTagType {
|
||||
nsPluginTagType_Unknown,
|
||||
nsPluginTagType_Embed,
|
||||
nsPluginTagType_Object
|
||||
};
|
||||
%}
|
||||
|
||||
[ptr] native nsNPAPIPluginInstancePtr(nsNPAPIPluginInstance);
|
||||
|
||||
// Do not make this interface scriptable, because the virtual functions in C++
|
||||
// blocks will make script call the wrong functions.
|
||||
[uuid(7d65452e-c167-4cba-a0e3-ddc61bdde8c3)]
|
||||
interface nsIPluginInstanceOwner : nsISupports
|
||||
{
|
||||
/**
|
||||
* Let the owner know what its instance is
|
||||
*/
|
||||
void setInstance(in nsNPAPIPluginInstancePtr aInstance);
|
||||
|
||||
/**
|
||||
* Get the instance associated with this owner.
|
||||
*/
|
||||
[notxpcom, nostdcall] nsNPAPIPluginInstancePtr getInstance();
|
||||
|
||||
/**
|
||||
* Get a handle to the window structure of the owner.
|
||||
* This pointer cannot be made persistent by the caller.
|
||||
*/
|
||||
void getWindow(in NPWindowStarRef aWindow);
|
||||
|
||||
/**
|
||||
* Get the display mode for the plugin instance.
|
||||
*/
|
||||
readonly attribute int32_t mode;
|
||||
|
||||
/**
|
||||
* Create a place for the plugin to live in the owner's
|
||||
* environment. this may or may not create a window
|
||||
* depending on the windowless state of the plugin instance.
|
||||
*/
|
||||
void createWidget();
|
||||
|
||||
%{C++
|
||||
/**
|
||||
* Called when there is a valid target so that the proper
|
||||
* frame can be updated with new content. will not be called
|
||||
* with nullptr aTarget.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetURL(const char *aURL, const char *aTarget,
|
||||
nsIInputStream *aPostStream,
|
||||
void *aHeadersData, uint32_t aHeadersDataLen,
|
||||
bool aDoCheckLoadURIChecks) = 0;
|
||||
%}
|
||||
|
||||
/**
|
||||
* Get the associated document.
|
||||
*/
|
||||
readonly attribute Document document;
|
||||
|
||||
/**
|
||||
* Invalidate the rectangle
|
||||
*/
|
||||
void invalidateRect(in NPRectPtr aRect);
|
||||
|
||||
/**
|
||||
* Invalidate the region
|
||||
*/
|
||||
void invalidateRegion(in NPRegion aRegion);
|
||||
|
||||
/**
|
||||
* Have the plugin recomposited.
|
||||
*/
|
||||
void redrawPlugin();
|
||||
|
||||
/**
|
||||
* Get NetscapeWindow, corresponds to NPNVnetscapeWindow
|
||||
*/
|
||||
void getNetscapeWindow(in voidPtr aValue);
|
||||
|
||||
/**
|
||||
* Convert between plugin, window, and screen coordinate spaces.
|
||||
*/
|
||||
%{C++
|
||||
virtual NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
double *destX, double *destY, NPCoordinateSpace destSpace) = 0;
|
||||
virtual NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
|
||||
void *initData, NPAsyncSurface *surface) = 0;
|
||||
virtual NPError FinalizeAsyncSurface(NPAsyncSurface *surface) = 0;
|
||||
virtual void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) = 0;
|
||||
%}
|
||||
|
||||
void setEventModel(in int32_t eventModel);
|
||||
|
||||
/**
|
||||
* Call NPP_SetWindow on the plugin.
|
||||
*/
|
||||
void callSetWindow();
|
||||
|
||||
/**
|
||||
* Get the contents scale factor for the screen the plugin is
|
||||
* drawn on.
|
||||
*/
|
||||
double getContentsScaleFactor();
|
||||
};
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,99 +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 nsJSNPRuntime_h_
|
||||
#define nsJSNPRuntime_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "npapi.h"
|
||||
#include "npruntime.h"
|
||||
#include "PLDHashTable.h"
|
||||
#include "js/RootingAPI.h"
|
||||
|
||||
class nsJSNPRuntime {
|
||||
public:
|
||||
static void OnPluginDestroy(NPP npp);
|
||||
static void OnPluginDestroyPending(NPP npp);
|
||||
};
|
||||
|
||||
class nsJSObjWrapperKey {
|
||||
public:
|
||||
nsJSObjWrapperKey(JSObject* obj, NPP npp) : mJSObj(obj), mNpp(npp) {}
|
||||
|
||||
bool operator==(const nsJSObjWrapperKey& other) const {
|
||||
return mJSObj == other.mJSObj && mNpp == other.mNpp;
|
||||
}
|
||||
bool operator!=(const nsJSObjWrapperKey& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void trace(JSTracer* trc) {
|
||||
JS::TraceEdge(trc, &mJSObj, "nsJSObjWrapperKey");
|
||||
}
|
||||
|
||||
nsJSObjWrapperKey(nsJSObjWrapperKey&& other) = default;
|
||||
nsJSObjWrapperKey& operator=(nsJSObjWrapperKey&& other) = default;
|
||||
|
||||
JS::Heap<JSObject*> mJSObj;
|
||||
NPP mNpp;
|
||||
};
|
||||
|
||||
class nsJSObjWrapper : public NPObject {
|
||||
public:
|
||||
JS::Heap<JSObject*> mJSObj;
|
||||
// Because mJSObj might be a cross-compartment wrapper, we can't use it to
|
||||
// enter the target realm. We use this global instead (it's always
|
||||
// same-compartment with mJSObj).
|
||||
JS::Heap<JSObject*> mJSObjGlobal;
|
||||
const NPP mNpp;
|
||||
bool mDestroyPending;
|
||||
|
||||
static NPObject* GetNewOrUsed(NPP npp, JS::Handle<JSObject*> obj,
|
||||
JS::Handle<JSObject*> objGlobal);
|
||||
|
||||
void trace(JSTracer* trc) {
|
||||
JS::TraceEdge(trc, &mJSObj, "nsJSObjWrapper::mJSObj");
|
||||
JS::TraceEdge(trc, &mJSObjGlobal, "nsJSObjWrapper::mJSObjGlobal");
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit nsJSObjWrapper(NPP npp);
|
||||
~nsJSObjWrapper();
|
||||
|
||||
static NPObject* NP_Allocate(NPP npp, NPClass* aClass);
|
||||
static void NP_Deallocate(NPObject* obj);
|
||||
static void NP_Invalidate(NPObject* obj);
|
||||
static bool NP_HasMethod(NPObject*, NPIdentifier identifier);
|
||||
static bool NP_Invoke(NPObject* obj, NPIdentifier method,
|
||||
const NPVariant* args, uint32_t argCount,
|
||||
NPVariant* result);
|
||||
static bool NP_InvokeDefault(NPObject* obj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
static bool NP_HasProperty(NPObject* obj, NPIdentifier property);
|
||||
static bool NP_GetProperty(NPObject* obj, NPIdentifier property,
|
||||
NPVariant* result);
|
||||
static bool NP_SetProperty(NPObject* obj, NPIdentifier property,
|
||||
const NPVariant* value);
|
||||
static bool NP_RemoveProperty(NPObject* obj, NPIdentifier property);
|
||||
static bool NP_Enumerate(NPObject* npobj, NPIdentifier** identifier,
|
||||
uint32_t* count);
|
||||
static bool NP_Construct(NPObject* obj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
|
||||
public:
|
||||
static NPClass sJSObjWrapperNPClass;
|
||||
};
|
||||
|
||||
class nsNPObjWrapper {
|
||||
public:
|
||||
static bool IsWrapper(JSObject* obj);
|
||||
static void OnDestroy(NPObject* npobj);
|
||||
static JSObject* GetNewOrUsed(NPP npp, JSContext* cx, NPObject* npobj);
|
||||
};
|
||||
|
||||
bool JSValToNPVariant(NPP npp, JSContext* cx, const JS::Value& val,
|
||||
NPVariant* variant);
|
||||
|
||||
#endif // nsJSNPRuntime_h_
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,288 +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 nsNPAPIPlugin_h_
|
||||
#define nsNPAPIPlugin_h_
|
||||
|
||||
#include "prlink.h"
|
||||
#include "npfunctions.h"
|
||||
#include "nsPluginHost.h"
|
||||
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/PluginLibrary.h"
|
||||
#include "mozilla/RefCounted.h"
|
||||
|
||||
// nsNPAPIPlugin is held alive both by active nsPluginTag instances and
|
||||
// by active nsNPAPIPluginInstance.
|
||||
class nsNPAPIPlugin final {
|
||||
private:
|
||||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
|
||||
public:
|
||||
nsNPAPIPlugin();
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(nsNPAPIPlugin)
|
||||
|
||||
// Constructs and initializes an nsNPAPIPlugin object. A nullptr file path
|
||||
// will prevent this from calling NP_Initialize.
|
||||
static nsresult CreatePlugin(nsPluginTag* aPluginTag,
|
||||
nsNPAPIPlugin** aResult);
|
||||
|
||||
PluginLibrary* GetLibrary();
|
||||
// PluginFuncs() can't fail but results are only valid if GetLibrary()
|
||||
// succeeds
|
||||
NPPluginFuncs* PluginFuncs();
|
||||
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
void SetPluginRefNum(short aRefNum);
|
||||
#endif
|
||||
|
||||
// The IPC mechanism notifies the nsNPAPIPlugin if the plugin
|
||||
// crashes and is no longer usable. pluginDumpID is the ID of the minidump
|
||||
// that was written, or empty if no minidump was written.
|
||||
void PluginCrashed(const nsAString& aPluginDumpID,
|
||||
const nsACString& aAdditionalMinidumps);
|
||||
|
||||
nsresult Shutdown();
|
||||
|
||||
static nsresult RetainStream(NPStream* pstream, nsISupports** aRetainedPeer);
|
||||
|
||||
private:
|
||||
~nsNPAPIPlugin();
|
||||
|
||||
NPPluginFuncs mPluginFuncs;
|
||||
PluginLibrary* mLibrary;
|
||||
};
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
namespace parent {
|
||||
|
||||
static_assert(sizeof(NPIdentifier) == sizeof(jsid),
|
||||
"NPIdentifier must be binary compatible with jsid.");
|
||||
|
||||
inline jsid NPIdentifierToJSId(NPIdentifier id) {
|
||||
jsid tmp;
|
||||
JSID_BITS(tmp) = (size_t)id;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline NPIdentifier JSIdToNPIdentifier(jsid id) {
|
||||
return (NPIdentifier)JSID_BITS(id);
|
||||
}
|
||||
|
||||
inline bool NPIdentifierIsString(NPIdentifier id) {
|
||||
return JSID_IS_STRING(NPIdentifierToJSId(id));
|
||||
}
|
||||
|
||||
inline JSString* NPIdentifierToString(NPIdentifier id) {
|
||||
return JSID_TO_STRING(NPIdentifierToJSId(id));
|
||||
}
|
||||
|
||||
inline NPIdentifier StringToNPIdentifier(JSContext* cx, JSString* str) {
|
||||
return JSIdToNPIdentifier(JS::PropertyKey::fromPinnedString(str));
|
||||
}
|
||||
|
||||
inline bool NPIdentifierIsInt(NPIdentifier id) {
|
||||
return JSID_IS_INT(NPIdentifierToJSId(id));
|
||||
}
|
||||
|
||||
inline int NPIdentifierToInt(NPIdentifier id) {
|
||||
return JSID_TO_INT(NPIdentifierToJSId(id));
|
||||
}
|
||||
|
||||
inline NPIdentifier IntToNPIdentifier(int i) {
|
||||
return JSIdToNPIdentifier(INT_TO_JSID(i));
|
||||
}
|
||||
|
||||
JSContext* GetJSContext(NPP npp);
|
||||
|
||||
inline bool NPStringIdentifierIsPermanent(NPIdentifier id) {
|
||||
AutoSafeJSContext cx;
|
||||
return JS_StringHasBeenPinned(cx, NPIdentifierToString(id));
|
||||
}
|
||||
|
||||
#define NPIdentifier_VOID (JSIdToNPIdentifier(JSID_VOID))
|
||||
|
||||
NPObject* _getwindowobject(NPP npp);
|
||||
|
||||
NPObject* _getpluginelement(NPP npp);
|
||||
|
||||
NPIdentifier _getstringidentifier(const NPUTF8* name);
|
||||
|
||||
void _getstringidentifiers(const NPUTF8** names, int32_t nameCount,
|
||||
NPIdentifier* identifiers);
|
||||
|
||||
bool _identifierisstring(NPIdentifier identifiers);
|
||||
|
||||
NPIdentifier _getintidentifier(int32_t intid);
|
||||
|
||||
NPUTF8* _utf8fromidentifier(NPIdentifier identifier);
|
||||
|
||||
int32_t _intfromidentifier(NPIdentifier identifier);
|
||||
|
||||
NPObject* _createobject(NPP npp, NPClass* aClass);
|
||||
|
||||
NPObject* _retainobject(NPObject* npobj);
|
||||
|
||||
void _releaseobject(NPObject* npobj);
|
||||
|
||||
bool _invoke(NPP npp, NPObject* npobj, NPIdentifier method,
|
||||
const NPVariant* args, uint32_t argCount, NPVariant* result);
|
||||
|
||||
bool _invokeDefault(NPP npp, NPObject* npobj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
|
||||
bool _evaluate(NPP npp, NPObject* npobj, NPString* script, NPVariant* result);
|
||||
|
||||
bool _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
|
||||
NPVariant* result);
|
||||
|
||||
bool _setproperty(NPP npp, NPObject* npobj, NPIdentifier property,
|
||||
const NPVariant* value);
|
||||
|
||||
bool _removeproperty(NPP npp, NPObject* npobj, NPIdentifier property);
|
||||
|
||||
bool _hasproperty(NPP npp, NPObject* npobj, NPIdentifier propertyName);
|
||||
|
||||
bool _hasmethod(NPP npp, NPObject* npobj, NPIdentifier methodName);
|
||||
|
||||
bool _enumerate(NPP npp, NPObject* npobj, NPIdentifier** identifier,
|
||||
uint32_t* count);
|
||||
|
||||
bool _construct(NPP npp, NPObject* npobj, const NPVariant* args,
|
||||
uint32_t argCount, NPVariant* result);
|
||||
|
||||
void _releasevariantvalue(NPVariant* variant);
|
||||
|
||||
void _setexception(NPObject* npobj, const NPUTF8* message);
|
||||
|
||||
void _pushpopupsenabledstate(NPP npp, NPBool enabled);
|
||||
|
||||
void _poppopupsenabledstate(NPP npp);
|
||||
|
||||
NPError _getvalueforurl(NPP instance, NPNURLVariable variable, const char* url,
|
||||
char** value, uint32_t* len);
|
||||
|
||||
NPError _setvalueforurl(NPP instance, NPNURLVariable variable, const char* url,
|
||||
const char* value, uint32_t len);
|
||||
|
||||
typedef void (*PluginTimerFunc)(NPP npp, uint32_t timerID);
|
||||
|
||||
uint32_t _scheduletimer(NPP instance, uint32_t interval, NPBool repeat,
|
||||
PluginTimerFunc timerFunc);
|
||||
|
||||
void _unscheduletimer(NPP instance, uint32_t timerID);
|
||||
|
||||
NPError _popupcontextmenu(NPP instance, NPMenu* menu);
|
||||
|
||||
NPBool _convertpoint(NPP instance, double sourceX, double sourceY,
|
||||
NPCoordinateSpace sourceSpace, double* destX,
|
||||
double* destY, NPCoordinateSpace destSpace);
|
||||
|
||||
NPError _requestread(NPStream* pstream, NPByteRange* rangeList);
|
||||
|
||||
NPError _geturlnotify(NPP npp, const char* relativeURL, const char* target,
|
||||
void* notifyData);
|
||||
|
||||
NPError _getvalue(NPP npp, NPNVariable variable, void* r_value);
|
||||
|
||||
NPError _setvalue(NPP npp, NPPVariable variable, void* r_value);
|
||||
|
||||
NPError _geturl(NPP npp, const char* relativeURL, const char* target);
|
||||
|
||||
NPError _posturlnotify(NPP npp, const char* relativeURL, const char* target,
|
||||
uint32_t len, const char* buf, NPBool file,
|
||||
void* notifyData);
|
||||
|
||||
NPError _posturl(NPP npp, const char* relativeURL, const char* target,
|
||||
uint32_t len, const char* buf, NPBool file);
|
||||
|
||||
void _status(NPP npp, const char* message);
|
||||
|
||||
void _memfree(void* ptr);
|
||||
|
||||
uint32_t _memflush(uint32_t size);
|
||||
|
||||
void _reloadplugins(NPBool reloadPages);
|
||||
|
||||
void _invalidaterect(NPP npp, NPRect* invalidRect);
|
||||
|
||||
void _invalidateregion(NPP npp, NPRegion invalidRegion);
|
||||
|
||||
void _forceredraw(NPP npp);
|
||||
|
||||
const char* _useragent(NPP npp);
|
||||
|
||||
void* _memalloc(uint32_t size);
|
||||
|
||||
// Deprecated entry points for the old Java plugin.
|
||||
void* /* OJI type: JRIEnv* */
|
||||
_getJavaEnv();
|
||||
|
||||
void* /* OJI type: jref */
|
||||
_getJavaPeer(NPP npp);
|
||||
|
||||
void _urlredirectresponse(NPP instance, void* notifyData, NPBool allow);
|
||||
|
||||
NPError _initasyncsurface(NPP instance, NPSize* size, NPImageFormat format,
|
||||
void* initData, NPAsyncSurface* surface);
|
||||
|
||||
NPError _finalizeasyncsurface(NPP instance, NPAsyncSurface* surface);
|
||||
|
||||
void _setcurrentasyncsurface(NPP instance, NPAsyncSurface* surface,
|
||||
NPRect* changed);
|
||||
|
||||
} /* namespace parent */
|
||||
} /* namespace plugins */
|
||||
} /* namespace mozilla */
|
||||
|
||||
const char* PeekException();
|
||||
|
||||
void PopException();
|
||||
|
||||
class NPPStack {
|
||||
public:
|
||||
static NPP Peek() { return sCurrentNPP; }
|
||||
|
||||
protected:
|
||||
static NPP sCurrentNPP;
|
||||
};
|
||||
|
||||
// XXXjst: The NPPAutoPusher stack is a bit redundant now that
|
||||
// PluginDestructionGuard exists, and could thus be replaced by code
|
||||
// that uses the PluginDestructionGuard list of plugins on the
|
||||
// stack. But they're not identical, and to minimize code changes
|
||||
// we're keeping both for the moment, and making NPPAutoPusher inherit
|
||||
// the PluginDestructionGuard class to avoid having to keep two
|
||||
// separate objects on the stack since we always want a
|
||||
// PluginDestructionGuard where we use an NPPAutoPusher.
|
||||
|
||||
class MOZ_STACK_CLASS NPPAutoPusher : public NPPStack,
|
||||
protected PluginDestructionGuard {
|
||||
public:
|
||||
explicit NPPAutoPusher(NPP aNpp)
|
||||
: PluginDestructionGuard(aNpp), mOldNPP(sCurrentNPP) {
|
||||
NS_ASSERTION(aNpp, "Uh, null aNpp passed to NPPAutoPusher!");
|
||||
|
||||
sCurrentNPP = aNpp;
|
||||
}
|
||||
|
||||
~NPPAutoPusher() { sCurrentNPP = mOldNPP; }
|
||||
|
||||
private:
|
||||
NPP mOldNPP;
|
||||
};
|
||||
|
||||
class NPPExceptionAutoHolder {
|
||||
public:
|
||||
NPPExceptionAutoHolder();
|
||||
~NPPExceptionAutoHolder();
|
||||
|
||||
protected:
|
||||
char* mOldException;
|
||||
};
|
||||
|
||||
#endif // nsNPAPIPlugin_h_
|
|
@ -10,12 +10,9 @@
|
|||
#include "prenv.h"
|
||||
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsNPAPIPlugin.h"
|
||||
#include "nsNPAPIPluginStreamListener.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
|
@ -23,8 +20,6 @@
|
|||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsJSNPRuntime.h"
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIContent.h"
|
||||
|
@ -41,7 +36,6 @@ using namespace mozilla;
|
|||
using namespace mozilla::dom;
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::plugins::parent;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsNPAPIPluginInstance, nsIAudioChannelAgentCallback)
|
||||
|
@ -54,9 +48,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance()
|
|||
mCached(false),
|
||||
mUsesDOMForCursor(false),
|
||||
mInPluginInitCall(false),
|
||||
mPlugin(nullptr),
|
||||
mMIMEType(nullptr),
|
||||
mOwner(nullptr)
|
||||
mMIMEType(nullptr)
|
||||
#ifdef XP_MACOSX
|
||||
,
|
||||
mCurrentPluginEvent(nullptr)
|
||||
|
@ -106,395 +98,37 @@ uint32_t nsNPAPIPluginInstance::gInUnsafePluginCalls = 0;
|
|||
|
||||
void nsNPAPIPluginInstance::Destroy() {
|
||||
Stop();
|
||||
mPlugin = nullptr;
|
||||
mAudioChannelAgent = nullptr;
|
||||
}
|
||||
|
||||
TimeStamp nsNPAPIPluginInstance::StopTime() { return mStopTime; }
|
||||
|
||||
nsresult nsNPAPIPluginInstance::Initialize(nsNPAPIPlugin* aPlugin,
|
||||
nsPluginInstanceOwner* aOwner,
|
||||
const nsACString& aMIMEType) {
|
||||
AUTO_PROFILER_LABEL("nsNPAPIPlugin::Initialize", OTHER);
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsNPAPIPluginInstance::Initialize this=%p\n", this));
|
||||
|
||||
NS_ENSURE_ARG_POINTER(aPlugin);
|
||||
NS_ENSURE_ARG_POINTER(aOwner);
|
||||
|
||||
mPlugin = aPlugin;
|
||||
mOwner = aOwner;
|
||||
|
||||
if (!aMIMEType.IsEmpty()) {
|
||||
mMIMEType = ToNewCString(aMIMEType);
|
||||
}
|
||||
|
||||
return Start();
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::Stop() {
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsNPAPIPluginInstance::Stop this=%p\n", this));
|
||||
|
||||
// Make sure the plugin didn't leave popups enabled.
|
||||
if (mPopupStates.Length() > 0) {
|
||||
PopupBlocker::PopPopupControlState(PopupBlocker::openAbused);
|
||||
}
|
||||
|
||||
if (RUNNING != mRunning) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// clean up all outstanding timers
|
||||
for (uint32_t i = mTimers.Length(); i > 0; i--)
|
||||
UnscheduleTimer(mTimers[i - 1]->id);
|
||||
|
||||
// If there's code from this plugin instance on the stack, delay the
|
||||
// destroy.
|
||||
if (PluginDestructionGuard::DelayDestroy(this)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mRunning = DESTROYING;
|
||||
mStopTime = TimeStamp::Now();
|
||||
|
||||
// clean up open streams
|
||||
while (mStreamListeners.Length() > 0) {
|
||||
RefPtr<nsNPAPIPluginStreamListener> currentListener(mStreamListeners[0]);
|
||||
currentListener->CleanUpStream(NPRES_USER_BREAK);
|
||||
mStreamListeners.RemoveElement(currentListener);
|
||||
}
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
NPError error = NPERR_GENERIC_ERROR;
|
||||
if (pluginFunctions->destroy) {
|
||||
NPSavedData* sdata = 0;
|
||||
|
||||
NS_TRY_SAFE_CALL_RETURN(error, (*pluginFunctions->destroy)(&mNPP, &sdata),
|
||||
this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP Destroy called: this=%p, npp=%p, return=%d\n", this,
|
||||
&mNPP, error));
|
||||
}
|
||||
mRunning = DESTROYED;
|
||||
|
||||
nsJSNPRuntime::OnPluginDestroy(&mNPP);
|
||||
|
||||
if (error != NPERR_NO_ERROR)
|
||||
return NS_ERROR_FAILURE;
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult nsNPAPIPluginInstance::Stop() { return NS_ERROR_FAILURE; }
|
||||
|
||||
already_AddRefed<nsPIDOMWindowOuter> nsNPAPIPluginInstance::GetDOMWindow() {
|
||||
if (!mOwner) return nullptr;
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> kungFuDeathGrip(mOwner);
|
||||
|
||||
nsCOMPtr<Document> doc;
|
||||
kungFuDeathGrip->GetDocument(getter_AddRefs(doc));
|
||||
if (!doc) return nullptr;
|
||||
|
||||
RefPtr<nsPIDOMWindowOuter> window = doc->GetWindow();
|
||||
|
||||
return window.forget();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetTagType(nsPluginTagType* result) {
|
||||
if (!mOwner) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mOwner->GetTagType(result);
|
||||
}
|
||||
|
||||
nsTArray<nsNPAPIPluginStreamListener*>*
|
||||
nsNPAPIPluginInstance::StreamListeners() {
|
||||
return &mStreamListeners;
|
||||
}
|
||||
|
||||
nsTArray<nsPluginStreamListenerPeer*>*
|
||||
nsNPAPIPluginInstance::FileCachedStreamListeners() {
|
||||
return &mFileCachedStreamListeners;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::Start() {
|
||||
if (mRunning == RUNNING) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!mOwner) {
|
||||
MOZ_ASSERT(false, "Should not be calling Start() on unowned plugin.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
nsTArray<MozPluginParameter> attributes;
|
||||
nsTArray<MozPluginParameter> params;
|
||||
|
||||
nsPluginTagType tagtype;
|
||||
nsresult rv = GetTagType(&tagtype);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mOwner->GetAttributes(attributes);
|
||||
mOwner->GetParameters(params);
|
||||
} else {
|
||||
MOZ_ASSERT(false, "Failed to get tag type.");
|
||||
}
|
||||
|
||||
mCachedParamLength = attributes.Length() + 1 + params.Length();
|
||||
|
||||
// We add an extra entry "PARAM" as a separator between the attribute
|
||||
// and param values, but we don't count it if there are no <param> entries.
|
||||
// Legacy behavior quirk.
|
||||
uint32_t quirkParamLength =
|
||||
params.Length() ? mCachedParamLength : attributes.Length();
|
||||
|
||||
mCachedParamNames = (char**)moz_xmalloc(sizeof(char*) * mCachedParamLength);
|
||||
mCachedParamValues = (char**)moz_xmalloc(sizeof(char*) * mCachedParamLength);
|
||||
|
||||
for (uint32_t i = 0; i < attributes.Length(); i++) {
|
||||
mCachedParamNames[i] = ToNewUTF8String(attributes[i].mName);
|
||||
mCachedParamValues[i] = ToNewUTF8String(attributes[i].mValue);
|
||||
}
|
||||
|
||||
mCachedParamNames[attributes.Length()] = ToNewUTF8String(u"PARAM"_ns);
|
||||
mCachedParamValues[attributes.Length()] = nullptr;
|
||||
|
||||
for (uint32_t i = 0, pos = attributes.Length() + 1; i < params.Length();
|
||||
i++) {
|
||||
mCachedParamNames[pos] = ToNewUTF8String(params[i].mName);
|
||||
mCachedParamValues[pos] = ToNewUTF8String(params[i].mValue);
|
||||
pos++;
|
||||
}
|
||||
|
||||
const char* mimetype;
|
||||
NPError error = NPERR_GENERIC_ERROR;
|
||||
|
||||
GetMIMEType(&mimetype);
|
||||
|
||||
bool oldVal = mInPluginInitCall;
|
||||
mInPluginInitCall = true;
|
||||
|
||||
// Need this on the stack before calling NPP_New otherwise some callbacks that
|
||||
// the plugin may make could fail (NPN_HasProperty, for example).
|
||||
NPPAutoPusher autopush(&mNPP);
|
||||
|
||||
if (!mPlugin) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
// Mark this instance as running before calling NPP_New because the plugin may
|
||||
// call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
|
||||
// before returning. If the plugin returns failure, we'll clear it out below.
|
||||
mRunning = RUNNING;
|
||||
|
||||
nsresult newResult =
|
||||
library->NPP_New((char*)mimetype, &mNPP, quirkParamLength,
|
||||
mCachedParamNames, mCachedParamValues, nullptr, &error);
|
||||
mInPluginInitCall = oldVal;
|
||||
|
||||
NPP_PLUGIN_LOG(
|
||||
PLUGIN_LOG_NORMAL,
|
||||
("NPP New called: this=%p, npp=%p, mime=%s, argc=%d, return=%d\n", this,
|
||||
&mNPP, mimetype, quirkParamLength, error));
|
||||
|
||||
if (NS_FAILED(newResult) || error != NPERR_NO_ERROR) {
|
||||
mRunning = DESTROYED;
|
||||
nsJSNPRuntime::OnPluginDestroy(&mNPP);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return newResult;
|
||||
}
|
||||
nsresult nsNPAPIPluginInstance::Start() { return NS_ERROR_FAILURE; }
|
||||
|
||||
nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window) {
|
||||
// NPAPI plugins don't want a SetWindow(nullptr).
|
||||
if (!window || RUNNING != mRunning) return NS_OK;
|
||||
|
||||
#if MOZ_WIDGET_GTK
|
||||
// bug 108347, flash plugin on linux doesn't like window->width <= 0
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
if (pluginFunctions->setwindow) {
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
// XXX Turns out that NPPluginWindow and NPWindow are structurally
|
||||
// identical (on purpose!), so there's no need to make a copy.
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("nsNPAPIPluginInstance::SetWindow (about to call it) this=%p\n",
|
||||
this));
|
||||
|
||||
bool oldVal = mInPluginInitCall;
|
||||
mInPluginInitCall = true;
|
||||
|
||||
NPPAutoPusher nppPusher(&mNPP);
|
||||
|
||||
NPError error;
|
||||
NS_TRY_SAFE_CALL_RETURN(
|
||||
error, (*pluginFunctions->setwindow)(&mNPP, (NPWindow*)window), this,
|
||||
NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
// 'error' is only used if this is a logging-enabled build.
|
||||
// That is somewhat complex to check, so we just use "unused"
|
||||
// to suppress any compiler warnings in build configurations
|
||||
// where the logging is a no-op.
|
||||
mozilla::Unused << error;
|
||||
|
||||
mInPluginInitCall = oldVal;
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP SetWindow called: this=%p, [x=%d,y=%d,w=%d,h=%d], "
|
||||
"clip[t=%d,b=%d,l=%d,r=%d], return=%d\n",
|
||||
this, window->x, window->y, window->width, window->height,
|
||||
window->clipRect.top, window->clipRect.bottom,
|
||||
window->clipRect.left, window->clipRect.right, error));
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::NewStreamListener(
|
||||
const char* aURL, void* notifyData,
|
||||
nsNPAPIPluginStreamListener** listener) {
|
||||
RefPtr<nsNPAPIPluginStreamListener> sl =
|
||||
new nsNPAPIPluginStreamListener(this, notifyData, aURL);
|
||||
|
||||
mStreamListeners.AppendElement(sl);
|
||||
|
||||
sl.forget(listener);
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::Print(NPPrint* platformPrint) {
|
||||
NS_ENSURE_TRUE(platformPrint, NS_ERROR_NULL_POINTER);
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
NPPrint* thePrint = (NPPrint*)platformPrint;
|
||||
|
||||
// to be compatible with the older SDK versions and to match what
|
||||
// NPAPI and other browsers do, overwrite |window.type| field with one
|
||||
// more copy of |platformPrint|. See bug 113264
|
||||
uint16_t sdkmajorversion = (pluginFunctions->version & 0xff00) >> 8;
|
||||
uint16_t sdkminorversion = pluginFunctions->version & 0x00ff;
|
||||
if ((sdkmajorversion == 0) && (sdkminorversion < 11)) {
|
||||
// Let's copy platformPrint bytes over to where it was supposed to be
|
||||
// in older versions -- four bytes towards the beginning of the struct
|
||||
// but we should be careful about possible misalignments
|
||||
if (sizeof(NPWindowType) >= sizeof(void*)) {
|
||||
void* source = thePrint->print.embedPrint.platformPrint;
|
||||
void** destination = (void**)&(thePrint->print.embedPrint.window.type);
|
||||
*destination = source;
|
||||
} else {
|
||||
NS_ERROR("Incompatible OS for assignment");
|
||||
}
|
||||
}
|
||||
|
||||
if (pluginFunctions->print)
|
||||
NS_TRY_SAFE_CALL_VOID((*pluginFunctions->print)(&mNPP, thePrint), this,
|
||||
NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP PrintProc called: this=%p, pDC=%p, "
|
||||
"[x=%d,y=%d,w=%d,h=%d], clip[t=%d,b=%d,l=%d,r=%d]\n",
|
||||
this, platformPrint->print.embedPrint.platformPrint,
|
||||
platformPrint->print.embedPrint.window.x,
|
||||
platformPrint->print.embedPrint.window.y,
|
||||
platformPrint->print.embedPrint.window.width,
|
||||
platformPrint->print.embedPrint.window.height,
|
||||
platformPrint->print.embedPrint.window.clipRect.top,
|
||||
platformPrint->print.embedPrint.window.clipRect.bottom,
|
||||
platformPrint->print.embedPrint.window.clipRect.left,
|
||||
platformPrint->print.embedPrint.window.clipRect.right));
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::HandleEvent(
|
||||
void* event, int16_t* result, NSPluginCallReentry aSafeToReenterGecko) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AUTO_PROFILER_LABEL("nsNPAPIPluginInstance::HandleEvent", OTHER);
|
||||
|
||||
if (!event) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
int16_t tmpResult = kNPEventNotHandled;
|
||||
|
||||
if (pluginFunctions->event) {
|
||||
#ifdef XP_MACOSX
|
||||
mCurrentPluginEvent = event;
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
NS_TRY_SAFE_CALL_RETURN(tmpResult, (*pluginFunctions->event)(&mNPP, event),
|
||||
this, aSafeToReenterGecko);
|
||||
#else
|
||||
tmpResult = (*pluginFunctions->event)(&mNPP, event);
|
||||
#endif
|
||||
NPP_PLUGIN_LOG(
|
||||
PLUGIN_LOG_NOISY,
|
||||
("NPP HandleEvent called: this=%p, npp=%p, event=%p, return=%d\n", this,
|
||||
&mNPP, event, tmpResult));
|
||||
|
||||
if (result) *result = tmpResult;
|
||||
#ifdef XP_MACOSX
|
||||
mCurrentPluginEvent = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable,
|
||||
void* value) {
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
if (pluginFunctions->getvalue && RUNNING == mRunning) {
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
NPError pluginError = NPERR_GENERIC_ERROR;
|
||||
NS_TRY_SAFE_CALL_RETURN(
|
||||
pluginError, (*pluginFunctions->getvalue)(&mNPP, variable, value), this,
|
||||
NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
NPP_PLUGIN_LOG(
|
||||
PLUGIN_LOG_NORMAL,
|
||||
("NPP GetValue called: this=%p, npp=%p, var=%d, value=%p, return=%d\n",
|
||||
this, &mNPP, variable, value, pluginError));
|
||||
|
||||
if (pluginError == NPERR_NO_ERROR) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsNPAPIPlugin* nsNPAPIPluginInstance::GetPlugin() { return mPlugin; }
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetNPP(NPP* aNPP) {
|
||||
if (aNPP)
|
||||
*aNPP = &mNPP;
|
||||
|
@ -525,18 +159,10 @@ void nsNPAPIPluginInstance::SetDrawingModel(NPDrawingModel aModel) {
|
|||
mDrawingModel = aModel;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginInstance::RedrawPlugin() { mOwner->RedrawPlugin(); }
|
||||
void nsNPAPIPluginInstance::RedrawPlugin() {}
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel) {
|
||||
// the event model needs to be set for the object frame immediately
|
||||
if (!mOwner) {
|
||||
NS_WARNING("Trying to set event model without a plugin instance owner!");
|
||||
return;
|
||||
}
|
||||
|
||||
mOwner->SetEventModel(aModel);
|
||||
}
|
||||
void nsNPAPIPluginInstance::SetEventModel(NPEventModel aModel) {}
|
||||
#endif
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetDrawingModel(int32_t* aModel) {
|
||||
|
@ -545,69 +171,21 @@ nsresult nsNPAPIPluginInstance::GetDrawingModel(int32_t* aModel) {
|
|||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(bool* aDrawing) {
|
||||
#ifdef XP_MACOSX
|
||||
if (!mPlugin) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
|
||||
#else
|
||||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::ContentsScaleFactorChanged(
|
||||
double aContentsScaleFactor) {
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
if (!mPlugin) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
// We only need to call this if the plugin is running OOP.
|
||||
if (!library->IsOOP()) return NS_OK;
|
||||
|
||||
return library->ContentsScaleFactorChanged(&mNPP, aContentsScaleFactor);
|
||||
#else
|
||||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::CSSZoomFactorChanged(float aCSSZoomFactor) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of "
|
||||
"CSS Zoom Factor change this=%p\n",
|
||||
this));
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
if (!pluginFunctions->setvalue) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
NPError error;
|
||||
double value = static_cast<double>(aCSSZoomFactor);
|
||||
NS_TRY_SAFE_CALL_RETURN(
|
||||
error, (*pluginFunctions->setvalue)(&mNPP, NPNVCSSZoomFactor, &value),
|
||||
this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetJSObject(JSContext* cx,
|
||||
JSObject** outObject) {
|
||||
NPObject* npobj = nullptr;
|
||||
nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
|
||||
if (NS_FAILED(rv) || !npobj) return NS_ERROR_FAILURE;
|
||||
|
||||
*outObject = nsNPObjWrapper::GetNewOrUsed(&mNPP, cx, npobj);
|
||||
|
||||
_releaseobject(npobj);
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginInstance::SetCached(bool aCache) { mCached = aCache; }
|
||||
|
@ -624,109 +202,62 @@ nsresult nsNPAPIPluginInstance::IsWindowless(bool* isWindowless) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class MOZ_STACK_CLASS AutoPluginLibraryCall {
|
||||
public:
|
||||
explicit AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
|
||||
: mThis(aThis), mGuard(aThis), mLibrary(nullptr) {
|
||||
nsNPAPIPlugin* plugin = mThis->GetPlugin();
|
||||
if (plugin) mLibrary = plugin->GetLibrary();
|
||||
}
|
||||
explicit operator bool() { return !!mLibrary; }
|
||||
PluginLibrary* operator->() { return mLibrary; }
|
||||
|
||||
private:
|
||||
nsNPAPIPluginInstance* mThis;
|
||||
PluginDestructionGuard mGuard;
|
||||
PluginLibrary* mLibrary;
|
||||
};
|
||||
|
||||
nsresult nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
return library->AsyncSetWindow(&mNPP, window);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetImageContainer(ImageContainer** aContainer) {
|
||||
*aContainer = nullptr;
|
||||
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
return !library ? NS_ERROR_FAILURE
|
||||
: library->GetImageContainer(&mNPP, aContainer);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetImageSize(nsIntSize* aSize) {
|
||||
*aSize = nsIntSize(0, 0);
|
||||
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
return !library ? NS_ERROR_FAILURE : library->GetImageSize(&mNPP, aSize);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
nsresult nsNPAPIPluginInstance::GetScrollCaptureContainer(
|
||||
ImageContainer** aContainer) {
|
||||
*aContainer = nullptr;
|
||||
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
return !library ? NS_ERROR_FAILURE
|
||||
: library->GetScrollCaptureContainer(&mNPP, aContainer);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
void nsNPAPIPluginInstance::DidComposite() {
|
||||
if (RUNNING != mRunning) return;
|
||||
nsresult nsNPAPIPluginInstance::HandledWindowedPluginKeyEvent(
|
||||
const NativeEventData& aKeyEventData, bool aIsConsumed) {
|
||||
if (NS_WARN_IF(!mPlugin)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
library->DidComposite(&mNPP);
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
if (NS_WARN_IF(!library)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return library->HandledWindowedPluginKeyEvent(&mNPP, aKeyEventData,
|
||||
aIsConsumed);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginInstance::DidComposite() {}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::NotifyPainted(void) {
|
||||
MOZ_ASSERT_UNREACHABLE("Dead code, shouldn't be called.");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetIsOOP(bool* aIsAsync) {
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
*aIsAsync = library->IsOOP();
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::SetBackgroundUnknown() {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
return library->SetBackgroundUnknown(&mNPP);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::BeginUpdateBackground(
|
||||
nsIntRect* aRect, DrawTarget** aDrawTarget) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
return library->BeginUpdateBackground(&mNPP, *aRect, aDrawTarget);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::EndUpdateBackground(nsIntRect* aRect) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
AutoPluginLibraryCall library(this);
|
||||
if (!library) return NS_ERROR_FAILURE;
|
||||
|
||||
return library->EndUpdateBackground(&mNPP, *aRect);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::IsTransparent(bool* isTransparent) {
|
||||
|
@ -781,56 +312,15 @@ nsresult nsNPAPIPluginInstance::PopPopupsEnabledState() {
|
|||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetPluginAPIVersion(uint16_t* version) {
|
||||
NS_ENSURE_ARG_POINTER(version);
|
||||
|
||||
if (!mPlugin) return NS_ERROR_FAILURE;
|
||||
|
||||
if (!mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
*version = pluginFunctions->version;
|
||||
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::PrivateModeStateChanged(bool enabled) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of "
|
||||
"private mode state change this=%p\n",
|
||||
this));
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
if (!pluginFunctions->setvalue) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
NPError error;
|
||||
NPBool value = static_cast<NPBool>(enabled);
|
||||
NS_TRY_SAFE_CALL_RETURN(
|
||||
error, (*pluginFunctions->setvalue)(&mNPP, NPNVprivateModeBool, &value),
|
||||
this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::IsPrivateBrowsing(bool* aEnabled) {
|
||||
if (!mOwner) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<Document> doc;
|
||||
mOwner->GetDocument(getter_AddRefs(doc));
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> domwindow = doc->GetWindow();
|
||||
NS_ENSURE_TRUE(domwindow, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell = domwindow->GetDocShell();
|
||||
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
|
||||
*aEnabled = (loadContext && loadContext->UsePrivateBrowsing());
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
static void PluginTimerCallback(nsITimer* aTimer, void* aClosure) {
|
||||
|
@ -932,37 +422,19 @@ NPBool nsNPAPIPluginInstance::ConvertPoint(double sourceX, double sourceY,
|
|||
NPCoordinateSpace sourceSpace,
|
||||
double* destX, double* destY,
|
||||
NPCoordinateSpace destSpace) {
|
||||
if (mOwner) {
|
||||
return mOwner->ConvertPoint(sourceX, sourceY, sourceSpace, destX, destY,
|
||||
destSpace);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetDOMElement(Element** result) {
|
||||
if (!mOwner) {
|
||||
*result = nullptr;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return mOwner->GetDOMElement(result);
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::InvalidateRect(NPRect* invalidRect) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
if (!mOwner) return NS_ERROR_FAILURE;
|
||||
|
||||
return mOwner->InvalidateRect(invalidRect);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::InvalidateRegion(NPRegion invalidRegion) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
if (!mOwner) return NS_ERROR_FAILURE;
|
||||
|
||||
return mOwner->InvalidateRegion(invalidRegion);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetMIMEType(const char** result) {
|
||||
|
@ -974,88 +446,33 @@ nsresult nsNPAPIPluginInstance::GetMIMEType(const char** result) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsPluginInstanceOwner* nsNPAPIPluginInstance::GetOwner() { return mOwner; }
|
||||
|
||||
void nsNPAPIPluginInstance::SetOwner(nsPluginInstanceOwner* aOwner) {
|
||||
mOwner = aOwner;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::AsyncSetWindow(NPWindow& window) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginInstance::URLRedirectResponse(void* notifyData,
|
||||
NPBool allow) {
|
||||
if (!notifyData) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t listenerCount = mStreamListeners.Length();
|
||||
for (uint32_t i = 0; i < listenerCount; i++) {
|
||||
nsNPAPIPluginStreamListener* currentListener = mStreamListeners[i];
|
||||
if (currentListener->GetNotifyData() == notifyData) {
|
||||
currentListener->URLRedirectResponse(allow);
|
||||
}
|
||||
}
|
||||
}
|
||||
NPBool allow) {}
|
||||
|
||||
NPError nsNPAPIPluginInstance::InitAsyncSurface(NPSize* size,
|
||||
NPImageFormat format,
|
||||
void* initData,
|
||||
NPAsyncSurface* surface) {
|
||||
if (mOwner) {
|
||||
return mOwner->InitAsyncSurface(size, format, initData, surface);
|
||||
}
|
||||
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
NPError nsNPAPIPluginInstance::FinalizeAsyncSurface(NPAsyncSurface* surface) {
|
||||
if (mOwner) {
|
||||
return mOwner->FinalizeAsyncSurface(surface);
|
||||
}
|
||||
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginInstance::SetCurrentAsyncSurface(NPAsyncSurface* surface,
|
||||
NPRect* changed) {
|
||||
if (mOwner) {
|
||||
mOwner->SetCurrentAsyncSurface(surface, changed);
|
||||
}
|
||||
}
|
||||
NPRect* changed) {}
|
||||
|
||||
double nsNPAPIPluginInstance::GetContentsScaleFactor() {
|
||||
double scaleFactor = 1.0;
|
||||
if (mOwner) {
|
||||
mOwner->GetContentsScaleFactor(&scaleFactor);
|
||||
}
|
||||
return scaleFactor;
|
||||
}
|
||||
double nsNPAPIPluginInstance::GetContentsScaleFactor() { return -1.0; }
|
||||
|
||||
float nsNPAPIPluginInstance::GetCSSZoomFactor() {
|
||||
float zoomFactor = 1.0;
|
||||
if (mOwner) {
|
||||
mOwner->GetCSSZoomFactor(&zoomFactor);
|
||||
}
|
||||
return zoomFactor;
|
||||
}
|
||||
float nsNPAPIPluginInstance::GetCSSZoomFactor() { return -1.0f; }
|
||||
|
||||
nsresult nsNPAPIPluginInstance::GetRunID(uint32_t* aRunID) {
|
||||
if (NS_WARN_IF(!aRunID)) {
|
||||
return NS_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mPlugin)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
PluginLibrary* library = mPlugin->GetLibrary();
|
||||
if (!library) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return library->GetRunID(aRunID);
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::CreateAudioChannelAgentIfNeeded() {
|
||||
|
@ -1165,25 +582,5 @@ nsresult nsNPAPIPluginInstance::UpdateMutedIfNeeded() {
|
|||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::SetMuted(bool aIsMuted) {
|
||||
if (RUNNING != mRunning) return NS_OK;
|
||||
|
||||
PLUGIN_LOG(
|
||||
PLUGIN_LOG_NORMAL,
|
||||
("nsNPAPIPluginInstance informing plugin of mute state change this=%p\n",
|
||||
this));
|
||||
|
||||
if (!mPlugin || !mPlugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = mPlugin->PluginFuncs();
|
||||
|
||||
if (!pluginFunctions->setvalue) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(this);
|
||||
|
||||
NPError error;
|
||||
NPBool value = static_cast<NPBool>(aIsMuted);
|
||||
NS_TRY_SAFE_CALL_RETURN(
|
||||
error, (*pluginFunctions->setvalue)(&mNPP, NPNVmuteAudioBool, &value),
|
||||
this, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
return (error == NPERR_NO_ERROR) ? NS_OK : NS_ERROR_FAILURE;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
|
|
@ -11,29 +11,27 @@
|
|||
#include "nsTArray.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsIPluginInstanceOwner.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include <prinrval.h>
|
||||
#include "js/TypeDecls.h"
|
||||
#include "AudioChannelAgent.h"
|
||||
#include "npapi.h"
|
||||
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/PluginLibrary.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
#include "mozilla/dom/PopupBlocker.h"
|
||||
|
||||
class nsPluginStreamListenerPeer; // browser-initiated stream class
|
||||
class nsNPAPIPluginStreamListener; // plugin-initiated stream class
|
||||
class nsIPluginInstanceOwner;
|
||||
class nsIOutputStream;
|
||||
class nsPluginInstanceOwner;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
} // namespace dom
|
||||
namespace layers {
|
||||
class ImageContainer;
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
@ -79,17 +77,12 @@ class nsNPAPITimer {
|
|||
|
||||
class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
||||
public mozilla::SupportsWeakPtr {
|
||||
private:
|
||||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
|
||||
public:
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
|
||||
|
||||
nsresult Initialize(nsNPAPIPlugin* aPlugin, nsPluginInstanceOwner* aOwner,
|
||||
const nsACString& aMIMEType);
|
||||
nsresult Start();
|
||||
nsresult Stop();
|
||||
nsresult SetWindow(NPWindow* window);
|
||||
|
@ -127,8 +120,6 @@ class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
|||
nsresult GetScrollCaptureContainer(
|
||||
mozilla::layers::ImageContainer** aContainer);
|
||||
#endif
|
||||
nsPluginInstanceOwner* GetOwner();
|
||||
void SetOwner(nsPluginInstanceOwner* aOwner);
|
||||
void DidComposite();
|
||||
|
||||
bool HasAudioChannelAgent() const { return !!mAudioChannelAgent; }
|
||||
|
@ -138,8 +129,6 @@ class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
|||
|
||||
nsresult SetMuted(bool aIsMuted);
|
||||
|
||||
nsNPAPIPlugin* GetPlugin();
|
||||
|
||||
nsresult GetNPP(NPP* aNPP);
|
||||
|
||||
NPError SetWindowless(bool aWindowless);
|
||||
|
@ -159,9 +148,6 @@ class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
|||
void* GetCurrentEvent() { return mCurrentPluginEvent; }
|
||||
#endif
|
||||
|
||||
nsresult NewStreamListener(const char* aURL, void* notifyData,
|
||||
nsNPAPIPluginStreamListener** listener);
|
||||
|
||||
nsNPAPIPluginInstance();
|
||||
|
||||
// To be called when an instance becomes orphaned, when
|
||||
|
@ -199,10 +185,6 @@ class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
|||
NPCoordinateSpace sourceSpace, double* destX,
|
||||
double* destY, NPCoordinateSpace destSpace);
|
||||
|
||||
nsTArray<nsNPAPIPluginStreamListener*>* StreamListeners();
|
||||
|
||||
nsTArray<nsPluginStreamListenerPeer*>* FileCachedStreamListeners();
|
||||
|
||||
nsresult AsyncSetWindow(NPWindow& window);
|
||||
|
||||
void URLRedirectResponse(void* notifyData, NPBool allow);
|
||||
|
@ -238,8 +220,6 @@ class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
|||
protected:
|
||||
virtual ~nsNPAPIPluginInstance();
|
||||
|
||||
nsresult GetTagType(nsPluginTagType* result);
|
||||
|
||||
nsresult CreateAudioChannelAgentIfNeeded();
|
||||
|
||||
void NotifyAudibleStateChanged() const;
|
||||
|
@ -266,20 +246,10 @@ class nsNPAPIPluginInstance final : public nsIAudioChannelAgentCallback,
|
|||
bool mInPluginInitCall;
|
||||
|
||||
private:
|
||||
RefPtr<nsNPAPIPlugin> mPlugin;
|
||||
|
||||
nsTArray<nsNPAPIPluginStreamListener*> mStreamListeners;
|
||||
|
||||
nsTArray<nsPluginStreamListenerPeer*> mFileCachedStreamListeners;
|
||||
|
||||
nsTArray<mozilla::dom::PopupBlocker::PopupControlState> mPopupStates;
|
||||
|
||||
char* mMIMEType;
|
||||
|
||||
// Weak pointer to the owner. The owner nulls this out (by calling
|
||||
// InvalidateOwner()) when it's no longer our owner.
|
||||
nsPluginInstanceOwner* mOwner;
|
||||
|
||||
nsTArray<nsNPAPITimer*> mTimers;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
|
|
|
@ -1,776 +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 "nsNPAPIPluginStreamListener.h"
|
||||
#include "plstr.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsNPAPIPlugin.h"
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
#include "mozilla/ProfilerLabels.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
|
||||
nsNPAPIStreamWrapper::nsNPAPIStreamWrapper(
|
||||
nsIOutputStream* outputStream,
|
||||
nsNPAPIPluginStreamListener* streamListener) {
|
||||
mOutputStream = outputStream;
|
||||
mStreamListener = streamListener;
|
||||
|
||||
memset(&mNPStream, 0, sizeof(mNPStream));
|
||||
mNPStream.ndata = static_cast<void*>(this);
|
||||
}
|
||||
|
||||
nsNPAPIStreamWrapper::~nsNPAPIStreamWrapper() {
|
||||
if (mOutputStream) {
|
||||
mOutputStream->Close();
|
||||
}
|
||||
}
|
||||
|
||||
// nsNPAPIPluginStreamListener Methods
|
||||
NS_IMPL_ISUPPORTS(nsNPAPIPluginStreamListener, nsITimerCallback,
|
||||
nsIHTTPHeaderListener, nsINamed)
|
||||
|
||||
nsNPAPIPluginStreamListener::nsNPAPIPluginStreamListener(
|
||||
nsNPAPIPluginInstance* inst, void* notifyData, const char* aURL)
|
||||
: mStreamBuffer(nullptr),
|
||||
mNotifyURL(aURL ? PL_strdup(aURL) : nullptr),
|
||||
mInst(inst),
|
||||
mStreamBufferSize(0),
|
||||
mStreamBufferByteCount(0),
|
||||
mStreamState(eStreamStopped),
|
||||
mStreamCleanedUp(false),
|
||||
mCallNotify(notifyData ? true : false),
|
||||
mIsSuspended(false),
|
||||
mIsPluginInitJSStream(
|
||||
mInst->mInPluginInitCall && aURL &&
|
||||
strncmp(aURL, "javascript:", sizeof("javascript:") - 1) == 0),
|
||||
mRedirectDenied(false),
|
||||
mResponseHeaderBuf(nullptr),
|
||||
mStreamStopMode(eNormalStop),
|
||||
mPendingStopBindingStatus(NS_OK) {
|
||||
mNPStreamWrapper = new nsNPAPIStreamWrapper(nullptr, this);
|
||||
mNPStreamWrapper->mNPStream.notifyData = notifyData;
|
||||
}
|
||||
|
||||
nsNPAPIPluginStreamListener::~nsNPAPIPluginStreamListener() {
|
||||
// remove this from the plugin instance's stream list
|
||||
nsTArray<nsNPAPIPluginStreamListener*>* streamListeners =
|
||||
mInst->StreamListeners();
|
||||
streamListeners->RemoveElement(this);
|
||||
|
||||
// For those cases when NewStream is never called, we still may need
|
||||
// to fire a notification callback. Return network error as fallback
|
||||
// reason because for other cases, notify should have already been
|
||||
// called for other reasons elsewhere.
|
||||
CallURLNotify(NPRES_NETWORK_ERR);
|
||||
|
||||
// lets get rid of the buffer
|
||||
if (mStreamBuffer) {
|
||||
free(mStreamBuffer);
|
||||
mStreamBuffer = nullptr;
|
||||
}
|
||||
|
||||
if (mNotifyURL) PL_strfree(mNotifyURL);
|
||||
|
||||
if (mResponseHeaderBuf) PL_strfree(mResponseHeaderBuf);
|
||||
|
||||
if (mNPStreamWrapper) {
|
||||
delete mNPStreamWrapper;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason) {
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
|
||||
// Various bits of code in the rest of this method may result in the
|
||||
// deletion of this object. Use a KungFuDeathGrip to keep ourselves
|
||||
// alive during cleanup.
|
||||
RefPtr<nsNPAPIPluginStreamListener> kungFuDeathGrip(this);
|
||||
|
||||
if (mStreamCleanedUp) return NS_OK;
|
||||
|
||||
mStreamCleanedUp = true;
|
||||
|
||||
StopDataPump();
|
||||
|
||||
// Release any outstanding redirect callback.
|
||||
if (mHTTPRedirectCallback) {
|
||||
mHTTPRedirectCallback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
|
||||
mHTTPRedirectCallback = nullptr;
|
||||
}
|
||||
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->CancelRequests(NS_BINDING_ABORTED);
|
||||
mStreamListenerPeer = nullptr;
|
||||
}
|
||||
|
||||
if (!mInst || !mInst->CanFireNotifications()) return rv;
|
||||
|
||||
PluginDestructionGuard guard(mInst);
|
||||
|
||||
nsNPAPIPlugin* plugin = mInst->GetPlugin();
|
||||
if (!plugin || !plugin->GetLibrary()) return rv;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
|
||||
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
|
||||
if (mStreamState >= eNewStreamCalled && pluginFunctions->destroystream) {
|
||||
NPPAutoPusher nppPusher(npp);
|
||||
|
||||
NPError error;
|
||||
NS_TRY_SAFE_CALL_RETURN(error,
|
||||
(*pluginFunctions->destroystream)(
|
||||
npp, &mNPStreamWrapper->mNPStream, reason),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP DestroyStream called: this=%p, npp=%p, reason=%d, "
|
||||
"return=%d, url=%s\n",
|
||||
this, npp, reason, error, mNPStreamWrapper->mNPStream.url));
|
||||
|
||||
if (error == NPERR_NO_ERROR) rv = NS_OK;
|
||||
}
|
||||
|
||||
mStreamState = eStreamStopped;
|
||||
|
||||
// fire notification back to plugin, just like before
|
||||
CallURLNotify(reason);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginStreamListener::CallURLNotify(NPReason reason) {
|
||||
if (!mCallNotify || !mInst || !mInst->CanFireNotifications()) return;
|
||||
|
||||
PluginDestructionGuard guard(mInst);
|
||||
|
||||
mCallNotify = false; // only do this ONCE and prevent recursion
|
||||
|
||||
nsNPAPIPlugin* plugin = mInst->GetPlugin();
|
||||
if (!plugin || !plugin->GetLibrary()) return;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
|
||||
|
||||
if (pluginFunctions->urlnotify) {
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
|
||||
NS_TRY_SAFE_CALL_VOID(
|
||||
(*pluginFunctions->urlnotify)(npp, mNotifyURL, reason,
|
||||
mNPStreamWrapper->mNPStream.notifyData),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP URLNotify called: this=%p, npp=%p, notify=%p, "
|
||||
"reason=%d, url=%s\n",
|
||||
this, npp, mNPStreamWrapper->mNPStream.notifyData, reason,
|
||||
mNotifyURL));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginStreamListener::OnStartBinding(
|
||||
nsPluginStreamListenerPeer* streamPeer) {
|
||||
AUTO_PROFILER_LABEL("nsNPAPIPluginStreamListener::OnStartBinding", OTHER);
|
||||
if (!mInst || !mInst->CanFireNotifications() || mStreamCleanedUp)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(mInst);
|
||||
|
||||
nsNPAPIPlugin* plugin = mInst->GetPlugin();
|
||||
if (!plugin || !plugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
|
||||
|
||||
if (!pluginFunctions->newstream) return NS_ERROR_FAILURE;
|
||||
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
|
||||
char* contentType;
|
||||
uint16_t streamType = NP_NORMAL;
|
||||
NPError error;
|
||||
|
||||
streamPeer->GetURL(&mNPStreamWrapper->mNPStream.url);
|
||||
streamPeer->GetLength((uint32_t*)&(mNPStreamWrapper->mNPStream.end));
|
||||
streamPeer->GetLastModified(
|
||||
(uint32_t*)&(mNPStreamWrapper->mNPStream.lastmodified));
|
||||
streamPeer->GetContentType(&contentType);
|
||||
|
||||
if (!mResponseHeaders.IsEmpty()) {
|
||||
mResponseHeaderBuf = PL_strdup(mResponseHeaders.get());
|
||||
mNPStreamWrapper->mNPStream.headers = mResponseHeaderBuf;
|
||||
}
|
||||
|
||||
mStreamListenerPeer = streamPeer;
|
||||
|
||||
NPPAutoPusher nppPusher(npp);
|
||||
|
||||
NS_TRY_SAFE_CALL_RETURN(error,
|
||||
(*pluginFunctions->newstream)(
|
||||
npp, (char*)contentType,
|
||||
&mNPStreamWrapper->mNPStream, false, &streamType),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP NewStream called: this=%p, npp=%p, mime=%s, seek=%d, "
|
||||
"type=%d, return=%d, url=%s\n",
|
||||
this, npp, (char*)contentType, false, streamType, error,
|
||||
mNPStreamWrapper->mNPStream.url));
|
||||
|
||||
if (error != NPERR_NO_ERROR) return NS_ERROR_FAILURE;
|
||||
|
||||
mStreamState = eNewStreamCalled;
|
||||
|
||||
if (streamType != NP_NORMAL) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginStreamListener::SuspendRequest() {
|
||||
NS_ASSERTION(!mIsSuspended, "Suspending a request that's already suspended!");
|
||||
|
||||
nsresult rv = StartDataPump();
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
mIsSuspended = true;
|
||||
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->SuspendRequests();
|
||||
}
|
||||
}
|
||||
|
||||
void nsNPAPIPluginStreamListener::ResumeRequest() {
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->ResumeRequests();
|
||||
}
|
||||
mIsSuspended = false;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginStreamListener::StartDataPump() {
|
||||
// Start pumping data to the plugin every 100ms until it obeys and
|
||||
// eats the data.
|
||||
return NS_NewTimerWithCallback(getter_AddRefs(mDataPumpTimer), this, 100,
|
||||
nsITimer::TYPE_REPEATING_SLACK);
|
||||
}
|
||||
|
||||
void nsNPAPIPluginStreamListener::StopDataPump() {
|
||||
if (mDataPumpTimer) {
|
||||
mDataPumpTimer->Cancel();
|
||||
mDataPumpTimer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if a javascript: load that was started while the plugin
|
||||
// was being initialized is still in progress.
|
||||
bool nsNPAPIPluginStreamListener::PluginInitJSLoadInProgress() {
|
||||
if (!mInst) return false;
|
||||
|
||||
nsTArray<nsNPAPIPluginStreamListener*>* streamListeners =
|
||||
mInst->StreamListeners();
|
||||
for (unsigned int i = 0; i < streamListeners->Length(); i++) {
|
||||
if (streamListeners->ElementAt(i)->mIsPluginInitJSStream) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// This method is called when there's more data available off the
|
||||
// network, but it's also called from our data pump when we're feeding
|
||||
// the plugin data that we already got off the network, but the plugin
|
||||
// was unable to consume it at the point it arrived. In the case when
|
||||
// the plugin pump calls this method, the input argument will be null,
|
||||
// and the length will be the number of bytes available in our
|
||||
// internal buffer.
|
||||
nsresult nsNPAPIPluginStreamListener::OnDataAvailable(
|
||||
nsPluginStreamListenerPeer* streamPeer, nsIInputStream* input,
|
||||
uint32_t length) {
|
||||
if (!length || !mInst || !mInst->CanFireNotifications())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(mInst);
|
||||
|
||||
// Just in case the caller switches plugin info on us.
|
||||
mStreamListenerPeer = streamPeer;
|
||||
|
||||
nsNPAPIPlugin* plugin = mInst->GetPlugin();
|
||||
if (!plugin || !plugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
|
||||
|
||||
// check out if plugin implements NPP_Write call
|
||||
if (!pluginFunctions->write)
|
||||
return NS_ERROR_FAILURE; // it'll cancel necko transaction
|
||||
|
||||
if (!mStreamBuffer) {
|
||||
// To optimize the mem usage & performance we have to allocate
|
||||
// mStreamBuffer here in first ODA when length of data available
|
||||
// in input stream is known. mStreamBuffer will be freed in DTOR.
|
||||
// we also have to remember the size of that buff to make safe
|
||||
// consecutive Read() calls form input stream into our buff.
|
||||
|
||||
uint32_t contentLength;
|
||||
streamPeer->GetLength(&contentLength);
|
||||
|
||||
mStreamBufferSize = std::max(length, contentLength);
|
||||
|
||||
// Limit the size of the initial buffer to MAX_PLUGIN_NECKO_BUFFER
|
||||
// (16k). This buffer will grow if needed, as in the case where
|
||||
// we're getting data faster than the plugin can process it.
|
||||
mStreamBufferSize =
|
||||
std::min(mStreamBufferSize, uint32_t(MAX_PLUGIN_NECKO_BUFFER));
|
||||
|
||||
mStreamBuffer = (char*)malloc(mStreamBufferSize);
|
||||
if (!mStreamBuffer) return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// prepare NPP_ calls params
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
|
||||
int32_t streamPosition;
|
||||
streamPeer->GetStreamOffset(&streamPosition);
|
||||
int32_t streamOffset = streamPosition;
|
||||
|
||||
if (input) {
|
||||
streamOffset += length;
|
||||
|
||||
// Set new stream offset for the next ODA call regardless of how
|
||||
// following NPP_Write call will behave we pretend to consume all
|
||||
// data from the input stream. It's possible that current steam
|
||||
// position will be overwritten from NPP_RangeRequest call made
|
||||
// from NPP_Write, so we cannot call SetStreamOffset after
|
||||
// NPP_Write.
|
||||
//
|
||||
// Note: there is a special case when data flow should be
|
||||
// temporarily stopped if NPP_WriteReady returns 0 (bug #89270)
|
||||
streamPeer->SetStreamOffset(streamOffset);
|
||||
|
||||
// set new end in case the content is compressed
|
||||
// initial end is less than end of decompressed stream
|
||||
// and some plugins (e.g. acrobat) can fail.
|
||||
if ((int32_t)mNPStreamWrapper->mNPStream.end < streamOffset)
|
||||
mNPStreamWrapper->mNPStream.end = streamOffset;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
while (NS_SUCCEEDED(rv) && length > 0) {
|
||||
if (input && length) {
|
||||
if (mStreamBufferSize < mStreamBufferByteCount + length) {
|
||||
// We're in the ::OnDataAvailable() call that we might get
|
||||
// after suspending a request, or we suspended the request
|
||||
// from within this ::OnDataAvailable() call while there's
|
||||
// still data in the input, or we have resumed a previously
|
||||
// suspended request and our buffer is already full, and we
|
||||
// don't have enough space to store what we got off the network.
|
||||
// Reallocate our internal buffer.
|
||||
mStreamBufferSize = mStreamBufferByteCount + length;
|
||||
char* buf = (char*)realloc(mStreamBuffer, mStreamBufferSize);
|
||||
if (!buf) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
mStreamBuffer = buf;
|
||||
}
|
||||
|
||||
uint32_t bytesToRead =
|
||||
std::min(length, mStreamBufferSize - mStreamBufferByteCount);
|
||||
MOZ_ASSERT(bytesToRead > 0);
|
||||
|
||||
uint32_t amountRead = 0;
|
||||
rv = input->Read(mStreamBuffer + mStreamBufferByteCount, bytesToRead,
|
||||
&amountRead);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (amountRead == 0) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"input->Read() returns no data, it's almost "
|
||||
"impossible to get here");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mStreamBufferByteCount += amountRead;
|
||||
length -= amountRead;
|
||||
} else {
|
||||
// No input, nothing to read. Set length to 0 so that we don't
|
||||
// keep iterating through this outer loop any more.
|
||||
|
||||
length = 0;
|
||||
}
|
||||
|
||||
// Temporary pointer to the beginning of the data we're writing as
|
||||
// we loop and feed the plugin data.
|
||||
char* ptrStreamBuffer = mStreamBuffer;
|
||||
|
||||
// it is possible plugin's NPP_Write() returns 0 byte consumed. We
|
||||
// use zeroBytesWriteCount to count situation like this and break
|
||||
// the loop
|
||||
int32_t zeroBytesWriteCount = 0;
|
||||
|
||||
// mStreamBufferByteCount tells us how many bytes there are in the
|
||||
// buffer. WriteReady returns to us how many bytes the plugin is
|
||||
// ready to handle.
|
||||
while (mStreamBufferByteCount > 0) {
|
||||
int32_t numtowrite;
|
||||
if (pluginFunctions->writeready) {
|
||||
NPPAutoPusher nppPusher(npp);
|
||||
|
||||
NS_TRY_SAFE_CALL_RETURN(
|
||||
numtowrite,
|
||||
(*pluginFunctions->writeready)(npp, &mNPStreamWrapper->mNPStream),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
NPP_PLUGIN_LOG(
|
||||
PLUGIN_LOG_NOISY,
|
||||
("NPP WriteReady called: this=%p, npp=%p, "
|
||||
"return(towrite)=%d, url=%s\n",
|
||||
this, npp, numtowrite, mNPStreamWrapper->mNPStream.url));
|
||||
|
||||
if (mStreamState == eStreamStopped) {
|
||||
// The plugin called NPN_DestroyStream() from within
|
||||
// NPP_WriteReady(), kill the stream.
|
||||
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
// if WriteReady returned 0, the plugin is not ready to handle
|
||||
// the data, suspend the stream (if it isn't already
|
||||
// suspended).
|
||||
//
|
||||
// Also suspend the stream if the stream we're loading is not
|
||||
// a javascript: URL load that was initiated during plugin
|
||||
// initialization and there currently is such a stream
|
||||
// loading. This is done to work around a Windows Media Player
|
||||
// plugin bug where it can't deal with being fed data for
|
||||
// other streams while it's waiting for data from the
|
||||
// javascript: URL loads it requests during
|
||||
// initialization. See bug 386493 for more details.
|
||||
|
||||
if (numtowrite <= 0 ||
|
||||
(!mIsPluginInitJSStream && PluginInitJSLoadInProgress())) {
|
||||
if (!mIsSuspended) {
|
||||
SuspendRequest();
|
||||
}
|
||||
|
||||
// Break out of the inner loop, but keep going through the
|
||||
// outer loop in case there's more data to read from the
|
||||
// input stream.
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
numtowrite = std::min(numtowrite, mStreamBufferByteCount);
|
||||
} else {
|
||||
// if WriteReady is not supported by the plugin, just write
|
||||
// the whole buffer
|
||||
numtowrite = mStreamBufferByteCount;
|
||||
}
|
||||
|
||||
NPPAutoPusher nppPusher(npp);
|
||||
|
||||
int32_t writeCount = 0; // bytes consumed by plugin instance
|
||||
NS_TRY_SAFE_CALL_RETURN(writeCount,
|
||||
(*pluginFunctions->write)(
|
||||
npp, &mNPStreamWrapper->mNPStream,
|
||||
streamPosition, numtowrite, ptrStreamBuffer),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(
|
||||
PLUGIN_LOG_NOISY,
|
||||
("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, "
|
||||
"buf=%.*s, return(written)=%d, url=%s\n",
|
||||
this, npp, streamPosition, numtowrite, numtowrite, ptrStreamBuffer,
|
||||
writeCount, mNPStreamWrapper->mNPStream.url));
|
||||
|
||||
if (mStreamState == eStreamStopped) {
|
||||
// The plugin called NPN_DestroyStream() from within
|
||||
// NPP_Write(), kill the stream.
|
||||
return NS_BINDING_ABORTED;
|
||||
}
|
||||
|
||||
if (writeCount > 0) {
|
||||
NS_ASSERTION(writeCount <= mStreamBufferByteCount,
|
||||
"Plugin read past the end of the available data!");
|
||||
|
||||
writeCount = std::min(writeCount, mStreamBufferByteCount);
|
||||
mStreamBufferByteCount -= writeCount;
|
||||
|
||||
streamPosition += writeCount;
|
||||
|
||||
zeroBytesWriteCount = 0;
|
||||
|
||||
if (mStreamBufferByteCount > 0) {
|
||||
// This alignment code is most likely bogus, but we'll leave
|
||||
// it in for now in case it matters for some plugins on some
|
||||
// architectures. Who knows...
|
||||
if (writeCount % sizeof(intptr_t)) {
|
||||
// memmove will take care about alignment
|
||||
memmove(mStreamBuffer, ptrStreamBuffer + writeCount,
|
||||
mStreamBufferByteCount);
|
||||
ptrStreamBuffer = mStreamBuffer;
|
||||
} else {
|
||||
// if aligned we can use ptrStreamBuffer += to eliminate
|
||||
// memmove()
|
||||
ptrStreamBuffer += writeCount;
|
||||
}
|
||||
}
|
||||
} else if (writeCount == 0) {
|
||||
// if NPP_Write() returns writeCount == 0 lets say 3 times in
|
||||
// a row, suspend the request and continue feeding the plugin
|
||||
// the data we got so far. Once that data is consumed, we'll
|
||||
// resume the request.
|
||||
if (mIsSuspended || ++zeroBytesWriteCount == 3) {
|
||||
if (!mIsSuspended) {
|
||||
SuspendRequest();
|
||||
}
|
||||
|
||||
// Break out of the for loop, but keep going through the
|
||||
// while loop in case there's more data to read from the
|
||||
// input stream.
|
||||
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Something's really wrong, kill the stream.
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
break;
|
||||
}
|
||||
} // end of inner while loop
|
||||
|
||||
if (mStreamBufferByteCount && mStreamBuffer != ptrStreamBuffer) {
|
||||
memmove(mStreamBuffer, ptrStreamBuffer, mStreamBufferByteCount);
|
||||
}
|
||||
}
|
||||
|
||||
if (streamPosition != streamOffset) {
|
||||
// The plugin didn't consume all available data, or consumed some
|
||||
// of our cached data while we're pumping cached data. Adjust the
|
||||
// plugin info's stream offset to match reality, except if the
|
||||
// plugin info's stream offset was set by a re-entering
|
||||
// NPN_RequestRead() call.
|
||||
|
||||
int32_t postWriteStreamPosition;
|
||||
streamPeer->GetStreamOffset(&postWriteStreamPosition);
|
||||
|
||||
if (postWriteStreamPosition == streamOffset) {
|
||||
streamPeer->SetStreamOffset(streamPosition);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginStreamListener::OnFileAvailable(
|
||||
nsPluginStreamListenerPeer* streamPeer, const char* fileName) {
|
||||
if (!mInst || !mInst->CanFireNotifications()) return NS_ERROR_FAILURE;
|
||||
|
||||
PluginDestructionGuard guard(mInst);
|
||||
|
||||
nsNPAPIPlugin* plugin = mInst->GetPlugin();
|
||||
if (!plugin || !plugin->GetLibrary()) return NS_ERROR_FAILURE;
|
||||
|
||||
NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
|
||||
|
||||
if (!pluginFunctions->asfile) return NS_ERROR_FAILURE;
|
||||
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
|
||||
NS_TRY_SAFE_CALL_VOID(
|
||||
(*pluginFunctions->asfile)(npp, &mNPStreamWrapper->mNPStream, fileName),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
|
||||
NPP_PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("NPP StreamAsFile called: this=%p, npp=%p, url=%s, file=%s\n",
|
||||
this, npp, mNPStreamWrapper->mNPStream.url, fileName));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginStreamListener::OnStopBinding(
|
||||
nsPluginStreamListenerPeer* streamPeer, nsresult status) {
|
||||
if (NS_FAILED(status)) {
|
||||
// The stream was destroyed, or died for some reason. Make sure we
|
||||
// cancel the underlying request.
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->CancelRequests(status);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mInst || !mInst->CanFireNotifications()) {
|
||||
StopDataPump();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// We need to detect that the stop is due to async stream init completion.
|
||||
if (mStreamStopMode == eDoDeferredStop) {
|
||||
// We shouldn't be delivering this until async init is done
|
||||
mStreamStopMode = eStopPending;
|
||||
mPendingStopBindingStatus = status;
|
||||
if (!mDataPumpTimer) {
|
||||
StartDataPump();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
StopDataPump();
|
||||
|
||||
NPReason reason = NS_FAILED(status) ? NPRES_NETWORK_ERR : NPRES_DONE;
|
||||
if (mRedirectDenied || status == NS_BINDING_ABORTED) {
|
||||
reason = NPRES_USER_BREAK;
|
||||
}
|
||||
|
||||
// The following code can result in the deletion of 'this'. Don't
|
||||
// assume we are alive after this!
|
||||
return CleanUpStream(reason);
|
||||
}
|
||||
|
||||
bool nsNPAPIPluginStreamListener::MaybeRunStopBinding() {
|
||||
if (mIsSuspended || mStreamStopMode != eStopPending) {
|
||||
return false;
|
||||
}
|
||||
OnStopBinding(mStreamListenerPeer, mPendingStopBindingStatus);
|
||||
mStreamStopMode = eNormalStop;
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginStreamListener::Notify(nsITimer* aTimer) {
|
||||
NS_ASSERTION(aTimer == mDataPumpTimer, "Uh, wrong timer?");
|
||||
|
||||
int32_t oldStreamBufferByteCount = mStreamBufferByteCount;
|
||||
|
||||
nsresult rv =
|
||||
OnDataAvailable(mStreamListenerPeer, nullptr, mStreamBufferByteCount);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// We ran into an error, no need to keep firing this timer then.
|
||||
StopDataPump();
|
||||
MaybeRunStopBinding();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mStreamBufferByteCount != oldStreamBufferByteCount &&
|
||||
((mStreamState == eStreamTypeSet && mStreamBufferByteCount < 1024) ||
|
||||
mStreamBufferByteCount == 0)) {
|
||||
// The plugin read some data and we've got less than 1024 bytes in
|
||||
// our buffer (or its empty and the stream is already
|
||||
// done). Resume the request so that we get more data off the
|
||||
// network.
|
||||
ResumeRequest();
|
||||
// Necko will pump data now that we've resumed the request.
|
||||
StopDataPump();
|
||||
}
|
||||
|
||||
MaybeRunStopBinding();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginStreamListener::GetName(nsACString& aName) {
|
||||
aName.AssignLiteral("nsNPAPIPluginStreamListener");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginStreamListener::StatusLine(const char* line) {
|
||||
mResponseHeaders.Append(line);
|
||||
mResponseHeaders.Append('\n');
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNPAPIPluginStreamListener::NewResponseHeader(const char* headerName,
|
||||
const char* headerValue) {
|
||||
mResponseHeaders.Append(headerName);
|
||||
mResponseHeaders.AppendLiteral(": ");
|
||||
mResponseHeaders.Append(headerValue);
|
||||
mResponseHeaders.Append('\n');
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsNPAPIPluginStreamListener::HandleRedirectNotification(
|
||||
nsIChannel* oldChannel, nsIChannel* newChannel,
|
||||
nsIAsyncVerifyRedirectCallback* callback) {
|
||||
nsCOMPtr<nsIHttpChannel> oldHttpChannel = do_QueryInterface(oldChannel);
|
||||
nsCOMPtr<nsIHttpChannel> newHttpChannel = do_QueryInterface(newChannel);
|
||||
if (!oldHttpChannel || !newHttpChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mInst || !mInst->CanFireNotifications()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsNPAPIPlugin* plugin = mInst->GetPlugin();
|
||||
if (!plugin || !plugin->GetLibrary()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NPPluginFuncs* pluginFunctions = plugin->PluginFuncs();
|
||||
if (!pluginFunctions->urlredirectnotify) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A non-null closure is required for redirect handling support.
|
||||
if (mNPStreamWrapper->mNPStream.notifyData) {
|
||||
uint32_t status;
|
||||
if (NS_SUCCEEDED(oldHttpChannel->GetResponseStatus(&status))) {
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_SUCCEEDED(newHttpChannel->GetURI(getter_AddRefs(uri))) && uri) {
|
||||
nsAutoCString spec;
|
||||
if (NS_SUCCEEDED(uri->GetAsciiSpec(spec))) {
|
||||
// At this point the plugin will be responsible for making the
|
||||
// callback so save the callback object.
|
||||
mHTTPRedirectCallback = callback;
|
||||
|
||||
NPP npp;
|
||||
mInst->GetNPP(&npp);
|
||||
#if defined(XP_WIN)
|
||||
NS_TRY_SAFE_CALL_VOID(
|
||||
(*pluginFunctions->urlredirectnotify)(
|
||||
npp, spec.get(), static_cast<int32_t>(status),
|
||||
mNPStreamWrapper->mNPStream.notifyData),
|
||||
mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO);
|
||||
#else
|
||||
(*pluginFunctions->urlredirectnotify)(
|
||||
npp, spec.get(), static_cast<int32_t>(status),
|
||||
mNPStreamWrapper->mNPStream.notifyData);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback->OnRedirectVerifyCallback(NS_ERROR_FAILURE);
|
||||
return true;
|
||||
}
|
||||
|
||||
void nsNPAPIPluginStreamListener::URLRedirectResponse(NPBool allow) {
|
||||
if (mHTTPRedirectCallback) {
|
||||
mHTTPRedirectCallback->OnRedirectVerifyCallback(allow ? NS_OK
|
||||
: NS_ERROR_FAILURE);
|
||||
mRedirectDenied = !allow;
|
||||
mHTTPRedirectCallback = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void* nsNPAPIPluginStreamListener::GetNotifyData() {
|
||||
if (mNPStreamWrapper) {
|
||||
return mNPStreamWrapper->mNPStream.notifyData;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
|
@ -1,126 +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 nsNPAPIPluginStreamListener_h_
|
||||
#define nsNPAPIPluginStreamListener_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIHTTPHeaderListener.h"
|
||||
#include "nsINamed.h"
|
||||
#include "nsITimer.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIAsyncVerifyRedirectCallback.h"
|
||||
#include "mozilla/PluginLibrary.h"
|
||||
|
||||
#define MAX_PLUGIN_NECKO_BUFFER 16384
|
||||
|
||||
class nsPluginStreamListenerPeer;
|
||||
class nsNPAPIPluginStreamListener;
|
||||
class nsNPAPIPluginInstance;
|
||||
class nsIChannel;
|
||||
|
||||
class nsNPAPIStreamWrapper {
|
||||
public:
|
||||
nsNPAPIStreamWrapper(nsIOutputStream* outputStream,
|
||||
nsNPAPIPluginStreamListener* streamListener);
|
||||
~nsNPAPIStreamWrapper();
|
||||
|
||||
nsIOutputStream* GetOutputStream() { return mOutputStream.get(); }
|
||||
nsNPAPIPluginStreamListener* GetStreamListener() { return mStreamListener; }
|
||||
|
||||
NPStream mNPStream;
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIOutputStream>
|
||||
mOutputStream; // only valid if not browser initiated
|
||||
nsNPAPIPluginStreamListener*
|
||||
mStreamListener; // only valid if browser initiated
|
||||
};
|
||||
|
||||
class nsNPAPIPluginStreamListener : public nsITimerCallback,
|
||||
public nsIHTTPHeaderListener,
|
||||
public nsINamed {
|
||||
private:
|
||||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIHTTPHEADERLISTENER
|
||||
NS_DECL_NSINAMED
|
||||
|
||||
nsNPAPIPluginStreamListener(nsNPAPIPluginInstance* inst, void* notifyData,
|
||||
const char* aURL);
|
||||
|
||||
nsresult OnStartBinding(nsPluginStreamListenerPeer* streamPeer);
|
||||
nsresult OnDataAvailable(nsPluginStreamListenerPeer* streamPeer,
|
||||
nsIInputStream* input, uint32_t length);
|
||||
nsresult OnFileAvailable(nsPluginStreamListenerPeer* streamPeer,
|
||||
const char* fileName);
|
||||
nsresult OnStopBinding(nsPluginStreamListenerPeer* streamPeer,
|
||||
nsresult status);
|
||||
|
||||
bool IsStarted();
|
||||
nsresult CleanUpStream(NPReason reason);
|
||||
void CallURLNotify(NPReason reason);
|
||||
void SetCallNotify(bool aCallNotify) { mCallNotify = aCallNotify; }
|
||||
void SuspendRequest();
|
||||
void ResumeRequest();
|
||||
nsresult StartDataPump();
|
||||
void StopDataPump();
|
||||
bool PluginInitJSLoadInProgress();
|
||||
|
||||
void* GetNotifyData();
|
||||
nsPluginStreamListenerPeer* GetStreamListenerPeer() {
|
||||
return mStreamListenerPeer;
|
||||
}
|
||||
void SetStreamListenerPeer(nsPluginStreamListenerPeer* aPeer) {
|
||||
mStreamListenerPeer = aPeer;
|
||||
}
|
||||
|
||||
// Returns true if the redirect will be handled by NPAPI, false otherwise.
|
||||
bool HandleRedirectNotification(nsIChannel* oldChannel,
|
||||
nsIChannel* newChannel,
|
||||
nsIAsyncVerifyRedirectCallback* callback);
|
||||
void URLRedirectResponse(NPBool allow);
|
||||
|
||||
protected:
|
||||
enum StreamState {
|
||||
eStreamStopped = 0, // The stream is stopped
|
||||
eNewStreamCalled, // NPP_NewStream was called but has not completed yet
|
||||
eStreamTypeSet // The stream is fully initialized
|
||||
};
|
||||
|
||||
enum StreamStopMode { eNormalStop = 0, eDoDeferredStop, eStopPending };
|
||||
|
||||
virtual ~nsNPAPIPluginStreamListener();
|
||||
bool MaybeRunStopBinding();
|
||||
|
||||
char* mStreamBuffer;
|
||||
char* mNotifyURL;
|
||||
RefPtr<nsNPAPIPluginInstance> mInst;
|
||||
nsNPAPIStreamWrapper* mNPStreamWrapper;
|
||||
uint32_t mStreamBufferSize;
|
||||
int32_t mStreamBufferByteCount;
|
||||
StreamState mStreamState;
|
||||
bool mStreamCleanedUp;
|
||||
bool mCallNotify;
|
||||
bool mIsSuspended;
|
||||
bool mIsPluginInitJSStream;
|
||||
bool mRedirectDenied;
|
||||
nsCString mResponseHeaders;
|
||||
char* mResponseHeaderBuf;
|
||||
nsCOMPtr<nsITimer> mDataPumpTimer;
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mHTTPRedirectCallback;
|
||||
StreamStopMode mStreamStopMode;
|
||||
nsresult mPendingStopBindingStatus;
|
||||
|
||||
public:
|
||||
RefPtr<nsPluginStreamListenerPeer> mStreamListenerPeer;
|
||||
};
|
||||
|
||||
#endif // nsNPAPIPluginStreamListener_h_
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -14,7 +14,6 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "prlink.h"
|
||||
#include "nsIPluginTag.h"
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsTArray.h"
|
||||
|
@ -26,7 +25,6 @@
|
|||
#include "nsIIDNService.h"
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include <minwindef.h>
|
||||
|
@ -42,16 +40,11 @@ class ContentParent;
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
class nsNPAPIPlugin;
|
||||
class nsIFile;
|
||||
class nsIChannel;
|
||||
class nsPluginNativeWindow;
|
||||
class nsObjectLoadingContent;
|
||||
class nsPluginInstanceOwner;
|
||||
class nsPluginUnloadRunnable;
|
||||
class nsNPAPIPluginInstance;
|
||||
class nsNPAPIPluginStreamListener;
|
||||
class nsIPluginInstanceOwner;
|
||||
class nsIInputStream;
|
||||
class nsIStreamListener;
|
||||
#ifndef npapi_h_
|
||||
|
@ -97,27 +90,11 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
void GetPlugins(nsTArray<nsCOMPtr<nsIInternalPluginTag>>& aPluginArray,
|
||||
bool aIncludeDisabled = false);
|
||||
|
||||
nsresult GetURL(nsISupports* pluginInst, const char* url, const char* target,
|
||||
nsNPAPIPluginStreamListener* streamListener,
|
||||
const char* altHost, const char* referrer,
|
||||
bool forceJSEnabled);
|
||||
nsresult PostURL(nsISupports* pluginInst, const char* url,
|
||||
uint32_t postDataLen, const char* postData,
|
||||
const char* target,
|
||||
nsNPAPIPluginStreamListener* streamListener,
|
||||
const char* altHost, const char* referrer,
|
||||
bool forceJSEnabled, uint32_t postHeadersLength,
|
||||
const char* postHeaders);
|
||||
|
||||
nsresult UserAgent(const char** retstring);
|
||||
nsresult ParsePostBufferToFixHeaders(const char* inPostData,
|
||||
uint32_t inPostDataLen,
|
||||
char** outPostData,
|
||||
uint32_t* outPostDataLen);
|
||||
nsresult NewPluginNativeWindow(nsPluginNativeWindow** aPluginNativeWindow);
|
||||
|
||||
void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, bool isVisible);
|
||||
void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame);
|
||||
|
||||
nsresult GetPluginName(nsNPAPIPluginInstance* aPluginInstance,
|
||||
const char** aPluginName);
|
||||
|
@ -125,21 +102,6 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
nsresult GetPluginTagForInstance(nsNPAPIPluginInstance* aPluginInstance,
|
||||
nsIPluginTag** aPluginTag);
|
||||
|
||||
nsresult NewPluginURLStream(const nsString& aURL,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsNPAPIPluginStreamListener* aListener,
|
||||
nsIInputStream* aPostStream = nullptr,
|
||||
const char* aHeadersData = nullptr,
|
||||
uint32_t aHeadersDataLen = 0);
|
||||
|
||||
nsresult GetURLWithHeaders(
|
||||
nsNPAPIPluginInstance* pluginInst, const char* url,
|
||||
const char* target = nullptr,
|
||||
nsNPAPIPluginStreamListener* streamListener = nullptr,
|
||||
const char* altHost = nullptr, const char* referrer = nullptr,
|
||||
bool forceJSEnabled = false, uint32_t getHeadersLength = 0,
|
||||
const char* getHeaders = nullptr);
|
||||
|
||||
nsresult AddHeadersToChannel(const char* aHeadersData,
|
||||
uint32_t aHeadersDataLen,
|
||||
nsIChannel* aGenericChannel);
|
||||
|
@ -166,9 +128,6 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
|
||||
static nsresult PostPluginUnloadEvent(PRLibrary* aLibrary);
|
||||
|
||||
void PluginCrashed(nsNPAPIPlugin* aPlugin, const nsAString& aPluginDumpID,
|
||||
const nsACString& aAdditionalMinidumps);
|
||||
|
||||
nsNPAPIPluginInstance* FindInstance(const char* mimetype);
|
||||
nsNPAPIPluginInstance* FindOldestStoppedInstance();
|
||||
uint32_t StoppedInstanceCount();
|
||||
|
@ -178,37 +137,20 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
// Return the tag for |aLibrary| if found, nullptr if not.
|
||||
nsPluginTag* FindTagForLibrary(PRLibrary* aLibrary);
|
||||
|
||||
// The last argument should be false if we already have an in-flight stream
|
||||
// and don't need to set up a new stream.
|
||||
nsresult InstantiatePluginInstance(const nsACString& aMimeType, nsIURI* aURL,
|
||||
nsObjectLoadingContent* aContent,
|
||||
nsPluginInstanceOwner** aOwner);
|
||||
|
||||
// Does not accept nullptr and should never fail.
|
||||
nsPluginTag* TagForPlugin(nsNPAPIPlugin* aPlugin);
|
||||
|
||||
nsPluginTag* PluginWithId(uint32_t aId);
|
||||
|
||||
nsresult GetPlugin(const nsACString& aMimeType, nsNPAPIPlugin** aPlugin);
|
||||
nsresult GetPluginForContentProcess(uint32_t aPluginId,
|
||||
nsNPAPIPlugin** aPlugin);
|
||||
void NotifyContentModuleDestroyed(uint32_t aPluginId);
|
||||
|
||||
nsresult NewPluginStreamListener(nsIURI* aURL,
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIStreamListener** aStreamListener);
|
||||
|
||||
void CreateWidget(nsPluginInstanceOwner* aOwner);
|
||||
|
||||
nsresult EnumerateSiteData(const nsACString& domain,
|
||||
const nsTArray<nsCString>& sites,
|
||||
nsTArray<nsCString>& result, bool firstMatchOnly);
|
||||
|
||||
nsresult UpdateCachedSerializablePluginList();
|
||||
nsresult SendPluginsToContent(mozilla::dom::ContentParent* parent);
|
||||
nsresult SetPluginsInContent(
|
||||
uint32_t aPluginEpoch, nsTArray<mozilla::plugins::PluginTag>& aPlugins,
|
||||
nsTArray<mozilla::plugins::FakePluginTag>& aFakePlugins);
|
||||
|
||||
void UpdatePluginBlocklistState(nsPluginTag* aPluginTag,
|
||||
bool aShouldSoftblock = false);
|
||||
|
@ -217,9 +159,6 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
nsresult LoadPlugins();
|
||||
nsresult UnloadPlugins();
|
||||
|
||||
nsresult SetUpPluginInstance(const nsACString& aMimeType, nsIURI* aURL,
|
||||
nsPluginInstanceOwner* aOwner);
|
||||
|
||||
friend class nsPluginUnloadRunnable;
|
||||
friend class mozilla::plugins::BlocklistPromiseHandler;
|
||||
|
||||
|
@ -229,9 +168,6 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
// if it is now disabled. Should only be called by the plugin tag in question
|
||||
void UpdatePluginInfo(nsPluginTag* aPluginTag);
|
||||
|
||||
nsresult TrySetUpPluginInstance(const nsACString& aMimeType, nsIURI* aURL,
|
||||
nsPluginInstanceOwner* aOwner);
|
||||
|
||||
// FIXME-jsplugins comment here about when things may be fake
|
||||
nsPluginTag* FindPreferredPlugin(const nsTArray<nsPluginTag*>& matches);
|
||||
|
||||
|
@ -266,9 +202,6 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
/* out */ nsACString& aMimeType,
|
||||
bool aCheckEnabled);
|
||||
|
||||
nsresult FindStoppedPluginForURL(nsIURI* aURL,
|
||||
nsIPluginInstanceOwner* aOwner);
|
||||
|
||||
nsresult BroadcastPluginsToContent();
|
||||
|
||||
// FIXME revisit, no ns prefix
|
||||
|
@ -318,9 +251,6 @@ class nsPluginHost final : public nsIPluginHost,
|
|||
|
||||
nsTArray<RefPtr<nsFakePluginTag>> mFakePlugins;
|
||||
|
||||
AutoTArray<mozilla::plugins::PluginTag, 1> mSerializablePlugins;
|
||||
nsTArray<mozilla::plugins::FakePluginTag> mSerializableFakePlugins;
|
||||
|
||||
bool mPluginsLoaded;
|
||||
|
||||
// set by pref plugin.override_internal_types
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,365 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:set ts=2 sts=2 sw=2 et cin:
|
||||
/* 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 nsPluginInstanceOwner_h_
|
||||
#define nsPluginInstanceOwner_h_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/dom/HTMLObjectElementBinding.h"
|
||||
#include "npapi.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIPluginInstanceOwner.h"
|
||||
#include "nsIPrivacyTransitionObserver.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "gfxRect.h"
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
# include "mozilla/gfx/QuartzSupport.h"
|
||||
# include <ApplicationServices/ApplicationServices.h>
|
||||
#endif
|
||||
|
||||
class nsIInputStream;
|
||||
class nsPluginDOMContextMenuListener;
|
||||
class nsDisplayListBuilder;
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
class gfxContext;
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
class TextComposition;
|
||||
namespace dom {
|
||||
class Element;
|
||||
class Event;
|
||||
} // namespace dom
|
||||
namespace widget {
|
||||
class PuppetWidget;
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
||||
using mozilla::widget::PuppetWidget;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
# include "gfxXlibNativeRenderer.h"
|
||||
#endif
|
||||
|
||||
class nsPluginInstanceOwner final : public nsIPluginInstanceOwner,
|
||||
public nsIDOMEventListener,
|
||||
public nsIPrivacyTransitionObserver,
|
||||
public nsSupportsWeakReference {
|
||||
public:
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
|
||||
nsPluginInstanceOwner();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPLUGININSTANCEOWNER
|
||||
NS_DECL_NSIPRIVACYTRANSITIONOBSERVER
|
||||
|
||||
NS_IMETHOD GetURL(const char* aURL, const char* aTarget,
|
||||
nsIInputStream* aPostStream, void* aHeadersData,
|
||||
uint32_t aHeadersDataLen,
|
||||
bool aDoCheckLoadURIChecks) override;
|
||||
|
||||
NPBool ConvertPoint(double sourceX, double sourceY,
|
||||
NPCoordinateSpace sourceSpace, double* destX,
|
||||
double* destY, NPCoordinateSpace destSpace) override;
|
||||
|
||||
NPError InitAsyncSurface(NPSize* size, NPImageFormat format, void* initData,
|
||||
NPAsyncSurface* surface) override;
|
||||
NPError FinalizeAsyncSurface(NPAsyncSurface* surface) override;
|
||||
void SetCurrentAsyncSurface(NPAsyncSurface* surface,
|
||||
NPRect* changed) override;
|
||||
|
||||
/**
|
||||
* Get the type of the HTML tag that was used to instantiate this
|
||||
* plugin. Currently supported tags are EMBED or OBJECT.
|
||||
*/
|
||||
NS_IMETHOD GetTagType(nsPluginTagType* aResult);
|
||||
|
||||
void GetParameters(nsTArray<mozilla::dom::MozPluginParameter>& parameters);
|
||||
void GetAttributes(nsTArray<mozilla::dom::MozPluginParameter>& attributes);
|
||||
|
||||
/**
|
||||
* Returns the DOM element corresponding to the tag which references
|
||||
* this plugin in the document.
|
||||
*
|
||||
* @param aDOMElement - resulting DOM element
|
||||
* @result - NS_OK if this operation was successful
|
||||
*/
|
||||
NS_IMETHOD GetDOMElement(mozilla::dom::Element** aResult);
|
||||
|
||||
// nsIDOMEventListener interfaces
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult
|
||||
ProcessMouseDown(mozilla::dom::Event* aMouseEvent);
|
||||
nsresult ProcessKeyPress(mozilla::dom::Event* aKeyEvent);
|
||||
nsresult Destroy();
|
||||
|
||||
#ifdef XP_WIN
|
||||
void Paint(const RECT& aDirty, HDC aDC);
|
||||
#elif defined(XP_MACOSX)
|
||||
void Paint(const gfxRect& aDirtyRect, CGContextRef cgContext);
|
||||
void RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight);
|
||||
void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext);
|
||||
#elif defined(MOZ_X11)
|
||||
void Paint(gfxContext* aContext, const gfxRect& aFrameRect,
|
||||
const gfxRect& aDirtyRect);
|
||||
#endif
|
||||
|
||||
// locals
|
||||
|
||||
nsresult Init(nsIContent* aContent);
|
||||
|
||||
void* GetPluginPort();
|
||||
void ReleasePluginPort(void* pluginPort);
|
||||
|
||||
nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
|
||||
|
||||
static void GeneratePluginEvent(
|
||||
const mozilla::WidgetCompositionEvent* aSrcCompositionEvent,
|
||||
mozilla::WidgetCompositionEvent* aDistCompositionEvent);
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void SetWidgetWindowAsParent(HWND aWindowToAdopt);
|
||||
nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt);
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
enum {ePluginPaintEnable, ePluginPaintDisable};
|
||||
|
||||
void WindowFocusMayHaveChanged();
|
||||
|
||||
bool WindowIsActive();
|
||||
void SendWindowFocusChanged(bool aIsActive);
|
||||
NPDrawingModel GetDrawingModel();
|
||||
bool IsRemoteDrawingCoreAnimation();
|
||||
|
||||
NPEventModel GetEventModel();
|
||||
static void CARefresh(nsITimer* aTimer, void* aClosure);
|
||||
void AddToCARefreshTimer();
|
||||
void RemoveFromCARefreshTimer();
|
||||
// This calls into the plugin (NPP_SetWindow) and can run script.
|
||||
void FixUpPluginWindow(int32_t inPaintState);
|
||||
void HidePluginWindow();
|
||||
// Set plugin port info in the plugin (in the 'window' member of the
|
||||
// NPWindow structure passed to the plugin by SetWindow()).
|
||||
void SetPluginPort();
|
||||
#else // XP_MACOSX
|
||||
void UpdateWindowPositionAndClipRect(bool aSetWindow);
|
||||
void UpdateWindowVisibility(bool aVisible);
|
||||
#endif // XP_MACOSX
|
||||
|
||||
void ResolutionMayHaveChanged();
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
#endif
|
||||
|
||||
void UpdateDocumentActiveState(bool aIsActive);
|
||||
|
||||
uint32_t GetLastEventloopNestingLevel() const {
|
||||
return mLastEventloopNestingLevel;
|
||||
}
|
||||
|
||||
static uint32_t GetEventloopNestingLevel();
|
||||
|
||||
void ConsiderNewEventloopNestingLevel() {
|
||||
uint32_t currentLevel = GetEventloopNestingLevel();
|
||||
|
||||
if (currentLevel < mLastEventloopNestingLevel) {
|
||||
mLastEventloopNestingLevel = currentLevel;
|
||||
}
|
||||
}
|
||||
|
||||
const char* GetPluginName() {
|
||||
if (mInstance && mPluginHost) {
|
||||
const char* name = nullptr;
|
||||
if (NS_SUCCEEDED(mPluginHost->GetPluginName(mInstance, &name)) && name)
|
||||
return name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
void GetPluginDescription(nsACString& aDescription) {
|
||||
aDescription.Truncate();
|
||||
if (mInstance && mPluginHost) {
|
||||
nsCOMPtr<nsIPluginTag> pluginTag;
|
||||
|
||||
mPluginHost->GetPluginTagForInstance(mInstance,
|
||||
getter_AddRefs(pluginTag));
|
||||
if (pluginTag) {
|
||||
pluginTag->GetDescription(aDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SendNativeEvents() {
|
||||
#ifdef XP_WIN
|
||||
// XXX we should remove the plugin name check
|
||||
return mPluginWindow->type == NPWindowTypeDrawable &&
|
||||
(MatchPluginName("Shockwave Flash") ||
|
||||
MatchPluginName("Test Plug-in"));
|
||||
#elif defined(MOZ_X11) || defined(XP_MACOSX)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool MatchPluginName(const char* aPluginName) {
|
||||
return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0;
|
||||
}
|
||||
|
||||
void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
|
||||
|
||||
// Returns the image container that has our currently displayed image.
|
||||
already_AddRefed<mozilla::layers::ImageContainer> GetImageContainer();
|
||||
// Returns true if this is windowed plugin that can return static captures
|
||||
// for scroll operations.
|
||||
bool NeedsScrollImageLayer();
|
||||
|
||||
void DidComposite();
|
||||
|
||||
/**
|
||||
* Returns the bounds of the current async-rendered surface. This can only
|
||||
* change in response to messages received by the event loop (i.e. not during
|
||||
* painting).
|
||||
*/
|
||||
nsIntSize GetCurrentImageSize();
|
||||
|
||||
// Methods to update the background image we send to async plugins.
|
||||
// The eventual target of these operations is PluginInstanceParent,
|
||||
// but it takes several hops to get there.
|
||||
void SetBackgroundUnknown();
|
||||
already_AddRefed<DrawTarget> BeginUpdateBackground(const nsIntRect& aRect);
|
||||
void EndUpdateBackground(const nsIntRect& aRect);
|
||||
|
||||
bool UseAsyncRendering();
|
||||
|
||||
nsIURI* GetBaseURI() const;
|
||||
|
||||
bool GetCompositionString(uint32_t aIndex, nsTArray<uint8_t>* aString,
|
||||
int32_t* aLength);
|
||||
bool RequestCommitOrCancel(bool aCommitted);
|
||||
|
||||
void GetCSSZoomFactor(float* result);
|
||||
|
||||
private:
|
||||
virtual ~nsPluginInstanceOwner();
|
||||
|
||||
// return FALSE if LayerSurface dirty (newly created and don't have valid
|
||||
// plugin content yet)
|
||||
bool IsUpToDate() {
|
||||
nsIntSize size;
|
||||
return NS_SUCCEEDED(mInstance->GetImageSize(&size)) &&
|
||||
size == nsIntSize(mPluginWindow->width, mPluginWindow->height);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
nsIWidget* GetContainingWidgetIfOffset();
|
||||
already_AddRefed<mozilla::TextComposition> GetTextComposition();
|
||||
void HandleNoConsumedCompositionMessage(
|
||||
mozilla::WidgetCompositionEvent* aCompositionEvent,
|
||||
const NPEvent* aPluginEvent);
|
||||
bool mGotCompositionData;
|
||||
bool mSentStartComposition;
|
||||
bool mPluginDidNotHandleIMEComposition;
|
||||
uint32_t mWheelScrollLines;
|
||||
uint32_t mWheelScrollChars;
|
||||
#endif
|
||||
|
||||
nsPluginNativeWindow* mPluginWindow;
|
||||
RefPtr<nsNPAPIPluginInstance> mInstance;
|
||||
nsWeakPtr mContent; // WEAK, content owns us
|
||||
nsCString mDocumentBase;
|
||||
bool mWidgetCreationComplete;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
RefPtr<nsPluginHost> mPluginHost;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
static mozilla::StaticRefPtr<nsITimer> sCATimer;
|
||||
static nsTArray<nsPluginInstanceOwner*>* sCARefreshListeners;
|
||||
bool mSentInitialTopLevelWindowEvent;
|
||||
bool mLastWindowIsActive;
|
||||
bool mLastContentFocused;
|
||||
// True if, the next time the window is activated, we should blur ourselves.
|
||||
bool mShouldBlurOnActivate;
|
||||
#endif
|
||||
double mLastScaleFactor;
|
||||
double mLastCSSZoomFactor;
|
||||
// Initially, the event loop nesting level we were created on, it's updated
|
||||
// if we detect the appshell is on a lower level as long as we're not stopped.
|
||||
// We delay DoStopPlugin() until the appshell reaches this level or lower.
|
||||
uint32_t mLastEventloopNestingLevel;
|
||||
bool mContentFocused;
|
||||
bool mWidgetVisible; // used on Mac to store our widget's visible state
|
||||
#ifdef MOZ_X11
|
||||
// Used with windowless plugins only, initialized in CreateWidget().
|
||||
bool mFlash10Quirks;
|
||||
#endif
|
||||
bool mPluginWindowVisible;
|
||||
bool mPluginDocumentActiveState;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
NPEventModel mEventModel;
|
||||
// This is a hack! UseAsyncRendering() can incorrectly return false
|
||||
// when we don't have an object frame (possible as of bug 90268).
|
||||
// We hack around this by always returning true if we've ever
|
||||
// returned true.
|
||||
bool mUseAsyncRendering;
|
||||
#endif
|
||||
|
||||
// pointer to wrapper for nsIDOMContextMenuListener
|
||||
RefPtr<nsPluginDOMContextMenuListener> mCXMenuListener;
|
||||
|
||||
nsresult DispatchKeyToPlugin(mozilla::dom::Event* aKeyEvent);
|
||||
nsresult DispatchMouseToPlugin(mozilla::dom::Event* aMouseEvent,
|
||||
bool aAllowPropagate = false);
|
||||
nsresult DispatchFocusToPlugin(mozilla::dom::Event* aFocusEvent);
|
||||
nsresult DispatchCompositionToPlugin(mozilla::dom::Event* aEvent);
|
||||
|
||||
#ifdef XP_WIN
|
||||
void CallDefaultProc(const mozilla::WidgetGUIEvent* aEvent);
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
void PerformDelayedBlurs();
|
||||
#endif // XP_MACOSX
|
||||
|
||||
int mLastMouseDownButtonType;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
class Renderer : public gfxXlibNativeRenderer {
|
||||
public:
|
||||
Renderer(NPWindow* aWindow, nsPluginInstanceOwner* aInstanceOwner,
|
||||
const nsIntSize& aPluginSize, const nsIntRect& aDirtyRect)
|
||||
: mWindow(aWindow),
|
||||
mInstanceOwner(aInstanceOwner),
|
||||
mPluginSize(aPluginSize),
|
||||
mDirtyRect(aDirtyRect) {}
|
||||
virtual nsresult DrawWithXlib(cairo_surface_t* surface, nsIntPoint offset,
|
||||
nsIntRect* clipRects,
|
||||
uint32_t numClipRects) override;
|
||||
|
||||
private:
|
||||
NPWindow* mWindow;
|
||||
nsPluginInstanceOwner* mInstanceOwner;
|
||||
const nsIntSize& mPluginSize;
|
||||
const nsIntRect& mDirtyRect;
|
||||
};
|
||||
#endif
|
||||
|
||||
bool mWaitingForPaint;
|
||||
};
|
||||
|
||||
#endif // nsPluginInstanceOwner_h_
|
|
@ -1,101 +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 nsPluginManifestLineReader_h_
|
||||
#define nsPluginManifestLineReader_h_
|
||||
|
||||
#include "nspr.h"
|
||||
#include "nsDebug.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
# define PLUGIN_REGISTRY_FIELD_DELIMITER '|'
|
||||
#else
|
||||
# define PLUGIN_REGISTRY_FIELD_DELIMITER ':'
|
||||
#endif
|
||||
|
||||
#define PLUGIN_REGISTRY_END_OF_LINE_MARKER '$'
|
||||
|
||||
class nsPluginManifestLineReader {
|
||||
public:
|
||||
nsPluginManifestLineReader() : mLength(0) {
|
||||
mBase = mCur = mNext = mLimit = 0;
|
||||
}
|
||||
~nsPluginManifestLineReader() {
|
||||
if (mBase) delete[] mBase;
|
||||
mBase = 0;
|
||||
}
|
||||
|
||||
char* Init(uint32_t flen) {
|
||||
mBase = mCur = mNext = new char[flen + 1];
|
||||
if (mBase) {
|
||||
mLimit = mBase + flen;
|
||||
*mLimit = 0;
|
||||
}
|
||||
mLength = 0;
|
||||
return mBase;
|
||||
}
|
||||
|
||||
bool NextLine() {
|
||||
if (mNext >= mLimit) return false;
|
||||
|
||||
mCur = mNext;
|
||||
mLength = 0;
|
||||
|
||||
char* lastDelimiter = 0;
|
||||
while (mNext < mLimit) {
|
||||
if (IsEOL(*mNext)) {
|
||||
if (lastDelimiter) {
|
||||
if (lastDelimiter &&
|
||||
*(mNext - 1) != PLUGIN_REGISTRY_END_OF_LINE_MARKER)
|
||||
return false;
|
||||
*lastDelimiter = '\0';
|
||||
} else {
|
||||
*mNext = '\0';
|
||||
}
|
||||
|
||||
for (++mNext; mNext < mLimit; ++mNext) {
|
||||
if (!IsEOL(*mNext)) break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (*mNext == PLUGIN_REGISTRY_FIELD_DELIMITER) lastDelimiter = mNext;
|
||||
++mNext;
|
||||
++mLength;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int ParseLine(char** chunks, int maxChunks) {
|
||||
NS_ASSERTION(mCur && maxChunks && chunks, "bad call to ParseLine");
|
||||
int found = 0;
|
||||
chunks[found++] = mCur;
|
||||
|
||||
if (found < maxChunks) {
|
||||
for (char* cur = mCur; *cur; cur++) {
|
||||
if (*cur == PLUGIN_REGISTRY_FIELD_DELIMITER) {
|
||||
*cur = 0;
|
||||
chunks[found++] = cur + 1;
|
||||
if (found == maxChunks) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
char* LinePtr() { return mCur; }
|
||||
uint32_t LineLength() { return mLength; }
|
||||
|
||||
bool IsEOL(char c) { return c == '\n' || c == '\r'; }
|
||||
|
||||
char* mBase;
|
||||
|
||||
private:
|
||||
char* mCur;
|
||||
uint32_t mLength;
|
||||
char* mNext;
|
||||
char* mLimit;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,61 +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/. */
|
||||
|
||||
/**
|
||||
* This file is the default implementation of plugin native window
|
||||
* empty stubs, it should be replaced with real platform implementation
|
||||
* for every platform
|
||||
*/
|
||||
|
||||
#include "nsDebug.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
|
||||
class nsPluginNativeWindowImpl : public nsPluginNativeWindow {
|
||||
public:
|
||||
nsPluginNativeWindowImpl();
|
||||
virtual ~nsPluginNativeWindowImpl();
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
|
||||
NPSetWindowCallbackStruct mWsInfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
nsPluginNativeWindowImpl::nsPluginNativeWindowImpl() : nsPluginNativeWindow() {
|
||||
// initialize the struct fields
|
||||
window = nullptr;
|
||||
x = 0;
|
||||
y = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
memset(&clipRect, 0, sizeof(clipRect));
|
||||
type = NPWindowTypeWindow;
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)
|
||||
ws_info = &mWsInfo;
|
||||
mWsInfo.type = 0;
|
||||
mWsInfo.display = nullptr;
|
||||
mWsInfo.visual = nullptr;
|
||||
mWsInfo.colormap = 0;
|
||||
mWsInfo.depth = 0;
|
||||
#elif defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
ws_info = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsPluginNativeWindowImpl::~nsPluginNativeWindowImpl() = default;
|
||||
|
||||
nsresult PLUG_NewPluginNativeWindow(
|
||||
nsPluginNativeWindow** aPluginNativeWindow) {
|
||||
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
|
||||
*aPluginNativeWindow = new nsPluginNativeWindowImpl();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PLUG_DeletePluginNativeWindow(
|
||||
nsPluginNativeWindow* aPluginNativeWindow) {
|
||||
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
|
||||
delete static_cast<nsPluginNativeWindowImpl*>(aPluginNativeWindow);
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,76 +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 _nsPluginNativeWindow_h_
|
||||
#define _nsPluginNativeWindow_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "npapi.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
/**
|
||||
* base class for native plugin window implementations
|
||||
*/
|
||||
class nsPluginNativeWindow : public NPWindow {
|
||||
public:
|
||||
nsPluginNativeWindow() : NPWindow() { MOZ_COUNT_CTOR(nsPluginNativeWindow); }
|
||||
|
||||
MOZ_COUNTED_DTOR_VIRTUAL(nsPluginNativeWindow)
|
||||
|
||||
/**
|
||||
* !!! CAUTION !!!
|
||||
*
|
||||
* The base class |nsPluginWindow| is defined as a struct in nsplugindefs.h,
|
||||
* thus it does not have a destructor of its own.
|
||||
* One should never attempt to delete |nsPluginNativeWindow| object instance
|
||||
* (or derivatives) using a pointer of |nsPluginWindow *| type. Should such
|
||||
* necessity occur it must be properly casted first.
|
||||
*/
|
||||
|
||||
public:
|
||||
nsresult GetPluginInstance(RefPtr<nsNPAPIPluginInstance>& aPluginInstance) {
|
||||
aPluginInstance = mPluginInstance;
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult SetPluginInstance(nsNPAPIPluginInstance* aPluginInstance) {
|
||||
if (mPluginInstance != aPluginInstance) mPluginInstance = aPluginInstance;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetPluginWidget(nsIWidget** aWidget) const {
|
||||
NS_IF_ADDREF(*aWidget = mWidget);
|
||||
return NS_OK;
|
||||
}
|
||||
nsresult SetPluginWidget(nsIWidget* aWidget) {
|
||||
mWidget = aWidget;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
public:
|
||||
virtual nsresult CallSetWindow(
|
||||
RefPtr<nsNPAPIPluginInstance>& aPluginInstance) {
|
||||
// null aPluginInstance means that we want to call SetWindow(null)
|
||||
if (aPluginInstance)
|
||||
aPluginInstance->SetWindow(this);
|
||||
else if (mPluginInstance)
|
||||
mPluginInstance->SetWindow(nullptr);
|
||||
|
||||
SetPluginInstance(aPluginInstance);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<nsNPAPIPluginInstance> mPluginInstance;
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
};
|
||||
|
||||
nsresult PLUG_NewPluginNativeWindow(nsPluginNativeWindow** aPluginNativeWindow);
|
||||
nsresult PLUG_DeletePluginNativeWindow(
|
||||
nsPluginNativeWindow* aPluginNativeWindow);
|
||||
|
||||
#endif //_nsPluginNativeWindow_h_
|
|
@ -1,633 +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 "mozilla/BasicEvents.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/WeakPtr.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
// XXXbz windowsx.h defines GetFirstChild, GetNextSibling,
|
||||
// GetPrevSibling are macros, apparently... Eeevil. We have functions
|
||||
// called that on some classes, so undef them.
|
||||
#undef GetFirstChild
|
||||
#undef GetNextSibling
|
||||
#undef GetPrevSibling
|
||||
|
||||
#include "nsDebug.h"
|
||||
|
||||
#include "nsWindowsDllInterceptor.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsCrashOnException.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define NP_POPUP_API_VERSION 16
|
||||
|
||||
#define nsMajorVersion(v) (((int32_t)(v) >> 16) & 0xffff)
|
||||
#define nsMinorVersion(v) ((int32_t)(v)&0xffff)
|
||||
#define versionOK(suppliedV, requiredV) \
|
||||
(nsMajorVersion(suppliedV) == nsMajorVersion(requiredV) && \
|
||||
nsMinorVersion(suppliedV) >= nsMinorVersion(requiredV))
|
||||
|
||||
#define NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION \
|
||||
TEXT("MozillaPluginWindowPropertyAssociation")
|
||||
#define NS_PLUGIN_CUSTOM_MSG_ID TEXT("MozFlashUserRelay")
|
||||
#define WM_USER_FLASH WM_USER + 1
|
||||
static UINT sWM_FLASHBOUNCEMSG = 0;
|
||||
|
||||
class nsPluginNativeWindowWin;
|
||||
|
||||
/**
|
||||
* PLEvent handling code
|
||||
*/
|
||||
class PluginWindowEvent : public Runnable {
|
||||
public:
|
||||
PluginWindowEvent();
|
||||
void Init(WeakPtr<nsPluginNativeWindowWin> aRef, HWND aWnd, UINT aMsg,
|
||||
WPARAM aParam, LPARAM aLParam);
|
||||
void Clear();
|
||||
HWND GetWnd() { return mWnd; };
|
||||
UINT GetMsg() { return mMsg; };
|
||||
WPARAM GetWParam() { return mWParam; };
|
||||
LPARAM GetLParam() { return mLParam; };
|
||||
bool InUse() { return mWnd != nullptr; };
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
protected:
|
||||
WeakPtr<nsPluginNativeWindowWin> mPluginWindowRef;
|
||||
HWND mWnd;
|
||||
UINT mMsg;
|
||||
WPARAM mWParam;
|
||||
LPARAM mLParam;
|
||||
};
|
||||
|
||||
PluginWindowEvent::PluginWindowEvent() : Runnable("PluginWindowEvent") {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void PluginWindowEvent::Clear() {
|
||||
mWnd = nullptr;
|
||||
mMsg = 0;
|
||||
mWParam = 0;
|
||||
mLParam = 0;
|
||||
}
|
||||
|
||||
void PluginWindowEvent::Init(WeakPtr<nsPluginNativeWindowWin> aRef, HWND aWnd,
|
||||
UINT aMsg, WPARAM aWParam, LPARAM aLParam) {
|
||||
NS_ASSERTION(aWnd != nullptr, "invalid plugin event value");
|
||||
NS_ASSERTION(mWnd == nullptr, "event already in use");
|
||||
mPluginWindowRef = aRef;
|
||||
mWnd = aWnd;
|
||||
mMsg = aMsg;
|
||||
mWParam = aWParam;
|
||||
mLParam = aLParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* nsPluginNativeWindow Windows specific class declaration
|
||||
*/
|
||||
|
||||
class nsPluginNativeWindowWin : public nsPluginNativeWindow,
|
||||
public SupportsWeakPtr {
|
||||
public:
|
||||
nsPluginNativeWindowWin();
|
||||
|
||||
virtual nsresult CallSetWindow(
|
||||
RefPtr<nsNPAPIPluginInstance>& aPluginInstance);
|
||||
|
||||
private:
|
||||
nsresult SubclassAndAssociateWindow();
|
||||
nsresult UndoSubclassAndAssociateWindow();
|
||||
|
||||
public:
|
||||
// locals
|
||||
WNDPROC GetPrevWindowProc();
|
||||
void SetPrevWindowProc(WNDPROC proc) { mPluginWinProc = proc; }
|
||||
WNDPROC GetWindowProc();
|
||||
PluginWindowEvent* GetPluginWindowEvent(HWND aWnd, UINT aMsg, WPARAM aWParam,
|
||||
LPARAM aLParam);
|
||||
|
||||
private:
|
||||
WNDPROC mPluginWinProc;
|
||||
WNDPROC mPrevWinProc;
|
||||
WeakPtr<nsPluginNativeWindowWin> mWeakRef;
|
||||
RefPtr<PluginWindowEvent> mCachedPluginWindowEvent;
|
||||
|
||||
HWND mParentWnd;
|
||||
LONG_PTR mParentProc;
|
||||
|
||||
public:
|
||||
nsPluginHost::SpecialType mPluginType;
|
||||
};
|
||||
|
||||
static bool sInPreviousMessageDispatch = false;
|
||||
|
||||
static bool ProcessFlashMessageDelayed(nsPluginNativeWindowWin* aWin,
|
||||
nsNPAPIPluginInstance* aInst, HWND hWnd,
|
||||
UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
NS_ENSURE_TRUE(aWin, false);
|
||||
NS_ENSURE_TRUE(aInst, false);
|
||||
|
||||
if (msg == sWM_FLASHBOUNCEMSG) {
|
||||
// See PluginWindowEvent::Run() below.
|
||||
NS_ASSERTION((sWM_FLASHBOUNCEMSG != 0),
|
||||
"RegisterWindowMessage failed in flash plugin WM_USER message "
|
||||
"handling!");
|
||||
::CallWindowProc((WNDPROC)aWin->GetWindowProc(), hWnd, WM_USER_FLASH,
|
||||
wParam, lParam);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg != WM_USER_FLASH) return false; // no need to delay
|
||||
|
||||
// do stuff
|
||||
nsCOMPtr<nsIRunnable> pwe =
|
||||
aWin->GetPluginWindowEvent(hWnd, msg, wParam, lParam);
|
||||
if (pwe) {
|
||||
NS_DispatchToCurrentThread(pwe);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class nsDelayedPopupsEnabledEvent : public Runnable {
|
||||
public:
|
||||
explicit nsDelayedPopupsEnabledEvent(nsNPAPIPluginInstance* inst)
|
||||
: Runnable("nsDelayedPopupsEnabledEvent"), mInst(inst) {}
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
|
||||
private:
|
||||
RefPtr<nsNPAPIPluginInstance> mInst;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP nsDelayedPopupsEnabledEvent::Run() {
|
||||
mInst->PushPopupsEnabledState(false);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
|
||||
/**
|
||||
* New plugin window procedure
|
||||
*
|
||||
* e10s note - this subclass, and the hooks we set below using
|
||||
* WindowsDllInterceptor are currently not in use when running with e10s.
|
||||
* (Utility calls like CallSetWindow are still in use in the content process.)
|
||||
* We would like to keep things this away, essentially making all the hacks here
|
||||
* obsolete. Some of the mitigation work here has already been supplanted by
|
||||
* code in PluginInstanceChild. The rest we eventually want to rip out.
|
||||
*/
|
||||
static LRESULT CALLBACK PluginWndProcInternal(HWND hWnd, UINT msg,
|
||||
WPARAM wParam, LPARAM lParam) {
|
||||
nsPluginNativeWindowWin* win = (nsPluginNativeWindowWin*)::GetProp(
|
||||
hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
if (!win) return TRUE;
|
||||
|
||||
// The DispatchEvent(ePluginActivate) below can trigger a reentrant focus
|
||||
// event which might destroy us. Hold a strong ref on the plugin instance
|
||||
// to prevent that, bug 374229.
|
||||
RefPtr<nsNPAPIPluginInstance> inst;
|
||||
win->GetPluginInstance(inst);
|
||||
|
||||
bool enablePopups = false;
|
||||
|
||||
// Activate/deactivate mouse capture on the plugin widget
|
||||
// here, before we pass the Windows event to the plugin
|
||||
// because its possible our widget won't get paired events
|
||||
// (see bug 131007) and we'll look frozen. Note that this
|
||||
// is also done in ChildWindow::DispatchMouseEvent.
|
||||
switch (msg) {
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN: {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
win->GetPluginWidget(getter_AddRefs(widget));
|
||||
if (widget) widget->CaptureMouse(true);
|
||||
break;
|
||||
}
|
||||
case WM_LBUTTONUP:
|
||||
enablePopups = true;
|
||||
|
||||
// fall through
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP: {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
win->GetPluginWidget(getter_AddRefs(widget));
|
||||
if (widget) widget->CaptureMouse(false);
|
||||
break;
|
||||
}
|
||||
case WM_KEYDOWN:
|
||||
// Ignore repeating keydown messages...
|
||||
if ((lParam & 0x40000000) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// fall through
|
||||
case WM_KEYUP:
|
||||
enablePopups = true;
|
||||
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
case WM_KILLFOCUS: {
|
||||
// Make sure setfocus and killfocus get through to the widget procedure
|
||||
// even if they are eaten by the plugin. Also make sure we aren't calling
|
||||
// recursively.
|
||||
WNDPROC prevWndProc = win->GetPrevWindowProc();
|
||||
if (prevWndProc && !sInPreviousMessageDispatch) {
|
||||
sInPreviousMessageDispatch = true;
|
||||
::CallWindowProc(prevWndProc, hWnd, msg, wParam, lParam);
|
||||
sInPreviousMessageDispatch = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Macromedia Flash plugin may flood the message queue with some special
|
||||
// messages (WM_USER+1) causing 100% CPU consumption and GUI freeze, see
|
||||
// mozilla bug 132759; we can prevent this from happening by delaying the
|
||||
// processing such messages;
|
||||
if (win->mPluginType == nsPluginHost::eSpecialType_Flash) {
|
||||
if (ProcessFlashMessageDelayed(win, inst, hWnd, msg, wParam, lParam))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (enablePopups && inst) {
|
||||
uint16_t apiVersion;
|
||||
if (NS_SUCCEEDED(inst->GetPluginAPIVersion(&apiVersion)) &&
|
||||
!versionOK(apiVersion, NP_POPUP_API_VERSION)) {
|
||||
inst->PushPopupsEnabledState(true);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT res;
|
||||
WNDPROC proc = (WNDPROC)win->GetWindowProc();
|
||||
if (PluginWndProc == proc) {
|
||||
NS_WARNING(
|
||||
"Previous plugin window procedure references PluginWndProc! "
|
||||
"Report this bug!");
|
||||
res = CallWindowProc(DefWindowProc, hWnd, msg, wParam, lParam);
|
||||
} else {
|
||||
res = CallWindowProc(proc, hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
if (inst) {
|
||||
// Popups are enabled (were enabled before the call to
|
||||
// CallWindowProc()). Some plugins (at least the flash player)
|
||||
// post messages from their key handlers etc that delay the actual
|
||||
// processing, so we need to delay the disabling of popups so that
|
||||
// popups remain enabled when the flash player ends up processing
|
||||
// the actual key handlers. We do this by posting an event that
|
||||
// does the disabling, this way our disabling will happen after
|
||||
// the handlers in the plugin are done.
|
||||
|
||||
// Note that it's not fatal if any of this fails (which won't
|
||||
// happen unless we're out of memory anyways) since the plugin
|
||||
// code will pop any popup state pushed by this plugin on
|
||||
// destruction.
|
||||
|
||||
nsCOMPtr<nsIRunnable> event = new nsDelayedPopupsEnabledEvent(inst);
|
||||
if (event) NS_DispatchToCurrentThread(event);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK PluginWndProc(HWND hWnd, UINT msg, WPARAM wParam,
|
||||
LPARAM lParam) {
|
||||
return mozilla::CallWindowProcCrashProtected(PluginWndProcInternal, hWnd, msg,
|
||||
wParam, lParam);
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash will reset the subclass of our widget at various times.
|
||||
* (Notably when entering and exiting full screen mode.) This
|
||||
* occurs independent of the main plugin window event procedure.
|
||||
* We trap these subclass calls to prevent our subclass hook from
|
||||
* getting dropped.
|
||||
* Note, ascii versions can be nixed once flash versions < 10.1
|
||||
* are considered obsolete.
|
||||
*/
|
||||
static WindowsDllInterceptor sUser32Intercept;
|
||||
|
||||
#ifdef _WIN64
|
||||
typedef LONG_PTR(WINAPI* User32SetWindowLongPtrA)(HWND hWnd, int nIndex,
|
||||
LONG_PTR dwNewLong);
|
||||
typedef LONG_PTR(WINAPI* User32SetWindowLongPtrW)(HWND hWnd, int nIndex,
|
||||
LONG_PTR dwNewLong);
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrA>
|
||||
sUser32SetWindowLongAHookStub;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongPtrW>
|
||||
sUser32SetWindowLongWHookStub;
|
||||
#else
|
||||
typedef LONG(WINAPI* User32SetWindowLongA)(HWND hWnd, int nIndex,
|
||||
LONG dwNewLong);
|
||||
typedef LONG(WINAPI* User32SetWindowLongW)(HWND hWnd, int nIndex,
|
||||
LONG dwNewLong);
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongA>
|
||||
sUser32SetWindowLongAHookStub;
|
||||
static WindowsDllInterceptor::FuncHookType<User32SetWindowLongW>
|
||||
sUser32SetWindowLongWHookStub;
|
||||
#endif
|
||||
static inline bool SetWindowLongHookCheck(HWND hWnd, int nIndex,
|
||||
LONG_PTR newLong) {
|
||||
nsPluginNativeWindowWin* win = (nsPluginNativeWindowWin*)GetProp(
|
||||
hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
if (!win || (win && win->mPluginType != nsPluginHost::eSpecialType_Flash) ||
|
||||
(nIndex == GWLP_WNDPROC &&
|
||||
newLong == reinterpret_cast<LONG_PTR>(PluginWndProc)))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
LONG_PTR WINAPI SetWindowLongPtrAHook(HWND hWnd, int nIndex, LONG_PTR newLong)
|
||||
#else
|
||||
LONG WINAPI SetWindowLongAHook(HWND hWnd, int nIndex, LONG newLong)
|
||||
#endif
|
||||
{
|
||||
if (SetWindowLongHookCheck(hWnd, nIndex, newLong))
|
||||
return sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong);
|
||||
|
||||
// Set flash's new subclass to get the result.
|
||||
LONG_PTR proc = sUser32SetWindowLongAHookStub(hWnd, nIndex, newLong);
|
||||
|
||||
// We already checked this in SetWindowLongHookCheck
|
||||
nsPluginNativeWindowWin* win = (nsPluginNativeWindowWin*)GetProp(
|
||||
hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
|
||||
// Hook our subclass back up, just like we do on setwindow.
|
||||
win->SetPrevWindowProc(
|
||||
reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(
|
||||
hWnd, nIndex, reinterpret_cast<LONG_PTR>(PluginWndProc))));
|
||||
return proc;
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
LONG_PTR WINAPI SetWindowLongPtrWHook(HWND hWnd, int nIndex, LONG_PTR newLong)
|
||||
#else
|
||||
LONG WINAPI SetWindowLongWHook(HWND hWnd, int nIndex, LONG newLong)
|
||||
#endif
|
||||
{
|
||||
if (SetWindowLongHookCheck(hWnd, nIndex, newLong))
|
||||
return sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong);
|
||||
|
||||
// Set flash's new subclass to get the result.
|
||||
LONG_PTR proc = sUser32SetWindowLongWHookStub(hWnd, nIndex, newLong);
|
||||
|
||||
// We already checked this in SetWindowLongHookCheck
|
||||
nsPluginNativeWindowWin* win = (nsPluginNativeWindowWin*)GetProp(
|
||||
hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
|
||||
// Hook our subclass back up, just like we do on setwindow.
|
||||
win->SetPrevWindowProc(
|
||||
reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(
|
||||
hWnd, nIndex, reinterpret_cast<LONG_PTR>(PluginWndProc))));
|
||||
return proc;
|
||||
}
|
||||
|
||||
static void HookSetWindowLongPtr() {
|
||||
sUser32Intercept.Init("user32.dll");
|
||||
#ifdef _WIN64
|
||||
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongPtrA",
|
||||
&SetWindowLongPtrAHook);
|
||||
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongPtrW",
|
||||
&SetWindowLongPtrWHook);
|
||||
#else
|
||||
sUser32SetWindowLongAHookStub.Set(sUser32Intercept, "SetWindowLongA",
|
||||
&SetWindowLongAHook);
|
||||
sUser32SetWindowLongWHookStub.Set(sUser32Intercept, "SetWindowLongW",
|
||||
&SetWindowLongWHook);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* nsPluginNativeWindowWin implementation
|
||||
*/
|
||||
nsPluginNativeWindowWin::nsPluginNativeWindowWin() : nsPluginNativeWindow() {
|
||||
// initialize the struct fields
|
||||
window = nullptr;
|
||||
x = 0;
|
||||
y = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
type = NPWindowTypeWindow;
|
||||
|
||||
mPrevWinProc = nullptr;
|
||||
mPluginWinProc = nullptr;
|
||||
mPluginType = nsPluginHost::eSpecialType_None;
|
||||
|
||||
mParentWnd = nullptr;
|
||||
mParentProc = 0;
|
||||
}
|
||||
|
||||
WNDPROC nsPluginNativeWindowWin::GetPrevWindowProc() { return mPrevWinProc; }
|
||||
|
||||
WNDPROC nsPluginNativeWindowWin::GetWindowProc() { return mPluginWinProc; }
|
||||
|
||||
NS_IMETHODIMP PluginWindowEvent::Run() {
|
||||
nsPluginNativeWindowWin* win = mPluginWindowRef;
|
||||
if (!win) return NS_OK;
|
||||
|
||||
HWND hWnd = GetWnd();
|
||||
if (!hWnd) return NS_OK;
|
||||
|
||||
RefPtr<nsNPAPIPluginInstance> inst;
|
||||
win->GetPluginInstance(inst);
|
||||
|
||||
if (GetMsg() == WM_USER_FLASH) {
|
||||
// XXX Unwind issues related to runnable event callback depth for this
|
||||
// event and destruction of the plugin. (Bug 493601)
|
||||
::PostMessage(hWnd, sWM_FLASHBOUNCEMSG, GetWParam(), GetLParam());
|
||||
} else {
|
||||
// Currently not used, but added so that processing events here
|
||||
// is more generic.
|
||||
::CallWindowProc(win->GetWindowProc(), hWnd, GetMsg(), GetWParam(),
|
||||
GetLParam());
|
||||
}
|
||||
|
||||
Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PluginWindowEvent* nsPluginNativeWindowWin::GetPluginWindowEvent(
|
||||
HWND aWnd, UINT aMsg, WPARAM aWParam, LPARAM aLParam) {
|
||||
if (!mWeakRef) {
|
||||
mWeakRef = this;
|
||||
if (!mWeakRef) return nullptr;
|
||||
}
|
||||
|
||||
PluginWindowEvent* event;
|
||||
|
||||
// We have the ability to alloc if needed in case in the future some plugin
|
||||
// should post multiple PostMessages. However, this could lead to many
|
||||
// alloc's per second which could become a performance issue. See bug 169247.
|
||||
if (!mCachedPluginWindowEvent) {
|
||||
event = new PluginWindowEvent();
|
||||
mCachedPluginWindowEvent = event;
|
||||
} else if (mCachedPluginWindowEvent->InUse()) {
|
||||
event = new PluginWindowEvent();
|
||||
} else {
|
||||
event = mCachedPluginWindowEvent;
|
||||
}
|
||||
|
||||
event->Init(mWeakRef, aWnd, aMsg, aWParam, aLParam);
|
||||
return event;
|
||||
}
|
||||
|
||||
nsresult nsPluginNativeWindowWin::CallSetWindow(
|
||||
RefPtr<nsNPAPIPluginInstance>& aPluginInstance) {
|
||||
// Note, 'window' can be null
|
||||
|
||||
// check the incoming instance, null indicates that window is going away and
|
||||
// we are not interested in subclassing business any more, undo and don't
|
||||
// subclass
|
||||
if (!aPluginInstance) {
|
||||
UndoSubclassAndAssociateWindow();
|
||||
// release plugin instance
|
||||
SetPluginInstance(nullptr);
|
||||
nsPluginNativeWindow::CallSetWindow(aPluginInstance);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// check plugin mime type and cache it if it will need special treatment later
|
||||
if (mPluginType == nsPluginHost::eSpecialType_None) {
|
||||
const char* mimetype = nullptr;
|
||||
if (NS_SUCCEEDED(aPluginInstance->GetMIMEType(&mimetype)) && mimetype) {
|
||||
mPluginType = nsPluginHost::GetSpecialType(nsDependentCString(mimetype));
|
||||
}
|
||||
}
|
||||
|
||||
// With e10s we execute in the content process and as such we don't
|
||||
// have access to native widgets. CallSetWindow and skip native widget
|
||||
// subclassing.
|
||||
if (!XRE_IsParentProcess()) {
|
||||
nsPluginNativeWindow::CallSetWindow(aPluginInstance);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!sWM_FLASHBOUNCEMSG) {
|
||||
sWM_FLASHBOUNCEMSG = ::RegisterWindowMessage(NS_PLUGIN_CUSTOM_MSG_ID);
|
||||
}
|
||||
|
||||
if (window) {
|
||||
// grab the widget procedure before the plug-in does a subclass in
|
||||
// setwindow. We'll use this in PluginWndProc for forwarding focus
|
||||
// events to the widget.
|
||||
WNDPROC currentWndProc =
|
||||
(WNDPROC)::GetWindowLongPtr((HWND)window, GWLP_WNDPROC);
|
||||
if (!mPrevWinProc && currentWndProc != PluginWndProc)
|
||||
mPrevWinProc = currentWndProc;
|
||||
}
|
||||
|
||||
nsPluginNativeWindow::CallSetWindow(aPluginInstance);
|
||||
|
||||
SubclassAndAssociateWindow();
|
||||
|
||||
if (window && mPluginType == nsPluginHost::eSpecialType_Flash &&
|
||||
!GetPropW((HWND)window, L"PluginInstanceParentProperty")) {
|
||||
HookSetWindowLongPtr();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginNativeWindowWin::SubclassAndAssociateWindow() {
|
||||
if (type != NPWindowTypeWindow || !window) return NS_ERROR_FAILURE;
|
||||
|
||||
HWND hWnd = (HWND)window;
|
||||
|
||||
// check if we need to subclass
|
||||
WNDPROC currentWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
|
||||
if (currentWndProc == PluginWndProc) return NS_OK;
|
||||
|
||||
// If the plugin reset the subclass, set it back.
|
||||
if (mPluginWinProc) {
|
||||
#ifdef DEBUG
|
||||
NS_WARNING("A plugin cleared our subclass - resetting.");
|
||||
if (currentWndProc != mPluginWinProc) {
|
||||
NS_WARNING("Procedures do not match up, discarding old subclass value.");
|
||||
}
|
||||
if (mPrevWinProc && currentWndProc == mPrevWinProc) {
|
||||
NS_WARNING("The new procedure is our widget procedure?");
|
||||
}
|
||||
#endif
|
||||
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PluginWndProc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LONG_PTR style = GetWindowLongPtr(hWnd, GWL_STYLE);
|
||||
// Out of process plugins must not have the WS_CLIPCHILDREN style set on their
|
||||
// parent windows or else synchronous paints (via UpdateWindow() and others)
|
||||
// will cause deadlocks.
|
||||
if (::GetPropW(hWnd, L"PluginInstanceParentProperty"))
|
||||
style &= ~WS_CLIPCHILDREN;
|
||||
else
|
||||
style |= WS_CLIPCHILDREN;
|
||||
SetWindowLongPtr(hWnd, GWL_STYLE, style);
|
||||
|
||||
mPluginWinProc =
|
||||
(WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)PluginWndProc);
|
||||
if (!mPluginWinProc) return NS_ERROR_FAILURE;
|
||||
|
||||
DebugOnly<nsPluginNativeWindowWin*> win = (nsPluginNativeWindowWin*)::GetProp(
|
||||
hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
NS_ASSERTION(!win || (win == this),
|
||||
"plugin window already has property and this is not us");
|
||||
|
||||
if (!::SetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION, (HANDLE)this))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginNativeWindowWin::UndoSubclassAndAssociateWindow() {
|
||||
// remove window property
|
||||
HWND hWnd = (HWND)window;
|
||||
if (IsWindow(hWnd)) ::RemoveProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
|
||||
|
||||
// restore the original win proc
|
||||
// but only do this if this were us last time
|
||||
if (mPluginWinProc) {
|
||||
WNDPROC currentWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
|
||||
if (currentWndProc == PluginWndProc)
|
||||
SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)mPluginWinProc);
|
||||
mPluginWinProc = nullptr;
|
||||
|
||||
LONG_PTR style = GetWindowLongPtr(hWnd, GWL_STYLE);
|
||||
style &= ~WS_CLIPCHILDREN;
|
||||
SetWindowLongPtr(hWnd, GWL_STYLE, style);
|
||||
}
|
||||
|
||||
if (mPluginType == nsPluginHost::eSpecialType_Flash && mParentWnd) {
|
||||
::SetWindowLongPtr(mParentWnd, GWLP_WNDPROC, mParentProc);
|
||||
mParentWnd = nullptr;
|
||||
mParentProc = 0;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PLUG_NewPluginNativeWindow(
|
||||
nsPluginNativeWindow** aPluginNativeWindow) {
|
||||
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
|
||||
|
||||
*aPluginNativeWindow = new nsPluginNativeWindowWin();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult PLUG_DeletePluginNativeWindow(
|
||||
nsPluginNativeWindow* aPluginNativeWindow) {
|
||||
NS_ENSURE_ARG_POINTER(aPluginNativeWindow);
|
||||
nsPluginNativeWindowWin* p = (nsPluginNativeWindowWin*)aPluginNativeWindow;
|
||||
delete p;
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,605 +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 "nsPluginStreamListenerPeer.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsContentPolicyUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsMimeTypes.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsIMultiPartChannel.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
#include "nsPluginInstanceOwner.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/ProfilerLabels.h"
|
||||
|
||||
// nsPluginStreamListenerPeer
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsPluginStreamListenerPeer, nsIStreamListener,
|
||||
nsIRequestObserver, nsIHttpHeaderVisitor,
|
||||
nsISupportsWeakReference, nsIInterfaceRequestor,
|
||||
nsIChannelEventSink)
|
||||
|
||||
nsPluginStreamListenerPeer::nsPluginStreamListenerPeer() : mLength(0) {
|
||||
mStreamType = NP_NORMAL;
|
||||
mStartBinding = false;
|
||||
mRequestFailed = false;
|
||||
|
||||
mPendingRequests = 0;
|
||||
mHaveFiredOnStartRequest = false;
|
||||
|
||||
mUseLocalCache = false;
|
||||
mModified = 0;
|
||||
mStreamOffset = 0;
|
||||
mStreamComplete = 0;
|
||||
}
|
||||
|
||||
nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer() {
|
||||
#ifdef PLUGIN_LOGGING
|
||||
MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
|
||||
("nsPluginStreamListenerPeer::dtor this=%p, url=%s\n", this,
|
||||
mURLSpec.get()));
|
||||
#endif
|
||||
|
||||
if (mPStreamListener) {
|
||||
mPStreamListener->SetStreamListenerPeer(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Called as a result of GetURL and PostURL, or by the host in the case of the
|
||||
// initial plugin stream.
|
||||
nsresult nsPluginStreamListenerPeer::Initialize(
|
||||
nsIURI* aURL, nsNPAPIPluginInstance* aInstance,
|
||||
nsNPAPIPluginStreamListener* aListener) {
|
||||
#ifdef PLUGIN_LOGGING
|
||||
MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL,
|
||||
("nsPluginStreamListenerPeer::Initialize instance=%p, url=%s\n",
|
||||
aInstance, aURL ? aURL->GetSpecOrDefault().get() : ""));
|
||||
|
||||
PR_LogFlush();
|
||||
#endif
|
||||
|
||||
// Not gonna work out
|
||||
if (!aInstance) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mURL = aURL;
|
||||
|
||||
NS_ASSERTION(
|
||||
mPluginInstance == nullptr,
|
||||
"nsPluginStreamListenerPeer::Initialize mPluginInstance != nullptr");
|
||||
mPluginInstance = aInstance;
|
||||
|
||||
// If the plugin did not request this stream, e.g. the initial stream, we wont
|
||||
// have a nsNPAPIPluginStreamListener yet - this will be handled by
|
||||
// SetUpStreamListener
|
||||
if (aListener) {
|
||||
mPStreamListener = aListener;
|
||||
mPStreamListener->SetStreamListenerPeer(this);
|
||||
}
|
||||
|
||||
mPendingRequests = 1;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginStreamListenerPeer::OnStartRequest(nsIRequest* request) {
|
||||
nsresult rv = NS_OK;
|
||||
AUTO_PROFILER_LABEL("nsPluginStreamListenerPeer::OnStartRequest", OTHER);
|
||||
|
||||
if (mRequests.IndexOfObject(request) == -1) {
|
||||
NS_ASSERTION(mRequests.Count() == 0,
|
||||
"Only our initial stream should be unknown!");
|
||||
TrackRequest(request);
|
||||
}
|
||||
|
||||
if (mHaveFiredOnStartRequest) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mHaveFiredOnStartRequest = true;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
NS_ENSURE_TRUE(channel, NS_ERROR_FAILURE);
|
||||
|
||||
// deal with 404 (Not Found) HTTP response,
|
||||
// just return, this causes the request to be ignored.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
|
||||
if (httpChannel) {
|
||||
uint32_t responseCode = 0;
|
||||
rv = httpChannel->GetResponseStatus(&responseCode);
|
||||
if (NS_FAILED(rv)) {
|
||||
// NPP_Notify() will be called from OnStopRequest
|
||||
// in nsNPAPIPluginStreamListener::CleanUpStream
|
||||
// return error will cancel this request
|
||||
// ...and we also need to tell the plugin that
|
||||
mRequestFailed = true;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (responseCode > 206) { // not normal
|
||||
uint32_t wantsAllNetworkStreams = 0;
|
||||
|
||||
// We don't always have an instance here already, but if we do, check
|
||||
// to see if it wants all streams.
|
||||
if (mPluginInstance) {
|
||||
rv = mPluginInstance->GetValueFromPlugin(
|
||||
NPPVpluginWantsAllNetworkStreams, &wantsAllNetworkStreams);
|
||||
// If the call returned an error code make sure we still use our default
|
||||
// value.
|
||||
if (NS_FAILED(rv)) {
|
||||
wantsAllNetworkStreams = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wantsAllNetworkStreams) {
|
||||
mRequestFailed = true;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString contentType;
|
||||
rv = channel->GetContentType(contentType);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Check ShouldProcess with content policy
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->LoadInfo();
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
rv = NS_CheckContentProcessPolicy(mURL, loadInfo, contentType, &shouldLoad);
|
||||
if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) {
|
||||
mRequestFailed = true;
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
|
||||
// Get the notification callbacks from the channel and save it as
|
||||
// week ref we'll use it in nsPluginStreamInfo::RequestRead() when
|
||||
// we'll create channel for byte range request.
|
||||
nsCOMPtr<nsIInterfaceRequestor> callbacks;
|
||||
channel->GetNotificationCallbacks(getter_AddRefs(callbacks));
|
||||
if (callbacks) mWeakPtrChannelCallbacks = do_GetWeakReference(callbacks);
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
channel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
if (loadGroup) mWeakPtrChannelLoadGroup = do_GetWeakReference(loadGroup);
|
||||
|
||||
int64_t length;
|
||||
rv = channel->GetContentLength(&length);
|
||||
|
||||
// it's possible for the server to not send a Content-Length.
|
||||
// we should still work in this case.
|
||||
if (NS_FAILED(rv) || length < 0 || length > UINT32_MAX) {
|
||||
// check out if this is file channel
|
||||
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel);
|
||||
if (fileChannel) {
|
||||
// file does not exist
|
||||
mRequestFailed = true;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mLength = 0;
|
||||
} else {
|
||||
mLength = uint32_t(length);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> aURL;
|
||||
rv = channel->GetURI(getter_AddRefs(aURL));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
aURL->GetSpec(mURLSpec);
|
||||
|
||||
if (!contentType.IsEmpty()) mContentType = contentType;
|
||||
|
||||
#ifdef PLUGIN_LOGGING
|
||||
MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY,
|
||||
("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p "
|
||||
"mime=%s, url=%s\n",
|
||||
this, request, contentType.get(), mURLSpec.get()));
|
||||
|
||||
PR_LogFlush();
|
||||
#endif
|
||||
|
||||
// Set up the stream listener...
|
||||
rv = SetUpStreamListener(request, aURL);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginStreamListenerPeer::OnProgress(nsIRequest* request,
|
||||
int64_t aProgress,
|
||||
int64_t aProgressMax) {
|
||||
nsresult rv = NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStatus(nsIRequest* request,
|
||||
nsresult aStatus,
|
||||
const char16_t* aStatusArg) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::GetContentType(char** result) {
|
||||
*result = const_cast<char*>(mContentType.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::GetLength(uint32_t* result) {
|
||||
*result = mLength;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::GetLastModified(uint32_t* result) {
|
||||
*result = mModified;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::GetURL(const char** result) {
|
||||
*result = mURLSpec.get();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::GetStreamOffset(int32_t* result) {
|
||||
*result = mStreamOffset;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::SetStreamOffset(int32_t value) {
|
||||
mStreamOffset = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(
|
||||
nsIRequest* request, nsIInputStream* aIStream, uint64_t sourceOffset,
|
||||
uint32_t aLength) {
|
||||
if (mRequests.IndexOfObject(request) == -1) {
|
||||
MOZ_ASSERT(false, "Received OnDataAvailable for untracked request.");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (mRequestFailed) return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!mPStreamListener) return NS_ERROR_FAILURE;
|
||||
|
||||
const char* url = nullptr;
|
||||
GetURL(&url);
|
||||
|
||||
PLUGIN_LOG(PLUGIN_LOG_NOISY,
|
||||
("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, "
|
||||
"offset=%" PRIu64 ", length=%u, url=%s\n",
|
||||
this, request, sourceOffset, aLength, url ? url : "no url set"));
|
||||
|
||||
nsCOMPtr<nsIInputStream> stream = aIStream;
|
||||
rv = mPStreamListener->OnDataAvailable(this, stream, aLength);
|
||||
|
||||
// if a plugin returns an error, the peer must kill the stream
|
||||
// else the stream and PluginStreamListener leak
|
||||
if (NS_FAILED(rv)) {
|
||||
request->Cancel(rv);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStopRequest(nsIRequest* request,
|
||||
nsresult aStatus) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIMultiPartChannel> mp = do_QueryInterface(request);
|
||||
if (!mp) {
|
||||
bool found = mRequests.RemoveObject(request);
|
||||
if (!found) {
|
||||
NS_ERROR("Received OnStopRequest for untracked request.");
|
||||
}
|
||||
}
|
||||
|
||||
PLUGIN_LOG(
|
||||
PLUGIN_LOG_NOISY,
|
||||
("nsPluginStreamListenerPeer::OnStopRequest this=%p aStatus=%" PRIu32
|
||||
" request=%p\n",
|
||||
this, static_cast<uint32_t>(aStatus), request));
|
||||
|
||||
// if we still have pending stuff to do, lets not close the plugin socket.
|
||||
if (--mPendingRequests > 0) return NS_OK;
|
||||
|
||||
if (!mPStreamListener) return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
if (!channel) return NS_ERROR_FAILURE;
|
||||
// Set the content type to ensure we don't pass null to the plugin
|
||||
nsAutoCString aContentType;
|
||||
rv = channel->GetContentType(aContentType);
|
||||
if (NS_FAILED(rv) && !mRequestFailed) return rv;
|
||||
|
||||
if (!aContentType.IsEmpty()) mContentType = aContentType;
|
||||
|
||||
// set error status if stream failed so we notify the plugin
|
||||
if (mRequestFailed) aStatus = NS_ERROR_FAILURE;
|
||||
|
||||
if (NS_FAILED(aStatus)) {
|
||||
// on error status cleanup the stream
|
||||
// and return w/o OnFileAvailable()
|
||||
mPStreamListener->OnStopBinding(this, aStatus);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mStartBinding) {
|
||||
// On start binding has been called
|
||||
mPStreamListener->OnStopBinding(this, aStatus);
|
||||
} else {
|
||||
// OnStartBinding hasn't been called, so complete the action.
|
||||
mPStreamListener->OnStartBinding(this);
|
||||
mPStreamListener->OnStopBinding(this, aStatus);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(aStatus)) {
|
||||
mStreamComplete = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest* request,
|
||||
nsIURI* aURL) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// If we don't yet have a stream listener, we need to get
|
||||
// one from the plugin.
|
||||
// NOTE: this should only happen when a stream was NOT created
|
||||
// with GetURL or PostURL (i.e. it's the initial stream we
|
||||
// send to the plugin as determined by the SRC or DATA attribute)
|
||||
if (!mPStreamListener) {
|
||||
if (!mPluginInstance) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<nsNPAPIPluginStreamListener> streamListener;
|
||||
rv = mPluginInstance->NewStreamListener(nullptr, nullptr,
|
||||
getter_AddRefs(streamListener));
|
||||
if (NS_FAILED(rv) || !streamListener) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mPStreamListener =
|
||||
static_cast<nsNPAPIPluginStreamListener*>(streamListener.get());
|
||||
}
|
||||
|
||||
mPStreamListener->SetStreamListenerPeer(this);
|
||||
|
||||
// get httpChannel to retrieve some info we need for nsIPluginStreamInfo setup
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
||||
|
||||
/*
|
||||
* Assumption
|
||||
* By the time nsPluginStreamListenerPeer::OnDataAvailable() gets
|
||||
* called, all the headers have been read.
|
||||
*/
|
||||
if (httpChannel) {
|
||||
// Reassemble the HTTP response status line and provide it to our
|
||||
// listener. Would be nice if we could get the raw status line,
|
||||
// but nsIHttpChannel doesn't currently provide that.
|
||||
// Status code: required; the status line isn't useful without it.
|
||||
uint32_t statusNum;
|
||||
if (NS_SUCCEEDED(httpChannel->GetResponseStatus(&statusNum)) &&
|
||||
statusNum < 1000) {
|
||||
// HTTP version: provide if available. Defaults to empty string.
|
||||
nsCString ver;
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal =
|
||||
do_QueryInterface(channel);
|
||||
if (httpChannelInternal) {
|
||||
uint32_t major, minor;
|
||||
if (NS_SUCCEEDED(
|
||||
httpChannelInternal->GetResponseVersion(&major, &minor))) {
|
||||
ver = nsPrintfCString("/%" PRIu32 ".%" PRIu32, major, minor);
|
||||
}
|
||||
}
|
||||
|
||||
// Status text: provide if available. Defaults to "OK".
|
||||
nsCString statusText;
|
||||
if (NS_FAILED(httpChannel->GetResponseStatusText(statusText))) {
|
||||
statusText = "OK";
|
||||
}
|
||||
|
||||
// Assemble everything and pass to listener.
|
||||
nsPrintfCString status("HTTP%s %" PRIu32 " %s", ver.get(), statusNum,
|
||||
statusText.get());
|
||||
static_cast<nsIHTTPHeaderListener*>(mPStreamListener)
|
||||
->StatusLine(status.get());
|
||||
}
|
||||
|
||||
// Also provide all HTTP response headers to our listener.
|
||||
rv = httpChannel->VisitResponseHeaders(this);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
// we require a content len
|
||||
// get Last-Modified header for plugin info
|
||||
nsAutoCString lastModified;
|
||||
if (NS_SUCCEEDED(
|
||||
httpChannel->GetResponseHeader("last-modified"_ns, lastModified)) &&
|
||||
!lastModified.IsEmpty()) {
|
||||
PRTime time64;
|
||||
PR_ParseTimeString(lastModified.get(), true,
|
||||
&time64); // convert string time to integer time
|
||||
|
||||
// Convert PRTime to unix-style time_t, i.e. seconds since the epoch
|
||||
double fpTime = double(time64);
|
||||
mModified = (uint32_t)(fpTime * 1e-6 + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRequest);
|
||||
mRequest = request;
|
||||
|
||||
rv = mPStreamListener->OnStartBinding(this);
|
||||
|
||||
mStartBinding = true;
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginStreamListenerPeer::VisitHeader(const nsACString& header,
|
||||
const nsACString& value) {
|
||||
return mPStreamListener->NewResponseHeader(PromiseFlatCString(header).get(),
|
||||
PromiseFlatCString(value).get());
|
||||
}
|
||||
|
||||
nsresult nsPluginStreamListenerPeer::GetInterfaceGlobal(const nsIID& aIID,
|
||||
void** result) {
|
||||
if (!mPluginInstance) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner();
|
||||
if (!owner) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozilla::dom::Document> doc;
|
||||
nsresult rv = owner->GetDocument(getter_AddRefs(doc));
|
||||
if (NS_FAILED(rv) || !doc) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* window = doc->GetWindow();
|
||||
if (!window) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(window);
|
||||
nsCOMPtr<nsIInterfaceRequestor> ir = do_QueryInterface(webNav);
|
||||
if (!ir) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ir->GetInterface(aIID, result);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginStreamListenerPeer::GetInterface(const nsIID& aIID, void** result) {
|
||||
// Provide nsIChannelEventSink ourselves, otherwise let our document's
|
||||
// script global object owner provide the interface.
|
||||
if (aIID.Equals(NS_GET_IID(nsIChannelEventSink))) {
|
||||
return QueryInterface(aIID, result);
|
||||
}
|
||||
|
||||
return GetInterfaceGlobal(aIID, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy class which forwards async redirect notifications back to the necko
|
||||
* callback, keeping nsPluginStreamListenerPeer::mRequests in sync with
|
||||
* which channel is active.
|
||||
*/
|
||||
class ChannelRedirectProxyCallback : public nsIAsyncVerifyRedirectCallback {
|
||||
public:
|
||||
ChannelRedirectProxyCallback(nsPluginStreamListenerPeer* listener,
|
||||
nsIAsyncVerifyRedirectCallback* parent,
|
||||
nsIChannel* oldChannel, nsIChannel* newChannel)
|
||||
: mWeakListener(
|
||||
do_GetWeakReference(static_cast<nsIStreamListener*>(listener))),
|
||||
mParent(parent),
|
||||
mOldChannel(oldChannel),
|
||||
mNewChannel(newChannel) {}
|
||||
|
||||
ChannelRedirectProxyCallback() = default;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD OnRedirectVerifyCallback(nsresult aResult) override {
|
||||
if (NS_SUCCEEDED(aResult)) {
|
||||
nsCOMPtr<nsIStreamListener> listener = do_QueryReferent(mWeakListener);
|
||||
if (listener)
|
||||
static_cast<nsPluginStreamListenerPeer*>(listener.get())
|
||||
->ReplaceRequest(mOldChannel, mNewChannel);
|
||||
}
|
||||
return mParent->OnRedirectVerifyCallback(aResult);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual ~ChannelRedirectProxyCallback() = default;
|
||||
|
||||
nsWeakPtr mWeakListener;
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> mParent;
|
||||
nsCOMPtr<nsIChannel> mOldChannel;
|
||||
nsCOMPtr<nsIChannel> mNewChannel;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(ChannelRedirectProxyCallback, nsIAsyncVerifyRedirectCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginStreamListenerPeer::AsyncOnChannelRedirect(
|
||||
nsIChannel* oldChannel, nsIChannel* newChannel, uint32_t flags,
|
||||
nsIAsyncVerifyRedirectCallback* callback) {
|
||||
// Disallow redirects if we don't have a stream listener.
|
||||
if (!mPStreamListener) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Don't allow cross-origin 307/308 POST redirects.
|
||||
nsCOMPtr<nsIHttpChannel> oldHttpChannel(do_QueryInterface(oldChannel));
|
||||
if (oldHttpChannel) {
|
||||
uint32_t responseStatus;
|
||||
nsresult rv = oldHttpChannel->GetResponseStatus(&responseStatus);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (responseStatus == 307 || responseStatus == 308) {
|
||||
nsAutoCString method;
|
||||
rv = oldHttpChannel->GetRequestMethod(method);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (method.EqualsLiteral("POST")) {
|
||||
rv = nsContentUtils::CheckSameOrigin(oldChannel, newChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAsyncVerifyRedirectCallback> proxyCallback =
|
||||
new ChannelRedirectProxyCallback(this, callback, oldChannel, newChannel);
|
||||
|
||||
// Give NPAPI a chance to control redirects.
|
||||
bool notificationHandled = mPStreamListener->HandleRedirectNotification(
|
||||
oldChannel, newChannel, proxyCallback);
|
||||
if (notificationHandled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Fall back to channel event sink for window.
|
||||
nsCOMPtr<nsIChannelEventSink> channelEventSink;
|
||||
nsresult rv = GetInterfaceGlobal(NS_GET_IID(nsIChannelEventSink),
|
||||
getter_AddRefs(channelEventSink));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return channelEventSink->AsyncOnChannelRedirect(oldChannel, newChannel, flags,
|
||||
proxyCallback);
|
||||
}
|
|
@ -1,149 +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 nsPluginStreamListenerPeer_h_
|
||||
#define nsPluginStreamListenerPeer_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIRequest.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "nsNPAPIPluginStreamListener.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
|
||||
class nsIChannel;
|
||||
|
||||
/**
|
||||
* When a plugin requests opens multiple requests to the same URL and
|
||||
* the request must be satified by saving a file to disk, each stream
|
||||
* listener holds a reference to the backing file: the file is only removed
|
||||
* when all the listeners are done.
|
||||
*/
|
||||
class CachedFileHolder {
|
||||
public:
|
||||
explicit CachedFileHolder(nsIFile* cacheFile);
|
||||
~CachedFileHolder();
|
||||
|
||||
void AddRef();
|
||||
void Release();
|
||||
|
||||
nsIFile* file() const { return mFile; }
|
||||
|
||||
private:
|
||||
nsAutoRefCnt mRefCnt;
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
};
|
||||
|
||||
class nsPluginStreamListenerPeer : public nsIStreamListener,
|
||||
public nsIProgressEventSink,
|
||||
public nsIHttpHeaderVisitor,
|
||||
public nsSupportsWeakReference,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIChannelEventSink {
|
||||
virtual ~nsPluginStreamListenerPeer();
|
||||
|
||||
public:
|
||||
nsPluginStreamListenerPeer();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIPROGRESSEVENTSINK
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIHTTPHEADERVISITOR
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
|
||||
// Called by GetURL and PostURL (via NewStream) or by the host in the case of
|
||||
// the initial plugin stream.
|
||||
nsresult Initialize(nsIURI* aURL, nsNPAPIPluginInstance* aInstance,
|
||||
nsNPAPIPluginStreamListener* aListener);
|
||||
|
||||
nsNPAPIPluginInstance* GetPluginInstance() { return mPluginInstance; }
|
||||
|
||||
nsresult GetLength(uint32_t* result);
|
||||
nsresult GetURL(const char** result);
|
||||
nsresult GetLastModified(uint32_t* result);
|
||||
nsresult GetContentType(char** result);
|
||||
nsresult GetStreamOffset(int32_t* result);
|
||||
nsresult SetStreamOffset(int32_t value);
|
||||
|
||||
void TrackRequest(nsIRequest* request) { mRequests.AppendObject(request); }
|
||||
|
||||
void ReplaceRequest(nsIRequest* oldRequest, nsIRequest* newRequest) {
|
||||
int32_t i = mRequests.IndexOfObject(oldRequest);
|
||||
if (i == -1) {
|
||||
NS_ASSERTION(mRequests.Count() == 0,
|
||||
"Only our initial stream should be unknown!");
|
||||
mRequests.AppendObject(oldRequest);
|
||||
} else {
|
||||
mRequests.ReplaceObjectAt(newRequest, i);
|
||||
}
|
||||
}
|
||||
|
||||
void CancelRequests(nsresult status) {
|
||||
// Copy the array to avoid modification during the loop.
|
||||
nsCOMArray<nsIRequest> requestsCopy(mRequests);
|
||||
for (int32_t i = 0; i < requestsCopy.Count(); ++i)
|
||||
requestsCopy[i]->Cancel(status);
|
||||
}
|
||||
|
||||
void SuspendRequests() {
|
||||
nsCOMArray<nsIRequest> requestsCopy(mRequests);
|
||||
for (int32_t i = 0; i < requestsCopy.Count(); ++i)
|
||||
requestsCopy[i]->Suspend();
|
||||
}
|
||||
|
||||
void ResumeRequests() {
|
||||
nsCOMArray<nsIRequest> requestsCopy(mRequests);
|
||||
for (int32_t i = 0; i < requestsCopy.Count(); ++i)
|
||||
requestsCopy[i]->Resume();
|
||||
}
|
||||
|
||||
private:
|
||||
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
|
||||
nsresult GetInterfaceGlobal(const nsIID& aIID, void** result);
|
||||
|
||||
nsCOMPtr<nsIURI> mURL;
|
||||
nsCString
|
||||
mURLSpec; // Have to keep this member because GetURL hands out char*
|
||||
RefPtr<nsNPAPIPluginStreamListener> mPStreamListener;
|
||||
|
||||
// Set to true if we request failed (like with a HTTP response of 404)
|
||||
bool mRequestFailed;
|
||||
|
||||
/*
|
||||
* Set to true after nsNPAPIPluginStreamListener::OnStartBinding() has
|
||||
* been called. Checked in ::OnStopRequest so we can call the
|
||||
* plugin's OnStartBinding if, for some reason, it has not already
|
||||
* been called.
|
||||
*/
|
||||
bool mStartBinding;
|
||||
bool mHaveFiredOnStartRequest;
|
||||
// these get passed to the plugin stream listener
|
||||
uint32_t mLength;
|
||||
int32_t mStreamType;
|
||||
|
||||
nsCString mContentType;
|
||||
bool mUseLocalCache;
|
||||
nsCOMPtr<nsIRequest> mRequest;
|
||||
uint32_t mModified;
|
||||
RefPtr<nsNPAPIPluginInstance> mPluginInstance;
|
||||
int32_t mStreamOffset;
|
||||
bool mStreamComplete;
|
||||
|
||||
public:
|
||||
int32_t mPendingRequests;
|
||||
nsWeakPtr mWeakPtrChannelCallbacks;
|
||||
nsWeakPtr mWeakPtrChannelLoadGroup;
|
||||
nsCOMArray<nsIRequest> mRequests;
|
||||
};
|
||||
|
||||
#endif // nsPluginStreamListenerPeer_h_
|
|
@ -7,11 +7,9 @@
|
|||
|
||||
#include "prlink.h"
|
||||
#include "plstr.h"
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsPluginHost.h"
|
||||
#include "nsIBlocklistService.h"
|
||||
#include "nsPluginLogging.h"
|
||||
#include "nsNPAPIPlugin.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
@ -194,28 +192,6 @@ bool nsIInternalPluginTag::HasMimeType(const nsACString& aMimeType) const {
|
|||
|
||||
/* nsPluginTag */
|
||||
|
||||
nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo, int64_t aLastModifiedTime,
|
||||
uint32_t aBlocklistState)
|
||||
: nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription,
|
||||
aPluginInfo->fFileName, aPluginInfo->fVersion),
|
||||
mId(sNextId++),
|
||||
mContentProcessRunningCount(0),
|
||||
mHadLocalInstance(false),
|
||||
mLibrary(nullptr),
|
||||
mIsFlashPlugin(false),
|
||||
mSupportsAsyncRender(false),
|
||||
mFullPath(aPluginInfo->fFullPath),
|
||||
mLastModifiedTime(aLastModifiedTime),
|
||||
mSandboxLevel(0),
|
||||
mIsSandboxLoggingEnabled(false),
|
||||
mBlocklistState(aBlocklistState) {
|
||||
InitMime(aPluginInfo->fMimeTypeArray, aPluginInfo->fMimeDescriptionArray,
|
||||
aPluginInfo->fExtensionArray, aPluginInfo->fVariantCount);
|
||||
InitSandboxLevel();
|
||||
EnsureMembersAreUTF8();
|
||||
FixupVersion();
|
||||
}
|
||||
|
||||
nsPluginTag::nsPluginTag(const char* aName, const char* aDescription,
|
||||
const char* aFileName, const char* aFullPath,
|
||||
const char* aVersion, const char* const* aMimeTypes,
|
||||
|
@ -579,22 +555,9 @@ bool nsPluginTag::HasSameNameAndMimes(const nsPluginTag* aPluginTag) const {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPluginTag::GetLoaded(bool* aIsLoaded) {
|
||||
*aIsLoaded = !!mPlugin;
|
||||
return NS_OK;
|
||||
}
|
||||
nsPluginTag::GetLoaded(bool* aIsLoaded) { return NS_ERROR_FAILURE; }
|
||||
|
||||
void nsPluginTag::TryUnloadPlugin(bool inShutdown) {
|
||||
// We never want to send NPP_Shutdown to an in-process plugin unless
|
||||
// this process is shutting down.
|
||||
if (!mPlugin) {
|
||||
return;
|
||||
}
|
||||
if (inShutdown || mPlugin->GetLibrary()->IsOOP()) {
|
||||
mPlugin->Shutdown();
|
||||
mPlugin = nullptr;
|
||||
}
|
||||
}
|
||||
void nsPluginTag::TryUnloadPlugin(bool inShutdown) {}
|
||||
|
||||
/* static */ void nsPluginTag::EnsureSandboxInformation() {
|
||||
if (sInitializedSandboxingInfo) {
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
|
||||
class nsIURI;
|
||||
struct PRLibrary;
|
||||
struct nsPluginInfo;
|
||||
class nsNPAPIPlugin;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -113,8 +111,6 @@ class nsPluginTag final : public nsIInternalPluginTag {
|
|||
ePluginState_MaxValue = 3,
|
||||
};
|
||||
|
||||
nsPluginTag(nsPluginInfo* aPluginInfo, int64_t aLastModifiedTime,
|
||||
uint32_t aBlocklistState);
|
||||
nsPluginTag(const char* aName, const char* aDescription,
|
||||
const char* aFileName, const char* aFullPath,
|
||||
const char* aVersion, const char* const* aMimeTypes,
|
||||
|
@ -161,7 +157,6 @@ class nsPluginTag final : public nsIInternalPluginTag {
|
|||
bool mHadLocalInstance;
|
||||
|
||||
PRLibrary* mLibrary;
|
||||
RefPtr<nsNPAPIPlugin> mPlugin;
|
||||
bool mIsFlashPlugin;
|
||||
bool mSupportsAsyncRender;
|
||||
nsCString mFullPath; // UTF-8
|
||||
|
|
|
@ -1,16 +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 nsPluginsCID_h_
|
||||
#define nsPluginsCID_h_
|
||||
|
||||
#define NS_PLUGIN_HOST_CID \
|
||||
{ \
|
||||
0x23E8FD98, 0xA625, 0x4B08, { \
|
||||
0xBE, 0x1A, 0xF7, 0xCC, 0x18, 0xA5, 0xB1, 0x06 \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // nsPluginsCID_h_
|
|
@ -1,80 +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 nsPluginsDir_h_
|
||||
#define nsPluginsDir_h_
|
||||
|
||||
#include "nsError.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
/**
|
||||
* nsPluginsDir is nearly obsolete. Directory Service should be used instead.
|
||||
* It exists for the sake of one static function.
|
||||
*/
|
||||
|
||||
class nsPluginsDir {
|
||||
public:
|
||||
/**
|
||||
* Determines whether or not the given file is actually a plugin file.
|
||||
*/
|
||||
static bool IsPluginFile(nsIFile* file);
|
||||
};
|
||||
|
||||
struct PRLibrary;
|
||||
|
||||
struct nsPluginInfo {
|
||||
char* fName; // name of the plugin
|
||||
char* fDescription; // etc.
|
||||
uint32_t fVariantCount;
|
||||
char** fMimeTypeArray;
|
||||
char** fMimeDescriptionArray;
|
||||
char** fExtensionArray;
|
||||
char* fFileName;
|
||||
char* fFullPath;
|
||||
char* fVersion;
|
||||
bool fSupportsAsyncRender;
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides cross-platform access to a plugin file. Deals with reading
|
||||
* properties from the plugin file, and loading the plugin's shared
|
||||
* library. Insulates core nsIPluginHost implementations from these
|
||||
* details.
|
||||
*/
|
||||
class nsPluginFile {
|
||||
#ifndef XP_WIN
|
||||
PRLibrary* pLibrary;
|
||||
#endif
|
||||
nsCOMPtr<nsIFile> mPlugin;
|
||||
|
||||
public:
|
||||
/**
|
||||
* If spec corresponds to a valid plugin file, constructs a reference
|
||||
* to a plugin file on disk. Plugins are typically located using the
|
||||
* nsPluginsDir class.
|
||||
*/
|
||||
explicit nsPluginFile(nsIFile* spec);
|
||||
virtual ~nsPluginFile();
|
||||
|
||||
/**
|
||||
* Loads the plugin into memory using NSPR's shared-library loading
|
||||
* mechanism. Handles platform differences in loading shared libraries.
|
||||
*/
|
||||
nsresult LoadPlugin(PRLibrary** outLibrary);
|
||||
|
||||
/**
|
||||
* Obtains all of the information currently available for this plugin.
|
||||
* Has a library outparam which will be non-null if a library load was
|
||||
* required.
|
||||
*/
|
||||
nsresult GetPluginInfo(nsPluginInfo& outPluginInfo, PRLibrary** outLibrary);
|
||||
|
||||
/**
|
||||
* Should be called after GetPluginInfo to free all allocated stuff
|
||||
*/
|
||||
nsresult FreePluginInfo(nsPluginInfo& PluginInfo);
|
||||
};
|
||||
|
||||
#endif /* nsPluginsDir_h_ */
|
|
@ -1,522 +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/. */
|
||||
|
||||
/*
|
||||
nsPluginsDirDarwin.cpp
|
||||
|
||||
Mac OS X implementation of the nsPluginsDir/nsPluginsFile classes.
|
||||
|
||||
by Patrick C. Beard.
|
||||
*/
|
||||
|
||||
#include "GeckoChildProcessHost.h"
|
||||
#include "base/process_util.h"
|
||||
|
||||
#include "prlink.h"
|
||||
#include "prnetdb.h"
|
||||
#include "nsXPCOM.h"
|
||||
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsNPAPIPlugin.h"
|
||||
#include "nsPluginsDirUtils.h"
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
#include "nsCocoaFeatures.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/fat.h>
|
||||
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(const char*, NP_GETMIMEDESCRIPTION)();
|
||||
typedef NS_NPAPIPLUGIN_CALLBACK(OSErr, BP_GETSUPPORTEDMIMETYPES)(
|
||||
BPSupportedMIMETypes* mimeInfo, UInt32 flags);
|
||||
|
||||
/*
|
||||
** Returns a CFBundleRef if the path refers to a Mac OS X bundle directory.
|
||||
** The caller is responsible for calling CFRelease() to deallocate.
|
||||
*/
|
||||
static CFBundleRef getPluginBundle(const char* path) {
|
||||
CFBundleRef bundle = nullptr;
|
||||
CFStringRef pathRef =
|
||||
::CFStringCreateWithCString(nullptr, path, kCFStringEncodingUTF8);
|
||||
if (pathRef) {
|
||||
CFURLRef bundleURL = ::CFURLCreateWithFileSystemPath(
|
||||
nullptr, pathRef, kCFURLPOSIXPathStyle, true);
|
||||
if (bundleURL) {
|
||||
bundle = ::CFBundleCreate(nullptr, bundleURL);
|
||||
::CFRelease(bundleURL);
|
||||
}
|
||||
::CFRelease(pathRef);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
bool nsPluginsDir::IsPluginFile(nsIFile* file) {
|
||||
nsCString fileName;
|
||||
file->GetNativeLeafName(fileName);
|
||||
/*
|
||||
* Don't load the VDP fake plugin, to avoid tripping a bad bug in OS X
|
||||
* 10.5.3 (see bug 436575).
|
||||
*/
|
||||
if (!strcmp(fileName.get(), "VerifiedDownloadPlugin.plugin")) {
|
||||
NS_WARNING(
|
||||
"Preventing load of VerifiedDownloadPlugin.plugin (see bug 436575)");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Caller is responsible for freeing returned buffer.
|
||||
static char* CFStringRefToUTF8Buffer(CFStringRef cfString) {
|
||||
const char* buffer = ::CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8);
|
||||
if (buffer) {
|
||||
return PL_strdup(buffer);
|
||||
}
|
||||
|
||||
int64_t bufferLength =
|
||||
::CFStringGetMaximumSizeForEncoding(::CFStringGetLength(cfString),
|
||||
kCFStringEncodingUTF8) +
|
||||
1;
|
||||
char* newBuffer = static_cast<char*>(moz_xmalloc(bufferLength));
|
||||
|
||||
if (!::CFStringGetCString(cfString, newBuffer, bufferLength,
|
||||
kCFStringEncodingUTF8)) {
|
||||
free(newBuffer);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newBuffer =
|
||||
static_cast<char*>(moz_xrealloc(newBuffer, strlen(newBuffer) + 1));
|
||||
return newBuffer;
|
||||
}
|
||||
|
||||
class AutoCFTypeObject {
|
||||
public:
|
||||
explicit AutoCFTypeObject(CFTypeRef aObject) { mObject = aObject; }
|
||||
~AutoCFTypeObject() { ::CFRelease(mObject); }
|
||||
|
||||
private:
|
||||
CFTypeRef mObject;
|
||||
};
|
||||
|
||||
static Boolean MimeTypeEnabled(CFDictionaryRef mimeDict) {
|
||||
if (!mimeDict) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CFTypeRef value;
|
||||
if (::CFDictionaryGetValueIfPresent(mimeDict, CFSTR("WebPluginTypeEnabled"),
|
||||
&value)) {
|
||||
if (value && ::CFGetTypeID(value) == ::CFBooleanGetTypeID()) {
|
||||
return ::CFBooleanGetValue(static_cast<CFBooleanRef>(value));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static CFDictionaryRef ParsePlistForMIMETypesFilename(CFBundleRef bundle) {
|
||||
CFTypeRef mimeFileName = ::CFBundleGetValueForInfoDictionaryKey(
|
||||
bundle, CFSTR("WebPluginMIMETypesFilename"));
|
||||
if (!mimeFileName || ::CFGetTypeID(mimeFileName) != ::CFStringGetTypeID()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FSRef homeDir;
|
||||
if (::FSFindFolder(kUserDomain, kCurrentUserFolderType, kDontCreateFolder,
|
||||
&homeDir) != noErr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CFURLRef userDirURL = ::CFURLCreateFromFSRef(kCFAllocatorDefault, &homeDir);
|
||||
if (!userDirURL) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoCFTypeObject userDirURLAutorelease(userDirURL);
|
||||
CFStringRef mimeFilePath = ::CFStringCreateWithFormat(
|
||||
kCFAllocatorDefault, nullptr, CFSTR("Library/Preferences/%@"),
|
||||
static_cast<CFStringRef>(mimeFileName));
|
||||
if (!mimeFilePath) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoCFTypeObject mimeFilePathAutorelease(mimeFilePath);
|
||||
CFURLRef mimeFileURL = ::CFURLCreateWithFileSystemPathRelativeToBase(
|
||||
kCFAllocatorDefault, mimeFilePath, kCFURLPOSIXPathStyle, false,
|
||||
userDirURL);
|
||||
if (!mimeFileURL) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoCFTypeObject mimeFileURLAutorelease(mimeFileURL);
|
||||
SInt32 errorCode = 0;
|
||||
CFDataRef mimeFileData = nullptr;
|
||||
Boolean result = ::CFURLCreateDataAndPropertiesFromResource(
|
||||
kCFAllocatorDefault, mimeFileURL, &mimeFileData, nullptr, nullptr,
|
||||
&errorCode);
|
||||
if (!result) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoCFTypeObject mimeFileDataAutorelease(mimeFileData);
|
||||
if (errorCode != 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CFPropertyListRef propertyList = ::CFPropertyListCreateFromXMLData(
|
||||
kCFAllocatorDefault, mimeFileData, kCFPropertyListImmutable, nullptr);
|
||||
if (!propertyList) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AutoCFTypeObject propertyListAutorelease(propertyList);
|
||||
if (::CFGetTypeID(propertyList) != ::CFDictionaryGetTypeID()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CFTypeRef mimeTypes = ::CFDictionaryGetValue(
|
||||
static_cast<CFDictionaryRef>(propertyList), CFSTR("WebPluginMIMETypes"));
|
||||
if (!mimeTypes || ::CFGetTypeID(mimeTypes) != ::CFDictionaryGetTypeID() ||
|
||||
::CFDictionaryGetCount(static_cast<CFDictionaryRef>(mimeTypes)) == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<CFDictionaryRef>(::CFRetain(mimeTypes));
|
||||
}
|
||||
|
||||
static void ParsePlistPluginInfo(nsPluginInfo& info, CFBundleRef bundle) {
|
||||
CFDictionaryRef mimeDict = ParsePlistForMIMETypesFilename(bundle);
|
||||
|
||||
if (!mimeDict) {
|
||||
CFTypeRef mimeTypes = ::CFBundleGetValueForInfoDictionaryKey(
|
||||
bundle, CFSTR("WebPluginMIMETypes"));
|
||||
if (!mimeTypes || ::CFGetTypeID(mimeTypes) != ::CFDictionaryGetTypeID() ||
|
||||
::CFDictionaryGetCount(static_cast<CFDictionaryRef>(mimeTypes)) == 0)
|
||||
return;
|
||||
mimeDict = static_cast<CFDictionaryRef>(::CFRetain(mimeTypes));
|
||||
}
|
||||
|
||||
AutoCFTypeObject mimeDictAutorelease(mimeDict);
|
||||
int mimeDictKeyCount = ::CFDictionaryGetCount(mimeDict);
|
||||
|
||||
// Allocate memory for mime data
|
||||
int mimeDataArraySize = mimeDictKeyCount * sizeof(char*);
|
||||
info.fMimeTypeArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
|
||||
memset(info.fMimeTypeArray, 0, mimeDataArraySize);
|
||||
info.fExtensionArray = static_cast<char**>(moz_xmalloc(mimeDataArraySize));
|
||||
memset(info.fExtensionArray, 0, mimeDataArraySize);
|
||||
info.fMimeDescriptionArray =
|
||||
static_cast<char**>(moz_xmalloc(mimeDataArraySize));
|
||||
memset(info.fMimeDescriptionArray, 0, mimeDataArraySize);
|
||||
|
||||
// Allocate memory for mime dictionary keys and values
|
||||
mozilla::UniquePtr<CFTypeRef[]> keys(new CFTypeRef[mimeDictKeyCount]);
|
||||
mozilla::UniquePtr<CFTypeRef[]> values(new CFTypeRef[mimeDictKeyCount]);
|
||||
|
||||
info.fVariantCount = 0;
|
||||
|
||||
::CFDictionaryGetKeysAndValues(mimeDict, keys.get(), values.get());
|
||||
for (int i = 0; i < mimeDictKeyCount; i++) {
|
||||
CFTypeRef mimeString = keys[i];
|
||||
if (!mimeString || ::CFGetTypeID(mimeString) != ::CFStringGetTypeID()) {
|
||||
continue;
|
||||
}
|
||||
CFTypeRef mimeDict = values[i];
|
||||
if (mimeDict && ::CFGetTypeID(mimeDict) == ::CFDictionaryGetTypeID()) {
|
||||
if (!MimeTypeEnabled(static_cast<CFDictionaryRef>(mimeDict))) {
|
||||
continue;
|
||||
}
|
||||
info.fMimeTypeArray[info.fVariantCount] =
|
||||
CFStringRefToUTF8Buffer(static_cast<CFStringRef>(mimeString));
|
||||
if (!info.fMimeTypeArray[info.fVariantCount]) {
|
||||
continue;
|
||||
}
|
||||
CFTypeRef extensions = ::CFDictionaryGetValue(
|
||||
static_cast<CFDictionaryRef>(mimeDict), CFSTR("WebPluginExtensions"));
|
||||
if (extensions && ::CFGetTypeID(extensions) == ::CFArrayGetTypeID()) {
|
||||
int extensionCount =
|
||||
::CFArrayGetCount(static_cast<CFArrayRef>(extensions));
|
||||
CFMutableStringRef extensionList =
|
||||
::CFStringCreateMutable(kCFAllocatorDefault, 0);
|
||||
for (int j = 0; j < extensionCount; j++) {
|
||||
CFTypeRef extension =
|
||||
::CFArrayGetValueAtIndex(static_cast<CFArrayRef>(extensions), j);
|
||||
if (extension && ::CFGetTypeID(extension) == ::CFStringGetTypeID()) {
|
||||
if (j > 0) ::CFStringAppend(extensionList, CFSTR(","));
|
||||
::CFStringAppend(static_cast<CFMutableStringRef>(extensionList),
|
||||
static_cast<CFStringRef>(extension));
|
||||
}
|
||||
}
|
||||
info.fExtensionArray[info.fVariantCount] =
|
||||
CFStringRefToUTF8Buffer(static_cast<CFStringRef>(extensionList));
|
||||
::CFRelease(extensionList);
|
||||
}
|
||||
CFTypeRef description =
|
||||
::CFDictionaryGetValue(static_cast<CFDictionaryRef>(mimeDict),
|
||||
CFSTR("WebPluginTypeDescription"));
|
||||
if (description && ::CFGetTypeID(description) == ::CFStringGetTypeID())
|
||||
info.fMimeDescriptionArray[info.fVariantCount] =
|
||||
CFStringRefToUTF8Buffer(static_cast<CFStringRef>(description));
|
||||
}
|
||||
info.fVariantCount++;
|
||||
}
|
||||
}
|
||||
|
||||
nsPluginFile::nsPluginFile(nsIFile* spec) : pLibrary(nullptr), mPlugin(spec) {}
|
||||
|
||||
nsPluginFile::~nsPluginFile() {}
|
||||
|
||||
nsresult nsPluginFile::LoadPlugin(PRLibrary** outLibrary) {
|
||||
if (!mPlugin) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// 64-bit NSPR does not (yet) support bundles. So in 64-bit builds we need
|
||||
// (for now) to load the bundle's executable. However this can cause
|
||||
// problems: CFBundleCreate() doesn't run the bundle's executable's
|
||||
// initialization code, while NSAddImage() and dlopen() do run it. So using
|
||||
// NSPR's dyld loading mechanisms here (NSAddImage() or dlopen()) can cause
|
||||
// a bundle's initialization code to run earlier than expected, and lead to
|
||||
// crashes. See bug 577967.
|
||||
#ifdef __LP64__
|
||||
char executablePath[PATH_MAX];
|
||||
executablePath[0] = '\0';
|
||||
nsAutoCString bundlePath;
|
||||
mPlugin->GetNativePath(bundlePath);
|
||||
CFStringRef pathRef = ::CFStringCreateWithCString(nullptr, bundlePath.get(),
|
||||
kCFStringEncodingUTF8);
|
||||
if (pathRef) {
|
||||
CFURLRef bundleURL = ::CFURLCreateWithFileSystemPath(
|
||||
nullptr, pathRef, kCFURLPOSIXPathStyle, true);
|
||||
if (bundleURL) {
|
||||
CFBundleRef bundle = ::CFBundleCreate(nullptr, bundleURL);
|
||||
if (bundle) {
|
||||
CFURLRef executableURL = ::CFBundleCopyExecutableURL(bundle);
|
||||
if (executableURL) {
|
||||
if (!::CFURLGetFileSystemRepresentation(
|
||||
executableURL, true, (UInt8*)&executablePath, PATH_MAX))
|
||||
executablePath[0] = '\0';
|
||||
::CFRelease(executableURL);
|
||||
}
|
||||
::CFRelease(bundle);
|
||||
}
|
||||
::CFRelease(bundleURL);
|
||||
}
|
||||
::CFRelease(pathRef);
|
||||
}
|
||||
#else
|
||||
nsAutoCString bundlePath;
|
||||
mPlugin->GetNativePath(bundlePath);
|
||||
const char* executablePath = bundlePath.get();
|
||||
#endif
|
||||
|
||||
*outLibrary = PR_LoadLibrary(executablePath);
|
||||
pLibrary = *outLibrary;
|
||||
if (!pLibrary) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("[loaded plugin %s]\n", bundlePath.get());
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static char* p2cstrdup(StringPtr pstr) {
|
||||
int len = pstr[0];
|
||||
char* cstr = static_cast<char*>(moz_xmalloc(len + 1));
|
||||
memmove(cstr, pstr + 1, len);
|
||||
cstr[len] = '\0';
|
||||
return cstr;
|
||||
}
|
||||
|
||||
static char* GetNextPluginStringFromHandle(Handle h, short* index) {
|
||||
char* ret = p2cstrdup((unsigned char*)(*h + *index));
|
||||
*index += (ret ? strlen(ret) : 0) + 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains all of the information currently available for this plugin.
|
||||
*/
|
||||
nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info,
|
||||
PRLibrary** outLibrary) {
|
||||
*outLibrary = nullptr;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
// clear out the info, except for the first field.
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
// Try to get a bundle reference.
|
||||
nsAutoCString path;
|
||||
if (NS_FAILED(rv = mPlugin->GetNativePath(path))) return rv;
|
||||
CFBundleRef bundle = getPluginBundle(path.get());
|
||||
|
||||
// fill in full path
|
||||
info.fFullPath = PL_strdup(path.get());
|
||||
|
||||
// fill in file name
|
||||
nsAutoCString fileName;
|
||||
if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName))) return rv;
|
||||
info.fFileName = PL_strdup(fileName.get());
|
||||
|
||||
// Get fName
|
||||
if (bundle) {
|
||||
CFTypeRef name =
|
||||
::CFBundleGetValueForInfoDictionaryKey(bundle, CFSTR("WebPluginName"));
|
||||
if (name && ::CFGetTypeID(name) == ::CFStringGetTypeID())
|
||||
info.fName = CFStringRefToUTF8Buffer(static_cast<CFStringRef>(name));
|
||||
}
|
||||
|
||||
// Get fDescription
|
||||
if (bundle) {
|
||||
CFTypeRef description = ::CFBundleGetValueForInfoDictionaryKey(
|
||||
bundle, CFSTR("WebPluginDescription"));
|
||||
if (description && ::CFGetTypeID(description) == ::CFStringGetTypeID())
|
||||
info.fDescription =
|
||||
CFStringRefToUTF8Buffer(static_cast<CFStringRef>(description));
|
||||
}
|
||||
|
||||
// Get fVersion
|
||||
if (bundle) {
|
||||
// Look for the release version first
|
||||
CFTypeRef version = ::CFBundleGetValueForInfoDictionaryKey(
|
||||
bundle, CFSTR("CFBundleShortVersionString"));
|
||||
if (!version) // try the build version
|
||||
version =
|
||||
::CFBundleGetValueForInfoDictionaryKey(bundle, kCFBundleVersionKey);
|
||||
if (version && ::CFGetTypeID(version) == ::CFStringGetTypeID())
|
||||
info.fVersion =
|
||||
CFStringRefToUTF8Buffer(static_cast<CFStringRef>(version));
|
||||
}
|
||||
|
||||
// The last thing we need to do is get MIME data
|
||||
// fVariantCount, fMimeTypeArray, fExtensionArray, fMimeDescriptionArray
|
||||
|
||||
// First look for data in a bundle plist
|
||||
if (bundle) {
|
||||
ParsePlistPluginInfo(info, bundle);
|
||||
::CFRelease(bundle);
|
||||
if (info.fVariantCount > 0) return NS_OK;
|
||||
}
|
||||
|
||||
// Don't load "fbplugin" or any plugins whose name starts with "fbplugin_"
|
||||
// (Facebook plugins) if we're running on OS X 10.10 (Yosemite) or later.
|
||||
// A "fbplugin" file crashes on load, in the call to LoadPlugin() below.
|
||||
// See bug 1086977.
|
||||
if (fileName.EqualsLiteral("fbplugin") ||
|
||||
StringBeginsWith(fileName, "fbplugin_"_ns)) {
|
||||
nsAutoCString msg;
|
||||
msg.AppendPrintf("Preventing load of %s (see bug 1086977)", fileName.get());
|
||||
NS_WARNING(msg.get());
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// The block above assumes that "fbplugin" is the filename of the plugin
|
||||
// to be blocked, or that the filename starts with "fbplugin_". But we
|
||||
// don't yet know for sure if this is always true. So for the time being
|
||||
// record extra information in our crash logs.
|
||||
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::Bug_1086977,
|
||||
fileName);
|
||||
|
||||
// It's possible that our plugin has 2 entry points that'll give us mime type
|
||||
// info. Quicktime does this to get around the need of having admin rights to
|
||||
// change mime info in the resource fork. We need to use this info instead of
|
||||
// the resource. See bug 113464.
|
||||
|
||||
// Sadly we have to load the library for this to work.
|
||||
rv = LoadPlugin(outLibrary);
|
||||
|
||||
// If we didn't crash in LoadPlugin(), remove the annotation so we don't
|
||||
// sow confusion.
|
||||
CrashReporter::RemoveCrashReportAnnotation(
|
||||
CrashReporter::Annotation::Bug_1086977);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Try to get data from NP_GetMIMEDescription
|
||||
if (pLibrary) {
|
||||
NP_GETMIMEDESCRIPTION pfnGetMimeDesc =
|
||||
(NP_GETMIMEDESCRIPTION)PR_FindFunctionSymbol(
|
||||
pLibrary, NP_GETMIMEDESCRIPTION_NAME);
|
||||
if (pfnGetMimeDesc) ParsePluginMimeDescription(pfnGetMimeDesc(), info);
|
||||
if (info.fVariantCount) return NS_OK;
|
||||
}
|
||||
|
||||
// We'll fill this in using BP_GetSupportedMIMETypes and/or resource fork data
|
||||
BPSupportedMIMETypes mi = {kBPSupportedMIMETypesStructVers_1, nullptr,
|
||||
nullptr};
|
||||
|
||||
// Try to get data from BP_GetSupportedMIMETypes
|
||||
if (pLibrary) {
|
||||
BP_GETSUPPORTEDMIMETYPES pfnMime =
|
||||
(BP_GETSUPPORTEDMIMETYPES)PR_FindFunctionSymbol(
|
||||
pLibrary, "BP_GetSupportedMIMETypes");
|
||||
if (pfnMime && noErr == pfnMime(&mi, 0) && mi.typeStrings) {
|
||||
info.fVariantCount = (**(short**)mi.typeStrings) / 2;
|
||||
::HLock(mi.typeStrings);
|
||||
if (mi.infoStrings) // it's possible some plugins have infoStrings
|
||||
// missing
|
||||
::HLock(mi.infoStrings);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the info struct based on the data in the BPSupportedMIMETypes
|
||||
// struct
|
||||
int variantCount = info.fVariantCount;
|
||||
info.fMimeTypeArray =
|
||||
static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
|
||||
info.fExtensionArray =
|
||||
static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
|
||||
if (mi.infoStrings) {
|
||||
info.fMimeDescriptionArray =
|
||||
static_cast<char**>(moz_xmalloc(variantCount * sizeof(char*)));
|
||||
}
|
||||
short mimeIndex = 2;
|
||||
short descriptionIndex = 2;
|
||||
for (int i = 0; i < variantCount; i++) {
|
||||
info.fMimeTypeArray[i] =
|
||||
GetNextPluginStringFromHandle(mi.typeStrings, &mimeIndex);
|
||||
info.fExtensionArray[i] =
|
||||
GetNextPluginStringFromHandle(mi.typeStrings, &mimeIndex);
|
||||
if (mi.infoStrings)
|
||||
info.fMimeDescriptionArray[i] =
|
||||
GetNextPluginStringFromHandle(mi.infoStrings, &descriptionIndex);
|
||||
}
|
||||
|
||||
::HUnlock(mi.typeStrings);
|
||||
::DisposeHandle(mi.typeStrings);
|
||||
if (mi.infoStrings) {
|
||||
::HUnlock(mi.infoStrings);
|
||||
::DisposeHandle(mi.infoStrings);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info) {
|
||||
free(info.fName);
|
||||
free(info.fDescription);
|
||||
int variantCount = info.fVariantCount;
|
||||
for (int i = 0; i < variantCount; i++) {
|
||||
free(info.fMimeTypeArray[i]);
|
||||
free(info.fExtensionArray[i]);
|
||||
free(info.fMimeDescriptionArray[i]);
|
||||
}
|
||||
free(info.fMimeTypeArray);
|
||||
free(info.fMimeDescriptionArray);
|
||||
free(info.fExtensionArray);
|
||||
free(info.fFileName);
|
||||
free(info.fFullPath);
|
||||
free(info.fVersion);
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,188 +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/. */
|
||||
|
||||
#include "nsNPAPIPlugin.h"
|
||||
#include "nsNPAPIPluginInstance.h"
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsPluginsDirUtils.h"
|
||||
#include "prenv.h"
|
||||
#include "prerror.h"
|
||||
#include "prio.h"
|
||||
#include <sys/stat.h>
|
||||
#include "nsString.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
#define LOCAL_PLUGIN_DLL_SUFFIX ".so"
|
||||
#if defined(__hpux)
|
||||
# define DEFAULT_X11_PATH "/usr/lib/X11R6/"
|
||||
# undef LOCAL_PLUGIN_DLL_SUFFIX
|
||||
# define LOCAL_PLUGIN_DLL_SUFFIX ".sl"
|
||||
# define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".so"
|
||||
#elif defined(_AIX)
|
||||
# define DEFAULT_X11_PATH "/usr/lib"
|
||||
# define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".a"
|
||||
#elif defined(SOLARIS)
|
||||
# define DEFAULT_X11_PATH "/usr/openwin/lib/"
|
||||
#elif defined(LINUX)
|
||||
# define DEFAULT_X11_PATH "/usr/X11R6/lib/"
|
||||
#elif defined(__APPLE__)
|
||||
# define DEFAULT_X11_PATH "/usr/X11R6/lib"
|
||||
# undef LOCAL_PLUGIN_DLL_SUFFIX
|
||||
# define LOCAL_PLUGIN_DLL_SUFFIX ".dylib"
|
||||
# define LOCAL_PLUGIN_DLL_ALT_SUFFIX ".so"
|
||||
#else
|
||||
# define DEFAULT_X11_PATH ""
|
||||
#endif
|
||||
|
||||
/* nsPluginsDir implementation */
|
||||
|
||||
bool nsPluginsDir::IsPluginFile(nsIFile* file) {
|
||||
nsAutoCString filename;
|
||||
if (NS_FAILED(file->GetNativeLeafName(filename))) return false;
|
||||
|
||||
constexpr auto dllSuffix = nsLiteralCString{LOCAL_PLUGIN_DLL_SUFFIX};
|
||||
if (filename.Length() > dllSuffix.Length() &&
|
||||
StringEndsWith(filename, dllSuffix))
|
||||
return true;
|
||||
|
||||
#ifdef LOCAL_PLUGIN_DLL_ALT_SUFFIX
|
||||
constexpr auto dllAltSuffix = nsLiteralCString{LOCAL_PLUGIN_DLL_ALT_SUFFIX};
|
||||
if (filename.Length() > dllAltSuffix.Length() &&
|
||||
StringEndsWith(filename, dllAltSuffix))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
/* nsPluginFile implementation */
|
||||
|
||||
nsPluginFile::nsPluginFile(nsIFile* file) : mPlugin(file) {}
|
||||
|
||||
nsPluginFile::~nsPluginFile() = default;
|
||||
|
||||
nsresult nsPluginFile::LoadPlugin(PRLibrary** outLibrary) {
|
||||
PRLibSpec libSpec;
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
bool exists = false;
|
||||
mPlugin->Exists(&exists);
|
||||
if (!exists) return NS_ERROR_FILE_NOT_FOUND;
|
||||
|
||||
nsresult rv;
|
||||
nsAutoCString path;
|
||||
rv = mPlugin->GetNativePath(path);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
libSpec.value.pathname = path.get();
|
||||
|
||||
*outLibrary = PR_LoadLibraryWithFlags(libSpec, 0);
|
||||
pLibrary = *outLibrary;
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("LoadPlugin() %s returned %lx\n", libSpec.value.pathname,
|
||||
(unsigned long)pLibrary);
|
||||
#endif
|
||||
|
||||
if (!pLibrary) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info,
|
||||
PRLibrary** outLibrary) {
|
||||
*outLibrary = nullptr;
|
||||
|
||||
info.fVersion = nullptr;
|
||||
|
||||
// Sadly we have to load the library for this to work.
|
||||
nsresult rv = LoadPlugin(outLibrary);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
const char* (*npGetPluginVersion)() =
|
||||
(const char* (*)())PR_FindFunctionSymbol(pLibrary, "NP_GetPluginVersion");
|
||||
if (npGetPluginVersion) {
|
||||
info.fVersion = PL_strdup(npGetPluginVersion());
|
||||
}
|
||||
|
||||
const char* (*npGetMIMEDescription)() =
|
||||
(const char* (*)())PR_FindFunctionSymbol(pLibrary,
|
||||
"NP_GetMIMEDescription");
|
||||
if (!npGetMIMEDescription) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
const char* mimedescr = npGetMIMEDescription();
|
||||
if (!mimedescr) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = ParsePluginMimeDescription(mimedescr, info);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString path;
|
||||
if (NS_FAILED(rv = mPlugin->GetNativePath(path))) return rv;
|
||||
info.fFullPath = PL_strdup(path.get());
|
||||
|
||||
nsAutoCString fileName;
|
||||
if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName))) return rv;
|
||||
info.fFileName = PL_strdup(fileName.get());
|
||||
|
||||
NP_GetValueFunc npGetValue =
|
||||
(NP_GetValueFunc)PR_FindFunctionSymbol(pLibrary, "NP_GetValue");
|
||||
if (!npGetValue) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
const char* name = nullptr;
|
||||
npGetValue(nullptr, NPPVpluginNameString, &name);
|
||||
if (name) {
|
||||
info.fName = PL_strdup(name);
|
||||
} else {
|
||||
info.fName = PL_strdup(fileName.get());
|
||||
}
|
||||
|
||||
const char* description = nullptr;
|
||||
npGetValue(nullptr, NPPVpluginDescriptionString, &description);
|
||||
if (description) {
|
||||
info.fDescription = PL_strdup(description);
|
||||
} else {
|
||||
info.fDescription = PL_strdup("");
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info) {
|
||||
if (info.fName != nullptr) PL_strfree(info.fName);
|
||||
|
||||
if (info.fDescription != nullptr) PL_strfree(info.fDescription);
|
||||
|
||||
for (uint32_t i = 0; i < info.fVariantCount; i++) {
|
||||
if (info.fMimeTypeArray[i] != nullptr) PL_strfree(info.fMimeTypeArray[i]);
|
||||
|
||||
if (info.fMimeDescriptionArray[i] != nullptr)
|
||||
PL_strfree(info.fMimeDescriptionArray[i]);
|
||||
|
||||
if (info.fExtensionArray[i] != nullptr) PL_strfree(info.fExtensionArray[i]);
|
||||
}
|
||||
|
||||
free(info.fMimeTypeArray);
|
||||
info.fMimeTypeArray = nullptr;
|
||||
free(info.fMimeDescriptionArray);
|
||||
info.fMimeDescriptionArray = nullptr;
|
||||
free(info.fExtensionArray);
|
||||
info.fExtensionArray = nullptr;
|
||||
|
||||
if (info.fFullPath != nullptr) PL_strfree(info.fFullPath);
|
||||
|
||||
if (info.fFileName != nullptr) PL_strfree(info.fFileName);
|
||||
|
||||
if (info.fVersion != nullptr) PL_strfree(info.fVersion);
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -1,88 +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 nsPluginsDirUtils_h___
|
||||
#define nsPluginsDirUtils_h___
|
||||
|
||||
#include "nsPluginsDir.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Output format from NPP_GetMIMEDescription: "...mime
|
||||
// type[;version]:[extension]:[desecription];..." The ambiguity of mime
|
||||
// description could cause the browser fail to parse the MIME types correctly.
|
||||
// E.g. "mime type::desecription;" // correct w/o ext
|
||||
// "mime type:desecription;" // wrong w/o ext
|
||||
//
|
||||
static nsresult ParsePluginMimeDescription(const char* mdesc,
|
||||
nsPluginInfo& info) {
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (!mdesc || !*mdesc) return rv;
|
||||
|
||||
char* mdescDup =
|
||||
PL_strdup(mdesc); // make a dup of intput string we'll change it content
|
||||
char anEmptyString[] = "";
|
||||
AutoTArray<char*, 8> tmpMimeTypeArr;
|
||||
char delimiters[] = {':', ':', ';'};
|
||||
int mimeTypeVariantCount = 0;
|
||||
char* p = mdescDup; // make a dup of intput string we'll change it content
|
||||
while (p) {
|
||||
char* ptrMimeArray[] = {anEmptyString, anEmptyString, anEmptyString};
|
||||
|
||||
// It's easy to point out ptrMimeArray[0] to the string sounds like
|
||||
// "Mime type is not specified, plugin will not function properly."
|
||||
// and show this on "about:plugins" page, but we have to mark this
|
||||
// particular mime type of given plugin as disable on "about:plugins" page,
|
||||
// which feature is not implemented yet.
|
||||
// So we'll ignore, without any warnings, an empty description strings,
|
||||
// in other words, if after parsing ptrMimeArray[0] == anEmptyString is
|
||||
// true. It is possible do not to registry a plugin at all if it returns an
|
||||
// empty string on GetMIMEDescription() call, e.g. plugger returns "" if
|
||||
// pluggerrc file is not found.
|
||||
|
||||
char* s = p;
|
||||
int i;
|
||||
for (i = 0;
|
||||
i < (int)sizeof(delimiters) && (p = PL_strchr(s, delimiters[i]));
|
||||
i++) {
|
||||
ptrMimeArray[i] = s; // save start ptr
|
||||
*p++ = 0; // overwrite delimiter
|
||||
s = p; // move forward
|
||||
}
|
||||
if (i == 2) ptrMimeArray[i] = s;
|
||||
// fill out the temp array
|
||||
// the order is important, it should be the same in for loop below
|
||||
if (ptrMimeArray[0] != anEmptyString) {
|
||||
tmpMimeTypeArr.AppendElement(ptrMimeArray[0]);
|
||||
tmpMimeTypeArr.AppendElement(ptrMimeArray[1]);
|
||||
tmpMimeTypeArr.AppendElement(ptrMimeArray[2]);
|
||||
mimeTypeVariantCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// fill out info structure
|
||||
if (mimeTypeVariantCount) {
|
||||
info.fVariantCount = mimeTypeVariantCount;
|
||||
// we can do these 3 mallocs at once, later on code cleanup
|
||||
info.fMimeTypeArray = (char**)malloc(mimeTypeVariantCount * sizeof(char*));
|
||||
info.fMimeDescriptionArray =
|
||||
(char**)malloc(mimeTypeVariantCount * sizeof(char*));
|
||||
info.fExtensionArray = (char**)malloc(mimeTypeVariantCount * sizeof(char*));
|
||||
|
||||
int j, i;
|
||||
for (j = i = 0; i < mimeTypeVariantCount; i++) {
|
||||
// the order is important, do not change it
|
||||
// we can get rid of PL_strdup here, later on code cleanup
|
||||
info.fMimeTypeArray[i] = PL_strdup(tmpMimeTypeArr.ElementAt(j++));
|
||||
info.fExtensionArray[i] = PL_strdup(tmpMimeTypeArr.ElementAt(j++));
|
||||
info.fMimeDescriptionArray[i] = PL_strdup(tmpMimeTypeArr.ElementAt(j++));
|
||||
}
|
||||
rv = NS_OK;
|
||||
}
|
||||
if (mdescDup) PL_strfree(mdescDup);
|
||||
return rv;
|
||||
}
|
||||
|
||||
#endif /* nsPluginsDirUtils_h___ */
|
|
@ -1,349 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||
|
||||
/*
|
||||
nsPluginsDirWin.cpp
|
||||
|
||||
Windows implementation of the nsPluginsDir/nsPluginsFile classes.
|
||||
|
||||
by Alex Musil
|
||||
*/
|
||||
|
||||
#include "mozilla/ArrayUtils.h" // ArrayLength
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Printf.h"
|
||||
|
||||
#include "nsPluginsDir.h"
|
||||
#include "prlink.h"
|
||||
#include "plstr.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
/* Local helper functions */
|
||||
|
||||
static char* GetKeyValue(void* verbuf, const WCHAR* key, UINT language,
|
||||
UINT codepage) {
|
||||
WCHAR keybuf[64]; // plenty for the template below, with the longest key
|
||||
// we use (currently "FileDescription")
|
||||
const WCHAR keyFormat[] = L"\\StringFileInfo\\%04X%04X\\%ls";
|
||||
WCHAR* buf = nullptr;
|
||||
UINT blen;
|
||||
|
||||
if (_snwprintf_s(keybuf, ArrayLength(keybuf), _TRUNCATE, keyFormat, language,
|
||||
codepage, key) < 0) {
|
||||
MOZ_ASSERT_UNREACHABLE("plugin info key too long for buffer!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (::VerQueryValueW(verbuf, keybuf, (void**)&buf, &blen) == 0 ||
|
||||
buf == nullptr || blen == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return PL_strdup(NS_ConvertUTF16toUTF8(buf, blen).get());
|
||||
}
|
||||
|
||||
static char* GetVersion(void* verbuf) {
|
||||
VS_FIXEDFILEINFO* fileInfo;
|
||||
UINT fileInfoLen;
|
||||
|
||||
::VerQueryValueW(verbuf, L"\\", (void**)&fileInfo, &fileInfoLen);
|
||||
|
||||
if (fileInfo) {
|
||||
return mozilla::Smprintf("%ld.%ld.%ld.%ld",
|
||||
HIWORD(fileInfo->dwFileVersionMS),
|
||||
LOWORD(fileInfo->dwFileVersionMS),
|
||||
HIWORD(fileInfo->dwFileVersionLS),
|
||||
LOWORD(fileInfo->dwFileVersionLS))
|
||||
.release();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Returns a boolean indicating if the key's value contains a string
|
||||
// entry equal to "1" or "0". No entry for the key returns false.
|
||||
static bool GetBooleanFlag(void* verbuf, const WCHAR* key, UINT language,
|
||||
UINT codepage) {
|
||||
char* flagStr = GetKeyValue(verbuf, key, language, codepage);
|
||||
if (!flagStr) {
|
||||
return false;
|
||||
}
|
||||
bool result = (PL_strncmp("1", flagStr, 1) == 0);
|
||||
PL_strfree(flagStr);
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t CalculateVariantCount(char* mimeTypes) {
|
||||
uint32_t variants = 1;
|
||||
|
||||
if (!mimeTypes) return 0;
|
||||
|
||||
char* index = mimeTypes;
|
||||
while (*index) {
|
||||
if (*index == '|') variants++;
|
||||
|
||||
++index;
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
|
||||
static char** MakeStringArray(uint32_t variants, char* data) {
|
||||
// The number of variants has been calculated based on the mime
|
||||
// type array. Plugins are not explicitely required to match
|
||||
// this number in two other arrays: file extention array and mime
|
||||
// description array, and some of them actually don't.
|
||||
// We should handle such situations gracefully
|
||||
|
||||
if ((variants <= 0) || !data) return nullptr;
|
||||
|
||||
char** array = (char**)calloc(variants, sizeof(char*));
|
||||
if (!array) return nullptr;
|
||||
|
||||
char* start = data;
|
||||
|
||||
for (uint32_t i = 0; i < variants; i++) {
|
||||
char* p = PL_strchr(start, '|');
|
||||
if (p) *p = 0;
|
||||
|
||||
array[i] = PL_strdup(start);
|
||||
|
||||
if (!p) {
|
||||
// nothing more to look for, fill everything left
|
||||
// with empty strings and break
|
||||
while (++i < variants) array[i] = PL_strdup("");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
start = ++p;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
static void FreeStringArray(uint32_t variants, char** array) {
|
||||
if ((variants == 0) || !array) return;
|
||||
|
||||
for (uint32_t i = 0; i < variants; i++) {
|
||||
if (array[i]) {
|
||||
PL_strfree(array[i]);
|
||||
array[i] = nullptr;
|
||||
}
|
||||
}
|
||||
free(array);
|
||||
}
|
||||
|
||||
static bool CanLoadPlugin(char16ptr_t aBinaryPath) {
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_IA64)
|
||||
bool canLoad = false;
|
||||
|
||||
HANDLE file =
|
||||
CreateFileW(aBinaryPath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||
if (file != INVALID_HANDLE_VALUE) {
|
||||
HANDLE map = CreateFileMappingW(file, nullptr, PAGE_READONLY, 0,
|
||||
GetFileSize(file, nullptr), nullptr);
|
||||
if (map != nullptr) {
|
||||
LPVOID mapView = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 0);
|
||||
if (mapView != nullptr) {
|
||||
if (((IMAGE_DOS_HEADER*)mapView)->e_magic == IMAGE_DOS_SIGNATURE) {
|
||||
long peImageHeaderStart = (((IMAGE_DOS_HEADER*)mapView)->e_lfanew);
|
||||
if (peImageHeaderStart != 0L) {
|
||||
DWORD arch =
|
||||
(((IMAGE_NT_HEADERS*)((LPBYTE)mapView + peImageHeaderStart))
|
||||
->FileHeader.Machine);
|
||||
# ifdef _M_IX86
|
||||
canLoad = (arch == IMAGE_FILE_MACHINE_I386);
|
||||
# elif defined(_M_X64)
|
||||
canLoad = (arch == IMAGE_FILE_MACHINE_AMD64);
|
||||
# elif defined(_M_IA64)
|
||||
canLoad = (arch == IMAGE_FILE_MACHINE_IA64);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
UnmapViewOfFile(mapView);
|
||||
}
|
||||
CloseHandle(map);
|
||||
}
|
||||
CloseHandle(file);
|
||||
}
|
||||
|
||||
return canLoad;
|
||||
#else
|
||||
// Assume correct binaries for unhandled cases.
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* nsPluginsDir implementation */
|
||||
|
||||
// The file name must be in the form "np*.dll"
|
||||
bool nsPluginsDir::IsPluginFile(nsIFile* file) {
|
||||
nsAutoString path;
|
||||
if (NS_FAILED(file->GetPath(path))) return false;
|
||||
|
||||
// this is most likely a path, so skip to the filename
|
||||
auto filename = Substring(path, path.RFindChar('\\') + 1);
|
||||
// The file name must have at least one character between "np" and ".dll".
|
||||
if (filename.Length() < 7) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ToLowerCase(filename);
|
||||
if (StringBeginsWith(filename, u"np"_ns) &&
|
||||
StringEndsWith(filename, u".dll"_ns)) {
|
||||
// don't load OJI-based Java plugins
|
||||
if (StringBeginsWith(filename, u"npoji"_ns) ||
|
||||
StringBeginsWith(filename, u"npjava"_ns))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* nsPluginFile implementation */
|
||||
|
||||
nsPluginFile::nsPluginFile(nsIFile* file) : mPlugin(file) {
|
||||
// nada
|
||||
}
|
||||
|
||||
nsPluginFile::~nsPluginFile() {
|
||||
// nada
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the plugin into memory using NSPR's shared-library loading
|
||||
* mechanism. Handles platform differences in loading shared libraries.
|
||||
*/
|
||||
nsresult nsPluginFile::LoadPlugin(PRLibrary** outLibrary) {
|
||||
if (!mPlugin) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoString pluginFilePath;
|
||||
mPlugin->GetPath(pluginFilePath);
|
||||
|
||||
nsAutoString pluginFolderPath = pluginFilePath;
|
||||
int32_t idx = pluginFilePath.RFindChar('\\');
|
||||
pluginFolderPath.SetLength(idx);
|
||||
|
||||
BOOL restoreOrigDir = FALSE;
|
||||
WCHAR aOrigDir[MAX_PATH + 1];
|
||||
DWORD dwCheck = GetCurrentDirectoryW(MAX_PATH, aOrigDir);
|
||||
NS_ASSERTION(dwCheck <= MAX_PATH + 1, "Error in Loading plugin");
|
||||
|
||||
if (dwCheck <= MAX_PATH + 1) {
|
||||
restoreOrigDir = SetCurrentDirectoryW(pluginFolderPath.get());
|
||||
NS_ASSERTION(restoreOrigDir, "Error in Loading plugin");
|
||||
}
|
||||
|
||||
// Temporarily add the current directory back to the DLL load path.
|
||||
SetDllDirectory(nullptr);
|
||||
|
||||
nsresult rv = mPlugin->Load(outLibrary);
|
||||
if (NS_FAILED(rv)) *outLibrary = nullptr;
|
||||
|
||||
SetDllDirectory(L"");
|
||||
|
||||
if (restoreOrigDir) {
|
||||
DebugOnly<BOOL> bCheck = SetCurrentDirectoryW(aOrigDir);
|
||||
NS_ASSERTION(bCheck, "Error in Loading plugin");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains all of the information currently available for this plugin.
|
||||
*/
|
||||
nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info,
|
||||
PRLibrary** outLibrary) {
|
||||
*outLibrary = nullptr;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
DWORD zerome, versionsize;
|
||||
void* verbuf = nullptr;
|
||||
|
||||
if (!mPlugin) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsAutoString fullPath;
|
||||
if (NS_FAILED(rv = mPlugin->GetPath(fullPath))) return rv;
|
||||
|
||||
if (!CanLoadPlugin(fullPath.get())) return NS_ERROR_FAILURE;
|
||||
|
||||
nsAutoString fileName;
|
||||
if (NS_FAILED(rv = mPlugin->GetLeafName(fileName))) return rv;
|
||||
|
||||
LPCWSTR lpFilepath = fullPath.get();
|
||||
|
||||
versionsize = ::GetFileVersionInfoSizeW(lpFilepath, &zerome);
|
||||
|
||||
if (versionsize > 0) verbuf = malloc(versionsize);
|
||||
if (!verbuf) return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
if (::GetFileVersionInfoW(lpFilepath, 0, versionsize, verbuf)) {
|
||||
// TODO: get appropriately-localized info from plugin file
|
||||
UINT lang = 1033; // language = English, 0x409
|
||||
UINT cp = 1252; // codepage = Western, 0x4E4
|
||||
info.fName = GetKeyValue(verbuf, L"ProductName", lang, cp);
|
||||
info.fDescription = GetKeyValue(verbuf, L"FileDescription", lang, cp);
|
||||
info.fSupportsAsyncRender =
|
||||
GetBooleanFlag(verbuf, L"AsyncDrawingSupport", lang, cp);
|
||||
|
||||
char* mimeType = GetKeyValue(verbuf, L"MIMEType", lang, cp);
|
||||
char* mimeDescription = GetKeyValue(verbuf, L"FileOpenName", lang, cp);
|
||||
char* extensions = GetKeyValue(verbuf, L"FileExtents", lang, cp);
|
||||
|
||||
info.fVariantCount = CalculateVariantCount(mimeType);
|
||||
info.fMimeTypeArray = MakeStringArray(info.fVariantCount, mimeType);
|
||||
info.fMimeDescriptionArray =
|
||||
MakeStringArray(info.fVariantCount, mimeDescription);
|
||||
info.fExtensionArray = MakeStringArray(info.fVariantCount, extensions);
|
||||
info.fFullPath = PL_strdup(NS_ConvertUTF16toUTF8(fullPath).get());
|
||||
info.fFileName = PL_strdup(NS_ConvertUTF16toUTF8(fileName).get());
|
||||
info.fVersion = GetVersion(verbuf);
|
||||
|
||||
PL_strfree(mimeType);
|
||||
PL_strfree(mimeDescription);
|
||||
PL_strfree(extensions);
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
free(verbuf);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info) {
|
||||
if (info.fName) PL_strfree(info.fName);
|
||||
|
||||
if (info.fDescription) PL_strfree(info.fDescription);
|
||||
|
||||
if (info.fMimeTypeArray)
|
||||
FreeStringArray(info.fVariantCount, info.fMimeTypeArray);
|
||||
|
||||
if (info.fMimeDescriptionArray)
|
||||
FreeStringArray(info.fVariantCount, info.fMimeDescriptionArray);
|
||||
|
||||
if (info.fExtensionArray)
|
||||
FreeStringArray(info.fVariantCount, info.fExtensionArray);
|
||||
|
||||
if (info.fFullPath) PL_strfree(info.fFullPath);
|
||||
|
||||
if (info.fFileName) PL_strfree(info.fFileName);
|
||||
|
||||
if (info.fVersion) free(info.fVersion);
|
||||
|
||||
ZeroMemory((void*)&info, sizeof(info));
|
||||
|
||||
return NS_OK;
|
||||
}
|
|
@ -3,29 +3,6 @@
|
|||
* 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/. */
|
||||
|
||||
native REFNSIID(REFNSIID);
|
||||
native nativeVoid(void *);
|
||||
native nativeChar(const char * *);
|
||||
[ptr] native constVoidPtr(const void);
|
||||
[ref] native PRUint32Ref(uint32_t);
|
||||
[ref] native PRUint16Ref(uint16_t);
|
||||
[ref] native constCharStarConstStar(const char* const*);
|
||||
[ptr] native constCharPtr(const char);
|
||||
[ref] native constCharStarRef(const char *);
|
||||
|
||||
native NPWindowType(NPWindowType);
|
||||
native NPWindow(NPWindow);
|
||||
[ptr] native NPWindowPtr(NPWindow);
|
||||
[ref] native NPWindowStarRef(NPWindow *);
|
||||
[ptr] native NPPrintPtr(NPPrint);
|
||||
native NPByteRange(NPByteRange);
|
||||
[ptr] native NPByteRangePtr(NPByteRange);
|
||||
native NPPVariable(NPPVariable);
|
||||
native NPNVariable(NPNVariable);
|
||||
[ptr] native NPRectPtr(NPRect);
|
||||
native NPRegion(NPRegion);
|
||||
native NPDrawingModel(NPDrawingModel);
|
||||
native NPEventModel(NPEventModel);
|
||||
|
||||
[ptr] native JRIEnvPtr(JRIEnv);
|
||||
native jref(jref);
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 mozilla_plugins_AStream_h
|
||||
#define mozilla_plugins_AStream_h
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* When we are passed NPStream->{ndata,pdata} in {NPN,NPP}_DestroyStream, we
|
||||
* don't know whether it's a plugin stream or a browser stream. This abstract
|
||||
* class lets us cast to the right type of object and send the appropriate
|
||||
* message.
|
||||
*/
|
||||
class AStream {
|
||||
public:
|
||||
virtual bool IsBrowserStream() = 0;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -1,217 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 "mozilla/plugins/BrowserStreamChild.h"
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/plugins/PluginInstanceChild.h"
|
||||
#include "mozilla/plugins/StreamNotifyChild.h"
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
BrowserStreamChild::BrowserStreamChild(PluginInstanceChild* instance,
|
||||
const nsCString& url,
|
||||
const uint32_t& length,
|
||||
const uint32_t& lastmodified,
|
||||
StreamNotifyChild* notifyData,
|
||||
const nsCString& headers)
|
||||
: mInstance(instance),
|
||||
mStreamStatus(kStreamOpen),
|
||||
mDestroyPending(NOT_DESTROYED),
|
||||
mNotifyPending(false),
|
||||
mInstanceDying(false),
|
||||
mState(CONSTRUCTING),
|
||||
mURL(url),
|
||||
mHeaders(headers),
|
||||
mStreamNotify(notifyData),
|
||||
mDeliveryTracker(this) {
|
||||
PLUGIN_LOG_DEBUG(("%s (%s, %i, %i, %p, %s)", FULLFUNCTION, url.get(), length,
|
||||
lastmodified, (void*)notifyData, headers.get()));
|
||||
|
||||
AssertPluginThread();
|
||||
|
||||
memset(&mStream, 0, sizeof(mStream));
|
||||
mStream.ndata = static_cast<AStream*>(this);
|
||||
mStream.url = NullableStringGet(mURL);
|
||||
mStream.end = length;
|
||||
mStream.lastmodified = lastmodified;
|
||||
mStream.headers = NullableStringGet(mHeaders);
|
||||
if (notifyData) {
|
||||
mStream.notifyData = notifyData->mClosure;
|
||||
notifyData->SetAssociatedStream(this);
|
||||
}
|
||||
}
|
||||
|
||||
NPError BrowserStreamChild::StreamConstructed(const nsCString& mimeType,
|
||||
const bool& seekable,
|
||||
uint16_t* stype) {
|
||||
NPError rv = NPERR_NO_ERROR;
|
||||
|
||||
*stype = NP_NORMAL;
|
||||
rv = mInstance->mPluginIface->newstream(
|
||||
&mInstance->mData, const_cast<char*>(NullableStringGet(mimeType)),
|
||||
&mStream, seekable, stype);
|
||||
|
||||
// NP_NORMAL is the only permissible stream type
|
||||
if (*stype != NP_NORMAL) {
|
||||
rv = NPERR_INVALID_PARAM;
|
||||
// The plugin thinks the stream is alive, so we kill it explicitly
|
||||
(void)mInstance->mPluginIface->destroystream(&mInstance->mData, &mStream,
|
||||
NPRES_NETWORK_ERR);
|
||||
}
|
||||
|
||||
if (rv != NPERR_NO_ERROR) {
|
||||
mState = DELETING;
|
||||
if (mStreamNotify) {
|
||||
mStreamNotify->SetAssociatedStream(nullptr);
|
||||
mStreamNotify = nullptr;
|
||||
}
|
||||
} else {
|
||||
mState = ALIVE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
BrowserStreamChild::~BrowserStreamChild() {
|
||||
NS_ASSERTION(!mStreamNotify, "Should have nulled it by now!");
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserStreamChild::RecvWrite(const int32_t& offset,
|
||||
const uint32_t& newlength,
|
||||
const Buffer& data) {
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
|
||||
AssertPluginThread();
|
||||
|
||||
if (ALIVE != mState)
|
||||
MOZ_CRASH("Unexpected state: received data after NPP_DestroyStream?");
|
||||
|
||||
if (kStreamOpen != mStreamStatus) return IPC_OK();
|
||||
|
||||
mStream.end = newlength;
|
||||
|
||||
NS_ASSERTION(data.Length() > 0, "Empty data");
|
||||
|
||||
PendingData* newdata = mPendingData.AppendElement();
|
||||
newdata->offset = offset;
|
||||
newdata->data = data;
|
||||
newdata->curpos = 0;
|
||||
|
||||
EnsureDeliveryPending();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserStreamChild::RecvNPP_DestroyStream(
|
||||
const NPReason& reason) {
|
||||
PLUGIN_LOG_DEBUG_METHOD;
|
||||
|
||||
if (ALIVE != mState)
|
||||
MOZ_CRASH("Unexpected state: recevied NPP_DestroyStream twice?");
|
||||
|
||||
mState = DYING;
|
||||
mDestroyPending = DESTROY_PENDING;
|
||||
if (NPRES_DONE != reason) mStreamStatus = reason;
|
||||
|
||||
EnsureDeliveryPending();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserStreamChild::Recv__delete__() {
|
||||
AssertPluginThread();
|
||||
|
||||
if (DELETING != mState) MOZ_CRASH("Bad state, not DELETING");
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
void BrowserStreamChild::EnsureDeliveryPending() {
|
||||
MessageLoop::current()->PostTask(
|
||||
mDeliveryTracker.NewRunnableMethod(&BrowserStreamChild::Deliver));
|
||||
}
|
||||
|
||||
void BrowserStreamChild::Deliver() {
|
||||
while (kStreamOpen == mStreamStatus && mPendingData.Length()) {
|
||||
if (DeliverPendingData() && kStreamOpen == mStreamStatus) {
|
||||
SetSuspendedTimer();
|
||||
return;
|
||||
}
|
||||
}
|
||||
ClearSuspendedTimer();
|
||||
|
||||
NS_ASSERTION(kStreamOpen != mStreamStatus || 0 == mPendingData.Length(),
|
||||
"Exit out of the data-delivery loop with pending data");
|
||||
mPendingData.Clear();
|
||||
|
||||
if (DESTROY_PENDING == mDestroyPending) {
|
||||
mDestroyPending = DESTROYED;
|
||||
if (mState != DYING) MOZ_CRASH("mDestroyPending but state not DYING");
|
||||
|
||||
NS_ASSERTION(NPRES_DONE != mStreamStatus, "Success status set too early!");
|
||||
if (kStreamOpen == mStreamStatus) mStreamStatus = NPRES_DONE;
|
||||
|
||||
(void)mInstance->mPluginIface->destroystream(&mInstance->mData, &mStream,
|
||||
mStreamStatus);
|
||||
}
|
||||
if (DESTROYED == mDestroyPending && mNotifyPending) {
|
||||
NS_ASSERTION(mStreamNotify, "mDestroyPending but no mStreamNotify?");
|
||||
|
||||
mNotifyPending = false;
|
||||
mStreamNotify->NPP_URLNotify(mStreamStatus);
|
||||
delete mStreamNotify;
|
||||
mStreamNotify = nullptr;
|
||||
}
|
||||
if (DYING == mState && DESTROYED == mDestroyPending && !mStreamNotify &&
|
||||
!mInstanceDying) {
|
||||
SendStreamDestroyed();
|
||||
mState = DELETING;
|
||||
}
|
||||
}
|
||||
|
||||
bool BrowserStreamChild::DeliverPendingData() {
|
||||
if (mState != ALIVE && mState != DYING) MOZ_CRASH("Unexpected state");
|
||||
|
||||
NS_ASSERTION(mPendingData.Length(), "Called from Deliver with empty pending");
|
||||
|
||||
while (mPendingData[0].curpos <
|
||||
static_cast<int32_t>(mPendingData[0].data.Length())) {
|
||||
int32_t r =
|
||||
mInstance->mPluginIface->writeready(&mInstance->mData, &mStream);
|
||||
if (kStreamOpen != mStreamStatus) return false;
|
||||
if (0 == r) // plugin wants to suspend delivery
|
||||
return true;
|
||||
|
||||
r = mInstance->mPluginIface->write(
|
||||
&mInstance->mData, &mStream,
|
||||
mPendingData[0].offset + mPendingData[0].curpos, // offset
|
||||
mPendingData[0].data.Length() - mPendingData[0].curpos, // length
|
||||
const_cast<char*>(mPendingData[0].data.BeginReading() +
|
||||
mPendingData[0].curpos));
|
||||
if (kStreamOpen != mStreamStatus) return false;
|
||||
if (0 == r) return true;
|
||||
if (r < 0) { // error condition
|
||||
mStreamStatus = NPRES_NETWORK_ERR;
|
||||
|
||||
// Set up stream destruction
|
||||
EnsureDeliveryPending();
|
||||
return false;
|
||||
}
|
||||
mPendingData[0].curpos += r;
|
||||
}
|
||||
mPendingData.RemoveElementAt(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void BrowserStreamChild::SetSuspendedTimer() {
|
||||
if (mSuspendedTimer.IsRunning()) return;
|
||||
mSuspendedTimer.Start(base::TimeDelta::FromMilliseconds(
|
||||
100), // 100ms copied from Mozilla plugin host
|
||||
this, &BrowserStreamChild::Deliver);
|
||||
}
|
||||
|
||||
void BrowserStreamChild::ClearSuspendedTimer() { mSuspendedTimer.Stop(); }
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,150 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 mozilla_plugins_BrowserStreamChild_h
|
||||
#define mozilla_plugins_BrowserStreamChild_h 1
|
||||
|
||||
#include "mozilla/plugins/PBrowserStreamChild.h"
|
||||
#include "mozilla/plugins/AStream.h"
|
||||
#include "base/task.h"
|
||||
#include "base/timer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class PluginInstanceChild;
|
||||
class StreamNotifyChild;
|
||||
|
||||
class BrowserStreamChild : public PBrowserStreamChild, public AStream {
|
||||
public:
|
||||
BrowserStreamChild(PluginInstanceChild* instance, const nsCString& url,
|
||||
const uint32_t& length, const uint32_t& lastmodified,
|
||||
StreamNotifyChild* notifyData, const nsCString& headers);
|
||||
virtual ~BrowserStreamChild();
|
||||
|
||||
virtual bool IsBrowserStream() override { return true; }
|
||||
|
||||
NPError StreamConstructed(const nsCString& mimeType, const bool& seekable,
|
||||
uint16_t* stype);
|
||||
|
||||
mozilla::ipc::IPCResult RecvWrite(const int32_t& offset,
|
||||
const uint32_t& newsize,
|
||||
const Buffer& data);
|
||||
mozilla::ipc::IPCResult RecvNPP_DestroyStream(const NPReason& reason);
|
||||
virtual mozilla::ipc::IPCResult Recv__delete__() override;
|
||||
|
||||
void EnsureCorrectInstance(PluginInstanceChild* i) {
|
||||
if (i != mInstance) MOZ_CRASH("Incorrect stream instance");
|
||||
}
|
||||
void EnsureCorrectStream(NPStream* s) {
|
||||
if (s != &mStream) MOZ_CRASH("Incorrect stream data");
|
||||
}
|
||||
|
||||
void NotifyPending() {
|
||||
NS_ASSERTION(!mNotifyPending, "Pending twice?");
|
||||
mNotifyPending = true;
|
||||
EnsureDeliveryPending();
|
||||
}
|
||||
|
||||
/**
|
||||
* During instance destruction, artificially cancel all outstanding streams.
|
||||
*
|
||||
* @return false if we are already in the DELETING state.
|
||||
*/
|
||||
bool InstanceDying() {
|
||||
if (DELETING == mState) return false;
|
||||
|
||||
mInstanceDying = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FinishDelivery() {
|
||||
NS_ASSERTION(mInstanceDying, "Should only be called after InstanceDying");
|
||||
NS_ASSERTION(DELETING != mState, "InstanceDying didn't work?");
|
||||
mStreamStatus = NPRES_USER_BREAK;
|
||||
Deliver();
|
||||
NS_ASSERTION(!mStreamNotify, "Didn't deliver NPN_URLNotify?");
|
||||
}
|
||||
|
||||
private:
|
||||
friend class StreamNotifyChild;
|
||||
|
||||
/**
|
||||
* Post an event to ensure delivery of pending data/destroy/urlnotify events
|
||||
* outside of the current RPC stack.
|
||||
*/
|
||||
void EnsureDeliveryPending();
|
||||
|
||||
/**
|
||||
* Deliver data, destruction, notify scheduling
|
||||
* or cancelling the suspended timer as needed.
|
||||
*/
|
||||
void Deliver();
|
||||
|
||||
/**
|
||||
* Deliver one chunk of pending data.
|
||||
* @return true if the plugin indicated a pause was necessary
|
||||
*/
|
||||
bool DeliverPendingData();
|
||||
|
||||
void SetSuspendedTimer();
|
||||
void ClearSuspendedTimer();
|
||||
|
||||
PluginInstanceChild* mInstance;
|
||||
NPStream mStream;
|
||||
|
||||
static const NPReason kStreamOpen = -1;
|
||||
|
||||
/**
|
||||
* The plugin's notion of whether a stream has been "closed" (no more
|
||||
* data delivery) differs from the plugin host due to asynchronous delivery
|
||||
* of data and stream destruction. While the plugin-visible stream is open,
|
||||
* mStreamStatus should be kStreamOpen (-1). mStreamStatus will be a
|
||||
* failure code if either the parent or child indicates stream failure.
|
||||
*/
|
||||
NPReason mStreamStatus;
|
||||
|
||||
/**
|
||||
* Delivery of NPP_DestroyStream and NPP_URLNotify must be postponed until
|
||||
* all data has been delivered.
|
||||
*/
|
||||
enum {
|
||||
NOT_DESTROYED, // NPP_DestroyStream not yet received
|
||||
DESTROY_PENDING, // NPP_DestroyStream received, not yet delivered
|
||||
DESTROYED // NPP_DestroyStream delivered, NPP_URLNotify may still be
|
||||
// pending
|
||||
} mDestroyPending;
|
||||
bool mNotifyPending;
|
||||
|
||||
// When NPP_Destroy is called for our instance (manager), this flag is set
|
||||
// cancels the stream and avoids sending StreamDestroyed.
|
||||
bool mInstanceDying;
|
||||
|
||||
enum { CONSTRUCTING, ALIVE, DYING, DELETING } mState;
|
||||
nsCString mURL;
|
||||
nsCString mHeaders;
|
||||
StreamNotifyChild* mStreamNotify;
|
||||
|
||||
struct PendingData {
|
||||
int32_t offset;
|
||||
Buffer data;
|
||||
int32_t curpos;
|
||||
};
|
||||
nsTArray<PendingData> mPendingData;
|
||||
|
||||
/**
|
||||
* Asynchronous RecvWrite messages are never delivered to the plugin
|
||||
* immediately, because that may be in the midst of an unexpected RPC
|
||||
* stack frame. It instead posts a runnable using this tracker to cancel
|
||||
* in case we are destroyed.
|
||||
*/
|
||||
ScopedRunnableMethodFactory<BrowserStreamChild> mDeliveryTracker;
|
||||
base::RepeatingTimer<BrowserStreamChild> mSuspendedTimer;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_plugins_BrowserStreamChild_h */
|
|
@ -1,85 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 "BrowserStreamParent.h"
|
||||
#include "PluginInstanceParent.h"
|
||||
#include "nsNPAPIPlugin.h"
|
||||
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
// How much data are we willing to send across the wire
|
||||
// in one chunk?
|
||||
static const int32_t kSendDataChunk = 0xffff;
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp,
|
||||
NPStream* stream)
|
||||
: mNPP(npp), mStream(stream), mState(INITIALIZING) {
|
||||
mStream->pdata = static_cast<AStream*>(this);
|
||||
nsNPAPIStreamWrapper* wrapper =
|
||||
reinterpret_cast<nsNPAPIStreamWrapper*>(mStream->ndata);
|
||||
if (wrapper) {
|
||||
mStreamListener = wrapper->GetStreamListener();
|
||||
}
|
||||
}
|
||||
|
||||
BrowserStreamParent::~BrowserStreamParent() { mStream->pdata = nullptr; }
|
||||
|
||||
void BrowserStreamParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
// Implement me! Bug 1005159
|
||||
}
|
||||
|
||||
void BrowserStreamParent::NPP_DestroyStream(NPReason reason) {
|
||||
NS_ASSERTION(ALIVE == mState || INITIALIZING == mState,
|
||||
"NPP_DestroyStream called twice?");
|
||||
bool stillInitializing = INITIALIZING == mState;
|
||||
if (stillInitializing) {
|
||||
mState = DEFERRING_DESTROY;
|
||||
} else {
|
||||
mState = DYING;
|
||||
Unused << SendNPP_DestroyStream(reason);
|
||||
}
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult BrowserStreamParent::RecvStreamDestroyed() {
|
||||
if (DYING != mState) {
|
||||
NS_ERROR("Unexpected state");
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
|
||||
mStreamPeer = nullptr;
|
||||
|
||||
mState = DELETING;
|
||||
IProtocol* mgr = Manager();
|
||||
if (!Send__delete__(this)) {
|
||||
return IPC_FAIL_NO_REASON(mgr);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
int32_t BrowserStreamParent::WriteReady() {
|
||||
if (mState == INITIALIZING) {
|
||||
return 0;
|
||||
}
|
||||
return kSendDataChunk;
|
||||
}
|
||||
|
||||
int32_t BrowserStreamParent::Write(int32_t offset, int32_t len, void* buffer) {
|
||||
PLUGIN_LOG_DEBUG_FUNCTION;
|
||||
|
||||
NS_ASSERTION(ALIVE == mState, "Sending data after NPP_DestroyStream?");
|
||||
NS_ASSERTION(len > 0, "Non-positive length to NPP_Write");
|
||||
|
||||
if (len > kSendDataChunk) len = kSendDataChunk;
|
||||
|
||||
return SendWrite(offset, mStream->end,
|
||||
nsCString(static_cast<char*>(buffer), len))
|
||||
? len
|
||||
: -1;
|
||||
}
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,58 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 mozilla_plugins_BrowserStreamParent_h
|
||||
#define mozilla_plugins_BrowserStreamParent_h
|
||||
|
||||
#include "mozilla/plugins/PBrowserStreamParent.h"
|
||||
#include "mozilla/plugins/AStream.h"
|
||||
#include "nsNPAPIPluginStreamListener.h"
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class PluginInstanceParent;
|
||||
|
||||
class BrowserStreamParent : public PBrowserStreamParent, public AStream {
|
||||
friend class PluginModuleParent;
|
||||
friend class PluginInstanceParent;
|
||||
|
||||
public:
|
||||
BrowserStreamParent(PluginInstanceParent* npp, NPStream* stream);
|
||||
virtual ~BrowserStreamParent();
|
||||
|
||||
virtual bool IsBrowserStream() override { return true; }
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvStreamDestroyed() override;
|
||||
|
||||
int32_t WriteReady();
|
||||
int32_t Write(int32_t offset, int32_t len, void* buffer);
|
||||
|
||||
void NPP_DestroyStream(NPReason reason);
|
||||
|
||||
void SetAlive() {
|
||||
if (mState == INITIALIZING) {
|
||||
mState = ALIVE;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using PBrowserStreamParent::SendNPP_DestroyStream;
|
||||
|
||||
PluginInstanceParent* mNPP;
|
||||
NPStream* mStream;
|
||||
nsCOMPtr<nsISupports> mStreamPeer;
|
||||
RefPtr<nsNPAPIPluginStreamListener> mStreamListener;
|
||||
|
||||
enum { INITIALIZING, DEFERRING_DESTROY, ALIVE, DYING, DELETING } mState;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -1,31 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 "ChildTimer.h"
|
||||
#include "PluginInstanceChild.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
ChildTimer::ChildTimer(PluginInstanceChild* instance, uint32_t interval,
|
||||
bool repeat, TimerFunc func)
|
||||
: mInstance(instance),
|
||||
mFunc(func),
|
||||
mRepeating(repeat),
|
||||
mID(gNextTimerID++) {
|
||||
mTimer.Start(base::TimeDelta::FromMilliseconds(interval), this,
|
||||
&ChildTimer::Run);
|
||||
}
|
||||
|
||||
uint32_t ChildTimer::gNextTimerID = 1;
|
||||
|
||||
void ChildTimer::Run() {
|
||||
if (!mRepeating) mTimer.Stop();
|
||||
mFunc(mInstance->GetNPP(), mID);
|
||||
}
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,55 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 mozilla_plugins_ChildTimer_h
|
||||
#define mozilla_plugins_ChildTimer_h
|
||||
|
||||
#include "PluginMessageUtils.h"
|
||||
#include "npapi.h"
|
||||
#include "base/timer.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class PluginInstanceChild;
|
||||
typedef void (*TimerFunc)(NPP npp, uint32_t timerID);
|
||||
|
||||
class ChildTimer {
|
||||
public:
|
||||
/**
|
||||
* If initialization failed, ID() will return 0.
|
||||
*/
|
||||
ChildTimer(PluginInstanceChild* instance, uint32_t interval, bool repeat,
|
||||
TimerFunc func);
|
||||
~ChildTimer() = default;
|
||||
|
||||
uint32_t ID() const { return mID; }
|
||||
|
||||
class IDComparator {
|
||||
public:
|
||||
bool Equals(const UniquePtr<ChildTimer>& t, uint32_t id) const {
|
||||
return t->ID() == id;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
PluginInstanceChild* mInstance;
|
||||
TimerFunc mFunc;
|
||||
bool mRepeating;
|
||||
uint32_t mID;
|
||||
base::RepeatingTimer<ChildTimer> mTimer;
|
||||
|
||||
void Run();
|
||||
|
||||
static uint32_t gNextTimerID;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_ChildTimer_h
|
|
@ -1,81 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 "nsDebug.h"
|
||||
#include "D3D11SurfaceHolder.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/DeviceManagerDx.h"
|
||||
#include "mozilla/layers/TextureD3D11.h"
|
||||
#include <d3d11.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
D3D11SurfaceHolder::D3D11SurfaceHolder(ID3D11Texture2D* back,
|
||||
SurfaceFormat format,
|
||||
const IntSize& size)
|
||||
: mDevice11(DeviceManagerDx::Get()->GetContentDevice()),
|
||||
mBack(back),
|
||||
mFormat(format),
|
||||
mSize(size) {}
|
||||
|
||||
D3D11SurfaceHolder::~D3D11SurfaceHolder() {}
|
||||
|
||||
bool D3D11SurfaceHolder::IsValid() {
|
||||
// If a TDR occurred, platform devices will be recreated.
|
||||
if (DeviceManagerDx::Get()->GetContentDevice() != mDevice11) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool D3D11SurfaceHolder::CopyToTextureClient(TextureClient* aClient) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
D3D11TextureData* data = aClient->GetInternalData()->AsD3D11TextureData();
|
||||
if (!data) {
|
||||
// We don't support this yet. We expect to have a D3D11 compositor, and
|
||||
// therefore D3D11 surfaces.
|
||||
NS_WARNING("Plugin DXGI surface has unsupported TextureClient");
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11DeviceContext> context;
|
||||
mDevice11->GetImmediateContext(getter_AddRefs(context));
|
||||
if (!context) {
|
||||
NS_WARNING("Could not get an immediate D3D11 context");
|
||||
return false;
|
||||
}
|
||||
|
||||
TextureClientAutoLock autoLock(aClient, OpenMode::OPEN_WRITE_ONLY);
|
||||
if (!autoLock.Succeeded()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<IDXGIKeyedMutex> mutex;
|
||||
HRESULT hr = mBack->QueryInterface(__uuidof(IDXGIKeyedMutex),
|
||||
(void**)getter_AddRefs(mutex));
|
||||
if (FAILED(hr) || !mutex) {
|
||||
NS_WARNING("Could not acquire an IDXGIKeyedMutex");
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
AutoTextureLock lock(mutex, hr);
|
||||
if (hr == WAIT_ABANDONED || hr == WAIT_TIMEOUT || FAILED(hr)) {
|
||||
NS_WARNING(
|
||||
"Could not acquire DXGI surface lock - plugin forgot to release?");
|
||||
return false;
|
||||
}
|
||||
|
||||
context->CopyResource(data->GetD3D11Texture(), mBack);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,46 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 _include_dom_plugins_ipc_D3D11SurfaceHolder_h__
|
||||
#define _include_dom_plugins_ipc_D3D11SurfaceHolder_h__
|
||||
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/gfx/Point.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class D3D11ShareHandleImage;
|
||||
class TextureClient;
|
||||
} // namespace layers
|
||||
|
||||
namespace plugins {
|
||||
|
||||
class D3D11SurfaceHolder {
|
||||
public:
|
||||
D3D11SurfaceHolder(ID3D11Texture2D* back, gfx::SurfaceFormat format,
|
||||
const gfx::IntSize& size);
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(D3D11SurfaceHolder);
|
||||
|
||||
bool IsValid();
|
||||
bool CopyToTextureClient(layers::TextureClient* aClient);
|
||||
|
||||
gfx::SurfaceFormat GetFormat() const { return mFormat; }
|
||||
const gfx::IntSize& GetSize() const { return mSize; }
|
||||
|
||||
private:
|
||||
~D3D11SurfaceHolder();
|
||||
|
||||
private:
|
||||
RefPtr<ID3D11Device> mDevice11;
|
||||
RefPtr<ID3D11Texture2D> mBack;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
gfx::IntSize mSize;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // _include_dom_plugins_ipc_D3D11nSurfaceHolder_h__
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,111 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 "FunctionBrokerChild.h"
|
||||
#include "FunctionBrokerThread.h"
|
||||
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
FunctionBrokerChild* FunctionBrokerChild::sInstance = nullptr;
|
||||
|
||||
bool FunctionBrokerChild::IsDispatchThread() { return mThread->IsOnThread(); }
|
||||
|
||||
void FunctionBrokerChild::PostToDispatchThread(
|
||||
already_AddRefed<nsIRunnable>&& runnable) {
|
||||
mThread->Dispatch(std::move(runnable));
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool FunctionBrokerChild::Initialize(
|
||||
Endpoint<PFunctionBrokerChild>&& aBrokerEndpoint) {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
XRE_IsPluginProcess(),
|
||||
"FunctionBrokerChild can only be used in plugin processes");
|
||||
|
||||
MOZ_ASSERT(!sInstance);
|
||||
FunctionBrokerThread* thread = FunctionBrokerThread::Create();
|
||||
if (!thread) {
|
||||
return false;
|
||||
}
|
||||
sInstance = new FunctionBrokerChild(thread, std::move(aBrokerEndpoint));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
FunctionBrokerChild* FunctionBrokerChild::GetInstance() {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
XRE_IsPluginProcess(),
|
||||
"FunctionBrokerChild can only be used in plugin processes");
|
||||
|
||||
MOZ_ASSERT(sInstance, "Must initialize FunctionBrokerChild before using it");
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
FunctionBrokerChild::FunctionBrokerChild(
|
||||
FunctionBrokerThread* aThread, Endpoint<PFunctionBrokerChild>&& aEndpoint)
|
||||
: mThread(aThread),
|
||||
mShutdownDone(false),
|
||||
mMonitor("FunctionBrokerChild Lock") {
|
||||
MOZ_ASSERT(aThread);
|
||||
PostToDispatchThread(
|
||||
NewNonOwningRunnableMethod<Endpoint<PFunctionBrokerChild>&&>(
|
||||
"FunctionBrokerChild::Bind", this, &FunctionBrokerChild::Bind,
|
||||
std::move(aEndpoint)));
|
||||
}
|
||||
|
||||
void FunctionBrokerChild::Bind(Endpoint<PFunctionBrokerChild>&& aEndpoint) {
|
||||
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
|
||||
DebugOnly<bool> ok = aEndpoint.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
void FunctionBrokerChild::ShutdownOnDispatchThread() {
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
|
||||
// Set mShutdownDone and notify waiting thread (if any) that we are done.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mShutdownDone = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
void FunctionBrokerChild::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
|
||||
// Queue up a task on the PD thread. When that task is executed then
|
||||
// we know that anything queued before ActorDestroy has completed.
|
||||
// At that point, we can set mShutdownDone and alert any waiting
|
||||
// threads that it is safe to destroy us.
|
||||
sInstance->PostToDispatchThread(NewNonOwningRunnableMethod(
|
||||
"FunctionBrokerChild::ShutdownOnDispatchThread", sInstance,
|
||||
&FunctionBrokerChild::ShutdownOnDispatchThread));
|
||||
}
|
||||
|
||||
void FunctionBrokerChild::Destroy() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!sInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
// mShutdownDone will tell us when ActorDestroy has been run and any tasks
|
||||
// on the FunctionBrokerThread have completed. At that point, we can
|
||||
// safely delete the actor.
|
||||
{
|
||||
MonitorAutoLock lock(sInstance->mMonitor);
|
||||
while (!sInstance->mShutdownDone) {
|
||||
// Release lock and wait. Regain lock when we are notified that
|
||||
// we have ShutdownOnDispatchThread.
|
||||
sInstance->mMonitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
delete sInstance;
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,51 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 mozilla_plugins_functionbrokerchild_h
|
||||
#define mozilla_plugins_functionbrokerchild_h
|
||||
|
||||
#include "mozilla/plugins/PFunctionBrokerChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class FunctionBrokerThread;
|
||||
|
||||
/**
|
||||
* Dispatches brokered methods to the Parent process to allow functionality
|
||||
* that is otherwise blocked by the sandbox.
|
||||
*/
|
||||
class FunctionBrokerChild : public PFunctionBrokerChild {
|
||||
public:
|
||||
static bool Initialize(Endpoint<PFunctionBrokerChild>&& aBrokerEndpoint);
|
||||
static FunctionBrokerChild* GetInstance();
|
||||
static void Destroy();
|
||||
|
||||
bool IsDispatchThread();
|
||||
void PostToDispatchThread(already_AddRefed<nsIRunnable>&& runnable);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
private:
|
||||
explicit FunctionBrokerChild(FunctionBrokerThread* aThread,
|
||||
Endpoint<PFunctionBrokerChild>&& aEndpoint);
|
||||
void ShutdownOnDispatchThread();
|
||||
void Bind(Endpoint<PFunctionBrokerChild>&& aEndpoint);
|
||||
|
||||
UniquePtr<FunctionBrokerThread> mThread;
|
||||
|
||||
// True if tasks on the FunctionBrokerThread have completed
|
||||
bool mShutdownDone;
|
||||
// This monitor guards mShutdownDone.
|
||||
Monitor mMonitor;
|
||||
|
||||
static FunctionBrokerChild* sInstance;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_functionbrokerchild_h
|
|
@ -1,334 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* 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 "FunctionBrokerIPCUtils.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
# include <schannel.h>
|
||||
|
||||
/* these defines are missing from mingw headers */
|
||||
# ifndef SP_PROT_TLS1_1_CLIENT
|
||||
# define SP_PROT_TLS1_1_CLIENT 0x00000200
|
||||
# endif
|
||||
|
||||
# ifndef SP_PROT_TLS1_2_CLIENT
|
||||
# define SP_PROT_TLS1_2_CLIENT 0x00000800
|
||||
# endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
mozilla::LazyLogModule sPluginHooksLog("PluginHooks");
|
||||
|
||||
static const DWORD SCHANNEL_SUPPORTED_PROTOCOLS =
|
||||
SP_PROT_TLS1_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
|
||||
|
||||
static const DWORD SCHANNEL_SUPPORTED_FLAGS =
|
||||
SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_DEFAULT_CREDS |
|
||||
SCH_CRED_REVOCATION_CHECK_END_CERT;
|
||||
|
||||
void OpenFileNameIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn) {
|
||||
mHwndOwner = nullptr;
|
||||
|
||||
// Filter is double-NULL terminated. mFilter should include the double-NULL.
|
||||
mHasFilter = aLpofn->lpstrFilter != nullptr;
|
||||
if (mHasFilter) {
|
||||
uint32_t dNullIdx = 0;
|
||||
while (aLpofn->lpstrFilter[dNullIdx] != L'\0' ||
|
||||
aLpofn->lpstrFilter[dNullIdx + 1] != L'\0') {
|
||||
dNullIdx++;
|
||||
}
|
||||
mFilter.assign(aLpofn->lpstrFilter, dNullIdx + 2);
|
||||
}
|
||||
mHasCustomFilter = aLpofn->lpstrCustomFilter != nullptr;
|
||||
if (mHasCustomFilter) {
|
||||
mCustomFilterIn = std::wstring(aLpofn->lpstrCustomFilter);
|
||||
mNMaxCustFilterOut =
|
||||
aLpofn->nMaxCustFilter - (wcslen(aLpofn->lpstrCustomFilter) + 1);
|
||||
} else {
|
||||
mNMaxCustFilterOut = 0;
|
||||
}
|
||||
mFilterIndex = aLpofn->nFilterIndex;
|
||||
mFile = std::wstring(aLpofn->lpstrFile);
|
||||
mNMaxFile = aLpofn->nMaxFile;
|
||||
mNMaxFileTitle =
|
||||
aLpofn->lpstrFileTitle != nullptr ? aLpofn->nMaxFileTitle : 0;
|
||||
mHasInitialDir = aLpofn->lpstrInitialDir != nullptr;
|
||||
if (mHasInitialDir) {
|
||||
mInitialDir = std::wstring(aLpofn->lpstrInitialDir);
|
||||
}
|
||||
mHasTitle = aLpofn->lpstrTitle != nullptr;
|
||||
if (mHasTitle) {
|
||||
mTitle = std::wstring(aLpofn->lpstrTitle);
|
||||
}
|
||||
mHasDefExt = aLpofn->lpstrDefExt != nullptr;
|
||||
if (mHasDefExt) {
|
||||
mDefExt = std::wstring(aLpofn->lpstrDefExt);
|
||||
}
|
||||
|
||||
mFlags = aLpofn->Flags;
|
||||
// If the user sets OFN_ALLOWMULTISELECT then we require OFN_EXPLORER
|
||||
// as well. Without OFN_EXPLORER, the method has ancient legacy
|
||||
// behavior that we don't support.
|
||||
MOZ_ASSERT((mFlags & OFN_EXPLORER) || !(mFlags & OFN_ALLOWMULTISELECT));
|
||||
|
||||
// We ignore any visual customization and callbacks that the user set.
|
||||
mFlags &= ~(OFN_ENABLEHOOK | OFN_ENABLETEMPLATEHANDLE | OFN_ENABLETEMPLATE);
|
||||
|
||||
mFlagsEx = aLpofn->FlagsEx;
|
||||
}
|
||||
|
||||
void OpenFileNameIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const {
|
||||
aLpofn->lStructSize = sizeof(OPENFILENAMEW);
|
||||
aLpofn->hwndOwner = mHwndOwner;
|
||||
if (mHasFilter) {
|
||||
memcpy(const_cast<LPWSTR>(aLpofn->lpstrFilter), mFilter.data(),
|
||||
mFilter.size() * sizeof(wchar_t));
|
||||
}
|
||||
if (mHasCustomFilter) {
|
||||
aLpofn->nMaxCustFilter = mCustomFilterIn.size() + 1 + mNMaxCustFilterOut;
|
||||
wcscpy(aLpofn->lpstrCustomFilter, mCustomFilterIn.c_str());
|
||||
memset(aLpofn->lpstrCustomFilter + mCustomFilterIn.size() + 1, 0,
|
||||
mNMaxCustFilterOut * sizeof(wchar_t));
|
||||
} else {
|
||||
aLpofn->nMaxCustFilter = 0;
|
||||
}
|
||||
aLpofn->nFilterIndex = mFilterIndex;
|
||||
if (mNMaxFile > 0) {
|
||||
wcsncpy(aLpofn->lpstrFile, mFile.c_str(),
|
||||
std::min(static_cast<uint32_t>(mFile.size() + 1), mNMaxFile));
|
||||
aLpofn->lpstrFile[mNMaxFile - 1] = L'\0';
|
||||
}
|
||||
aLpofn->nMaxFile = mNMaxFile;
|
||||
aLpofn->nMaxFileTitle = mNMaxFileTitle;
|
||||
if (mHasInitialDir) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrInitialDir), mInitialDir.c_str());
|
||||
}
|
||||
if (mHasTitle) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrTitle), mTitle.c_str());
|
||||
}
|
||||
aLpofn->Flags = mFlags; /* TODO: Consider adding OFN_NOCHANGEDIR */
|
||||
if (mHasDefExt) {
|
||||
wcscpy(const_cast<LPWSTR>(aLpofn->lpstrDefExt), mDefExt.c_str());
|
||||
}
|
||||
aLpofn->FlagsEx = mFlagsEx;
|
||||
}
|
||||
|
||||
void OpenFileNameIPC::AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const {
|
||||
if (mHasFilter) {
|
||||
// mFilter is double-NULL terminated and it includes the double-NULL in its
|
||||
// length.
|
||||
aLpofn->lpstrFilter =
|
||||
static_cast<LPCTSTR>(moz_xmalloc(sizeof(wchar_t) * (mFilter.size())));
|
||||
}
|
||||
if (mHasCustomFilter) {
|
||||
aLpofn->lpstrCustomFilter = static_cast<LPTSTR>(moz_xmalloc(
|
||||
sizeof(wchar_t) * (mCustomFilterIn.size() + 1 + mNMaxCustFilterOut)));
|
||||
}
|
||||
aLpofn->lpstrFile =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFile));
|
||||
if (mNMaxFileTitle > 0) {
|
||||
aLpofn->lpstrFileTitle =
|
||||
static_cast<LPTSTR>(moz_xmalloc(sizeof(wchar_t) * mNMaxFileTitle));
|
||||
}
|
||||
if (mHasInitialDir) {
|
||||
aLpofn->lpstrInitialDir = static_cast<LPCTSTR>(
|
||||
moz_xmalloc(sizeof(wchar_t) * (mInitialDir.size() + 1)));
|
||||
}
|
||||
if (mHasTitle) {
|
||||
aLpofn->lpstrTitle = static_cast<LPCTSTR>(
|
||||
moz_xmalloc(sizeof(wchar_t) * (mTitle.size() + 1)));
|
||||
}
|
||||
if (mHasDefExt) {
|
||||
aLpofn->lpstrDefExt = static_cast<LPCTSTR>(
|
||||
moz_xmalloc(sizeof(wchar_t) * (mDefExt.size() + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void OpenFileNameIPC::FreeOfnStrings(LPOPENFILENAMEW aLpofn) {
|
||||
if (aLpofn->lpstrFilter) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrFilter));
|
||||
}
|
||||
if (aLpofn->lpstrCustomFilter) {
|
||||
free(aLpofn->lpstrCustomFilter);
|
||||
}
|
||||
if (aLpofn->lpstrFile) {
|
||||
free(aLpofn->lpstrFile);
|
||||
}
|
||||
if (aLpofn->lpstrFileTitle) {
|
||||
free(aLpofn->lpstrFileTitle);
|
||||
}
|
||||
if (aLpofn->lpstrInitialDir) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrInitialDir));
|
||||
}
|
||||
if (aLpofn->lpstrTitle) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrTitle));
|
||||
}
|
||||
if (aLpofn->lpstrDefExt) {
|
||||
free(const_cast<LPWSTR>(aLpofn->lpstrDefExt));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenFileNameRetIPC::CopyFromOfn(LPOPENFILENAMEW aLpofn) {
|
||||
if (aLpofn->lpstrCustomFilter != nullptr) {
|
||||
mCustomFilterOut = std::wstring(aLpofn->lpstrCustomFilter +
|
||||
wcslen(aLpofn->lpstrCustomFilter) + 1);
|
||||
}
|
||||
mFile.assign(aLpofn->lpstrFile, aLpofn->nMaxFile);
|
||||
if (aLpofn->lpstrFileTitle != nullptr) {
|
||||
mFileTitle.assign(aLpofn->lpstrFileTitle,
|
||||
wcslen(aLpofn->lpstrFileTitle) + 1);
|
||||
}
|
||||
mFileOffset = aLpofn->nFileOffset;
|
||||
mFileExtension = aLpofn->nFileExtension;
|
||||
}
|
||||
|
||||
void OpenFileNameRetIPC::AddToOfn(LPOPENFILENAMEW aLpofn) const {
|
||||
if (aLpofn->lpstrCustomFilter) {
|
||||
LPWSTR secondString =
|
||||
aLpofn->lpstrCustomFilter + wcslen(aLpofn->lpstrCustomFilter) + 1;
|
||||
const wchar_t* customFilterOut = mCustomFilterOut.c_str();
|
||||
MOZ_ASSERT(wcslen(aLpofn->lpstrCustomFilter) + 1 + wcslen(customFilterOut) +
|
||||
1 + 1 <=
|
||||
aLpofn->nMaxCustFilter);
|
||||
wcscpy(secondString, customFilterOut);
|
||||
secondString[wcslen(customFilterOut) + 1] =
|
||||
L'\0'; // terminated with two NULLs
|
||||
}
|
||||
MOZ_ASSERT(mFile.size() <= aLpofn->nMaxFile);
|
||||
memcpy(aLpofn->lpstrFile, mFile.data(), mFile.size() * sizeof(wchar_t));
|
||||
if (aLpofn->lpstrFileTitle != nullptr) {
|
||||
MOZ_ASSERT(mFileTitle.size() + 1 < aLpofn->nMaxFileTitle);
|
||||
wcscpy(aLpofn->lpstrFileTitle, mFileTitle.c_str());
|
||||
}
|
||||
aLpofn->nFileOffset = mFileOffset;
|
||||
aLpofn->nFileExtension = mFileExtension;
|
||||
}
|
||||
|
||||
void IPCSchannelCred::CopyFrom(const PSCHANNEL_CRED& aSCred) {
|
||||
// We assert that the aSCred fields take supported values.
|
||||
// If they do not then we ignore the values we were given.
|
||||
MOZ_ASSERT(aSCred->dwVersion == SCHANNEL_CRED_VERSION);
|
||||
MOZ_ASSERT(aSCred->cCreds == 0);
|
||||
MOZ_ASSERT(aSCred->paCred == nullptr);
|
||||
MOZ_ASSERT(aSCred->hRootStore == nullptr);
|
||||
MOZ_ASSERT(aSCred->cMappers == 0);
|
||||
MOZ_ASSERT(aSCred->aphMappers == nullptr);
|
||||
MOZ_ASSERT(aSCred->cSupportedAlgs == 0);
|
||||
MOZ_ASSERT(aSCred->palgSupportedAlgs == nullptr);
|
||||
MOZ_ASSERT((aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS) ==
|
||||
aSCred->grbitEnabledProtocols);
|
||||
mEnabledProtocols =
|
||||
aSCred->grbitEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
|
||||
mMinStrength = aSCred->dwMinimumCipherStrength;
|
||||
mMaxStrength = aSCred->dwMaximumCipherStrength;
|
||||
MOZ_ASSERT(aSCred->dwSessionLifespan == 0);
|
||||
MOZ_ASSERT((aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS) == aSCred->dwFlags);
|
||||
mFlags = aSCred->dwFlags & SCHANNEL_SUPPORTED_FLAGS;
|
||||
MOZ_ASSERT(aSCred->dwCredFormat == 0);
|
||||
}
|
||||
|
||||
void IPCSchannelCred::CopyTo(PSCHANNEL_CRED& aSCred) const {
|
||||
// Validate values as they come from an untrusted process.
|
||||
memset(aSCred, 0, sizeof(SCHANNEL_CRED));
|
||||
aSCred->dwVersion = SCHANNEL_CRED_VERSION;
|
||||
aSCred->grbitEnabledProtocols =
|
||||
mEnabledProtocols & SCHANNEL_SUPPORTED_PROTOCOLS;
|
||||
aSCred->dwMinimumCipherStrength = mMinStrength;
|
||||
aSCred->dwMaximumCipherStrength = mMaxStrength;
|
||||
aSCred->dwFlags = mFlags & SCHANNEL_SUPPORTED_FLAGS;
|
||||
}
|
||||
|
||||
void IPCInternetBuffers::CopyFrom(const LPINTERNET_BUFFERSA& aBufs) {
|
||||
mBuffers.Clear();
|
||||
|
||||
LPINTERNET_BUFFERSA inetBuf = aBufs;
|
||||
while (inetBuf) {
|
||||
MOZ_ASSERT(inetBuf->dwStructSize == sizeof(INTERNET_BUFFERSA));
|
||||
Buffer* ipcBuf = mBuffers.AppendElement();
|
||||
|
||||
ipcBuf->mHeader.SetIsVoid(inetBuf->lpcszHeader == nullptr);
|
||||
if (inetBuf->lpcszHeader) {
|
||||
ipcBuf->mHeader.Assign(inetBuf->lpcszHeader, inetBuf->dwHeadersLength);
|
||||
}
|
||||
ipcBuf->mHeaderTotal = inetBuf->dwHeadersTotal;
|
||||
|
||||
ipcBuf->mBuffer.SetIsVoid(inetBuf->lpvBuffer == nullptr);
|
||||
if (inetBuf->lpvBuffer) {
|
||||
ipcBuf->mBuffer.Assign(static_cast<char*>(inetBuf->lpvBuffer),
|
||||
inetBuf->dwBufferLength);
|
||||
}
|
||||
ipcBuf->mBufferTotal = inetBuf->dwBufferTotal;
|
||||
inetBuf = inetBuf->Next;
|
||||
}
|
||||
}
|
||||
|
||||
void IPCInternetBuffers::CopyTo(LPINTERNET_BUFFERSA& aBufs) const {
|
||||
MOZ_ASSERT(!aBufs);
|
||||
|
||||
LPINTERNET_BUFFERSA lastBuf = nullptr;
|
||||
for (size_t idx = 0; idx < mBuffers.Length(); ++idx) {
|
||||
const Buffer& ipcBuf = mBuffers[idx];
|
||||
LPINTERNET_BUFFERSA newBuf = static_cast<LPINTERNET_BUFFERSA>(
|
||||
moz_xcalloc(1, sizeof(INTERNET_BUFFERSA)));
|
||||
if (idx == 0) {
|
||||
aBufs = newBuf;
|
||||
} else {
|
||||
MOZ_ASSERT(lastBuf);
|
||||
lastBuf->Next = newBuf;
|
||||
lastBuf = newBuf;
|
||||
}
|
||||
|
||||
newBuf->dwStructSize = sizeof(INTERNET_BUFFERSA);
|
||||
|
||||
newBuf->dwHeadersTotal = ipcBuf.mHeaderTotal;
|
||||
if (!ipcBuf.mHeader.IsVoid()) {
|
||||
newBuf->lpcszHeader =
|
||||
static_cast<LPCSTR>(moz_xmalloc(ipcBuf.mHeader.Length()));
|
||||
memcpy(const_cast<char*>(newBuf->lpcszHeader), ipcBuf.mHeader.Data(),
|
||||
ipcBuf.mHeader.Length());
|
||||
newBuf->dwHeadersLength = ipcBuf.mHeader.Length();
|
||||
}
|
||||
|
||||
newBuf->dwBufferTotal = ipcBuf.mBufferTotal;
|
||||
if (!ipcBuf.mBuffer.IsVoid()) {
|
||||
newBuf->lpvBuffer = moz_xmalloc(ipcBuf.mBuffer.Length());
|
||||
memcpy(newBuf->lpvBuffer, ipcBuf.mBuffer.Data(), ipcBuf.mBuffer.Length());
|
||||
newBuf->dwBufferLength = ipcBuf.mBuffer.Length();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void IPCInternetBuffers::FreeBuffers(LPINTERNET_BUFFERSA& aBufs) {
|
||||
if (!aBufs) {
|
||||
return;
|
||||
}
|
||||
while (aBufs) {
|
||||
LPINTERNET_BUFFERSA temp = aBufs->Next;
|
||||
free(const_cast<char*>(aBufs->lpcszHeader));
|
||||
free(aBufs->lpvBuffer);
|
||||
free(aBufs);
|
||||
aBufs = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void IPCPrintDlg::CopyFrom(const LPPRINTDLGW& aDlg) {
|
||||
// DLP: Trouble -- my prior impl "worked" but didn't return anything
|
||||
// AFAIR. So... ??? But it printed a page!!! How?!
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
|
||||
void IPCPrintDlg::CopyTo(LPPRINTDLGW& aDlg) const {
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined(XP_WIN)
|
|
@ -1,436 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 dom_plugins_ipc_functionbrokeripcutils_h
|
||||
#define dom_plugins_ipc_functionbrokeripcutils_h 1
|
||||
|
||||
#include "ipc/EnumSerializer.h"
|
||||
#include "ipc/IPCMessageUtilsSpecializations.h"
|
||||
#include "PluginMessageUtils.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
# define SECURITY_WIN32
|
||||
# include <security.h>
|
||||
# include <wininet.h>
|
||||
# include <schannel.h>
|
||||
# include <commdlg.h>
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* This enum represents all of the methods hooked by the main facility in
|
||||
* BrokerClient. It is used to allow quick lookup in the sFunctionsToHook
|
||||
* structure.
|
||||
*/
|
||||
enum FunctionHookId {
|
||||
#if defined(XP_WIN)
|
||||
ID_GetWindowInfo = 0,
|
||||
ID_GetKeyState,
|
||||
ID_SetCursorPos,
|
||||
ID_GetSaveFileNameW,
|
||||
ID_GetOpenFileNameW,
|
||||
ID_InternetOpenA,
|
||||
ID_InternetConnectA,
|
||||
ID_InternetCloseHandle,
|
||||
ID_InternetQueryDataAvailable,
|
||||
ID_InternetReadFile,
|
||||
ID_InternetWriteFile,
|
||||
ID_InternetSetOptionA,
|
||||
ID_HttpAddRequestHeadersA,
|
||||
ID_HttpOpenRequestA,
|
||||
ID_HttpQueryInfoA,
|
||||
ID_HttpSendRequestA,
|
||||
ID_HttpSendRequestExA,
|
||||
ID_HttpEndRequestA,
|
||||
ID_InternetQueryOptionA,
|
||||
ID_InternetErrorDlg,
|
||||
ID_AcquireCredentialsHandleA,
|
||||
ID_QueryCredentialsAttributesA,
|
||||
ID_FreeCredentialsHandle,
|
||||
ID_PrintDlgW,
|
||||
ID_CreateMutexW
|
||||
# if defined(MOZ_SANDBOX)
|
||||
,
|
||||
ID_GetFileAttributesW
|
||||
# endif // defined(MOZ_SANDBOX)
|
||||
,
|
||||
ID_FunctionHookCount
|
||||
#else // defined(XP_WIN)
|
||||
ID_FunctionHookCount
|
||||
#endif // defined(XP_WIN)
|
||||
};
|
||||
|
||||
// Max number of bytes to show when logging a blob of raw memory
|
||||
static const uint32_t MAX_BLOB_CHARS_TO_LOG = 12;
|
||||
|
||||
// Format strings for safe logging despite the fact that they are sometimes
|
||||
// used as raw binary blobs.
|
||||
inline nsCString FormatBlob(const nsACString& aParam) {
|
||||
if (aParam.IsVoid() || aParam.IsEmpty()) {
|
||||
return nsCString(aParam.IsVoid() ? "<void>" : "<empty>");
|
||||
}
|
||||
|
||||
nsCString str;
|
||||
uint32_t totalLen = std::min(MAX_BLOB_CHARS_TO_LOG, aParam.Length());
|
||||
// If we are printing only a portion of the string then follow it with
|
||||
// ellipsis
|
||||
const char* maybeEllipsis =
|
||||
(MAX_BLOB_CHARS_TO_LOG < aParam.Length()) ? "..." : "";
|
||||
for (uint32_t idx = 0; idx < totalLen; ++idx) {
|
||||
// Should be %02x but I've run into a AppendPrintf bug...
|
||||
str.AppendPrintf("0x%2x ", aParam.Data()[idx] & 0xff);
|
||||
}
|
||||
str.AppendPrintf("%s | '", maybeEllipsis);
|
||||
for (uint32_t idx = 0; idx < totalLen; ++idx) {
|
||||
str.AppendPrintf("%c", (aParam.Data()[idx] > 0) ? aParam.Data()[idx] : '.');
|
||||
}
|
||||
str.AppendPrintf("'%s", maybeEllipsis);
|
||||
return str;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
// Values indicate GetOpenFileNameW and GetSaveFileNameW.
|
||||
enum GetFileNameFunc { OPEN_FUNC, SAVE_FUNC };
|
||||
|
||||
typedef CopyableTArray<nsCString> StringArray;
|
||||
|
||||
// IPC-capable version of the Windows OPENFILENAMEW struct.
|
||||
typedef struct _OpenFileNameIPC {
|
||||
// Allocates memory for the strings in this object. This should usually
|
||||
// be used with a zeroed out OPENFILENAMEW structure.
|
||||
void AllocateOfnStrings(LPOPENFILENAMEW aLpofn) const;
|
||||
static void FreeOfnStrings(LPOPENFILENAMEW aLpofn);
|
||||
void AddToOfn(LPOPENFILENAMEW aLpofn) const;
|
||||
void CopyFromOfn(LPOPENFILENAMEW aLpofn);
|
||||
bool operator==(const _OpenFileNameIPC& o) const {
|
||||
return (o.mHwndOwner == mHwndOwner) && (o.mFilter == mFilter) &&
|
||||
(o.mHasFilter == mHasFilter) &&
|
||||
(o.mCustomFilterIn == mCustomFilterIn) &&
|
||||
(o.mHasCustomFilter == mHasCustomFilter) &&
|
||||
(o.mNMaxCustFilterOut == mNMaxCustFilterOut) &&
|
||||
(o.mFilterIndex == mFilterIndex) && (o.mFile == mFile) &&
|
||||
(o.mNMaxFile == mNMaxFile) && (o.mNMaxFileTitle == mNMaxFileTitle) &&
|
||||
(o.mInitialDir == mInitialDir) &&
|
||||
(o.mHasInitialDir == mHasInitialDir) && (o.mTitle == mTitle) &&
|
||||
(o.mHasTitle == mHasTitle) && (o.mFlags == mFlags) &&
|
||||
(o.mDefExt == mDefExt) && (o.mHasDefExt == mHasDefExt) &&
|
||||
(o.mFlagsEx == mFlagsEx);
|
||||
}
|
||||
|
||||
NativeWindowHandle mHwndOwner;
|
||||
std::wstring
|
||||
mFilter; // Double-NULL terminated (i.e. L"\0\0") if mHasFilter is true
|
||||
bool mHasFilter;
|
||||
std::wstring mCustomFilterIn;
|
||||
bool mHasCustomFilter;
|
||||
uint32_t mNMaxCustFilterOut;
|
||||
uint32_t mFilterIndex;
|
||||
std::wstring mFile;
|
||||
uint32_t mNMaxFile;
|
||||
uint32_t mNMaxFileTitle;
|
||||
std::wstring mInitialDir;
|
||||
bool mHasInitialDir;
|
||||
std::wstring mTitle;
|
||||
bool mHasTitle;
|
||||
uint32_t mFlags;
|
||||
std::wstring mDefExt;
|
||||
bool mHasDefExt;
|
||||
uint32_t mFlagsEx;
|
||||
} OpenFileNameIPC;
|
||||
|
||||
// GetOpenFileNameW and GetSaveFileNameW overwrite fields of their OPENFILENAMEW
|
||||
// parameter. This represents those values so that they can be returned via
|
||||
// IPC.
|
||||
typedef struct _OpenFileNameRetIPC {
|
||||
void CopyFromOfn(LPOPENFILENAMEW aLpofn);
|
||||
void AddToOfn(LPOPENFILENAMEW aLpofn) const;
|
||||
bool operator==(const _OpenFileNameRetIPC& o) const {
|
||||
return (o.mCustomFilterOut == mCustomFilterOut) && (o.mFile == mFile) &&
|
||||
(o.mFileTitle == mFileTitle) && (o.mFileOffset == mFileOffset) &&
|
||||
(o.mFileExtension == mFileExtension);
|
||||
}
|
||||
|
||||
std::wstring mCustomFilterOut;
|
||||
std::wstring mFile; // Double-NULL terminated (i.e. L"\0\0")
|
||||
std::wstring mFileTitle;
|
||||
uint16_t mFileOffset;
|
||||
uint16_t mFileExtension;
|
||||
} OpenFileNameRetIPC;
|
||||
|
||||
typedef struct _IPCSchannelCred {
|
||||
void CopyFrom(const PSCHANNEL_CRED& aSCred);
|
||||
void CopyTo(PSCHANNEL_CRED& aSCred) const;
|
||||
bool operator==(const _IPCSchannelCred& o) const {
|
||||
return (o.mEnabledProtocols == mEnabledProtocols) &&
|
||||
(o.mMinStrength == mMinStrength) &&
|
||||
(o.mMaxStrength == mMaxStrength) && (o.mFlags == mFlags);
|
||||
}
|
||||
|
||||
DWORD mEnabledProtocols;
|
||||
DWORD mMinStrength;
|
||||
DWORD mMaxStrength;
|
||||
DWORD mFlags;
|
||||
} IPCSchannelCred;
|
||||
|
||||
typedef struct _IPCInternetBuffers {
|
||||
void CopyFrom(const LPINTERNET_BUFFERSA& aBufs);
|
||||
void CopyTo(LPINTERNET_BUFFERSA& aBufs) const;
|
||||
bool operator==(const _IPCInternetBuffers& o) const {
|
||||
return o.mBuffers == mBuffers;
|
||||
}
|
||||
static void FreeBuffers(LPINTERNET_BUFFERSA& aBufs);
|
||||
|
||||
struct Buffer {
|
||||
nsCString mHeader;
|
||||
uint32_t mHeaderTotal;
|
||||
nsCString mBuffer;
|
||||
uint32_t mBufferTotal;
|
||||
bool operator==(const Buffer& o) const {
|
||||
return (o.mHeader == mHeader) && (o.mHeaderTotal == mHeaderTotal) &&
|
||||
(o.mBuffer == mBuffer) && (o.mBufferTotal == mBufferTotal);
|
||||
}
|
||||
};
|
||||
CopyableTArray<Buffer> mBuffers;
|
||||
} IPCInternetBuffers;
|
||||
|
||||
typedef struct _IPCPrintDlg {
|
||||
void CopyFrom(const LPPRINTDLGW& aDlg);
|
||||
void CopyTo(LPPRINTDLGW& aDlg) const;
|
||||
bool operator==(const _IPCPrintDlg& o) const {
|
||||
MOZ_ASSERT_UNREACHABLE("DLP: TODO:");
|
||||
return false;
|
||||
}
|
||||
} IPCPrintDlg;
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
using mozilla::plugins::FunctionHookId;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
using mozilla::plugins::IPCInternetBuffers;
|
||||
using mozilla::plugins::IPCPrintDlg;
|
||||
using mozilla::plugins::IPCSchannelCred;
|
||||
using mozilla::plugins::NativeWindowHandle;
|
||||
using mozilla::plugins::OpenFileNameIPC;
|
||||
using mozilla::plugins::OpenFileNameRetIPC;
|
||||
using mozilla::plugins::StringArray;
|
||||
|
||||
template <>
|
||||
struct ParamTraits<OpenFileNameIPC> {
|
||||
typedef OpenFileNameIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mHwndOwner);
|
||||
WriteParam(aMsg, aParam.mFilter);
|
||||
WriteParam(aMsg, aParam.mHasFilter);
|
||||
WriteParam(aMsg, aParam.mCustomFilterIn);
|
||||
WriteParam(aMsg, aParam.mHasCustomFilter);
|
||||
WriteParam(aMsg, aParam.mNMaxCustFilterOut);
|
||||
WriteParam(aMsg, aParam.mFilterIndex);
|
||||
WriteParam(aMsg, aParam.mFile);
|
||||
WriteParam(aMsg, aParam.mNMaxFile);
|
||||
WriteParam(aMsg, aParam.mNMaxFileTitle);
|
||||
WriteParam(aMsg, aParam.mInitialDir);
|
||||
WriteParam(aMsg, aParam.mHasInitialDir);
|
||||
WriteParam(aMsg, aParam.mTitle);
|
||||
WriteParam(aMsg, aParam.mHasTitle);
|
||||
WriteParam(aMsg, aParam.mFlags);
|
||||
WriteParam(aMsg, aParam.mDefExt);
|
||||
WriteParam(aMsg, aParam.mHasDefExt);
|
||||
WriteParam(aMsg, aParam.mFlagsEx);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
if (ReadParam(aMsg, aIter, &aResult->mHwndOwner) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mCustomFilterIn) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasCustomFilter) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxCustFilterOut) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFilterIndex) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mNMaxFileTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mInitialDir) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasInitialDir) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlags) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mDefExt) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHasDefExt) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlagsEx)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%ls, %ls, %ls, %ls]", aParam.mFilter.c_str(),
|
||||
aParam.mCustomFilterIn.c_str(),
|
||||
aParam.mFile.c_str(), aParam.mTitle.c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<OpenFileNameRetIPC> {
|
||||
typedef OpenFileNameRetIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mCustomFilterOut);
|
||||
WriteParam(aMsg, aParam.mFile);
|
||||
WriteParam(aMsg, aParam.mFileTitle);
|
||||
WriteParam(aMsg, aParam.mFileOffset);
|
||||
WriteParam(aMsg, aParam.mFileExtension);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
if (ReadParam(aMsg, aIter, &aResult->mCustomFilterOut) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFile) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileTitle) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileOffset) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFileExtension)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%ls, %ls, %ls, %d, %d]",
|
||||
aParam.mCustomFilterOut.c_str(),
|
||||
aParam.mFile.c_str(), aParam.mFileTitle.c_str(),
|
||||
aParam.mFileOffset, aParam.mFileExtension));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::GetFileNameFunc>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
mozilla::plugins::GetFileNameFunc, mozilla::plugins::OPEN_FUNC,
|
||||
mozilla::plugins::SAVE_FUNC> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCSchannelCred> {
|
||||
typedef mozilla::plugins::IPCSchannelCred paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mEnabledProtocols));
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mMinStrength));
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mMaxStrength));
|
||||
WriteParam(aMsg, static_cast<uint32_t>(aParam.mFlags));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint32_t proto, minStr, maxStr, flags;
|
||||
if (!ReadParam(aMsg, aIter, &proto) || !ReadParam(aMsg, aIter, &minStr) ||
|
||||
!ReadParam(aMsg, aIter, &maxStr) || !ReadParam(aMsg, aIter, &flags)) {
|
||||
return false;
|
||||
}
|
||||
aResult->mEnabledProtocols = proto;
|
||||
aResult->mMinStrength = minStr;
|
||||
aResult->mMaxStrength = maxStr;
|
||||
aResult->mFlags = flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%d,%d,%d,%d]", aParam.mEnabledProtocols,
|
||||
aParam.mMinStrength, aParam.mMaxStrength,
|
||||
aParam.mFlags));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCInternetBuffers::Buffer> {
|
||||
typedef mozilla::plugins::IPCInternetBuffers::Buffer paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mHeader);
|
||||
WriteParam(aMsg, aParam.mHeaderTotal);
|
||||
WriteParam(aMsg, aParam.mBuffer);
|
||||
WriteParam(aMsg, aParam.mBufferTotal);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
return ReadParam(aMsg, aIter, &aResult->mHeader) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mHeaderTotal) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mBuffer) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mBufferTotal);
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
nsCString head = mozilla::plugins::FormatBlob(aParam.mHeader);
|
||||
nsCString buffer = mozilla::plugins::FormatBlob(aParam.mBuffer);
|
||||
std::string msg =
|
||||
StringPrintf("[%s, %d, %s, %d]", head.Data(), aParam.mHeaderTotal,
|
||||
buffer.Data(), aParam.mBufferTotal);
|
||||
aLog->append(msg.begin(), msg.end());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCInternetBuffers> {
|
||||
typedef mozilla::plugins::IPCInternetBuffers paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mBuffers);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
return ReadParam(aMsg, aIter, &aResult->mBuffers);
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
ParamTraits<nsTArray<IPCInternetBuffers::Buffer>>::Log(aParam.mBuffers,
|
||||
aLog);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IPCPrintDlg> {
|
||||
typedef mozilla::plugins::IPCPrintDlg paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
MOZ_ASSERT_UNREACHABLE("TODO: DLP:");
|
||||
}
|
||||
};
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
template <>
|
||||
struct ParamTraits<FunctionHookId>
|
||||
: public ContiguousEnumSerializer<FunctionHookId,
|
||||
static_cast<FunctionHookId>(0),
|
||||
FunctionHookId::ID_FunctionHookCount> {};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif /* dom_plugins_ipc_functionbrokeripcutils_h */
|
|
@ -1,139 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 "FunctionBrokerParent.h"
|
||||
#include "FunctionBroker.h"
|
||||
#include "FunctionBrokerThread.h"
|
||||
|
||||
#include "mozilla/ipc/Endpoint.h"
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
#if defined(XP_WIN)
|
||||
UlongPairToIdMap sPairToIdMap;
|
||||
IdToUlongPairMap sIdToPairMap;
|
||||
PtrToIdMap sPtrToIdMap;
|
||||
IdToPtrMap sIdToPtrMap;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
/* static */
|
||||
FunctionBrokerParent* FunctionBrokerParent::Create(
|
||||
Endpoint<PFunctionBrokerParent>&& aParentEnd) {
|
||||
FunctionBrokerThread* thread = FunctionBrokerThread::Create();
|
||||
if (!thread) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// We get the FunctionHooks so that they are created here, not on the
|
||||
// message thread.
|
||||
FunctionHook::GetHooks();
|
||||
|
||||
return new FunctionBrokerParent(thread, std::move(aParentEnd));
|
||||
}
|
||||
|
||||
FunctionBrokerParent::FunctionBrokerParent(
|
||||
FunctionBrokerThread* aThread, Endpoint<PFunctionBrokerParent>&& aParentEnd)
|
||||
: mThread(aThread),
|
||||
mMonitor("FunctionBrokerParent Lock"),
|
||||
mShutdownDone(false) {
|
||||
MOZ_ASSERT(mThread);
|
||||
mThread->Dispatch(
|
||||
NewNonOwningRunnableMethod<Endpoint<PFunctionBrokerParent>&&>(
|
||||
"FunctionBrokerParent::Bind", this, &FunctionBrokerParent::Bind,
|
||||
std::move(aParentEnd)));
|
||||
}
|
||||
|
||||
FunctionBrokerParent::~FunctionBrokerParent() {
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
// Clean up any file permissions that we granted to the child process.
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
RemovePermissionsForProcess(OtherPid());
|
||||
#endif
|
||||
}
|
||||
|
||||
void FunctionBrokerParent::Bind(Endpoint<PFunctionBrokerParent>&& aEnd) {
|
||||
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
|
||||
DebugOnly<bool> ok = aEnd.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
}
|
||||
|
||||
void FunctionBrokerParent::ShutdownOnBrokerThread() {
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
Close();
|
||||
|
||||
// Notify waiting thread that we are done.
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mShutdownDone = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
void FunctionBrokerParent::Destroy(FunctionBrokerParent* aInst) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aInst);
|
||||
|
||||
{
|
||||
// Hold the lock while we destroy the actor on the broker thread.
|
||||
MonitorAutoLock lock(aInst->mMonitor);
|
||||
aInst->mThread->Dispatch(NewNonOwningRunnableMethod(
|
||||
"FunctionBrokerParent::ShutdownOnBrokerThread", aInst,
|
||||
&FunctionBrokerParent::ShutdownOnBrokerThread));
|
||||
|
||||
// Wait for broker thread to complete destruction.
|
||||
while (!aInst->mShutdownDone) {
|
||||
aInst->mMonitor.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
delete aInst;
|
||||
}
|
||||
|
||||
void FunctionBrokerParent::ActorDestroy(ActorDestroyReason aWhy) {
|
||||
MOZ_RELEASE_ASSERT(mThread->IsOnThread());
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult FunctionBrokerParent::RecvBrokerFunction(
|
||||
const FunctionHookId& aFunctionId, const IpdlTuple& aInTuple,
|
||||
IpdlTuple* aOutTuple) {
|
||||
#if defined(XP_WIN)
|
||||
MOZ_ASSERT(mThread->IsOnThread());
|
||||
if (RunBrokeredFunction(OtherPid(), aFunctionId, aInTuple, aOutTuple)) {
|
||||
return IPC_OK();
|
||||
}
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#else
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"BrokerFunction is currently only implemented on Windows.");
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
bool FunctionBrokerParent::RunBrokeredFunction(
|
||||
base::ProcessId aClientId, const FunctionHookId& aFunctionId,
|
||||
const IPC::IpdlTuple& aInTuple, IPC::IpdlTuple* aOutTuple) {
|
||||
if ((size_t)aFunctionId >= FunctionHook::GetHooks()->Length()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid function ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionHook* hook = FunctionHook::GetHooks()->ElementAt(aFunctionId);
|
||||
MOZ_ASSERT(hook->FunctionId() == aFunctionId);
|
||||
return hook->RunOriginalFunction(aClientId, aInTuple, aOutTuple);
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
mozilla::SandboxPermissions FunctionBrokerParent::sSandboxPermissions;
|
||||
|
||||
// static
|
||||
void FunctionBrokerParent::RemovePermissionsForProcess(
|
||||
base::ProcessId aClientId) {
|
||||
sSandboxPermissions.RemovePermissionsForProcess(aClientId);
|
||||
}
|
||||
|
||||
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,67 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 mozilla_plugins_functionbrokerparent_h
|
||||
#define mozilla_plugins_functionbrokerparent_h
|
||||
|
||||
#include "mozilla/plugins/PFunctionBrokerParent.h"
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
# include "sandboxPermissions.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class FunctionBrokerThread;
|
||||
|
||||
/**
|
||||
* Top-level actor run on the process to which we broker calls from sandboxed
|
||||
* plugin processes.
|
||||
*/
|
||||
class FunctionBrokerParent : public PFunctionBrokerParent {
|
||||
public:
|
||||
static FunctionBrokerParent* Create(
|
||||
Endpoint<PFunctionBrokerParent>&& aParentEnd);
|
||||
static void Destroy(FunctionBrokerParent* aInst);
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvBrokerFunction(const FunctionHookId& aFunctionId,
|
||||
const IpdlTuple& aInTuple,
|
||||
IpdlTuple* aOutTuple) override;
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
static mozilla::SandboxPermissions* GetSandboxPermissions() {
|
||||
return &sSandboxPermissions;
|
||||
}
|
||||
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
private:
|
||||
explicit FunctionBrokerParent(FunctionBrokerThread* aThread,
|
||||
Endpoint<PFunctionBrokerParent>&& aParentEnd);
|
||||
~FunctionBrokerParent();
|
||||
void ShutdownOnBrokerThread();
|
||||
void Bind(Endpoint<PFunctionBrokerParent>&& aEnd);
|
||||
|
||||
static bool RunBrokeredFunction(base::ProcessId aClientId,
|
||||
const FunctionHookId& aFunctionId,
|
||||
const IPC::IpdlTuple& aInTuple,
|
||||
IPC::IpdlTuple* aOutTuple);
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
static void RemovePermissionsForProcess(base::ProcessId aClientId);
|
||||
static mozilla::SandboxPermissions sSandboxPermissions;
|
||||
#endif // defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
|
||||
UniquePtr<FunctionBrokerThread> mThread;
|
||||
Monitor mMonitor;
|
||||
bool mShutdownDone;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_functionbrokerparent_hk
|
|
@ -1,52 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 mozilla_plugins_functionbrokerthread_h
|
||||
#define mozilla_plugins_functionbrokerthread_h
|
||||
|
||||
#include "nsThreadManager.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class FunctionBrokerThread {
|
||||
public:
|
||||
void Dispatch(already_AddRefed<nsIRunnable>&& aRunnable) {
|
||||
mThread->Dispatch(std::move(aRunnable), nsIEventTarget::NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
bool IsOnThread() {
|
||||
bool on;
|
||||
return NS_SUCCEEDED(mThread->IsOnCurrentThread(&on)) && on;
|
||||
}
|
||||
|
||||
static FunctionBrokerThread* Create() {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
if (NS_FAILED(
|
||||
NS_NewNamedThread("Function Broker", getter_AddRefs(thread)))) {
|
||||
return nullptr;
|
||||
}
|
||||
return new FunctionBrokerThread(thread);
|
||||
}
|
||||
|
||||
~FunctionBrokerThread() {
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
mThread->Shutdown();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit FunctionBrokerThread(nsIThread* aThread) : mThread(aThread) {
|
||||
MOZ_ASSERT(mThread);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_functionbrokerthread_h
|
|
@ -1,359 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 "mozilla/TextUtils.h"
|
||||
|
||||
#include "FunctionHook.h"
|
||||
#include "FunctionBroker.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include <shlobj.h>
|
||||
# include "PluginModuleChild.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
StaticAutoPtr<FunctionHookArray> FunctionHook::sFunctionHooks;
|
||||
|
||||
bool AlwaysHook(int) { return true; }
|
||||
|
||||
FunctionHookArray* FunctionHook::GetHooks() {
|
||||
if (sFunctionHooks) {
|
||||
return sFunctionHooks;
|
||||
}
|
||||
|
||||
// sFunctionHooks is the StaticAutoPtr to the singleton array of FunctionHook
|
||||
// objects. We free it by clearing the StaticAutoPtr on shutdown.
|
||||
sFunctionHooks = new FunctionHookArray();
|
||||
ClearOnShutdown(&sFunctionHooks);
|
||||
sFunctionHooks->SetLength(ID_FunctionHookCount);
|
||||
|
||||
AddFunctionHooks(*sFunctionHooks);
|
||||
AddBrokeredFunctionHooks(*sFunctionHooks);
|
||||
return sFunctionHooks;
|
||||
}
|
||||
|
||||
void FunctionHook::HookFunctions(int aQuirks) {
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
|
||||
FunctionHookArray* hooks = FunctionHook::GetHooks();
|
||||
MOZ_ASSERT(hooks);
|
||||
for (size_t i = 0; i < hooks->Length(); ++i) {
|
||||
FunctionHook* mhb = hooks->ElementAt(i);
|
||||
// Check that the FunctionHook array is in the same order as the
|
||||
// FunctionHookId enum.
|
||||
MOZ_ASSERT((size_t)mhb->FunctionId() == i);
|
||||
mhb->Register(aQuirks);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
|
||||
// This cache is created when a DLL is registered with a FunctionHook.
|
||||
// It is cleared on a call to ClearDllInterceptorCache(). It
|
||||
// must be freed before exit to avoid leaks.
|
||||
typedef nsClassHashtable<nsStringHashKey, WindowsDllInterceptor>
|
||||
DllInterceptors;
|
||||
DllInterceptors* sDllInterceptorCache = nullptr;
|
||||
|
||||
WindowsDllInterceptor* FunctionHook::GetDllInterceptorFor(
|
||||
const char* aModuleName) {
|
||||
if (!sDllInterceptorCache) {
|
||||
sDllInterceptorCache = new DllInterceptors();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(IsAsciiNullTerminated(aModuleName),
|
||||
"Non-ASCII module names are not supported");
|
||||
NS_ConvertASCIItoUTF16 moduleName(aModuleName);
|
||||
|
||||
WindowsDllInterceptor* ret = sDllInterceptorCache->GetOrInsertNew(moduleName);
|
||||
MOZ_ASSERT(ret);
|
||||
ret->Init(moduleName.get());
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FunctionHook::ClearDllInterceptorCache() {
|
||||
delete sDllInterceptorCache;
|
||||
sDllInterceptorCache = nullptr;
|
||||
}
|
||||
|
||||
/* GetWindowInfo */
|
||||
|
||||
typedef BasicFunctionHook<ID_GetWindowInfo, decltype(GetWindowInfo)>
|
||||
GetWindowInfoFH;
|
||||
|
||||
template <>
|
||||
ShouldHookFunc* const GetWindowInfoFH::mShouldHook =
|
||||
&CheckQuirks<QUIRK_FLASH_HOOK_GETWINDOWINFO>;
|
||||
|
||||
static const wchar_t* kMozillaWindowClass = L"MozillaWindowClass";
|
||||
static HWND sBrowserHwnd = nullptr;
|
||||
|
||||
INTERCEPTOR_DISABLE_CFGUARD BOOL WINAPI GetWindowInfoHook(HWND hWnd,
|
||||
PWINDOWINFO pwi) {
|
||||
if (!pwi) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(ID_GetWindowInfo < FunctionHook::GetHooks()->Length());
|
||||
GetWindowInfoFH* functionHook = static_cast<GetWindowInfoFH*>(
|
||||
FunctionHook::GetHooks()->ElementAt(ID_GetWindowInfo));
|
||||
if (!functionHook->OriginalFunction()) {
|
||||
NS_ASSERTION(FALSE, "Something is horribly wrong in PHGetWindowInfoHook!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!sBrowserHwnd) {
|
||||
wchar_t szClass[20];
|
||||
// GetClassNameW returns the length it copied w/o null terminator.
|
||||
// Therefore, if the name and null-terminator fit then it returns a
|
||||
// value less than the buffer's length.
|
||||
int nameLen = GetClassNameW(hWnd, szClass, ArrayLength(szClass));
|
||||
if ((nameLen < (int)ArrayLength(szClass)) &&
|
||||
!wcscmp(szClass, kMozillaWindowClass)) {
|
||||
sBrowserHwnd = hWnd;
|
||||
}
|
||||
}
|
||||
|
||||
// Oddity: flash does strange rect comparisons for mouse input destined for
|
||||
// it's internal settings window. Post removing sub widgets for tabs, touch
|
||||
// this up so they get the rect they expect.
|
||||
// XXX potentially tie this to a specific major version?
|
||||
typedef BOOL(WINAPI * GetWindowInfoPtr)(HWND hwnd, PWINDOWINFO pwi);
|
||||
GetWindowInfoPtr gwiFunc =
|
||||
static_cast<GetWindowInfoPtr>(functionHook->OriginalFunction());
|
||||
BOOL result = gwiFunc(hWnd, pwi);
|
||||
if (sBrowserHwnd && sBrowserHwnd == hWnd) {
|
||||
pwi->rcWindow = pwi->rcClient;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* PrintDlgW */
|
||||
|
||||
typedef BasicFunctionHook<ID_PrintDlgW, decltype(PrintDlgW)> PrintDlgWFH;
|
||||
|
||||
template <>
|
||||
ShouldHookFunc* const PrintDlgWFH::mShouldHook =
|
||||
&CheckQuirks<QUIRK_FLASH_HOOK_PRINTDLGW>;
|
||||
|
||||
INTERCEPTOR_DISABLE_CFGUARD BOOL WINAPI PrintDlgWHook(LPPRINTDLGW aDlg) {
|
||||
// Zero out the HWND supplied by the plugin. We are sacrificing window
|
||||
// parentage for the ability to run in the NPAPI sandbox.
|
||||
HWND hwnd = aDlg->hwndOwner;
|
||||
aDlg->hwndOwner = 0;
|
||||
MOZ_ASSERT(ID_PrintDlgW < FunctionHook::GetHooks()->Length());
|
||||
PrintDlgWFH* functionHook = static_cast<PrintDlgWFH*>(
|
||||
FunctionHook::GetHooks()->ElementAt(ID_PrintDlgW));
|
||||
MOZ_ASSERT(functionHook);
|
||||
BOOL ret = functionHook->OriginalFunction()(aDlg);
|
||||
aDlg->hwndOwner = hwnd;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Hooking CreateFileW for protected-mode magic
|
||||
static WindowsDllInterceptor sKernel32Intercept;
|
||||
typedef HANDLE(WINAPI* CreateFileWPtr)(LPCWSTR aFname, DWORD aAccess,
|
||||
DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate);
|
||||
static WindowsDllInterceptor::FuncHookType<CreateFileWPtr> sCreateFileWStub;
|
||||
typedef HANDLE(WINAPI* CreateFileAPtr)(LPCSTR aFname, DWORD aAccess,
|
||||
DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate);
|
||||
static WindowsDllInterceptor::FuncHookType<CreateFileAPtr> sCreateFileAStub;
|
||||
|
||||
// Windows 8 RTM (kernelbase's version is 6.2.9200.16384) doesn't call
|
||||
// CreateFileW from CreateFileA.
|
||||
// So we hook CreateFileA too to use CreateFileW hook.
|
||||
static HANDLE WINAPI CreateFileAHookFn(LPCSTR aFname, DWORD aAccess,
|
||||
DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate) {
|
||||
while (true) { // goto out
|
||||
// Our hook is for mms.cfg into \Windows\System32\Macromed\Flash
|
||||
// We don't require supporting too long path.
|
||||
WCHAR unicodeName[MAX_PATH];
|
||||
size_t len = strlen(aFname);
|
||||
|
||||
if (len >= MAX_PATH) {
|
||||
break;
|
||||
}
|
||||
|
||||
// We call to CreateFileW for workaround of Windows 8 RTM
|
||||
int newLen = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, aFname, len,
|
||||
unicodeName, MAX_PATH);
|
||||
if (newLen == 0 || newLen >= MAX_PATH) {
|
||||
break;
|
||||
}
|
||||
unicodeName[newLen] = '\0';
|
||||
|
||||
return CreateFileW(unicodeName, aAccess, aShare, aSecurity, aCreation,
|
||||
aFlags, aFTemplate);
|
||||
}
|
||||
|
||||
return sCreateFileAStub(aFname, aAccess, aShare, aSecurity, aCreation, aFlags,
|
||||
aFTemplate);
|
||||
}
|
||||
|
||||
static bool GetLocalLowTempPath(size_t aLen, LPWSTR aPath) {
|
||||
constexpr auto tempname = u"\\Temp"_ns;
|
||||
LPWSTR path;
|
||||
if (SUCCEEDED(
|
||||
SHGetKnownFolderPath(FOLDERID_LocalAppDataLow, 0, nullptr, &path))) {
|
||||
if (wcslen(path) + tempname.Length() < aLen) {
|
||||
wcscpy(aPath, path);
|
||||
wcscat(aPath, tempname.get());
|
||||
CoTaskMemFree(path);
|
||||
return true;
|
||||
}
|
||||
CoTaskMemFree(path);
|
||||
}
|
||||
|
||||
// XP doesn't support SHGetKnownFolderPath and LocalLow
|
||||
if (!GetTempPathW(aLen, aPath)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
HANDLE WINAPI CreateFileWHookFn(LPCWSTR aFname, DWORD aAccess, DWORD aShare,
|
||||
LPSECURITY_ATTRIBUTES aSecurity,
|
||||
DWORD aCreation, DWORD aFlags,
|
||||
HANDLE aFTemplate) {
|
||||
static const WCHAR kConfigFile[] = L"mms.cfg";
|
||||
static const size_t kConfigLength = ArrayLength(kConfigFile) - 1;
|
||||
|
||||
while (true) { // goto out, in sheep's clothing
|
||||
size_t len = wcslen(aFname);
|
||||
if (len < kConfigLength) {
|
||||
break;
|
||||
}
|
||||
if (wcscmp(aFname + len - kConfigLength, kConfigFile) != 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// This is the config file we want to rewrite
|
||||
WCHAR tempPath[MAX_PATH + 1];
|
||||
if (GetLocalLowTempPath(MAX_PATH, tempPath) == 0) {
|
||||
break;
|
||||
}
|
||||
WCHAR tempFile[MAX_PATH + 1];
|
||||
if (GetTempFileNameW(tempPath, L"fx", 0, tempFile) == 0) {
|
||||
break;
|
||||
}
|
||||
HANDLE replacement = sCreateFileWStub(
|
||||
tempFile, GENERIC_READ | GENERIC_WRITE, aShare, aSecurity,
|
||||
TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE,
|
||||
nullptr);
|
||||
if (replacement == INVALID_HANDLE_VALUE) {
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE original = sCreateFileWStub(aFname, aAccess, aShare, aSecurity,
|
||||
aCreation, aFlags, aFTemplate);
|
||||
if (original != INVALID_HANDLE_VALUE) {
|
||||
// copy original to replacement
|
||||
static const size_t kBufferSize = 1024;
|
||||
char buffer[kBufferSize];
|
||||
DWORD bytes;
|
||||
while (ReadFile(original, buffer, kBufferSize, &bytes, NULL)) {
|
||||
if (bytes == 0) {
|
||||
break;
|
||||
}
|
||||
DWORD wbytes;
|
||||
WriteFile(replacement, buffer, bytes, &wbytes, NULL);
|
||||
if (bytes < kBufferSize) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
CloseHandle(original);
|
||||
}
|
||||
static const char kSettingString[] = "\nProtectedMode=0\n";
|
||||
DWORD wbytes;
|
||||
WriteFile(replacement, static_cast<const void*>(kSettingString),
|
||||
sizeof(kSettingString) - 1, &wbytes, NULL);
|
||||
SetFilePointer(replacement, 0, NULL, FILE_BEGIN);
|
||||
return replacement;
|
||||
}
|
||||
return sCreateFileWStub(aFname, aAccess, aShare, aSecurity, aCreation, aFlags,
|
||||
aFTemplate);
|
||||
}
|
||||
|
||||
void FunctionHook::HookProtectedMode() {
|
||||
// Legacy code. Uses the nsWindowsDLLInterceptor directly instead of
|
||||
// using the FunctionHook
|
||||
sKernel32Intercept.Init("kernel32.dll");
|
||||
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Plugin);
|
||||
sCreateFileWStub.Set(sKernel32Intercept, "CreateFileW", &CreateFileWHookFn);
|
||||
sCreateFileAStub.Set(sKernel32Intercept, "CreateFileA", &CreateFileAHookFn);
|
||||
}
|
||||
|
||||
# if defined(MOZ_SANDBOX)
|
||||
|
||||
/* GetFileAttributesW */
|
||||
|
||||
typedef BasicFunctionHook<ID_GetFileAttributesW, decltype(GetFileAttributesW)>
|
||||
GetFileAttributesWFH;
|
||||
|
||||
INTERCEPTOR_DISABLE_CFGUARD DWORD WINAPI
|
||||
GetFileAttributesWHook(LPCWSTR aFilename) {
|
||||
MOZ_ASSERT(ID_GetFileAttributesW < FunctionHook::GetHooks()->Length());
|
||||
GetFileAttributesWFH* functionHook = static_cast<GetFileAttributesWFH*>(
|
||||
FunctionHook::GetHooks()->ElementAt(ID_GetFileAttributesW));
|
||||
if (!functionHook->OriginalFunction()) {
|
||||
NS_ASSERTION(FALSE,
|
||||
"Something is horribly wrong in GetFileAttributesWHook!");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
DWORD ret = functionHook->OriginalFunction()(aFilename);
|
||||
if (ret != INVALID_FILE_ATTRIBUTES) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// If aFilename is a parent of PluginModuleChild::GetFlashRoamingPath then
|
||||
// assume it was blocked by the sandbox and just report it as a plain
|
||||
// directory.
|
||||
size_t len = wcslen(aFilename);
|
||||
std::wstring roamingPath = PluginModuleChild::GetFlashRoamingPath();
|
||||
bool isParent = (len > 0) && (aFilename[len - 1] == L'\\') &&
|
||||
(_wcsnicmp(aFilename, roamingPath.c_str(), len) == 0);
|
||||
if (!isParent) {
|
||||
return ret;
|
||||
}
|
||||
return FILE_ATTRIBUTE_DIRECTORY;
|
||||
}
|
||||
|
||||
# endif // defined(MOZ_SANDBOX)
|
||||
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
#define FUN_HOOK(x) static_cast<FunctionHook*>(x)
|
||||
|
||||
void FunctionHook::AddFunctionHooks(FunctionHookArray& aHooks) {
|
||||
// We transfer ownership of the FunctionHook objects to the array.
|
||||
#if defined(XP_WIN)
|
||||
aHooks[ID_GetWindowInfo] = FUN_HOOK(new GetWindowInfoFH(
|
||||
"user32.dll", "GetWindowInfo", &GetWindowInfo, &GetWindowInfoHook));
|
||||
aHooks[ID_PrintDlgW] = FUN_HOOK(
|
||||
new PrintDlgWFH("comdlg32.dll", "PrintDlgW", &PrintDlgW, PrintDlgWHook));
|
||||
# if defined(MOZ_SANDBOX)
|
||||
aHooks[ID_GetFileAttributesW] = FUN_HOOK(
|
||||
new GetFileAttributesWFH("kernel32.dll", "GetFileAttributesW",
|
||||
&GetFileAttributesW, &GetFileAttributesWHook));
|
||||
# endif // defined(MOZ_SANDBOX)
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
#undef FUN_HOOK
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,206 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 dom_plugins_ipc_functionhook_h
|
||||
#define dom_plugins_ipc_functionhook_h 1
|
||||
|
||||
#include "IpdlTuple.h"
|
||||
#include "base/process.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "nsWindowsDllInterceptor.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <class T>
|
||||
class StaticAutoPtr;
|
||||
|
||||
namespace plugins {
|
||||
|
||||
// "PluginHooks" logging helpers
|
||||
extern mozilla::LazyLogModule sPluginHooksLog;
|
||||
#define HOOK_LOG(lvl, msg) MOZ_LOG(mozilla::plugins::sPluginHooksLog, lvl, msg);
|
||||
inline const char* SuccessMsg(bool aVal) {
|
||||
return aVal ? "succeeded" : "failed";
|
||||
}
|
||||
|
||||
class FunctionHook;
|
||||
class FunctionHookArray;
|
||||
|
||||
class FunctionHook {
|
||||
public:
|
||||
virtual ~FunctionHook() = default;
|
||||
|
||||
virtual FunctionHookId FunctionId() const = 0;
|
||||
|
||||
/**
|
||||
* Register to hook the function represented by this class.
|
||||
* Returns false if we should have hooked but didn't.
|
||||
*/
|
||||
virtual bool Register(int aQuirks) = 0;
|
||||
|
||||
/**
|
||||
* Run the original function with parameters stored in a tuple.
|
||||
* This is only supported on server-side and for auto-brokered methods.
|
||||
*/
|
||||
virtual bool RunOriginalFunction(base::ProcessId aClientId,
|
||||
const IPC::IpdlTuple& aInTuple,
|
||||
IPC::IpdlTuple* aOutTuple) const = 0;
|
||||
|
||||
/**
|
||||
* Hook the Win32 methods needed by the plugin process.
|
||||
*/
|
||||
static void HookFunctions(int aQuirks);
|
||||
|
||||
static FunctionHookArray* GetHooks();
|
||||
|
||||
#if defined(XP_WIN)
|
||||
/**
|
||||
* Special handler for hooking some kernel32.dll methods that we use to
|
||||
* disable Flash protected mode.
|
||||
*/
|
||||
static void HookProtectedMode();
|
||||
|
||||
/**
|
||||
* Get the WindowsDllInterceptor for the given module. Creates a cache of
|
||||
* WindowsDllInterceptors by name.
|
||||
*/
|
||||
static WindowsDllInterceptor* GetDllInterceptorFor(const char* aModuleName);
|
||||
|
||||
/**
|
||||
* Must be called to clear the cache created by calls to GetDllInterceptorFor.
|
||||
*/
|
||||
static void ClearDllInterceptorCache();
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
private:
|
||||
static StaticAutoPtr<FunctionHookArray> sFunctionHooks;
|
||||
static void AddFunctionHooks(FunctionHookArray& aHooks);
|
||||
};
|
||||
|
||||
// The FunctionHookArray deletes its FunctionHook objects when freed.
|
||||
class FunctionHookArray : public nsTArray<FunctionHook*> {
|
||||
public:
|
||||
~FunctionHookArray() {
|
||||
for (uint32_t idx = 0; idx < Length(); ++idx) {
|
||||
FunctionHook* elt = ElementAt(idx);
|
||||
MOZ_ASSERT(elt);
|
||||
delete elt;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Type of function that returns true if a function should be hooked according
|
||||
// to quirks.
|
||||
typedef bool(ShouldHookFunc)(int aQuirks);
|
||||
|
||||
template <FunctionHookId functionId, typename FunctionType>
|
||||
class BasicFunctionHook : public FunctionHook {
|
||||
#if defined(XP_WIN)
|
||||
using FuncHookType = WindowsDllInterceptor::FuncHookType<FunctionType*>;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
public:
|
||||
BasicFunctionHook(const char* aModuleName, const char* aFunctionName,
|
||||
FunctionType* aOldFunction, FunctionType* aNewFunction)
|
||||
: mOldFunction(aOldFunction),
|
||||
mRegistration(UNREGISTERED),
|
||||
mModuleName(aModuleName),
|
||||
mFunctionName(aFunctionName),
|
||||
mNewFunction(aNewFunction) {
|
||||
MOZ_ASSERT(mOldFunction);
|
||||
MOZ_ASSERT(mNewFunction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks the function if we haven't already and if ShouldHook() says to.
|
||||
*/
|
||||
bool Register(int aQuirks) override;
|
||||
|
||||
/**
|
||||
* Can be specialized to perform "extra" operations when running the
|
||||
* function on the server side.
|
||||
*/
|
||||
bool RunOriginalFunction(base::ProcessId aClientId,
|
||||
const IPC::IpdlTuple& aInTuple,
|
||||
IPC::IpdlTuple* aOutTuple) const override {
|
||||
return false;
|
||||
}
|
||||
|
||||
FunctionHookId FunctionId() const override { return functionId; }
|
||||
|
||||
FunctionType* OriginalFunction() const { return mOldFunction; }
|
||||
|
||||
protected:
|
||||
// Once the function is hooked, this field will take the value of a pointer to
|
||||
// a function that performs the old behavior. Before that, it is a pointer to
|
||||
// the original function.
|
||||
Atomic<FunctionType*> mOldFunction;
|
||||
#if defined(XP_WIN)
|
||||
FuncHookType mStub;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
enum RegistrationStatus { UNREGISTERED, FAILED, SUCCEEDED };
|
||||
RegistrationStatus mRegistration;
|
||||
|
||||
// The name of the module containing the function to hook. E.g. "user32.dll".
|
||||
const nsCString mModuleName;
|
||||
// The name of the function in the module.
|
||||
const nsCString mFunctionName;
|
||||
// The function that we should replace functionName with. The signature of
|
||||
// newFunction must match that of functionName.
|
||||
FunctionType* const mNewFunction;
|
||||
static ShouldHookFunc* const mShouldHook;
|
||||
};
|
||||
|
||||
// Default behavior is to hook every registered function.
|
||||
extern bool AlwaysHook(int);
|
||||
template <FunctionHookId functionId, typename FunctionType>
|
||||
ShouldHookFunc* const BasicFunctionHook<functionId, FunctionType>::mShouldHook =
|
||||
AlwaysHook;
|
||||
|
||||
template <FunctionHookId functionId, typename FunctionType>
|
||||
bool BasicFunctionHook<functionId, FunctionType>::Register(int aQuirks) {
|
||||
MOZ_RELEASE_ASSERT(XRE_IsPluginProcess());
|
||||
|
||||
// If we have already attempted to hook this function or if quirks tell us
|
||||
// not to then don't hook.
|
||||
if (mRegistration != UNREGISTERED || !mShouldHook(aQuirks)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isHooked = false;
|
||||
mRegistration = FAILED;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
WindowsDllInterceptor* dllInterceptor =
|
||||
FunctionHook::GetDllInterceptorFor(mModuleName.Data());
|
||||
if (!dllInterceptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isHooked = mStub.Set(*dllInterceptor, mFunctionName.Data(), mNewFunction);
|
||||
#endif
|
||||
|
||||
if (isHooked) {
|
||||
#if defined(XP_WIN)
|
||||
mOldFunction = mStub.GetStub();
|
||||
#endif
|
||||
mRegistration = SUCCEEDED;
|
||||
}
|
||||
|
||||
HOOK_LOG(LogLevel::Debug, ("Registering to intercept function '%s' : '%s'",
|
||||
mFunctionName.Data(), SuccessMsg(isHooked)));
|
||||
|
||||
return isHooked;
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // dom_plugins_ipc_functionhook_h
|
|
@ -1,186 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 dom_plugins_ipc_ipdltuple_h
|
||||
#define dom_plugins_ipc_ipdltuple_h
|
||||
|
||||
#include "ipc/IPCMessageUtilsSpecializations.h"
|
||||
#include "mozilla/plugins/FunctionBrokerIPCUtils.h"
|
||||
#include "mozilla/Variant.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
// The stuff in this "internal" namespace used to be inside the IpdlTuple
|
||||
// class, but that prevented the MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR
|
||||
// that is needed on the IpdlTupleElement struct. Without this, nsTArray can end
|
||||
// up using a move constructor on this struct, which is not memmovable on
|
||||
// Windows.
|
||||
namespace internal {
|
||||
|
||||
struct InvalidType {};
|
||||
|
||||
// Like Variant but with a default constructor.
|
||||
template <typename... Types>
|
||||
struct MaybeVariant {
|
||||
public:
|
||||
MaybeVariant() : mValue(InvalidType()) {}
|
||||
MaybeVariant(MaybeVariant&& o) : mValue(std::move(o.mValue)) {}
|
||||
|
||||
template <typename Param>
|
||||
void Set(const Param& aParam) {
|
||||
mValue = mozilla::AsVariant(aParam);
|
||||
}
|
||||
|
||||
typedef mozilla::Variant<InvalidType, Types...> MaybeVariantType;
|
||||
MaybeVariantType& GetVariant() { return mValue; }
|
||||
const MaybeVariantType& GetVariant() const { return mValue; }
|
||||
|
||||
private:
|
||||
MaybeVariantType mValue;
|
||||
};
|
||||
|
||||
#if defined(XP_WIN)
|
||||
typedef MaybeVariant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, nsCString, nsString, bool,
|
||||
OpenFileNameIPC, OpenFileNameRetIPC, NativeWindowHandle,
|
||||
IPCSchannelCred, IPCInternetBuffers, StringArray,
|
||||
IPCPrintDlg>
|
||||
IpdlTupleElement;
|
||||
#else
|
||||
typedef MaybeVariant<int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
|
||||
int64_t, uint64_t, nsCString, nsString, bool>
|
||||
IpdlTupleElement;
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
} // namespace internal
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
MOZ_DECLARE_RELOCATE_USING_MOVE_CONSTRUCTOR(
|
||||
mozilla::plugins::internal::IpdlTupleElement)
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* IpdlTuple is used by automatic function brokering to pass parameter
|
||||
* lists for brokered functions. It supports a limited set of types
|
||||
* (see IpdlTuple::IpdlTupleElement).
|
||||
*/
|
||||
class IpdlTuple {
|
||||
public:
|
||||
uint32_t NumElements() const { return mTupleElements.Length(); }
|
||||
|
||||
template <typename EltType>
|
||||
EltType* Element(uint32_t index) {
|
||||
if ((index >= mTupleElements.Length()) ||
|
||||
!mTupleElements[index].GetVariant().is<EltType>()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &mTupleElements[index].GetVariant().as<EltType>();
|
||||
}
|
||||
|
||||
template <typename EltType>
|
||||
const EltType* Element(uint32_t index) const {
|
||||
return const_cast<IpdlTuple*>(this)->Element<EltType>(index);
|
||||
}
|
||||
|
||||
template <typename EltType>
|
||||
void AddElement(const EltType& aElt) {
|
||||
IpdlTupleElement* newEntry = mTupleElements.AppendElement();
|
||||
newEntry->Set(aElt);
|
||||
}
|
||||
|
||||
private:
|
||||
typedef mozilla::plugins::internal::InvalidType InvalidType;
|
||||
typedef mozilla::plugins::internal::IpdlTupleElement IpdlTupleElement;
|
||||
|
||||
friend struct IPC::ParamTraits<IpdlTuple>;
|
||||
friend struct IPC::ParamTraits<IpdlTuple::IpdlTupleElement>;
|
||||
friend struct IPC::ParamTraits<IpdlTuple::InvalidType>;
|
||||
|
||||
nsTArray<IpdlTupleElement> mTupleElements;
|
||||
};
|
||||
|
||||
namespace internal {
|
||||
template <>
|
||||
template <>
|
||||
inline void IpdlTupleElement::Set<nsDependentCSubstring>(
|
||||
const nsDependentCSubstring& aParam) {
|
||||
mValue = MaybeVariantType(mozilla::VariantType<nsCString>(), aParam);
|
||||
}
|
||||
} // namespace internal
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
using namespace mozilla::plugins;
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IpdlTuple> {
|
||||
typedef IpdlTuple paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.mTupleElements);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aParam) {
|
||||
return ReadParam(aMsg, aIter, &aParam->mTupleElements);
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
LogParam(aParam.mTupleElements, aLog);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IpdlTuple::IpdlTupleElement> {
|
||||
typedef IpdlTuple::IpdlTupleElement paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
MOZ_RELEASE_ASSERT(!aParam.GetVariant().is<IpdlTuple::InvalidType>());
|
||||
WriteParam(aMsg, aParam.GetVariant());
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aParam) {
|
||||
bool ret = ReadParam(aMsg, aIter, &aParam->GetVariant());
|
||||
MOZ_RELEASE_ASSERT(!aParam->GetVariant().is<IpdlTuple::InvalidType>());
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aParam.GetVariant().match(
|
||||
[aLog](const auto& aParam) { LogParam(aParam, aLog); });
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<IpdlTuple::InvalidType> {
|
||||
typedef IpdlTuple::InvalidType paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
MOZ_ASSERT_UNREACHABLE("Attempt to serialize an invalid tuple element");
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aParam) {
|
||||
MOZ_ASSERT_UNREACHABLE("Attempt to deserialize an invalid tuple element");
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(L"<Invalid Tuple Entry>");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif /* dom_plugins_ipc_ipdltuple_h */
|
|
@ -1,178 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 "MiniShmParent.h"
|
||||
|
||||
#include "base/scoped_handle.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
// static
|
||||
const unsigned int MiniShmParent::kDefaultMiniShmSectionSize = 0x1000;
|
||||
|
||||
MiniShmParent::MiniShmParent()
|
||||
: mSectionSize(0),
|
||||
mParentEvent(nullptr),
|
||||
mParentGuard(nullptr),
|
||||
mChildEvent(nullptr),
|
||||
mChildGuard(nullptr),
|
||||
mRegWait(nullptr),
|
||||
mFileMapping(nullptr),
|
||||
mView(nullptr),
|
||||
mIsConnected(false),
|
||||
mTimeout(INFINITE) {}
|
||||
|
||||
MiniShmParent::~MiniShmParent() { CleanUp(); }
|
||||
|
||||
void MiniShmParent::CleanUp() {
|
||||
if (mRegWait) {
|
||||
::UnregisterWaitEx(mRegWait, INVALID_HANDLE_VALUE);
|
||||
mRegWait = nullptr;
|
||||
}
|
||||
if (mParentEvent) {
|
||||
::CloseHandle(mParentEvent);
|
||||
mParentEvent = nullptr;
|
||||
}
|
||||
if (mParentGuard) {
|
||||
::CloseHandle(mParentGuard);
|
||||
mParentGuard = nullptr;
|
||||
}
|
||||
if (mChildEvent) {
|
||||
::CloseHandle(mChildEvent);
|
||||
mChildEvent = nullptr;
|
||||
}
|
||||
if (mChildGuard) {
|
||||
::CloseHandle(mChildGuard);
|
||||
mChildGuard = nullptr;
|
||||
}
|
||||
if (mView) {
|
||||
::UnmapViewOfFile(mView);
|
||||
mView = nullptr;
|
||||
}
|
||||
if (mFileMapping) {
|
||||
::CloseHandle(mFileMapping);
|
||||
mFileMapping = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult MiniShmParent::Init(MiniShmObserver* aObserver, const DWORD aTimeout,
|
||||
const unsigned int aSectionSize) {
|
||||
if (!aObserver || !aSectionSize || (aSectionSize % 0x1000) || !aTimeout) {
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
if (mFileMapping) {
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
SECURITY_ATTRIBUTES securityAttributes = {sizeof(securityAttributes), nullptr,
|
||||
TRUE};
|
||||
ScopedHandle parentEvent(
|
||||
::CreateEvent(&securityAttributes, FALSE, FALSE, nullptr));
|
||||
if (!parentEvent.IsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ScopedHandle parentGuard(
|
||||
::CreateEvent(&securityAttributes, FALSE, TRUE, nullptr));
|
||||
if (!parentGuard.IsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ScopedHandle childEvent(
|
||||
::CreateEvent(&securityAttributes, FALSE, FALSE, nullptr));
|
||||
if (!childEvent.IsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ScopedHandle childGuard(
|
||||
::CreateEvent(&securityAttributes, FALSE, TRUE, nullptr));
|
||||
if (!childGuard.IsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ScopedHandle mapping(::CreateFileMapping(INVALID_HANDLE_VALUE,
|
||||
&securityAttributes, PAGE_READWRITE,
|
||||
0, aSectionSize, nullptr));
|
||||
if (!mapping.IsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
ScopedMappedFileView view(::MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0));
|
||||
if (!view.IsValid()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsresult rv = SetView(view, aSectionSize, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = SetGuard(childGuard, aTimeout);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
MiniShmInit* initStruct = nullptr;
|
||||
rv = GetWritePtrInternal(initStruct);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
initStruct->mParentEvent = parentEvent;
|
||||
initStruct->mParentGuard = parentGuard;
|
||||
initStruct->mChildEvent = childEvent;
|
||||
initStruct->mChildGuard = childGuard;
|
||||
|
||||
if (!::RegisterWaitForSingleObject(&mRegWait, parentEvent, &SOnEvent, this,
|
||||
INFINITE, WT_EXECUTEDEFAULT)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mParentEvent = parentEvent.Take();
|
||||
mParentGuard = parentGuard.Take();
|
||||
mChildEvent = childEvent.Take();
|
||||
mChildGuard = childGuard.Take();
|
||||
mFileMapping = mapping.Take();
|
||||
mView = view.Take();
|
||||
mSectionSize = aSectionSize;
|
||||
SetObserver(aObserver);
|
||||
mTimeout = aTimeout;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MiniShmParent::GetCookie(std::wstring& cookie) {
|
||||
if (!mFileMapping) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
std::wostringstream oss;
|
||||
oss << mFileMapping;
|
||||
if (!oss) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
cookie = oss.str();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult MiniShmParent::Send() {
|
||||
if (!mChildEvent) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
if (!::SetEvent(mChildEvent)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool MiniShmParent::IsConnected() const { return mIsConnected; }
|
||||
|
||||
void MiniShmParent::OnEvent() {
|
||||
if (mIsConnected) {
|
||||
MiniShmBase::OnEvent();
|
||||
} else {
|
||||
FinalizeConnection();
|
||||
}
|
||||
::SetEvent(mParentGuard);
|
||||
}
|
||||
|
||||
void MiniShmParent::FinalizeConnection() {
|
||||
const MiniShmInitComplete* initCompleteStruct = nullptr;
|
||||
nsresult rv = GetReadPtr(initCompleteStruct);
|
||||
mIsConnected = NS_SUCCEEDED(rv) && initCompleteStruct->mSucceeded;
|
||||
if (mIsConnected) {
|
||||
OnConnect();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,87 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_plugins_MiniShmParent_h
|
||||
#define mozilla_plugins_MiniShmParent_h
|
||||
|
||||
#include "MiniShmBase.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* This class provides a lightweight shared memory interface for a parent
|
||||
* process in Win32.
|
||||
* This code assumes that there is a parent-child relationship between
|
||||
* processes, as it creates inheritable handles.
|
||||
* Note that this class is *not* an IPDL actor.
|
||||
*
|
||||
* @see MiniShmChild
|
||||
*/
|
||||
class MiniShmParent : public MiniShmBase {
|
||||
public:
|
||||
MiniShmParent();
|
||||
virtual ~MiniShmParent();
|
||||
|
||||
static const unsigned int kDefaultMiniShmSectionSize;
|
||||
|
||||
/**
|
||||
* Initialize shared memory on the parent side.
|
||||
*
|
||||
* @param aObserver A MiniShmObserver object to receive event notifications.
|
||||
* @param aTimeout Timeout in milliseconds.
|
||||
* @param aSectionSize Desired size of the shared memory section. This is
|
||||
* expected to be a multiple of 0x1000 (4KiB).
|
||||
* @return nsresult error code
|
||||
*/
|
||||
nsresult Init(MiniShmObserver* aObserver, const DWORD aTimeout,
|
||||
const unsigned int aSectionSize = kDefaultMiniShmSectionSize);
|
||||
|
||||
/**
|
||||
* Destroys the shared memory section. Useful to explicitly release
|
||||
* resources if it is known that they won't be needed again.
|
||||
*/
|
||||
void CleanUp();
|
||||
|
||||
/**
|
||||
* Provides a cookie string that should be passed to MiniShmChild
|
||||
* during its initialization.
|
||||
*
|
||||
* @param aCookie A std::wstring variable to receive the cookie.
|
||||
* @return nsresult error code
|
||||
*/
|
||||
nsresult GetCookie(std::wstring& aCookie);
|
||||
|
||||
virtual nsresult Send() override;
|
||||
|
||||
bool IsConnected() const;
|
||||
|
||||
protected:
|
||||
void OnEvent() override;
|
||||
|
||||
private:
|
||||
void FinalizeConnection();
|
||||
|
||||
unsigned int mSectionSize;
|
||||
HANDLE mParentEvent;
|
||||
HANDLE mParentGuard;
|
||||
HANDLE mChildEvent;
|
||||
HANDLE mChildGuard;
|
||||
HANDLE mRegWait;
|
||||
HANDLE mFileMapping;
|
||||
LPVOID mView;
|
||||
bool mIsConnected;
|
||||
DWORD mTimeout;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MiniShmParent);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_MiniShmParent_h
|
|
@ -1,50 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
/* 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/. */
|
||||
|
||||
// This is a NPEventX11.h derived stub for Android
|
||||
// Plugins aren't actually supported yet
|
||||
|
||||
#ifndef mozilla_dom_plugins_NPEventAndroid_h
|
||||
#define mozilla_dom_plugins_NPEventAndroid_h
|
||||
|
||||
#include "npapi.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace plugins {
|
||||
|
||||
struct NPRemoteEvent {
|
||||
NPEvent event;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteEvent> {
|
||||
typedef mozilla::plugins::NPRemoteEvent paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteBytes(&aParam, sizeof(paramType));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
return aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType));
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
// TODO
|
||||
aLog->append(L"(AndroidEvent)");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla_dom_plugins_NPEventAndroid_h
|
|
@ -1,198 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
/* 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 mozilla_dom_plugins_NPEventOSX_h
|
||||
#define mozilla_dom_plugins_NPEventOSX_h 1
|
||||
|
||||
#include "npapi.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace plugins {
|
||||
|
||||
struct NPRemoteEvent {
|
||||
NPCocoaEvent event;
|
||||
double contentsScaleFactor;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteEvent> {
|
||||
typedef mozilla::plugins::NPRemoteEvent paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteInt(aParam.event.type);
|
||||
aMsg->WriteUInt32(aParam.event.version);
|
||||
switch (aParam.event.type) {
|
||||
case NPCocoaEventMouseDown:
|
||||
case NPCocoaEventMouseUp:
|
||||
case NPCocoaEventMouseMoved:
|
||||
case NPCocoaEventMouseEntered:
|
||||
case NPCocoaEventMouseExited:
|
||||
case NPCocoaEventMouseDragged:
|
||||
case NPCocoaEventScrollWheel:
|
||||
aMsg->WriteUInt32(aParam.event.data.mouse.modifierFlags);
|
||||
aMsg->WriteDouble(aParam.event.data.mouse.pluginX);
|
||||
aMsg->WriteDouble(aParam.event.data.mouse.pluginY);
|
||||
aMsg->WriteInt32(aParam.event.data.mouse.buttonNumber);
|
||||
aMsg->WriteInt32(aParam.event.data.mouse.clickCount);
|
||||
aMsg->WriteDouble(aParam.event.data.mouse.deltaX);
|
||||
aMsg->WriteDouble(aParam.event.data.mouse.deltaY);
|
||||
aMsg->WriteDouble(aParam.event.data.mouse.deltaZ);
|
||||
break;
|
||||
case NPCocoaEventKeyDown:
|
||||
case NPCocoaEventKeyUp:
|
||||
case NPCocoaEventFlagsChanged:
|
||||
aMsg->WriteUInt32(aParam.event.data.key.modifierFlags);
|
||||
WriteParam(aMsg, aParam.event.data.key.characters);
|
||||
WriteParam(aMsg, aParam.event.data.key.charactersIgnoringModifiers);
|
||||
aMsg->WriteUnsignedChar(aParam.event.data.key.isARepeat);
|
||||
aMsg->WriteUInt16(aParam.event.data.key.keyCode);
|
||||
break;
|
||||
case NPCocoaEventFocusChanged:
|
||||
case NPCocoaEventWindowFocusChanged:
|
||||
aMsg->WriteUnsignedChar(aParam.event.data.focus.hasFocus);
|
||||
break;
|
||||
case NPCocoaEventDrawRect:
|
||||
// We don't write out the context pointer, it would always be
|
||||
// nullptr and is just filled in as such on the read.
|
||||
aMsg->WriteDouble(aParam.event.data.draw.x);
|
||||
aMsg->WriteDouble(aParam.event.data.draw.y);
|
||||
aMsg->WriteDouble(aParam.event.data.draw.width);
|
||||
aMsg->WriteDouble(aParam.event.data.draw.height);
|
||||
break;
|
||||
case NPCocoaEventTextInput:
|
||||
WriteParam(aMsg, aParam.event.data.text.text);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Attempted to serialize unknown event "
|
||||
"type.");
|
||||
return;
|
||||
}
|
||||
aMsg->WriteDouble(aParam.contentsScaleFactor);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
int type = 0;
|
||||
if (!aMsg->ReadInt(aIter, &type)) {
|
||||
return false;
|
||||
}
|
||||
aResult->event.type = static_cast<NPCocoaEventType>(type);
|
||||
|
||||
if (!aMsg->ReadUInt32(aIter, &aResult->event.version)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (aResult->event.type) {
|
||||
case NPCocoaEventMouseDown:
|
||||
case NPCocoaEventMouseUp:
|
||||
case NPCocoaEventMouseMoved:
|
||||
case NPCocoaEventMouseEntered:
|
||||
case NPCocoaEventMouseExited:
|
||||
case NPCocoaEventMouseDragged:
|
||||
case NPCocoaEventScrollWheel:
|
||||
if (!aMsg->ReadUInt32(aIter,
|
||||
&aResult->event.data.mouse.modifierFlags)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.mouse.pluginX)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.mouse.pluginY)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadInt32(aIter, &aResult->event.data.mouse.buttonNumber)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadInt32(aIter, &aResult->event.data.mouse.clickCount)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.mouse.deltaX)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.mouse.deltaY)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.mouse.deltaZ)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NPCocoaEventKeyDown:
|
||||
case NPCocoaEventKeyUp:
|
||||
case NPCocoaEventFlagsChanged:
|
||||
if (!aMsg->ReadUInt32(aIter, &aResult->event.data.key.modifierFlags)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadParam(aMsg, aIter, &aResult->event.data.key.characters)) {
|
||||
return false;
|
||||
}
|
||||
if (!ReadParam(aMsg, aIter,
|
||||
&aResult->event.data.key.charactersIgnoringModifiers)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadUnsignedChar(aIter,
|
||||
&aResult->event.data.key.isARepeat)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadUInt16(aIter, &aResult->event.data.key.keyCode)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NPCocoaEventFocusChanged:
|
||||
case NPCocoaEventWindowFocusChanged:
|
||||
if (!aMsg->ReadUnsignedChar(aIter,
|
||||
&aResult->event.data.focus.hasFocus)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NPCocoaEventDrawRect:
|
||||
aResult->event.data.draw.context = nullptr;
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.draw.x)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.draw.y)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.draw.width)) {
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->event.data.draw.height)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case NPCocoaEventTextInput:
|
||||
if (!ReadParam(aMsg, aIter, &aResult->event.data.text.text)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Attempted to de-serialize unknown "
|
||||
"event type.");
|
||||
return false;
|
||||
}
|
||||
if (!aMsg->ReadDouble(aIter, &aResult->contentsScaleFactor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(L"(NPCocoaEvent)");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // ifndef mozilla_dom_plugins_NPEventOSX_h
|
|
@ -1,90 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
/* 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 mozilla_dom_plugins_NPEventUnix_h
|
||||
#define mozilla_dom_plugins_NPEventUnix_h 1
|
||||
|
||||
#include "npapi.h"
|
||||
|
||||
#ifdef MOZ_X11
|
||||
# include "mozilla/X11Util.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace plugins {
|
||||
|
||||
struct NPRemoteEvent {
|
||||
NPEvent event;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
//
|
||||
// XEvent is defined as a union of all more specific X*Events.
|
||||
// Luckily, as of xorg 1.6.0 / X protocol 11 rev 0, the only pointer
|
||||
// field contained in any of these specific X*Event structs is a
|
||||
// |Display*|. So to simplify serializing these XEvents, we make the
|
||||
//
|
||||
// ********** XXX ASSUMPTION XXX **********
|
||||
//
|
||||
// that the process to which the event is forwarded shares the same
|
||||
// display as the process on which the event originated.
|
||||
//
|
||||
// With this simplification, serialization becomes a simple memcpy to
|
||||
// the output stream. Deserialization starts as just a memcpy from
|
||||
// the input stream, BUT we then have to write the correct |Display*|
|
||||
// into the right field of each X*Event that contains one.
|
||||
//
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteEvent> // synonym for XEvent
|
||||
{
|
||||
typedef mozilla::plugins::NPRemoteEvent paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteBytes(&aParam, sizeof(paramType));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
if (!aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
SetXDisplay(aResult->event);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
// TODO
|
||||
aLog->append(L"(XEvent)");
|
||||
}
|
||||
|
||||
#ifdef MOZ_X11
|
||||
private:
|
||||
static void SetXDisplay(XEvent& ev) {
|
||||
Display* display = mozilla::DefaultXDisplay();
|
||||
if (ev.type >= KeyPress) {
|
||||
ev.xany.display = display;
|
||||
} else {
|
||||
// XXX assuming that this is an error event
|
||||
// (type == 0? not clear from Xlib.h)
|
||||
ev.xerror.display = display;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // ifndef mozilla_dom_plugins_NPEventX11_h
|
|
@ -1,158 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||
/* 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 mozilla_dom_plugins_NPEventWindows_h
|
||||
#define mozilla_dom_plugins_NPEventWindows_h 1
|
||||
|
||||
#ifndef WM_MOUSEHWHEEL
|
||||
# define WM_MOUSEHWHEEL (0x020E)
|
||||
#endif
|
||||
|
||||
#include "npapi.h"
|
||||
namespace mozilla {
|
||||
|
||||
namespace plugins {
|
||||
|
||||
// We use an NPRemoteEvent struct so that we can store the extra data on
|
||||
// the stack so that we don't need to worry about managing the memory.
|
||||
struct NPRemoteEvent {
|
||||
NPEvent event;
|
||||
union {
|
||||
RECT rect;
|
||||
WINDOWPOS windowpos;
|
||||
} lParamData;
|
||||
double contentsScaleFactor;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteEvent> {
|
||||
typedef mozilla::plugins::NPRemoteEvent paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
// Make a non-const copy of aParam so that we can muck with
|
||||
// its insides for tranport
|
||||
paramType paramCopy;
|
||||
|
||||
paramCopy.event = aParam.event;
|
||||
|
||||
// We can't blindly ipc events because they may sometimes contain
|
||||
// pointers to memory in the sending process. For example, the
|
||||
// WM_IME_CONTROL with the IMC_GETCOMPOSITIONFONT message has lParam
|
||||
// set to a pointer to a LOGFONT structure.
|
||||
switch (paramCopy.event.event) {
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
// The lParam parameter of WM_WINDOWPOSCHANGED holds a pointer to
|
||||
// a WINDOWPOS structure that contains information about the
|
||||
// window's new size and position
|
||||
paramCopy.lParamData.windowpos =
|
||||
*(reinterpret_cast<WINDOWPOS*>(paramCopy.event.lParam));
|
||||
break;
|
||||
case WM_PAINT:
|
||||
// The lParam parameter of WM_PAINT holds a pointer to an RECT
|
||||
// structure specifying the bounding box of the update area.
|
||||
paramCopy.lParamData.rect =
|
||||
*(reinterpret_cast<RECT*>(paramCopy.event.lParam));
|
||||
break;
|
||||
|
||||
// the white list of events that we will ipc to the client
|
||||
case WM_CHAR:
|
||||
case WM_SYSCHAR:
|
||||
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYUP:
|
||||
|
||||
case WM_KEYDOWN:
|
||||
case WM_SYSKEYDOWN:
|
||||
|
||||
case WM_DEADCHAR:
|
||||
case WM_SYSDEADCHAR:
|
||||
case WM_CONTEXTMENU:
|
||||
|
||||
case WM_CUT:
|
||||
case WM_COPY:
|
||||
case WM_PASTE:
|
||||
case WM_CLEAR:
|
||||
case WM_UNDO:
|
||||
|
||||
case WM_MOUSELEAVE:
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
case WM_RBUTTONDBLCLK:
|
||||
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_MOUSEHWHEEL:
|
||||
|
||||
case WM_SETFOCUS:
|
||||
case WM_KILLFOCUS:
|
||||
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
case WM_IME_COMPOSITION:
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
case WM_IME_CHAR:
|
||||
case WM_IME_SETCONTEXT:
|
||||
case WM_IME_COMPOSITIONFULL:
|
||||
case WM_IME_KEYDOWN:
|
||||
case WM_IME_KEYUP:
|
||||
case WM_IME_SELECT:
|
||||
case WM_INPUTLANGCHANGEREQUEST:
|
||||
case WM_INPUTLANGCHANGE:
|
||||
break;
|
||||
|
||||
default:
|
||||
// RegisterWindowMessage events should be passed.
|
||||
if (paramCopy.event.event >= 0xC000) break;
|
||||
|
||||
// FIXME/bug 567465: temporarily work around unhandled
|
||||
// events by forwarding a "dummy event". The eventual
|
||||
// fix will be to stop trying to send these events
|
||||
// entirely.
|
||||
paramCopy.event.event = WM_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
aMsg->WriteBytes(¶mCopy, sizeof(paramType));
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
if (!aMsg->ReadBytesInto(aIter, aResult, sizeof(paramType))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aResult->event.event == WM_PAINT) {
|
||||
// restore the lParam to point at the RECT
|
||||
aResult->event.lParam =
|
||||
reinterpret_cast<LPARAM>(&aResult->lParamData.rect);
|
||||
} else if (aResult->event.event == WM_WINDOWPOSCHANGED) {
|
||||
// restore the lParam to point at the WINDOWPOS
|
||||
aResult->event.lParam =
|
||||
reinterpret_cast<LPARAM>(&aResult->lParamData.windowpos);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(L"(WINEvent)");
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // ifndef mozilla_dom_plugins_NPEventWindows_h
|
|
@ -1,42 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 protocol PPluginInstance;
|
||||
|
||||
|
||||
using mozilla::plugins::Buffer from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using mozilla::plugins::IPCByteRanges from "mozilla/plugins/PluginMessageUtils.h";
|
||||
|
||||
using NPError from "npapi.h";
|
||||
using NPReason from "npapi.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* NPBrowserStream represents a NPStream sent from the browser to the plugin.
|
||||
*/
|
||||
|
||||
intr protocol PBrowserStream
|
||||
{
|
||||
manager PPluginInstance;
|
||||
|
||||
child:
|
||||
async Write(int32_t offset, uint32_t newlength,
|
||||
Buffer data);
|
||||
|
||||
/**
|
||||
* NPP_DestroyStream may race with other messages: the child acknowledges
|
||||
* the message with StreamDestroyed before this actor is deleted.
|
||||
*/
|
||||
async NPP_DestroyStream(NPReason reason);
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
async StreamDestroyed();
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,23 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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/. */
|
||||
|
||||
using mozilla::plugins::FunctionHookId from "mozilla/plugins/FunctionBrokerIPCUtils.h";
|
||||
using IPC::IpdlTuple from "mozilla/plugins/IpdlTuple.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* Top-level actor that brokers functions for the client process.
|
||||
*/
|
||||
sync protocol PFunctionBroker
|
||||
{
|
||||
parent:
|
||||
sync BrokerFunction(FunctionHookId aFunctionId, IpdlTuple aFunctionParams)
|
||||
returns (IpdlTuple aFunctionRet);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,34 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: sw=4 ts=8 et :
|
||||
*/
|
||||
/* 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 protocol PPluginInstance;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* This protocol exists to allow us to correctly destroy background
|
||||
* surfaces. The browser owns the surfaces, but shares a "reference"
|
||||
* with the plugin. The browser needs to notify the plugin when the
|
||||
* background is going to be destroyed, but it can't rely on the
|
||||
* plugin to destroy it because the plugin may crash at any time. So
|
||||
* the plugin instance relinquishes destruction of the its old
|
||||
* background to actors of this protocol, which can deal with crashy
|
||||
* corner cases more easily than the instance.
|
||||
*/
|
||||
protocol PPluginBackgroundDestroyer {
|
||||
manager PPluginInstance;
|
||||
|
||||
// The ctor message for this protocol serves double-duty as
|
||||
// notification that that the background is stale.
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,270 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 protocol PPluginBackgroundDestroyer;
|
||||
include protocol PPluginModule;
|
||||
include protocol PPluginScriptableObject;
|
||||
include protocol PBrowserStream;
|
||||
include protocol PStreamNotify;
|
||||
|
||||
include "gfxipc/ShadowLayerUtils.h";
|
||||
include "mozilla/GfxMessageUtils.h";
|
||||
include "mozilla/layers/LayersMessageUtils.h";
|
||||
|
||||
using NPError from "npapi.h";
|
||||
using struct mozilla::plugins::NPRemoteWindow from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using struct mozilla::plugins::NPRemoteEvent from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using NPRect from "npapi.h";
|
||||
using NPNURLVariable from "npapi.h";
|
||||
using NPCoordinateSpace from "npapi.h";
|
||||
using NPNVariable from "npapi.h";
|
||||
using mozilla::plugins::NativeWindowHandle from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using gfxSurfaceType from "gfxTypes.h";
|
||||
using mozilla::gfx::IntSize from "mozilla/gfx/2D.h";
|
||||
using mozilla::gfx::IntRect from "mozilla/gfx/2D.h";
|
||||
using struct mozilla::null_t from "mozilla/ipc/IPCCore.h";
|
||||
using mozilla::WindowsHandle from "mozilla/ipc/IPCTypes.h";
|
||||
using mozilla::plugins::WindowsSharedMemoryHandle from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using mozilla::layers::SurfaceDescriptorX11 from "gfxipc/SurfaceDescriptor.h";
|
||||
using nsIntRect from "nsRect.h";
|
||||
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
|
||||
using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
|
||||
using struct mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
|
||||
using class mozilla::NativeEventData from "ipc/nsGUIEventIPC.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
struct IOSurfaceDescriptor {
|
||||
uint32_t surfaceId;
|
||||
double contentsScaleFactor;
|
||||
};
|
||||
|
||||
union SurfaceDescriptor {
|
||||
Shmem;
|
||||
SurfaceDescriptorX11;
|
||||
IOSurfaceDescriptor; // used on OSX 10.5+
|
||||
// Descriptor can be null here in case
|
||||
// 1) of first Show call (prevSurface is null)
|
||||
// 2) when child is going to destroy
|
||||
// and it just want to grab prevSurface
|
||||
// back without giving new surface
|
||||
null_t;
|
||||
};
|
||||
|
||||
intr protocol PPluginInstance
|
||||
{
|
||||
manager PPluginModule;
|
||||
|
||||
manages PPluginBackgroundDestroyer;
|
||||
manages PPluginScriptableObject;
|
||||
manages PBrowserStream;
|
||||
manages PStreamNotify;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
// This is only used on Windows and, for windowed plugins, must be called
|
||||
// before the first call to NPP_SetWindow.
|
||||
intr CreateChildPluginWindow()
|
||||
returns (NativeWindowHandle childPluginWindow);
|
||||
|
||||
// This is only used on Windows and, for windowless plugins.
|
||||
async CreateChildPopupSurrogate(NativeWindowHandle netscapeWindow);
|
||||
|
||||
intr NPP_SetWindow(NPRemoteWindow window);
|
||||
|
||||
intr NPP_GetValue_NPPVpluginWantsAllNetworkStreams()
|
||||
returns (bool value, NPError result);
|
||||
|
||||
intr NPP_GetValue_NPPVpluginScriptableNPObject()
|
||||
returns (nullable PPluginScriptableObject value, NPError result);
|
||||
|
||||
intr NPP_SetValue_NPNVprivateModeBool(bool value) returns (NPError result);
|
||||
intr NPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId()
|
||||
returns (nsCString plug_id, NPError result);
|
||||
|
||||
intr NPP_SetValue_NPNVCSSZoomFactor(double value) returns (NPError result);
|
||||
|
||||
intr NPP_SetValue_NPNVmuteAudioBool(bool muted) returns (NPError result);
|
||||
|
||||
intr NPP_HandleEvent(NPRemoteEvent event)
|
||||
returns (int16_t handled);
|
||||
// special cases where we need to a shared memory buffer
|
||||
intr NPP_HandleEvent_Shmem(NPRemoteEvent event, Shmem buffer)
|
||||
returns (int16_t handled, Shmem rtnbuffer);
|
||||
// special cases where we need an iosurface
|
||||
intr NPP_HandleEvent_IOSurface(NPRemoteEvent event, uint32_t surfaceid)
|
||||
returns (int16_t handled);
|
||||
// special cases of HandleEvent to make mediating races simpler
|
||||
intr Paint(NPRemoteEvent event)
|
||||
returns (int16_t handled);
|
||||
// this is only used on windows to forward WM_WINDOWPOSCHANGE
|
||||
async WindowPosChanged(NPRemoteEvent event);
|
||||
// used on OS X to tell the child the contents scale factor
|
||||
// of its parent has changed
|
||||
async ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
|
||||
// ********************** Async plugins rendering
|
||||
// see https://wiki.mozilla.org/Gecko:AsyncPluginPainting
|
||||
// **********************
|
||||
|
||||
// Async version of SetWindow call
|
||||
// @param surfaceType - gfxASurface::gfxSurfaceType
|
||||
// plugin child must create offscreen buffer
|
||||
// with type equals to surfaceType
|
||||
async AsyncSetWindow(gfxSurfaceType surfaceType, NPRemoteWindow window);
|
||||
|
||||
// There is now an opaque background behind this instance (or the
|
||||
// background was updated). The changed area is |rect|. The
|
||||
// browser owns the background surface, and it's read-only from
|
||||
// within the plugin process. |background| is either null_t to
|
||||
// refer to the existing background or a fresh descriptor.
|
||||
async UpdateBackground(SurfaceDescriptor background, nsIntRect rect);
|
||||
|
||||
async NPP_DidComposite();
|
||||
|
||||
intr NPP_Destroy()
|
||||
returns (NPError rv);
|
||||
|
||||
parent:
|
||||
intr NPN_GetValue_NPNVWindowNPObject()
|
||||
returns (nullable PPluginScriptableObject value, NPError result);
|
||||
intr NPN_GetValue_NPNVPluginElementNPObject()
|
||||
returns (nullable PPluginScriptableObject value, NPError result);
|
||||
intr NPN_GetValue_NPNVprivateModeBool()
|
||||
returns (bool value, NPError result);
|
||||
intr NPN_GetValue_NPNVnetscapeWindow()
|
||||
returns (NativeWindowHandle value, NPError result);
|
||||
intr NPN_GetValue_NPNVdocumentOrigin()
|
||||
returns (nsCString value, NPError result);
|
||||
intr NPN_GetValue_DrawingModelSupport(NPNVariable model)
|
||||
returns (bool value);
|
||||
intr NPN_GetValue_SupportsAsyncBitmapSurface()
|
||||
returns (bool value);
|
||||
intr NPN_GetValue_SupportsAsyncDXGISurface()
|
||||
returns (bool value);
|
||||
intr NPN_GetValue_PreferredDXGIAdapter()
|
||||
returns (DxgiAdapterDesc desc);
|
||||
|
||||
intr NPN_SetValue_NPPVpluginWindow(bool windowed)
|
||||
returns (NPError result);
|
||||
intr NPN_SetValue_NPPVpluginTransparent(bool transparent)
|
||||
returns (NPError result);
|
||||
intr NPN_SetValue_NPPVpluginUsesDOMForCursor(bool useDOMForCursor)
|
||||
returns (NPError result);
|
||||
intr NPN_SetValue_NPPVpluginDrawingModel(int drawingModel)
|
||||
returns (NPError result);
|
||||
intr NPN_SetValue_NPPVpluginEventModel(int eventModel)
|
||||
returns (NPError result);
|
||||
intr NPN_SetValue_NPPVpluginIsPlayingAudio(bool isAudioPlaying)
|
||||
returns (NPError result);
|
||||
|
||||
intr NPN_GetURL(nsCString url, nsCString target)
|
||||
returns (NPError result);
|
||||
intr NPN_PostURL(nsCString url, nsCString target, nsCString buffer, bool file)
|
||||
returns (NPError result);
|
||||
|
||||
/**
|
||||
* Covers both NPN_GetURLNotify and NPN_PostURLNotify.
|
||||
* @TODO This would be more readable as an overloaded method,
|
||||
* but IPDL doesn't allow that for constructors.
|
||||
*/
|
||||
intr PStreamNotify(nsCString url, nsCString target, bool post,
|
||||
nsCString buffer, bool file)
|
||||
returns (NPError result);
|
||||
|
||||
async NPN_InvalidateRect(NPRect rect);
|
||||
|
||||
// Clear the current plugin image.
|
||||
sync RevokeCurrentDirectSurface();
|
||||
|
||||
// Create a new DXGI shared surface with the given format and size. The
|
||||
// returned handle, on success, can be opened as an ID3D10Texture2D or
|
||||
// ID3D11Texture2D on a corresponding device.
|
||||
sync InitDXGISurface(SurfaceFormat format, IntSize size)
|
||||
returns (WindowsHandle handle, NPError result);
|
||||
|
||||
// Destroy a surface previously allocated with InitDXGISurface().
|
||||
sync FinalizeDXGISurface(WindowsHandle handle);
|
||||
|
||||
// Set the current plugin image to the bitmap in the given shmem buffer. The
|
||||
// format must be B8G8R8A8 or B8G8R8X8.
|
||||
sync ShowDirectBitmap(Shmem buffer,
|
||||
SurfaceFormat format,
|
||||
uint32_t stride,
|
||||
IntSize size,
|
||||
IntRect dirty);
|
||||
|
||||
// Set the current plugin image to the DXGI surface in |handle|.
|
||||
sync ShowDirectDXGISurface(WindowsHandle handle,
|
||||
IntRect dirty);
|
||||
|
||||
// Give |newSurface|, containing this instance's updated pixels, to
|
||||
// the browser for compositing. When this method returns, any surface
|
||||
// previously passed to Show may be destroyed.
|
||||
//
|
||||
// @param rect - actually updated rectangle, comparing to prevSurface content
|
||||
// could be used for partial render of layer to topLevel context
|
||||
// @param newSurface - remotable surface
|
||||
// @param prevSurface - if the previous surface was shared-memory, returns
|
||||
// the shmem for reuse
|
||||
sync Show(NPRect updatedRect, SurfaceDescriptor newSurface)
|
||||
returns (SurfaceDescriptor prevSurface);
|
||||
|
||||
intr NPN_PushPopupsEnabledState(bool aState);
|
||||
|
||||
intr NPN_PopPopupsEnabledState();
|
||||
|
||||
intr NPN_GetValueForURL(NPNURLVariable variable, nsCString url)
|
||||
returns (nsCString value, NPError result);
|
||||
|
||||
intr NPN_SetValueForURL(NPNURLVariable variable, nsCString url,
|
||||
nsCString value)
|
||||
returns (NPError result);
|
||||
|
||||
intr NPN_ConvertPoint(double sourceX, bool ignoreDestX, double sourceY, bool ignoreDestY, NPCoordinateSpace sourceSpace,
|
||||
NPCoordinateSpace destSpace)
|
||||
returns (double destX, double destY, bool result);
|
||||
|
||||
async RedrawPlugin();
|
||||
|
||||
// Sends a native window to be adopted by the native window that would be
|
||||
// returned by NPN_GetValue_NPNVnetscapeWindow. Only used on Windows.
|
||||
async SetNetscapeWindowAsParent(NativeWindowHandle childWindow);
|
||||
|
||||
sync GetCompositionString(uint32_t aType)
|
||||
returns (uint8_t[] aDist, int32_t aLength);
|
||||
async RequestCommitOrCancel(bool aCommitted);
|
||||
|
||||
both:
|
||||
async PPluginScriptableObject();
|
||||
|
||||
child:
|
||||
/* NPP_NewStream */
|
||||
async PBrowserStream(nsCString url,
|
||||
uint32_t length,
|
||||
uint32_t lastmodified,
|
||||
nullable PStreamNotify notifyData,
|
||||
nsCString headers);
|
||||
|
||||
// Implements the legacy (synchronous) version of NPP_NewStream for when
|
||||
// async plugin init is preffed off.
|
||||
intr NPP_NewStream(PBrowserStream actor, nsCString mimeType, bool seekable)
|
||||
returns (NPError rv,
|
||||
uint16_t stype);
|
||||
|
||||
parent:
|
||||
intr PluginFocusChange(bool gotFocus);
|
||||
|
||||
child:
|
||||
intr SetPluginFocus();
|
||||
intr UpdateWindow();
|
||||
|
||||
async PPluginBackgroundDestroyer();
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,148 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 protocol PPluginInstance;
|
||||
include protocol PPluginScriptableObject;
|
||||
include protocol PContent;
|
||||
include protocol PProfiler;
|
||||
include protocol PFunctionBroker;
|
||||
|
||||
using NPError from "npapi.h";
|
||||
using NPNVariable from "npapi.h";
|
||||
using mozilla::dom::NativeThreadId from "mozilla/dom/NativeThreadId.h";
|
||||
using struct nsID from "nsID.h";
|
||||
using struct mozilla::plugins::NPAudioDeviceChangeDetailsIPC from "mozilla/plugins/PluginMessageUtils.h";
|
||||
using struct mozilla::plugins::NPAudioDeviceStateChangedIPC from "mozilla/plugins/PluginMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
struct PluginSettings
|
||||
{
|
||||
// These settings correspond to NPNVariable. They are fetched from
|
||||
// mozilla::plugins::parent::_getvalue.
|
||||
bool javascriptEnabled;
|
||||
bool asdEnabled;
|
||||
bool isOffline;
|
||||
bool supportsXembed;
|
||||
bool supportsWindowless;
|
||||
|
||||
// These settings come from elsewhere.
|
||||
nsCString userAgent;
|
||||
bool nativeCursorsSupported;
|
||||
};
|
||||
|
||||
intr protocol PPluginModule
|
||||
{
|
||||
manages PPluginInstance;
|
||||
|
||||
both:
|
||||
// Window-specific message which instructs the interrupt mechanism to enter
|
||||
// a nested event loop for the current interrupt call.
|
||||
async ProcessNativeEventsInInterruptCall();
|
||||
|
||||
child:
|
||||
async InitProfiler(Endpoint<PProfilerChild> aEndPoint);
|
||||
|
||||
async DisableFlashProtectedMode();
|
||||
|
||||
// Sync query to check if a Flash library indicates it
|
||||
// supports async rendering mode.
|
||||
intr ModuleSupportsAsyncRender()
|
||||
returns (bool result);
|
||||
|
||||
// Forces the child process to update its plugin function table.
|
||||
intr NP_GetEntryPoints()
|
||||
returns (NPError rv);
|
||||
|
||||
intr NP_Initialize(PluginSettings settings)
|
||||
returns (NPError rv);
|
||||
|
||||
async PPluginInstance(nsCString aMimeType,
|
||||
nsCString[] aNames,
|
||||
nsCString[] aValues);
|
||||
|
||||
// Implements the synchronous version of NPP_New for when async plugin init
|
||||
// is preffed off.
|
||||
intr SyncNPP_New(PPluginInstance aActor)
|
||||
returns (NPError rv);
|
||||
|
||||
intr NP_Shutdown()
|
||||
returns (NPError rv);
|
||||
|
||||
intr OptionalFunctionsSupported()
|
||||
returns (bool aURLRedirectNotify, bool aClearSiteData,
|
||||
bool aGetSitesWithData);
|
||||
|
||||
async NPP_ClearSiteData(nsCString site, uint64_t flags, uint64_t maxAge, uint64_t aCallbackId);
|
||||
|
||||
async NPP_GetSitesWithData(uint64_t aCallbackId);
|
||||
|
||||
// Windows specific message to set up an audio session in the plugin process
|
||||
async SetAudioSessionData(nsID aID,
|
||||
nsString aDisplayName,
|
||||
nsString aIconPath);
|
||||
|
||||
async SetParentHangTimeout(uint32_t seconds);
|
||||
|
||||
intr InitCrashReporter()
|
||||
returns (NativeThreadId tid);
|
||||
|
||||
async SettingChanged(PluginSettings settings);
|
||||
|
||||
async NPP_SetValue_NPNVaudioDeviceChangeDetails(NPAudioDeviceChangeDetailsIPC changeDetails);
|
||||
async NPP_SetValue_NPNVaudioDeviceStateChanged(NPAudioDeviceStateChangedIPC deviceState);
|
||||
|
||||
async InitPluginModuleChild(Endpoint<PPluginModuleChild> endpoint);
|
||||
|
||||
async InitPluginFunctionBroker(Endpoint<PFunctionBrokerChild> endpoint);
|
||||
|
||||
parent:
|
||||
/**
|
||||
* This message is only used on X11 platforms.
|
||||
*
|
||||
* Send a dup of the plugin process's X socket to the parent
|
||||
* process. In theory, this scheme keeps the plugin's X resources
|
||||
* around until after both the plugin process shuts down *and* the
|
||||
* parent process closes the dup fd. This is used to prevent the
|
||||
* parent process from crashing on X errors if, e.g., the plugin
|
||||
* crashes *just before* a repaint and the parent process tries to
|
||||
* use the newly-invalid surface.
|
||||
*/
|
||||
async BackUpXResources(FileDescriptor aXSocketFd);
|
||||
|
||||
// Wake up and process a few native events. Periodically called by
|
||||
// Gtk-specific code upon detecting that the plugin process has
|
||||
// entered a nested event loop. If the browser doesn't process
|
||||
// native events, then "livelock" and some other glitches can occur.
|
||||
intr ProcessSomeEvents();
|
||||
|
||||
// OS X Specific calls to manage the plugin's window
|
||||
// when interposing system calls.
|
||||
async PluginShowWindow(uint32_t aWindowId, bool aModal,
|
||||
int32_t aX, int32_t aY,
|
||||
double aWidth, double aHeight);
|
||||
async PluginHideWindow(uint32_t aWindowId);
|
||||
|
||||
sync NPN_SetException(nsCString message);
|
||||
|
||||
async NPN_ReloadPlugins(bool aReloadPages);
|
||||
|
||||
// Notifies the chrome process that a PluginModuleChild linked to a content
|
||||
// process was destroyed. The chrome process may choose to asynchronously shut
|
||||
// down the plugin process in response.
|
||||
async NotifyContentModuleDestroyed();
|
||||
|
||||
// Answers to request about site data
|
||||
async ReturnClearSiteData(NPError aRv, uint64_t aCallbackId);
|
||||
|
||||
async ReturnSitesWithData(nsCString[] aSites, uint64_t aCallbackId);
|
||||
|
||||
intr NPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(bool shouldRegister)
|
||||
returns (NPError result);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,102 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 protocol PPluginInstance;
|
||||
include PluginTypes;
|
||||
|
||||
using struct mozilla::void_t from "mozilla/ipc/IPCCore.h";
|
||||
using struct mozilla::null_t from "mozilla/ipc/IPCCore.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
union Variant {
|
||||
void_t;
|
||||
null_t;
|
||||
bool;
|
||||
int;
|
||||
double;
|
||||
nsCString;
|
||||
nullable PPluginScriptableObject;
|
||||
};
|
||||
|
||||
intr protocol PPluginScriptableObject
|
||||
{
|
||||
manager PPluginInstance;
|
||||
|
||||
both:
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
intr NPN_Evaluate(nsCString aScript)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
child:
|
||||
intr Invalidate();
|
||||
|
||||
both:
|
||||
// NPClass methods
|
||||
intr HasMethod(PluginIdentifier aId)
|
||||
returns (bool aHasMethod);
|
||||
|
||||
intr Invoke(PluginIdentifier aId,
|
||||
Variant[] aArgs)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
intr InvokeDefault(Variant[] aArgs)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
intr HasProperty(PluginIdentifier aId)
|
||||
returns (bool aHasProperty);
|
||||
|
||||
intr SetProperty(PluginIdentifier aId,
|
||||
Variant aValue)
|
||||
returns (bool aSuccess);
|
||||
|
||||
intr RemoveProperty(PluginIdentifier aId)
|
||||
returns (bool aSuccess);
|
||||
|
||||
intr Enumerate()
|
||||
returns (PluginIdentifier[] aProperties,
|
||||
bool aSuccess);
|
||||
|
||||
intr Construct(Variant[] aArgs)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
// Objects are initially unprotected, and the Protect and Unprotect functions
|
||||
// only affect protocol objects that represent NPObjects created in the same
|
||||
// process (rather than protocol objects that are a proxy for an NPObject
|
||||
// created in another process). Protocol objects representing local NPObjects
|
||||
// are protected after an NPObject has been associated with the protocol
|
||||
// object. Sending the protocol object as an argument to the other process
|
||||
// temporarily protects the protocol object again for the duration of the call.
|
||||
async Protect();
|
||||
async Unprotect();
|
||||
|
||||
/**
|
||||
* GetProperty is slightly wonky due to the way we support NPObjects that have
|
||||
* methods and properties with the same name. When child calls parent we
|
||||
* simply return a property. When parent calls child, however, we need to do
|
||||
* several checks at once and return all the results simultaneously.
|
||||
*/
|
||||
parent:
|
||||
intr GetParentProperty(PluginIdentifier aId)
|
||||
returns (Variant aResult,
|
||||
bool aSuccess);
|
||||
|
||||
child:
|
||||
intr GetChildProperty(PluginIdentifier aId)
|
||||
returns (bool aHasProperty,
|
||||
bool aHasMethod,
|
||||
Variant aResult,
|
||||
bool aSuccess);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,39 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* 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 protocol PPluginInstance;
|
||||
|
||||
|
||||
using NPReason from "npapi.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
intr protocol PStreamNotify
|
||||
{
|
||||
manager PPluginInstance;
|
||||
|
||||
parent:
|
||||
|
||||
/**
|
||||
* Represents NPN_URLRedirectResponse
|
||||
*/
|
||||
async RedirectNotifyResponse(bool allow);
|
||||
|
||||
child:
|
||||
/**
|
||||
* Represents NPP_URLRedirectNotify
|
||||
*/
|
||||
async RedirectNotify(nsCString url, int32_t status);
|
||||
|
||||
/**
|
||||
* Represents NPP_URLNotify
|
||||
*/
|
||||
async __delete__(NPReason reason);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,35 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 "PluginBackgroundDestroyer.h"
|
||||
#include "gfxSharedImageSurface.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace plugins;
|
||||
|
||||
PluginBackgroundDestroyerParent::PluginBackgroundDestroyerParent(
|
||||
gfxASurface* aDyingBackground)
|
||||
: mDyingBackground(aDyingBackground) {}
|
||||
|
||||
PluginBackgroundDestroyerParent::~PluginBackgroundDestroyerParent() = default;
|
||||
|
||||
void PluginBackgroundDestroyerParent::ActorDestroy(ActorDestroyReason why) {
|
||||
switch (why) {
|
||||
case Deletion:
|
||||
case AncestorDeletion:
|
||||
if (gfxSharedImageSurface::IsSharedImage(mDyingBackground)) {
|
||||
gfxSharedImageSurface* s =
|
||||
static_cast<gfxSharedImageSurface*>(mDyingBackground.get());
|
||||
DeallocShmem(s->GetShmem());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// We're shutting down or crashed, let automatic cleanup
|
||||
// take care of our shmem, if we have one.
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=8 et :
|
||||
*/
|
||||
/* 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 dom_plugins_PluginBackgroundDestroyer
|
||||
#define dom_plugins_PluginBackgroundDestroyer
|
||||
|
||||
#include "mozilla/plugins/PPluginBackgroundDestroyerChild.h"
|
||||
#include "mozilla/plugins/PPluginBackgroundDestroyerParent.h"
|
||||
|
||||
#include "gfxSharedImageSurface.h"
|
||||
|
||||
class gfxASurface;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
/**
|
||||
* When instances of this class are destroyed, the old background goes
|
||||
* along with them, completing the destruction process (whether or not
|
||||
* the plugin stayed alive long enough to ack).
|
||||
*/
|
||||
class PluginBackgroundDestroyerParent
|
||||
: public PPluginBackgroundDestroyerParent {
|
||||
public:
|
||||
explicit PluginBackgroundDestroyerParent(gfxASurface* aDyingBackground);
|
||||
|
||||
virtual ~PluginBackgroundDestroyerParent();
|
||||
|
||||
private:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
RefPtr<gfxASurface> mDyingBackground;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class exists solely to instruct its instance to release its
|
||||
* current background, a new one may be coming.
|
||||
*/
|
||||
class PluginBackgroundDestroyerChild : public PPluginBackgroundDestroyerChild {
|
||||
public:
|
||||
PluginBackgroundDestroyerChild() = default;
|
||||
virtual ~PluginBackgroundDestroyerChild() = default;
|
||||
|
||||
private:
|
||||
// Implementing this for good hygiene.
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override {}
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // dom_plugins_PluginBackgroundDestroyer
|
|
@ -1,41 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 et :
|
||||
* 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 mozilla_plugins_PluginBridge_h
|
||||
#define mozilla_plugins_PluginBridge_h
|
||||
|
||||
#include "base/process.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace dom {
|
||||
class ContentParent;
|
||||
} // namespace dom
|
||||
|
||||
namespace ipc {
|
||||
template <class PFooSide>
|
||||
class Endpoint;
|
||||
} // namespace ipc
|
||||
|
||||
namespace plugins {
|
||||
|
||||
class PPluginModuleParent;
|
||||
|
||||
bool SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent,
|
||||
nsresult* aResult, uint32_t* aRunID,
|
||||
ipc::Endpoint<PPluginModuleParent>* aEndpoint);
|
||||
|
||||
void TakeFullMinidump(uint32_t aPluginId, base::ProcessId aContentProcessId,
|
||||
const nsAString& aBrowserDumpId, nsString& aDumpId);
|
||||
|
||||
void TerminatePlugin(uint32_t aPluginId, base::ProcessId aContentProcessId,
|
||||
const nsCString& aMonitorDescription,
|
||||
const nsAString& aDumpId);
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_PluginBridge_h
|
|
@ -1,400 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 "PluginHangUI.h"
|
||||
|
||||
#include "PluginHangUIParent.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/plugins/PluginModuleParent.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIProperties.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIWinTaskbar.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "WidgetUtils.h"
|
||||
|
||||
#define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
|
||||
|
||||
using base::ProcessHandle;
|
||||
|
||||
using mozilla::widget::WidgetUtils;
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
namespace {
|
||||
class nsPluginHangUITelemetry : public mozilla::Runnable {
|
||||
public:
|
||||
nsPluginHangUITelemetry(int aResponseCode, int aDontAskCode,
|
||||
uint32_t aResponseTimeMs, uint32_t aTimeoutMs)
|
||||
: Runnable("nsPluginHangUITelemetry"),
|
||||
mResponseCode(aResponseCode),
|
||||
mDontAskCode(aDontAskCode),
|
||||
mResponseTimeMs(aResponseTimeMs),
|
||||
mTimeoutMs(aTimeoutMs) {}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override {
|
||||
mozilla::Telemetry::Accumulate(
|
||||
mozilla::Telemetry::PLUGIN_HANG_UI_USER_RESPONSE, mResponseCode);
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::PLUGIN_HANG_UI_DONT_ASK,
|
||||
mDontAskCode);
|
||||
mozilla::Telemetry::Accumulate(
|
||||
mozilla::Telemetry::PLUGIN_HANG_UI_RESPONSE_TIME, mResponseTimeMs);
|
||||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::PLUGIN_HANG_TIME,
|
||||
mTimeoutMs + mResponseTimeMs);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
int mResponseCode;
|
||||
int mDontAskCode;
|
||||
uint32_t mResponseTimeMs;
|
||||
uint32_t mTimeoutMs;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
PluginHangUIParent::PluginHangUIParent(PluginModuleChromeParent* aModule,
|
||||
const int32_t aHangUITimeoutPref,
|
||||
const int32_t aChildTimeoutPref)
|
||||
: mMutex("mozilla::plugins::PluginHangUIParent::mMutex"),
|
||||
mModule(aModule),
|
||||
mTimeoutPrefMs(static_cast<uint32_t>(aHangUITimeoutPref) * 1000U),
|
||||
mIPCTimeoutMs(static_cast<uint32_t>(aChildTimeoutPref) * 1000U),
|
||||
mMainThreadMessageLoop(MessageLoop::current()),
|
||||
mIsShowing(false),
|
||||
mLastUserResponse(0),
|
||||
mHangUIProcessHandle(nullptr),
|
||||
mMainWindowHandle(nullptr),
|
||||
mRegWait(nullptr),
|
||||
mShowEvent(nullptr),
|
||||
mShowTicks(0),
|
||||
mResponseTicks(0) {}
|
||||
|
||||
PluginHangUIParent::~PluginHangUIParent() {
|
||||
{ // Scope for lock
|
||||
MutexAutoLock lock(mMutex);
|
||||
UnwatchHangUIChildProcess(true);
|
||||
}
|
||||
if (mShowEvent) {
|
||||
::CloseHandle(mShowEvent);
|
||||
}
|
||||
if (mHangUIProcessHandle) {
|
||||
::CloseHandle(mHangUIProcessHandle);
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginHangUIParent::DontShowAgain() const {
|
||||
return (mLastUserResponse & HANGUI_USER_RESPONSE_DONT_SHOW_AGAIN);
|
||||
}
|
||||
|
||||
bool PluginHangUIParent::WasLastHangStopped() const {
|
||||
return (mLastUserResponse & HANGUI_USER_RESPONSE_STOP);
|
||||
}
|
||||
|
||||
unsigned int PluginHangUIParent::LastShowDurationMs() const {
|
||||
// We only return something if there was a user response
|
||||
if (!mLastUserResponse) {
|
||||
return 0;
|
||||
}
|
||||
return static_cast<unsigned int>(mResponseTicks - mShowTicks);
|
||||
}
|
||||
|
||||
bool PluginHangUIParent::Init(const nsString& aPluginName) {
|
||||
if (mHangUIProcessHandle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
rv = mMiniShm.Init(this, ::IsDebuggerPresent() ? INFINITE : mIPCTimeoutMs);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
nsCOMPtr<nsIProperties> directoryService(
|
||||
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
||||
if (!directoryService) {
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIFile> greDir;
|
||||
rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(greDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
nsAutoString path;
|
||||
greDir->GetPath(path);
|
||||
|
||||
FilePath exePath(path.get());
|
||||
exePath = exePath.AppendASCII(MOZ_HANGUI_PROCESS_NAME);
|
||||
CommandLine commandLine(exePath.value());
|
||||
|
||||
nsAutoString localizedStr;
|
||||
rv = nsContentUtils::FormatLocalizedString(
|
||||
localizedStr, nsContentUtils::eDOM_PROPERTIES, "PluginHangUIMessage",
|
||||
aPluginName);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
commandLine.AppendLooseValue(localizedStr.get());
|
||||
|
||||
const char* keys[] = {"PluginHangUITitle", "PluginHangUIWaitButton",
|
||||
"PluginHangUIStopButton", "DontAskAgain"};
|
||||
for (unsigned int i = 0; i < ArrayLength(keys); ++i) {
|
||||
rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||
keys[i], localizedStr);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
commandLine.AppendLooseValue(localizedStr.get());
|
||||
}
|
||||
|
||||
rv = GetHangUIOwnerWindowHandle(mMainWindowHandle);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
nsAutoString hwndStr;
|
||||
hwndStr.AppendPrintf("%p", mMainWindowHandle);
|
||||
commandLine.AppendLooseValue(hwndStr.get());
|
||||
|
||||
ScopedHandle procHandle(
|
||||
::OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId()));
|
||||
if (!procHandle.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
nsAutoString procHandleStr;
|
||||
procHandleStr.AppendPrintf("%p", procHandle.Get());
|
||||
commandLine.AppendLooseValue(procHandleStr.get());
|
||||
|
||||
// On Win7+, pass the application user model to the child, so it can
|
||||
// register with it. This insures windows created by the Hang UI
|
||||
// properly group with the parent app on the Win7 taskbar.
|
||||
nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
|
||||
if (taskbarInfo) {
|
||||
bool isSupported = false;
|
||||
taskbarInfo->GetAvailable(&isSupported);
|
||||
nsAutoString appId;
|
||||
if (isSupported && NS_SUCCEEDED(taskbarInfo->GetDefaultGroupId(appId))) {
|
||||
commandLine.AppendLooseValue(appId.get());
|
||||
} else {
|
||||
commandLine.AppendLooseValue(L"-");
|
||||
}
|
||||
} else {
|
||||
commandLine.AppendLooseValue(L"-");
|
||||
}
|
||||
|
||||
nsAutoString ipcTimeoutStr;
|
||||
ipcTimeoutStr.AppendInt(mIPCTimeoutMs);
|
||||
commandLine.AppendLooseValue(ipcTimeoutStr.get());
|
||||
|
||||
std::wstring ipcCookie;
|
||||
rv = mMiniShm.GetCookie(ipcCookie);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
commandLine.AppendLooseValue(ipcCookie);
|
||||
|
||||
ScopedHandle showEvent(::CreateEventW(nullptr, FALSE, FALSE, nullptr));
|
||||
if (!showEvent.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
mShowEvent = showEvent.Get();
|
||||
|
||||
MutexAutoLock lock(mMutex);
|
||||
STARTUPINFO startupInfo = {sizeof(STARTUPINFO)};
|
||||
PROCESS_INFORMATION processInfo = {nullptr};
|
||||
BOOL isProcessCreated = ::CreateProcess(
|
||||
exePath.value().c_str(),
|
||||
const_cast<wchar_t*>(commandLine.command_line_string().c_str()), nullptr,
|
||||
nullptr, TRUE, DETACHED_PROCESS, nullptr, nullptr, &startupInfo,
|
||||
&processInfo);
|
||||
if (isProcessCreated) {
|
||||
::CloseHandle(processInfo.hThread);
|
||||
mHangUIProcessHandle = processInfo.hProcess;
|
||||
::RegisterWaitForSingleObject(&mRegWait, processInfo.hProcess,
|
||||
&SOnHangUIProcessExit, this, INFINITE,
|
||||
WT_EXECUTEDEFAULT | WT_EXECUTEONLYONCE);
|
||||
::WaitForSingleObject(mShowEvent,
|
||||
::IsDebuggerPresent() ? INFINITE : mIPCTimeoutMs);
|
||||
// Setting this to true even if we time out on mShowEvent. This timeout
|
||||
// typically occurs when the machine is thrashing so badly that
|
||||
// plugin-hang-ui.exe is taking a while to start. If we didn't set
|
||||
// this to true, Firefox would keep spawning additional plugin-hang-ui
|
||||
// processes, which is not what we want.
|
||||
mIsShowing = true;
|
||||
}
|
||||
mShowEvent = nullptr;
|
||||
return !(!isProcessCreated);
|
||||
}
|
||||
|
||||
// static
|
||||
VOID CALLBACK PluginHangUIParent::SOnHangUIProcessExit(PVOID aContext,
|
||||
BOOLEAN aIsTimer) {
|
||||
PluginHangUIParent* object = static_cast<PluginHangUIParent*>(aContext);
|
||||
MutexAutoLock lock(object->mMutex);
|
||||
// If the Hang UI child process died unexpectedly, act as if the UI cancelled
|
||||
if (object->IsShowing()) {
|
||||
object->RecvUserResponse(HANGUI_USER_RESPONSE_CANCEL);
|
||||
// Firefox window was disabled automatically when the Hang UI was shown.
|
||||
// If plugin-hang-ui.exe was unexpectedly terminated, we need to re-enable.
|
||||
::EnableWindow(object->mMainWindowHandle, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
// A precondition for this function is that the caller has locked mMutex
|
||||
bool PluginHangUIParent::UnwatchHangUIChildProcess(bool aWait) {
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
if (mRegWait) {
|
||||
// If aWait is false then we want to pass a nullptr (i.e. default
|
||||
// constructor) completionEvent
|
||||
ScopedHandle completionEvent;
|
||||
if (aWait) {
|
||||
completionEvent.Set(::CreateEventW(nullptr, FALSE, FALSE, nullptr));
|
||||
if (!completionEvent.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// if aWait == false and UnregisterWaitEx fails with ERROR_IO_PENDING,
|
||||
// it is okay to clear mRegWait; Windows is telling us that the wait's
|
||||
// callback is running but will be cleaned up once the callback returns.
|
||||
if (::UnregisterWaitEx(mRegWait, completionEvent) ||
|
||||
(!aWait && ::GetLastError() == ERROR_IO_PENDING)) {
|
||||
mRegWait = nullptr;
|
||||
if (aWait) {
|
||||
// We must temporarily unlock mMutex while waiting for the registered
|
||||
// wait callback to complete, or else we could deadlock.
|
||||
MutexAutoUnlock unlock(mMutex);
|
||||
::WaitForSingleObject(completionEvent, INFINITE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginHangUIParent::Cancel() {
|
||||
MutexAutoLock lock(mMutex);
|
||||
bool result = mIsShowing && SendCancel();
|
||||
if (result) {
|
||||
mIsShowing = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool PluginHangUIParent::SendCancel() {
|
||||
PluginHangUICommand* cmd = nullptr;
|
||||
nsresult rv = mMiniShm.GetWritePtr(cmd);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
cmd->mCode = PluginHangUICommand::HANGUI_CMD_CANCEL;
|
||||
return NS_SUCCEEDED(mMiniShm.Send());
|
||||
}
|
||||
|
||||
// A precondition for this function is that the caller has locked mMutex
|
||||
bool PluginHangUIParent::RecvUserResponse(const unsigned int& aResponse) {
|
||||
mMutex.AssertCurrentThreadOwns();
|
||||
if (!mIsShowing && !(aResponse & HANGUI_USER_RESPONSE_CANCEL)) {
|
||||
// Don't process a user response if a cancellation is already pending
|
||||
return true;
|
||||
}
|
||||
mLastUserResponse = aResponse;
|
||||
mResponseTicks = ::GetTickCount();
|
||||
mIsShowing = false;
|
||||
// responseCode: 1 = Stop, 2 = Continue, 3 = Cancel
|
||||
int responseCode;
|
||||
if (aResponse & HANGUI_USER_RESPONSE_STOP) {
|
||||
// User clicked Stop
|
||||
mModule->TerminateChildProcess(mMainThreadMessageLoop,
|
||||
mozilla::ipc::kInvalidProcessId,
|
||||
"ModalHangUI"_ns, u""_ns);
|
||||
responseCode = 1;
|
||||
} else if (aResponse & HANGUI_USER_RESPONSE_CONTINUE) {
|
||||
mModule->OnHangUIContinue();
|
||||
// User clicked Continue
|
||||
responseCode = 2;
|
||||
} else {
|
||||
// Dialog was cancelled
|
||||
responseCode = 3;
|
||||
}
|
||||
int dontAskCode = (aResponse & HANGUI_USER_RESPONSE_DONT_SHOW_AGAIN) ? 1 : 0;
|
||||
nsCOMPtr<nsIRunnable> workItem = new nsPluginHangUITelemetry(
|
||||
responseCode, dontAskCode, LastShowDurationMs(), mTimeoutPrefMs);
|
||||
NS_DispatchToMainThread(workItem);
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult PluginHangUIParent::GetHangUIOwnerWindowHandle(
|
||||
NativeWindowHandle& windowHandle) {
|
||||
windowHandle = nullptr;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIWindowMediator> winMediator(
|
||||
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<mozIDOMWindowProxy> navWin;
|
||||
rv = winMediator->GetMostRecentWindow(u"navigator:browser",
|
||||
getter_AddRefs(navWin));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (!navWin) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsPIDOMWindowOuter* win = nsPIDOMWindowOuter::From(navWin);
|
||||
nsCOMPtr<nsIWidget> widget = WidgetUtils::DOMWindowToWidget(win);
|
||||
if (!widget) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
windowHandle = reinterpret_cast<NativeWindowHandle>(
|
||||
widget->GetNativeData(NS_NATIVE_WINDOW));
|
||||
if (!windowHandle) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void PluginHangUIParent::OnMiniShmEvent(MiniShmBase* aMiniShmObj) {
|
||||
const PluginHangUIResponse* response = nullptr;
|
||||
nsresult rv = aMiniShmObj->GetReadPtr(response);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't obtain read pointer OnMiniShmEvent");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// The child process has returned a response so we shouldn't worry about
|
||||
// its state anymore.
|
||||
MutexAutoLock lock(mMutex);
|
||||
UnwatchHangUIChildProcess(false);
|
||||
RecvUserResponse(response->mResponseBits);
|
||||
}
|
||||
}
|
||||
|
||||
void PluginHangUIParent::OnMiniShmConnect(MiniShmBase* aMiniShmObj) {
|
||||
PluginHangUICommand* cmd = nullptr;
|
||||
nsresult rv = aMiniShmObj->GetWritePtr(cmd);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"Couldn't obtain write pointer OnMiniShmConnect");
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
cmd->mCode = PluginHangUICommand::HANGUI_CMD_SHOW;
|
||||
if (NS_SUCCEEDED(aMiniShmObj->Send())) {
|
||||
mShowTicks = ::GetTickCount();
|
||||
}
|
||||
::SetEvent(mShowEvent);
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
|
@ -1,142 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_plugins_PluginHangUIParent_h
|
||||
#define mozilla_plugins_PluginHangUIParent_h
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
#include "base/process.h"
|
||||
#include "base/process_util.h"
|
||||
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/plugins/PluginMessageUtils.h"
|
||||
|
||||
#include "MiniShmParent.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class PluginModuleChromeParent;
|
||||
|
||||
/**
|
||||
* This class is responsible for launching and communicating with the
|
||||
* plugin-hang-ui process.
|
||||
*
|
||||
* NOTE: PluginHangUIParent is *not* an IPDL actor! In this case, "Parent"
|
||||
* is describing the fact that firefox is the parent process to the
|
||||
* plugin-hang-ui process, which is the PluginHangUIChild.
|
||||
* PluginHangUIParent and PluginHangUIChild are a matched pair.
|
||||
* @see PluginHangUIChild
|
||||
*/
|
||||
class PluginHangUIParent : public MiniShmObserver {
|
||||
public:
|
||||
PluginHangUIParent(PluginModuleChromeParent* aModule,
|
||||
const int32_t aHangUITimeoutPref,
|
||||
const int32_t aChildTimeoutPref);
|
||||
virtual ~PluginHangUIParent();
|
||||
|
||||
/**
|
||||
* Spawn the plugin-hang-ui.exe child process and terminate the given
|
||||
* plugin container process if the user elects to stop the hung plugin.
|
||||
*
|
||||
* @param aPluginName Human-readable name of the affected plugin.
|
||||
* @return true if the plugin hang ui process was successfully launched,
|
||||
* otherwise false.
|
||||
*/
|
||||
bool Init(const nsString& aPluginName);
|
||||
|
||||
/**
|
||||
* If the Plugin Hang UI is being shown, send a cancel notification to the
|
||||
* Plugin Hang UI child process.
|
||||
*
|
||||
* @return true if the UI was shown and the cancel command was successfully
|
||||
* sent to the child process, otherwise false.
|
||||
*/
|
||||
bool Cancel();
|
||||
|
||||
/**
|
||||
* Returns whether the Plugin Hang UI is currently being displayed.
|
||||
*
|
||||
* @return true if the Plugin Hang UI is showing, otherwise false.
|
||||
*/
|
||||
bool IsShowing() const { return mIsShowing; }
|
||||
|
||||
/**
|
||||
* Returns whether this Plugin Hang UI instance has been shown. Note
|
||||
* that this does not necessarily mean that the UI is showing right now.
|
||||
*
|
||||
* @return true if the Plugin Hang UI has shown, otherwise false.
|
||||
*/
|
||||
bool WasShown() const { return mIsShowing || mLastUserResponse != 0; }
|
||||
|
||||
/**
|
||||
* Returns whether the user checked the "Don't ask me again" checkbox.
|
||||
*
|
||||
* @return true if the user does not want to see the Hang UI again.
|
||||
*/
|
||||
bool DontShowAgain() const;
|
||||
|
||||
/**
|
||||
* Returns whether the user clicked stop during the last time that the
|
||||
* Plugin Hang UI was displayed, if applicable.
|
||||
*
|
||||
* @return true if the UI was shown and the user chose to stop the
|
||||
* plugin, otherwise false
|
||||
*/
|
||||
bool WasLastHangStopped() const;
|
||||
|
||||
/**
|
||||
* @return unsigned int containing the response bits from the last
|
||||
* time the Plugin Hang UI ran.
|
||||
*/
|
||||
unsigned int LastUserResponse() const { return mLastUserResponse; }
|
||||
|
||||
/**
|
||||
* @return unsigned int containing the number of milliseconds that
|
||||
* the Plugin Hang UI was displayed before the user responded.
|
||||
* Returns 0 if the Plugin Hang UI has not been shown or was cancelled.
|
||||
*/
|
||||
unsigned int LastShowDurationMs() const;
|
||||
|
||||
virtual void OnMiniShmEvent(MiniShmBase* aMiniShmObj) override;
|
||||
|
||||
virtual void OnMiniShmConnect(MiniShmBase* aMiniShmObj) override;
|
||||
|
||||
private:
|
||||
nsresult GetHangUIOwnerWindowHandle(NativeWindowHandle& windowHandle);
|
||||
|
||||
bool SendCancel();
|
||||
|
||||
bool RecvUserResponse(const unsigned int& aResponse);
|
||||
|
||||
bool UnwatchHangUIChildProcess(bool aWait);
|
||||
|
||||
static VOID CALLBACK SOnHangUIProcessExit(PVOID aContext, BOOLEAN aIsTimer);
|
||||
|
||||
private:
|
||||
Mutex mMutex;
|
||||
PluginModuleChromeParent* mModule;
|
||||
const uint32_t mTimeoutPrefMs;
|
||||
const uint32_t mIPCTimeoutMs;
|
||||
MessageLoop* mMainThreadMessageLoop;
|
||||
bool mIsShowing;
|
||||
unsigned int mLastUserResponse;
|
||||
base::ProcessHandle mHangUIProcessHandle;
|
||||
NativeWindowHandle mMainWindowHandle;
|
||||
HANDLE mRegWait;
|
||||
HANDLE mShowEvent;
|
||||
DWORD mShowTicks;
|
||||
DWORD mResponseTicks;
|
||||
MiniShmParent mMiniShm;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PluginHangUIParent);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_PluginHangUIParent_h
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,577 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 dom_plugins_PluginInstanceChild_h
|
||||
#define dom_plugins_PluginInstanceChild_h 1
|
||||
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/plugins/PPluginInstanceChild.h"
|
||||
#include "mozilla/plugins/PluginScriptableObjectChild.h"
|
||||
#include "mozilla/plugins/StreamNotifyChild.h"
|
||||
#include "mozilla/ipc/CrossProcessMutex.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
# include "PluginUtilsOSX.h"
|
||||
# include "mozilla/gfx/QuartzSupport.h"
|
||||
# include "base/timer.h"
|
||||
|
||||
#endif
|
||||
|
||||
#include "npfunctions.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "ChildTimer.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "mozilla/PaintTracker.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
class gfxASurface;
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class PBrowserStreamChild;
|
||||
class BrowserStreamChild;
|
||||
class StreamNotifyChild;
|
||||
|
||||
class PluginInstanceChild : public PPluginInstanceChild {
|
||||
friend class BrowserStreamChild;
|
||||
friend class PluginStreamChild;
|
||||
friend class StreamNotifyChild;
|
||||
friend class PluginScriptableObjectChild;
|
||||
friend class PPluginInstanceChild;
|
||||
|
||||
#ifdef OS_WIN
|
||||
friend LRESULT CALLBACK PluginWindowProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK PluginWindowProcInternal(HWND hWnd, UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
mozilla::ipc::IPCResult AnswerCreateChildPluginWindow(
|
||||
NativeWindowHandle* aChildPluginWindow);
|
||||
|
||||
mozilla::ipc::IPCResult RecvCreateChildPopupSurrogate(
|
||||
const NativeWindowHandle& aNetscapeWindow);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPP_SetWindow(const NPRemoteWindow& window);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(
|
||||
bool* wantsAllStreams, NPError* rv);
|
||||
mozilla::ipc::IPCResult AnswerNPP_GetValue_NPPVpluginScriptableNPObject(
|
||||
PPluginScriptableObjectChild** value, NPError* result);
|
||||
mozilla::ipc::IPCResult
|
||||
AnswerNPP_GetValue_NPPVpluginNativeAccessibleAtkPlugId(nsCString* aPlugId,
|
||||
NPError* aResult);
|
||||
mozilla::ipc::IPCResult AnswerNPP_SetValue_NPNVprivateModeBool(
|
||||
const bool& value, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPP_SetValue_NPNVmuteAudioBool(
|
||||
const bool& value, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPP_SetValue_NPNVCSSZoomFactor(
|
||||
const double& value, NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPP_HandleEvent(const NPRemoteEvent& event,
|
||||
int16_t* handled);
|
||||
mozilla::ipc::IPCResult AnswerNPP_HandleEvent_Shmem(
|
||||
const NPRemoteEvent& event, Shmem&& mem, int16_t* handled, Shmem* rtnmem);
|
||||
mozilla::ipc::IPCResult AnswerNPP_HandleEvent_IOSurface(
|
||||
const NPRemoteEvent& event, const uint32_t& surface, int16_t* handled);
|
||||
|
||||
// Async rendering
|
||||
mozilla::ipc::IPCResult RecvAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||
const NPRemoteWindow& aWindow);
|
||||
|
||||
virtual void DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType,
|
||||
const NPRemoteWindow& aWindow, bool aIsAsync);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerPaint(const NPRemoteEvent& event,
|
||||
int16_t* handled) {
|
||||
PaintTracker pt;
|
||||
if (!AnswerNPP_HandleEvent(event, handled)) {
|
||||
return IPC_FAIL_NO_REASON(this);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RecvWindowPosChanged(const NPRemoteEvent& event);
|
||||
|
||||
mozilla::ipc::IPCResult RecvContentsScaleFactorChanged(
|
||||
const double& aContentsScaleFactor);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPP_Destroy(NPError* result);
|
||||
|
||||
PPluginScriptableObjectChild* AllocPPluginScriptableObjectChild();
|
||||
|
||||
bool DeallocPPluginScriptableObjectChild(
|
||||
PPluginScriptableObjectChild* aObject);
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPPluginScriptableObjectConstructor(
|
||||
PPluginScriptableObjectChild* aActor) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPBrowserStreamConstructor(
|
||||
PBrowserStreamChild* aActor, const nsCString& aURL,
|
||||
const uint32_t& aLength, const uint32_t& aLastmodified,
|
||||
PStreamNotifyChild* aNotifyData, const nsCString& aHeaders) override;
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPP_NewStream(PBrowserStreamChild* actor,
|
||||
const nsCString& mimeType,
|
||||
const bool& seekable, NPError* rv,
|
||||
uint16_t* stype);
|
||||
|
||||
PBrowserStreamChild* AllocPBrowserStreamChild(const nsCString& url,
|
||||
const uint32_t& length,
|
||||
const uint32_t& lastmodified,
|
||||
PStreamNotifyChild* notifyData,
|
||||
const nsCString& headers);
|
||||
|
||||
bool DeallocPBrowserStreamChild(PBrowserStreamChild* stream);
|
||||
|
||||
PStreamNotifyChild* AllocPStreamNotifyChild(
|
||||
const nsCString& url, const nsCString& target, const bool& post,
|
||||
const nsCString& buffer, const bool& file, NPError* result);
|
||||
|
||||
bool DeallocPStreamNotifyChild(PStreamNotifyChild* notifyData);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerSetPluginFocus();
|
||||
|
||||
mozilla::ipc::IPCResult AnswerUpdateWindow();
|
||||
|
||||
mozilla::ipc::IPCResult RecvNPP_DidComposite();
|
||||
|
||||
public:
|
||||
PluginInstanceChild(const NPPluginFuncs* aPluginIface,
|
||||
const nsCString& aMimeType,
|
||||
const nsTArray<nsCString>& aNames,
|
||||
const nsTArray<nsCString>& aValues);
|
||||
|
||||
virtual ~PluginInstanceChild();
|
||||
|
||||
NPError DoNPP_New();
|
||||
|
||||
// Common sync+async implementation of NPP_NewStream
|
||||
NPError DoNPP_NewStream(BrowserStreamChild* actor, const nsCString& mimeType,
|
||||
const bool& seekable, uint16_t* stype);
|
||||
|
||||
bool Initialize();
|
||||
|
||||
NPP GetNPP() { return &mData; }
|
||||
|
||||
NPError NPN_GetValue(NPNVariable aVariable, void* aValue);
|
||||
|
||||
NPError NPN_SetValue(NPPVariable aVariable, void* aValue);
|
||||
|
||||
PluginScriptableObjectChild* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
NPError NPN_NewStream(NPMIMEType aMIMEType, const char* aWindow,
|
||||
NPStream** aStream);
|
||||
|
||||
void InvalidateRect(NPRect* aInvalidRect);
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
void Invalidate();
|
||||
#endif // definied(MOZ_WIDGET_COCOA)
|
||||
|
||||
uint32_t ScheduleTimer(uint32_t interval, bool repeat, TimerFunc func);
|
||||
void UnscheduleTimer(uint32_t id);
|
||||
|
||||
int GetQuirks();
|
||||
|
||||
void NPN_URLRedirectResponse(void* notifyData, NPBool allow);
|
||||
|
||||
NPError NPN_InitAsyncSurface(NPSize* size, NPImageFormat format,
|
||||
void* initData, NPAsyncSurface* surface);
|
||||
NPError NPN_FinalizeAsyncSurface(NPAsyncSurface* surface);
|
||||
|
||||
void NPN_SetCurrentAsyncSurface(NPAsyncSurface* surface, NPRect* changed);
|
||||
|
||||
void DoAsyncRedraw();
|
||||
|
||||
#if defined(XP_WIN)
|
||||
NPError DefaultAudioDeviceChanged(NPAudioDeviceChangeDetails& details);
|
||||
NPError AudioDeviceStateChanged(NPAudioDeviceStateChanged& aDeviceState);
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class PluginModuleChild;
|
||||
|
||||
NPError InternalGetNPObjectForValue(NPNVariable aValue, NPObject** aObject);
|
||||
|
||||
bool IsUsingDirectDrawing();
|
||||
|
||||
mozilla::ipc::IPCResult RecvUpdateBackground(
|
||||
const SurfaceDescriptor& aBackground, const nsIntRect& aRect);
|
||||
|
||||
PPluginBackgroundDestroyerChild* AllocPPluginBackgroundDestroyerChild();
|
||||
|
||||
mozilla::ipc::IPCResult RecvPPluginBackgroundDestroyerConstructor(
|
||||
PPluginBackgroundDestroyerChild* aActor) override;
|
||||
|
||||
bool DeallocPPluginBackgroundDestroyerChild(
|
||||
PPluginBackgroundDestroyerChild* aActor);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
static bool RegisterWindowClass();
|
||||
bool CreatePluginWindow();
|
||||
void DestroyPluginWindow();
|
||||
void SizePluginWindow(int width, int height);
|
||||
int16_t WinlessHandleEvent(NPEvent& event);
|
||||
void CreateWinlessPopupSurrogate();
|
||||
void DestroyWinlessPopupSurrogate();
|
||||
void InitPopupMenuHook();
|
||||
void SetupFlashMsgThrottle();
|
||||
void UnhookWinlessFlashThrottle();
|
||||
void HookSetWindowLongPtr();
|
||||
void InitImm32Hook();
|
||||
static inline bool SetWindowLongHookCheck(HWND hWnd, int nIndex,
|
||||
LONG_PTR newLong);
|
||||
void FlashThrottleMessage(HWND, UINT, WPARAM, LPARAM, bool);
|
||||
static LRESULT CALLBACK DummyWindowProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK PluginWindowProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
static BOOL WINAPI TrackPopupHookProc(HMENU hMenu, UINT uFlags, int x, int y,
|
||||
int nReserved, HWND hWnd,
|
||||
CONST RECT* prcRect);
|
||||
static BOOL CALLBACK EnumThreadWindowsCallback(HWND hWnd, LPARAM aParam);
|
||||
static LRESULT CALLBACK WinlessHiddenFlashWndProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
# ifdef _WIN64
|
||||
static LONG_PTR WINAPI SetWindowLongPtrAHook(HWND hWnd, int nIndex,
|
||||
LONG_PTR newLong);
|
||||
static LONG_PTR WINAPI SetWindowLongPtrWHook(HWND hWnd, int nIndex,
|
||||
LONG_PTR newLong);
|
||||
|
||||
# else
|
||||
static LONG WINAPI SetWindowLongAHook(HWND hWnd, int nIndex, LONG newLong);
|
||||
static LONG WINAPI SetWindowLongWHook(HWND hWnd, int nIndex, LONG newLong);
|
||||
# endif
|
||||
|
||||
static HIMC WINAPI ImmGetContextProc(HWND aWND);
|
||||
static LONG WINAPI ImmGetCompositionStringProc(HIMC aIMC, DWORD aIndex,
|
||||
LPVOID aBuf, DWORD aLen);
|
||||
static BOOL WINAPI ImmSetCandidateWindowProc(HIMC hIMC,
|
||||
LPCANDIDATEFORM plCandidate);
|
||||
static BOOL WINAPI ImmNotifyIME(HIMC aIMC, DWORD aAction, DWORD aIndex,
|
||||
DWORD aValue);
|
||||
static BOOL WINAPI ImmAssociateContextExProc(HWND hWnd, HIMC aIMC,
|
||||
DWORD dwFlags);
|
||||
|
||||
class FlashThrottleMsg : public CancelableRunnable {
|
||||
public:
|
||||
FlashThrottleMsg(PluginInstanceChild* aInstance, HWND aWnd, UINT aMsg,
|
||||
WPARAM aWParam, LPARAM aLParam, bool isWindowed)
|
||||
: CancelableRunnable("FlashThrottleMsg"),
|
||||
mInstance(aInstance),
|
||||
mWnd(aWnd),
|
||||
mMsg(aMsg),
|
||||
mWParam(aWParam),
|
||||
mLParam(aLParam),
|
||||
mWindowed(isWindowed) {}
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
nsresult Cancel() override;
|
||||
|
||||
WNDPROC GetProc();
|
||||
HWND GetWnd() { return mWnd; }
|
||||
UINT GetMsg() { return mMsg; }
|
||||
WPARAM GetWParam() { return mWParam; }
|
||||
LPARAM GetLParam() { return mLParam; }
|
||||
|
||||
private:
|
||||
PluginInstanceChild* mInstance;
|
||||
HWND mWnd;
|
||||
UINT mMsg;
|
||||
WPARAM mWParam;
|
||||
LPARAM mLParam;
|
||||
bool mWindowed;
|
||||
};
|
||||
|
||||
#endif // #if defined(OS_WIN)
|
||||
const NPPluginFuncs* mPluginIface;
|
||||
nsCString mMimeType;
|
||||
nsTArray<nsCString> mNames;
|
||||
nsTArray<nsCString> mValues;
|
||||
NPP_t mData;
|
||||
NPWindow mWindow;
|
||||
#if defined(XP_DARWIN) || defined(XP_WIN)
|
||||
double mContentsScaleFactor;
|
||||
#endif
|
||||
double mCSSZoomFactor;
|
||||
int16_t mDrawingModel;
|
||||
|
||||
NPAsyncSurface* mCurrentDirectSurface;
|
||||
|
||||
// The surface hashtables below serve a few purposes. They let us verify
|
||||
// and retain extra information about plugin surfaces, and they let us
|
||||
// free shared memory that the plugin might forget to release.
|
||||
struct DirectBitmap {
|
||||
DirectBitmap(PluginInstanceChild* aOwner, const Shmem& shmem,
|
||||
const gfx::IntSize& size, uint32_t stride,
|
||||
SurfaceFormat format);
|
||||
|
||||
private:
|
||||
~DirectBitmap();
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DirectBitmap);
|
||||
|
||||
PluginInstanceChild* mOwner;
|
||||
Shmem mShmem;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
gfx::IntSize mSize;
|
||||
uint32_t mStride;
|
||||
};
|
||||
nsRefPtrHashtable<nsPtrHashKey<NPAsyncSurface>, DirectBitmap> mDirectBitmaps;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
nsTHashMap<nsPtrHashKey<NPAsyncSurface>, WindowsHandle> mDxgiSurfaces;
|
||||
#endif
|
||||
|
||||
mozilla::Mutex mAsyncInvalidateMutex;
|
||||
CancelableRunnable* mAsyncInvalidateTask;
|
||||
|
||||
// Cached scriptable actors to avoid IPC churn
|
||||
PluginScriptableObjectChild* mCachedWindowActor;
|
||||
PluginScriptableObjectChild* mCachedElementActor;
|
||||
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
NPSetWindowCallbackStruct mWsInfo;
|
||||
#elif defined(OS_WIN)
|
||||
HWND mPluginWindowHWND;
|
||||
WNDPROC mPluginWndProc;
|
||||
HWND mPluginParentHWND;
|
||||
int mNestedEventLevelDepth;
|
||||
HWND mCachedWinlessPluginHWND;
|
||||
HWND mWinlessPopupSurrogateHWND;
|
||||
nsIntPoint mPluginSize;
|
||||
WNDPROC mWinlessThrottleOldWndProc;
|
||||
HWND mWinlessHiddenMsgHWND;
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
nsTArray<FlashThrottleMsg*> mPendingFlashThrottleMsgs;
|
||||
#endif
|
||||
nsTArray<UniquePtr<ChildTimer> > mTimers;
|
||||
|
||||
/**
|
||||
* During destruction we enumerate all remaining scriptable objects and
|
||||
* invalidate/delete them. Enumeration can re-enter, so maintain a
|
||||
* hash separate from PluginModuleChild.mObjectMap.
|
||||
*/
|
||||
UniquePtr<nsTHashtable<DeletingObjectEntry> > mDeletingHash;
|
||||
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
private:
|
||||
# if defined(__i386__)
|
||||
NPEventModel mEventModel;
|
||||
# endif
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
CGContextRef mShContext;
|
||||
RefPtr<nsCARenderer> mCARenderer;
|
||||
void* mCGLayer;
|
||||
|
||||
// Core Animation drawing model requires a refresh timer.
|
||||
uint32_t mCARefreshTimer;
|
||||
|
||||
public:
|
||||
const NPCocoaEvent* getCurrentEvent() { return mCurrentEvent; }
|
||||
|
||||
bool CGDraw(CGContextRef ref, nsIntRect aUpdateRect);
|
||||
|
||||
# if defined(__i386__)
|
||||
NPEventModel EventModel() { return mEventModel; }
|
||||
# endif
|
||||
|
||||
private:
|
||||
const NPCocoaEvent* mCurrentEvent;
|
||||
#endif
|
||||
|
||||
bool CanPaintOnBackground();
|
||||
|
||||
bool IsVisible() {
|
||||
#ifdef XP_MACOSX
|
||||
return mWindow.clipRect.top != mWindow.clipRect.bottom &&
|
||||
mWindow.clipRect.left != mWindow.clipRect.right;
|
||||
#else
|
||||
return mWindow.clipRect.top != 0 || mWindow.clipRect.left != 0 ||
|
||||
mWindow.clipRect.bottom != 0 || mWindow.clipRect.right != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ShowPluginFrame - in general does four things:
|
||||
// 1) Create mCurrentSurface optimized for rendering to parent process
|
||||
// 2) Updated mCurrentSurface to be a complete copy of mBackSurface
|
||||
// 3) Draw the invalidated plugin area into mCurrentSurface
|
||||
// 4) Send it to parent process.
|
||||
bool ShowPluginFrame(void);
|
||||
|
||||
// If we can read back safely from mBackSurface, copy
|
||||
// mSurfaceDifferenceRect from mBackSurface to mFrontSurface.
|
||||
// @return Whether the back surface could be read.
|
||||
bool ReadbackDifferenceRect(const nsIntRect& rect);
|
||||
|
||||
// Post ShowPluginFrame task
|
||||
void AsyncShowPluginFrame(void);
|
||||
|
||||
// In the PaintRect functions, aSurface is the size of the full plugin
|
||||
// window. Each PaintRect function renders into the subrectangle aRect of
|
||||
// aSurface (possibly more if we're working around a Flash bug).
|
||||
|
||||
// Paint plugin content rectangle to surface with bg color filling
|
||||
void PaintRectToSurface(const nsIntRect& aRect, gfxASurface* aSurface,
|
||||
const gfx::DeviceColor& aColor);
|
||||
|
||||
// Render plugin content to surface using
|
||||
// white/black image alpha extraction algorithm
|
||||
void PaintRectWithAlphaExtraction(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface);
|
||||
|
||||
// Call plugin NPAPI function to render plugin content to surface
|
||||
// @param - aSurface - should be compatible with current platform plugin
|
||||
// rendering
|
||||
// @return - FALSE if plugin not painted to surface
|
||||
void PaintRectToPlatformSurface(const nsIntRect& aRect,
|
||||
gfxASurface* aSurface);
|
||||
|
||||
// Update NPWindow platform attributes and call plugin "setwindow"
|
||||
// @param - aForceSetWindow - call setwindow even if platform attributes are
|
||||
// the same
|
||||
void UpdateWindowAttributes(bool aForceSetWindow = false);
|
||||
|
||||
// Create optimized mCurrentSurface for parent process rendering
|
||||
// @return FALSE if optimized surface not created
|
||||
bool CreateOptSurface(void);
|
||||
|
||||
// Create mHelperSurface if mCurrentSurface non compatible with plugins
|
||||
// @return TRUE if helper surface created successfully, or not needed
|
||||
bool MaybeCreatePlatformHelperSurface(void);
|
||||
|
||||
// Make sure that we have surface for rendering
|
||||
bool EnsureCurrentBuffer(void);
|
||||
|
||||
// Helper function for delayed InvalidateRect call
|
||||
// non null mCurrentInvalidateTask will call this function
|
||||
void InvalidateRectDelayed(void);
|
||||
|
||||
// Clear mCurrentSurface/mCurrentSurfaceActor/mHelperSurface
|
||||
void ClearCurrentSurface();
|
||||
|
||||
// Swap mCurrentSurface/mBackSurface and their associated actors
|
||||
void SwapSurfaces();
|
||||
|
||||
// Clear all surfaces in response to NPP_Destroy
|
||||
void ClearAllSurfaces();
|
||||
|
||||
void Destroy();
|
||||
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
// Set as true when SetupLayer called
|
||||
// and go with different path in InvalidateRect function
|
||||
bool mLayersRendering;
|
||||
|
||||
// Current surface available for rendering
|
||||
RefPtr<gfxASurface> mCurrentSurface;
|
||||
|
||||
// Back surface, just keeping reference to
|
||||
// surface which is on ParentProcess side
|
||||
RefPtr<gfxASurface> mBackSurface;
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Current IOSurface available for rendering
|
||||
// We can't use thebes gfxASurface like other platforms.
|
||||
PluginUtilsOSX::nsDoubleBufferCARenderer mDoubleBufferCARenderer;
|
||||
#endif
|
||||
|
||||
// (Not to be confused with mBackSurface). This is a recent copy
|
||||
// of the opaque pixels under our object frame, if
|
||||
// |mIsTransparent|. We ask the plugin render directly onto a
|
||||
// copy of the background pixels if available, and fall back on
|
||||
// alpha recovery otherwise.
|
||||
RefPtr<gfxASurface> mBackground;
|
||||
|
||||
// Accumulated invalidate rect, while back buffer is not accessible,
|
||||
// in plugin coordinates.
|
||||
nsIntRect mAccumulatedInvalidRect;
|
||||
|
||||
// Plugin only call SetTransparent
|
||||
// and does not remember their transparent state
|
||||
// and p->getvalue return always false
|
||||
bool mIsTransparent;
|
||||
|
||||
// Surface type optimized of parent process
|
||||
gfxSurfaceType mSurfaceType;
|
||||
|
||||
// Keep InvalidateRect task pointer to be able Cancel it on Destroy
|
||||
RefPtr<CancelableRunnable> mCurrentInvalidateTask;
|
||||
|
||||
// Keep AsyncSetWindow task pointer to be able to Cancel it on Destroy
|
||||
RefPtr<CancelableRunnable> mCurrentAsyncSetWindowTask;
|
||||
|
||||
// True while plugin-child in plugin call
|
||||
// Use to prevent plugin paint re-enter
|
||||
bool mPendingPluginCall;
|
||||
|
||||
// On some platforms, plugins may not support rendering to a surface with
|
||||
// alpha, or not support rendering to an image surface.
|
||||
// In those cases we need to draw to a temporary platform surface; we cache
|
||||
// that surface here.
|
||||
RefPtr<gfxASurface> mHelperSurface;
|
||||
|
||||
// true when plugin does not support painting to ARGB32
|
||||
// surface this is false if plugin supports
|
||||
// NPPVpluginTransparentAlphaBool (which is not part of
|
||||
// NPAPI yet)
|
||||
bool mDoAlphaExtraction;
|
||||
|
||||
// true when the plugin has painted at least once. We use this to ensure
|
||||
// that we ask a plugin to paint at least once even if it's invisible;
|
||||
// some plugin (instances) rely on this in order to work properly.
|
||||
bool mHasPainted;
|
||||
|
||||
// Cached rectangle rendered to previous surface(mBackSurface)
|
||||
// Used for reading back to current surface and syncing data,
|
||||
// in plugin coordinates.
|
||||
nsIntRect mSurfaceDifferenceRect;
|
||||
|
||||
// Has this instance been destroyed, either by ActorDestroy or NPP_Destroy?
|
||||
bool mDestroyed;
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Store the last IME state by ImmAssociateContextEx. This will reset by
|
||||
// WM_KILLFOCUS;
|
||||
bool mLastEnableIMEState;
|
||||
#endif // #ifdef XP_WIN
|
||||
|
||||
// A counter is incremented by AutoStackHelper to indicate that there is an
|
||||
// active plugin call which should be preventing shutdown.
|
||||
public:
|
||||
class AutoStackHelper {
|
||||
public:
|
||||
explicit AutoStackHelper(PluginInstanceChild* instance)
|
||||
: mInstance(instance) {
|
||||
++mInstance->mStackDepth;
|
||||
}
|
||||
~AutoStackHelper() { --mInstance->mStackDepth; }
|
||||
|
||||
private:
|
||||
PluginInstanceChild* const mInstance;
|
||||
};
|
||||
|
||||
private:
|
||||
int32_t mStackDepth;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ifndef dom_plugins_PluginInstanceChild_h
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,391 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 dom_plugins_PluginInstanceParent_h
|
||||
#define dom_plugins_PluginInstanceParent_h 1
|
||||
|
||||
#include "mozilla/plugins/PPluginInstanceParent.h"
|
||||
#include "mozilla/plugins/PluginScriptableObjectParent.h"
|
||||
#if defined(OS_WIN)
|
||||
# include "mozilla/gfx/SharedDIBWin.h"
|
||||
# include <d3d10_1.h>
|
||||
# include "nsRefPtrHashtable.h"
|
||||
# include "mozilla/layers/LayersSurfaces.h"
|
||||
#elif defined(MOZ_WIDGET_COCOA)
|
||||
# include "mozilla/gfx/QuartzSupport.h"
|
||||
#endif
|
||||
|
||||
#include "npfunctions.h"
|
||||
#include "nsTHashMap.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
|
||||
class gfxASurface;
|
||||
class gfxContext;
|
||||
class nsPluginInstanceOwner;
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
class Image;
|
||||
class ImageContainer;
|
||||
class TextureClientRecycleAllocator;
|
||||
} // namespace layers
|
||||
namespace plugins {
|
||||
|
||||
class PBrowserStreamParent;
|
||||
class PluginModuleParent;
|
||||
class D3D11SurfaceHolder;
|
||||
|
||||
class PluginInstanceParent : public PPluginInstanceParent {
|
||||
friend class PluginModuleParent;
|
||||
friend class BrowserStreamParent;
|
||||
friend class StreamNotifyParent;
|
||||
friend class PPluginInstanceParent;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
public:
|
||||
/**
|
||||
* Helper method for looking up instances based on a supplied id.
|
||||
*/
|
||||
static PluginInstanceParent* LookupPluginInstanceByID(uintptr_t aId);
|
||||
#endif // defined(XP_WIN)
|
||||
|
||||
public:
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
|
||||
PluginInstanceParent(PluginModuleParent* parent, NPP npp,
|
||||
const nsCString& mimeType,
|
||||
const NPNetscapeFuncs* npniface);
|
||||
|
||||
virtual ~PluginInstanceParent();
|
||||
|
||||
bool InitMetadata(const nsACString& aMimeType,
|
||||
const nsACString& aSrcAttribute);
|
||||
NPError Destroy();
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
PPluginScriptableObjectParent* AllocPPluginScriptableObjectParent();
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvPPluginScriptableObjectConstructor(
|
||||
PPluginScriptableObjectParent* aActor) override;
|
||||
|
||||
bool DeallocPPluginScriptableObjectParent(
|
||||
PPluginScriptableObjectParent* aObject);
|
||||
PBrowserStreamParent* AllocPBrowserStreamParent(
|
||||
const nsCString& url, const uint32_t& length,
|
||||
const uint32_t& lastmodified, PStreamNotifyParent* notifyData,
|
||||
const nsCString& headers);
|
||||
bool DeallocPBrowserStreamParent(PBrowserStreamParent* stream);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_NPNVnetscapeWindow(
|
||||
NativeWindowHandle* value, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_NPNVWindowNPObject(
|
||||
PPluginScriptableObjectParent** value, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_NPNVPluginElementNPObject(
|
||||
PPluginScriptableObjectParent** value, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_NPNVprivateModeBool(
|
||||
bool* value, NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_DrawingModelSupport(
|
||||
const NPNVariable& model, bool* value);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_NPNVdocumentOrigin(
|
||||
nsCString* value, NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_SupportsAsyncBitmapSurface(
|
||||
bool* value);
|
||||
|
||||
static bool SupportsPluginDirectDXGISurfaceDrawing();
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_SupportsAsyncDXGISurface(
|
||||
bool* value) {
|
||||
*value = SupportsPluginDirectDXGISurfaceDrawing();
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValue_PreferredDXGIAdapter(
|
||||
DxgiAdapterDesc* desc);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginWindow(
|
||||
const bool& windowed, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginTransparent(
|
||||
const bool& transparent, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginUsesDOMForCursor(
|
||||
const bool& useDOMForCursor, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginDrawingModel(
|
||||
const int& drawingModel, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginEventModel(
|
||||
const int& eventModel, NPError* result);
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginIsPlayingAudio(
|
||||
const bool& isAudioPlaying, NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetURL(const nsCString& url,
|
||||
const nsCString& target,
|
||||
NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_PostURL(const nsCString& url,
|
||||
const nsCString& target,
|
||||
const nsCString& buffer,
|
||||
const bool& file, NPError* result);
|
||||
|
||||
PStreamNotifyParent* AllocPStreamNotifyParent(
|
||||
const nsCString& url, const nsCString& target, const bool& post,
|
||||
const nsCString& buffer, const bool& file, NPError* result);
|
||||
|
||||
virtual mozilla::ipc::IPCResult AnswerPStreamNotifyConstructor(
|
||||
PStreamNotifyParent* actor, const nsCString& url, const nsCString& target,
|
||||
const bool& post, const nsCString& buffer, const bool& file,
|
||||
NPError* result) override;
|
||||
|
||||
bool DeallocPStreamNotifyParent(PStreamNotifyParent* notifyData);
|
||||
|
||||
mozilla::ipc::IPCResult RecvNPN_InvalidateRect(const NPRect& rect);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRevokeCurrentDirectSurface();
|
||||
|
||||
/**
|
||||
* Windows async plugin rendering uses DXGI surface objects, entirely
|
||||
* maintained by the compositor process, to back the rendering of plugins.
|
||||
* The expected mechanics are:
|
||||
* - The PluginInstanceChild (PIC) in the plugin process sends
|
||||
* InitDXGISurface to us, the content process' PluginInstanceParent (PIP).
|
||||
* - The PIP uses the ImageBridge to tell the compositor to create 2
|
||||
* surfaces -- one to be written to by the plugin process and another
|
||||
* to be displayed by the compositor. The PIP returns the plugin
|
||||
* surface to the PIC.
|
||||
* - The PIC repeatedly issues ShowDirectDXGISurface calls to tell the
|
||||
* PIP to blit the plugin surface to the display surface. These
|
||||
* requests are forwarded to the compositor via the ImageBridge.
|
||||
* - The PIC sends FinalizeDXGISurface tio the PIP when it no longer needs
|
||||
* the surface. The PIP then tells the compositor to destroy the
|
||||
* plugin surface. After this, the PIP will tell the compositor to
|
||||
* also destroy the display surface as soon as the ImageBridge says it
|
||||
* no longer needs it.
|
||||
*/
|
||||
mozilla::ipc::IPCResult RecvInitDXGISurface(const gfx::SurfaceFormat& format,
|
||||
const gfx::IntSize& size,
|
||||
WindowsHandle* outHandle,
|
||||
NPError* outError);
|
||||
mozilla::ipc::IPCResult RecvShowDirectDXGISurface(const WindowsHandle& handle,
|
||||
const gfx::IntRect& rect);
|
||||
|
||||
mozilla::ipc::IPCResult RecvFinalizeDXGISurface(const WindowsHandle& handle);
|
||||
|
||||
// --
|
||||
|
||||
mozilla::ipc::IPCResult RecvShowDirectBitmap(Shmem&& buffer,
|
||||
const gfx::SurfaceFormat& format,
|
||||
const uint32_t& stride,
|
||||
const gfx::IntSize& size,
|
||||
const gfx::IntRect& dirty);
|
||||
|
||||
mozilla::ipc::IPCResult RecvShow(const NPRect& updatedRect,
|
||||
const SurfaceDescriptor& newSurface,
|
||||
SurfaceDescriptor* prevSurface);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_PushPopupsEnabledState(const bool& aState);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_PopPopupsEnabledState();
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_GetValueForURL(
|
||||
const NPNURLVariable& variable, const nsCString& url, nsCString* value,
|
||||
NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_SetValueForURL(
|
||||
const NPNURLVariable& variable, const nsCString& url,
|
||||
const nsCString& value, NPError* result);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerNPN_ConvertPoint(
|
||||
const double& sourceX, const bool& ignoreDestX, const double& sourceY,
|
||||
const bool& ignoreDestY, const NPCoordinateSpace& sourceSpace,
|
||||
const NPCoordinateSpace& destSpace, double* destX, double* destY,
|
||||
bool* result);
|
||||
|
||||
mozilla::ipc::IPCResult RecvRedrawPlugin();
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetNetscapeWindowAsParent(
|
||||
const NativeWindowHandle& childWindow);
|
||||
|
||||
NPError NPP_SetWindow(const NPWindow* aWindow);
|
||||
|
||||
NPError NPP_GetValue(NPPVariable variable, void* retval);
|
||||
NPError NPP_SetValue(NPNVariable variable, void* value);
|
||||
|
||||
void NPP_URLRedirectNotify(const char* url, int32_t status, void* notifyData);
|
||||
|
||||
NPError NPP_NewStream(NPMIMEType type, NPStream* stream, NPBool seekable,
|
||||
uint16_t* stype);
|
||||
NPError NPP_DestroyStream(NPStream* stream, NPReason reason);
|
||||
|
||||
void NPP_Print(NPPrint* platformPrint);
|
||||
|
||||
int16_t NPP_HandleEvent(void* event);
|
||||
|
||||
void NPP_URLNotify(const char* url, NPReason reason, void* notifyData);
|
||||
|
||||
PluginModuleParent* Module() { return mParent; }
|
||||
|
||||
const NPNetscapeFuncs* GetNPNIface() { return mNPNIface; }
|
||||
|
||||
bool RegisterNPObjectForActor(NPObject* aObject,
|
||||
PluginScriptableObjectParent* aActor);
|
||||
|
||||
void UnregisterNPObject(NPObject* aObject);
|
||||
|
||||
PluginScriptableObjectParent* GetActorForNPObject(NPObject* aObject);
|
||||
|
||||
NPP GetNPP() { return mNPP; }
|
||||
|
||||
void GetSrcAttribute(nsACString& aOutput) const { aOutput = mSrcAttribute; }
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY mozilla::ipc::IPCResult AnswerPluginFocusChange(
|
||||
const bool& gotFocus);
|
||||
|
||||
nsresult AsyncSetWindow(NPWindow* window);
|
||||
nsresult GetImageContainer(mozilla::layers::ImageContainer** aContainer);
|
||||
nsresult GetImageSize(nsIntSize* aSize);
|
||||
#ifdef XP_MACOSX
|
||||
nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
|
||||
#endif
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
nsresult ContentsScaleFactorChanged(double aContentsScaleFactor);
|
||||
#endif
|
||||
nsresult SetBackgroundUnknown();
|
||||
nsresult BeginUpdateBackground(const nsIntRect& aRect,
|
||||
DrawTarget** aDrawTarget);
|
||||
nsresult EndUpdateBackground(const nsIntRect& aRect);
|
||||
#if defined(XP_WIN)
|
||||
nsresult SetScrollCaptureId(uint64_t aScrollCaptureId);
|
||||
nsresult GetScrollCaptureContainer(
|
||||
mozilla::layers::ImageContainer** aContainer);
|
||||
#endif
|
||||
void DidComposite();
|
||||
|
||||
bool IsUsingDirectDrawing();
|
||||
|
||||
static PluginInstanceParent* Cast(NPP instance);
|
||||
|
||||
// for IME hook
|
||||
mozilla::ipc::IPCResult RecvGetCompositionString(const uint32_t& aIndex,
|
||||
nsTArray<uint8_t>* aBuffer,
|
||||
int32_t* aLength);
|
||||
mozilla::ipc::IPCResult RecvRequestCommitOrCancel(const bool& aCommitted);
|
||||
|
||||
private:
|
||||
// Create an appropriate platform surface for a background of size
|
||||
// |aSize|. Return true if successful.
|
||||
bool CreateBackground(const nsIntSize& aSize);
|
||||
void DestroyBackground();
|
||||
SurfaceDescriptor BackgroundDescriptor() /*const*/;
|
||||
|
||||
typedef mozilla::layers::ImageContainer ImageContainer;
|
||||
ImageContainer* GetImageContainer();
|
||||
|
||||
PPluginBackgroundDestroyerParent* AllocPPluginBackgroundDestroyerParent();
|
||||
|
||||
bool DeallocPPluginBackgroundDestroyerParent(
|
||||
PPluginBackgroundDestroyerParent* aActor);
|
||||
|
||||
bool InternalGetValueForNPObject(NPNVariable aVariable,
|
||||
PPluginScriptableObjectParent** aValue,
|
||||
NPError* aResult);
|
||||
|
||||
nsPluginInstanceOwner* GetOwner();
|
||||
|
||||
void SetCurrentImage(layers::Image* aImage);
|
||||
|
||||
// Update Telemetry with the current drawing model.
|
||||
void RecordDrawingModel();
|
||||
|
||||
private:
|
||||
PluginModuleParent* mParent;
|
||||
NPP mNPP;
|
||||
const NPNetscapeFuncs* mNPNIface;
|
||||
nsCString mSrcAttribute;
|
||||
NPWindowType mWindowType;
|
||||
int16_t mDrawingModel;
|
||||
|
||||
// Since plugins may request different drawing models to find a compatible
|
||||
// one, we only record the drawing model after a SetWindow call and if the
|
||||
// drawing model has changed.
|
||||
int mLastRecordedDrawingModel;
|
||||
|
||||
nsTHashMap<nsPtrHashKey<NPObject>, PluginScriptableObjectParent*>
|
||||
mScriptableObjects;
|
||||
|
||||
// This is used to tell the compositor that it should invalidate the
|
||||
// ImageLayer.
|
||||
uint32_t mFrameID;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// Note: DXGI 1.1 surface handles are global across all processes, and are not
|
||||
// marshaled. As long as we haven't freed a texture its handle should be valid
|
||||
// as a unique cross-process identifier for the texture.
|
||||
nsRefPtrHashtable<nsPtrHashKey<void>, D3D11SurfaceHolder> mD3D11Surfaces;
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
private:
|
||||
// Used in handling parent/child forwarding of events.
|
||||
static LRESULT CALLBACK PluginWindowHookProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
void SubclassPluginWindow(HWND aWnd);
|
||||
void UnsubclassPluginWindow();
|
||||
|
||||
bool MaybeCreateAndParentChildPluginWindow();
|
||||
void MaybeCreateChildPopupSurrogate();
|
||||
|
||||
private:
|
||||
nsIntRect mPluginPort;
|
||||
nsIntRect mSharedSize;
|
||||
HWND mPluginHWND;
|
||||
// This is used for the normal child plugin HWND for windowed plugins and,
|
||||
// if needed, also the child popup surrogate HWND for windowless plugins.
|
||||
HWND mChildPluginHWND;
|
||||
HWND mChildPluginsParentHWND;
|
||||
WNDPROC mPluginWndProc;
|
||||
|
||||
struct AsyncSurfaceInfo {
|
||||
layers::SurfaceDescriptorPlugin mSD;
|
||||
gfx::IntSize mSize;
|
||||
};
|
||||
// Key is plugin surface's texture's handle
|
||||
HashMap<WindowsHandle, AsyncSurfaceInfo> mAsyncSurfaceMap;
|
||||
#endif // defined(OS_WIN)
|
||||
|
||||
#if defined(MOZ_WIDGET_COCOA)
|
||||
private:
|
||||
Shmem mShSurface;
|
||||
uint16_t mShWidth;
|
||||
uint16_t mShHeight;
|
||||
CGColorSpaceRef mShColorSpace;
|
||||
RefPtr<MacIOSurface> mIOSurface;
|
||||
RefPtr<MacIOSurface> mFrontIOSurface;
|
||||
#endif // definied(MOZ_WIDGET_COCOA)
|
||||
|
||||
// ObjectFrame layer wrapper
|
||||
RefPtr<gfxASurface> mFrontSurface;
|
||||
// For windowless+transparent instances, this surface contains a
|
||||
// "pretty recent" copy of the pixels under its <object> frame.
|
||||
// On the plugin side, we use this surface to avoid doing alpha
|
||||
// recovery when possible. This surface is created and owned by
|
||||
// the browser, but a "read-only" reference is sent to the plugin.
|
||||
//
|
||||
// We have explicitly chosen not to provide any guarantees about
|
||||
// the consistency of the pixels in |mBackground|. A plugin may
|
||||
// be able to observe partial updates to the background.
|
||||
RefPtr<gfxASurface> mBackground;
|
||||
|
||||
RefPtr<ImageContainer> mImageContainer;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ifndef dom_plugins_PluginInstanceParent_h
|
|
@ -1,122 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 mozilla_PluginLibrary_h
|
||||
#define mozilla_PluginLibrary_h 1
|
||||
|
||||
#include "prlink.h"
|
||||
#include "npapi.h"
|
||||
#include "npfunctions.h"
|
||||
#include "nscore.h"
|
||||
#include "nsStringFwd.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsError.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "nsSize.h"
|
||||
#include "nsRect.h"
|
||||
|
||||
class nsNPAPIPlugin;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
}
|
||||
namespace layers {
|
||||
class Image;
|
||||
class ImageContainer;
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
class nsIClearSiteDataCallback;
|
||||
|
||||
#define nsIGetSitesWithDataCallback_CID \
|
||||
{ \
|
||||
0xd0028b83, 0xfdf9, 0x4c53, { \
|
||||
0xb7, 0xbb, 0x47, 0x46, 0x0f, 0x6b, 0x83, 0x6c \
|
||||
} \
|
||||
}
|
||||
class nsIGetSitesWithDataCallback : public nsISupports {
|
||||
public:
|
||||
NS_IMETHOD SitesWithData(nsTArray<nsCString>& result) = 0;
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(nsIGetSitesWithDataCallback_CID)
|
||||
};
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsIGetSitesWithDataCallback,
|
||||
nsIGetSitesWithDataCallback_CID)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PluginLibrary {
|
||||
public:
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
|
||||
virtual ~PluginLibrary() = default;
|
||||
|
||||
/**
|
||||
* Inform this library about the nsNPAPIPlugin which owns it. This
|
||||
* object will hold a weak pointer to the plugin.
|
||||
*/
|
||||
virtual void SetPlugin(nsNPAPIPlugin* plugin) = 0;
|
||||
|
||||
virtual bool HasRequiredFunctions() = 0;
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs,
|
||||
NPError* error) = 0;
|
||||
#else
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) = 0;
|
||||
#endif
|
||||
virtual nsresult NP_Shutdown(NPError* error) = 0;
|
||||
virtual nsresult NP_GetMIMEDescription(const char** mimeDesc) = 0;
|
||||
virtual nsresult NP_GetValue(void* future, NPPVariable aVariable,
|
||||
void* aValue, NPError* error) = 0;
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) = 0;
|
||||
#endif
|
||||
virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance, int16_t argc,
|
||||
char* argn[], char* argv[], NPSavedData* saved,
|
||||
NPError* error) = 0;
|
||||
|
||||
virtual nsresult NPP_ClearSiteData(
|
||||
const char* site, uint64_t flags, uint64_t maxAge,
|
||||
nsCOMPtr<nsIClearSiteDataCallback> callback) = 0;
|
||||
virtual nsresult NPP_GetSitesWithData(
|
||||
nsCOMPtr<nsIGetSitesWithDataCallback> callback) = 0;
|
||||
|
||||
virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window) = 0;
|
||||
virtual nsresult GetImageContainer(
|
||||
NPP instance, mozilla::layers::ImageContainer** aContainer) = 0;
|
||||
virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize) = 0;
|
||||
virtual void DidComposite(NPP instance) = 0;
|
||||
virtual bool IsOOP() = 0;
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance,
|
||||
bool* aDrawing) = 0;
|
||||
#endif
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
virtual nsresult ContentsScaleFactorChanged(NPP instance,
|
||||
double aContentsScaleFactor) = 0;
|
||||
#endif
|
||||
#if defined(XP_WIN)
|
||||
virtual nsresult GetScrollCaptureContainer(
|
||||
NPP aInstance, mozilla::layers::ImageContainer** aContainer) = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The next three methods are the third leg in the trip to
|
||||
* PluginInstanceParent. They approximately follow the ReadbackSink
|
||||
* API.
|
||||
*/
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance) = 0;
|
||||
virtual nsresult BeginUpdateBackground(NPP instance, const nsIntRect&,
|
||||
DrawTarget**) = 0;
|
||||
virtual nsresult EndUpdateBackground(NPP instance, const nsIntRect&) = 0;
|
||||
virtual nsresult GetRunID(uint32_t* aRunID) = 0;
|
||||
virtual void SetHasLocalInstance() = 0;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ifndef mozilla_PluginLibrary_h
|
|
@ -1,141 +0,0 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* 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 "PluginMessageUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "PluginInstanceParent.h"
|
||||
#include "PluginInstanceChild.h"
|
||||
#include "PluginScriptableObjectParent.h"
|
||||
#include "PluginScriptableObjectChild.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
using mozilla::ipc::MessageChannel;
|
||||
|
||||
namespace {
|
||||
|
||||
class DeferNPObjectReleaseRunnable : public mozilla::Runnable {
|
||||
public:
|
||||
DeferNPObjectReleaseRunnable(const NPNetscapeFuncs* f, NPObject* o)
|
||||
: Runnable("DeferNPObjectReleaseRunnable"), mFuncs(f), mObject(o) {
|
||||
NS_ASSERTION(o, "no release null objects");
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
private:
|
||||
const NPNetscapeFuncs* mFuncs;
|
||||
NPObject* mObject;
|
||||
};
|
||||
|
||||
NS_IMETHODIMP
|
||||
DeferNPObjectReleaseRunnable::Run() {
|
||||
mFuncs->releaseobject(mObject);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
NPRemoteWindow::NPRemoteWindow()
|
||||
: window(0),
|
||||
x(0),
|
||||
y(0),
|
||||
width(0),
|
||||
height(0),
|
||||
type(NPWindowTypeDrawable)
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
,
|
||||
visualID(0),
|
||||
colormap(0)
|
||||
#endif /* XP_UNIX */
|
||||
#if defined(XP_MACOSX)
|
||||
,
|
||||
contentsScaleFactor(1.0)
|
||||
#endif
|
||||
{
|
||||
clipRect.top = 0;
|
||||
clipRect.left = 0;
|
||||
clipRect.bottom = 0;
|
||||
clipRect.right = 0;
|
||||
}
|
||||
|
||||
ipc::RacyInterruptPolicy MediateRace(const MessageChannel::MessageInfo& parent,
|
||||
const MessageChannel::MessageInfo& child) {
|
||||
switch (parent.type()) {
|
||||
case PPluginInstance::Msg_Paint__ID:
|
||||
case PPluginInstance::Msg_NPP_SetWindow__ID:
|
||||
case PPluginInstance::Msg_NPP_HandleEvent_Shmem__ID:
|
||||
case PPluginInstance::Msg_NPP_HandleEvent_IOSurface__ID:
|
||||
// our code relies on the frame list not changing during paints and
|
||||
// reflows
|
||||
return ipc::RIPParentWins;
|
||||
|
||||
default:
|
||||
return ipc::RIPChildWins;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_SOLARIS)
|
||||
static string ReplaceAll(const string& haystack, const string& needle,
|
||||
const string& with) {
|
||||
string munged = haystack;
|
||||
string::size_type i = 0;
|
||||
|
||||
while (string::npos != (i = munged.find(needle, i))) {
|
||||
munged.replace(i, needle.length(), with);
|
||||
i += with.length();
|
||||
}
|
||||
|
||||
return munged;
|
||||
}
|
||||
#endif
|
||||
|
||||
string MungePluginDsoPath(const string& path) {
|
||||
#if defined(OS_LINUX) || defined(OS_SOLARIS)
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=519601
|
||||
return ReplaceAll(path, "netscape", "netsc@pe");
|
||||
#else
|
||||
return path;
|
||||
#endif
|
||||
}
|
||||
|
||||
string UnmungePluginDsoPath(const string& munged) {
|
||||
#if defined(OS_LINUX) || defined(OS_SOLARIS)
|
||||
return ReplaceAll(munged, "netsc@pe", "netscape");
|
||||
#else
|
||||
return munged;
|
||||
#endif
|
||||
}
|
||||
|
||||
LogModule* GetPluginLog() {
|
||||
static LazyLogModule sLog("IPCPlugins");
|
||||
return sLog;
|
||||
}
|
||||
|
||||
void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o) {
|
||||
if (!o) return;
|
||||
|
||||
if (o->referenceCount > 1) {
|
||||
f->releaseobject(o);
|
||||
return;
|
||||
}
|
||||
|
||||
NS_DispatchToCurrentThread(new DeferNPObjectReleaseRunnable(f, o));
|
||||
}
|
||||
|
||||
void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v) {
|
||||
if (!NPVARIANT_IS_OBJECT(*v)) {
|
||||
f->releasevariantvalue(v);
|
||||
return;
|
||||
}
|
||||
DeferNPObjectLastRelease(f, v->value.objectValue);
|
||||
VOID_TO_NPVARIANT(*v);
|
||||
}
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,562 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 DOM_PLUGINS_PLUGINMESSAGEUTILS_H
|
||||
#define DOM_PLUGINS_PLUGINMESSAGEUTILS_H
|
||||
|
||||
#include "ipc/EnumSerializer.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/shared_memory.h"
|
||||
|
||||
#include "mozilla/ipc/CrossProcessMutex.h"
|
||||
#include "mozilla/ipc/MessageChannel.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "gfxipc/SurfaceDescriptor.h"
|
||||
|
||||
#include "npapi.h"
|
||||
#include "npruntime.h"
|
||||
#include "npfunctions.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
using layers::SurfaceDescriptorX11;
|
||||
|
||||
enum ScriptableObjectType { LocalObject, Proxy };
|
||||
|
||||
mozilla::ipc::RacyInterruptPolicy MediateRace(
|
||||
const mozilla::ipc::MessageChannel::MessageInfo& parent,
|
||||
const mozilla::ipc::MessageChannel::MessageInfo& child);
|
||||
|
||||
std::string MungePluginDsoPath(const std::string& path);
|
||||
std::string UnmungePluginDsoPath(const std::string& munged);
|
||||
|
||||
extern mozilla::LogModule* GetPluginLog();
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define FULLFUNCTION __FUNCSIG__
|
||||
#elif defined(__GNUC__)
|
||||
# define FULLFUNCTION __PRETTY_FUNCTION__
|
||||
#else
|
||||
# define FULLFUNCTION __FUNCTION__
|
||||
#endif
|
||||
|
||||
#define PLUGIN_LOG_DEBUG(args) \
|
||||
MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, args)
|
||||
#define PLUGIN_LOG_DEBUG_FUNCTION \
|
||||
MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, ("%s", FULLFUNCTION))
|
||||
#define PLUGIN_LOG_DEBUG_METHOD \
|
||||
MOZ_LOG(GetPluginLog(), mozilla::LogLevel::Debug, \
|
||||
("%s [%p]", FULLFUNCTION, (void*)this))
|
||||
|
||||
/**
|
||||
* This is NPByteRange without the linked list.
|
||||
*/
|
||||
struct IPCByteRange {
|
||||
int32_t offset;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
typedef nsTArray<IPCByteRange> IPCByteRanges;
|
||||
|
||||
typedef nsCString Buffer;
|
||||
|
||||
struct NPRemoteWindow {
|
||||
NPRemoteWindow();
|
||||
uint64_t window;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
NPRect clipRect;
|
||||
NPWindowType type;
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
VisualID visualID;
|
||||
Colormap colormap;
|
||||
#endif /* XP_UNIX */
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
double contentsScaleFactor;
|
||||
#endif
|
||||
};
|
||||
|
||||
// This struct is like NPAudioDeviceChangeDetails, only it uses a
|
||||
// std::wstring instead of a const wchar_t* for the defaultDevice.
|
||||
// This gives us the necessary memory-ownership semantics without
|
||||
// requiring C++ objects in npapi.h.
|
||||
struct NPAudioDeviceChangeDetailsIPC {
|
||||
int32_t flow;
|
||||
int32_t role;
|
||||
std::wstring defaultDevice;
|
||||
};
|
||||
|
||||
struct NPAudioDeviceStateChangedIPC {
|
||||
std::wstring device;
|
||||
uint32_t state;
|
||||
};
|
||||
|
||||
#ifdef XP_WIN
|
||||
typedef HWND NativeWindowHandle;
|
||||
#elif defined(MOZ_X11)
|
||||
typedef XID NativeWindowHandle;
|
||||
#elif defined(XP_DARWIN) || defined(ANDROID) || defined(MOZ_WAYLAND)
|
||||
typedef intptr_t NativeWindowHandle; // never actually used, will always be 0
|
||||
#else
|
||||
# error Need NativeWindowHandle for this platform
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
typedef base::SharedMemoryHandle WindowsSharedMemoryHandle;
|
||||
typedef HANDLE DXGISharedSurfaceHandle;
|
||||
#else // XP_WIN
|
||||
typedef mozilla::null_t WindowsSharedMemoryHandle;
|
||||
typedef mozilla::null_t DXGISharedSurfaceHandle;
|
||||
#endif
|
||||
|
||||
// XXX maybe not the best place for these. better one?
|
||||
|
||||
#define VARSTR(v_) \
|
||||
case v_: \
|
||||
return #v_
|
||||
inline const char* NPPVariableToString(NPPVariable aVar) {
|
||||
switch (aVar) {
|
||||
VARSTR(NPPVpluginNameString);
|
||||
VARSTR(NPPVpluginDescriptionString);
|
||||
VARSTR(NPPVpluginWindowBool);
|
||||
VARSTR(NPPVpluginTransparentBool);
|
||||
VARSTR(NPPVjavaClass);
|
||||
VARSTR(NPPVpluginWindowSize);
|
||||
VARSTR(NPPVpluginTimerInterval);
|
||||
|
||||
VARSTR(NPPVpluginScriptableInstance);
|
||||
VARSTR(NPPVpluginScriptableIID);
|
||||
|
||||
VARSTR(NPPVjavascriptPushCallerBool);
|
||||
|
||||
VARSTR(NPPVpluginKeepLibraryInMemory);
|
||||
VARSTR(NPPVpluginNeedsXEmbed);
|
||||
|
||||
VARSTR(NPPVpluginScriptableNPObject);
|
||||
|
||||
VARSTR(NPPVformValue);
|
||||
|
||||
VARSTR(NPPVpluginUrlRequestsDisplayedBool);
|
||||
|
||||
VARSTR(NPPVpluginWantsAllNetworkStreams);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
VARSTR(NPPVpluginDrawingModel);
|
||||
VARSTR(NPPVpluginEventModel);
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
VARSTR(NPPVpluginRequiresAudioDeviceChanges);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
inline const char* NPNVariableToString(NPNVariable aVar) {
|
||||
switch (aVar) {
|
||||
VARSTR(NPNVxDisplay);
|
||||
VARSTR(NPNVxtAppContext);
|
||||
VARSTR(NPNVnetscapeWindow);
|
||||
VARSTR(NPNVjavascriptEnabledBool);
|
||||
VARSTR(NPNVasdEnabledBool);
|
||||
VARSTR(NPNVisOfflineBool);
|
||||
|
||||
VARSTR(NPNVserviceManager);
|
||||
VARSTR(NPNVDOMElement);
|
||||
VARSTR(NPNVDOMWindow);
|
||||
VARSTR(NPNVToolkit);
|
||||
VARSTR(NPNVSupportsXEmbedBool);
|
||||
|
||||
VARSTR(NPNVWindowNPObject);
|
||||
|
||||
VARSTR(NPNVPluginElementNPObject);
|
||||
|
||||
VARSTR(NPNVSupportsWindowless);
|
||||
|
||||
VARSTR(NPNVprivateModeBool);
|
||||
VARSTR(NPNVdocumentOrigin);
|
||||
|
||||
#ifdef XP_WIN
|
||||
VARSTR(NPNVaudioDeviceChangeDetails);
|
||||
#endif
|
||||
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
#undef VARSTR
|
||||
|
||||
inline bool IsPluginThread() {
|
||||
MessageLoop* loop = MessageLoop::current();
|
||||
if (!loop) return false;
|
||||
return (loop->type() == MessageLoop::TYPE_UI);
|
||||
}
|
||||
|
||||
inline void AssertPluginThread() {
|
||||
MOZ_RELEASE_ASSERT(IsPluginThread(),
|
||||
"Should be on the plugin's main thread!");
|
||||
}
|
||||
|
||||
#define ENSURE_PLUGIN_THREAD(retval) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (!IsPluginThread()) { \
|
||||
NS_WARNING("Not running on the plugin's main thread!"); \
|
||||
return (retval); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
#define ENSURE_PLUGIN_THREAD_VOID() \
|
||||
PR_BEGIN_MACRO \
|
||||
if (!IsPluginThread()) { \
|
||||
NS_WARNING("Not running on the plugin's main thread!"); \
|
||||
return; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o);
|
||||
void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v);
|
||||
|
||||
inline bool IsDrawingModelDirect(int16_t aModel) {
|
||||
return aModel == NPDrawingModelAsyncBitmapSurface
|
||||
#if defined(XP_WIN)
|
||||
|| aModel == NPDrawingModelAsyncWindowsDXGISurface
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
// in NPAPI, char* == nullptr is sometimes meaningful. the following is
|
||||
// helper code for dealing with nullable nsCString's
|
||||
inline nsCString NullableString(const char* aString) {
|
||||
if (!aString) {
|
||||
return VoidCString();
|
||||
}
|
||||
return nsCString(aString);
|
||||
}
|
||||
|
||||
inline const char* NullableStringGet(const nsCString& str) {
|
||||
if (str.IsVoid()) return nullptr;
|
||||
|
||||
return str.get();
|
||||
}
|
||||
|
||||
struct DeletingObjectEntry : public nsPtrHashKey<NPObject> {
|
||||
explicit DeletingObjectEntry(const NPObject* key)
|
||||
: nsPtrHashKey<NPObject>(key), mDeleted(false) {}
|
||||
|
||||
bool mDeleted;
|
||||
};
|
||||
|
||||
} /* namespace plugins */
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPRect> {
|
||||
typedef NPRect paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.top);
|
||||
WriteParam(aMsg, aParam.left);
|
||||
WriteParam(aMsg, aParam.bottom);
|
||||
WriteParam(aMsg, aParam.right);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint16_t top, left, bottom, right;
|
||||
if (ReadParam(aMsg, aIter, &top) && ReadParam(aMsg, aIter, &left) &&
|
||||
ReadParam(aMsg, aIter, &bottom) && ReadParam(aMsg, aIter, &right)) {
|
||||
aResult->top = top;
|
||||
aResult->left = left;
|
||||
aResult->bottom = bottom;
|
||||
aResult->right = right;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%u, %u, %u, %u]", aParam.top, aParam.left,
|
||||
aParam.bottom, aParam.right));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPWindowType>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
NPWindowType, NPWindowType::NPWindowTypeWindow,
|
||||
NPWindowType::NPWindowTypeDrawable> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPRemoteWindow> {
|
||||
typedef mozilla::plugins::NPRemoteWindow paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
aMsg->WriteUInt64(aParam.window);
|
||||
WriteParam(aMsg, aParam.x);
|
||||
WriteParam(aMsg, aParam.y);
|
||||
WriteParam(aMsg, aParam.width);
|
||||
WriteParam(aMsg, aParam.height);
|
||||
WriteParam(aMsg, aParam.clipRect);
|
||||
WriteParam(aMsg, aParam.type);
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
aMsg->WriteULong(aParam.visualID);
|
||||
aMsg->WriteULong(aParam.colormap);
|
||||
#endif
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
aMsg->WriteDouble(aParam.contentsScaleFactor);
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
uint64_t window;
|
||||
int32_t x, y;
|
||||
uint32_t width, height;
|
||||
NPRect clipRect;
|
||||
NPWindowType type;
|
||||
if (!(aMsg->ReadUInt64(aIter, &window) && ReadParam(aMsg, aIter, &x) &&
|
||||
ReadParam(aMsg, aIter, &y) && ReadParam(aMsg, aIter, &width) &&
|
||||
ReadParam(aMsg, aIter, &height) &&
|
||||
ReadParam(aMsg, aIter, &clipRect) && ReadParam(aMsg, aIter, &type)))
|
||||
return false;
|
||||
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
unsigned long visualID;
|
||||
unsigned long colormap;
|
||||
if (!(aMsg->ReadULong(aIter, &visualID) &&
|
||||
aMsg->ReadULong(aIter, &colormap)))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
double contentsScaleFactor;
|
||||
if (!aMsg->ReadDouble(aIter, &contentsScaleFactor)) return false;
|
||||
#endif
|
||||
|
||||
aResult->window = window;
|
||||
aResult->x = x;
|
||||
aResult->y = y;
|
||||
aResult->width = width;
|
||||
aResult->height = height;
|
||||
aResult->clipRect = clipRect;
|
||||
aResult->type = type;
|
||||
#if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
aResult->visualID = visualID;
|
||||
aResult->colormap = colormap;
|
||||
#endif
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
aResult->contentsScaleFactor = contentsScaleFactor;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%u, %d, %d, %u, %u, %d",
|
||||
(unsigned long)aParam.window, aParam.x, aParam.y,
|
||||
aParam.width, aParam.height, (long)aParam.type));
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
template <>
|
||||
struct ParamTraits<NPNSString*> {
|
||||
// Empty string writes a length of 0 and no buffer.
|
||||
// We don't write a nullptr terminating character in buffers.
|
||||
static void Write(Message* aMsg, NPNSString* aParam) {
|
||||
CFStringRef cfString = (CFStringRef)aParam;
|
||||
|
||||
// Write true if we have a string, false represents nullptr.
|
||||
aMsg->WriteBool(!!cfString);
|
||||
if (!cfString) {
|
||||
return;
|
||||
}
|
||||
|
||||
long length = ::CFStringGetLength(cfString);
|
||||
WriteParam(aMsg, length);
|
||||
if (length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to get characters without any allocation/conversion.
|
||||
if (::CFStringGetCharactersPtr(cfString)) {
|
||||
aMsg->WriteBytes(::CFStringGetCharactersPtr(cfString),
|
||||
length * sizeof(UniChar));
|
||||
} else {
|
||||
UniChar* buffer = (UniChar*)moz_xmalloc(length * sizeof(UniChar));
|
||||
::CFStringGetCharacters(cfString, ::CFRangeMake(0, length), buffer);
|
||||
aMsg->WriteBytes(buffer, length * sizeof(UniChar));
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
NPNSString** aResult) {
|
||||
bool haveString = false;
|
||||
if (!aMsg->ReadBool(aIter, &haveString)) {
|
||||
return false;
|
||||
}
|
||||
if (!haveString) {
|
||||
*aResult = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
long length;
|
||||
if (!ReadParam(aMsg, aIter, &length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Avoid integer multiplication overflow.
|
||||
if (length > INT_MAX / static_cast<long>(sizeof(UniChar))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto chars = mozilla::MakeUnique<UniChar[]>(length);
|
||||
if (length != 0) {
|
||||
if (!aMsg->ReadBytesInto(aIter, chars.get(), length * sizeof(UniChar))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = (NPNSString*)::CFStringCreateWithBytes(
|
||||
kCFAllocatorDefault, (UInt8*)chars.get(), length * sizeof(UniChar),
|
||||
kCFStringEncodingUTF16, false);
|
||||
if (!*aResult) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::IPCByteRange> {
|
||||
typedef mozilla::plugins::IPCByteRange paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.offset);
|
||||
WriteParam(aMsg, aParam.length);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
paramType p;
|
||||
if (ReadParam(aMsg, aIter, &p.offset) &&
|
||||
ReadParam(aMsg, aIter, &p.length)) {
|
||||
*aResult = p;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPNVariable>
|
||||
: public ContiguousEnumSerializer<NPNVariable, NPNVariable::NPNVxDisplay,
|
||||
NPNVariable::NPNVLast> {};
|
||||
|
||||
// The only accepted value is NPNURLVariable::NPNURLVProxy
|
||||
template <>
|
||||
struct ParamTraits<NPNURLVariable>
|
||||
: public ContiguousEnumSerializerInclusive<NPNURLVariable,
|
||||
NPNURLVariable::NPNURLVProxy,
|
||||
NPNURLVariable::NPNURLVProxy> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<NPCoordinateSpace>
|
||||
: public ContiguousEnumSerializerInclusive<
|
||||
NPCoordinateSpace, NPCoordinateSpace::NPCoordinateSpacePlugin,
|
||||
NPCoordinateSpace::NPCoordinateSpaceFlippedScreen> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPAudioDeviceChangeDetailsIPC> {
|
||||
typedef mozilla::plugins::NPAudioDeviceChangeDetailsIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.flow);
|
||||
WriteParam(aMsg, aParam.role);
|
||||
WriteParam(aMsg, aParam.defaultDevice);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
int32_t flow, role;
|
||||
std::wstring defaultDevice;
|
||||
if (ReadParam(aMsg, aIter, &flow) && ReadParam(aMsg, aIter, &role) &&
|
||||
ReadParam(aMsg, aIter, &defaultDevice)) {
|
||||
aResult->flow = flow;
|
||||
aResult->role = role;
|
||||
aResult->defaultDevice = defaultDevice;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%d, %d, %S]", aParam.flow, aParam.role,
|
||||
aParam.defaultDevice.c_str()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::plugins::NPAudioDeviceStateChangedIPC> {
|
||||
typedef mozilla::plugins::NPAudioDeviceStateChangedIPC paramType;
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.device);
|
||||
WriteParam(aMsg, aParam.state);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter,
|
||||
paramType* aResult) {
|
||||
int32_t state;
|
||||
std::wstring device;
|
||||
if (ReadParam(aMsg, aIter, &device) && ReadParam(aMsg, aIter, &state)) {
|
||||
aResult->device = device;
|
||||
aResult->state = state;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void Log(const paramType& aParam, std::wstring* aLog) {
|
||||
aLog->append(StringPrintf(L"[%S,%d]", aParam.device.c_str(), aParam.state));
|
||||
}
|
||||
};
|
||||
} /* namespace IPC */
|
||||
|
||||
// Serializing NPEvents is completely platform-specific and can be rather
|
||||
// intricate depending on the platform. So for readability we split it
|
||||
// into separate files and have the only macro crud live here.
|
||||
//
|
||||
// NB: these guards are based on those where struct NPEvent is defined
|
||||
// in npapi.h. They should be kept in sync.
|
||||
#if defined(XP_MACOSX)
|
||||
# include "mozilla/plugins/NPEventOSX.h"
|
||||
#elif defined(XP_WIN)
|
||||
# include "mozilla/plugins/NPEventWindows.h"
|
||||
#elif defined(ANDROID)
|
||||
# include "mozilla/plugins/NPEventAndroid.h"
|
||||
#elif defined(XP_UNIX)
|
||||
# include "mozilla/plugins/NPEventUnix.h"
|
||||
#else
|
||||
# error Unsupported platform
|
||||
#endif
|
||||
|
||||
#endif /* DOM_PLUGINS_PLUGINMESSAGEUTILS_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,333 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 dom_plugins_PluginModuleChild_h
|
||||
#define dom_plugins_PluginModuleChild_h 1
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "prlink.h"
|
||||
|
||||
#include "npapi.h"
|
||||
#include "npfunctions.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "nsTHashSet.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/plugins/PPluginModuleChild.h"
|
||||
#include "mozilla/plugins/PluginInstanceChild.h"
|
||||
#include "mozilla/plugins/PluginMessageUtils.h"
|
||||
#include "mozilla/plugins/PluginQuirks.h"
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
# include <glib.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class ChildProfilerController;
|
||||
|
||||
namespace plugins {
|
||||
|
||||
class PluginInstanceChild;
|
||||
|
||||
class PluginModuleChild : public PPluginModuleChild {
|
||||
friend class PPluginModuleChild;
|
||||
|
||||
protected:
|
||||
virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
|
||||
const MessageInfo& parent, const MessageInfo& child) override {
|
||||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
virtual bool ShouldContinueFromReplyTimeout() override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvSettingChanged(const PluginSettings& aSettings);
|
||||
|
||||
// Implement the PPluginModuleChild interface
|
||||
mozilla::ipc::IPCResult RecvInitProfiler(
|
||||
Endpoint<mozilla::PProfilerChild>&& aEndpoint);
|
||||
mozilla::ipc::IPCResult RecvDisableFlashProtectedMode();
|
||||
mozilla::ipc::IPCResult AnswerNP_GetEntryPoints(NPError* rv);
|
||||
mozilla::ipc::IPCResult AnswerNP_Initialize(const PluginSettings& aSettings,
|
||||
NPError* rv);
|
||||
mozilla::ipc::IPCResult AnswerSyncNPP_New(PPluginInstanceChild* aActor,
|
||||
NPError* rv);
|
||||
|
||||
mozilla::ipc::IPCResult RecvInitPluginModuleChild(
|
||||
Endpoint<PPluginModuleChild>&& endpoint);
|
||||
|
||||
mozilla::ipc::IPCResult RecvInitPluginFunctionBroker(
|
||||
Endpoint<PFunctionBrokerChild>&& endpoint);
|
||||
|
||||
PPluginInstanceChild* AllocPPluginInstanceChild(
|
||||
const nsCString& aMimeType, const nsTArray<nsCString>& aNames,
|
||||
const nsTArray<nsCString>& aValues);
|
||||
|
||||
bool DeallocPPluginInstanceChild(PPluginInstanceChild* aActor);
|
||||
|
||||
mozilla::ipc::IPCResult RecvPPluginInstanceConstructor(
|
||||
PPluginInstanceChild* aActor, const nsCString& aMimeType,
|
||||
nsTArray<nsCString>&& aNames, nsTArray<nsCString>&& aValues) override;
|
||||
mozilla::ipc::IPCResult AnswerNP_Shutdown(NPError* rv);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerOptionalFunctionsSupported(
|
||||
bool* aURLRedirectNotify, bool* aClearSiteData, bool* aGetSitesWithData);
|
||||
|
||||
mozilla::ipc::IPCResult RecvNPP_ClearSiteData(const nsCString& aSite,
|
||||
const uint64_t& aFlags,
|
||||
const uint64_t& aMaxAge,
|
||||
const uint64_t& aCallbackId);
|
||||
|
||||
mozilla::ipc::IPCResult RecvNPP_GetSitesWithData(const uint64_t& aCallbackId);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetAudioSessionData(const nsID& aId,
|
||||
const nsString& aDisplayName,
|
||||
const nsString& aIconPath);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetParentHangTimeout(const uint32_t& aSeconds);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerInitCrashReporter(
|
||||
mozilla::dom::NativeThreadId* aId);
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvProcessNativeEventsInInterruptCall();
|
||||
|
||||
mozilla::ipc::IPCResult AnswerModuleSupportsAsyncRender(bool* aResult);
|
||||
|
||||
public:
|
||||
explicit PluginModuleChild(bool aIsChrome);
|
||||
virtual ~PluginModuleChild();
|
||||
|
||||
void CommonInit();
|
||||
|
||||
#if defined(OS_WIN) && defined(MOZ_SANDBOX)
|
||||
// Path to the roaming Flash Player folder. This is used to restore some
|
||||
// behavior blocked by the sandbox.
|
||||
static void SetFlashRoamingPath(const std::wstring& aRoamingPath);
|
||||
static std::wstring GetFlashRoamingPath();
|
||||
#endif
|
||||
|
||||
// aPluginFilename is UTF8, not native-charset!
|
||||
bool InitForChrome(const std::string& aPluginFilename,
|
||||
base::ProcessId aParentPid, MessageLoop* aIOLoop,
|
||||
UniquePtr<IPC::Channel> aChannel);
|
||||
|
||||
bool InitForContent(Endpoint<PPluginModuleChild>&& aEndpoint);
|
||||
|
||||
static bool CreateForContentProcess(Endpoint<PPluginModuleChild>&& aEndpoint);
|
||||
|
||||
void CleanUp();
|
||||
|
||||
NPError NP_Shutdown();
|
||||
|
||||
const char* GetUserAgent();
|
||||
|
||||
static const NPNetscapeFuncs sBrowserFuncs;
|
||||
|
||||
static PluginModuleChild* GetChrome();
|
||||
|
||||
/**
|
||||
* The child implementation of NPN_CreateObject.
|
||||
*/
|
||||
static NPObject* NPN_CreateObject(NPP aNPP, NPClass* aClass);
|
||||
/**
|
||||
* The child implementation of NPN_RetainObject.
|
||||
*/
|
||||
static NPObject* NPN_RetainObject(NPObject* aNPObj);
|
||||
/**
|
||||
* The child implementation of NPN_ReleaseObject.
|
||||
*/
|
||||
static void NPN_ReleaseObject(NPObject* aNPObj);
|
||||
|
||||
/**
|
||||
* The child implementations of NPIdentifier-related functions.
|
||||
*/
|
||||
static NPIdentifier NPN_GetStringIdentifier(const NPUTF8* aName);
|
||||
static void NPN_GetStringIdentifiers(const NPUTF8** aNames,
|
||||
int32_t aNameCount,
|
||||
NPIdentifier* aIdentifiers);
|
||||
static NPIdentifier NPN_GetIntIdentifier(int32_t aIntId);
|
||||
static bool NPN_IdentifierIsString(NPIdentifier aIdentifier);
|
||||
static NPUTF8* NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
|
||||
static int32_t NPN_IntFromIdentifier(NPIdentifier aIdentifier);
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
void ProcessNativeEvents();
|
||||
|
||||
void PluginShowWindow(uint32_t window_id, bool modal, CGRect r) {
|
||||
SendPluginShowWindow(window_id, modal, r.origin.x, r.origin.y, r.size.width,
|
||||
r.size.height);
|
||||
}
|
||||
|
||||
void PluginHideWindow(uint32_t window_id) { SendPluginHideWindow(window_id); }
|
||||
|
||||
bool GetNativeCursorsSupported() {
|
||||
return Settings().nativeCursorsSupported();
|
||||
}
|
||||
#endif
|
||||
|
||||
int GetQuirks() { return mQuirks; }
|
||||
|
||||
const PluginSettings& Settings() const { return mCachedSettings; }
|
||||
|
||||
NPError PluginRequiresAudioDeviceChanges(PluginInstanceChild* aInstance,
|
||||
NPBool aShouldRegister);
|
||||
mozilla::ipc::IPCResult RecvNPP_SetValue_NPNVaudioDeviceChangeDetails(
|
||||
const NPAudioDeviceChangeDetailsIPC& detailsIPC);
|
||||
mozilla::ipc::IPCResult RecvNPP_SetValue_NPNVaudioDeviceStateChanged(
|
||||
const NPAudioDeviceStateChangedIPC& aDeviceStateIPC);
|
||||
|
||||
private:
|
||||
NPError DoNP_Initialize(const PluginSettings& aSettings);
|
||||
void AddQuirk(PluginQuirks quirk) {
|
||||
if (mQuirks == QUIRKS_NOT_INITIALIZED) mQuirks = 0;
|
||||
mQuirks |= quirk;
|
||||
}
|
||||
void InitQuirksModes(const nsCString& aMimeType);
|
||||
bool InitGraphics();
|
||||
void DeinitGraphics();
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
static gboolean DetectNestedEventLoop(gpointer data);
|
||||
static gboolean ProcessBrowserEvents(gpointer data);
|
||||
|
||||
virtual void EnteredCxxStack() override;
|
||||
virtual void ExitedCxxStack() override;
|
||||
#endif
|
||||
|
||||
PRLibrary* mLibrary;
|
||||
nsCString mPluginFilename; // UTF8
|
||||
int mQuirks;
|
||||
|
||||
bool mIsChrome;
|
||||
bool mHasShutdown; // true if NP_Shutdown has run
|
||||
|
||||
#ifdef MOZ_GECKO_PROFILER
|
||||
RefPtr<ChildProfilerController> mProfilerController;
|
||||
#endif
|
||||
|
||||
// we get this from the plugin
|
||||
NP_PLUGINSHUTDOWN mShutdownFunc;
|
||||
#if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
||||
NP_PLUGINUNIXINIT mInitializeFunc;
|
||||
#elif defined(OS_WIN) || defined(OS_MACOSX)
|
||||
NP_PLUGININIT mInitializeFunc;
|
||||
NP_GETENTRYPOINTS mGetEntryPointsFunc;
|
||||
#endif
|
||||
|
||||
NPPluginFuncs mFunctions;
|
||||
|
||||
PluginSettings mCachedSettings;
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
// If a plugin spins a nested glib event loop in response to a
|
||||
// synchronous IPC message from the browser, the loop might break
|
||||
// only after the browser responds to a request sent by the
|
||||
// plugin. This can happen if a plugin uses gtk's synchronous
|
||||
// copy/paste, for example. But because the browser is blocked on
|
||||
// a condvar, it can't respond to the request. This situation
|
||||
// isn't technically a deadlock, but the symptoms are basically
|
||||
// the same from the user's perspective.
|
||||
//
|
||||
// We take two steps to prevent this
|
||||
//
|
||||
// (1) Detect nested event loops spun by the plugin. This is
|
||||
// done by scheduling a glib timer event in the plugin
|
||||
// process whenever the browser might block on the plugin.
|
||||
// If the plugin indeed spins a nested loop, this timer event
|
||||
// will fire "soon" thereafter.
|
||||
//
|
||||
// (2) When a nested loop is detected, deschedule the
|
||||
// nested-loop-detection timer and in its place, schedule
|
||||
// another timer that periodically calls back into the
|
||||
// browser and spins a mini event loop. This mini event loop
|
||||
// processes a handful of pending native events.
|
||||
//
|
||||
// Because only timer (1) or (2) (or neither) may be active at any
|
||||
// point in time, we use the same member variable
|
||||
// |mNestedLoopTimerId| to refer to both.
|
||||
//
|
||||
// When the browser no longer might be blocked on a plugin's IPC
|
||||
// response, we deschedule whichever of (1) or (2) is active.
|
||||
guint mNestedLoopTimerId;
|
||||
# ifdef DEBUG
|
||||
// Depth of the stack of calls to g_main_context_dispatch before any
|
||||
// nested loops are run. This is 1 when IPC calls are dispatched from
|
||||
// g_main_context_iteration, or 0 when dispatched directly from
|
||||
// MessagePumpForUI.
|
||||
int mTopLoopDepth;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN)
|
||||
typedef nsTHashSet<PluginInstanceChild*> PluginInstanceSet;
|
||||
// Set of plugins that have registered to be notified when the audio device
|
||||
// changes.
|
||||
PluginInstanceSet mAudioNotificationSet;
|
||||
#endif
|
||||
|
||||
public: // called by PluginInstanceChild
|
||||
/**
|
||||
* Dealloc an NPObject after last-release or when the associated instance
|
||||
* is destroyed. This function will remove the object from mObjectMap.
|
||||
*/
|
||||
static void DeallocNPObject(NPObject* o);
|
||||
|
||||
NPError NPP_Destroy(PluginInstanceChild* instance) {
|
||||
return mFunctions.destroy(instance->GetNPP(), 0);
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX) && defined(MOZ_SANDBOX)
|
||||
void EnableFlashSandbox(int aLevel, bool aShouldEnableLogging);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#if defined(OS_MACOSX) && defined(MOZ_SANDBOX)
|
||||
int mFlashSandboxLevel;
|
||||
bool mEnableFlashSandboxLogging;
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
virtual void EnteredCall() override;
|
||||
virtual void ExitedCall() override;
|
||||
|
||||
// Entered/ExitedCall notifications keep track of whether the plugin has
|
||||
// entered a nested event loop within this interrupt call.
|
||||
struct IncallFrame {
|
||||
IncallFrame() : _spinning(false), _savedNestableTasksAllowed(false) {}
|
||||
|
||||
bool _spinning;
|
||||
bool _savedNestableTasksAllowed;
|
||||
};
|
||||
|
||||
AutoTArray<IncallFrame, 8> mIncallPumpingStack;
|
||||
|
||||
static LRESULT CALLBACK NestedInputEventHook(int code, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
static LRESULT CALLBACK CallWindowProcHook(int code, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
void SetEventHooks();
|
||||
void ResetEventHooks();
|
||||
HHOOK mNestedEventHook;
|
||||
HHOOK mGlobalCallWndProcHook;
|
||||
|
||||
public:
|
||||
bool mAsyncRenderSupport;
|
||||
#endif
|
||||
};
|
||||
|
||||
} /* namespace plugins */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif // ifndef dom_plugins_PluginModuleChild_h
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,532 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 mozilla_plugins_PluginModuleParent_h
|
||||
#define mozilla_plugins_PluginModuleParent_h
|
||||
|
||||
#include "base/process.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
#include "mozilla/HangAnnotations.h"
|
||||
#include "mozilla/PluginLibrary.h"
|
||||
#include "mozilla/plugins/PluginProcessParent.h"
|
||||
#include "mozilla/plugins/PPluginModuleParent.h"
|
||||
#include "mozilla/plugins/PluginMessageUtils.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "npapi.h"
|
||||
#include "npfunctions.h"
|
||||
#include "nsExceptionHandler.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIObserver.h"
|
||||
#ifdef XP_WIN
|
||||
# include "nsWindowsHelpers.h"
|
||||
#endif
|
||||
|
||||
class nsPluginTag;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace ipc {
|
||||
class CrashReporterHost;
|
||||
} // namespace ipc
|
||||
namespace layers {
|
||||
class TextureClientRecycleAllocator;
|
||||
} // namespace layers
|
||||
|
||||
namespace plugins {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class BrowserStreamParent;
|
||||
class PluginInstanceParent;
|
||||
|
||||
#ifdef XP_WIN
|
||||
class PluginHangUIParent;
|
||||
class FunctionBrokerParent;
|
||||
#endif
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
class FinishInjectorInitTask;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* PluginModuleParent
|
||||
*
|
||||
* This class implements the NPP API from the perspective of the rest
|
||||
* of Gecko, forwarding NPP calls along to the child process that is
|
||||
* actually running the plugin.
|
||||
*
|
||||
* This class /also/ implements a version of the NPN API, because the
|
||||
* child process needs to make these calls back into Gecko proper.
|
||||
* This class is responsible for "actually" making those function calls.
|
||||
*
|
||||
* If a plugin is running, there will always be one PluginModuleParent for it in
|
||||
* the chrome process. In addition, any content process using the plugin will
|
||||
* have its own PluginModuleParent. The subclasses PluginModuleChromeParent and
|
||||
* PluginModuleContentParent implement functionality that is specific to one
|
||||
* case or the other.
|
||||
*/
|
||||
class PluginModuleParent : public PPluginModuleParent,
|
||||
public PluginLibrary
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
,
|
||||
public CrashReporter::InjectorCrashCallback
|
||||
#endif
|
||||
{
|
||||
friend class PPluginModuleParent;
|
||||
|
||||
protected:
|
||||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
|
||||
PPluginInstanceParent* AllocPPluginInstanceParent(
|
||||
const nsCString& aMimeType, const nsTArray<nsCString>& aNames,
|
||||
const nsTArray<nsCString>& aValues);
|
||||
|
||||
bool DeallocPPluginInstanceParent(PPluginInstanceParent* aActor);
|
||||
|
||||
public:
|
||||
explicit PluginModuleParent(bool aIsChrome);
|
||||
virtual ~PluginModuleParent();
|
||||
|
||||
bool IsChrome() const { return mIsChrome; }
|
||||
|
||||
virtual void SetPlugin(nsNPAPIPlugin* plugin) override { mPlugin = plugin; }
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
const NPNetscapeFuncs* GetNetscapeFuncs() { return mNPNIface; }
|
||||
|
||||
bool OkToCleanup() const { return !IsOnCxxStack(); }
|
||||
|
||||
void ProcessRemoteNativeEventsInInterruptCall() override;
|
||||
|
||||
virtual nsresult GetRunID(uint32_t* aRunID) override;
|
||||
virtual void SetHasLocalInstance() override { mHadLocalInstance = true; }
|
||||
|
||||
int GetQuirks() { return mQuirks; }
|
||||
|
||||
protected:
|
||||
virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
|
||||
const MessageInfo& parent, const MessageInfo& child) override {
|
||||
return MediateRace(parent, child);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RecvBackUpXResources(
|
||||
const FileDescriptor& aXSocketFd);
|
||||
|
||||
mozilla::ipc::IPCResult AnswerProcessSomeEvents();
|
||||
|
||||
mozilla::ipc::IPCResult RecvProcessNativeEventsInInterruptCall();
|
||||
|
||||
mozilla::ipc::IPCResult RecvPluginShowWindow(
|
||||
const uint32_t& aWindowId, const bool& aModal, const int32_t& aX,
|
||||
const int32_t& aY, const double& aWidth, const double& aHeight);
|
||||
|
||||
mozilla::ipc::IPCResult RecvPluginHideWindow(const uint32_t& aWindowId);
|
||||
|
||||
mozilla::ipc::IPCResult RecvNPN_SetException(const nsCString& aMessage);
|
||||
|
||||
mozilla::ipc::IPCResult RecvNPN_ReloadPlugins(const bool& aReloadPages);
|
||||
|
||||
static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
|
||||
|
||||
virtual mozilla::ipc::IPCResult
|
||||
AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
|
||||
const bool& shouldRegister, NPError* result);
|
||||
|
||||
protected:
|
||||
void SetChildTimeout(const int32_t aChildTimeout);
|
||||
static void TimeoutChanged(const char* aPref, void* aModule);
|
||||
|
||||
virtual void UpdatePluginTimeout() {}
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult RecvReturnClearSiteData(const NPError& aRv,
|
||||
const uint64_t& aCallbackId);
|
||||
|
||||
mozilla::ipc::IPCResult RecvReturnSitesWithData(nsTArray<nsCString>&& aSites,
|
||||
const uint64_t& aCallbackId);
|
||||
|
||||
void SetPluginFuncs(NPPluginFuncs* aFuncs);
|
||||
|
||||
nsresult NPP_NewInternal(NPMIMEType pluginType, NPP instance,
|
||||
nsTArray<nsCString>& names,
|
||||
nsTArray<nsCString>& values, NPSavedData* saved,
|
||||
NPError* error);
|
||||
|
||||
// NPP-like API that Gecko calls are trampolined into. These
|
||||
// messages then get forwarded along to the plugin instance,
|
||||
// and then eventually the child process.
|
||||
|
||||
static NPError NPP_Destroy(NPP instance, NPSavedData** save);
|
||||
|
||||
static NPError NPP_SetWindow(NPP instance, NPWindow* window);
|
||||
static NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream,
|
||||
NPBool seekable, uint16_t* stype);
|
||||
static NPError NPP_DestroyStream(NPP instance, NPStream* stream,
|
||||
NPReason reason);
|
||||
static int32_t NPP_WriteReady(NPP instance, NPStream* stream);
|
||||
static int32_t NPP_Write(NPP instance, NPStream* stream, int32_t offset,
|
||||
int32_t len, void* buffer);
|
||||
static void NPP_Print(NPP instance, NPPrint* platformPrint);
|
||||
static int16_t NPP_HandleEvent(NPP instance, void* event);
|
||||
static void NPP_URLNotify(NPP instance, const char* url, NPReason reason,
|
||||
void* notifyData);
|
||||
static NPError NPP_GetValue(NPP instance, NPPVariable variable,
|
||||
void* ret_value);
|
||||
static NPError NPP_SetValue(NPP instance, NPNVariable variable, void* value);
|
||||
static void NPP_URLRedirectNotify(NPP instance, const char* url,
|
||||
int32_t status, void* notifyData);
|
||||
|
||||
virtual bool HasRequiredFunctions() override;
|
||||
virtual nsresult AsyncSetWindow(NPP aInstance, NPWindow* aWindow) override;
|
||||
virtual nsresult GetImageContainer(
|
||||
NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
|
||||
virtual nsresult GetImageSize(NPP aInstance, nsIntSize* aSize) override;
|
||||
virtual void DidComposite(NPP aInstance) override;
|
||||
virtual bool IsOOP() override { return true; }
|
||||
virtual nsresult SetBackgroundUnknown(NPP instance) override;
|
||||
virtual nsresult BeginUpdateBackground(NPP instance, const nsIntRect& aRect,
|
||||
DrawTarget** aDrawTarget) override;
|
||||
virtual nsresult EndUpdateBackground(NPP instance,
|
||||
const nsIntRect& aRect) override;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
virtual nsresult GetScrollCaptureContainer(
|
||||
NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
|
||||
#endif
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs,
|
||||
NPError* error) override;
|
||||
#else
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs,
|
||||
NPError* error) override;
|
||||
#endif
|
||||
virtual nsresult NP_Shutdown(NPError* error) override;
|
||||
|
||||
virtual nsresult NP_GetMIMEDescription(const char** mimeDesc) override;
|
||||
virtual nsresult NP_GetValue(void* future, NPPVariable aVariable,
|
||||
void* aValue, NPError* error) override;
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs,
|
||||
NPError* error) override;
|
||||
#endif
|
||||
virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance, int16_t argc,
|
||||
char* argn[], char* argv[], NPSavedData* saved,
|
||||
NPError* error) override;
|
||||
virtual nsresult NPP_ClearSiteData(
|
||||
const char* site, uint64_t flags, uint64_t maxAge,
|
||||
nsCOMPtr<nsIClearSiteDataCallback> callback) override;
|
||||
virtual nsresult NPP_GetSitesWithData(
|
||||
nsCOMPtr<nsIGetSitesWithDataCallback> callback) override;
|
||||
|
||||
private:
|
||||
std::map<uint64_t, nsCOMPtr<nsIClearSiteDataCallback>>
|
||||
mClearSiteDataCallbacks;
|
||||
std::map<uint64_t, nsCOMPtr<nsIGetSitesWithDataCallback>>
|
||||
mSitesWithDataCallbacks;
|
||||
|
||||
nsCString mPluginFilename;
|
||||
int mQuirks;
|
||||
void InitQuirksModes(const nsCString& aMimeType);
|
||||
|
||||
public:
|
||||
#if defined(XP_MACOSX)
|
||||
virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance,
|
||||
bool* aDrawing) override;
|
||||
#endif
|
||||
#if defined(XP_MACOSX) || defined(XP_WIN)
|
||||
virtual nsresult ContentsScaleFactorChanged(
|
||||
NPP instance, double aContentsScaleFactor) override;
|
||||
#endif
|
||||
|
||||
layers::TextureClientRecycleAllocator*
|
||||
EnsureTextureAllocatorForDirectBitmap();
|
||||
layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDXGISurface();
|
||||
|
||||
protected:
|
||||
void NotifyFlashHang();
|
||||
void NotifyPluginCrashed();
|
||||
void OnInitFailure();
|
||||
bool DoShutdown(NPError* error);
|
||||
|
||||
bool GetSetting(NPNVariable aVariable);
|
||||
void GetSettings(PluginSettings* aSettings);
|
||||
|
||||
bool mIsChrome;
|
||||
bool mShutdown;
|
||||
bool mHadLocalInstance;
|
||||
bool mClearSiteDataSupported;
|
||||
bool mGetSitesWithDataSupported;
|
||||
NPNetscapeFuncs* mNPNIface;
|
||||
NPPluginFuncs* mNPPIface;
|
||||
nsNPAPIPlugin* mPlugin;
|
||||
ipc::TaskFactory<PluginModuleParent> mTaskFactory;
|
||||
nsString mHangID;
|
||||
nsCString mPluginName;
|
||||
nsCString mPluginVersion;
|
||||
int32_t mSandboxLevel;
|
||||
bool mIsFlashPlugin;
|
||||
|
||||
#ifdef MOZ_X11
|
||||
// Dup of plugin's X socket, used to scope its resources to this
|
||||
// object instead of the plugin process's lifetime
|
||||
ScopedClose mPluginXSocketFdDup;
|
||||
#endif
|
||||
|
||||
bool GetPluginDetails();
|
||||
|
||||
uint32_t mRunID;
|
||||
|
||||
RefPtr<layers::TextureClientRecycleAllocator>
|
||||
mTextureAllocatorForDirectBitmap;
|
||||
RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDXGISurface;
|
||||
|
||||
/**
|
||||
* This mutex protects the crash reporter when the Plugin Hang UI event
|
||||
* handler is executing off main thread. It is intended to protect both
|
||||
* the mCrashReporter variable in addition to the CrashReporterHost object
|
||||
* that mCrashReporter refers to.
|
||||
*/
|
||||
mozilla::Mutex mCrashReporterMutex;
|
||||
UniquePtr<ipc::CrashReporterHost> mCrashReporter;
|
||||
nsString mOrphanedDumpId;
|
||||
};
|
||||
|
||||
class PluginModuleContentParent : public PluginModuleParent {
|
||||
public:
|
||||
explicit PluginModuleContentParent();
|
||||
|
||||
static PluginLibrary* LoadModule(uint32_t aPluginId, nsPluginTag* aPluginTag);
|
||||
|
||||
virtual ~PluginModuleContentParent();
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
static void Initialize(Endpoint<PPluginModuleParent>&& aEndpoint);
|
||||
|
||||
virtual bool ShouldContinueFromReplyTimeout() override;
|
||||
virtual void OnExitedSyncSend() override;
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
void OnCrash(DWORD processID) override {}
|
||||
#endif
|
||||
|
||||
static PluginModuleContentParent* sSavedModuleParent;
|
||||
|
||||
uint32_t mPluginId;
|
||||
};
|
||||
|
||||
class PluginModuleChromeParent : public PluginModuleParent,
|
||||
public mozilla::BackgroundHangAnnotator {
|
||||
friend class mozilla::ipc::CrashReporterHost;
|
||||
|
||||
public:
|
||||
/**
|
||||
* LoadModule
|
||||
*
|
||||
* This may or may not launch a plugin child process,
|
||||
* and may or may not be very expensive.
|
||||
*/
|
||||
static PluginLibrary* LoadModule(const char* aFilePath, uint32_t aPluginId,
|
||||
nsPluginTag* aPluginTag);
|
||||
|
||||
virtual ~PluginModuleChromeParent();
|
||||
|
||||
/*
|
||||
* Takes a full multi-process dump including the plugin process and the
|
||||
* content process. If aBrowserDumpId is not empty then the browser dump
|
||||
* associated with it will be paired to the resulting minidump.
|
||||
* Takes ownership of the file associated with aBrowserDumpId.
|
||||
*
|
||||
* @param aContentPid PID of the e10s content process from which a hang was
|
||||
* reported. May be kInvalidProcessId if not applicable.
|
||||
* @param aBrowserDumpId (optional) previously taken browser dump id. If
|
||||
* provided TakeFullMinidump will use this dump file instead of
|
||||
* generating a new one. If not provided a browser dump will be taken at
|
||||
* the time of this call.
|
||||
* @param aDumpId Returns the ID of the newly generated crash dump. Left
|
||||
* untouched upon failure.
|
||||
*/
|
||||
void TakeFullMinidump(base::ProcessId aContentPid,
|
||||
const nsAString& aBrowserDumpId, nsString& aDumpId);
|
||||
|
||||
/*
|
||||
* Terminates the plugin process associated with this plugin module. Also
|
||||
* generates appropriate crash reports unless an existing one is provided.
|
||||
* Takes ownership of the file associated with aDumpId on success.
|
||||
*
|
||||
* @param aMsgLoop the main message pump associated with the module
|
||||
* protocol.
|
||||
* @param aContentPid PID of the e10s content process from which a hang was
|
||||
* reported. May be kInvalidProcessId if not applicable.
|
||||
* @param aMonitorDescription a string describing the hang monitor that
|
||||
* is making this call. This string is added to the crash reporter
|
||||
* annotations for the plugin process.
|
||||
* @param aDumpId (optional) previously taken dump id. If provided
|
||||
* TerminateChildProcess will use this dump file instead of generating a
|
||||
* multi-process crash report. If not provided a multi-process dump will
|
||||
* be taken at the time of this call.
|
||||
*/
|
||||
void TerminateChildProcess(MessageLoop* aMsgLoop, base::ProcessId aContentPid,
|
||||
const nsCString& aMonitorDescription,
|
||||
const nsAString& aDumpId);
|
||||
|
||||
#ifdef XP_WIN
|
||||
/**
|
||||
* Called by Plugin Hang UI to notify that the user has clicked continue.
|
||||
* Used for chrome hang annotations.
|
||||
*/
|
||||
void OnHangUIContinue();
|
||||
|
||||
void EvaluateHangUIState(const bool aReset);
|
||||
#endif // XP_WIN
|
||||
|
||||
void CachedSettingChanged();
|
||||
|
||||
private:
|
||||
virtual void EnteredCxxStack() override;
|
||||
|
||||
void ExitedCxxStack() override;
|
||||
|
||||
mozilla::ipc::IProtocol* GetInvokingProtocol();
|
||||
PluginInstanceParent* GetManagingInstance(mozilla::ipc::IProtocol* aProtocol);
|
||||
|
||||
virtual void AnnotateHang(
|
||||
mozilla::BackgroundHangAnnotations& aAnnotations) override;
|
||||
|
||||
virtual bool ShouldContinueFromReplyTimeout() override;
|
||||
|
||||
void ProcessFirstMinidump();
|
||||
void HandleOrphanedMinidump();
|
||||
void AddCrashAnnotations();
|
||||
|
||||
PluginProcessParent* Process() const { return mSubprocess; }
|
||||
base::ProcessHandle ChildProcessHandle() {
|
||||
return mSubprocess->GetChildProcessHandle();
|
||||
}
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs,
|
||||
NPError* error) override;
|
||||
#else
|
||||
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs,
|
||||
NPError* error) override;
|
||||
#endif
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs,
|
||||
NPError* error) override;
|
||||
#endif
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
// aFilePath is UTF8, not native!
|
||||
explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId,
|
||||
int32_t aSandboxLevel);
|
||||
|
||||
void CleanupFromTimeout(const bool aByHangUI);
|
||||
|
||||
virtual void UpdatePluginTimeout() override;
|
||||
|
||||
void RegisterSettingsCallbacks();
|
||||
void UnregisterSettingsCallbacks();
|
||||
|
||||
bool InitCrashReporter();
|
||||
|
||||
mozilla::ipc::IPCResult RecvNotifyContentModuleDestroyed() override;
|
||||
|
||||
static void CachedSettingChanged(const char* aPref, void* aModule);
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges(
|
||||
const bool& shouldRegister, NPError* result) override;
|
||||
|
||||
PluginProcessParent* mSubprocess;
|
||||
uint32_t mPluginId;
|
||||
|
||||
ipc::TaskFactory<PluginModuleChromeParent> mChromeTaskFactory;
|
||||
|
||||
enum HangAnnotationFlags {
|
||||
kInPluginCall = (1u << 0),
|
||||
kHangUIShown = (1u << 1),
|
||||
kHangUIContinued = (1u << 2),
|
||||
kHangUIDontShow = (1u << 3)
|
||||
};
|
||||
Atomic<uint32_t> mHangAnnotationFlags;
|
||||
#ifdef XP_WIN
|
||||
nsTArray<float> mPluginCpuUsageOnHang;
|
||||
PluginHangUIParent* mHangUIParent;
|
||||
bool mHangUIEnabled;
|
||||
bool mIsTimerReset;
|
||||
|
||||
/**
|
||||
* Launches the Plugin Hang UI.
|
||||
*
|
||||
* @return true if plugin-hang-ui.exe has been successfully launched.
|
||||
* false if the Plugin Hang UI is disabled, already showing,
|
||||
* or the launch failed.
|
||||
*/
|
||||
bool LaunchHangUI();
|
||||
|
||||
/**
|
||||
* Finishes the Plugin Hang UI and cancels if it is being shown to the user.
|
||||
*/
|
||||
void FinishHangUI();
|
||||
|
||||
FunctionBrokerParent* mBrokerParent;
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_CRASHREPORTER_INJECTOR
|
||||
friend class mozilla::plugins::FinishInjectorInitTask;
|
||||
|
||||
void InitializeInjector();
|
||||
void DoInjection(const nsAutoHandle& aSnapshot);
|
||||
static DWORD WINAPI GetToolhelpSnapshot(LPVOID aContext);
|
||||
|
||||
void OnCrash(DWORD processID) override;
|
||||
|
||||
DWORD mFlashProcess1;
|
||||
DWORD mFlashProcess2;
|
||||
RefPtr<mozilla::plugins::FinishInjectorInitTask> mFinishInitTask;
|
||||
#endif
|
||||
|
||||
void OnProcessLaunched(const bool aSucceeded);
|
||||
|
||||
class LaunchedTask : public LaunchCompleteTask {
|
||||
public:
|
||||
explicit LaunchedTask(PluginModuleChromeParent* aModule)
|
||||
: mModule(aModule) {
|
||||
MOZ_ASSERT(aModule);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override {
|
||||
mModule->OnProcessLaunched(mLaunchSucceeded);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
PluginModuleChromeParent* mModule;
|
||||
};
|
||||
|
||||
friend class LaunchedTask;
|
||||
|
||||
nsCOMPtr<nsIObserver> mPluginOfflineObserver;
|
||||
bool mIsBlocklisted;
|
||||
bool mIsCleaningFromTimeout;
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_plugins_PluginModuleParent_h
|
|
@ -1,186 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 "mozilla/plugins/PluginProcessChild.h"
|
||||
|
||||
#include "ClearOnShutdown.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/message_loop.h" // for MessageLoop
|
||||
#include "base/string_util.h"
|
||||
#include "mozilla/AbstractThread.h"
|
||||
#include "mozilla/TaskController.h"
|
||||
#include "mozilla/ipc/IOThreadChild.h"
|
||||
#include "nsDebugImpl.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "prlink.h"
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
# include "mozilla/SandboxSettings.h"
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
# if defined(MOZ_SANDBOX)
|
||||
# include "mozilla/sandboxTarget.h"
|
||||
# include "ProcessUtils.h"
|
||||
# include "nsDirectoryService.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
using mozilla::ipc::IOThreadChild;
|
||||
|
||||
#ifdef OS_WIN
|
||||
# include <algorithm>
|
||||
#endif
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
static void SetSandboxTempPath(const std::wstring& aFullTmpPath) {
|
||||
// Save the TMP environment variable so that is is picked up by GetTempPath().
|
||||
// Note that we specifically write to the TMP variable, as that is the first
|
||||
// variable that is checked by GetTempPath() to determine its output.
|
||||
Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", aFullTmpPath.c_str()));
|
||||
|
||||
// We also set TEMP in case there is naughty third-party code that is
|
||||
// referencing the environment variable directly.
|
||||
Unused << NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", aFullTmpPath.c_str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool PluginProcessChild::Init(int aArgc, char* aArgv[]) {
|
||||
nsDebugImpl::SetMultiprocessMode("NPAPI");
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
// Remove the trigger for "dyld interposing" that we added in
|
||||
// GeckoChildProcessHost::PerformAsyncLaunch(), in the host
|
||||
// process just before we were launched. Dyld interposing will still
|
||||
// happen in our process (the plugin child process). But we don't want
|
||||
// it to happen in any processes that the plugin might launch from our
|
||||
// process.
|
||||
nsCString interpose(PR_GetEnv("DYLD_INSERT_LIBRARIES"));
|
||||
if (!interpose.IsEmpty()) {
|
||||
// If we added the path to libplugin_child_interpose.dylib to an
|
||||
// existing DYLD_INSERT_LIBRARIES, we appended it to the end, after a
|
||||
// ":" path seperator.
|
||||
int32_t lastSeparatorPos = interpose.RFind(":");
|
||||
int32_t lastTriggerPos = interpose.RFind("libplugin_child_interpose.dylib");
|
||||
bool needsReset = false;
|
||||
if (lastTriggerPos != -1) {
|
||||
if (lastSeparatorPos == -1) {
|
||||
interpose.Truncate();
|
||||
needsReset = true;
|
||||
} else if (lastTriggerPos > lastSeparatorPos) {
|
||||
interpose.SetLength(lastSeparatorPos);
|
||||
needsReset = true;
|
||||
}
|
||||
}
|
||||
if (needsReset) {
|
||||
nsCString setInterpose("DYLD_INSERT_LIBRARIES=");
|
||||
if (!interpose.IsEmpty()) {
|
||||
setInterpose.Append(interpose);
|
||||
}
|
||||
// Values passed to PR_SetEnv() must be seperately allocated.
|
||||
char* setInterposePtr = strdup(setInterpose.get());
|
||||
PR_SetEnv(setInterposePtr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Certain plugins, such as flash, steal the unhandled exception filter
|
||||
// thus we never get crash reports when they fault. This call fixes it.
|
||||
message_loop()->set_exception_restoration(true);
|
||||
|
||||
std::string pluginFilename;
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
// NB: need to be very careful in ensuring that the first arg
|
||||
// (after the binary name) here is indeed the plugin module path.
|
||||
// Keep in sync with dom/plugins/PluginModuleParent.
|
||||
std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
|
||||
MOZ_ASSERT(values.size() >= 2, "not enough args");
|
||||
|
||||
pluginFilename = UnmungePluginDsoPath(values[1]);
|
||||
|
||||
# if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
int level;
|
||||
if (values.size() >= 4 && values[2] == "-flashSandboxLevel" &&
|
||||
(level = std::stoi(values[3], nullptr)) > 0) {
|
||||
level = ClampFlashSandboxLevel(level);
|
||||
MOZ_ASSERT(level > 0);
|
||||
|
||||
bool enableLogging = false;
|
||||
if (values.size() >= 5 && values[4] == "-flashSandboxLogging") {
|
||||
enableLogging = true;
|
||||
}
|
||||
|
||||
mPlugin.EnableFlashSandbox(level, enableLogging);
|
||||
}
|
||||
# endif
|
||||
|
||||
#elif defined(OS_WIN)
|
||||
std::vector<std::wstring> values =
|
||||
CommandLine::ForCurrentProcess()->GetLooseValues();
|
||||
MOZ_ASSERT(values.size() >= 1, "not enough loose args");
|
||||
|
||||
// parameters are:
|
||||
// values[0] is path to plugin DLL
|
||||
// values[1] is path to folder that should be used for temp files
|
||||
// values[2] is path to the Flash Player roaming folder
|
||||
// (this is always that Flash folder, regardless of what plugin is being
|
||||
// run)
|
||||
pluginFilename = WideToUTF8(values[0]);
|
||||
|
||||
// We don't initialize XPCOM but we need the thread manager and the
|
||||
// logging framework for the FunctionBroker.
|
||||
NS_SetMainThread();
|
||||
mozilla::TimeStamp::Startup();
|
||||
NS_LogInit();
|
||||
mozilla::LogModule::Init(aArgc, aArgv);
|
||||
nsThreadManager::get().Init();
|
||||
|
||||
# if defined(MOZ_SANDBOX)
|
||||
MOZ_ASSERT(values.size() >= 3,
|
||||
"not enough loose args for sandboxed plugin process");
|
||||
|
||||
// The sandbox closes off the default location temp file location so we set
|
||||
// a new one here (regardless of whether or not we are sandboxing).
|
||||
SetSandboxTempPath(values[1]);
|
||||
PluginModuleChild::SetFlashRoamingPath(values[2]);
|
||||
|
||||
// This is probably the earliest we would want to start the sandbox.
|
||||
// As we attempt to tighten the sandbox, we may need to consider moving this
|
||||
// to later in the plugin initialization.
|
||||
mozilla::SandboxTarget::Instance()->StartSandbox();
|
||||
# endif
|
||||
#else
|
||||
# error Sorry
|
||||
#endif
|
||||
|
||||
return mPlugin.InitForChrome(pluginFilename, ParentPid(),
|
||||
IOThreadChild::message_loop(),
|
||||
IOThreadChild::TakeChannel());
|
||||
}
|
||||
|
||||
void PluginProcessChild::CleanUp() {
|
||||
#if defined(OS_WIN)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Shutdown components we started in Init. Note that KillClearOnShutdown
|
||||
// is an event that is regularly part of XPCOM shutdown. We do not
|
||||
// call XPCOM's shutdown but we need this event to be sent to avoid
|
||||
// leaking objects labeled as ClearOnShutdown.
|
||||
nsThreadManager::get().Shutdown();
|
||||
NS_LogTerm();
|
||||
#endif
|
||||
|
||||
mozilla::KillClearOnShutdown(ShutdownPhase::XPCOMShutdownFinal);
|
||||
|
||||
AbstractThread::ShutdownMainThread();
|
||||
|
||||
mozilla::TaskController::Shutdown();
|
||||
}
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,53 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 dom_plugins_PluginProcessChild_h
|
||||
#define dom_plugins_PluginProcessChild_h 1
|
||||
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
#include "mozilla/plugins/PluginModuleChild.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "mozilla/mscom/ProcessRuntime.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class PluginProcessChild : public mozilla::ipc::ProcessChild {
|
||||
protected:
|
||||
typedef mozilla::ipc::ProcessChild ProcessChild;
|
||||
|
||||
public:
|
||||
explicit PluginProcessChild(ProcessId aParentPid)
|
||||
: ProcessChild(aParentPid), mPlugin(true) {}
|
||||
|
||||
virtual ~PluginProcessChild() = default;
|
||||
|
||||
virtual bool Init(int aArgc, char* aArgv[]) override;
|
||||
virtual void CleanUp() override;
|
||||
|
||||
protected:
|
||||
static PluginProcessChild* current() {
|
||||
return static_cast<PluginProcessChild*>(ProcessChild::current());
|
||||
}
|
||||
|
||||
private:
|
||||
#if defined(XP_WIN)
|
||||
/* Drag-and-drop depends on the host initializing COM.
|
||||
* This object initializes and configures COM. */
|
||||
mozilla::mscom::ProcessRuntime mCOMRuntime;
|
||||
#endif
|
||||
PluginModuleChild mPlugin;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(PluginProcessChild);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ifndef dom_plugins_PluginProcessChild_h
|
|
@ -1,191 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 "mozilla/plugins/PluginProcessParent.h"
|
||||
|
||||
#include "base/string_util.h"
|
||||
#include "base/process_util.h"
|
||||
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIProperties.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
|
||||
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
||||
#include "mozilla/plugins/PluginMessageUtils.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
using mozilla::ipc::BrowserProcessSubThread;
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
using mozilla::plugins::LaunchCompleteTask;
|
||||
using mozilla::plugins::PluginProcessParent;
|
||||
|
||||
#ifdef XP_WIN
|
||||
PluginProcessParent::PidSet* PluginProcessParent::sPidSet = nullptr;
|
||||
#endif
|
||||
|
||||
PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath)
|
||||
: GeckoChildProcessHost(GeckoProcessType_Plugin),
|
||||
mPluginFilePath(aPluginFilePath),
|
||||
mTaskFactory(this),
|
||||
mMainMsgLoop(MessageLoop::current())
|
||||
#ifdef XP_WIN
|
||||
,
|
||||
mChildPid(0)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
PluginProcessParent::~PluginProcessParent() {
|
||||
#ifdef XP_WIN
|
||||
if (sPidSet && mChildPid) {
|
||||
sPidSet->Remove(mChildPid);
|
||||
if (sPidSet->IsEmpty()) {
|
||||
delete sPidSet;
|
||||
sPidSet = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool PluginProcessParent::Launch(
|
||||
mozilla::UniquePtr<LaunchCompleteTask> aLaunchCompleteTask,
|
||||
int32_t aSandboxLevel, bool aIsSandboxLoggingEnabled) {
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_SANDBOX)
|
||||
// At present, the Mac Flash plugin sandbox does not support different
|
||||
// levels and is enabled via a boolean pref or environment variable.
|
||||
// On Mac, when |aSandboxLevel| is positive, we enable the sandbox.
|
||||
# if defined(XP_WIN)
|
||||
mSandboxLevel = aSandboxLevel;
|
||||
|
||||
// The sandbox process sometimes needs read access to the plugin file.
|
||||
if (aSandboxLevel >= 3) {
|
||||
std::wstring pluginFile(
|
||||
NS_ConvertUTF8toUTF16(mPluginFilePath.c_str()).get());
|
||||
mAllowedFilesRead.push_back(pluginFile);
|
||||
}
|
||||
# endif // XP_WIN
|
||||
#else
|
||||
if (aSandboxLevel != 0) {
|
||||
MOZ_ASSERT(false,
|
||||
"Can't enable an NPAPI process sandbox for platform/build.");
|
||||
}
|
||||
#endif
|
||||
|
||||
mLaunchCompleteTask = std::move(aLaunchCompleteTask);
|
||||
|
||||
vector<string> args;
|
||||
args.push_back(MungePluginDsoPath(mPluginFilePath));
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
if (aSandboxLevel > 0) {
|
||||
args.push_back("-flashSandboxLevel");
|
||||
args.push_back(std::to_string(aSandboxLevel));
|
||||
if (aIsSandboxLoggingEnabled) {
|
||||
args.push_back("-flashSandboxLogging");
|
||||
}
|
||||
}
|
||||
#elif defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIProperties> dirSvc =
|
||||
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT(false, "Failed to get directory service.");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> dir;
|
||||
rv = dirSvc->Get(NS_APP_PLUGIN_PROCESS_TEMP_DIR, NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(dir));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to get plugin process temp directory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString tempDir;
|
||||
MOZ_ALWAYS_SUCCEEDS(dir->GetPath(tempDir));
|
||||
args.push_back(NS_ConvertUTF16toUTF8(tempDir).get());
|
||||
|
||||
rv =
|
||||
dirSvc->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsIFile), getter_AddRefs(dir));
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to get appdata directory.");
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoString appdataDir;
|
||||
MOZ_ALWAYS_SUCCEEDS(dir->GetPath(appdataDir));
|
||||
appdataDir.Append(L"\\Adobe\\");
|
||||
args.push_back(NS_ConvertUTF16toUTF8(appdataDir).get());
|
||||
#endif
|
||||
|
||||
bool result = AsyncLaunch(args);
|
||||
if (!result) {
|
||||
mLaunchCompleteTask = nullptr;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function exists so that we may provide an additional level of
|
||||
* indirection between the task being posted to main event loop (a
|
||||
* RunnableMethod) and the launch complete task itself. This is needed
|
||||
* for cases when both WaitUntilConnected or OnChannel* race to invoke the
|
||||
* task.
|
||||
*/
|
||||
void PluginProcessParent::RunLaunchCompleteTask() {
|
||||
if (mLaunchCompleteTask) {
|
||||
mLaunchCompleteTask->Run();
|
||||
mLaunchCompleteTask = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs) {
|
||||
bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs);
|
||||
if (mLaunchCompleteTask) {
|
||||
if (result) {
|
||||
mLaunchCompleteTask->SetLaunchSucceeded();
|
||||
}
|
||||
RunLaunchCompleteTask();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void PluginProcessParent::OnChannelConnected(int32_t peer_pid) {
|
||||
#ifdef XP_WIN
|
||||
mChildPid = static_cast<uint32_t>(peer_pid);
|
||||
if (!sPidSet) {
|
||||
sPidSet = new PluginProcessParent::PidSet();
|
||||
}
|
||||
sPidSet->Insert(mChildPid);
|
||||
#endif
|
||||
|
||||
GeckoChildProcessHost::OnChannelConnected(peer_pid);
|
||||
}
|
||||
|
||||
void PluginProcessParent::OnChannelError() {
|
||||
GeckoChildProcessHost::OnChannelError();
|
||||
}
|
||||
|
||||
bool PluginProcessParent::IsConnected() {
|
||||
mozilla::MonitorAutoLock lock(mMonitor);
|
||||
return mProcessState == PROCESS_CONNECTED;
|
||||
}
|
||||
|
||||
bool PluginProcessParent::IsPluginProcessId(base::ProcessId procId) {
|
||||
#ifdef XP_WIN
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
return sPidSet && sPidSet->Contains(static_cast<uint32_t>(procId));
|
||||
#else
|
||||
NS_ERROR("IsPluginProcessId not available on this platform.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 dom_plugins_PluginProcessParent_h
|
||||
#define dom_plugins_PluginProcessParent_h 1
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "base/basictypes.h"
|
||||
|
||||
#include "base/file_path.h"
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
#include "chrome/common/child_process_host.h"
|
||||
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# include "nsTHashSet.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
class LaunchCompleteTask : public Runnable {
|
||||
public:
|
||||
LaunchCompleteTask()
|
||||
: Runnable("plugins::LaunchCompleteTask"), mLaunchSucceeded(false) {}
|
||||
|
||||
void SetLaunchSucceeded() { mLaunchSucceeded = true; }
|
||||
|
||||
protected:
|
||||
bool mLaunchSucceeded;
|
||||
};
|
||||
|
||||
class PluginProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
|
||||
public:
|
||||
explicit PluginProcessParent(const std::string& aPluginFilePath);
|
||||
|
||||
/**
|
||||
* Launch the plugin process. If the process fails to launch,
|
||||
* this method will return false.
|
||||
*
|
||||
* @param aLaunchCompleteTask Task that is executed on the main
|
||||
* thread once the asynchonous launch has completed.
|
||||
* @param aSandboxLevel Determines the strength of the sandbox.
|
||||
* <= 0 means no sandbox.
|
||||
* @param aIsSandboxLoggingEnabled Indicates if sandbox violation
|
||||
* logging should be enabled for the plugin process.
|
||||
*/
|
||||
bool Launch(UniquePtr<LaunchCompleteTask> aLaunchCompleteTask =
|
||||
UniquePtr<LaunchCompleteTask>(),
|
||||
int32_t aSandboxLevel = 0, bool aIsSandboxLoggingEnabled = false);
|
||||
|
||||
virtual bool CanShutdown() override { return true; }
|
||||
|
||||
const std::string& GetPluginFilePath() { return mPluginFilePath; }
|
||||
|
||||
using mozilla::ipc::GeckoChildProcessHost::GetChannel;
|
||||
|
||||
virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0) override;
|
||||
|
||||
virtual void OnChannelConnected(int32_t peer_pid) override;
|
||||
virtual void OnChannelError() override;
|
||||
|
||||
bool IsConnected();
|
||||
|
||||
static bool IsPluginProcessId(base::ProcessId procId);
|
||||
|
||||
private:
|
||||
~PluginProcessParent();
|
||||
|
||||
void RunLaunchCompleteTask();
|
||||
|
||||
std::string mPluginFilePath;
|
||||
ipc::TaskFactory<PluginProcessParent> mTaskFactory;
|
||||
UniquePtr<LaunchCompleteTask> mLaunchCompleteTask;
|
||||
MessageLoop* mMainMsgLoop;
|
||||
#ifdef XP_WIN
|
||||
typedef nsTHashSet<uint32_t> PidSet;
|
||||
// Set of PIDs for all plugin child processes or NULL if empty.
|
||||
static PidSet* sPidSet;
|
||||
uint32_t mChildPid;
|
||||
#endif
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
|
||||
};
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ifndef dom_plugins_PluginProcessParent_h
|
|
@ -1,54 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 "PluginQuirks.h"
|
||||
|
||||
#include "nsPluginHost.h"
|
||||
|
||||
namespace mozilla::plugins {
|
||||
|
||||
int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType,
|
||||
const nsCString& aPluginFilename) {
|
||||
int quirks = 0;
|
||||
|
||||
nsPluginHost::SpecialType specialType =
|
||||
nsPluginHost::GetSpecialType(aMimeType);
|
||||
|
||||
if (specialType == nsPluginHost::eSpecialType_Flash) {
|
||||
quirks |= QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN;
|
||||
#ifdef OS_WIN
|
||||
quirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
|
||||
quirks |= QUIRK_FLASH_THROTTLE_WMUSER_EVENTS;
|
||||
quirks |= QUIRK_FLASH_HOOK_SETLONGPTR;
|
||||
quirks |= QUIRK_FLASH_HOOK_GETWINDOWINFO;
|
||||
quirks |= QUIRK_FLASH_FIXUP_MOUSE_CAPTURE;
|
||||
quirks |= QUIRK_WINLESS_HOOK_IME;
|
||||
# if defined(_M_X64) || defined(__x86_64__)
|
||||
quirks |= QUIRK_FLASH_HOOK_GETKEYSTATE;
|
||||
quirks |= QUIRK_FLASH_HOOK_PRINTDLGW;
|
||||
quirks |= QUIRK_FLASH_HOOK_SSL;
|
||||
quirks |= QUIRK_FLASH_HOOK_CREATEMUTEXW;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
// Whitelist Flash to support offline renderer.
|
||||
if (specialType == nsPluginHost::eSpecialType_Flash) {
|
||||
quirks |= QUIRK_ALLOW_OFFLINE_RENDERER;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_WIN
|
||||
if (specialType == nsPluginHost::eSpecialType_Test) {
|
||||
quirks |= QUIRK_WINLESS_HOOK_IME;
|
||||
}
|
||||
#endif
|
||||
|
||||
return quirks;
|
||||
}
|
||||
|
||||
} // namespace mozilla::plugins
|
|
@ -1,64 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=4 et :
|
||||
* 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 dom_plugins_PluginQuirks_h
|
||||
#define dom_plugins_PluginQuirks_h
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
|
||||
// Quirks mode support for various plugin mime types
|
||||
enum PluginQuirks {
|
||||
QUIRKS_NOT_INITIALIZED = 0,
|
||||
// Win32: Hook TrackPopupMenu api so that we can swap out parent
|
||||
// hwnds. The api will fail with parents not associated with our
|
||||
// child ui thread. See WinlessHandleEvent for details.
|
||||
QUIRK_WINLESS_TRACKPOPUP_HOOK = 1 << 1,
|
||||
// Win32: Throttle flash WM_USER+1 heart beat messages to prevent
|
||||
// flooding chromium's dispatch loop, which can cause ipc traffic
|
||||
// processing lag.
|
||||
QUIRK_FLASH_THROTTLE_WMUSER_EVENTS = 1 << 2,
|
||||
// Win32: Catch resets on our subclass by hooking SetWindowLong.
|
||||
QUIRK_FLASH_HOOK_SETLONGPTR = 1 << 3,
|
||||
// X11: Work around a bug in Flash up to 10.1 d51 at least, where
|
||||
// expose event top left coordinates within the plugin-rect and
|
||||
// not at the drawable origin are misinterpreted.
|
||||
QUIRK_FLASH_EXPOSE_COORD_TRANSLATION = 1 << 4,
|
||||
// Win32: Catch get window info calls on the browser and tweak the
|
||||
// results so mouse input works when flash is displaying it's settings
|
||||
// window.
|
||||
QUIRK_FLASH_HOOK_GETWINDOWINFO = 1 << 5,
|
||||
// Win: Addresses a flash bug with mouse capture and full screen
|
||||
// windows.
|
||||
QUIRK_FLASH_FIXUP_MOUSE_CAPTURE = 1 << 6,
|
||||
// Mac: Allow the plugin to use offline renderer mode.
|
||||
// Use this only if the plugin is certified the support the offline renderer.
|
||||
QUIRK_ALLOW_OFFLINE_RENDERER = 1 << 9,
|
||||
// Work around a Flash bug where it fails to check the error code of a
|
||||
// NPN_GetValue(NPNVdocumentOrigin) call before trying to dereference
|
||||
// its char* output.
|
||||
QUIRK_FLASH_RETURN_EMPTY_DOCUMENT_ORIGIN = 1 << 10,
|
||||
// Win: Hook IMM32 API to handle IME event on windowless plugin
|
||||
QUIRK_WINLESS_HOOK_IME = 1 << 12,
|
||||
// Win: Hook GetKeyState to get keyboard state on sandbox process
|
||||
QUIRK_FLASH_HOOK_GETKEYSTATE = 1 << 13,
|
||||
// Win: Hook PrintDlgW to show print settings dialog on sandbox process
|
||||
QUIRK_FLASH_HOOK_PRINTDLGW = 1 << 14,
|
||||
// Win: Broker Win32 SSL operations
|
||||
QUIRK_FLASH_HOOK_SSL = 1 << 15,
|
||||
// Win: Hook CreateMutexW for brokering when using the camera
|
||||
QUIRK_FLASH_HOOK_CREATEMUTEXW = 1 << 16,
|
||||
};
|
||||
|
||||
int GetQuirksFromMimeTypeAndFilename(const nsCString& aMimeType,
|
||||
const nsCString& aPluginFilename);
|
||||
|
||||
} /* namespace plugins */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif // ifndef dom_plugins_PluginQuirks_h
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче