author | John Schoenick <jschoenick@mozilla.com> |
Thu, 06 Dec 2012 15:10:54 -0800 | |
changeset 115981 | 1b68ff48e22c35a471bfed05e8222929399a9b53 |
parent 115980 | 6aed5f5caecb8eb5fe6fb610d70bf08452e52587 |
child 115982 | 11341616d7cb84252fe339b8e1bec3b2ae3dd3c3 |
push id | 24034 |
push user | emorley@mozilla.com |
push date | Fri, 14 Dec 2012 15:28:57 +0000 |
treeherder | autoland@50d8f411d305 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | josh |
bugs | 767633 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -527,16 +527,45 @@ IsPluginEnabledForType(const nsCString& return NS_OK; } /// /// Member Functions /// +// Tedious syntax to create a plugin stream listener with checks and put it in +// mFinalListener +bool +nsObjectLoadingContent::MakePluginListener() +{ + if (!mInstanceOwner) { + NS_NOTREACHED("expecting a spawned plugin"); + return false; + } + nsRefPtr<nsPluginHost> pluginHost = + already_AddRefed<nsPluginHost>(nsPluginHost::GetInst()); + if (!pluginHost) { + NS_NOTREACHED("No pluginHost"); + return false; + } + NS_ASSERTION(!mFinalListener, "overwriting a final listener"); + nsresult rv; + nsRefPtr<nsNPAPIPluginInstance> inst; + nsCOMPtr<nsIStreamListener> finalListener; + rv = mInstanceOwner->GetInstance(getter_AddRefs(inst)); + NS_ENSURE_SUCCESS(rv, false); + rv = pluginHost->NewEmbeddedPluginStreamListener(mURI, inst, + getter_AddRefs(finalListener)); + NS_ENSURE_SUCCESS(rv, false); + mFinalListener = finalListener; + return true; +} + + bool nsObjectLoadingContent::IsSupportedDocument(const nsCString& aMimeType) { nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); NS_ASSERTION(thisContent, "must be a content"); nsCOMPtr<nsIWebNavigationInfo> info( @@ -651,22 +680,28 @@ nsObjectLoadingContent::~nsObjectLoading // object... NS_NOTREACHED("Should not be tearing down a plugin at this point!"); StopPluginInstance(); } DestroyImageLoadingContent(); } nsresult -nsObjectLoadingContent::InstantiatePluginInstance() +nsObjectLoadingContent::InstantiatePluginInstance(bool aIsLoading) { - if (mInstanceOwner || mType != eType_Plugin || mIsLoading || mInstantiating) { + 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)); nsIDocument* doc = thisContent->GetCurrentDoc(); if (!doc || !InActiveDocument(thisContent)) { @@ -758,16 +793,29 @@ nsObjectLoadingContent::InstantiatePlugi nsCOMPtr<nsIRunnable> ev = new nsSimplePluginEvent(thisContent, NS_LITERAL_STRING("PluginOutdated")); 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"); + if (MakePluginListener()) { + // We intentionally ignore errors here, leaving it up to the plugin to + // deal with not having an initial stream. + OpenChannel(); + } + } } return NS_OK; } void nsObjectLoadingContent::NotifyOwnerDocumentActivityChanged() { @@ -783,29 +831,42 @@ nsObjectLoadingContent::NotifyOwnerDocum } } // nsIRequestObserver NS_IMETHODIMP nsObjectLoadingContent::OnStartRequest(nsIRequest *aRequest, nsISupports *aContext) { - /// This must call LoadObject, even upon failure, to allow it to either - /// proceed with the load, or trigger fallback content. - SAMPLE_LABEL("nsObjectLoadingContent", "OnStartRequest"); LOG(("OBJLC [%p]: Channel OnStartRequest", this)); if (aRequest != mChannel || !aRequest) { // happens when a new load starts before the previous one got here return NS_BINDING_ABORTED; } NS_ASSERTION(!mChannelLoaded, "mChannelLoaded set already?"); + // If we already switched to type plugin, this channel can just be passed to + // the final listener. + if (mType == eType_Plugin) { + if (!mInstanceOwner || !mFinalListener) { + // We drop mChannel when stopping plugins, so something is wrong + NS_NOTREACHED("Opened a channel in plugin mode, but don't have a plugin"); + return NS_BINDING_ABORTED; + } + return mFinalListener->OnStartRequest(aRequest, nullptr); + } + + // Otherwise we should be state loading, and call LoadObject with the channel + if (mType != eType_Loading) { + NS_NOTREACHED("Should be type loading at this point"); + return NS_BINDING_ABORTED; + } NS_ASSERTION(!mFinalListener, "mFinalListener exists already?"); mChannelLoaded = true; nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest)); NS_ASSERTION(chan, "Why is our request not a channel?"); nsCOMPtr<nsIURI> uri; @@ -1621,30 +1682,25 @@ nsObjectLoadingContent::LoadObject(bool } // // Security checks // if (mType != eType_Null) { int16_t contentPolicy = nsIContentPolicy::ACCEPT; - bool allowLoad = false; - // We check load policy before opening a channel, and process policy before - // going ahead with any final-type load - if (mType == eType_Loading) { - nsCOMPtr<nsIScriptSecurityManager> secMan = - nsContentUtils::GetSecurityManager(); - if (!secMan) { - NS_NOTREACHED("No security manager?"); - } else { - rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), - mURI, 0); - allowLoad = NS_SUCCEEDED(rv) && CheckLoadPolicy(&contentPolicy); - } - } else { + bool allowLoad = true; + // If mChannelLoaded is set we presumably already passed load policy + if (mURI && !mChannelLoaded) { + allowLoad = CheckLoadPolicy(&contentPolicy); + } + // If we're loading a type now, check ProcessPolicy. Note that we may check + // both now in the case of plugins whose type is determined before opening a + // channel. + if (allowLoad && mType != eType_Loading) { allowLoad = CheckProcessPolicy(&contentPolicy); } // Content policy implementations can mutate the DOM, check for re-entry if (!mIsLoading) { LOG(("OBJLC [%p]: We re-entered in content policy, leaving original load", this)); return NS_OK; @@ -1710,55 +1766,49 @@ nsObjectLoadingContent::LoadObject(bool /// /// Attempt to load new type /// // We don't set mFinalListener until OnStartRequest has been called, to // prevent re-entry ugliness with CloseChannel() nsCOMPtr<nsIStreamListener> finalListener; + // If we decide to synchronously spawn a plugin, we do it after firing + // notifications to avoid re-entry causing notifications to fire out of order. + bool doSpawnPlugin = false; switch (mType) { case eType_Image: if (!mChannel) { // We have a LoadImage() call, but UpdateObjectParameters requires a // channel for images, so this is not a valid state. NS_NOTREACHED("Attempting to load image without a channel?"); rv = NS_ERROR_UNEXPECTED; break; } rv = LoadImageWithChannel(mChannel, getter_AddRefs(finalListener)); // finalListener will receive OnStartRequest below break; case eType_Plugin: { if (mChannel) { - nsRefPtr<nsPluginHost> pluginHost = - already_AddRefed<nsPluginHost>(nsPluginHost::GetInst()); - if (!pluginHost) { - NS_NOTREACHED("No pluginHost"); - rv = NS_ERROR_UNEXPECTED; - break; - } - // Force a sync state change now, we need the frame created NotifyStateChanged(oldType, oldState, true, aNotify); oldType = mType; oldState = ObjectState(); if (!thisContent->GetPrimaryFrame()) { // We're un-rendered, and can't instantiate a plugin. HasNewFrame will // re-start us when we can proceed. LOG(("OBJLC [%p]: Aborting load - plugin-type, but no frame", this)); CloseChannel(); break; } - rv = pluginHost->NewEmbeddedPluginStreamListener(mURI, this, nullptr, - getter_AddRefs(finalListener)); - // finalListener will receive OnStartRequest below + // We'll handle this below + doSpawnPlugin = true; } else { rv = AsyncStartPluginInstance(); } } break; case eType_Document: { if (!mChannel) { @@ -1843,61 +1893,69 @@ nsObjectLoadingContent::LoadObject(bool NS_ASSERTION(!mFrameLoader && !mInstanceOwner, "switched to type null but also loaded something"); if (mChannel) { // If we were loading with a channel but then failed over, throw it away CloseChannel(); } - // Don't try to initialize final listener below + // Don't try to initialize plugins or final listener below + doSpawnPlugin = false; finalListener = nullptr; // Don't notify, as LoadFallback doesn't know of our previous state // (so really this is just setting mFallbackType) LoadFallback(fallbackType, false); } // Notify of our final state NotifyStateChanged(oldType, oldState, false, aNotify); + NS_ENSURE_TRUE(mIsLoading, NS_OK); + // - // Pass load on to finalListener if loading with a channel. + // Spawning plugins and dispatching to the final listener may re-enter, so are + // delayed until after we fire a notification, to prevent missing + // notifications or firing them out of order. // - // We do this after finishing our notification such that re-entrance doesn't - // skip notifications or fire them out of order. + // Note that we ensured that we entered into LoadObject() from + // ::OnStartRequest above when loading with a channel. // - if (!mIsLoading) { - LOG(("OBJLC [%p]: Re-entered before dispatching to final listener", this)); + rv = NS_OK; + if (doSpawnPlugin) { + rv = InstantiatePluginInstance(true); + NS_ENSURE_TRUE(mIsLoading, NS_OK); + // Create the final listener if we're loading with a channel. We can't do + // this in the loading block above as it requires an instance. + if (aLoadingChannel && NS_SUCCEEDED(rv)) { + // Plugins can continue to run even if their initial stream dies. Some + // plugins will even return failure codes to reject the stream, but expect + // to continue running, so ignore the error code. rv is thus the result of + // spawning the plugin above + if (NS_SUCCEEDED(rv) && MakePluginListener()) { + mFinalListener->OnStartRequest(mChannel, nullptr); + } + } } else if (finalListener) { NS_ASSERTION(mType != eType_Null && mType != eType_Loading, "We should not have a final listener with a non-loaded type"); - // Note that we always enter into LoadObject() from ::OnStartRequest when - // loading with a channel. - mSrcStreamLoading = true; - // Remove blocker on entering into instantiate - // (this is otherwise unset by the stack class) - mIsLoading = false; mFinalListener = finalListener; rv = finalListener->OnStartRequest(mChannel, nullptr); - mSrcStreamLoading = false; - if (NS_FAILED(rv)) { - // Failed to load new content, but since we've already notified of our - // transition, we can just Unload and call LoadFallback (which will notify - // again) - mType = eType_Null; - // This could *also* technically re-enter if OnStartRequest fails after - // spawning a plugin. - mIsLoading = true; - UnloadObject(false); - NS_ENSURE_TRUE(mIsLoading, NS_OK); - CloseChannel(); - LoadFallback(fallbackType, true); - } + } + + if (NS_FAILED(rv) && mIsLoading) { + // Since we've already notified of our transition, we can just Unload and + // call LoadFallback (which will notify again) + mType = eType_Null; + UnloadObject(false); + NS_ENSURE_TRUE(mIsLoading, NS_OK); + CloseChannel(); + LoadFallback(fallbackType, true); } return NS_OK; } // This call can re-enter when dealing with plugin listeners nsresult nsObjectLoadingContent::CloseChannel() @@ -1917,32 +1975,35 @@ nsObjectLoadingContent::CloseChannel() } } return NS_OK; } nsresult nsObjectLoadingContent::OpenChannel() { - nsCOMPtr<nsIContent> thisContent = + nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); + nsCOMPtr<nsIScriptSecurityManager> secMan = + nsContentUtils::GetSecurityManager(); NS_ASSERTION(thisContent, "must be a content"); nsIDocument* doc = thisContent->OwnerDoc(); NS_ASSERTION(doc, "No owner document?"); - NS_ASSERTION(!mInstanceOwner && !mInstantiating, - "opening a new channel with already loaded content"); nsresult rv; mChannel = nullptr; // E.g. mms:// if (!mURI || !CanHandleURI(mURI)) { return NS_ERROR_NOT_AVAILABLE; } + rv = secMan->CheckLoadURIWithPrincipal(thisContent->NodePrincipal(), mURI, 0); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsILoadGroup> group = doc->GetDocumentLoadGroup(); nsCOMPtr<nsIChannel> chan; nsCOMPtr<nsIChannelPolicy> channelPolicy; nsCOMPtr<nsIContentSecurityPolicy> csp; rv = doc->NodePrincipal()->GetCsp(getter_AddRefs(csp)); NS_ENSURE_SUCCESS(rv, rv); if (csp) { channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
--- a/content/base/src/nsObjectLoadingContent.h +++ b/content/base/src/nsObjectLoadingContent.h @@ -111,20 +111,23 @@ class nsObjectLoadingContent : public ns ObjectType Type() const { return mType; } void SetIsNetworkCreated(bool aNetworkCreated) { mNetworkCreated = aNetworkCreated; } /** - * Immediately instantiate a plugin instance. This is a no-op if - * mType != eType_Plugin or a plugin is already running. + * Immediately instantiate a plugin instance. This is a no-op if mType != + * eType_Plugin or a plugin is already running. + * + * aIsLoading indicates that we are in the loading code, and we can bypass + * the mIsLoading check. */ - nsresult InstantiatePluginInstance(); + nsresult InstantiatePluginInstance(bool aIsLoading = false); /** * Notify this class the document state has changed * Called by nsDocument so we may suspend plugins in inactive documents) */ void NotifyOwnerDocumentActivityChanged(); /** @@ -175,22 +178,21 @@ class nsObjectLoadingContent : public ns eSupportImages = 1u << 0, // Images are supported (imgILoader) eSupportPlugins = 1u << 1, // Plugins are supported (nsIPluginHost) eSupportDocuments = 1u << 2, // Documents are supported // (nsIDocumentLoaderFactory) // This flag always includes SVG eSupportSVG = 1u << 3, // SVG is supported (image/svg+xml) eSupportClassID = 1u << 4, // The classid attribute is supported - // Allows us to load a plugin if it matches a MIME type or file extension - // registered to a plugin without opening its specified URI first. Can - // result in launching plugins for URIs that return differing content - // types. Plugins without URIs may instantiate regardless. - // XXX(johns) this is our legacy behavior on <embed> tags, whereas object - // will always open a channel and check its MIME if a URI is present. + // If possible to get a *plugin* type from the type attribute *or* file + // extension, we can use that type and begin loading the plugin before + // opening a channel. + // A side effect of this is if the channel fails, the plugin is still + // running. eAllowPluginSkipChannel = 1u << 5 }; /** * Returns the list of capabilities this content node supports. This is a * bitmask consisting of flags from the Capabilities enum. * * The default implementation supports all types but not @@ -325,16 +327,22 @@ class nsObjectLoadingContent : public ns /** * Checks whether the given type is a supported document type * * NOTE Does not take content policy or capabilities into account */ bool IsSupportedDocument(const nsCString& aType); /** + * Gets the plugin instance and creates a plugin stream listener, assigning + * it to mFinalListener + */ + bool MakePluginListener(); + + /** * Unloads all content and resets the object to a completely unloaded state * * NOTE Calls StopPluginInstance() and may spin the event loop * * @param aResetState Reset the object type to 'loading' and destroy channel * as well */ void UnloadObject(bool aResetState = true); @@ -407,18 +415,19 @@ class nsObjectLoadingContent : public ns // Type of the currently-loaded content. ObjectType mType : 8; // The type of fallback content we're showing (see ObjectState()) FallbackType mFallbackType : 8; - // If true, the current load has finished opening a channel. Does not imply - // mChannel -- mChannelLoaded && !mChannel may occur for a load that failed + // If true, we have opened a channel as the listener and it has reached + // OnStartRequest. Does not get set for channels that are passed directly to + // the plugin listener. bool mChannelLoaded : 1; // Whether we are about to call instantiate on our frame. If we aren't, // SetFrame needs to asynchronously call Instantiate. bool mInstantiating : 1; // True when the object is created for an element which the parser has // created using NS_FROM_PARSER_NETWORK flag. If the element is modified,
--- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -3342,25 +3342,24 @@ nsPluginHost::StopPluginInstance(nsNPAPI mInstances.RemoveElement(aInstance); OnPluginInstanceDestroyed(pluginTag); } return NS_OK; } nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURI, - nsObjectLoadingContent *aContent, nsNPAPIPluginInstance* aInstance, nsIStreamListener **aStreamListener) { NS_ENSURE_ARG_POINTER(aURI); NS_ENSURE_ARG_POINTER(aStreamListener); nsRefPtr<nsPluginStreamListenerPeer> listener = new nsPluginStreamListenerPeer(); - nsresult rv = listener->InitializeEmbedded(aURI, aInstance, aContent); + nsresult rv = listener->InitializeEmbedded(aURI, aInstance); if (NS_FAILED(rv)) { return rv; } listener.forget(aStreamListener); return NS_OK; }
--- a/dom/plugins/base/nsPluginHost.h +++ b/dom/plugins/base/nsPluginHost.h @@ -194,17 +194,17 @@ public: nsPluginInstanceOwner **aOwner, nsIStreamListener **aStreamListener); // Does not accept NULL and should never fail. nsPluginTag* TagForPlugin(nsNPAPIPlugin* aPlugin); nsresult GetPlugin(const char *aMimeType, nsNPAPIPlugin** aPlugin); - nsresult NewEmbeddedPluginStreamListener(nsIURI* aURL, nsObjectLoadingContent *aContent, + nsresult NewEmbeddedPluginStreamListener(nsIURI* aURL, nsNPAPIPluginInstance* aInstance, nsIStreamListener **aStreamListener); nsresult NewFullPagePluginStreamListener(nsIURI* aURI, nsNPAPIPluginInstance *aInstance, nsIStreamListener **aStreamListener); private:
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp +++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp @@ -22,17 +22,17 @@ #include "nsPrintfCString.h" #include "nsIScriptGlobalObject.h" #include "nsIDocument.h" #include "nsIWebNavigation.h" #include "nsContentUtils.h" #include "nsNetUtil.h" #include "nsPluginNativeWindow.h" #include "sampler.h" -#include "nsObjectLoadingContent.h" +#include "nsPluginInstanceOwner.h" #define MAGIC_REQUEST_CONTEXT 0x01020304 // nsPluginByteRangeStreamListener class nsPluginByteRangeStreamListener : public nsIStreamListener , public nsIInterfaceRequestor @@ -341,49 +341,44 @@ nsresult nsPluginStreamListenerPeer::Ini mDataForwardToRequest = new nsHashtable(16, false); if (!mDataForwardToRequest) return NS_ERROR_FAILURE; return NS_OK; } nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL, - nsNPAPIPluginInstance* aInstance, - nsObjectLoadingContent *aContent) + nsNPAPIPluginInstance* aInstance) { #ifdef PLUGIN_LOGGING nsAutoCString urlSpec; aURL->GetSpec(urlSpec); - + PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NORMAL, ("nsPluginStreamListenerPeer::InitializeEmbedded url=%s\n", urlSpec.get())); - + PR_LogFlush(); #endif - // We have to have one or the other. - if (!aInstance && !aContent) { + // Not gonna work out + if (!aInstance) { return NS_ERROR_FAILURE; } mURL = aURL; - - if (aInstance) { - NS_ASSERTION(mPluginInstance == nullptr, "nsPluginStreamListenerPeer::InitializeEmbedded mPluginInstance != nullptr"); - mPluginInstance = aInstance; - } else { - mContent = aContent; - } - + + NS_ASSERTION(mPluginInstance == nullptr, "nsPluginStreamListenerPeer::InitializeEmbedded mPluginInstance != nullptr"); + mPluginInstance = aInstance; + mPendingRequests = 1; - + mDataForwardToRequest = new nsHashtable(16, false); if (!mDataForwardToRequest) return NS_ERROR_FAILURE; - + return NS_OK; } // Called by NewFullPagePluginStream() nsresult nsPluginStreamListenerPeer::InitializeFullPage(nsIURI* aURL, nsNPAPIPluginInstance *aInstance) { PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsPluginStreamListenerPeer::InitializeFullPage instance=%p\n",aInstance)); @@ -492,41 +487,41 @@ nsPluginStreamListenerPeer::OnStartReque nsresult rv = NS_OK; SAMPLE_LABEL("nsPluginStreamListenerPeer", "OnStartRequest"); if (mRequests.IndexOfObject(GetBaseRequest(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 bool bWantsAllNetworkStreams = false; // 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, &bWantsAllNetworkStreams); @@ -537,90 +532,76 @@ nsPluginStreamListenerPeer::OnStartReque } if (!bWantsAllNetworkStreams) { mRequestFailed = true; return NS_ERROR_FAILURE; } } } - + // 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 == -1) { // 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 = length; } - + nsAutoCString aContentType; // XXX but we already got the type above! rv = channel->GetContentType(aContentType); if (NS_FAILED(rv)) return rv; - + nsCOMPtr<nsIURI> aURL; rv = channel->GetURI(getter_AddRefs(aURL)); if (NS_FAILED(rv)) return rv; - + aURL->GetSpec(mURLSpec); - + if (!aContentType.IsEmpty()) mContentType = aContentType; - + #ifdef PLUGIN_LOGGING PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnStartRequest this=%p request=%p mime=%s, url=%s\n", this, request, aContentType.get(), mURLSpec.get())); - + PR_LogFlush(); #endif - // If we don't have an instance yet it means we weren't able to load - // a plugin previously because we didn't have the mimetype. Try again - // if we have a mime type now. - if (!mPluginInstance && mContent && !aContentType.IsEmpty()) { - nsObjectLoadingContent *olc = static_cast<nsObjectLoadingContent*>(mContent.get()); - rv = olc->InstantiatePluginInstance(); - if (NS_SUCCEEDED(rv)) { - rv = olc->GetPluginInstance(getter_AddRefs(mPluginInstance)); - if (NS_FAILED(rv)) { - return rv; - } - } - } - // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) return rv; - + return rv; } NS_IMETHODIMP nsPluginStreamListenerPeer::OnProgress(nsIRequest *request, nsISupports* aContext, uint64_t aProgress, uint64_t aProgressMax) {
--- a/dom/plugins/base/nsPluginStreamListenerPeer.h +++ b/dom/plugins/base/nsPluginStreamListenerPeer.h @@ -12,20 +12,18 @@ #include "nsIProgressEventSink.h" #include "nsIHttpHeaderVisitor.h" #include "nsWeakReference.h" #include "nsNPAPIPluginStreamListener.h" #include "nsHashtable.h" #include "nsNPAPIPluginInstance.h" #include "nsIInterfaceRequestor.h" #include "nsIChannelEventSink.h" -#include "nsIObjectLoadingContent.h" class nsIChannel; -class nsObjectLoadingContent; /** * 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 @@ -70,18 +68,17 @@ public: bool UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi); // Called by GetURL and PostURL (via NewStream) nsresult Initialize(nsIURI *aURL, nsNPAPIPluginInstance *aInstance, nsNPAPIPluginStreamListener *aListener); nsresult InitializeEmbedded(nsIURI *aURL, - nsNPAPIPluginInstance* aInstance, - nsObjectLoadingContent *aContent); + nsNPAPIPluginInstance* aInstance); nsresult InitializeFullPage(nsIURI* aURL, nsNPAPIPluginInstance *aInstance); nsresult OnFileAvailable(nsIFile* aFile); nsresult ServeStreamAsFile(nsIRequest *request, nsISupports *ctxt); nsNPAPIPluginInstance *GetPluginInstance() { return mPluginInstance; } @@ -135,17 +132,16 @@ public: private: nsresult SetUpStreamListener(nsIRequest* request, nsIURI* aURL); nsresult SetupPluginCacheFile(nsIChannel* channel); nsresult GetInterfaceGlobal(const nsIID& aIID, void** result); nsCOMPtr<nsIURI> mURL; nsCString mURLSpec; // Have to keep this member because GetURL hands out char* - nsCOMPtr<nsIObjectLoadingContent> mContent; nsRefPtr<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