| 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..85a57f79a781a33b20f19b7c24740f3c9b36edc9
|
| --- /dev/null
|
| +++ b/content/browser/service_worker/service_worker_controllee_url_loader_factory.cc
|
| @@ -0,0 +1,261 @@
|
| +// 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.
|
| +}
|
| +
|
| +ServiceWorkerControlleeURLLoaderFactory::
|
| + ServiceWorkerControlleeURLLoaderFactory(
|
| + std::unique_ptr<ServiceWorkerRequestHandler> handler,
|
| + const std::string& client_id,
|
| + base::WeakPtr<storage::BlobStorageContext> blob_storage_context,
|
| + const ResourceContext* resource_context,
|
| + FetchRequestMode request_mode,
|
| + FetchCredentialsMode credentials_mode,
|
| + FetchRedirectMode redirect_mode,
|
| + ResourceType resource_type,
|
| + RequestContextType request_context_type,
|
| + RequestContextFrameType frame_type,
|
| + scoped_refptr<ResourceRequestBodyImpl> body,
|
| + ServiceWorkerFetchType fetch_type,
|
| + const base::Optional<base::TimeDelta>& timeout,
|
| + Delegate* delegate,
|
| + NetworkFallbackCallback network_fallback_callback)
|
| + : response_type_(ResponseType::kNotDetermined),
|
| + handler_(std::move(handler)),
|
| + client_id_(client_id),
|
| + blob_storage_context_(blob_storage_context),
|
| + request_mode_(request_mode),
|
| + credentials_mode_(credentials_mode),
|
| + redirect_mode_(redirect_mode),
|
| + resource_type_(resource_type),
|
| + request_context_type_(request_context_type),
|
| + frame_type_(frame_type),
|
| + body_(body),
|
| + fetch_type_(fetch_type),
|
| + timeout_(timeout),
|
| + delegate_(delegate),
|
| + network_fallback_callback_(network_fallback_callback),
|
| + weak_factory_(this) {}
|
| +
|
| +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(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
|
|
|