url_pipe_loader.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright (c) 2019 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/browser/net/url_pipe_loader.h"
  5. #include <utility>
  6. #include "base/task/sequenced_task_runner.h"
  7. #include "mojo/public/cpp/bindings/pending_remote.h"
  8. #include "mojo/public/cpp/system/string_data_source.h"
  9. #include "services/network/public/cpp/shared_url_loader_factory.h"
  10. #include "services/network/public/mojom/url_response_head.mojom.h"
  11. namespace electron {
  12. URLPipeLoader::URLPipeLoader(
  13. scoped_refptr<network::SharedURLLoaderFactory> factory,
  14. std::unique_ptr<network::ResourceRequest> request,
  15. mojo::PendingReceiver<network::mojom::URLLoader> loader,
  16. mojo::PendingRemote<network::mojom::URLLoaderClient> client,
  17. const net::NetworkTrafficAnnotationTag& annotation,
  18. base::Value::Dict upload_data)
  19. : url_loader_(this, std::move(loader)), client_(std::move(client)) {
  20. url_loader_.set_disconnect_handler(base::BindOnce(
  21. &URLPipeLoader::NotifyComplete, base::Unretained(this), net::ERR_FAILED));
  22. // PostTask since it might destruct.
  23. base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
  24. FROM_HERE,
  25. base::BindOnce(&URLPipeLoader::Start, weak_factory_.GetWeakPtr(), factory,
  26. std::move(request), annotation, std::move(upload_data)));
  27. }
  28. URLPipeLoader::~URLPipeLoader() = default;
  29. void URLPipeLoader::Start(
  30. scoped_refptr<network::SharedURLLoaderFactory> factory,
  31. std::unique_ptr<network::ResourceRequest> request,
  32. const net::NetworkTrafficAnnotationTag& annotation,
  33. base::Value::Dict upload_data) {
  34. loader_ = network::SimpleURLLoader::Create(std::move(request), annotation);
  35. loader_->SetOnResponseStartedCallback(base::BindOnce(
  36. &URLPipeLoader::OnResponseStarted, weak_factory_.GetWeakPtr()));
  37. // TODO(zcbenz): The old protocol API only supports string as upload data,
  38. // we should seek to support more types in future.
  39. std::string* content_type = upload_data.FindString("contentType");
  40. std::string* data = upload_data.FindString("data");
  41. if (content_type && data)
  42. loader_->AttachStringForUpload(*data, *content_type);
  43. loader_->DownloadAsStream(factory.get(), this);
  44. }
  45. void URLPipeLoader::NotifyComplete(int result) {
  46. client_->OnComplete(network::URLLoaderCompletionStatus(result));
  47. delete this;
  48. }
  49. void URLPipeLoader::OnResponseStarted(
  50. const GURL& final_url,
  51. const network::mojom::URLResponseHead& response_head) {
  52. mojo::ScopedDataPipeProducerHandle producer;
  53. mojo::ScopedDataPipeConsumerHandle consumer;
  54. MojoResult rv = mojo::CreateDataPipe(nullptr, producer, consumer);
  55. if (rv != MOJO_RESULT_OK) {
  56. NotifyComplete(net::ERR_INSUFFICIENT_RESOURCES);
  57. return;
  58. }
  59. producer_ = std::make_unique<mojo::DataPipeProducer>(std::move(producer));
  60. client_->OnReceiveResponse(response_head.Clone(), std::move(consumer),
  61. std::nullopt);
  62. }
  63. void URLPipeLoader::OnWrite(base::OnceClosure resume, MojoResult result) {
  64. if (result == MOJO_RESULT_OK)
  65. std::move(resume).Run();
  66. else
  67. NotifyComplete(net::ERR_FAILED);
  68. }
  69. void URLPipeLoader::OnDataReceived(base::StringPiece string_piece,
  70. base::OnceClosure resume) {
  71. producer_->Write(
  72. std::make_unique<mojo::StringDataSource>(
  73. string_piece, mojo::StringDataSource::AsyncWritingMode::
  74. STRING_MAY_BE_INVALIDATED_BEFORE_COMPLETION),
  75. base::BindOnce(&URLPipeLoader::OnWrite, weak_factory_.GetWeakPtr(),
  76. std::move(resume)));
  77. }
  78. void URLPipeLoader::OnRetry(base::OnceClosure start_retry) {
  79. NOTREACHED();
  80. }
  81. void URLPipeLoader::OnComplete(bool success) {
  82. NotifyComplete(loader_->NetError());
  83. }
  84. } // namespace electron