nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream) { if (!mOutput) return NS_ERROR_NOT_INITIALIZED; nsresult rv = OnStartRequest(nullptr, nullptr); NS_ENSURE_SUCCESS(rv, rv); nsAutoArrayPtr<char> buffer(new char[4096]); NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY); uint32_t read = 0; uint32_t offset = 0; do { rv = aStream->Read(buffer.get(), 4096, &read); if (NS_FAILED(rv)) { OnStopRequest(nullptr, nullptr, rv); return rv; } if (read > 0) { rv = ProcessData(nullptr, nullptr, buffer.get(), offset, read); if (NS_FAILED(rv)) { OnStopRequest(nullptr, nullptr, rv); return rv; } offset += read; } } while (read > 0); return OnStopRequest(nullptr, nullptr, NS_OK); }
nsresult VectorImage::OnImageDataComplete(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus, bool aLastPart) { // Call our internal OnStopRequest method, which only talks to our embedded // SVG document. This won't have any effect on our ProgressTracker. nsresult finalStatus = OnStopRequest(aRequest, aContext, aStatus); // Give precedence to Necko failure codes. if (NS_FAILED(aStatus)) { finalStatus = aStatus; } Progress loadProgress = LoadCompleteProgress(aLastPart, mError, finalStatus); if (mIsFullyLoaded || mError) { // Our document is loaded, so we're ready to notify now. mProgressTracker->SyncNotifyProgress(loadProgress); } else { // Record our progress so far; we'll actually send the notifications in // OnSVGDocumentLoaded or OnSVGDocumentError. mLoadProgress = Some(loadProgress); } return finalStatus; }
nsresult VectorImage::OnImageDataComplete(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus) { return OnStopRequest(aRequest, aContext, aStatus); }
NS_IMETHODIMP nsImageLoadingContent::OnStopRequest(imgIRequest* aRequest, PRBool aLastPart) { NS_ENSURE_TRUE(nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); LOOP_OVER_OBSERVERS(OnStopRequest(aRequest, aLastPart)); return NS_OK; }
/* static */ void ProgressTracker::SyncNotifyInternal(ProxyArray& aProxies, bool aHasImage, Progress aProgress, const nsIntRect& aDirtyRect) { MOZ_ASSERT(NS_IsMainThread()); // OnStartRequest if (aProgress & FLAG_REQUEST_STARTED) NOTIFY_IMAGE_OBSERVERS(aProxies, OnStartRequest()); // OnStartContainer if (aProgress & FLAG_HAS_SIZE) NOTIFY_IMAGE_OBSERVERS(aProxies, OnStartContainer()); // OnStartDecode if (aProgress & FLAG_DECODE_STARTED) NOTIFY_IMAGE_OBSERVERS(aProxies, OnStartDecode()); // BlockOnload if (aProgress & FLAG_ONLOAD_BLOCKED) NOTIFY_IMAGE_OBSERVERS(aProxies, BlockOnload()); if (aHasImage) { // OnFrameUpdate // If there's any content in this frame at all (always true for // vector images, true for raster images that have decoded at // least one frame) then send OnFrameUpdate. if (!aDirtyRect.IsEmpty()) NOTIFY_IMAGE_OBSERVERS(aProxies, OnFrameUpdate(&aDirtyRect)); if (aProgress & FLAG_FRAME_STOPPED) NOTIFY_IMAGE_OBSERVERS(aProxies, OnStopFrame()); // OnImageIsAnimated if (aProgress & FLAG_IS_ANIMATED) NOTIFY_IMAGE_OBSERVERS(aProxies, OnImageIsAnimated()); } // Send UnblockOnload before OnStopDecode and OnStopRequest. This allows // observers that can fire events when they receive those notifications to do // so then, instead of being forced to wait for UnblockOnload. if (aProgress & FLAG_ONLOAD_UNBLOCKED) { NOTIFY_IMAGE_OBSERVERS(aProxies, UnblockOnload()); } if (aProgress & FLAG_DECODE_STOPPED) { MOZ_ASSERT(aHasImage, "Stopped decoding without ever having an image?"); NOTIFY_IMAGE_OBSERVERS(aProxies, OnStopDecode()); } if (aProgress & FLAG_REQUEST_STOPPED) { NOTIFY_IMAGE_OBSERVERS(aProxies, OnStopRequest(aProgress & FLAG_MULTIPART_STOPPED)); } }
bool HttpChannelChild::RecvOnStopRequest(const nsresult& statusCode) { if (mEventQ.ShouldEnqueue()) { mEventQ.Enqueue(new StopRequestEvent(this, statusCode)); } else { OnStopRequest(statusCode); } return true; }
NS_IMETHODIMP nsURLFetcher::OnStateChange(nsIWebProgress *aProgress, nsIRequest *aRequest, uint32_t aStateFlags, nsresult aStatus) { // all we care about is the case where an error occurred (as in we were unable to locate the // the url.... if (NS_FAILED(aStatus)) OnStopRequest(aRequest, nullptr, aStatus); return NS_OK; }
NS_IMETHODIMP nsAlertsIconListener::Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) { if (aType == imgINotificationObserver::LOAD_COMPLETE) { return OnStopRequest(aRequest); } if (aType == imgINotificationObserver::FRAME_COMPLETE) { return OnStopFrame(aRequest); } return NS_OK; }
NS_IMETHODIMP ImageDocument::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData) { if (aType == imgINotificationObserver::SIZE_AVAILABLE) { nsCOMPtr<imgIContainer> image; aRequest->GetImage(getter_AddRefs(image)); return OnStartContainer(aRequest, image); } nsDOMTokenList* classList = mImageContent->AsElement()->ClassList(); mozilla::ErrorResult rv; if (aType == imgINotificationObserver::DECODE_COMPLETE) { if (mImageContent && !nsContentUtils::IsChildOfSameType(this)) { // Update the background-color of the image only after the // image has been decoded to prevent flashes of just the // background-color. classList->Add(NS_LITERAL_STRING("decoded"), rv); NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode()); } } if (aType == imgINotificationObserver::DISCARD) { // mImageContent can be null if the document is already destroyed if (mImageContent && !nsContentUtils::IsChildOfSameType(this)) { // Remove any decoded-related styling when the image is unloaded. classList->Remove(NS_LITERAL_STRING("decoded"), rv); NS_ENSURE_SUCCESS(rv.ErrorCode(), rv.ErrorCode()); } } if (aType == imgINotificationObserver::LOAD_COMPLETE) { uint32_t reqStatus; aRequest->GetImageStatus(&reqStatus); nsresult status = reqStatus & imgIRequest::STATUS_ERROR ? NS_ERROR_FAILURE : NS_OK; return OnStopRequest(aRequest, status); } return NS_OK; }
nsresult VectorImage::OnImageDataComplete(nsIRequest* aRequest, nsISupports* aContext, nsresult aStatus, bool aLastPart) { // Call our internal OnStopRequest method, which only talks to our embedded // SVG document. This won't have any effect on our ProgressTracker. nsresult finalStatus = OnStopRequest(aRequest, aContext, aStatus); // Give precedence to Necko failure codes. if (NS_FAILED(aStatus)) finalStatus = aStatus; // Actually fire OnStopRequest. if (mProgressTracker) { mProgressTracker->SyncNotifyProgress(LoadCompleteProgress(aLastPart, mError, finalStatus)); } return finalStatus; }
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; }
// This is called when the channel is redirected. NS_IMETHODIMP FetchDriver::AsyncOnChannelRedirect(nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags, nsIAsyncVerifyRedirectCallback *aCallback) { NS_PRECONDITION(aNewChannel, "Redirect without a channel?"); nsresult rv; // HTTP Fetch step 5, "redirect status", step 1 if (NS_WARN_IF(mRequest->GetRedirectMode() == RequestRedirect::Error)) { aOldChannel->Cancel(NS_BINDING_FAILED); return NS_BINDING_FAILED; } // HTTP Fetch step 5, "redirect status", steps 2 through 6 are automatically // handled by necko before calling AsyncOnChannelRedirect() with the new // nsIChannel. // HTTP Fetch step 5, "redirect status", steps 7 and 8 enforcing a redirect // count are done by Necko. The pref used is "network.http.redirection-limit" // which is set to 20 by default. // HTTP Fetch Step 9, "redirect status". We only unset this for spec // compatibility. Any actions we take on mRequest here do not affect what the //channel does. mRequest->UnsetSameOriginDataURL(); // HTTP Fetch step 5, "redirect status", step 10 requires us to halt the // redirect, but successfully return an opaqueredirect Response to the // initiating Fetch. if (mRequest->GetRedirectMode() == RequestRedirect::Manual) { // Ideally we would simply not cancel the old channel and allow it to // be processed as normal. Unfortunately this is quite fragile and // other redirect handlers can easily break it for certain use cases. // // For example, nsCORSListenerProxy cancels vetoed redirect channels. // The HTTP cache will also error on vetoed redirects when the // redirect has been previously cached. // // Therefore simulate the completion of the channel to produce the // opaqueredirect Response and then cancel the original channel. This // will result in OnStartRequest() getting called twice, but the second // time will be with an error response (from the Cancel) which will // be ignored. mRequest->SetResponseTainting(InternalRequest::RESPONSETAINT_OPAQUEREDIRECT); unused << OnStartRequest(aOldChannel, nullptr); unused << OnStopRequest(aOldChannel, nullptr, NS_OK); aOldChannel->Cancel(NS_BINDING_FAILED); return NS_BINDING_FAILED; } // The following steps are from HTTP Fetch step 5, "redirect status", step 11 // which requires the RequestRedirect to be "follow". MOZ_ASSERT(mRequest->GetRedirectMode() == RequestRedirect::Follow); // HTTP Fetch step 5, "redirect status", steps 11.1 and 11.2 block redirecting // to a URL with credentials in CORS mode. This is implemented in // nsCORSListenerProxy. mRedirectCallback = aCallback; mOldRedirectChannel = aOldChannel; mNewRedirectChannel = aNewChannel; nsCOMPtr<nsIChannelEventSink> outer = do_GetInterface(mNotificationCallbacks); if (outer) { // The callee is supposed to call OnRedirectVerifyCallback() on success, // and nobody has to call it on failure, so we can just return after this // block. rv = outer->AsyncOnChannelRedirect(aOldChannel, aNewChannel, aFlags, this); if (NS_FAILED(rv)) { aOldChannel->Cancel(rv); mRedirectCallback = nullptr; mOldRedirectChannel = nullptr; mNewRedirectChannel = nullptr; } return rv; } (void) OnRedirectVerifyCallback(NS_OK); return NS_OK; }