Bug 1222464 - Part 2: Implement FetchEvent.clientId; r=jdm

This commit is contained in:
Ehsan Akhgari 2015-11-25 18:05:34 -05:00
parent acab631b47
commit a726d074a1
12 changed files with 90 additions and 12 deletions

View File

@ -14181,7 +14181,8 @@ nsDocShell::ChannelIntercepted(nsIInterceptedChannel* aChannel,
ErrorResult error;
nsCOMPtr<nsIRunnable> runnable =
swm->PrepareFetchEvent(attrs, doc, aChannel, isReload, isSubresourceLoad, error);
swm->PrepareFetchEvent(attrs, doc, mInterceptedDocumentId, aChannel,
isReload, isSubresourceLoad, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}

View File

@ -12,6 +12,7 @@
Exposed=(ServiceWorker)]
interface FetchEvent : ExtendableEvent {
[SameObject] readonly attribute Request? request;
readonly attribute DOMString? clientId;
readonly attribute boolean isReload;
[Throws]
@ -20,5 +21,6 @@ interface FetchEvent : ExtendableEvent {
dictionary FetchEventInit : EventInit {
Request request;
DOMString? clientId = null;
boolean isReload = false;
};

View File

@ -33,6 +33,11 @@ class ServiceWorkerClientInfo final
public:
explicit ServiceWorkerClientInfo(nsIDocument* aDoc);
const nsString& ClientId() const
{
return mClientId;
}
private:
nsString mClientId;
uint64_t mWindowId;

View File

@ -102,6 +102,7 @@ FetchEvent::Constructor(const GlobalObject& aGlobal,
e->SetTrusted(trusted);
e->mRequest = aOptions.mRequest.WasPassed() ?
&aOptions.mRequest.Value() : nullptr;
e->mClientId = aOptions.mClientId;
e->mIsReload = aOptions.mIsReload;
return e.forget();
}

View File

@ -107,6 +107,7 @@ class FetchEvent final : public ExtendableEvent
RefPtr<Request> mRequest;
nsCString mScriptSpec;
nsCString mPreventDefaultScriptSpec;
nsString mClientId;
uint32_t mPreventDefaultLineNumber;
uint32_t mPreventDefaultColumnNumber;
bool mIsReload;
@ -149,6 +150,12 @@ public:
return mRequest;
}
void
GetClientId(nsAString& aClientId) const
{
aClientId = mClientId;
}
bool
IsReload() const
{

View File

@ -3271,18 +3271,18 @@ class ContinueDispatchFetchEventRunnable : public nsRunnable
RefPtr<ServiceWorkerPrivate> mServiceWorkerPrivate;
nsCOMPtr<nsIInterceptedChannel> mChannel;
nsCOMPtr<nsILoadGroup> mLoadGroup;
UniquePtr<ServiceWorkerClientInfo> mClientInfo;
nsString mDocumentId;
bool mIsReload;
public:
ContinueDispatchFetchEventRunnable(ServiceWorkerPrivate* aServiceWorkerPrivate,
nsIInterceptedChannel* aChannel,
nsILoadGroup* aLoadGroup,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload)
: mServiceWorkerPrivate(aServiceWorkerPrivate)
, mChannel(aChannel)
, mLoadGroup(aLoadGroup)
, mClientInfo(Move(aClientInfo))
, mDocumentId(aDocumentId)
, mIsReload(aIsReload)
{
MOZ_ASSERT(aServiceWorkerPrivate);
@ -3321,7 +3321,7 @@ public:
}
rv = mServiceWorkerPrivate->SendFetchEvent(mChannel, mLoadGroup,
Move(mClientInfo), mIsReload);
mDocumentId, mIsReload);
if (NS_WARN_IF(NS_FAILED(rv))) {
HandleError();
}
@ -3335,6 +3335,7 @@ public:
already_AddRefed<nsIRunnable>
ServiceWorkerManager::PrepareFetchEvent(const PrincipalOriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
const nsAString& aDocumentIdForTopLevelNavigation,
nsIInterceptedChannel* aChannel,
bool aIsReload,
bool aIsSubresourceLoad,
@ -3345,13 +3346,16 @@ ServiceWorkerManager::PrepareFetchEvent(const PrincipalOriginAttributes& aOrigin
RefPtr<ServiceWorkerInfo> serviceWorker;
nsCOMPtr<nsILoadGroup> loadGroup;
UniquePtr<ServiceWorkerClientInfo> clientInfo;
nsAutoString documentId;
if (aIsSubresourceLoad) {
MOZ_ASSERT(aDoc);
serviceWorker = GetActiveWorkerInfoForDocument(aDoc);
loadGroup = aDoc->GetDocumentLoadGroup();
clientInfo.reset(new ServiceWorkerClientInfo(aDoc));
nsresult rv = aDoc->GetOrCreateId(documentId);
if (NS_WARN_IF(NS_FAILED(rv))) {
return nullptr;
}
} else {
nsCOMPtr<nsIChannel> internalChannel;
aRv = aChannel->GetChannel(getter_AddRefs(internalChannel));
@ -3361,6 +3365,8 @@ ServiceWorkerManager::PrepareFetchEvent(const PrincipalOriginAttributes& aOrigin
internalChannel->GetLoadGroup(getter_AddRefs(loadGroup));
documentId = aDocumentIdForTopLevelNavigation;
nsCOMPtr<nsIURI> uri;
aRv = internalChannel->GetURI(getter_AddRefs(uri));
if (NS_WARN_IF(aRv.Failed())) {
@ -3389,7 +3395,7 @@ ServiceWorkerManager::PrepareFetchEvent(const PrincipalOriginAttributes& aOrigin
nsCOMPtr<nsIRunnable> continueRunnable =
new ContinueDispatchFetchEventRunnable(serviceWorker->WorkerPrivate(),
aChannel, loadGroup,
Move(clientInfo), aIsReload);
documentId, aIsReload);
return continueRunnable.forget();
}

View File

@ -360,6 +360,7 @@ public:
already_AddRefed<nsIRunnable>
PrepareFetchEvent(const PrincipalOriginAttributes& aOriginAttributes,
nsIDocument* aDoc,
const nsAString& aDocumentIdForTopLevelNavigation,
nsIInterceptedChannel* aChannel,
bool aIsReload,
bool aIsSubresourceLoad,

View File

@ -1016,6 +1016,7 @@ class FetchEventRunnable : public ExtendableFunctionalEventWorkerRunnable
nsTArray<nsCString> mHeaderValues;
nsCString mSpec;
nsCString mMethod;
nsString mClientId;
bool mIsReload;
DebugOnly<bool> mIsHttpChannel;
RequestMode mRequestMode;
@ -1032,12 +1033,13 @@ public:
// later on.
const nsACString& aScriptSpec,
nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo>& aRegistration,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload)
: ExtendableFunctionalEventWorkerRunnable(
aWorkerPrivate, aKeepAliveToken, aRegistration)
, mInterceptedChannel(aChannel)
, mScriptSpec(aScriptSpec)
, mClientId(aDocumentId)
, mIsReload(aIsReload)
, mIsHttpChannel(false)
, mRequestMode(RequestMode::No_cors)
@ -1261,6 +1263,7 @@ private:
init.mRequest.Value() = request;
init.mBubbles = false;
init.mCancelable = true;
init.mClientId = mClientId;
init.mIsReload = mIsReload;
RefPtr<FetchEvent> event =
FetchEvent::Constructor(globalObj, NS_LITERAL_STRING("fetch"), init, result);
@ -1361,7 +1364,7 @@ NS_IMPL_ISUPPORTS_INHERITED(FetchEventRunnable, WorkerRunnable, nsIHttpHeaderVis
nsresult
ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
nsILoadGroup* aLoadGroup,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload)
{
AssertIsOnMainThread();
@ -1393,7 +1396,7 @@ ServiceWorkerPrivate::SendFetchEvent(nsIInterceptedChannel* aChannel,
RefPtr<FetchEventRunnable> r =
new FetchEventRunnable(mWorkerPrivate, mKeepAliveToken, handle,
mInfo->ScriptSpec(), regInfo,
Move(aClientInfo), aIsReload);
aDocumentId, aIsReload);
rv = r->Init();
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;

View File

@ -103,7 +103,7 @@ public:
nsresult
SendFetchEvent(nsIInterceptedChannel* aChannel,
nsILoadGroup* aLoadGroup,
UniquePtr<ServiceWorkerClientInfo>&& aClientInfo,
const nsAString& aDocumentId,
bool aIsReload);
void

View File

@ -68,6 +68,41 @@ async_test(function(t) {
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with the referrer URL');
async_test(function(t) {
var scope = 'resources/simple.html?clientId';
var frame;
var initial_client_id;
service_worker_unregister_and_register(t, worker, scope)
.then(function(reg) {
return wait_for_state(t, reg.installing, 'activated');
})
.then(function() { return with_iframe(scope); })
.then(function(f) {
frame = f;
assert_equals(
frame.contentDocument.body.textContent.substr(0, 15),
'Client ID Found',
'Service Worker should respond to fetch with a client id');
initial_client_id = frame.contentDocument.body.textContent.substr(17);
return frame.contentWindow.fetch('resources/other.html?clientId');
})
.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',
'Service Worker should respond to fetch with an existing client id');
assert_equals(
initial_client_id,
new_client_id,
'Service Worker should observe the correct client ID for a controlled document');
frame.remove();
return service_worker_unregister_and_done(t, scope);
})
.catch(unreached_rejection(t));
}, 'Service Worker responds to fetch event with an existing client id');
async_test(function(t) {
var scope = 'resources/simple.html?ignore';
service_worker_unregister_and_register(t, worker, scope)

View File

@ -11,6 +11,16 @@ function handleReferrer(event) {
['Referrer: ' + event.request.referrer])));
}
function handleClientId(event) {
var body;
if (event.clientId !== '') {
body = 'Client ID Found: ' + event.clientId;
} else {
body = 'Client ID Not Found';
}
event.respondWith(new Response(body));
}
function handleNullBody(event) {
event.respondWith(new Response());
}
@ -66,6 +76,7 @@ self.addEventListener('fetch', function(event) {
{ pattern: '?string', fn: handleString },
{ pattern: '?blob', fn: handleBlob },
{ pattern: '?referrer', fn: handleReferrer },
{ pattern: '?clientId', fn: handleClientId },
{ pattern: '?ignore', fn: function() {} },
{ pattern: '?null', fn: handleNullBody },
{ pattern: '?fetch', fn: handleFetch },

View File

@ -83,12 +83,18 @@ test(function() {
assert_equals(
new FetchEvent('FetchEvent').bubbles,
false, 'Default FetchEvent.bubbles should be false');
assert_equals(
new FetchEvent('FetchEvent').clientId,
null, 'Default FetchEvent.clientId should be null');
assert_equals(
new FetchEvent('FetchEvent').isReload,
false, 'Default FetchEvent.isReload should be false');
assert_equals(
new FetchEvent('FetchEvent', {cancelable: false}).cancelable,
false, 'FetchEvent.cancelable should be false');
assert_equals(
new FetchEvent('FetchEvent', {clientId : 'test-client-id'}).clientId, 'test-client-id',
'FetchEvent.clientId with option {clientId : "test-client-id"} should be "test-client-id"');
assert_equals(
new FetchEvent('FetchEvent', {isReload : true}).isReload, true,
'FetchEvent.isReload with option {isReload : true} should be true');