gin::Handle SimpleURLLoaderWrapper::Create()

in shell/browser/api/electron_api_url_loader.cc [391:543]


gin::Handle<SimpleURLLoaderWrapper> SimpleURLLoaderWrapper::Create(
    gin::Arguments* args) {
  gin_helper::Dictionary opts;
  if (!args->GetNext(&opts)) {
    args->ThrowTypeError("Expected a dictionary");
    return gin::Handle<SimpleURLLoaderWrapper>();
  }
  auto request = std::make_unique<network::ResourceRequest>();
  opts.Get("method", &request->method);
  opts.Get("url", &request->url);
  request->site_for_cookies = net::SiteForCookies::FromUrl(request->url);
  opts.Get("referrer", &request->referrer);
  std::string origin;
  opts.Get("origin", &origin);
  if (!origin.empty()) {
    request->request_initiator = url::Origin::Create(GURL(origin));
  }
  bool has_user_activation;
  if (opts.Get("hasUserActivation", &has_user_activation)) {
    request->trusted_params = network::ResourceRequest::TrustedParams();
    request->trusted_params->has_user_activation = has_user_activation;
  }

  std::string mode;
  if (opts.Get("mode", &mode) && !mode.empty()) {
    if (mode == "navigate") {
      request->mode = network::mojom::RequestMode::kNavigate;
    } else if (mode == "cors") {
      request->mode = network::mojom::RequestMode::kCors;
    } else if (mode == "no-cors") {
      request->mode = network::mojom::RequestMode::kNoCors;
    } else if (mode == "same-origin") {
      request->mode = network::mojom::RequestMode::kSameOrigin;
    }
  }

  std::string destination;
  if (opts.Get("destination", &destination) && !destination.empty()) {
    if (destination == "empty") {
      request->destination = network::mojom::RequestDestination::kEmpty;
    } else if (destination == "audio") {
      request->destination = network::mojom::RequestDestination::kAudio;
    } else if (destination == "audioworklet") {
      request->destination = network::mojom::RequestDestination::kAudioWorklet;
    } else if (destination == "document") {
      request->destination = network::mojom::RequestDestination::kDocument;
    } else if (destination == "embed") {
      request->destination = network::mojom::RequestDestination::kEmbed;
    } else if (destination == "font") {
      request->destination = network::mojom::RequestDestination::kFont;
    } else if (destination == "frame") {
      request->destination = network::mojom::RequestDestination::kFrame;
    } else if (destination == "iframe") {
      request->destination = network::mojom::RequestDestination::kIframe;
    } else if (destination == "image") {
      request->destination = network::mojom::RequestDestination::kImage;
    } else if (destination == "manifest") {
      request->destination = network::mojom::RequestDestination::kManifest;
    } else if (destination == "object") {
      request->destination = network::mojom::RequestDestination::kObject;
    } else if (destination == "paintworklet") {
      request->destination = network::mojom::RequestDestination::kPaintWorklet;
    } else if (destination == "report") {
      request->destination = network::mojom::RequestDestination::kReport;
    } else if (destination == "script") {
      request->destination = network::mojom::RequestDestination::kScript;
    } else if (destination == "serviceworker") {
      request->destination = network::mojom::RequestDestination::kServiceWorker;
    } else if (destination == "style") {
      request->destination = network::mojom::RequestDestination::kStyle;
    } else if (destination == "track") {
      request->destination = network::mojom::RequestDestination::kTrack;
    } else if (destination == "video") {
      request->destination = network::mojom::RequestDestination::kVideo;
    } else if (destination == "worker") {
      request->destination = network::mojom::RequestDestination::kWorker;
    } else if (destination == "xslt") {
      request->destination = network::mojom::RequestDestination::kXslt;
    }
  }

  bool credentials_specified =
      opts.Get("credentials", &request->credentials_mode);
  std::vector<std::pair<std::string, std::string>> extra_headers;
  if (opts.Get("extraHeaders", &extra_headers)) {
    for (const auto& it : extra_headers) {
      if (!net::HttpUtil::IsValidHeaderName(it.first) ||
          !net::HttpUtil::IsValidHeaderValue(it.second)) {
        args->ThrowTypeError("Invalid header name or value");
        return gin::Handle<SimpleURLLoaderWrapper>();
      }
      request->headers.SetHeader(it.first, it.second);
    }
  }

  bool use_session_cookies = false;
  opts.Get("useSessionCookies", &use_session_cookies);
  int options = 0;
  if (!credentials_specified && !use_session_cookies) {
    // This is the default case, as well as the case when credentials is not
    // specified and useSessionCoookies is false. credentials_mode will be
    // kInclude, but cookies will be blocked.
    request->credentials_mode = network::mojom::CredentialsMode::kInclude;
    options |= network::mojom::kURLLoadOptionBlockAllCookies;
  }

  v8::Local<v8::Value> body;
  v8::Local<v8::Value> chunk_pipe_getter;
  if (opts.Get("body", &body)) {
    if (body->IsArrayBufferView()) {
      auto buffer_body = body.As<v8::ArrayBufferView>();
      auto backing_store = buffer_body->Buffer()->GetBackingStore();
      request->request_body = network::ResourceRequestBody::CreateFromBytes(
          static_cast<char*>(backing_store->Data()) + buffer_body->ByteOffset(),
          buffer_body->ByteLength());
    } else if (body->IsFunction()) {
      auto body_func = body.As<v8::Function>();

      mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
          data_pipe_getter;
      chunk_pipe_getter = JSChunkedDataPipeGetter::Create(
                              args->isolate(), body_func,
                              data_pipe_getter.InitWithNewPipeAndPassReceiver())
                              .ToV8();
      request->request_body =
          base::MakeRefCounted<network::ResourceRequestBody>();
      request->request_body->SetToChunkedDataPipe(
          std::move(data_pipe_getter),
          network::ResourceRequestBody::ReadOnlyOnce(false));
    }
  }

  std::string partition;
  gin::Handle<Session> session;
  if (!opts.Get("session", &session)) {
    if (opts.Get("partition", &partition))
      session = Session::FromPartition(args->isolate(), partition);
    else  // default session
      session = Session::FromPartition(args->isolate(), "");
  }

  auto url_loader_factory = session->browser_context()->GetURLLoaderFactory();

  auto ret = gin::CreateHandle(
      args->isolate(),
      new SimpleURLLoaderWrapper(std::move(request), url_loader_factory.get(),
                                 options));
  ret->Pin();
  if (!chunk_pipe_getter.IsEmpty()) {
    ret->PinBodyGetter(chunk_pipe_getter);
  }
  return ret;
}