void ElectronURLLoaderFactory::StartLoading()

in shell/browser/net/electron_url_loader_factory.cc [309:424]


void ElectronURLLoaderFactory::StartLoading(
    mojo::PendingReceiver<network::mojom::URLLoader> loader,
    int32_t request_id,
    uint32_t options,
    const network::ResourceRequest& request,
    mojo::PendingRemote<network::mojom::URLLoaderClient> client,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
    mojo::PendingRemote<network::mojom::URLLoaderFactory> target_factory,
    ProtocolType type,
    gin::Arguments* args) {
  // Send network error when there is no argument passed.
  //
  // Note that we should not throw JS error in the callback no matter what is
  // passed, to keep compatibility with old code.
  v8::Local<v8::Value> response;
  if (!args->GetNext(&response)) {
    OnComplete(std::move(client), request_id,
               network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
    return;
  }

  // Parse {error} object.
  gin_helper::Dictionary dict = ToDict(args->isolate(), response);
  if (!dict.IsEmpty()) {
    int error_code;
    if (dict.Get("error", &error_code)) {
      OnComplete(std::move(client), request_id,
                 network::URLLoaderCompletionStatus(error_code));
      return;
    }
  }

  network::mojom::URLResponseHeadPtr head = ToResponseHead(dict);

  // Handle redirection.
  //
  // Note that with NetworkService, sending the "Location" header no longer
  // automatically redirects the request, we have explicitly create a new loader
  // to implement redirection. This is also what Chromium does with WebRequest
  // API in WebRequestProxyingURLLoaderFactory.
  std::string location;
  if (head->headers->IsRedirect(&location)) {
    // If the request is a MAIN_FRAME request, the first-party URL gets
    // updated on redirects.
    const net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy =
        request.resource_type ==
                static_cast<int>(blink::mojom::ResourceType::kMainFrame)
            ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT
            : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;

    net::RedirectInfo redirect_info = net::RedirectInfo::ComputeRedirectInfo(
        request.method, request.url, request.site_for_cookies,
        first_party_url_policy, request.referrer_policy,
        request.referrer.GetAsReferrer().spec(), head->headers->response_code(),
        request.url.Resolve(location),
        net::RedirectUtil::GetReferrerPolicyHeader(head->headers.get()), false);

    DCHECK(client.is_valid());

    mojo::Remote<network::mojom::URLLoaderClient> client_remote(
        std::move(client));

    client_remote->OnReceiveRedirect(redirect_info, std::move(head));

    // Bind the URLLoader receiver and wait for a FollowRedirect request, or for
    // the remote to disconnect, which will happen if the request is aborted.
    // That may happen when the redirect is to a different scheme, which will
    // cause the URL loader to be destroyed and a new one created using the
    // factory for that scheme.
    new RedirectedRequest(redirect_info, std::move(loader), request_id, options,
                          request, client_remote.Unbind(), traffic_annotation,
                          std::move(target_factory));

    return;
  }

  // Some protocol accepts non-object responses.
  if (dict.IsEmpty() && ResponseMustBeObject(type)) {
    OnComplete(std::move(client), request_id,
               network::URLLoaderCompletionStatus(net::ERR_NOT_IMPLEMENTED));
    return;
  }

  switch (type) {
    case ProtocolType::kBuffer:
      StartLoadingBuffer(std::move(client), std::move(head), dict);
      break;
    case ProtocolType::kString:
      StartLoadingString(std::move(client), std::move(head), dict,
                         args->isolate(), response);
      break;
    case ProtocolType::kFile:
      StartLoadingFile(std::move(loader), request, std::move(client),
                       std::move(head), dict, args->isolate(), response);
      break;
    case ProtocolType::kHttp:
      StartLoadingHttp(std::move(loader), request, std::move(client),
                       traffic_annotation, dict);
      break;
    case ProtocolType::kStream:
      StartLoadingStream(std::move(loader), std::move(client), std::move(head),
                         dict);
      break;
    case ProtocolType::kFree:
      ProtocolType type;
      if (!gin::ConvertFromV8(args->isolate(), response, &type)) {
        OnComplete(std::move(client), request_id,
                   network::URLLoaderCompletionStatus(net::ERR_FAILED));
        return;
      }
      StartLoading(std::move(loader), request_id, options, request,
                   std::move(client), traffic_annotation,
                   std::move(target_factory), type, args);
      break;
  }
}