diff options
Diffstat (limited to 'chromium/content/browser/service_worker/service_worker_navigation_loader.h')
-rw-r--r-- | chromium/content/browser/service_worker/service_worker_navigation_loader.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/chromium/content/browser/service_worker/service_worker_navigation_loader.h b/chromium/content/browser/service_worker/service_worker_navigation_loader.h new file mode 100644 index 00000000000..29293f14c99 --- /dev/null +++ b/chromium/content/browser/service_worker/service_worker_navigation_loader.h @@ -0,0 +1,187 @@ +// 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. + +#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_LOADER_H_ +#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_LOADER_H_ + +#include <memory> +#include <vector> + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "content/browser/loader/url_loader_request_handler.h" +#include "content/browser/service_worker/service_worker_fetch_dispatcher.h" +#include "content/browser/service_worker/service_worker_metrics.h" +#include "content/browser/service_worker/service_worker_response_type.h" +#include "content/browser/service_worker/service_worker_url_job_wrapper.h" +#include "content/browser/url_loader_factory_getter.h" +#include "content/common/service_worker/service_worker_status_code.h" +#include "content/common/service_worker/service_worker_types.h" +#include "mojo/public/cpp/bindings/strong_binding.h" +#include "mojo/public/cpp/system/data_pipe.h" +#include "services/network/public/mojom/url_loader.mojom.h" +#include "third_party/WebKit/public/mojom/blob/blob.mojom.h" +#include "third_party/WebKit/public/mojom/service_worker/service_worker_stream_handle.mojom.h" + +namespace content { + +struct ServiceWorkerResponse; +class ServiceWorkerVersion; + +// S13nServiceWorker: +// ServiceWorkerNavigationLoader is the URLLoader used for navigation requests +// that (potentially) go through a service worker. This loader is only used for +// the main resource request; once the navigation is committed, the page loads +// subresources via ServiceWorkerSubresourceLoader. +// +// This class works similarly to ServiceWorkerURLRequestJob but with +// network::mojom::URLLoader instead of URLRequest. +// +// This class is owned by the job wrapper until it is bound to a URLLoader +// request. After it is bound |this| is kept alive until the Mojo connection +// to this URLLoader is dropped. +class CONTENT_EXPORT ServiceWorkerNavigationLoader + : public network::mojom::URLLoader { + public: + using Delegate = ServiceWorkerURLJobWrapper::Delegate; + using ResponseType = ServiceWorkerResponseType; + + // Created by ServiceWorkerControlleeRequestHandler::MaybeCreateLoader + // when starting to load a page for navigation. + // + // This job typically works in the following order: + // 1. One of the FallbackTo* or ForwardTo* methods are called via + // URLJobWrapper by ServiceWorkerControlleeRequestHandler, which + // determines how the request should be served (e.g. should fallback + // to network or should be sent to the SW). If it decides to fallback + // to the network this will call |loader_callback| with a null + // RequestHandler, which will be then handled by + // NavigationURLLoaderNetworkService. + // 2. If it is decided that the request should be sent to the SW, + // this job dispatches a FetchEvent in StartRequest. + // 3. In DidDispatchFetchEvent() this job determines the request's + // final destination, and may still call |loader_callback| with null + // RequestHandler if it turns out that we need to fallback to the network. + // 4. Otherwise if the SW returned a stream or blob as a response + // this job calls |loader_callback| with a RequestHandler bound from + // StartResponse(). + // 5. Then StartResponse() will be called with a + // network::mojom::URLLoaderClientPtr that is connected to + // NavigationURLLoaderNetworkService (for resource loading for navigation). + // This forwards the blob/stream data pipe to the NavigationURLLoader if + // the response body was sent as a blob/stream. + ServiceWorkerNavigationLoader( + URLLoaderRequestHandler::LoaderCallback loader_callback, + Delegate* delegate, + const network::ResourceRequest& resource_request, + scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter); + + ~ServiceWorkerNavigationLoader() override; + + // Called via URLJobWrapper. + void FallbackToNetwork(); + void FallbackToNetworkOrRenderer(); + void ForwardToServiceWorker(); + bool ShouldFallbackToNetwork(); + void FailDueToLostController(); + void Cancel(); + bool WasCanceled() const; + + // The navigation request that was holding this job is + // going away. Calling this internally calls |DeleteIfNeeded()| + // and may delete |this| if it is not bound to a endpoint. + // Otherwise |this| will be kept around as far as the loader + // endpoint is held by the client. + void DetachedFromRequest(); + + private: + class StreamWaiter; + + // For FORWARD_TO_SERVICE_WORKER case. + void StartRequest(); + void DidPrepareFetchEvent(scoped_refptr<ServiceWorkerVersion> version); + void DidDispatchFetchEvent( + ServiceWorkerStatusCode status, + ServiceWorkerFetchDispatcher::FetchEventResult fetch_result, + const ServiceWorkerResponse& response, + blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, + blink::mojom::BlobPtr body_as_blob, + scoped_refptr<ServiceWorkerVersion> version); + + // Used as the RequestHandler passed to |loader_callback_| when the service + // worker chooses to handle a resource request. Returns the response to + // |client|. |body_as_blob| is kept around until BlobDataHandle is created + // from blob_uuid just to make sure the blob is kept alive. + void StartResponse(const ServiceWorkerResponse& response, + scoped_refptr<ServiceWorkerVersion> version, + blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream, + blink::mojom::BlobPtr body_as_blob, + network::mojom::URLLoaderRequest request, + network::mojom::URLLoaderClientPtr client); + + // Used as the RequestHandler passed to |loader_callback_| on error. Returns a + // network error to |client|. + void StartErrorResponse(network::mojom::URLLoaderRequest request, + network::mojom::URLLoaderClientPtr client); + + // Calls url_loader_client_->OnReceiveResopnse() with |response_head_|. + void CommitResponseHeaders(); + // Calls url_loader_client_->OnComplete(). Expected to be called after + // CommitResponseHeaders (i.e. status_ == kSentHeader). + void CommitCompleted(int error_code); + + // Calls |loader_callback_| with StartErrorResponse callback. Must not be + // called once either StartResponse or StartErrorResponse is called. + void ReturnNetworkError(); + + // network::mojom::URLLoader: + void FollowRedirect() override; + void ProceedWithResponse() override; + void SetPriority(net::RequestPriority priority, + int32_t intra_priority_value) override; + void PauseReadingBodyFromNet() override; + void ResumeReadingBodyFromNet() override; + + void OnBlobReadingComplete(int net_error); + + void DeleteIfNeeded(); + + ResponseType response_type_ = ResponseType::NOT_DETERMINED; + URLLoaderRequestHandler::LoaderCallback loader_callback_; + + Delegate* delegate_; + network::ResourceRequest resource_request_; + scoped_refptr<URLLoaderFactoryGetter> url_loader_factory_getter_; + std::unique_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_; + std::unique_ptr<StreamWaiter> stream_waiter_; + // The blob needs to be held while it's read to keep it alive. + blink::mojom::BlobPtr body_as_blob_; + + bool did_navigation_preload_ = false; + network::ResourceResponseHead response_head_; + base::Optional<net::SSLInfo> ssl_info_; + + // Pointer to the URLLoaderClient (i.e. NavigationURLLoader). + network::mojom::URLLoaderClientPtr url_loader_client_; + mojo::Binding<network::mojom::URLLoader> binding_; + + enum class Status { + kNotStarted, + kStarted, + kSentHeader, + kCompleted, + kCancelled + }; + Status status_ = Status::kNotStarted; + + bool detached_from_request_ = false; + + base::WeakPtrFactory<ServiceWorkerNavigationLoader> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(ServiceWorkerNavigationLoader); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_NAVIGATION_LOADER_H_ |