 Chromium Code Reviews
 Chromium Code Reviews Issue 2843043002:
  network service: Create URLLoader for service worker navigation case
    
  
    Issue 2843043002:
  network service: Create URLLoader for service worker navigation case 
  | Index: content/browser/service_worker/service_worker_controllee_url_loader_factory.cc | 
| diff --git a/content/browser/service_worker/service_worker_controllee_url_loader_factory.cc b/content/browser/service_worker/service_worker_controllee_url_loader_factory.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..0311b26760977551e086bac7c69f614348c801a1 | 
| --- /dev/null | 
| +++ b/content/browser/service_worker/service_worker_controllee_url_loader_factory.cc | 
| @@ -0,0 +1,213 @@ | 
| +// Copyright 2017 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "content/browser/service_worker/service_worker_controllee_url_loader_factory.h" | 
| + | 
| +#include "content/common/service_worker/service_worker_utils.h" | 
| +#include "content/public/browser/browser_thread.h" | 
| +#include "mojo/public/cpp/system/data_pipe.h" | 
| +#include "net/base/io_buffer.h" | 
| +#include "storage/browser/blob/blob_data_handle.h" | 
| +#include "storage/browser/blob/blob_storage_context.h" | 
| + | 
| +namespace content { | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::CreateLoaderAndStart( | 
| + mojom::URLLoaderAssociatedRequest request, | 
| + int32_t routing_id, | 
| + int32_t request_id, | 
| + uint32_t options, | 
| + const ResourceRequest& url_request, | 
| + mojom::URLLoaderClientPtr client) { | 
| + request_ = std::move(request); | 
| + url_request_ = std::move(url_request); | 
| + client_ = std::move(client); | 
| +} | 
| + | 
| +ServiceWorkerControlleeURLLoaderFactory:: | 
| + ~ServiceWorkerControlleeURLLoaderFactory() {} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::SyncLoad( | 
| + int32_t routing_id, | 
| + int32_t request_id, | 
| + const ResourceRequest& request, | 
| + SyncLoadCallback callback) { | 
| + NOTREACHED(); | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::FallbackToNetwork() { | 
| + DCHECK_EQ(ResponseType::kNotDetermined, response_type_); | 
| + response_type_ = ResponseType::kFallbackToNetwork; | 
| + StartRequest(); | 
| +} | 
| + | 
| +bool ServiceWorkerControlleeURLLoaderFactory::ShouldFallbackToNetwork() { | 
| + return response_type_ == ResponseType::kFallbackToNetwork; | 
| +} | 
| + | 
| +ui::PageTransition | 
| +ServiceWorkerControlleeURLLoaderFactory::GetPageTransition() { | 
| + NOTIMPLEMENTED() << __FUNCTION__; | 
| + return ui::PAGE_TRANSITION_LINK; | 
| +} | 
| + | 
| +size_t ServiceWorkerControlleeURLLoaderFactory::GetURLChainSize() { | 
| + NOTIMPLEMENTED() << __FUNCTION__; | 
| + return 0; | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::ForwardToServiceWorker() { | 
| + DCHECK_EQ(ResponseType::kNotDetermined, response_type_); | 
| + response_type_ = ResponseType::kForwardToServiceWorker; | 
| + StartRequest(); | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::FallbackToNetworkOrRenderer() { | 
| + NOTIMPLEMENTED() << __FUNCTION__; | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::FailToNetworkOrRenderer() { | 
| + NOTIMPLEMENTED() << __FUNCTION__; | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::FailDueToLostController() { | 
| + NOTIMPLEMENTED() << __FUNCTION__; | 
| +} | 
| + | 
| +bool ServiceWorkerControlleeURLLoaderFactory::WasCanceled() const { | 
| + NOTIMPLEMENTED() << __FUNCTION__; | 
| + return false; | 
| +} | 
| + | 
| +std::unique_ptr<ServiceWorkerFetchRequest> | 
| +ServiceWorkerControlleeURLLoaderFactory::CreateFetchRequest() { | 
| + std::string blob_uuid; | 
| + uint64_t blob_size = 0; | 
| +#if 0 // TODO(scottmg): | 
| + if (HasRequestBody()) | 
| + CreateRequestBodyBlob(&blob_uuid, &blob_size); | 
| +#endif | 
| + std::unique_ptr<ServiceWorkerFetchRequest> request( | 
| + new ServiceWorkerFetchRequest()); | 
| + request->mode = request_mode_; | 
| + request->is_main_resource_load = | 
| + ServiceWorkerUtils::IsMainResourceType(resource_type_); | 
| + request->request_context_type = request_context_type_; | 
| + request->frame_type = frame_type_; | 
| + request->url = url_request_.url; | 
| + request->method = url_request_.method; | 
| +#if 0 // TODO(scottmg): | 
| + const net::HttpRequestHeaders& headers = request_->extra_request_headers(); | 
| + for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) { | 
| + if (ServiceWorkerContext::IsExcludedHeaderNameForFetchEvent(it.name())) | 
| + continue; | 
| + request->headers[it.name()] = it.value(); | 
| + } | 
| +#endif | 
| + request->blob_uuid = blob_uuid; | 
| + request->blob_size = blob_size; | 
| + request->credentials_mode = credentials_mode_; | 
| + request->redirect_mode = redirect_mode_; | 
| + request->client_id = client_id_; | 
| +#if 0 // TODO(scottmg): | 
| + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); | 
| + if (info) { | 
| + request->is_reload = ui::PageTransitionCoreTypeIs( | 
| + info->GetPageTransition(), ui::PAGE_TRANSITION_RELOAD); | 
| + request->referrer = | 
| + Referrer(GURL(request_->referrer()), info->GetReferrerPolicy()); | 
| + } else { | 
| + CHECK( | 
| + request_->referrer_policy() == | 
| + net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE); | 
| + request->referrer = | 
| + Referrer(GURL(request_->referrer()), blink::kWebReferrerPolicyDefault); | 
| + } | 
| +#endif | 
| + request->fetch_type = fetch_type_; | 
| + return request; | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::StartRequest() { | 
| + if (response_type_ != ResponseType::kForwardToServiceWorker) { | 
| + NOTIMPLEMENTED() << " Unexpected response type!"; | 
| + return; | 
| + } | 
| + DCHECK(!fetch_dispatcher_); | 
| + ServiceWorkerMetrics::URLRequestJobResult result = | 
| + ServiceWorkerMetrics::REQUEST_JOB_ERROR_BAD_DELEGATE; | 
| + ServiceWorkerVersion* active_worker = | 
| + delegate_->GetServiceWorkerVersion(&result); | 
| + fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher( | 
| + CreateFetchRequest(), active_worker, resource_type_, timeout_, | 
| + net::NetLogWithSource() /* TODO(scottmg): net log */, | 
| + base::Bind(&ServiceWorkerControlleeURLLoaderFactory::DidPrepareFetchEvent, | 
| + weak_factory_.GetWeakPtr(), active_worker), | 
| + base::Bind( | 
| + &ServiceWorkerControlleeURLLoaderFactory::DidDispatchFetchEvent, | 
| + weak_factory_.GetWeakPtr()))); | 
| + fetch_dispatcher_->Run(); | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::DidPrepareFetchEvent( | 
| + scoped_refptr<ServiceWorkerVersion> version) {} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::DidDispatchFetchEvent( | 
| + ServiceWorkerStatusCode status, | 
| + ServiceWorkerFetchEventResult fetch_result, | 
| + const ServiceWorkerResponse& response, | 
| + blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, | 
| + const scoped_refptr<ServiceWorkerVersion>& version) { | 
| + ResourceResponseHead head; | 
| + // TODO(scottmg): More stuff copied over. | 
| + head.headers = new net::HttpResponseHeaders(""); | 
| + for (const auto& kv : response.headers) | 
| + head.headers->AddHeader(kv.first + ": " + kv.second); | 
| + head.url_list_via_service_worker = response.url_list; | 
| + head.mime_type = "text/html"; // TODO(scottmg): No idea where to get this. | 
| + head.was_fetched_via_service_worker = true; | 
| + head.cors_exposed_header_names = response.cors_exposed_header_names; | 
| + client_->OnReceiveResponse(head, base::nullopt /* TODO(scottmg): ssl info */, | 
| + mojom::DownloadedTempFilePtr()); | 
| + | 
| + // TODO(scottmg): We'd prefer this! But for now we we have to use the blob as | 
| + // SWFetchDispatcher only offers blobs for normal fetches. | 
| + // https://docs.google.com/a/google.com/document/d/1_ROmusFvd8ATwIZa29-P6Ls5yyLjfld0KvKchVfA84Y/edit?usp=drive_web | 
| + DCHECK(body_as_stream.is_null()); | 
| 
falken
2017/05/08 08:20:33
I'm not sure I understand the "SWFetchDispatcher o
 
scottmg
2017/05/08 20:12:31
Oh, ok, thanks. This was just my ignorance. I only
 
falken
2017/05/09 08:20:15
Yea if I understand what Blob Servicification mean
 | 
| + | 
| + // TODO(scottmg): This is temporary hacky code to load the blob right here and | 
| + // turn it into a data pipe to respond with. | 
| + if (!response.blob_uuid.empty() && blob_storage_context_) { | 
| + std::unique_ptr<storage::BlobDataHandle> blob_data_handle = | 
| + blob_storage_context_->GetBlobDataFromUUID(response.blob_uuid); | 
| + blob_reader_ = blob_data_handle->CreateReader( | 
| + nullptr /* file system context */, | 
| + BrowserThread::GetTaskRunnerForThread(BrowserThread::FILE).get()); | 
| + CHECK(storage::BlobReader::Status::DONE == | 
| + blob_reader_->CalculateSize(net::CompletionCallback())); | 
| + blob_reader_->SetReadRange(0, blob_reader_->total_size()); | 
| + scoped_refptr<net::IOBuffer> buffer( | 
| + new net::IOBuffer(static_cast<size_t>(blob_reader_->total_size()))); | 
| + | 
| + int bytes_read; | 
| + auto status = blob_reader_->Read( | 
| + buffer.get(), blob_reader_->total_size(), &bytes_read, | 
| + base::Bind(&ServiceWorkerControlleeURLLoaderFactory::AfterRead, | 
| + weak_factory_.GetWeakPtr(), buffer)); | 
| + LOG(ERROR) << (int)status; | 
| + } | 
| +} | 
| + | 
| +void ServiceWorkerControlleeURLLoaderFactory::AfterRead( | 
| + scoped_refptr<net::IOBuffer> buffer, | 
| + int bytes) { | 
| + uint32_t bytes_written = static_cast<uint32_t>(bytes); | 
| + MojoResult result = | 
| + mojo::WriteDataRaw(data_pipe_.producer_handle.get(), buffer->data(), | 
| + &bytes_written, MOJO_WRITE_DATA_FLAG_NONE); | 
| + LOG(ERROR) << (int)result; | 
| + client_->OnStartLoadingResponseBody(std::move(data_pipe_.consumer_handle)); | 
| +} | 
| + | 
| +} // namespace content |