1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
|
// Copyright 2014 The Chromium Authors
// 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_FETCH_DISPATCHER_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_
#include <memory>
#include <string>
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h"
#include "third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_fetch_response_callback.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_stream_handle.mojom.h"
namespace content {
class ServiceWorkerClient;
class ServiceWorkerContextWrapper;
class ServiceWorkerVersion;
// A helper class to dispatch fetch event to a service worker.
class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
public:
// Indicates how the service worker handled a fetch event.
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class FetchEventResult {
// Browser should fallback to native fetch.
kShouldFallback = 0,
// Service worker provided a ServiceWorkerResponse.
kGotResponse = 1,
kMaxValue = kGotResponse,
};
using FetchCallback =
base::OnceCallback<void(blink::ServiceWorkerStatusCode,
FetchEventResult,
blink::mojom::FetchAPIResponsePtr,
blink::mojom::ServiceWorkerStreamHandlePtr,
blink::mojom::ServiceWorkerFetchEventTimingPtr,
scoped_refptr<ServiceWorkerVersion>)>;
using WebContentsGetter = base::RepeatingCallback<WebContents*()>;
ServiceWorkerFetchDispatcher(blink::mojom::FetchAPIRequestPtr request,
network::mojom::RequestDestination destination,
const std::string& client_id,
const std::string& resulting_client_id,
scoped_refptr<ServiceWorkerVersion> version,
base::OnceClosure prepare_callback,
FetchCallback fetch_callback);
ServiceWorkerFetchDispatcher(const ServiceWorkerFetchDispatcher&) = delete;
ServiceWorkerFetchDispatcher& operator=(const ServiceWorkerFetchDispatcher&) =
delete;
~ServiceWorkerFetchDispatcher();
static const char* FetchEventResultToSuffix(FetchEventResult result);
// If appropriate, starts the navigation preload request and creates
// |preload_handle_|. Returns true if it started navigation preload.
bool MaybeStartNavigationPreload(
const network::ResourceRequest& original_request,
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
base::WeakPtr<ServiceWorkerClient> service_worker_client);
// Dispatches a fetch event to the |version| given in ctor, and fires
// |fetch_callback_| (also given in ctor) once a response is received from the
// service worker. It runs |prepare_callback_| as an intermediate step once
// the version is activated and running.
void Run();
bool FetchCallbackIsNull() { return fetch_callback_.is_null(); }
static void ForceDisableHighPriorityFetchResponseCallbackForTesting(
bool force_disable);
void set_race_network_request_token(base::UnguessableToken token) {
race_network_request_token_ = token;
}
void set_race_network_request_loader_factory(
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory) {
race_network_request_loader_factory_ = std::move(factory);
}
private:
class ResponseCallback;
class URLLoaderAssets;
void DidWaitForActivation();
void StartWorker();
void DidStartWorker(blink::ServiceWorkerStatusCode status);
void DispatchFetchEvent();
void DidFailToDispatch(std::unique_ptr<ResponseCallback> callback,
blink::ServiceWorkerStatusCode status);
void DidFail(blink::ServiceWorkerStatusCode status);
void DidFinish(int request_id,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing);
void RunCallback(blink::ServiceWorkerStatusCode status,
FetchEventResult fetch_result,
blink::mojom::FetchAPIResponsePtr response,
blink::mojom::ServiceWorkerStreamHandlePtr body_as_stream,
blink::mojom::ServiceWorkerFetchEventTimingPtr timing);
// The fetch event stays open until all respondWith() and waitUntil() promises
// are settled. This function is called once the renderer signals that
// happened. |fetch_callback_| can run before this, once respondWith() is
// settled.
static void OnFetchEventFinished(
base::WeakPtr<ServiceWorkerFetchDispatcher> fetch_dispatcher,
ServiceWorkerVersion* version,
int event_finish_id,
scoped_refptr<URLLoaderAssets> url_loader_assets,
blink::mojom::ServiceWorkerEventStatus status);
ServiceWorkerMetrics::EventType GetEventType() const;
bool IsEventDispatched() const;
blink::mojom::FetchAPIRequestPtr request_;
std::string client_id_;
std::string resulting_client_id_;
scoped_refptr<ServiceWorkerVersion> version_;
const network::mojom::RequestDestination destination_;
base::OnceClosure prepare_callback_;
FetchCallback fetch_callback_;
scoped_refptr<URLLoaderAssets> url_loader_assets_;
// Holds the URLLoaderClient for the service worker to receive the navigation
// preload response. It's passed to the service worker along with the fetch
// event.
mojo::PendingReceiver<network::mojom::URLLoaderClient>
preload_url_loader_client_receiver_;
base::UnguessableToken race_network_request_token_;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
race_network_request_loader_factory_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_FETCH_DISPATCHER_H_
|