зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1142015 - Add source for messages dispatched to a Service Worker. r=baku
This commit is contained in:
Родитель
ba688bded0
Коммит
96bdb9cb6a
|
@ -13,6 +13,9 @@
|
|||
#include "jsapi.h"
|
||||
#include "nsGlobalWindow.h" // So we can assign an nsGlobalWindow* to mWindowSource
|
||||
|
||||
#include "ServiceWorker.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -103,12 +106,14 @@ MessageEvent::GetSource(nsIDOMWindow** aSource)
|
|||
}
|
||||
|
||||
void
|
||||
MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const
|
||||
MessageEvent::GetSource(Nullable<OwningWindowProxyOrMessagePortOrClient>& aValue) const
|
||||
{
|
||||
if (mWindowSource) {
|
||||
aValue.SetValue().SetAsWindowProxy() = mWindowSource;
|
||||
} else if (mPortSource) {
|
||||
aValue.SetValue().SetAsMessagePort() = mPortSource;
|
||||
} else if (mClientSource) {
|
||||
aValue.SetValue().SetAsClient() = mClientSource;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,6 +211,12 @@ MessageEvent::SetSource(mozilla::dom::MessagePort* aPort)
|
|||
mPortSource = aPort;
|
||||
}
|
||||
|
||||
void
|
||||
MessageEvent::SetSource(mozilla::dom::workers::ServiceWorkerClient* aClient)
|
||||
{
|
||||
mClientSource = aClient;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -18,7 +18,13 @@ struct MessageEventInit;
|
|||
class MessagePort;
|
||||
class MessagePortBase;
|
||||
class MessagePortList;
|
||||
class OwningWindowProxyOrMessagePort;
|
||||
class OwningWindowProxyOrMessagePortOrClient;
|
||||
|
||||
namespace workers {
|
||||
|
||||
class ServiceWorkerClient;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the MessageEvent event, used for cross-document messaging and
|
||||
|
@ -48,7 +54,7 @@ public:
|
|||
void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aData,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void GetSource(Nullable<OwningWindowProxyOrMessagePort>& aValue) const;
|
||||
void GetSource(Nullable<OwningWindowProxyOrMessagePortOrClient>& aValue) const;
|
||||
|
||||
MessagePortList* GetPorts()
|
||||
{
|
||||
|
@ -60,6 +66,8 @@ public:
|
|||
// Non WebIDL methods
|
||||
void SetSource(mozilla::dom::MessagePort* aPort);
|
||||
|
||||
void SetSource(workers::ServiceWorkerClient* aClient);
|
||||
|
||||
void SetSource(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
mWindowSource = aWindow;
|
||||
|
@ -86,6 +94,7 @@ private:
|
|||
nsString mLastEventId;
|
||||
nsCOMPtr<nsIDOMWindow> mWindowSource;
|
||||
nsRefPtr<MessagePortBase> mPortSource;
|
||||
nsRefPtr<workers::ServiceWorkerClient> mClientSource;
|
||||
nsRefPtr<MessagePortList> mPorts;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,9 +31,12 @@ interface MessageEvent : Event {
|
|||
readonly attribute DOMString lastEventId;
|
||||
|
||||
/**
|
||||
* The window or the port which originated this event.
|
||||
* The window, port or client which originated this event.
|
||||
* FIXME(catalinb): Update this when the spec changes are implemented.
|
||||
* https://www.w3.org/Bugs/Public/show_bug.cgi?id=28199
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=1143717
|
||||
*/
|
||||
readonly attribute (WindowProxy or MessagePort)? source;
|
||||
readonly attribute (WindowProxy or MessagePort or Client)? source;
|
||||
|
||||
/**
|
||||
* Initializes this event with the given data, in a manner analogous to
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "ServiceWorker.h"
|
||||
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "ServiceWorkerClient.h"
|
||||
#include "ServiceWorkerManager.h"
|
||||
#include "SharedWorker.h"
|
||||
#include "WorkerPrivate.h"
|
||||
|
@ -95,7 +96,12 @@ ServiceWorker::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
|||
return;
|
||||
}
|
||||
|
||||
workerPrivate->PostMessage(aCx, aMessage, aTransferable, aRv);
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(GetParentObject());
|
||||
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
|
||||
nsAutoPtr<ServiceWorkerClientInfo> clientInfo(new ServiceWorkerClientInfo(doc));
|
||||
|
||||
workerPrivate->PostMessageToServiceWorker(aCx, aMessage, aTransferable,
|
||||
clientInfo, aRv);
|
||||
}
|
||||
|
||||
WorkerPrivate*
|
||||
|
|
|
@ -985,6 +985,9 @@ class MessageEventRunnable MOZ_FINAL : public WorkerRunnable
|
|||
uint64_t mMessagePortSerial;
|
||||
bool mToMessagePort;
|
||||
|
||||
// This is only used for messages dispatched to a service worker.
|
||||
nsAutoPtr<ServiceWorkerClientInfo> mEventSource;
|
||||
|
||||
public:
|
||||
MessageEventRunnable(WorkerPrivate* aWorkerPrivate,
|
||||
TargetAndBusyBehavior aBehavior,
|
||||
|
@ -999,6 +1002,12 @@ public:
|
|||
mClonedObjects.SwapElements(aClonedObjects);
|
||||
}
|
||||
|
||||
void
|
||||
SetMessageSource(ServiceWorkerClientInfo* aSource)
|
||||
{
|
||||
mEventSource = aSource;
|
||||
}
|
||||
|
||||
bool
|
||||
DispatchDOMEvent(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
DOMEventTargetHelper* aTarget, bool aIsMainThread)
|
||||
|
@ -1024,6 +1033,12 @@ public:
|
|||
EmptyString(),
|
||||
EmptyString(),
|
||||
nullptr);
|
||||
if (mEventSource) {
|
||||
nsRefPtr<ServiceWorkerClient> client =
|
||||
new ServiceWorkerWindowClient(aTarget, *mEventSource);
|
||||
event->SetSource(client);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
xpc::Throw(aCx, rv);
|
||||
return false;
|
||||
|
@ -3089,9 +3104,10 @@ void
|
|||
WorkerPrivateParent<Derived>::PostMessageInternal(
|
||||
JSContext* aCx,
|
||||
JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value> >& aTransferable,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
bool aToMessagePort,
|
||||
uint64_t aMessagePortSerial,
|
||||
ServiceWorkerClientInfo* aClientInfo,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnParentThread();
|
||||
|
@ -3155,11 +3171,26 @@ WorkerPrivateParent<Derived>::PostMessageInternal(
|
|||
WorkerRunnable::WorkerThreadModifyBusyCount,
|
||||
Move(buffer), clonedObjects, aToMessagePort,
|
||||
aMessagePortSerial);
|
||||
runnable->SetMessageSource(aClientInfo);
|
||||
|
||||
if (!runnable->Dispatch(aCx)) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessageToServiceWorker(
|
||||
JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, false, 0,
|
||||
aClientInfo.forget(), aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
void
|
||||
WorkerPrivateParent<Derived>::PostMessageToMessagePort(
|
||||
|
@ -3172,7 +3203,7 @@ WorkerPrivateParent<Derived>::PostMessageToMessagePort(
|
|||
AssertIsOnMainThread();
|
||||
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, true, aMessagePortSerial,
|
||||
aRv);
|
||||
nullptr, aRv);
|
||||
}
|
||||
|
||||
template <class Derived>
|
||||
|
|
|
@ -61,6 +61,7 @@ BEGIN_WORKERS_NAMESPACE
|
|||
class AutoSyncLoopHolder;
|
||||
class MessagePort;
|
||||
class SharedWorker;
|
||||
class ServiceWorkerClientInfo;
|
||||
class WorkerControlRunnable;
|
||||
class WorkerDebugger;
|
||||
class WorkerDebuggerGlobalScope;
|
||||
|
@ -221,8 +222,9 @@ private:
|
|||
|
||||
void
|
||||
PostMessageInternal(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value> >& aTransferable,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
bool aToMessagePort, uint64_t aMessagePortSerial,
|
||||
ServiceWorkerClientInfo* aClientInfo,
|
||||
ErrorResult& aRv);
|
||||
|
||||
nsresult
|
||||
|
@ -327,9 +329,15 @@ public:
|
|||
const Optional<Sequence<JS::Value> >& aTransferable,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, false, 0, aRv);
|
||||
PostMessageInternal(aCx, aMessage, aTransferable, false, 0, nullptr, aRv);
|
||||
}
|
||||
|
||||
void
|
||||
PostMessageToServiceWorker(JSContext* aCx, JS::Handle<JS::Value> aMessage,
|
||||
const Optional<Sequence<JS::Value>>& aTransferable,
|
||||
nsAutoPtr<ServiceWorkerClientInfo>& aClientInfo,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
PostMessageToMessagePort(JSContext* aCx,
|
||||
uint64_t aMessagePortSerial,
|
||||
|
|
|
@ -41,6 +41,7 @@ support-files =
|
|||
serviceworker_not_sharedworker.js
|
||||
match_all_client/match_all_client_id.html
|
||||
match_all_client_id_worker.js
|
||||
source_message_posting_worker.js
|
||||
|
||||
[test_unregister.html]
|
||||
[test_installation_simple.html]
|
||||
|
@ -56,6 +57,7 @@ support-files =
|
|||
[test_workerUnregister.html]
|
||||
[test_post_message.html]
|
||||
[test_post_message_advanced.html]
|
||||
[test_post_message_source.html]
|
||||
[test_match_all_client_properties.html]
|
||||
[test_close.html]
|
||||
[test_serviceworker_interfaces.html]
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
onmessage = function(e) {
|
||||
if (!e.source) {
|
||||
dump("ERROR: message doesn't have a source.");
|
||||
}
|
||||
|
||||
// The client should be a window client
|
||||
if (e.source instanceof WindowClient) {
|
||||
e.source.postMessage(e.data);
|
||||
} else {
|
||||
e.source.postMessage("ERROR. source is not a window client.");
|
||||
}
|
||||
};
|
|
@ -0,0 +1,65 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1142015 - Test service worker post message source </title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test"></pre>
|
||||
<script class="testbody" type="text/javascript">
|
||||
var magic_value = "MAGIC_VALUE_RANDOM";
|
||||
var registration;
|
||||
function start() {
|
||||
return navigator.serviceWorker.register("source_message_posting_worker.js",
|
||||
{ scope: "./nonexistent_scope/" })
|
||||
.then((swr) => registration = swr);
|
||||
}
|
||||
|
||||
function unregister() {
|
||||
return registration.unregister().then(function(result) {
|
||||
ok(result, "Unregister should return true.");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function testPostMessage(swr) {
|
||||
var p = new Promise(function(res, rej) {
|
||||
navigator.serviceWorker.onmessage = function(e) {
|
||||
ok(e.data === magic_value, "Worker posted the correct value.");
|
||||
res();
|
||||
}
|
||||
});
|
||||
|
||||
ok(swr.installing, "Installing worker exists.");
|
||||
swr.installing.postMessage(magic_value);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
function runTest() {
|
||||
start()
|
||||
.then(testPostMessage)
|
||||
.then(unregister)
|
||||
.catch(function(e) {
|
||||
ok(false, "Some test failed with error " + e);
|
||||
}).then(SimpleTest.finish);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [
|
||||
["dom.serviceWorkers.exemptFromPerDomainMax", true],
|
||||
["dom.serviceWorkers.enabled", true],
|
||||
["dom.serviceWorkers.testing.enabled", true]
|
||||
]}, runTest);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
Загрузка…
Ссылка в новой задаче