NS_IMETHODIMP EventSource::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) { mWaitingForOnStopRequest = false; if (mReadyState == CLOSED) { return NS_ERROR_ABORT; } if (NS_FAILED(aStatusCode)) { DispatchFailConnection(); return aStatusCode; } nsresult rv; nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest); if (NS_SUCCEEDED(healthOfRequestResult)) { // check if we had an incomplete UTF8 char at the end of the stream if (mLastConvertionResult == NS_PARTIAL_MORE_INPUT) { rv = ParseCharacter(REPLACEMENT_CHAR); NS_ENSURE_SUCCESS(rv, rv); } // once we reach the end of the stream we must // dispatch the current event switch (mStatus) { case PARSE_STATE_CR_CHAR: case PARSE_STATE_COMMENT: case PARSE_STATE_FIELD_NAME: case PARSE_STATE_FIRST_CHAR_OF_FIELD_VALUE: case PARSE_STATE_FIELD_VALUE: case PARSE_STATE_BEGIN_OF_LINE: rv = SetFieldAndClear(); NS_ENSURE_SUCCESS(rv, rv); rv = DispatchCurrentMessageEvent(); // there is an empty line (CRCR) NS_ENSURE_SUCCESS(rv, rv); break; // Just for not getting warnings when compiling case PARSE_STATE_OFF: case PARSE_STATE_BEGIN_OF_STREAM: case PARSE_STATE_BOM_WAS_READ: break; } } nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::ReestablishConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return healthOfRequestResult; }
NS_IMETHODIMP EventSource::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) { nsresult rv = CheckHealthOfRequestCallback(aRequest); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest, &rv); NS_ENSURE_SUCCESS(rv, rv); bool requestSucceeded; rv = httpChannel->GetRequestSucceeded(&requestSucceeded); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString contentType; rv = httpChannel->GetContentType(contentType); NS_ENSURE_SUCCESS(rv, rv); nsresult status; aRequest->GetStatus(&status); if (NS_FAILED(status) || !requestSucceeded || !contentType.EqualsLiteral(TEXT_EVENT_STREAM)) { DispatchFailConnection(); return NS_ERROR_NOT_AVAILABLE; } uint32_t httpStatus; rv = httpChannel->GetResponseStatus(&httpStatus); NS_ENSURE_SUCCESS(rv, rv); if (httpStatus != 200) { mInterrupted = true; DispatchFailConnection(); return NS_ERROR_ABORT; } nsCOMPtr<nsIPrincipal> principal = mPrincipal; if (nsContentUtils::IsSystemPrincipal(principal)) { // Don't give this channel the system principal. principal = do_CreateInstance("@mozilla.org/nullprincipal;1", &rv); NS_ENSURE_SUCCESS(rv, rv); } rv = httpChannel->SetOwner(principal); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::AnnounceConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); mStatus = PARSE_STATE_BEGIN_OF_STREAM; return NS_OK; }
NS_IMETHODIMP EventSource::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt) { nsresult rv = CheckHealthOfRequestCallback(aRequest); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest, &rv); NS_ENSURE_SUCCESS(rv, rv); nsresult status; rv = aRequest->GetStatus(&status); NS_ENSURE_SUCCESS(rv, rv); if (NS_FAILED(status)) { // EventSource::OnStopRequest will evaluate if it shall either reestablish // or fail the connection return NS_ERROR_ABORT; } uint32_t httpStatus; rv = httpChannel->GetResponseStatus(&httpStatus); NS_ENSURE_SUCCESS(rv, rv); if (httpStatus != 200) { DispatchFailConnection(); return NS_ERROR_ABORT; } nsAutoCString contentType; rv = httpChannel->GetContentType(contentType); NS_ENSURE_SUCCESS(rv, rv); if (!contentType.EqualsLiteral(TEXT_EVENT_STREAM)) { DispatchFailConnection(); return NS_ERROR_ABORT; } nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::AnnounceConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event); NS_ENSURE_SUCCESS(rv, rv); mStatus = PARSE_STATE_BEGIN_OF_STREAM; return NS_OK; }
NS_IMETHODIMP EventSource::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, uint64_t aOffset, uint32_t aCount) { NS_ENSURE_ARG_POINTER(aInputStream); nsresult rv = CheckHealthOfRequestCallback(aRequest); NS_ENSURE_SUCCESS(rv, rv); uint32_t totalRead; return aInputStream->ReadSegments(EventSource::StreamReaderFunc, this, aCount, &totalRead); }
NS_IMETHODIMP EventSource::AsyncOnChannelRedirect(nsIChannel *aOldChannel, nsIChannel *aNewChannel, uint32_t aFlags, nsIAsyncVerifyRedirectCallback *aCallback) { nsCOMPtr<nsIRequest> aOldRequest = do_QueryInterface(aOldChannel); NS_PRECONDITION(aOldRequest, "Redirect from a null request?"); nsresult rv = CheckHealthOfRequestCallback(aOldRequest); NS_ENSURE_SUCCESS(rv, rv); NS_PRECONDITION(aNewChannel, "Redirect without a channel?"); nsCOMPtr<nsIURI> newURI; rv = NS_GetFinalChannelURI(aNewChannel, getter_AddRefs(newURI)); NS_ENSURE_SUCCESS(rv, rv); bool isValidScheme = (NS_SUCCEEDED(newURI->SchemeIs("http", &isValidScheme)) && isValidScheme) || (NS_SUCCEEDED(newURI->SchemeIs("https", &isValidScheme)) && isValidScheme); rv = CheckInnerWindowCorrectness(); if (NS_FAILED(rv) || !isValidScheme) { DispatchFailConnection(); return NS_ERROR_DOM_SECURITY_ERR; } // update our channel mHttpChannel = do_QueryInterface(aNewChannel); NS_ENSURE_STATE(mHttpChannel); rv = SetupHttpChannel(); NS_ENSURE_SUCCESS(rv, rv); if ((aFlags & nsIChannelEventSink::REDIRECT_PERMANENT) != 0) { rv = NS_GetFinalChannelURI(mHttpChannel, getter_AddRefs(mSrc)); NS_ENSURE_SUCCESS(rv, rv); } aCallback->OnRedirectVerifyCallback(NS_OK); return NS_OK; }
NS_IMETHODIMP EventSource::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) { mWaitingForOnStopRequest = false; if (mReadyState == CLOSED) { return NS_ERROR_ABORT; } // "Network errors that prevents the connection from being established in the // first place (e.g. DNS errors), must cause the user agent to asynchronously // reestablish the connection. // // (...) the cancelation of the fetch algorithm by the user agent (e.g. in // response to window.stop() or the user canceling the network connection // manually) must cause the user agent to fail the connection. if (NS_FAILED(aStatusCode) && aStatusCode != NS_ERROR_CONNECTION_REFUSED && aStatusCode != NS_ERROR_NET_TIMEOUT && aStatusCode != NS_ERROR_NET_RESET && aStatusCode != NS_ERROR_NET_INTERRUPT && aStatusCode != NS_ERROR_PROXY_CONNECTION_REFUSED && aStatusCode != NS_ERROR_DNS_LOOKUP_QUEUE_FULL) { DispatchFailConnection(); return NS_ERROR_ABORT; } nsresult rv = CheckHealthOfRequestCallback(aRequest); NS_ENSURE_SUCCESS(rv, rv); ClearFields(); nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::ReestablishConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
NS_IMETHODIMP EventSource::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext, nsresult aStatusCode) { mWaitingForOnStopRequest = false; if (mReadyState == CLOSED) { return NS_ERROR_ABORT; } if (NS_FAILED(aStatusCode)) { DispatchFailConnection(); return aStatusCode; } nsresult rv; nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest); if (NS_SUCCEEDED(healthOfRequestResult) && mLastConvertionResult == NS_PARTIAL_MORE_INPUT) { // we had an incomplete UTF8 char at the end of the stream rv = ParseCharacter(REPLACEMENT_CHAR); NS_ENSURE_SUCCESS(rv, rv); } ClearFields(); nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &EventSource::ReestablishConnection); NS_ENSURE_STATE(event); rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL); NS_ENSURE_SUCCESS(rv, rv); return healthOfRequestResult; }