OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/loader/mojo_async_resource_handler.h" | 5 #include "content/browser/loader/mojo_async_resource_handler.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 | 123 |
124 GetRequestInfo()->set_on_transfer(base::Bind( | 124 GetRequestInfo()->set_on_transfer(base::Bind( |
125 &MojoAsyncResourceHandler::OnTransfer, weak_factory_.GetWeakPtr())); | 125 &MojoAsyncResourceHandler::OnTransfer, weak_factory_.GetWeakPtr())); |
126 } | 126 } |
127 | 127 |
128 MojoAsyncResourceHandler::~MojoAsyncResourceHandler() { | 128 MojoAsyncResourceHandler::~MojoAsyncResourceHandler() { |
129 if (has_checked_for_sufficient_resources_) | 129 if (has_checked_for_sufficient_resources_) |
130 rdh_->FinishedWithResourcesForRequest(request()); | 130 rdh_->FinishedWithResourcesForRequest(request()); |
131 } | 131 } |
132 | 132 |
133 bool MojoAsyncResourceHandler::OnRequestRedirected( | 133 void MojoAsyncResourceHandler::OnRequestRedirected( |
134 const net::RedirectInfo& redirect_info, | 134 const net::RedirectInfo& redirect_info, |
135 ResourceResponse* response, | 135 ResourceResponse* response, |
136 bool* defer) { | 136 std::unique_ptr<ResourceController> controller) { |
137 // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by | 137 // Unlike OnResponseStarted, OnRequestRedirected will NOT be preceded by |
138 // OnWillRead. | 138 // OnWillRead. |
| 139 DCHECK(!has_controller()); |
139 DCHECK(!shared_writer_); | 140 DCHECK(!shared_writer_); |
140 | 141 |
141 *defer = true; | |
142 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 142 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
| 143 set_controller(std::move(controller)); |
143 did_defer_on_redirect_ = true; | 144 did_defer_on_redirect_ = true; |
144 | 145 |
145 NetLogObserver::PopulateResponseInfo(request(), response); | 146 NetLogObserver::PopulateResponseInfo(request(), response); |
146 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); | 147 response->head.encoded_data_length = request()->GetTotalReceivedBytes(); |
147 response->head.request_start = request()->creation_time(); | 148 response->head.request_start = request()->creation_time(); |
148 response->head.response_start = base::TimeTicks::Now(); | 149 response->head.response_start = base::TimeTicks::Now(); |
149 // TODO(davidben): Is it necessary to pass the new first party URL for | 150 // TODO(davidben): Is it necessary to pass the new first party URL for |
150 // cookies? The only case where it can change is top-level navigation requests | 151 // cookies? The only case where it can change is top-level navigation requests |
151 // and hopefully those will eventually all be owned by the browser. It's | 152 // and hopefully those will eventually all be owned by the browser. It's |
152 // possible this is still needed while renderer-owned ones exist. | 153 // possible this is still needed while renderer-owned ones exist. |
153 url_loader_client_->OnReceiveRedirect(redirect_info, response->head); | 154 url_loader_client_->OnReceiveRedirect(redirect_info, response->head); |
154 return true; | |
155 } | 155 } |
156 | 156 |
157 bool MojoAsyncResourceHandler::OnResponseStarted(ResourceResponse* response, | 157 void MojoAsyncResourceHandler::OnResponseStarted( |
158 bool* defer) { | 158 ResourceResponse* response, |
| 159 std::unique_ptr<ResourceController> controller) { |
| 160 DCHECK(!has_controller()); |
| 161 |
159 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 162 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
160 | 163 |
161 if (rdh_->delegate()) { | 164 if (rdh_->delegate()) { |
162 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), | 165 rdh_->delegate()->OnResponseStarted(request(), info->GetContext(), |
163 response); | 166 response); |
164 } | 167 } |
165 | 168 |
166 NetLogObserver::PopulateResponseInfo(request(), response); | 169 NetLogObserver::PopulateResponseInfo(request(), response); |
167 | 170 |
168 response->head.request_start = request()->creation_time(); | 171 response->head.request_start = request()->creation_time(); |
169 response->head.response_start = base::TimeTicks::Now(); | 172 response->head.response_start = base::TimeTicks::Now(); |
170 sent_received_response_message_ = true; | 173 sent_received_response_message_ = true; |
171 | 174 |
172 mojom::DownloadedTempFilePtr downloaded_file_ptr; | 175 mojom::DownloadedTempFilePtr downloaded_file_ptr; |
173 if (!response->head.download_file_path.empty()) { | 176 if (!response->head.download_file_path.empty()) { |
174 downloaded_file_ptr = DownloadedTempFileImpl::Create(info->GetChildID(), | 177 downloaded_file_ptr = DownloadedTempFileImpl::Create(info->GetChildID(), |
175 info->GetRequestID()); | 178 info->GetRequestID()); |
176 rdh_->RegisterDownloadedTempFile(info->GetChildID(), info->GetRequestID(), | 179 rdh_->RegisterDownloadedTempFile(info->GetChildID(), info->GetRequestID(), |
177 response->head.download_file_path); | 180 response->head.download_file_path); |
178 } | 181 } |
179 | 182 |
180 url_loader_client_->OnReceiveResponse(response->head, | 183 url_loader_client_->OnReceiveResponse(response->head, |
181 std::move(downloaded_file_ptr)); | 184 std::move(downloaded_file_ptr)); |
182 return true; | 185 controller->Resume(); |
183 } | 186 } |
184 | 187 |
185 bool MojoAsyncResourceHandler::OnWillStart(const GURL& url, bool* defer) { | 188 void MojoAsyncResourceHandler::OnWillStart( |
186 return true; | 189 const GURL& url, |
| 190 std::unique_ptr<ResourceController> controller) { |
| 191 controller->Resume(); |
187 } | 192 } |
188 | 193 |
189 bool MojoAsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, | 194 bool MojoAsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf, |
190 int* buf_size, | 195 int* buf_size, |
191 int min_size) { | 196 int min_size) { |
192 DCHECK_EQ(-1, min_size); | 197 DCHECK_EQ(-1, min_size); |
193 | 198 |
| 199 // TODO(mmenke): Cancel with net::ERR_INSUFFICIENT_RESOURCES instead. |
194 if (!CheckForSufficientResource()) | 200 if (!CheckForSufficientResource()) |
195 return false; | 201 return false; |
196 | 202 |
197 if (!shared_writer_) { | 203 if (!shared_writer_) { |
198 MojoCreateDataPipeOptions options; | 204 MojoCreateDataPipeOptions options; |
199 options.struct_size = sizeof(MojoCreateDataPipeOptions); | 205 options.struct_size = sizeof(MojoCreateDataPipeOptions); |
200 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; | 206 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
201 options.element_num_bytes = 1; | 207 options.element_num_bytes = 1; |
202 options.capacity_num_bytes = g_allocation_size; | 208 options.capacity_num_bytes = g_allocation_size; |
203 mojo::DataPipe data_pipe(options); | 209 mojo::DataPipe data_pipe(options); |
(...skipping 27 matching lines...) Expand all Loading... |
231 is_using_io_buffer_not_from_writer_ = true; | 237 is_using_io_buffer_not_from_writer_ = true; |
232 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); | 238 buffer_ = new net::IOBufferWithSize(kMinAllocationSize); |
233 } | 239 } |
234 | 240 |
235 DCHECK_EQ(0u, buffer_offset_); | 241 DCHECK_EQ(0u, buffer_offset_); |
236 *buf = buffer_; | 242 *buf = buffer_; |
237 *buf_size = buffer_->size(); | 243 *buf_size = buffer_->size(); |
238 return true; | 244 return true; |
239 } | 245 } |
240 | 246 |
241 bool MojoAsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 247 void MojoAsyncResourceHandler::OnReadCompleted( |
| 248 int bytes_read, |
| 249 std::unique_ptr<ResourceController> controller) { |
| 250 DCHECK(!has_controller()); |
242 DCHECK_GE(bytes_read, 0); | 251 DCHECK_GE(bytes_read, 0); |
243 DCHECK(buffer_); | 252 DCHECK(buffer_); |
244 | 253 |
245 if (!bytes_read) | 254 if (!bytes_read) { |
246 return true; | 255 controller->Resume(); |
| 256 return; |
| 257 } |
247 | 258 |
248 if (is_using_io_buffer_not_from_writer_) { | 259 if (is_using_io_buffer_not_from_writer_) { |
249 // Couldn't allocate a buffer on the data pipe in OnWillRead. | 260 // Couldn't allocate a buffer on the data pipe in OnWillRead. |
250 DCHECK_EQ(0u, buffer_bytes_read_); | 261 DCHECK_EQ(0u, buffer_bytes_read_); |
251 buffer_bytes_read_ = bytes_read; | 262 buffer_bytes_read_ = bytes_read; |
252 if (!CopyReadDataToDataPipe(defer)) | 263 bool defer = false; |
253 return false; | 264 if (!CopyReadDataToDataPipe(&defer)) { |
254 if (*defer) { | 265 controller->Cancel(); |
| 266 return; |
| 267 } |
| 268 if (defer) { |
255 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 269 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
256 did_defer_on_writing_ = true; | 270 did_defer_on_writing_ = true; |
| 271 set_controller(std::move(controller)); |
| 272 return; |
257 } | 273 } |
258 return true; | 274 controller->Resume(); |
| 275 return; |
259 } | 276 } |
260 | 277 |
261 if (EndWrite(bytes_read) != MOJO_RESULT_OK) | 278 if (EndWrite(bytes_read) != MOJO_RESULT_OK) { |
262 return false; | 279 controller->Cancel(); |
| 280 return; |
| 281 } |
263 // Allocate a buffer for the next OnWillRead call here, because OnWillRead | 282 // Allocate a buffer for the next OnWillRead call here, because OnWillRead |
264 // doesn't have |defer| parameter. | 283 // doesn't have |defer| parameter. |
265 if (!AllocateWriterIOBuffer(&buffer_, defer)) | 284 bool defer = false; |
266 return false; | 285 if (!AllocateWriterIOBuffer(&buffer_, &defer)) { |
267 if (*defer) { | 286 controller->Cancel(); |
| 287 return; |
| 288 } |
| 289 if (defer) { |
268 request()->LogBlockedBy("MojoAsyncResourceHandler"); | 290 request()->LogBlockedBy("MojoAsyncResourceHandler"); |
269 did_defer_on_writing_ = true; | 291 did_defer_on_writing_ = true; |
| 292 set_controller(std::move(controller)); |
| 293 return; |
270 } | 294 } |
271 return true; | 295 |
| 296 controller->Resume(); |
272 } | 297 } |
273 | 298 |
274 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { | 299 void MojoAsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) { |
275 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); | 300 int64_t total_received_bytes = request()->GetTotalReceivedBytes(); |
276 int64_t bytes_to_report = | 301 int64_t bytes_to_report = |
277 total_received_bytes - reported_total_received_bytes_; | 302 total_received_bytes - reported_total_received_bytes_; |
278 reported_total_received_bytes_ = total_received_bytes; | 303 reported_total_received_bytes_ = total_received_bytes; |
279 DCHECK_LE(0, bytes_to_report); | 304 DCHECK_LE(0, bytes_to_report); |
280 | 305 |
281 url_loader_client_->OnDataDownloaded(bytes_downloaded, bytes_to_report); | 306 url_loader_client_->OnDataDownloaded(bytes_downloaded, bytes_to_report); |
282 } | 307 } |
283 | 308 |
284 void MojoAsyncResourceHandler::FollowRedirect() { | 309 void MojoAsyncResourceHandler::FollowRedirect() { |
285 if (!request()->status().is_success()) { | 310 if (!request()->status().is_success()) { |
286 DVLOG(1) << "FollowRedirect for invalid request"; | 311 DVLOG(1) << "FollowRedirect for invalid request"; |
287 return; | 312 return; |
288 } | 313 } |
289 if (!did_defer_on_redirect_) { | 314 if (!did_defer_on_redirect_) { |
290 DVLOG(1) << "Malformed FollowRedirect request"; | 315 DVLOG(1) << "Malformed FollowRedirect request"; |
291 ReportBadMessage("Malformed FollowRedirect request"); | 316 ReportBadMessage("Malformed FollowRedirect request"); |
292 return; | 317 return; |
293 } | 318 } |
294 | 319 |
295 DCHECK(!did_defer_on_writing_); | 320 DCHECK(!did_defer_on_writing_); |
296 did_defer_on_redirect_ = false; | 321 did_defer_on_redirect_ = false; |
297 request()->LogUnblocked(); | 322 request()->LogUnblocked(); |
298 controller()->Resume(); | 323 Resume(); |
299 } | 324 } |
300 | 325 |
301 void MojoAsyncResourceHandler::OnWritableForTesting() { | 326 void MojoAsyncResourceHandler::OnWritableForTesting() { |
302 OnWritable(MOJO_RESULT_OK); | 327 OnWritable(MOJO_RESULT_OK); |
303 } | 328 } |
304 | 329 |
305 void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { | 330 void MojoAsyncResourceHandler::SetAllocationSizeForTesting(size_t size) { |
306 g_allocation_size = size; | 331 g_allocation_size = size; |
307 } | 332 } |
308 | 333 |
309 MojoResult MojoAsyncResourceHandler::BeginWrite(void** data, | 334 MojoResult MojoAsyncResourceHandler::BeginWrite(void** data, |
310 uint32_t* available) { | 335 uint32_t* available) { |
311 MojoResult result = mojo::BeginWriteDataRaw( | 336 MojoResult result = mojo::BeginWriteDataRaw( |
312 shared_writer_->writer(), data, available, MOJO_WRITE_DATA_FLAG_NONE); | 337 shared_writer_->writer(), data, available, MOJO_WRITE_DATA_FLAG_NONE); |
313 if (result == MOJO_RESULT_OK) | 338 if (result == MOJO_RESULT_OK) |
314 *available = std::min(*available, static_cast<uint32_t>(kMaxChunkSize)); | 339 *available = std::min(*available, static_cast<uint32_t>(kMaxChunkSize)); |
315 return result; | 340 return result; |
316 } | 341 } |
317 | 342 |
318 MojoResult MojoAsyncResourceHandler::EndWrite(uint32_t written) { | 343 MojoResult MojoAsyncResourceHandler::EndWrite(uint32_t written) { |
319 return mojo::EndWriteDataRaw(shared_writer_->writer(), written); | 344 return mojo::EndWriteDataRaw(shared_writer_->writer(), written); |
320 } | 345 } |
321 | 346 |
322 void MojoAsyncResourceHandler::OnResponseCompleted( | 347 void MojoAsyncResourceHandler::OnResponseCompleted( |
323 const net::URLRequestStatus& status, | 348 const net::URLRequestStatus& status, |
324 bool* defer) { | 349 std::unique_ptr<ResourceController> controller) { |
325 shared_writer_ = nullptr; | 350 shared_writer_ = nullptr; |
326 buffer_ = nullptr; | 351 buffer_ = nullptr; |
327 handle_watcher_.Cancel(); | 352 handle_watcher_.Cancel(); |
328 | 353 |
329 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 354 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
330 | 355 |
331 // TODO(gavinp): Remove this CHECK when we figure out the cause of | 356 // TODO(gavinp): Remove this CHECK when we figure out the cause of |
332 // http://crbug.com/124680 . This check mirrors closely check in | 357 // http://crbug.com/124680 . This check mirrors closely check in |
333 // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore | 358 // WebURLLoaderImpl::OnCompletedRequest that routes this message to a WebCore |
334 // ResourceHandleInternal which asserts on its state and crashes. By crashing | 359 // ResourceHandleInternal which asserts on its state and crashes. By crashing |
(...skipping 13 matching lines...) Expand all Loading... |
348 ResourceRequestCompletionStatus request_complete_data; | 373 ResourceRequestCompletionStatus request_complete_data; |
349 request_complete_data.error_code = error_code; | 374 request_complete_data.error_code = error_code; |
350 request_complete_data.was_ignored_by_handler = was_ignored_by_handler; | 375 request_complete_data.was_ignored_by_handler = was_ignored_by_handler; |
351 request_complete_data.exists_in_cache = request()->response_info().was_cached; | 376 request_complete_data.exists_in_cache = request()->response_info().was_cached; |
352 request_complete_data.completion_time = base::TimeTicks::Now(); | 377 request_complete_data.completion_time = base::TimeTicks::Now(); |
353 request_complete_data.encoded_data_length = | 378 request_complete_data.encoded_data_length = |
354 request()->GetTotalReceivedBytes(); | 379 request()->GetTotalReceivedBytes(); |
355 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); | 380 request_complete_data.encoded_body_length = request()->GetRawBodyBytes(); |
356 | 381 |
357 url_loader_client_->OnComplete(request_complete_data); | 382 url_loader_client_->OnComplete(request_complete_data); |
| 383 controller->Resume(); |
358 } | 384 } |
359 | 385 |
360 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { | 386 bool MojoAsyncResourceHandler::CopyReadDataToDataPipe(bool* defer) { |
361 while (true) { | 387 while (true) { |
362 scoped_refptr<net::IOBufferWithSize> dest; | 388 scoped_refptr<net::IOBufferWithSize> dest; |
363 if (!AllocateWriterIOBuffer(&dest, defer)) | 389 if (!AllocateWriterIOBuffer(&dest, defer)) |
364 return false; | 390 return false; |
365 if (*defer) | 391 if (*defer) |
366 return true; | 392 return true; |
367 if (buffer_bytes_read_ == 0) { | 393 if (buffer_bytes_read_ == 0) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 } | 429 } |
404 | 430 |
405 bool MojoAsyncResourceHandler::CheckForSufficientResource() { | 431 bool MojoAsyncResourceHandler::CheckForSufficientResource() { |
406 if (has_checked_for_sufficient_resources_) | 432 if (has_checked_for_sufficient_resources_) |
407 return true; | 433 return true; |
408 has_checked_for_sufficient_resources_ = true; | 434 has_checked_for_sufficient_resources_ = true; |
409 | 435 |
410 if (rdh_->HasSufficientResourcesForRequest(request())) | 436 if (rdh_->HasSufficientResourcesForRequest(request())) |
411 return true; | 437 return true; |
412 | 438 |
413 controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES); | |
414 return false; | 439 return false; |
415 } | 440 } |
416 | 441 |
417 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { | 442 void MojoAsyncResourceHandler::OnWritable(MojoResult result) { |
418 if (!did_defer_on_writing_) | 443 if (!did_defer_on_writing_) |
419 return; | 444 return; |
| 445 DCHECK(has_controller()); |
420 DCHECK(!did_defer_on_redirect_); | 446 DCHECK(!did_defer_on_redirect_); |
421 did_defer_on_writing_ = false; | 447 did_defer_on_writing_ = false; |
422 | 448 |
423 if (is_using_io_buffer_not_from_writer_) { | 449 if (is_using_io_buffer_not_from_writer_) { |
424 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents | 450 // |buffer_| is set to a net::IOBufferWithSize. Write the buffer contents |
425 // to the data pipe. | 451 // to the data pipe. |
426 DCHECK_GT(buffer_bytes_read_, 0u); | 452 DCHECK_GT(buffer_bytes_read_, 0u); |
427 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { | 453 if (!CopyReadDataToDataPipe(&did_defer_on_writing_)) { |
428 controller()->CancelWithError(net::ERR_FAILED); | 454 CancelWithError(net::ERR_FAILED); |
429 return; | 455 return; |
430 } | 456 } |
431 } else { | 457 } else { |
432 // Allocate a buffer for the next OnWillRead call here. | 458 // Allocate a buffer for the next OnWillRead call here. |
433 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { | 459 if (!AllocateWriterIOBuffer(&buffer_, &did_defer_on_writing_)) { |
434 controller()->CancelWithError(net::ERR_FAILED); | 460 CancelWithError(net::ERR_FAILED); |
435 return; | 461 return; |
436 } | 462 } |
437 } | 463 } |
438 | 464 |
439 if (did_defer_on_writing_) { | 465 if (did_defer_on_writing_) { |
440 // Continue waiting. | 466 // Continue waiting. |
441 return; | 467 return; |
442 } | 468 } |
443 request()->LogUnblocked(); | 469 request()->LogUnblocked(); |
444 controller()->Resume(); | 470 Resume(); |
445 } | 471 } |
446 | 472 |
447 void MojoAsyncResourceHandler::Cancel() { | 473 void MojoAsyncResourceHandler::Cancel() { |
448 const ResourceRequestInfoImpl* info = GetRequestInfo(); | 474 const ResourceRequestInfoImpl* info = GetRequestInfo(); |
449 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( | 475 ResourceDispatcherHostImpl::Get()->CancelRequestFromRenderer( |
450 GlobalRequestID(info->GetChildID(), info->GetRequestID())); | 476 GlobalRequestID(info->GetChildID(), info->GetRequestID())); |
451 } | 477 } |
452 | 478 |
453 void MojoAsyncResourceHandler::ReportBadMessage(const std::string& error) { | 479 void MojoAsyncResourceHandler::ReportBadMessage(const std::string& error) { |
454 mojo::ReportBadMessage(error); | 480 mojo::ReportBadMessage(error); |
455 } | 481 } |
456 | 482 |
457 void MojoAsyncResourceHandler::OnTransfer( | 483 void MojoAsyncResourceHandler::OnTransfer( |
458 mojom::URLLoaderAssociatedRequest mojo_request, | 484 mojom::URLLoaderAssociatedRequest mojo_request, |
459 mojom::URLLoaderClientAssociatedPtr url_loader_client) { | 485 mojom::URLLoaderClientAssociatedPtr url_loader_client) { |
460 binding_.Unbind(); | 486 binding_.Unbind(); |
461 binding_.Bind(std::move(mojo_request)); | 487 binding_.Bind(std::move(mojo_request)); |
462 binding_.set_connection_error_handler( | 488 binding_.set_connection_error_handler( |
463 base::Bind(&MojoAsyncResourceHandler::Cancel, base::Unretained(this))); | 489 base::Bind(&MojoAsyncResourceHandler::Cancel, base::Unretained(this))); |
464 url_loader_client_ = std::move(url_loader_client); | 490 url_loader_client_ = std::move(url_loader_client); |
465 } | 491 } |
466 | 492 |
467 } // namespace content | 493 } // namespace content |
OLD | NEW |