mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 02:25:34 +00:00
Bug 1264177 - Implement FetchEvent.resultingClientId r=edenchuang,mrbkap
- Expose FetchEvent.resultingClientId on non-subresource, non-"report"-destination requests. - Delay Clients.get(FetchEvent.resultingClientId) resolution until the resulting client is execution ready. - Add WPTs to test for existence of resultingClientId and Clients.get promise resolution values. Differential Revision: https://phabricator.services.mozilla.com/D5333 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
b78d8dbce3
commit
84d5b8eb27
@ -18,7 +18,9 @@
|
||||
#include "mozilla/ipc/BackgroundParent.h"
|
||||
#include "mozilla/ipc/PBackgroundSharedTypes.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
#include "mozilla/SystemGroup.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "nsIAsyncShutdown.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsProxyRelease.h"
|
||||
@ -543,11 +545,34 @@ ClientManagerService::Claim(const ClientClaimArgs& aArgs)
|
||||
RefPtr<ClientOpPromise>
|
||||
ClientManagerService::GetInfoAndState(const ClientGetInfoAndStateArgs& aArgs)
|
||||
{
|
||||
RefPtr<ClientOpPromise> ref;
|
||||
|
||||
ClientSourceParent* source = FindSource(aArgs.id(), aArgs.principalInfo());
|
||||
if (!source || !source->ExecutionReady()) {
|
||||
ref = ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
|
||||
if (!source) {
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
if (!source->ExecutionReady()) {
|
||||
RefPtr<ClientManagerService> self = this;
|
||||
|
||||
// rejection ultimately converted to `undefined` in Clients::Get
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
source->ExecutionReadyPromise()
|
||||
->Then(GetCurrentThreadSerialEventTarget(), __func__,
|
||||
[self, aArgs] () -> RefPtr<ClientOpPromise> {
|
||||
ClientSourceParent* source = self->FindSource(aArgs.id(),
|
||||
aArgs.principalInfo());
|
||||
|
||||
if (!source) {
|
||||
RefPtr<ClientOpPromise> ref =
|
||||
ClientOpPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
return source->StartOp(aArgs);
|
||||
});
|
||||
|
||||
return ref.forget();
|
||||
}
|
||||
|
||||
|
@ -118,6 +118,8 @@ ClientSourceParent::RecvExecutionReady(const ClientSourceExecutionReadyArgs& aAr
|
||||
Unused << handle->SendExecutionReady(mClientInfo.ToIPC());
|
||||
}
|
||||
|
||||
mExecutionReadyPromise.ResolveIfExists(true, __func__);
|
||||
|
||||
return IPC_OK();
|
||||
};
|
||||
|
||||
@ -228,6 +230,8 @@ ClientSourceParent::ClientSourceParent(const ClientSourceConstructorArgs& aArgs)
|
||||
ClientSourceParent::~ClientSourceParent()
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mHandleList.IsEmpty());
|
||||
|
||||
mExecutionReadyPromise.RejectIfExists(NS_ERROR_FAILURE, __func__);
|
||||
}
|
||||
|
||||
void
|
||||
@ -268,6 +272,15 @@ ClientSourceParent::ExecutionReady() const
|
||||
return mExecutionReady;
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
ClientSourceParent::ExecutionReadyPromise()
|
||||
{
|
||||
// Only call if ClientSourceParent::ExecutionReady() is false; otherwise,
|
||||
// the promise will never resolve
|
||||
MOZ_ASSERT(!mExecutionReady);
|
||||
return mExecutionReadyPromise.Ensure(__func__);
|
||||
}
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
ClientSourceParent::GetController() const
|
||||
{
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "ClientOpPromise.h"
|
||||
#include "mozilla/dom/PClientSourceParent.h"
|
||||
#include "mozilla/dom/ServiceWorkerDescriptor.h"
|
||||
#include "mozilla/MozPromise.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -23,6 +24,7 @@ class ClientSourceParent final : public PClientSourceParent
|
||||
Maybe<ServiceWorkerDescriptor> mController;
|
||||
RefPtr<ClientManagerService> mService;
|
||||
nsTArray<ClientHandleParent*> mHandleList;
|
||||
MozPromiseHolder<GenericPromise> mExecutionReadyPromise;
|
||||
bool mExecutionReady;
|
||||
bool mFrozen;
|
||||
|
||||
@ -76,6 +78,9 @@ public:
|
||||
bool
|
||||
ExecutionReady() const;
|
||||
|
||||
RefPtr<GenericPromise>
|
||||
ExecutionReadyPromise();
|
||||
|
||||
const Maybe<ServiceWorkerDescriptor>&
|
||||
GetController() const;
|
||||
|
||||
|
@ -161,6 +161,7 @@ FetchEvent::Constructor(const GlobalObject& aGlobal,
|
||||
e->SetComposed(aOptions.mComposed);
|
||||
e->mRequest = aOptions.mRequest;
|
||||
e->mClientId = aOptions.mClientId;
|
||||
e->mResultingClientId = aOptions.mResultingClientId;
|
||||
e->mIsReload = aOptions.mIsReload;
|
||||
return e.forget();
|
||||
}
|
||||
|
@ -123,6 +123,7 @@ class FetchEvent final : public ExtendableEvent
|
||||
nsCString mScriptSpec;
|
||||
nsCString mPreventDefaultScriptSpec;
|
||||
nsString mClientId;
|
||||
nsString mResultingClientId;
|
||||
uint32_t mPreventDefaultLineNumber;
|
||||
uint32_t mPreventDefaultColumnNumber;
|
||||
bool mIsReload;
|
||||
@ -169,6 +170,12 @@ public:
|
||||
aClientId = mClientId;
|
||||
}
|
||||
|
||||
void
|
||||
GetResultingClientId(nsAString& aResultingClientId) const
|
||||
{
|
||||
aResultingClientId = mResultingClientId;
|
||||
}
|
||||
|
||||
bool
|
||||
IsReload() const
|
||||
{
|
||||
|
@ -2018,21 +2018,43 @@ public:
|
||||
}
|
||||
|
||||
nsString clientId;
|
||||
nsString resultingClientId;
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
|
||||
if (loadInfo) {
|
||||
char buf[NSID_LENGTH];
|
||||
Maybe<ClientInfo> clientInfo = loadInfo->GetClientInfo();
|
||||
if (clientInfo.isSome()) {
|
||||
char buf[NSID_LENGTH];
|
||||
clientInfo.ref().Id().ToProvidedString(buf);
|
||||
NS_ConvertASCIItoUTF16 uuid(buf);
|
||||
|
||||
// Remove {} and the null terminator
|
||||
clientId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
|
||||
}
|
||||
|
||||
// Having an initial or reserved client are mutually exclusive events:
|
||||
// either an initial client is used upon navigating an about:blank
|
||||
// iframe, or a new, reserved environment/client is created (e.g.
|
||||
// upon a top-level navigation). See step 4 of
|
||||
// https://html.spec.whatwg.org/#process-a-navigate-fetch as well as
|
||||
// https://github.com/w3c/ServiceWorker/issues/1228#issuecomment-345132444
|
||||
Maybe<ClientInfo> resulting = loadInfo->GetInitialClientInfo();
|
||||
|
||||
if (resulting.isNothing()) {
|
||||
resulting = loadInfo->GetReservedClientInfo();
|
||||
} else {
|
||||
MOZ_ASSERT(loadInfo->GetReservedClientInfo().isNothing());
|
||||
}
|
||||
|
||||
if (resulting.isSome()) {
|
||||
resulting.ref().Id().ToProvidedString(buf);
|
||||
NS_ConvertASCIItoUTF16 uuid(buf);
|
||||
|
||||
resultingClientId.Assign(Substring(uuid, 1, NSID_LENGTH - 3));
|
||||
}
|
||||
}
|
||||
|
||||
rv = mServiceWorkerPrivate->SendFetchEvent(mChannel, mLoadGroup, clientId,
|
||||
mIsReload);
|
||||
resultingClientId, mIsReload);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
HandleError();
|
||||
}
|
||||
|
@ -1309,6 +1309,7 @@ class FetchEventRunnable : public ExtendableFunctionalEventWorkerRunnable
|
||||
nsCString mFragment;
|
||||
nsCString mMethod;
|
||||
nsString mClientId;
|
||||
nsString mResultingClientId;
|
||||
bool mIsReload;
|
||||
bool mMarkLaunchServiceWorkerEnd;
|
||||
RequestCache mCacheMode;
|
||||
@ -1330,6 +1331,7 @@ public:
|
||||
const nsACString& aScriptSpec,
|
||||
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
|
||||
const nsAString& aClientId,
|
||||
const nsAString& aResultingClientId,
|
||||
bool aIsReload,
|
||||
bool aMarkLaunchServiceWorkerEnd)
|
||||
: ExtendableFunctionalEventWorkerRunnable(
|
||||
@ -1337,6 +1339,7 @@ public:
|
||||
, mInterceptedChannel(aChannel)
|
||||
, mScriptSpec(aScriptSpec)
|
||||
, mClientId(aClientId)
|
||||
, mResultingClientId(aResultingClientId)
|
||||
, mIsReload(aIsReload)
|
||||
, mMarkLaunchServiceWorkerEnd(aMarkLaunchServiceWorkerEnd)
|
||||
, mCacheMode(RequestCache::Default)
|
||||
@ -1624,12 +1627,26 @@ private:
|
||||
init.mBubbles = false;
|
||||
init.mCancelable = true;
|
||||
// Only expose the FetchEvent.clientId on subresource requests for now.
|
||||
// Once we implement .resultingClientId and .targetClientId we can then
|
||||
// start exposing .clientId on non-subresource requests as well. See
|
||||
// bug 1264177.
|
||||
// Once we implement .targetClientId we can then start exposing .clientId
|
||||
// on non-subresource requests as well. See bug 1487534.
|
||||
if (!mClientId.IsEmpty() && !internalReq->IsNavigationRequest()) {
|
||||
init.mClientId = mClientId;
|
||||
}
|
||||
|
||||
/*
|
||||
* https://w3c.github.io/ServiceWorker/#on-fetch-request-algorithm
|
||||
*
|
||||
* "If request is a non-subresource request and request’s
|
||||
* destination is not "report", initialize e’s resultingClientId attribute
|
||||
* to reservedClient’s [resultingClient's] id, and to the empty string
|
||||
* otherwise." (Step 18.8)
|
||||
*/
|
||||
if (!mResultingClientId.IsEmpty() &&
|
||||
nsContentUtils::IsNonSubresourceRequest(channel) &&
|
||||
internalReq->Destination() != RequestDestination::Report) {
|
||||
init.mResultingClientId = mResultingClientId;
|
||||
}
|
||||
|
||||
init.mIsReload = mIsReload;
|
||||
RefPtr<FetchEvent> event =
|
||||
FetchEvent::Constructor(globalObj, NS_LITERAL_STRING("fetch"), init, result);
|
||||
@ -1673,7 +1690,9 @@ NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVis
|
||||
nsresult
|
||||
ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aClientId, bool aIsReload)
|
||||
const nsAString& aClientId,
|
||||
const nsAString& aResultingClientId,
|
||||
bool aIsReload)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
@ -1742,7 +1761,8 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
RefPtr<FetchEventRunnable> r =
|
||||
new FetchEventRunnable(mWorkerPrivate, token, handle,
|
||||
mInfo->ScriptSpec(), regInfo,
|
||||
aClientId, aIsReload, newWorkerCreated);
|
||||
aClientId, aResultingClientId,
|
||||
aIsReload, newWorkerCreated);
|
||||
rv = r->Init();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -125,8 +125,11 @@ public:
|
||||
const nsAString& aScope);
|
||||
|
||||
nsresult
|
||||
SendFetchEvent(nsIInterceptedChannel* aChannel, nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aClientId, bool aIsReload);
|
||||
SendFetchEvent(nsIInterceptedChannel* aChannel,
|
||||
nsILoadGroup* aLoadGroup,
|
||||
const nsAString& aClientId,
|
||||
const nsAString& aResultingClientId,
|
||||
bool aIsReload);
|
||||
|
||||
bool
|
||||
MaybeStoreISupports(nsISupports* aSupports);
|
||||
|
@ -13,6 +13,7 @@
|
||||
interface FetchEvent : ExtendableEvent {
|
||||
[SameObject] readonly attribute Request request;
|
||||
readonly attribute DOMString clientId;
|
||||
readonly attribute DOMString resultingClientId;
|
||||
readonly attribute boolean isReload;
|
||||
|
||||
[Throws]
|
||||
@ -22,5 +23,6 @@ interface FetchEvent : ExtendableEvent {
|
||||
dictionary FetchEventInit : EventInit {
|
||||
required Request request;
|
||||
DOMString clientId = "";
|
||||
DOMString resultingClientId = "";
|
||||
boolean isReload = false;
|
||||
};
|
||||
|
@ -49,6 +49,162 @@ promise_test(function(t) {
|
||||
});
|
||||
}, 'Test Clients.get()');
|
||||
|
||||
promise_test((t) => {
|
||||
let frame = null;
|
||||
const scope = 'resources/simple.html';
|
||||
const outerSwContainer = navigator.serviceWorker;
|
||||
let innerSwReg = null;
|
||||
let innerSw = null;
|
||||
|
||||
return service_worker_unregister_and_register(
|
||||
t, 'resources/clients-get-resultingClientId-worker.js', scope)
|
||||
.then((registration) => {
|
||||
innerSwReg = registration;
|
||||
add_completion_callback(function() { registration.unregister(); });
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(() => {
|
||||
// load frame and get resulting client id
|
||||
let channel = new MessageChannel();
|
||||
innerSw = innerSwReg.active;
|
||||
|
||||
let p = new Promise(resolve => {
|
||||
function getResultingClientId(e) {
|
||||
if (e.data.msg == 'getResultingClientId') {
|
||||
const { resultingClientId } = e.data;
|
||||
|
||||
channel.port1.removeEventListener('message', getResultingClientId);
|
||||
|
||||
resolve({ resultingClientId, port: channel.port1 });
|
||||
}
|
||||
}
|
||||
|
||||
channel.port1.onmessage = getResultingClientId;
|
||||
});
|
||||
|
||||
|
||||
return with_iframe(scope).then((iframe) => {
|
||||
innerSw.postMessage(
|
||||
{ port: channel.port2, msg: 'getResultingClientId' },
|
||||
[channel.port2],
|
||||
);
|
||||
|
||||
frame = iframe;
|
||||
frame.focus();
|
||||
add_completion_callback(() => iframe.remove());
|
||||
|
||||
return p;
|
||||
});
|
||||
})
|
||||
.then(({ resultingClientId, port }) => {
|
||||
// query service worker for clients.get(resultingClientId)
|
||||
let channel = new MessageChannel();
|
||||
|
||||
let p = new Promise(resolve => {
|
||||
function getIsResultingClientUndefined(e) {
|
||||
if (e.data.msg == 'getIsResultingClientUndefined') {
|
||||
let { isResultingClientUndefined } = e.data;
|
||||
|
||||
port.removeEventListener('message', getIsResultingClientUndefined);
|
||||
|
||||
resolve(isResultingClientUndefined);
|
||||
}
|
||||
}
|
||||
|
||||
port.onmessage = getIsResultingClientUndefined;
|
||||
});
|
||||
|
||||
innerSw.postMessage(
|
||||
{ port: channel.port2, msg: 'getIsResultingClientUndefined', resultingClientId },
|
||||
[channel.port2],
|
||||
);
|
||||
|
||||
return p;
|
||||
})
|
||||
.then((isResultingClientUndefined) => {
|
||||
assert_false(isResultingClientUndefined, 'Clients.get(FetchEvent.resultingClientId) resolved with a Client');
|
||||
});
|
||||
}, 'Test successful Clients.get(FetchEvent.resultingClientId)');
|
||||
|
||||
promise_test((t) => {
|
||||
const scope = 'resources/simple.html?fail';
|
||||
const outerSwContainer = navigator.serviceWorker;
|
||||
let innerSwReg = null;
|
||||
let innerSw = null;
|
||||
|
||||
return service_worker_unregister_and_register(
|
||||
t, 'resources/clients-get-resultingClientId-worker.js', scope)
|
||||
.then((registration) => {
|
||||
innerSwReg = registration;
|
||||
add_completion_callback(function() { registration.unregister(); });
|
||||
return wait_for_state(t, registration.installing, 'activated');
|
||||
})
|
||||
.then(() => {
|
||||
// load frame, destroying it while loading, and get resulting client id
|
||||
innerSw = innerSwReg.active;
|
||||
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.className = 'test-iframe';
|
||||
iframe.src = scope;
|
||||
|
||||
function destroyIframe(e) {
|
||||
if (e.data.msg == 'destroyResultingClient') {
|
||||
iframe.remove();
|
||||
iframe = null;
|
||||
|
||||
innerSw.postMessage({ msg: 'resultingClientDestroyed' });
|
||||
}
|
||||
}
|
||||
|
||||
outerSwContainer.addEventListener('message', destroyIframe);
|
||||
|
||||
let p = new Promise(resolve => {
|
||||
function resultingClientDestroyedAck(e) {
|
||||
if (e.data.msg == 'resultingClientDestroyedAck') {
|
||||
let { resultingDestroyedClientId } = e.data;
|
||||
|
||||
outerSwContainer.removeEventListener('message', resultingClientDestroyedAck);
|
||||
resolve(resultingDestroyedClientId);
|
||||
}
|
||||
}
|
||||
|
||||
outerSwContainer.addEventListener('message', resultingClientDestroyedAck);
|
||||
});
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
return p;
|
||||
})
|
||||
.then((resultingDestroyedClientId) => {
|
||||
// query service worker for clients.get(resultingDestroyedClientId)
|
||||
let channel = new MessageChannel();
|
||||
|
||||
let p = new Promise((resolve, reject) => {
|
||||
function getIsResultingClientUndefined(e) {
|
||||
if (e.data.msg == 'getIsResultingClientUndefined') {
|
||||
let { isResultingClientUndefined } = e.data;
|
||||
|
||||
channel.port1.removeEventListener('message', getIsResultingClientUndefined);
|
||||
|
||||
resolve(isResultingClientUndefined);
|
||||
}
|
||||
}
|
||||
|
||||
channel.port1.onmessage = getIsResultingClientUndefined;
|
||||
});
|
||||
|
||||
innerSw.postMessage(
|
||||
{ port: channel.port2, msg: 'getIsResultingClientUndefined', resultingClientId: resultingDestroyedClientId },
|
||||
[channel.port2],
|
||||
);
|
||||
|
||||
return p;
|
||||
})
|
||||
.then((isResultingClientUndefined) => {
|
||||
assert_true(isResultingClientUndefined, 'Clients.get(FetchEvent.resultingClientId) resolved with `undefined`');
|
||||
});
|
||||
}, 'Test unsuccessful Clients.get(FetchEvent.resultingClientId)');
|
||||
|
||||
function wait_for_clientId() {
|
||||
return new Promise(function(resolve, reject) {
|
||||
function get_client_id(e) {
|
||||
|
@ -116,7 +116,6 @@ promise_test(t => {
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
var new_client_id = response_text.substr(17);
|
||||
assert_equals(
|
||||
response_text.substr(0, 15),
|
||||
'Client ID Found',
|
||||
@ -124,6 +123,28 @@ promise_test(t => {
|
||||
});
|
||||
}, 'Service Worker responds to fetch event with an existing client id');
|
||||
|
||||
promise_test(t => {
|
||||
const page_url = 'resources/simple.html?resultingClientId';
|
||||
const expected_found = 'Resulting Client ID Found';
|
||||
const expected_not_found = 'Resulting Client ID Not Found';
|
||||
return with_iframe(page_url)
|
||||
.then(function(frame) {
|
||||
t.add_cleanup(() => { frame.remove(); });
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent.substr(0, expected_found.length),
|
||||
expected_found,
|
||||
'Service Worker should respond with an existing resulting client id for non-subresource requests');
|
||||
return frame.contentWindow.fetch('resources/other.html?resultingClientId');
|
||||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
response_text.substr(0),
|
||||
expected_not_found,
|
||||
'Service Worker should respond with an empty resulting client id for subresource requests');
|
||||
});
|
||||
}, 'Service Worker responds to fetch event with the correct resulting client id');
|
||||
|
||||
promise_test(t => {
|
||||
const page_url = 'resources/simple.html?ignore';
|
||||
return with_iframe(page_url)
|
||||
|
@ -0,0 +1,64 @@
|
||||
let savedPort = null;
|
||||
let savedResultingClientId = null;
|
||||
|
||||
async function destroyResultingClient(e) {
|
||||
const outer = await self.clients.matchAll({ type: 'window', includeUncontrolled: true })
|
||||
.then((clientList) => {
|
||||
for (let c of clientList) {
|
||||
if (c.url.endsWith('clients-get.https.html')) {
|
||||
c.focus();
|
||||
return c;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const p = new Promise(resolve => {
|
||||
function resultingClientDestroyed(evt) {
|
||||
if (evt.data.msg == 'resultingClientDestroyed') {
|
||||
self.removeEventListener('message', resultingClientDestroyed);
|
||||
resolve(outer);
|
||||
}
|
||||
}
|
||||
|
||||
self.addEventListener('message', resultingClientDestroyed);
|
||||
});
|
||||
|
||||
outer.postMessage({ msg: 'destroyResultingClient' });
|
||||
|
||||
return await p;
|
||||
}
|
||||
|
||||
self.addEventListener('fetch', async (e) => {
|
||||
let { resultingClientId } = e;
|
||||
savedResultingClientId = resultingClientId;
|
||||
|
||||
if (e.request.url.endsWith('simple.html?fail')) {
|
||||
e.waitUntil(new Promise(async (resolve) => {
|
||||
let outer = await destroyResultingClient(e);
|
||||
|
||||
outer.postMessage({ msg: 'resultingClientDestroyedAck',
|
||||
resultingDestroyedClientId: savedResultingClientId });
|
||||
resolve();
|
||||
}));
|
||||
} else {
|
||||
e.respondWith(fetch(e.request));
|
||||
}
|
||||
});
|
||||
|
||||
self.addEventListener('message', (e) => {
|
||||
let { msg, port, resultingClientId } = e.data;
|
||||
savedPort = savedPort || port;
|
||||
|
||||
if (msg == 'getIsResultingClientUndefined') {
|
||||
self.clients.get(resultingClientId).then((client) => {
|
||||
let isUndefined = typeof client == 'undefined';
|
||||
savedPort.postMessage({ msg: 'getIsResultingClientUndefined',
|
||||
isResultingClientUndefined: isUndefined });
|
||||
});
|
||||
}
|
||||
|
||||
if (msg == 'getResultingClientId') {
|
||||
savedPort.postMessage({ msg: 'getResultingClientId',
|
||||
resultingClientId: savedResultingClientId });
|
||||
}
|
||||
});
|
@ -37,6 +37,16 @@ function handleClientId(event) {
|
||||
event.respondWith(new Response(body));
|
||||
}
|
||||
|
||||
function handleResultingClientId(event) {
|
||||
var body;
|
||||
if (event.resultingClientId !== "") {
|
||||
body = 'Resulting Client ID Found: ' + event.resultingClientId;
|
||||
} else {
|
||||
body = 'Resulting Client ID Not Found';
|
||||
}
|
||||
event.respondWith(new Response(body));
|
||||
}
|
||||
|
||||
function handleNullBody(event) {
|
||||
event.respondWith(new Response());
|
||||
}
|
||||
@ -155,6 +165,7 @@ self.addEventListener('fetch', function(event) {
|
||||
{ pattern: '?referrerPolicy', fn: handleReferrerPolicy },
|
||||
{ pattern: '?referrer', fn: handleReferrer },
|
||||
{ pattern: '?clientId', fn: handleClientId },
|
||||
{ pattern: '?resultingClientId', fn: handleResultingClientId },
|
||||
{ pattern: '?ignore', fn: function() {} },
|
||||
{ pattern: '?null', fn: handleNullBody },
|
||||
{ pattern: '?fetch', fn: handleFetch },
|
||||
|
Loading…
Reference in New Issue
Block a user