mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 998863: Asynchronous Plugin Initialization, Part 2: dom/plugins/base changes; r=johns,josh
This commit is contained in:
parent
7705475b25
commit
f0b2e92d9e
@ -523,7 +523,7 @@ nsNPAPIPluginInstance::Start()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return newResult;
|
||||
}
|
||||
|
||||
nsresult nsNPAPIPluginInstance::SetWindow(NPWindow* window)
|
||||
|
@ -331,20 +331,32 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsPluginStreamListenerPeer* streamPe
|
||||
|
||||
if (error != NPERR_NO_ERROR)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
switch(streamType)
|
||||
|
||||
if (streamType == nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN) {
|
||||
SuspendRequest();
|
||||
} else if (!SetStreamType(streamType, false)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsNPAPIPluginStreamListener::SetStreamType(uint16_t aType, bool aNeedsResume)
|
||||
{
|
||||
switch(aType)
|
||||
{
|
||||
case NP_NORMAL:
|
||||
mStreamType = NP_NORMAL;
|
||||
mStreamType = NP_NORMAL;
|
||||
break;
|
||||
case NP_ASFILEONLY:
|
||||
mStreamType = NP_ASFILEONLY;
|
||||
mStreamType = NP_ASFILEONLY;
|
||||
break;
|
||||
case NP_ASFILE:
|
||||
mStreamType = NP_ASFILE;
|
||||
mStreamType = NP_ASFILE;
|
||||
break;
|
||||
case NP_SEEK:
|
||||
mStreamType = NP_SEEK;
|
||||
mStreamType = NP_SEEK;
|
||||
// Seekable streams should continue to exist even after OnStopRequest
|
||||
// is fired, so we AddRef ourself an extra time and Release when the
|
||||
// plugin calls NPN_DestroyStream (CleanUpStream). If the plugin never
|
||||
@ -353,11 +365,16 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsPluginStreamListenerPeer* streamPe
|
||||
NS_ADDREF_THIS();
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_FAILURE;
|
||||
return false;
|
||||
}
|
||||
|
||||
mStreamStarted = true;
|
||||
return NS_OK;
|
||||
if (aNeedsResume) {
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->OnStreamTypeSet(mStreamType);
|
||||
}
|
||||
ResumeRequest();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -369,18 +386,20 @@ nsNPAPIPluginStreamListener::SuspendRequest()
|
||||
nsresult rv = StartDataPump();
|
||||
if (NS_FAILED(rv))
|
||||
return;
|
||||
|
||||
|
||||
mIsSuspended = true;
|
||||
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->SuspendRequests();
|
||||
mStreamListenerPeer->SuspendRequests();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsNPAPIPluginStreamListener::ResumeRequest()
|
||||
{
|
||||
mStreamListenerPeer->ResumeRequests();
|
||||
if (mStreamListenerPeer) {
|
||||
mStreamListenerPeer->ResumeRequests();
|
||||
}
|
||||
mIsSuspended = false;
|
||||
}
|
||||
|
||||
@ -390,7 +409,7 @@ nsNPAPIPluginStreamListener::StartDataPump()
|
||||
nsresult rv;
|
||||
mDataPumpTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
||||
// Start pumping data to the plugin every 100ms until it obeys and
|
||||
// eats the data.
|
||||
return mDataPumpTimer->InitWithCallback(this, 100,
|
||||
|
@ -83,6 +83,7 @@ public:
|
||||
nsresult OnStopBinding(nsPluginStreamListenerPeer* streamPeer,
|
||||
nsresult status);
|
||||
nsresult GetStreamType(int32_t *result);
|
||||
bool SetStreamType(uint16_t aType, bool aNeedsResume = true);
|
||||
|
||||
bool IsStarted();
|
||||
nsresult CleanUpStream(NPReason reason);
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsPluginStreamListenerPeer.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/LoadInfo.h"
|
||||
#include "mozilla/plugins/PluginAsyncSurrogate.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -110,6 +111,7 @@
|
||||
using namespace mozilla;
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::plugins::PluginTag;
|
||||
using mozilla::plugins::PluginAsyncSurrogate;
|
||||
|
||||
// Null out a strong ref to a linked list iteratively to avoid
|
||||
// exhausting the stack (bug 486349).
|
||||
@ -830,6 +832,7 @@ nsPluginHost::InstantiatePluginInstance(const char *aMimeType, nsIURI* aURL,
|
||||
if (NS_FAILED(rv)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
const bool isAsyncInit = (rv == NS_PLUGIN_INIT_PENDING);
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> instance;
|
||||
rv = instanceOwner->GetInstance(getter_AddRefs(instance));
|
||||
@ -837,11 +840,9 @@ nsPluginHost::InstantiatePluginInstance(const char *aMimeType, nsIURI* aURL,
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (instance) {
|
||||
instanceOwner->CreateWidget();
|
||||
|
||||
// If we've got a native window, the let the plugin know about it.
|
||||
instanceOwner->CallSetWindow();
|
||||
// Async init plugins will initiate their own widget creation.
|
||||
if (!isAsyncInit && instance) {
|
||||
CreateWidget(instanceOwner);
|
||||
}
|
||||
|
||||
// At this point we consider instantiation to be successful. Do not return an error.
|
||||
@ -3327,6 +3328,14 @@ nsresult nsPluginHost::NewPluginStreamListener(nsIURI* aURI,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsPluginHost::CreateWidget(nsPluginInstanceOwner* aOwner)
|
||||
{
|
||||
aOwner->CreateWidget();
|
||||
|
||||
// If we've got a native window, the let the plugin know about it.
|
||||
aOwner->CallSetWindow();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
const char16_t *someData)
|
||||
@ -3954,6 +3963,12 @@ PluginDestructionGuard::PluginDestructionGuard(nsNPAPIPluginInstance *aInstance)
|
||||
Init();
|
||||
}
|
||||
|
||||
PluginDestructionGuard::PluginDestructionGuard(PluginAsyncSurrogate *aSurrogate)
|
||||
: mInstance(static_cast<nsNPAPIPluginInstance*>(aSurrogate->GetNPP()->ndata))
|
||||
{
|
||||
InitAsync();
|
||||
}
|
||||
|
||||
PluginDestructionGuard::PluginDestructionGuard(NPP npp)
|
||||
: mInstance(npp ? static_cast<nsNPAPIPluginInstance*>(npp->ndata) : nullptr)
|
||||
{
|
||||
|
@ -30,6 +30,12 @@
|
||||
#include "nsCRT.h"
|
||||
#include "mozilla/plugins/PluginTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace plugins {
|
||||
class PluginAsyncSurrogate;
|
||||
} // namespace mozilla
|
||||
} // namespace plugins
|
||||
|
||||
class nsNPAPIPlugin;
|
||||
class nsIComponentManager;
|
||||
class nsIFile;
|
||||
@ -203,6 +209,8 @@ public:
|
||||
nsNPAPIPluginInstance* aInstance,
|
||||
nsIStreamListener **aStreamListener);
|
||||
|
||||
void CreateWidget(nsPluginInstanceOwner* aOwner);
|
||||
|
||||
private:
|
||||
friend class nsPluginUnloadRunnable;
|
||||
|
||||
@ -333,11 +341,11 @@ private:
|
||||
static nsPluginHost* sInst;
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS PluginDestructionGuard : protected PRCList
|
||||
class PluginDestructionGuard : protected PRCList
|
||||
{
|
||||
public:
|
||||
explicit PluginDestructionGuard(nsNPAPIPluginInstance *aInstance);
|
||||
|
||||
explicit PluginDestructionGuard(mozilla::plugins::PluginAsyncSurrogate *aSurrogate);
|
||||
explicit PluginDestructionGuard(NPP npp);
|
||||
|
||||
~PluginDestructionGuard();
|
||||
@ -355,6 +363,18 @@ protected:
|
||||
PR_INSERT_BEFORE(this, &sListHead);
|
||||
}
|
||||
|
||||
void InitAsync()
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread");
|
||||
|
||||
mDelayedDestroy = false;
|
||||
|
||||
PR_INIT_CLIST(this);
|
||||
// Instances with active surrogates must be inserted *after* sListHead so
|
||||
// that they appear to be at the bottom of the stack
|
||||
PR_INSERT_AFTER(this, &sListHead);
|
||||
}
|
||||
|
||||
nsRefPtr<nsNPAPIPluginInstance> mInstance;
|
||||
bool mDelayedDestroy;
|
||||
|
||||
|
@ -1452,6 +1452,28 @@ void nsPluginInstanceOwner::ExitFullScreen(jobject view) {
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
nsPluginInstanceOwner::NotifyHostAsyncInitFailed()
|
||||
{
|
||||
nsCOMPtr<nsIObjectLoadingContent> content = do_QueryInterface(mContent);
|
||||
content->StopPluginInstance();
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginInstanceOwner::NotifyHostCreateWidget()
|
||||
{
|
||||
mPluginHost->CreateWidget(this);
|
||||
#ifdef XP_MACOSX
|
||||
FixUpPluginWindow(ePluginPaintEnable);
|
||||
#else
|
||||
if (mPluginFrame) {
|
||||
mPluginFrame->InvalidateFrame();
|
||||
} else {
|
||||
CallSetWindow();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_ANDROID
|
||||
@ -3169,6 +3191,10 @@ nsPluginInstanceOwner::UpdateDocumentActiveState(bool aIsActive)
|
||||
NS_IMETHODIMP
|
||||
nsPluginInstanceOwner::CallSetWindow()
|
||||
{
|
||||
if (!mWidgetCreationComplete) {
|
||||
// No widget yet, we can't run this code
|
||||
return NS_OK;
|
||||
}
|
||||
if (mPluginFrame) {
|
||||
mPluginFrame->CallSetWindow(false);
|
||||
} else if (mInstance) {
|
||||
|
@ -255,7 +255,10 @@ public:
|
||||
// Called from AndroidJNI when we removed the fullscreen view.
|
||||
static void ExitFullScreen(jobject view);
|
||||
#endif
|
||||
|
||||
|
||||
void NotifyHostAsyncInitFailed();
|
||||
void NotifyHostCreateWidget();
|
||||
|
||||
private:
|
||||
virtual ~nsPluginInstanceOwner();
|
||||
|
||||
|
@ -266,6 +266,7 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
|
||||
mHaveFiredOnStartRequest = false;
|
||||
mDataForwardToRequest = nullptr;
|
||||
|
||||
mUseLocalCache = false;
|
||||
mSeekable = false;
|
||||
mModified = 0;
|
||||
mStreamOffset = 0;
|
||||
@ -533,7 +534,9 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
|
||||
|
||||
// Set up the stream listener...
|
||||
rv = SetUpStreamListener(request, aURL);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -1046,8 +1049,6 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
|
||||
|
||||
mPStreamListener->SetStreamListenerPeer(this);
|
||||
|
||||
bool useLocalCache = false;
|
||||
|
||||
// get httpChannel to retrieve some info we need for nsIPluginStreamInfo setup
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
||||
@ -1103,7 +1104,7 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
|
||||
nsAutoCString contentEncoding;
|
||||
if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"),
|
||||
contentEncoding))) {
|
||||
useLocalCache = true;
|
||||
mUseLocalCache = true;
|
||||
} else {
|
||||
// set seekability (seekable if the stream has a known length and if the
|
||||
// http server accepts byte ranges).
|
||||
@ -1132,6 +1133,9 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRequest);
|
||||
mRequest = request;
|
||||
|
||||
rv = mPStreamListener->OnStartBinding(this);
|
||||
|
||||
mStartBinding = true;
|
||||
@ -1139,23 +1143,37 @@ nsresult nsPluginStreamListenerPeer::SetUpStreamListener(nsIRequest *request,
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mPStreamListener->GetStreamType(&mStreamType);
|
||||
int32_t streamType = NP_NORMAL;
|
||||
mPStreamListener->GetStreamType(&streamType);
|
||||
|
||||
if (!useLocalCache && mStreamType >= NP_ASFILE) {
|
||||
// check it out if this is not a file channel.
|
||||
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(request);
|
||||
if (!fileChannel) {
|
||||
useLocalCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (useLocalCache) {
|
||||
SetupPluginCacheFile(channel);
|
||||
if (streamType != STREAM_TYPE_UNKNOWN) {
|
||||
OnStreamTypeSet(streamType);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginStreamListenerPeer::OnStreamTypeSet(const int32_t aStreamType)
|
||||
{
|
||||
MOZ_ASSERT(mRequest);
|
||||
mStreamType = aStreamType;
|
||||
if (!mUseLocalCache && mStreamType >= NP_ASFILE) {
|
||||
// check it out if this is not a file channel.
|
||||
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(mRequest);
|
||||
if (!fileChannel) {
|
||||
mUseLocalCache = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (mUseLocalCache) {
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(mRequest);
|
||||
SetupPluginCacheFile(channel);
|
||||
}
|
||||
}
|
||||
|
||||
const int32_t nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN = UINT16_MAX;
|
||||
|
||||
nsresult
|
||||
nsPluginStreamListenerPeer::OnFileAvailable(nsIFile* aFile)
|
||||
{
|
||||
|
@ -128,6 +128,11 @@ public:
|
||||
requestsCopy[i]->Resume();
|
||||
}
|
||||
|
||||
// Called by nsNPAPIPluginStreamListener
|
||||
void OnStreamTypeSet(const int32_t aStreamType);
|
||||
|
||||
static const int32_t STREAM_TYPE_UNKNOWN;
|
||||
|
||||
private:
|
||||
nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL);
|
||||
nsresult SetupPluginCacheFile(nsIChannel* channel);
|
||||
@ -159,6 +164,8 @@ private:
|
||||
nsDataHashtable<nsUint32HashKey, uint32_t>* mDataForwardToRequest;
|
||||
|
||||
nsCString mContentType;
|
||||
bool mUseLocalCache;
|
||||
nsCOMPtr<nsIRequest> mRequest;
|
||||
bool mSeekable;
|
||||
uint32_t mModified;
|
||||
nsRefPtr<nsNPAPIPluginInstance> mPluginInstance;
|
||||
|
@ -330,6 +330,7 @@
|
||||
ERROR(NS_ERROR_PLUGIN_BLOCKLISTED, FAILURE(1002)),
|
||||
ERROR(NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED, FAILURE(1003)),
|
||||
ERROR(NS_ERROR_PLUGIN_CLICKTOPLAY, FAILURE(1004)),
|
||||
ERROR(NS_PLUGIN_INIT_PENDING, SUCCESS(1005)),
|
||||
#undef MODULE
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user