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..71989b81d838f76e52d5a6f4d9b8def6c4c64cad |
--- /dev/null |
+++ b/content/browser/service_worker/service_worker_controllee_url_loader_factory.cc |
@@ -0,0 +1,227 @@ |
+// 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) { |
+ LOG(ERROR) << "URL: " << url_request.url; |
+ request_ = std::move(request); |
+ url_request_ = std::move(url_request); |
+ client_ = std::move(client); |
+ // TODO(scottmg): This factory currently only handles one request due to the |
+ // way it's hooked up for navigation and with ServiceWorkerStorage. It should |
+ // probably delegate all its work to a URLLoaderImpl that's created here, but |
+ // that's not done yet to keep things a bit simpler for now. |
kinuko
2017/05/09 14:45:25
Maybe the main work should be done by URLLoader im
scottmg
2017/05/09 22:14:10
Yeah, agreed. It just adds even more boilerplate,
|
+} |
+ |
+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::kFallbackToNetwork) { |
+ // Need to restart the request, and send it through the network. |
+ BrowserThread::PostTask( |
+ BrowserThread::UI, FROM_HERE, |
+ base::Bind(network_fallback_callback_, |
+ base::Passed(std::move( |
+ base::MakeUnique<ResourceRequest>(url_request_))))); |
+ return; |
+ } |
+ 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()); |
+ |
+ // Ideally, we would always get a data pipe fom SWFetchDispatcher and use this |
+ // case. See: |
+ // https://docs.google.com/a/google.com/document/d/1_ROmusFvd8ATwIZa29-P6Ls5yyLjfld0KvKchVfA84Y/edit?usp=drive_web |
+ if (!body_as_stream.is_null() && body_as_stream->stream.is_valid()) { |
+ client_->OnStartLoadingResponseBody(std::move(body_as_stream->stream)); |
+ } else { |
+ // TODO(scottmg): This is temporary hacky to load the blob right here and |
+ // turn it into a data pipe to respond with, until we are always able to |
+ // take the above path. |
+ 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; |
+ blob_reader_->Read( |
+ buffer.get(), blob_reader_->total_size(), &bytes_read, |
+ base::Bind(&ServiceWorkerControlleeURLLoaderFactory::AfterRead, |
+ weak_factory_.GetWeakPtr(), buffer)); |
+ } |
+ } |
+} |
+ |
+void ServiceWorkerControlleeURLLoaderFactory::AfterRead( |
+ scoped_refptr<net::IOBuffer> buffer, |
+ int bytes) { |
+ uint32_t bytes_written = static_cast<uint32_t>(bytes); |
+ mojo::WriteDataRaw(data_pipe_.producer_handle.get(), buffer->data(), |
+ &bytes_written, MOJO_WRITE_DATA_FLAG_NONE); |
+ client_->OnStartLoadingResponseBody(std::move(data_pipe_.consumer_handle)); |
+} |
+ |
+} // namespace content |