network_service_memory_cache_url_loader.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/network/network_service_memory_cache_url_loader.h"
  5. #include "base/bit_cast.h"
  6. #include "base/trace_event/common/trace_event_common.h"
  7. #include "base/trace_event/trace_event.h"
  8. #include "net/http/http_log_util.h"
  9. #include "services/network/network_service_memory_cache.h"
  10. #include "services/network/public/cpp/resource_request.h"
  11. #include "services/network/public/mojom/http_raw_headers.mojom.h"
  12. #include "services/network/public/mojom/ip_address_space.mojom.h"
  13. namespace network {
  14. NetworkServiceMemoryCacheURLLoader::NetworkServiceMemoryCacheURLLoader(
  15. NetworkServiceMemoryCache* memory_cache,
  16. uint64_t trace_id,
  17. const ResourceRequest& resource_request,
  18. const net::NetLogWithSource& net_log,
  19. mojo::PendingReceiver<mojom::URLLoader> receiver,
  20. mojo::PendingRemote<mojom::URLLoaderClient> client,
  21. scoped_refptr<base::RefCountedBytes> content,
  22. int64_t encoded_body_length)
  23. : memory_cache_(memory_cache),
  24. trace_id_(trace_id),
  25. net_log_(net_log),
  26. receiver_(this, std::move(receiver)),
  27. client_(std::move(client)),
  28. devtools_request_id_(resource_request.devtools_request_id),
  29. content_(std::move(content)),
  30. encoded_body_length_(encoded_body_length) {
  31. DCHECK(memory_cache_);
  32. TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
  33. "loading", "NetworkServiceMemoryCacheURLLoader",
  34. TRACE_ID_LOCAL(trace_id_), "url", resource_request.url.spec());
  35. if (resource_request.trusted_params &&
  36. resource_request.trusted_params->devtools_observer) {
  37. devtools_observer_.Bind(
  38. std::move(const_cast<mojo::PendingRemote<mojom::DevToolsObserver>&>(
  39. resource_request.trusted_params->devtools_observer)));
  40. }
  41. client_.set_disconnect_handler(
  42. base::BindOnce(&NetworkServiceMemoryCacheURLLoader::OnClientDisconnected,
  43. base::Unretained(this)));
  44. }
  45. NetworkServiceMemoryCacheURLLoader::~NetworkServiceMemoryCacheURLLoader() {
  46. TRACE_EVENT_NESTABLE_ASYNC_END0("loading",
  47. "NetworkServiceMemoryCacheURLLoader",
  48. TRACE_ID_LOCAL(trace_id_));
  49. }
  50. void NetworkServiceMemoryCacheURLLoader::Start(
  51. const ResourceRequest& resource_request,
  52. mojom::URLResponseHeadPtr response_head) {
  53. UpdateResponseHead(resource_request, response_head);
  54. MaybeNotifyRawResponse(*response_head);
  55. // Create a data pipe.
  56. MojoCreateDataPipeOptions options;
  57. options.struct_size = sizeof(MojoCreateDataPipeOptions);
  58. options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
  59. options.element_num_bytes = 1;
  60. options.capacity_num_bytes =
  61. memory_cache_->GetDataPipeCapacity(content_->size());
  62. mojo::ScopedDataPipeConsumerHandle consumer_handle;
  63. MojoResult result =
  64. mojo::CreateDataPipe(&options, producer_handle_, consumer_handle);
  65. if (result != MOJO_RESULT_OK) {
  66. Finish(net::ERR_FAILED);
  67. return;
  68. }
  69. net::NetLogRequestHeaders(
  70. net_log_, net::NetLogEventType::IN_MEMORY_CACHE_READ_REQUEST_HEADERS,
  71. /*request_line=*/"", &resource_request.headers);
  72. net::NetLogResponseHeaders(
  73. net_log_, net::NetLogEventType::IN_MEMORY_CACHE_READ_RESPONSE_HEADERS,
  74. response_head->headers.get());
  75. // Start sending the response.
  76. client_->OnReceiveResponse(std::move(response_head),
  77. std::move(consumer_handle));
  78. // Set up data pipe producer.
  79. producer_handle_watcher_ = std::make_unique<mojo::SimpleWatcher>(
  80. FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL,
  81. base::SequencedTaskRunnerHandle::Get());
  82. producer_handle_watcher_->Watch(
  83. producer_handle_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
  84. MOJO_WATCH_CONDITION_SATISFIED,
  85. base::BindRepeating(
  86. &NetworkServiceMemoryCacheURLLoader::OnProducerHandleReady,
  87. weak_ptr_factory_.GetWeakPtr()));
  88. WriteMore();
  89. }
  90. void NetworkServiceMemoryCacheURLLoader::UpdateResponseHead(
  91. const ResourceRequest& resource_request,
  92. mojom::URLResponseHeadPtr& response_head) {
  93. response_head->network_accessed = false;
  94. response_head->is_validated = false;
  95. response_head->was_fetched_via_cache = true;
  96. const base::Time now_time = base::Time::Now();
  97. const base::TimeTicks now_ticks = base::TimeTicks::Now();
  98. response_head->request_start = now_ticks;
  99. response_head->response_start = now_ticks;
  100. net::LoadTimingInfo load_timing;
  101. if (resource_request.enable_load_timing) {
  102. load_timing.request_start_time = now_time;
  103. load_timing.request_start = now_ticks;
  104. load_timing.send_start = now_ticks;
  105. load_timing.send_end = now_ticks;
  106. load_timing.receive_headers_start = now_ticks;
  107. load_timing.receive_headers_end = now_ticks;
  108. }
  109. response_head->load_timing = load_timing;
  110. }
  111. void NetworkServiceMemoryCacheURLLoader::MaybeNotifyRawResponse(
  112. const mojom::URLResponseHead& response_head) {
  113. if (!devtools_observer_ || !devtools_request_id_)
  114. return;
  115. std::vector<network::mojom::HttpRawHeaderPairPtr> header_array;
  116. size_t iter = 0;
  117. std::string name, value;
  118. while (response_head.headers->EnumerateHeaderLines(&iter, &name, &value)) {
  119. network::mojom::HttpRawHeaderPairPtr pair =
  120. network::mojom::HttpRawHeaderPair::New();
  121. pair->key = name;
  122. pair->value = value;
  123. header_array.push_back(std::move(pair));
  124. }
  125. devtools_observer_->OnRawResponse(
  126. *devtools_request_id_, /*cookies_with_access_result=*/{},
  127. std::move(header_array), /*raw_response_headers=*/absl::nullopt,
  128. mojom::IPAddressSpace::kUnknown, response_head.headers->response_code());
  129. }
  130. void NetworkServiceMemoryCacheURLLoader::WriteMore() {
  131. size_t original_write_position = write_position_;
  132. size_t total_write_size = 0;
  133. bool write_completed = false;
  134. while (true) {
  135. DCHECK_GE(content_->size(), write_position_);
  136. DCHECK_GE(std::numeric_limits<uint32_t>::max(),
  137. content_->size() - write_position_);
  138. uint32_t write_size =
  139. static_cast<uint32_t>(content_->size() - write_position_);
  140. if (write_size == 0) {
  141. write_completed = true;
  142. break;
  143. }
  144. MojoResult result =
  145. producer_handle_->WriteData(content_->data().data() + write_position_,
  146. &write_size, MOJO_WRITE_DATA_FLAG_NONE);
  147. if (result == MOJO_RESULT_SHOULD_WAIT) {
  148. producer_handle_watcher_->ArmOrNotify();
  149. break;
  150. }
  151. if (result != MOJO_RESULT_OK) {
  152. Finish(net::ERR_FAILED);
  153. return;
  154. }
  155. write_position_ += write_size;
  156. total_write_size += write_size;
  157. }
  158. TRACE_EVENT_NESTABLE_ASYNC_INSTANT2(
  159. "loading", "NetworkServiceMemoryCacheURLLoader::WriteMore",
  160. TRACE_ID_LOCAL(trace_id_), "write_position", write_position_,
  161. "total_write_bytes", total_write_size);
  162. if (net_log_.IsCapturing()) {
  163. net_log_.AddByteTransferEvent(
  164. net::NetLogEventType::IN_MEMORY_CACHE_BYTES_READ, total_write_size,
  165. base::bit_cast<const char*>(content_->data().data() +
  166. original_write_position));
  167. }
  168. if (write_completed) {
  169. Finish(net::OK);
  170. }
  171. }
  172. void NetworkServiceMemoryCacheURLLoader::OnProducerHandleReady(
  173. MojoResult result,
  174. const mojo::HandleSignalsState& state) {
  175. if (result == MOJO_RESULT_OK) {
  176. WriteMore();
  177. } else {
  178. Finish(net::ERR_FAILED);
  179. }
  180. }
  181. void NetworkServiceMemoryCacheURLLoader::Finish(int error_code) {
  182. TRACE_EVENT_NESTABLE_ASYNC_INSTANT0(
  183. "loading", "NetworkServiceMemoryCacheURLLoader::Finish",
  184. TRACE_ID_LOCAL(trace_id_));
  185. producer_handle_.reset();
  186. producer_handle_watcher_.reset();
  187. if (error_code == net::OK) {
  188. DCHECK(client_.is_connected());
  189. URLLoaderCompletionStatus status;
  190. status.error_code = net::OK;
  191. status.exists_in_cache = true;
  192. status.exists_in_memory_cache = true;
  193. status.completion_time = base::TimeTicks::Now();
  194. status.encoded_body_length = encoded_body_length_;
  195. status.decoded_body_length = content_->size();
  196. client_->OnComplete(status);
  197. } else if (client_.is_connected()) {
  198. URLLoaderCompletionStatus status;
  199. status.error_code = error_code;
  200. client_->OnComplete(status);
  201. }
  202. memory_cache_->OnLoaderCompleted(this);
  203. // `memory_cache_` deleted `this`.
  204. }
  205. void NetworkServiceMemoryCacheURLLoader::OnClientDisconnected() {
  206. Finish(net::ERR_FAILED);
  207. }
  208. void NetworkServiceMemoryCacheURLLoader::FollowRedirect(
  209. const std::vector<std::string>& removed_headers,
  210. const net::HttpRequestHeaders& modified_headers,
  211. const net::HttpRequestHeaders& modified_cors_exempt_headers,
  212. const absl::optional<GURL>& new_url) {
  213. NOTREACHED();
  214. }
  215. void NetworkServiceMemoryCacheURLLoader::SetPriority(
  216. net::RequestPriority priority,
  217. int32_t intra_priority_value) {}
  218. void NetworkServiceMemoryCacheURLLoader::PauseReadingBodyFromNet() {}
  219. void NetworkServiceMemoryCacheURLLoader::ResumeReadingBodyFromNet() {}
  220. } // namespace network