uint32_t GetContentSize(nsIRequest* aRequest) { // Use content-length as a size hint for http channels. nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { nsAutoCString contentLength; nsresult rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-length"), contentLength); if (NS_SUCCEEDED(rv)) { return std::max(contentLength.ToInteger(&rv), 0); } } // Use the file size as a size hint for file channels. nsCOMPtr<nsIFileChannel> fileChannel(do_QueryInterface(aRequest)); if (fileChannel) { nsCOMPtr<nsIFile> file; nsresult rv = fileChannel->GetFile(getter_AddRefs(file)); if (NS_SUCCEEDED(rv)) { int64_t filesize; rv = file->GetFileSize(&filesize); if (NS_SUCCEEDED(rv)) { return std::max(SaturateToInt32(filesize), 0); } } } // Fallback - neither http nor file. We'll use dynamic allocation. return 0; }
NS_IMETHODIMP nsPluginByteRangeStreamListener::OnStartRequest(nsIRequest *request, nsISupports *ctxt) { nsresult rv; nsCOMPtr<nsIStreamListener> finalStreamListener = do_QueryReferent(mWeakPtrPluginStreamListenerPeer); if (!finalStreamListener) return NS_ERROR_FAILURE; nsPluginStreamListenerPeer *pslp = static_cast<nsPluginStreamListenerPeer*>(finalStreamListener.get()); NS_ASSERTION(pslp->mRequests.IndexOfObject(GetBaseRequest(request)) != -1, "Untracked byte-range request?"); nsCOMPtr<nsIStreamConverterService> serv = do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { rv = serv->AsyncConvertData(MULTIPART_BYTERANGES, "*/*", finalStreamListener, nsnull, getter_AddRefs(mStreamConverter)); if (NS_SUCCEEDED(rv)) { rv = mStreamConverter->OnStartRequest(request, ctxt); if (NS_SUCCEEDED(rv)) return rv; } } mStreamConverter = 0; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request)); if (!httpChannel) { return NS_ERROR_FAILURE; } PRUint32 responseCode = 0; rv = httpChannel->GetResponseStatus(&responseCode); if (NS_FAILED(rv)) { return NS_ERROR_FAILURE; } if (responseCode != 200) { PRBool bWantsAllNetworkStreams = PR_FALSE; pslp->GetPluginInstance()-> GetValueFromPlugin(NPPVpluginWantsAllNetworkStreams, (void*)&bWantsAllNetworkStreams); if (!bWantsAllNetworkStreams){ return NS_ERROR_FAILURE; } } // if server cannot continue with byte range (206 status) and sending us whole object (200 status) // reset this seekable stream & try serve it to plugin instance as a file mStreamConverter = finalStreamListener; mRemoveMagicNumber = PR_TRUE; rv = pslp->ServeStreamAsFile(request, ctxt); return rv; }
static nsresult RequestSucceeded(nsIXMLHttpRequest* aRequest, PRBool* aReturn) { NS_ENSURE_ARG_POINTER(aRequest); nsresult rv; nsCOMPtr<nsIChannel> channel; aRequest->GetChannel(getter_AddRefs(channel)); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel, &rv)); NS_ENSURE_TRUE(httpChannel, rv); return httpChannel->GetRequestSucceeded(aReturn); }
nsresult txCompileObserver::startLoad(nsIURI* aUri, txStylesheetCompiler* aCompiler, nsIPrincipal* aReferrerPrincipal) { nsCOMPtr<nsIChannel> channel; nsresult rv = NS_NewChannel(getter_AddRefs(channel), aUri); NS_ENSURE_SUCCESS(rv, rv); channel->SetLoadGroup(mLoadGroup); channel->SetContentType(NS_LITERAL_CSTRING("text/xml")); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), NS_LITERAL_CSTRING("text/xml,application/xml,application/xhtml+xml,*/*;q=0.1"), PR_FALSE); nsCOMPtr<nsIURI> referrerURI; aReferrerPrincipal->GetURI(getter_AddRefs(referrerURI)); if (referrerURI) { httpChannel->SetReferrer(referrerURI); } } nsCOMPtr<nsIParser> parser = do_CreateInstance(kCParserCID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<txStylesheetSink> sink = new txStylesheetSink(aCompiler, parser); NS_ENSURE_TRUE(sink, NS_ERROR_OUT_OF_MEMORY); channel->SetNotificationCallbacks(sink); parser->SetCommand(kLoadAsData); parser->SetContentSink(sink); parser->Parse(aUri); // Always install in case of redirects nsCOMPtr<nsIStreamListener> listener = new nsCrossSiteListenerProxy(sink, aReferrerPrincipal, channel, PR_FALSE, &rv); NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); return channel->AsyncOpen(listener, parser); }
nsresult nsFeedSniffer::ConvertEncodedData(nsIRequest* request, const uint8_t* data, uint32_t length) { nsresult rv = NS_OK; mDecodedData = ""; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request)); if (!httpChannel) return NS_ERROR_NO_INTERFACE; nsCAutoString contentEncoding; httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Encoding"), contentEncoding); if (!contentEncoding.IsEmpty()) { nsCOMPtr<nsIStreamConverterService> converterService(do_GetService(NS_STREAMCONVERTERSERVICE_CONTRACTID)); if (converterService) { ToLowerCase(contentEncoding); nsCOMPtr<nsIStreamListener> converter; rv = converterService->AsyncConvertData(contentEncoding.get(), "uncompressed", this, nullptr, getter_AddRefs(converter)); NS_ENSURE_SUCCESS(rv, rv); converter->OnStartRequest(request, nullptr); nsCOMPtr<nsIStringInputStream> rawStream = do_CreateInstance(NS_STRINGINPUTSTREAM_CONTRACTID); if (!rawStream) return NS_ERROR_FAILURE; rv = rawStream->SetData((const char*)data, length); NS_ENSURE_SUCCESS(rv, rv); rv = converter->OnDataAvailable(request, nullptr, rawStream, 0, length); NS_ENSURE_SUCCESS(rv, rv); converter->OnStopRequest(request, nullptr, NS_OK); } } return rv; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { nsresult rv = NS_OK; PROFILER_LABEL("nsPluginStreamListenerPeer", "OnStartRequest", js::ProfileEntry::Category::OTHER); 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 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 nsRefPtr<nsPluginInstanceOwner> owner; if (mPluginInstance) { owner = mPluginInstance->GetOwner(); } nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDocument> doc; if (owner) { owner->GetDOMElement(getter_AddRefs(element)); owner->GetDocument(getter_AddRefs(doc)); } nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr; int16_t shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentProcessPolicy(nsIContentPolicy::TYPE_OBJECT_SUBREQUEST, mURL, principal, element, contentType, nullptr, &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; }
nsresult nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList) { nsAutoCString rangeString; int32_t numRequests; MakeByteRangeString(rangeList, rangeString, &numRequests); if (numRequests == 0) return NS_ERROR_FAILURE; nsresult rv = NS_OK; nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks); nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup); nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), mURL, nullptr, loadGroup, callbacks); if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (!httpChannel) return NS_ERROR_FAILURE; httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false); mAbort = true; // instruct old stream listener to cancel // the request on the next ODA. nsCOMPtr<nsIStreamListener> converter; if (numRequests == 1) { converter = this; // set current stream offset equal to the first offset in the range list // it will work for single byte range request // for multy range we'll reset it in ODA SetStreamOffset(rangeList->offset); } else { nsWeakPtr weakpeer = do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this)); nsPluginByteRangeStreamListener *brrListener = new nsPluginByteRangeStreamListener(weakpeer); if (brrListener) converter = brrListener; else return NS_ERROR_OUT_OF_MEMORY; } mPendingRequests += numRequests; nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; rv = container->SetData(MAGIC_REQUEST_CONTEXT); if (NS_FAILED(rv)) return rv; rv = channel->AsyncOpen(converter, container); if (NS_SUCCEEDED(rv)) TrackRequest(channel); return rv; }
nsresult nsUserFontSet::StartLoad(gfxFontEntry *aFontToLoad, const gfxFontFaceSrc *aFontFaceSrc) { nsresult rv; // check same-site origin nsIPresShell *ps = mPresContext->PresShell(); if (!ps) return NS_ERROR_FAILURE; NS_ASSERTION(aFontFaceSrc && !aFontFaceSrc->mIsLocal, "bad font face url passed to fontloader"); NS_ASSERTION(aFontFaceSrc->mURI, "null font uri"); if (!aFontFaceSrc->mURI) return NS_ERROR_FAILURE; // use document principal, original principal if flag set // this enables user stylesheets to load font files via // @font-face rules nsCOMPtr<nsIPrincipal> principal = ps->GetDocument()->NodePrincipal(); NS_ASSERTION(aFontFaceSrc->mOriginPrincipal, "null origin principal in @font-face rule"); if (aFontFaceSrc->mUseOriginPrincipal) { principal = do_QueryInterface(aFontFaceSrc->mOriginPrincipal); } rv = nsFontFaceLoader::CheckLoadAllowed(principal, aFontFaceSrc->mURI, ps->GetDocument()); if (NS_FAILED(rv)) { #ifdef PR_LOGGING if (LOG_ENABLED()) { nsCAutoString fontURI, referrerURI; aFontFaceSrc->mURI->GetSpec(fontURI); if (aFontFaceSrc->mReferrer) aFontFaceSrc->mReferrer->GetSpec(referrerURI); LOG(("fontdownloader download blocked - font uri: (%s) " "referrer uri: (%s) err: %8.8x\n", fontURI.get(), referrerURI.get(), rv)); } #endif return rv; } nsCOMPtr<nsIStreamLoader> streamLoader; nsCOMPtr<nsILoadGroup> loadGroup(ps->GetDocument()->GetDocumentLoadGroup()); nsCOMPtr<nsIChannel> channel; // get Content Security Policy from principal to pass into channel nsCOMPtr<nsIChannelPolicy> channelPolicy; nsCOMPtr<nsIContentSecurityPolicy> csp; rv = principal->GetCsp(getter_AddRefs(csp)); NS_ENSURE_SUCCESS(rv, rv); if (csp) { channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1"); channelPolicy->SetContentSecurityPolicy(csp); channelPolicy->SetLoadType(nsIContentPolicy::TYPE_FONT); } rv = NS_NewChannel(getter_AddRefs(channel), aFontFaceSrc->mURI, nsnull, loadGroup, nsnull, nsIRequest::LOAD_NORMAL, channelPolicy); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<nsFontFaceLoader> fontLoader = new nsFontFaceLoader(aFontToLoad, aFontFaceSrc->mURI, this, channel); if (!fontLoader) return NS_ERROR_OUT_OF_MEMORY; #ifdef PR_LOGGING if (LOG_ENABLED()) { nsCAutoString fontURI, referrerURI; aFontFaceSrc->mURI->GetSpec(fontURI); if (aFontFaceSrc->mReferrer) aFontFaceSrc->mReferrer->GetSpec(referrerURI); LOG(("fontdownloader (%p) download start - font uri: (%s) " "referrer uri: (%s)\n", fontLoader.get(), fontURI.get(), referrerURI.get())); } #endif nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) httpChannel->SetReferrer(aFontFaceSrc->mReferrer); rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), fontLoader); NS_ENSURE_SUCCESS(rv, rv); PRBool inherits = PR_FALSE; rv = NS_URIChainHasFlags(aFontFaceSrc->mURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT, &inherits); if (NS_SUCCEEDED(rv) && inherits) { // allow data, javascript, etc URI's rv = channel->AsyncOpen(streamLoader, nsnull); } else { nsCOMPtr<nsIStreamListener> listener = new nsCrossSiteListenerProxy(streamLoader, principal, channel, PR_FALSE, &rv); if (NS_FAILED(rv)) { fontLoader->DropChannel(); // explicitly need to break ref cycle } NS_ENSURE_TRUE(listener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); rv = channel->AsyncOpen(listener, nsnull); } if (NS_SUCCEEDED(rv)) { mLoaders.PutEntry(fontLoader); } return rv; }
nsresult nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement) { // We need a document to evaluate scripts. NS_ENSURE_TRUE(mDocument, NS_ERROR_FAILURE); // Check to see if scripts has been turned off. if (!mEnabled || !mDocument->IsScriptEnabled()) { return NS_ERROR_NOT_AVAILABLE; } NS_ASSERTION(!aElement->IsMalformed(), "Executing malformed script"); // Check that the script is not an eventhandler if (IsScriptEventHandler(aElement)) { return NS_CONTENT_SCRIPT_IS_EVENTHANDLER; } // Script evaluation can also be disabled in the current script // context even though it's enabled in the document. // XXX - still hard-coded for JS here, even though another language // may be specified. Should this check be made *after* we examine // the attributes to locate the script-type? // For now though, if JS is disabled we assume every language is // disabled. // XXX is this different from the mDocument->IsScriptEnabled() call? nsIScriptGlobalObject *globalObject = mDocument->GetScriptGlobalObject(); if (!globalObject) { return NS_ERROR_NOT_AVAILABLE; } nsIScriptContext *context = globalObject->GetScriptContext( nsIProgrammingLanguage::JAVASCRIPT); // If scripts aren't enabled in the current context, there's no // point in going on. if (!context || !context->GetScriptsEnabled()) { return NS_ERROR_NOT_AVAILABLE; } // Default script language is whatever the root content specifies // (which may come from a header or http-meta tag), or if there // is no root content, from the script global object. nsCOMPtr<nsIContent> rootContent = mDocument->GetRootContent(); PRUint32 typeID = rootContent ? rootContent->GetScriptTypeID() : context->GetScriptTypeID(); PRUint32 version = 0; nsAutoString language, type, src; nsresult rv = NS_OK; // Check the type attribute to determine language and version. // If type exists, it trumps the deprecated 'language=' aElement->GetScriptType(type); if (!type.IsEmpty()) { nsCOMPtr<nsIMIMEHeaderParam> mimeHdrParser = do_GetService("@mozilla.org/network/mime-hdrparam;1"); NS_ENSURE_TRUE(mimeHdrParser, NS_ERROR_FAILURE); NS_ConvertUTF16toUTF8 typeAndParams(type); nsAutoString mimeType; rv = mimeHdrParser->GetParameter(typeAndParams, nsnull, EmptyCString(), PR_FALSE, nsnull, mimeType); NS_ENSURE_SUCCESS(rv, rv); // Javascript keeps the fast path, optimized for most-likely type // Table ordered from most to least likely JS MIME types. // See bug 62485, feel free to add <script type="..."> survey data to it, // or to a new bug once 62485 is closed. static const char *jsTypes[] = { "text/javascript", "text/ecmascript", "application/javascript", "application/ecmascript", "application/x-javascript", nsnull }; PRBool isJavaScript = PR_FALSE; for (PRInt32 i = 0; jsTypes[i]; i++) { if (mimeType.LowerCaseEqualsASCII(jsTypes[i])) { isJavaScript = PR_TRUE; break; } } if (isJavaScript) typeID = nsIProgrammingLanguage::JAVASCRIPT; else { // Use the object factory to locate a matching language. nsCOMPtr<nsIScriptRuntime> runtime; rv = NS_GetScriptRuntime(mimeType, getter_AddRefs(runtime)); if (NS_FAILED(rv) || runtime == nsnull) { // Failed to get the explicitly specified language NS_WARNING("Failed to find a scripting language"); typeID = nsIProgrammingLanguage::UNKNOWN; } else typeID = runtime->GetScriptTypeID(); } if (typeID != nsIProgrammingLanguage::UNKNOWN) { // Get the version string, and ensure the language supports it. nsAutoString versionName; rv = mimeHdrParser->GetParameter(typeAndParams, "version", EmptyCString(), PR_FALSE, nsnull, versionName); if (NS_FAILED(rv)) { // no version attribute - version remains 0. if (rv != NS_ERROR_INVALID_ARG) return rv; } else { nsCOMPtr<nsIScriptRuntime> runtime; rv = NS_GetScriptRuntimeByID(typeID, getter_AddRefs(runtime)); if (NS_FAILED(rv)) { NS_ERROR("Failed to locate the language with this ID"); return rv; } rv = runtime->ParseVersion(versionName, &version); if (NS_FAILED(rv)) { NS_WARNING("This script language version is not supported - ignored"); typeID = nsIProgrammingLanguage::UNKNOWN; } } } // Some js specifics yet to be abstracted. if (typeID == nsIProgrammingLanguage::JAVASCRIPT) { nsAutoString value; rv = mimeHdrParser->GetParameter(typeAndParams, "e4x", EmptyCString(), PR_FALSE, nsnull, value); if (NS_FAILED(rv)) { if (rv != NS_ERROR_INVALID_ARG) return rv; } else { if (value.Length() == 1 && value[0] == '1') // This means that we need to set JSOPTION_XML in the JS options. // We re-use our knowledge of the implementation to reuse // JSVERSION_HAS_XML as a safe version flag. // If version has JSVERSION_UNKNOWN (-1), then this is still OK. version |= JSVERSION_HAS_XML; } } } else { // no 'type=' element // "language" is a deprecated attribute of HTML, so we check it only for // HTML script elements. nsCOMPtr<nsIDOMHTMLScriptElement> htmlScriptElement = do_QueryInterface(aElement); if (htmlScriptElement) { htmlScriptElement->GetAttribute(NS_LITERAL_STRING("language"), language); if (!language.IsEmpty()) { if (nsParserUtils::IsJavaScriptLanguage(language, &version)) typeID = nsIProgrammingLanguage::JAVASCRIPT; else typeID = nsIProgrammingLanguage::UNKNOWN; // IE, Opera, etc. do not respect language version, so neither should // we at this late date in the browser wars saga. Note that this change // affects HTML but not XUL or SVG (but note also that XUL has its own // code to check nsParserUtils::IsJavaScriptLanguage -- that's probably // a separate bug, one we may not be able to fix short of XUL2). See // bug 255895 (https://bugzilla.mozilla.org/show_bug.cgi?id=255895). NS_ASSERTION(JSVERSION_DEFAULT == 0, "We rely on all languages having 0 as a version default"); version = 0; } } } // If we don't know the language, we don't know how to evaluate if (typeID == nsIProgrammingLanguage::UNKNOWN) { return NS_ERROR_NOT_AVAILABLE; } // If not from a chrome document (which is always trusted), we need some way // of checking the language is "safe". Currently the only other language // impl is Python, and that is *not* safe in untrusted code - so fixing // this isn't a priority.! // See also similar code in nsXULContentSink.cpp if (typeID != nsIProgrammingLanguage::JAVASCRIPT && !nsContentUtils::IsChromeDoc(mDocument)) { NS_WARNING("Untrusted language called from non-chrome - ignored"); return NS_ERROR_NOT_AVAILABLE; } nsCOMPtr<nsIContent> eltContent(do_QueryInterface(aElement)); eltContent->SetScriptTypeID(typeID); // Create a request object for this script nsRefPtr<nsScriptLoadRequest> request = new nsScriptLoadRequest(aElement, version); NS_ENSURE_TRUE(request, NS_ERROR_OUT_OF_MEMORY); // First check to see if this is an external script nsCOMPtr<nsIURI> scriptURI = aElement->GetScriptURI(); if (scriptURI) { // Check that the containing page is allowed to load this URI. rv = nsContentUtils::GetSecurityManager()-> CheckLoadURIWithPrincipal(mDocument->NodePrincipal(), scriptURI, nsIScriptSecurityManager::ALLOW_CHROME); NS_ENSURE_SUCCESS(rv, rv); // After the security manager, the content-policy stuff gets a veto PRInt16 shouldLoad = nsIContentPolicy::ACCEPT; rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_SCRIPT, scriptURI, mDocument->NodePrincipal(), aElement, NS_LossyConvertUTF16toASCII(type), nsnull, //extra &shouldLoad, nsContentUtils::GetContentPolicy(), nsContentUtils::GetSecurityManager()); if (NS_FAILED(rv) || NS_CP_REJECTED(shouldLoad)) { if (NS_FAILED(rv) || shouldLoad != nsIContentPolicy::REJECT_TYPE) { return NS_ERROR_CONTENT_BLOCKED; } return NS_ERROR_CONTENT_BLOCKED_SHOW_ALT; } request->mURI = scriptURI; request->mIsInline = PR_FALSE; request->mLoading = PR_TRUE; nsCOMPtr<nsILoadGroup> loadGroup = mDocument->GetDocumentLoadGroup(); nsCOMPtr<nsIStreamLoader> loader; nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(globalObject)); nsIDocShell *docshell = window->GetDocShell(); nsCOMPtr<nsIInterfaceRequestor> prompter(do_QueryInterface(docshell)); nsCOMPtr<nsIChannel> channel; rv = NS_NewChannel(getter_AddRefs(channel), scriptURI, nsnull, loadGroup, prompter, nsIRequest::LOAD_NORMAL); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { // HTTP content negotation has little value in this context. httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"), NS_LITERAL_CSTRING("*/*"), PR_FALSE); httpChannel->SetReferrer(mDocument->GetDocumentURI()); } rv = NS_NewStreamLoader(getter_AddRefs(loader), this); NS_ENSURE_SUCCESS(rv, rv); rv = channel->AsyncOpen(loader, request); NS_ENSURE_SUCCESS(rv, rv); } else { request->mLoading = PR_FALSE; request->mIsInline = PR_TRUE; request->mURI = mDocument->GetDocumentURI(); request->mLineNo = aElement->GetScriptLineNumber(); // If we've got existing pending requests, add ourselves // to this list. if (mPendingRequests.Count() == 0 && ReadyToExecuteScripts() && nsContentUtils::IsSafeToRunScript()) { return ProcessRequest(request); } } // Add the request to our pending requests list NS_ENSURE_TRUE(mPendingRequests.AppendObject(request), NS_ERROR_OUT_OF_MEMORY); // If there weren't any pending requests before, and this one is // ready to execute, do that as soon as it's safe. if (mPendingRequests.Count() == 1 && !request->mLoading && ReadyToExecuteScripts()) { nsContentUtils::AddScriptRunner(new nsRunnableMethod<nsScriptLoader>(this, &nsScriptLoader::ProcessPendingRequests)); } // Added as pending request, now we can send blocking back return NS_ERROR_HTMLPARSER_BLOCK; }
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */ NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) { nsresult rv; LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest"); NS_ASSERTION(!mDecoder, "imgRequest::OnStartRequest -- we already have a decoder"); nsCOMPtr<nsIMultiPartChannel> mpchan(do_QueryInterface(aRequest)); if (mpchan) mIsMultiPartChannel = PR_TRUE; /* * If mRequest is null here, then we need to set it so that we'll be able to * cancel it if our Cancel() method is called. Note that this can only * happen for multipart channels. We could simply not null out mRequest for * non-last parts, if GetIsLastPart() were reliable, but it's not. See * https://bugzilla.mozilla.org/show_bug.cgi?id=339610 */ if (!mRequest) { NS_ASSERTION(mpchan, "We should have an mRequest here unless we're multipart"); nsCOMPtr<nsIChannel> chan; mpchan->GetBaseChannel(getter_AddRefs(chan)); mRequest = chan; } /* set our state variables to their initial values, but advance mState to onStartRequest. */ if (mIsMultiPartChannel) { // Don't blow away our status altogether mImageStatus &= ~imgIRequest::STATUS_LOAD_PARTIAL; mImageStatus &= ~imgIRequest::STATUS_LOAD_COMPLETE; mImageStatus &= ~imgIRequest::STATUS_FRAME_COMPLETE; } else { mImageStatus = imgIRequest::STATUS_NONE; } mState = onStartRequest; nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); if (channel) channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo)); /* set our loading flag to true */ mLoading = PR_TRUE; /* notify our kids */ nsTObserverArray<imgRequestProxy*>::ForwardIterator iter(mObservers); while (iter.HasMore()) { iter.GetNext()->OnStartRequest(aRequest, ctxt); } /* Get our principal */ nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest)); if (chan) { nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService("@mozilla.org/scriptsecuritymanager;1"); if (secMan) { nsresult rv = secMan->GetChannelPrincipal(chan, getter_AddRefs(mPrincipal)); if (NS_FAILED(rv)) { return rv; } } } /* get the expires info */ if (mCacheEntry) { nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(aRequest)); if (cacheChannel) { nsCOMPtr<nsISupports> cacheToken; cacheChannel->GetCacheToken(getter_AddRefs(cacheToken)); if (cacheToken) { nsCOMPtr<nsICacheEntryInfo> entryDesc(do_QueryInterface(cacheToken)); if (entryDesc) { PRUint32 expiration; /* get the expiration time from the caching channel's token */ entryDesc->GetExpirationTime(&expiration); /* set the expiration time on our entry */ mCacheEntry->SetExpiryTime(expiration); } } } // // Determine whether the cache entry must be revalidated when it expires. // If so, then the cache entry must *not* be used during HISTORY loads if // it has expired. // // Currently, only HTTP specifies this information... // nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { PRBool bMustRevalidate = PR_FALSE; rv = httpChannel->IsNoStoreResponse(&bMustRevalidate); if (!bMustRevalidate) { rv = httpChannel->IsNoCacheResponse(&bMustRevalidate); } if (!bMustRevalidate) { nsCAutoString cacheHeader; rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Cache-Control"), cacheHeader); if (PL_strcasestr(cacheHeader.get(), "must-revalidate")) { bMustRevalidate = PR_TRUE; } } mCacheEntry->SetMustValidateIfExpired(bMustRevalidate); } } // Shouldn't we be dead already if this gets hit? Probably multipart/x-mixed-replace... if (mObservers.IsEmpty()) { this->Cancel(NS_IMAGELIB_ERROR_FAILURE); } return NS_OK; }
nsresult NS_StartCORSPreflight(nsIChannel* aRequestChannel, nsIStreamListener* aListener, nsIPrincipal* aPrincipal, PRBool aWithCredentials, nsTArray<nsCString>& aUnsafeHeaders, nsIChannel** aPreflightChannel) { *aPreflightChannel = nsnull; nsCAutoString method; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequestChannel)); NS_ENSURE_TRUE(httpChannel, NS_ERROR_UNEXPECTED); httpChannel->GetRequestMethod(method); nsCOMPtr<nsIURI> uri; nsresult rv = NS_GetFinalChannelURI(aRequestChannel, getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); nsPreflightCache::CacheEntry* entry = sPreflightCache ? sPreflightCache->GetEntry(uri, aPrincipal, aWithCredentials, PR_FALSE) : nsnull; if (entry && entry->CheckRequest(method, aUnsafeHeaders)) { // We have a cached preflight result, just start the original channel return aRequestChannel->AsyncOpen(aListener, nsnull); } // Either it wasn't cached or the cached result has expired. Build a // channel for the OPTIONS request. nsCOMPtr<nsILoadGroup> loadGroup; rv = aRequestChannel->GetLoadGroup(getter_AddRefs(loadGroup)); NS_ENSURE_SUCCESS(rv, rv); nsLoadFlags loadFlags; rv = aRequestChannel->GetLoadFlags(&loadFlags); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIChannel> preflightChannel; rv = NS_NewChannel(getter_AddRefs(preflightChannel), uri, nsnull, loadGroup, nsnull, loadFlags); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> preHttp = do_QueryInterface(preflightChannel); NS_ASSERTION(preHttp, "Failed to QI to nsIHttpChannel!"); rv = preHttp->SetRequestMethod(NS_LITERAL_CSTRING("OPTIONS")); NS_ENSURE_SUCCESS(rv, rv); // Set up listener which will start the original channel nsCOMPtr<nsIStreamListener> preflightListener = new nsCORSPreflightListener(aRequestChannel, aListener, nsnull, aPrincipal, method, aWithCredentials); NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY); preflightListener = new nsCORSListenerProxy(preflightListener, aPrincipal, preflightChannel, aWithCredentials, method, aUnsafeHeaders, &rv); NS_ENSURE_TRUE(preflightListener, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_SUCCESS(rv, rv); // Start preflight rv = preflightChannel->AsyncOpen(preflightListener, nsnull); NS_ENSURE_SUCCESS(rv, rv); // Return newly created preflight channel preflightChannel.forget(aPreflightChannel); return NS_OK; }
NS_IMETHODIMP HeaderSniffer::OnStopRequest (nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) { nsresult rv; LOG ("HeaderSniffer::OnStopRequest"); if (aStatusCode != NS_BINDING_SUCCEEDED) { GtkWidget *parent, *dialog; parent = galeon_embed_persist_get_fc_parent (mEmbedPersist); dialog = hig_alert_new (parent ? GTK_WINDOW (parent) : NULL, GTK_DIALOG_DESTROY_WITH_PARENT, HIG_ALERT_ERROR, _("Unable to save link."), _("The web page might have been removed " "or had its name changed."), GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); g_signal_connect (dialog, "response", (GCallback)gtk_widget_destroy, NULL); gtk_widget_show (dialog); return NS_OK; } nsCOMPtr<nsIURIChecker> checker = do_QueryInterface (aRequest); NS_ENSURE_TRUE (checker, NS_ERROR_FAILURE); nsCOMPtr<nsIChannel> channel; checker->GetBaseChannel (getter_AddRefs(channel)); NS_ENSURE_TRUE (channel, NS_ERROR_FAILURE); /* Get the final URL of the request */ channel->GetURI (getter_AddRefs(mFinalURL)); /* Get the Content-Disposition header, it might give us a * hint on the filename */ nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); GulCString contentDisposition; if (httpChannel) { httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), contentDisposition); } /* Get the document encoding */ nsCOMPtr<nsIEncodedChannel> encodedChannel(do_QueryInterface(channel)); GulCString contentEncoding; if (encodedChannel) { nsCOMPtr<nsIUTF8StringEnumerator> enumerator; encodedChannel->GetContentEncodings (getter_AddRefs (enumerator)); if (enumerator) { PRBool more = PR_FALSE; enumerator->HasMore (&more); if (more) { enumerator->GetNext (contentEncoding); } } } /* Get the Content-Type header */ GulCString contentType; channel->GetContentType(contentType); if (contentType.Equals ("application/x-unknown-content-type")) { contentType = ""; } /* If no Content-Type, try and get it from the document */ if (contentType.IsEmpty() && mDocument) { nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(mDocument); if (doc) { GulString type; doc->GetContentType (type); contentType = type; } } /* Failing that, guess from the url */ if (contentType.IsEmpty()) { nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID)); mimeService->GetTypeFromURI (mFinalURL, contentType); } /* Calculate whether we whould decode */ mShouldDecode = PR_FALSE; if (contentEncoding.Length ()) { nsCOMPtr<nsIExternalHelperAppService> helperService = do_GetService (NS_EXTERNALHELPERAPPSERVICE_CONTRACTID); nsCOMPtr<nsIURL> resultURL = do_QueryInterface (mFinalURL); if (resultURL) { GulCString extension; resultURL->GetFileExtension (extension); rv = helperService->ApplyDecodingForExtension (extension, contentEncoding, &mShouldDecode); if (NS_FAILED (rv)) { mShouldDecode = PR_FALSE; } } } if (!mDocument && !mShouldDecode && contentEncoding.Length()) { // The data is encoded, we are not going to decode it, // and this is not a document save so just set our // content type to correspond to the outermost // encoding so we get extensions and the like right. contentType = contentEncoding; } GulCString filename; rv = GetFilename (contentDisposition, contentType, filename); NS_ENSURE_TRUE (NS_SUCCEEDED (rv), NS_ERROR_FAILURE); PerformSave (filename); return NS_OK; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { nsresult rv = NS_OK; 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) { PRUint32 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); // If the call returned an error code make sure we still use our default value. if (NS_FAILED(rv)) { bWantsAllNetworkStreams = false; } } if (!bWantsAllNetworkStreams) { mRequestFailed = true; return NS_ERROR_FAILURE; } } } // do a little sanity check to make sure our frame isn't gone // by getting the tag type and checking for an error, we can determine if // the frame is gone if (mOwner) { nsCOMPtr<nsIPluginTagInfo> pti = do_QueryInterface(mOwner); NS_ENSURE_TRUE(pti, NS_ERROR_FAILURE); nsPluginTagType tagType; if (NS_FAILED(pti->GetTagType(&tagType))) return NS_ERROR_FAILURE; // something happened to our object frame, so bail! } // 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); PRInt32 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; } nsCAutoString 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 NPWindow* window = nsnull; // if we don't have an nsNPAPIPluginInstance (mPluginInstance), it means // we weren't able to load a plugin previously because we // didn't have the mimetype. Now that we do (aContentType), // we'll try again with SetUpPluginInstance() // which is called by InstantiateEmbeddedPlugin() // NOTE: we don't want to try again if we didn't get the MIME type this time if (!mPluginInstance && mOwner && !aContentType.IsEmpty()) { nsRefPtr<nsNPAPIPluginInstance> pluginInstRefPtr; mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr)); mPluginInstance = pluginInstRefPtr.get(); mOwner->GetWindow(window); if (!mPluginInstance && window) { nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst()); rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner); if (NS_SUCCEEDED(rv)) { mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr)); mPluginInstance = pluginInstRefPtr.get(); if (mPluginInstance) { mOwner->CreateWidget(); // If we've got a native window, the let the plugin know about it. mOwner->SetWindow(); } } } } // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) return rv; return rv; }
// This method is largely cribbed from // nsExternalResourceMap::PendingLoad::SetupViewer. nsresult SVGDocumentWrapper::SetupViewer(nsIRequest* aRequest, nsIContentViewer** aViewer, nsILoadGroup** aLoadGroup) { nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest)); NS_ENSURE_TRUE(chan, NS_ERROR_UNEXPECTED); // Check for HTTP error page nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { bool requestSucceeded; if (NS_FAILED(httpChannel->GetRequestSucceeded(&requestSucceeded)) || !requestSucceeded) { return NS_ERROR_FAILURE; } } // Give this document its own loadgroup nsCOMPtr<nsILoadGroup> loadGroup; chan->GetLoadGroup(getter_AddRefs(loadGroup)); nsCOMPtr<nsILoadGroup> newLoadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID); NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY); newLoadGroup->SetLoadGroup(loadGroup); nsCOMPtr<nsICategoryManager> catMan = do_GetService(NS_CATEGORYMANAGER_CONTRACTID); NS_ENSURE_TRUE(catMan, NS_ERROR_NOT_AVAILABLE); nsXPIDLCString contractId; nsresult rv = catMan->GetCategoryEntry("Gecko-Content-Viewers", IMAGE_SVG_XML, getter_Copies(contractId)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocumentLoaderFactory> docLoaderFactory = do_GetService(contractId); NS_ENSURE_TRUE(docLoaderFactory, NS_ERROR_NOT_AVAILABLE); nsCOMPtr<nsIContentViewer> viewer; nsCOMPtr<nsIStreamListener> listener; rv = docLoaderFactory->CreateInstance("external-resource", chan, newLoadGroup, NS_LITERAL_CSTRING(IMAGE_SVG_XML), nullptr, nullptr, getter_AddRefs(listener), getter_AddRefs(viewer)); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(viewer, NS_ERROR_UNEXPECTED); nsCOMPtr<nsIParser> parser = do_QueryInterface(listener); NS_ENSURE_TRUE(parser, NS_ERROR_UNEXPECTED); // XML-only, because this is for SVG content nsIContentSink* sink = parser->GetContentSink(); nsCOMPtr<nsIXMLContentSink> xmlSink = do_QueryInterface(sink); NS_ENSURE_TRUE(sink, NS_ERROR_UNEXPECTED); listener.swap(mListener); viewer.forget(aViewer); newLoadGroup.forget(aLoadGroup); RegisterForXPCOMShutdown(); return NS_OK; }
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */ NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count) { LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "count", count); NS_ASSERTION(aRequest, "imgRequest::OnDataAvailable -- no request!"); mGotData = PR_TRUE; if (!mProcessing) { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |First time through... finding mimetype|"); /* set our processing flag to true if this is the first OnDataAvailable() */ mProcessing = PR_TRUE; /* look at the first few bytes and see if we can tell what the data is from that * since servers tend to lie. :( */ PRUint32 out; inStr->ReadSegments(sniff_mimetype_callback, this, count, &out); #ifdef NS_DEBUG /* NS_WARNING if the content type from the channel isn't the same if the sniffing */ #endif if (mContentType.IsEmpty()) { LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable |sniffing of mimetype failed|"); nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest)); nsresult rv = NS_ERROR_FAILURE; if (chan) { rv = chan->GetContentType(mContentType); } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_ERROR, ("[this=%p] imgRequest::OnDataAvailable -- Content type unavailable from the channel\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } LOG_MSG(gImgLog, "imgRequest::OnDataAvailable", "Got content type from the channel"); } /* set our mimetype as a property */ nsCOMPtr<nsISupportsCString> contentType(do_CreateInstance("@mozilla.org/supports-cstring;1")); if (contentType) { contentType->SetData(mContentType); mProperties->Set("type", contentType); } /* set our content disposition as a property */ nsCAutoString disposition; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aRequest)); if (httpChannel) { httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("content-disposition"), disposition); } else { nsCOMPtr<nsIMultiPartChannel> multiPartChannel(do_QueryInterface(aRequest)); if (multiPartChannel) { multiPartChannel->GetContentDisposition(disposition); } } if (!disposition.IsEmpty()) { nsCOMPtr<nsISupportsCString> contentDisposition(do_CreateInstance("@mozilla.org/supports-cstring;1")); if (contentDisposition) { contentDisposition->SetData(disposition); mProperties->Set("content-disposition", contentDisposition); } } LOG_MSG_WITH_PARAM(gImgLog, "imgRequest::OnDataAvailable", "content type", mContentType.get()); nsCAutoString conid(NS_LITERAL_CSTRING("@mozilla.org/image/decoder;2?type=") + mContentType); mDecoder = do_CreateInstance(conid.get()); if (!mDecoder) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- Decoder not available\n", this)); // no image decoder for this mimetype :( this->Cancel(NS_IMAGELIB_ERROR_NO_DECODER); return NS_IMAGELIB_ERROR_NO_DECODER; } nsresult rv = mDecoder->Init(static_cast<imgILoad*>(this)); if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- mDecoder->Init failed\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } } if (!mDecoder) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- no decoder\n", this)); this->Cancel(NS_IMAGELIB_ERROR_NO_DECODER); return NS_BINDING_ABORTED; } // The decoder will start decoding into the current frame (if we have one). // When it needs to add another frame, we will unlock this frame and lock the // new frame. // Our invariant is that, while in the decoder, the last frame is always // locked, and all others are unlocked. imgContainer *image = reinterpret_cast<imgContainer*>(mImage.get()); if (image->mFrames.Length() > 0) { imgFrame *curframe = image->mFrames.ElementAt(image->mFrames.Length() - 1); curframe->LockImageData(); } PRUint32 wrote; nsresult rv = mDecoder->WriteFrom(inStr, count, &wrote); // We unlock the current frame, even if that frame is different from the // frame we entered the decoder with. (See above.) if (image->mFrames.Length() > 0) { imgFrame *curframe = image->mFrames.ElementAt(image->mFrames.Length() - 1); curframe->UnlockImageData(); } if (NS_FAILED(rv)) { PR_LOG(gImgLog, PR_LOG_WARNING, ("[this=%p] imgRequest::OnDataAvailable -- mDecoder->WriteFrom failed\n", this)); this->Cancel(NS_IMAGELIB_ERROR_FAILURE); return NS_BINDING_ABORTED; } return NS_OK; }
nsresult nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList) { nsAutoCString rangeString; int32_t numRequests; MakeByteRangeString(rangeList, rangeString, &numRequests); if (numRequests == 0) return NS_ERROR_FAILURE; nsresult rv = NS_OK; nsRefPtr<nsPluginInstanceOwner> owner = mPluginInstance->GetOwner(); nsCOMPtr<nsIDOMElement> element; nsCOMPtr<nsIDocument> doc; if (owner) { rv = owner->GetDOMElement(getter_AddRefs(element)); NS_ENSURE_SUCCESS(rv, rv); rv = owner->GetDocument(getter_AddRefs(doc)); NS_ENSURE_SUCCESS(rv, rv); } nsCOMPtr<nsIInterfaceRequestor> callbacks = do_QueryReferent(mWeakPtrChannelCallbacks); nsCOMPtr<nsILoadGroup> loadGroup = do_QueryReferent(mWeakPtrChannelLoadGroup); nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsINode> requestingNode(do_QueryInterface(element)); if (requestingNode) { rv = NS_NewChannel(getter_AddRefs(channel), mURL, requestingNode, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER, loadGroup, callbacks); } else { // in this else branch we really don't know where the load is coming // from and in fact should use something better than just using // a nullPrincipal as the loadingPrincipal. nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create(); NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE); rv = NS_NewChannel(getter_AddRefs(channel), mURL, principal, nsILoadInfo::SEC_NORMAL, nsIContentPolicy::TYPE_OTHER, loadGroup, callbacks); } if (NS_FAILED(rv)) return rv; nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (!httpChannel) return NS_ERROR_FAILURE; httpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Range"), rangeString, false); mAbort = true; // instruct old stream listener to cancel // the request on the next ODA. nsCOMPtr<nsIStreamListener> converter; if (numRequests == 1) { converter = this; // set current stream offset equal to the first offset in the range list // it will work for single byte range request // for multy range we'll reset it in ODA SetStreamOffset(rangeList->offset); } else { nsWeakPtr weakpeer = do_GetWeakReference(static_cast<nsISupportsWeakReference*>(this)); nsPluginByteRangeStreamListener *brrListener = new nsPluginByteRangeStreamListener(weakpeer); if (brrListener) converter = brrListener; else return NS_ERROR_OUT_OF_MEMORY; } mPendingRequests += numRequests; nsCOMPtr<nsISupportsPRUint32> container = do_CreateInstance(NS_SUPPORTS_PRUINT32_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; rv = container->SetData(MAGIC_REQUEST_CONTEXT); if (NS_FAILED(rv)) return rv; rv = channel->AsyncOpen(converter, container); if (NS_SUCCEEDED(rv)) TrackRequest(channel); return rv; }
NS_IMETHODIMP nsJARChannel::OnDownloadComplete(nsIDownloader *downloader, nsIRequest *request, nsISupports *context, nsresult status, nsIFile *file) { nsresult rv; nsCOMPtr<nsIChannel> channel(do_QueryInterface(request)); if (channel) { PRUint32 loadFlags; channel->GetLoadFlags(&loadFlags); if (loadFlags & LOAD_REPLACE) { mLoadFlags |= LOAD_REPLACE; if (!mOriginalURI) { SetOriginalURI(mJarURI); } nsCOMPtr<nsIURI> innerURI; rv = channel->GetURI(getter_AddRefs(innerURI)); if (NS_SUCCEEDED(rv)) { nsCOMPtr<nsIJARURI> newURI; rv = mJarURI->CloneWithJARFile(innerURI, getter_AddRefs(newURI)); if (NS_SUCCEEDED(rv)) { mJarURI = newURI; } } if (NS_SUCCEEDED(status)) { status = rv; } } } if (NS_SUCCEEDED(status) && channel) { // Grab the security info from our base channel channel->GetSecurityInfo(getter_AddRefs(mSecurityInfo)); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel)); if (httpChannel) { // We only want to run scripts if the server really intended to // send us a JAR file. Check the server-supplied content type for // a JAR type. nsCAutoString header; httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("Content-Type"), header); nsCAutoString contentType; nsCAutoString charset; NS_ParseContentType(header, contentType, charset); nsCAutoString channelContentType; channel->GetContentType(channelContentType); mIsUnsafe = !(contentType.Equals(channelContentType) && (contentType.EqualsLiteral("application/java-archive") || contentType.EqualsLiteral("application/x-jar"))); } else { nsCOMPtr<nsIJARChannel> innerJARChannel(do_QueryInterface(channel)); if (innerJARChannel) { PRBool unsafe; innerJARChannel->GetIsUnsafe(&unsafe); mIsUnsafe = unsafe; } } channel->GetContentDisposition(mContentDisposition); } if (NS_SUCCEEDED(status) && mIsUnsafe) { PRBool allowUnpack = PR_FALSE; nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); if (prefs) { prefs->GetBoolPref("network.jar.open-unsafe-types", &allowUnpack); } if (!allowUnpack) { status = NS_ERROR_UNSAFE_CONTENT_TYPE; } } if (NS_SUCCEEDED(status)) { // Refuse to unpack view-source: jars even if open-unsafe-types is set. nsCOMPtr<nsIViewSourceChannel> viewSource = do_QueryInterface(channel); if (viewSource) { status = NS_ERROR_UNSAFE_CONTENT_TYPE; } } if (NS_SUCCEEDED(status)) { mJarFile = file; rv = CreateJarInput(nsnull); if (NS_SUCCEEDED(rv)) { // create input stream pump rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput); if (NS_SUCCEEDED(rv)) rv = mPump->AsyncRead(this, nsnull); } status = rv; } if (NS_FAILED(status)) { mStatus = status; OnStartRequest(nsnull, nsnull); OnStopRequest(nsnull, nsnull, status); } return NS_OK; }
nsresult nsDOMWorkerScriptLoader::OnStreamCompleteInternal(nsIStreamLoader* aLoader, nsISupports* aContext, nsresult aStatus, PRUint32 aStringLen, const PRUint8* aString) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); nsCOMPtr<nsISupportsPRUint32> indexSupports(do_QueryInterface(aContext)); NS_ENSURE_TRUE(indexSupports, NS_ERROR_NO_INTERFACE); PRUint32 index = PR_UINT32_MAX; indexSupports->GetData(&index); if (index >= mScriptCount) { NS_NOTREACHED("This really can't fail or we'll hang!"); return NS_ERROR_FAILURE; } ScriptLoadInfo& loadInfo = mLoadInfos[index]; NS_ASSERTION(!loadInfo.done, "Got complete on the same load twice!"); loadInfo.done = PR_TRUE; #ifdef DEBUG // Make sure we're seeing the channel that we expect. nsCOMPtr<nsIRequest> requestDebug; nsresult rvDebug = aLoader->GetRequest(getter_AddRefs(requestDebug)); // When we cancel sometimes we get null here. That should be ok, but only if // we're canceled. NS_ASSERTION(NS_SUCCEEDED(rvDebug) || mCanceled, "GetRequest failed!"); if (NS_SUCCEEDED(rvDebug)) { nsCOMPtr<nsIChannel> channel(do_QueryInterface(requestDebug)); NS_ASSERTION(channel, "QI failed!"); nsCOMPtr<nsISupports> thisChannel(do_QueryInterface(channel)); NS_ASSERTION(thisChannel, "QI failed!"); nsCOMPtr<nsISupports> ourChannel(do_QueryInterface(loadInfo.channel)); NS_ASSERTION(ourChannel, "QI failed!"); NS_ASSERTION(thisChannel == ourChannel, "Wrong channel!"); } #endif // Use an alias to keep rv and loadInfo.result in sync. nsresult& rv = loadInfo.result = aStatus; if (NS_FAILED(rv)) { return rv; } if (!(aStringLen && aString)) { return rv = NS_ERROR_UNEXPECTED; } // Make sure we're not seeing the result of a 404 or something by checking the // 'requestSucceeded' attribute on the http channel. nsCOMPtr<nsIRequest> request; rv = aLoader->GetRequest(getter_AddRefs(request)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(request)); if (httpChannel) { PRBool requestSucceeded; rv = httpChannel->GetRequestSucceeded(&requestSucceeded); NS_ENSURE_SUCCESS(rv, rv); if (!requestSucceeded) { return rv = NS_ERROR_NOT_AVAILABLE; } } nsIDocument* parentDoc = mWorker->Pool()->ParentDocument(); if (!parentDoc) { NS_ASSERTION(mWorker->IsCanceled(), "Null parent document when we're not canceled?!"); return rv = NS_ERROR_FAILURE; } // Use the regular nsScriptLoader for this grunt work! Should be just fine // because we're running on the main thread. rv = nsScriptLoader::ConvertToUTF16(loadInfo.channel, aString, aStringLen, EmptyString(), parentDoc, loadInfo.scriptText); if (NS_FAILED(rv)) { return rv; } if (loadInfo.scriptText.IsEmpty()) { return rv = NS_ERROR_FAILURE; } nsCString filename; loadInfo.finalURI->GetSpec(filename); if (filename.IsEmpty()) { filename.Assign(NS_LossyConvertUTF16toASCII(loadInfo.url)); } else { // This will help callers figure out what their script url resolved to in // case of errors. loadInfo.url.Assign(NS_ConvertUTF8toUTF16(filename)); } nsRefPtr<ScriptCompiler> compiler = new ScriptCompiler(this, loadInfo.scriptText, filename, loadInfo.scriptObj); NS_ASSERTION(compiler, "Out of memory!"); if (!compiler) { return rv = NS_ERROR_OUT_OF_MEMORY; } rv = mTarget->Dispatch(compiler, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return rv; }
nsresult CVE_2013_1709_thunderbird6_0_2_nsDocShell::AddToSessionHistory(nsIURI * aURI, nsIChannel * aChannel, nsISupports* aOwner, PRBool aCloneChildren, nsISHEntry ** aNewEntry) { NS_PRECONDITION(aURI, "uri is null"); NS_PRECONDITION(!aChannel || !aOwner, "Shouldn't have both set"); #if defined(PR_LOGGING) && defined(DEBUG) if (PR_LOG_TEST(gDocShellLog, PR_LOG_DEBUG)) { nsCAutoString spec; aURI->GetSpec(spec); nsCAutoString chanName; if (aChannel) aChannel->GetName(chanName); else chanName.AssignLiteral("<no channel>"); PR_LOG(gDocShellLog, PR_LOG_DEBUG, ("nsDocShell[%p]::AddToSessionHistory(\"%s\", [%s])\n", this, spec.get(), chanName.get())); } #endif nsresult rv = NS_OK; nsCOMPtr<nsISHEntry> entry; PRBool shouldPersist; shouldPersist = ShouldAddToSessionHistory(aURI); // Get a handle to the root docshell nsCOMPtr<nsIDocShellTreeItem> root; GetSameTypeRootTreeItem(getter_AddRefs(root)); /* * If this is a LOAD_FLAGS_REPLACE_HISTORY in a subframe, we use * the existing SH entry in the page and replace the url and * other vitalities. */ if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY) && root != static_cast<nsIDocShellTreeItem *>(this)) { // This is a subframe entry = mOSHE; nsCOMPtr<nsISHContainer> shContainer(do_QueryInterface(entry)); if (shContainer) { PRInt32 childCount = 0; shContainer->GetChildCount(&childCount); // Remove all children of this entry for (PRInt32 i = childCount - 1; i >= 0; i--) { nsCOMPtr<nsISHEntry> child; shContainer->GetChildAt(i, getter_AddRefs(child)); shContainer->RemoveChild(child); } // for } // shContainer } // Create a new entry if necessary. if (!entry) { entry = do_CreateInstance(NS_SHENTRY_CONTRACTID); if (!entry) { return NS_ERROR_OUT_OF_MEMORY; } } // Get the post data & referrer nsCOMPtr<nsIInputStream> inputStream; nsCOMPtr<nsIURI> referrerURI; nsCOMPtr<nsISupports> cacheKey; nsCOMPtr<nsISupports> owner = aOwner; PRBool expired = PR_FALSE; PRBool discardLayoutState = PR_FALSE; nsCOMPtr<nsICachingChannel> cacheChannel; if (aChannel) { cacheChannel = do_QueryInterface(aChannel); /* If there is a caching channel, get the Cache Key and store it * in SH. */ if (cacheChannel) { cacheChannel->GetCacheKey(getter_AddRefs(cacheKey)); } nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(aChannel)); // Check if the httpChannel is hiding under a multipartChannel if (!httpChannel) { GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); } if (httpChannel) { nsCOMPtr<nsIUploadChannel> uploadChannel(do_QueryInterface(httpChannel)); if (uploadChannel) { uploadChannel->GetUploadStream(getter_AddRefs(inputStream)); } httpChannel->GetReferrer(getter_AddRefs(referrerURI)); discardLayoutState = ShouldDiscardLayoutState(httpChannel); } aChannel->GetOwner(getter_AddRefs(owner)); } //Title is set in nsDocShell::SetTitle() entry->Create(aURI, // uri EmptyString(), // Title inputStream, // Post data stream nsnull, // LayoutHistory state cacheKey, // CacheKey mContentTypeHint, // Content-type owner, // Channel or provided owner mHistoryID, mDynamicallyCreated); entry->SetReferrerURI(referrerURI); /* If cache got a 'no-store', ask SH not to store * HistoryLayoutState. By default, SH will set this * flag to PR_TRUE and save HistoryLayoutState. */ if (discardLayoutState) { entry->SetSaveLayoutStateFlag(PR_FALSE); } if (cacheChannel) { // Check if the page has expired from cache PRUint32 expTime = 0; cacheChannel->GetCacheTokenExpirationTime(&expTime); PRUint32 now = PRTimeToSeconds(PR_Now()); if (expTime <= now) expired = PR_TRUE; } if (expired) entry->SetExpirationStatus(PR_TRUE); if (root == static_cast<nsIDocShellTreeItem *>(this) && mSessionHistory) { // If we need to clone our children onto the new session // history entry, do so now. if (aCloneChildren && mOSHE) { PRUint32 cloneID; mOSHE->GetID(&cloneID); nsCOMPtr<nsISHEntry> newEntry; CloneAndReplace(mOSHE, this, cloneID, entry, PR_TRUE, getter_AddRefs(newEntry)); NS_ASSERTION(entry == newEntry, "The new session history should be in the new entry"); } // This is the root docshell if (LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) { // Replace current entry in session history. PRInt32 index = 0; mSessionHistory->GetIndex(&index); nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory)); // Replace the current entry with the new entry if (shPrivate) rv = shPrivate->ReplaceEntry(index, entry); } else { // Add to session history nsCOMPtr<nsISHistoryInternal> shPrivate(do_QueryInterface(mSessionHistory)); NS_ENSURE_TRUE(shPrivate, NS_ERROR_FAILURE); mSessionHistory->GetIndex(&mPreviousTransIndex); rv = shPrivate->AddEntry(entry, shouldPersist); mSessionHistory->GetIndex(&mLoadedTransIndex); #ifdef DEBUG_PAGE_CACHE printf("Previous index: %d, Loaded index: %d\n\n", mPreviousTransIndex, mLoadedTransIndex); #endif } } else { // This is a subframe. if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) rv = DoAddChildSHEntry(entry, mChildOffset, aCloneChildren); } // Return the new SH entry... if (aNewEntry) { *aNewEntry = nsnull; if (NS_SUCCEEDED(rv)) { *aNewEntry = entry; NS_ADDREF(*aNewEntry); } } return rv; }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { 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 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; } } } // 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 // Set up the stream listener... rv = SetUpStreamListener(request, aURL); if (NS_FAILED(rv)) return rv; return rv; }