nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request, nsISupports* aContext) { if (!mPluginInstance) return NS_ERROR_FAILURE; // mPluginInstance->Stop calls mPStreamListener->CleanUpStream(), so stream will be properly clean up mPluginInstance->Stop(); mPluginInstance->Start(); nsCOMPtr<nsIPluginInstanceOwner> owner; mPluginInstance->GetOwner(getter_AddRefs(owner)); if (owner) { NPWindow* window = nsnull; owner->GetWindow(window); #if defined(MOZ_WIDGET_GTK2) || defined(MOZ_WIDGET_QT) // Should call GetPluginPort() here. // This part is copied from nsPluginInstanceOwner::GetPluginPort(). nsCOMPtr<nsIWidget> widget; ((nsPluginNativeWindow*)window)->GetPluginWidget(getter_AddRefs(widget)); if (widget) { window->window = widget->GetNativeData(NS_NATIVE_PLUGIN_PORT); } #endif nsCOMPtr<nsIPluginInstanceOwner_MOZILLA_2_0_BRANCH> owner = do_QueryInterface(mOwner); if (owner) owner->SetWindow(); } mSeekable = PR_FALSE; mPStreamListener->OnStartBinding(this); mStreamOffset = 0; // force the plugin to use stream as file mStreamType = NP_ASFILE; // then check it out if browser cache is not available nsCOMPtr<nsICachingChannel> cacheChannel = do_QueryInterface(request); if (!(cacheChannel && (NS_SUCCEEDED(cacheChannel->SetCacheAsFile(PR_TRUE))))) { nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); if (channel) { SetupPluginCacheFile(channel); } } // unset mPendingRequests mPendingRequests = 0; 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); } }
nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request, nsISupports* aContext) { if (!mPluginInstance) return NS_ERROR_FAILURE; // mPluginInstance->Stop calls mPStreamListener->CleanUpStream(), so stream will be properly clean up mPluginInstance->Stop(); mPluginInstance->Start(); nsRefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner(); if (owner) { NPWindow* window = nullptr; owner->GetWindow(window); #if (MOZ_WIDGET_GTK == 2) || defined(MOZ_WIDGET_QT) // Should call GetPluginPort() here. // This part is copied from nsPluginInstanceOwner::GetPluginPort(). nsCOMPtr<nsIWidget> widget; ((nsPluginNativeWindow*)window)->GetPluginWidget(getter_AddRefs(widget)); if (widget) { window->window = widget->GetNativeData(NS_NATIVE_PLUGIN_PORT); } #endif owner->CallSetWindow(); } mSeekable = false; mPStreamListener->OnStartBinding(this); mStreamOffset = 0; // force the plugin to use stream as file mStreamType = NP_ASFILE; nsCOMPtr<nsIChannel> channel = do_QueryInterface(request); if (channel) { SetupPluginCacheFile(channel); } // unset mPendingRequests mPendingRequests = 0; 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; } nsRefPtr<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); 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); /* * 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("/%lu.%lu", 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 %lu %s", ver.get(), statusNum, statusText.get()); static_cast<nsIHTTPHeaderListener*>(mPStreamListener)->StatusLine(status.get()); } // Also provide all HTTP response headers to our listener. httpChannel->VisitResponseHeaders(this); mSeekable = false; // first we look for a content-encoding header. If we find one, we tell the // plugin that stream is not seekable, because the plugin always sees // uncompressed data, so it can't make meaningful range requests on a // compressed entity. Also, we force the plugin to use // nsPluginStreamType_AsFile stream type and we have to save decompressed // file into local plugin cache, because necko cache contains original // compressed file. nsAutoCString contentEncoding; if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"), contentEncoding))) { useLocalCache = true; } else { // set seekability (seekable if the stream has a known length and if the // http server accepts byte ranges). uint32_t length; GetLength(&length); if (length) { nsAutoCString range; if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("accept-ranges"), range)) && range.Equals(NS_LITERAL_CSTRING("bytes"), nsCaseInsensitiveCStringComparator())) { mSeekable = true; } } } // we require a content len // get Last-Modified header for plugin info nsAutoCString lastModified; if (NS_SUCCEEDED(httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("last-modified"), 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); } } rv = mPStreamListener->OnStartBinding(this); mStartBinding = true; if (NS_FAILED(rv)) return rv; mPStreamListener->GetStreamType(&mStreamType); 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); } return NS_OK; }