Beispiel #1
0
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::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);

  if (!requestSucceeded || !contentType.EqualsLiteral(TEXT_EVENT_STREAM)) {
    DispatchFailConnection();
    return NS_ERROR_NOT_AVAILABLE;
  }

  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::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;
}
Beispiel #4
0
nsresult
EventSource::InitChannelAndRequestEventSource()
{
  if (mReadyState == CLOSED) {
    return NS_ERROR_ABORT;
  }

  bool isValidScheme =
    (NS_SUCCEEDED(mSrc->SchemeIs("http", &isValidScheme)) && isValidScheme) ||
    (NS_SUCCEEDED(mSrc->SchemeIs("https", &isValidScheme)) && isValidScheme);

  nsresult rv = CheckInnerWindowCorrectness();
  if (NS_FAILED(rv) || !isValidScheme) {
    DispatchFailConnection();
    return NS_ERROR_DOM_SECURITY_ERR;
  }

  nsLoadFlags loadFlags;
  loadFlags = nsIRequest::LOAD_BACKGROUND | nsIRequest::LOAD_BYPASS_CACHE;

  nsIScriptContext* sc = GetContextForEventHandlers(&rv);
  nsCOMPtr<nsIDocument> doc =
    nsContentUtils::GetDocumentFromScriptContext(sc);

  nsSecurityFlags securityFlags =
    nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS;

  if (mWithCredentials) {
    securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
  }

  nsCOMPtr<nsIChannel> channel;
  // If we have the document, use it
  if (doc) {
    rv = NS_NewChannel(getter_AddRefs(channel),
                       mSrc,
                       doc,
                       securityFlags,
                       nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
                       mLoadGroup,       // loadGroup
                       nullptr,          // aCallbacks
                       loadFlags);       // aLoadFlags
  } else {
    // otherwise use the principal
    rv = NS_NewChannel(getter_AddRefs(channel),
                       mSrc,
                       mPrincipal,
                       securityFlags,
                       nsIContentPolicy::TYPE_INTERNAL_EVENTSOURCE,
                       mLoadGroup,       // loadGroup
                       nullptr,          // aCallbacks
                       loadFlags);       // aLoadFlags
  }

  NS_ENSURE_SUCCESS(rv, rv);

  mHttpChannel = do_QueryInterface(channel);
  NS_ENSURE_TRUE(mHttpChannel, NS_ERROR_NO_INTERFACE);

  rv = SetupHttpChannel();
  NS_ENSURE_SUCCESS(rv, rv);

#ifdef DEBUG
  {
    nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks;
    mHttpChannel->GetNotificationCallbacks(getter_AddRefs(notificationCallbacks));
    MOZ_ASSERT(!notificationCallbacks);
  }
#endif
  mHttpChannel->SetNotificationCallbacks(this);

  // Start reading from the channel
  rv = mHttpChannel->AsyncOpen2(this);
  if (NS_FAILED(rv)) {
    DispatchFailConnection();
    return rv;
  }
  mWaitingForOnStopRequest = true;
  return rv;
}