Files
palemoon27/dom/workers/ServiceWorkerClient.cpp
T
roytam1 75be9ceb09 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1240094 - nsDocShell should initialize mUserContextId to nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID, r=smaug (a3a8358561)
- Bug 1142768 - Return the original document URI from ServiceWorkerClient.url; r=bkelly (17892631ab)
- Bug 1233613 - Make RegisterFrameCaptureListener fallible. r=mt (0a68d5f4ac)
- Bug 1233613 - Locate parent document before getting presentation shell for canvas capture. r=mt (47a285deab)
- Bug 866513 - Non-empty MediaStreamTrack labels. r=jib (1b1f364811)
- Bug 1170958 - Don't create owned MediaStreamTracks in MetadataLoaded. r=roc (3f031298fb)
- fix misspatch of Bug 1131802 part 2 (3a1e0d2799)
- trivial fixes (bffbd65448)
- Bug 1218454 - part 2a - fix bootlegging of nsContentUtils.h includes from nsILoadContext.h; r=bz (a587b686cd)
- bit of Bug 1223078 - Release WrappedJS eagerly (1fcb1a490b)
- Bug 1245767 followup - Throw an error when gczeal argument is out of range. r=jonco on IRC (32de34e6b7)
- Bug 1241934 - Remove the unused validategc API; r=jonco (a80436895b)
- Bug 961323 - Add a method for finding shortest retaining paths of `JS::ubi::Node` heap graphs; r=jimb (b2d3735d7d)
- Bug 1240090 - Make owned copies of filenames in JS::ubi::ByFilename. r=jimb (049ab3c6ed)
- Bug 1247412 - Add a reverse method to mozilla::Vector; r=Waldo (ad417ff38b)
- Bug 1247413 - Give JS::ubi::BreadthFirst handlers a non-const reference; r=jimb (9baadfa50e)
- bit of Bug 1246061 (51b6ef81dc)
- Bug 1243198 - Use rvalue references for JS::ubi::ByFilename constructor; r=jimb (5b1dab61a5)
- Bug 1216001 part 1 - Optimize nsRange::IsNodeSelected. r=bz (39aad5f0d4)
- Bug 1216001 part 2 - Optimize nsRange::ExcludeNonSelectableNodes by counting ignorable whitespace text nodes next to an unselectable node as unselectable too. r=bz (c6589b508e)
- Bug 1216001 part 3 - Cache the result of IsSelected() for the duration of painting. r=bz (aa5c000b4c)
- Bug 1188364 - Supress GC while transplanting to prevent compacting GC observing intermediate state r=terrence (6963b58989)
- Bug 1246318 - Make the proxy enumerate trap non-standard. r=efaust (f34d0a7c2a)
- Bug 1254293. Fix dom::GetArrayIndexFromId to actually follow the spec for large indices (i.e. ones that don't fit in in int32_t). r=peterv (b71cffbbbd)
- Bug 1256688 - Change BPH::has to follow [[HasProperty]] for ordinary objects. r=jorendorff (39b8de1a3d)
2023-09-07 10:56:10 +08:00

216 lines
6.1 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "ServiceWorkerClient.h"
#include "ServiceWorkerContainer.h"
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/Navigator.h"
#include "mozilla/dom/ServiceWorkerMessageEvent.h"
#include "mozilla/dom/ServiceWorkerMessageEventBinding.h"
#include "nsGlobalWindow.h"
#include "nsIDocument.h"
#include "WorkerPrivate.h"
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::dom::workers;
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(ServiceWorkerClient, mOwner)
NS_IMPL_CYCLE_COLLECTING_ADDREF(ServiceWorkerClient)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ServiceWorkerClient)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ServiceWorkerClient)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
ServiceWorkerClientInfo::ServiceWorkerClientInfo(nsIDocument* aDoc)
: mWindowId(0)
{
MOZ_ASSERT(aDoc);
nsresult rv = aDoc->GetOrCreateId(mClientId);
if (NS_FAILED(rv)) {
NS_WARNING("Failed to get the UUID of the document.");
}
RefPtr<nsGlobalWindow> innerWindow = static_cast<nsGlobalWindow*>(aDoc->GetInnerWindow());
if (innerWindow) {
// XXXcatalinb: The inner window can be null if the document is navigating
// and was detached.
mWindowId = innerWindow->WindowID();
}
nsCOMPtr<nsIURI> originalURI = aDoc->GetOriginalURI();
if (originalURI) {
nsAutoCString spec;
originalURI->GetSpec(spec);
CopyUTF8toUTF16(spec, mUrl);
}
mVisibilityState = aDoc->VisibilityState();
ErrorResult result;
mFocused = aDoc->HasFocus(result);
if (result.Failed()) {
NS_WARNING("Failed to get focus information.");
}
RefPtr<nsGlobalWindow> outerWindow = static_cast<nsGlobalWindow*>(aDoc->GetWindow());
MOZ_ASSERT(outerWindow);
if (!outerWindow->IsTopLevelWindow()) {
mFrameType = FrameType::Nested;
} else if (outerWindow->HadOriginalOpener()) {
mFrameType = FrameType::Auxiliary;
} else {
mFrameType = FrameType::Top_level;
}
}
JSObject*
ServiceWorkerClient::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return ClientBinding::Wrap(aCx, this, aGivenProto);
}
namespace {
class ServiceWorkerClientPostMessageRunnable final
: public nsRunnable
, public StructuredCloneHolder
{
uint64_t mWindowId;
public:
explicit ServiceWorkerClientPostMessageRunnable(uint64_t aWindowId)
: StructuredCloneHolder(CloningSupported, TransferringSupported,
SameProcessDifferentThread)
, mWindowId(aWindowId)
{}
NS_IMETHOD
Run()
{
AssertIsOnMainThread();
nsGlobalWindow* window = nsGlobalWindow::GetInnerWindowWithId(mWindowId);
if (!window) {
return NS_ERROR_FAILURE;
}
ErrorResult result;
dom::Navigator* navigator = window->GetNavigator(result);
if (NS_WARN_IF(result.Failed())) {
return result.StealNSResult();
}
RefPtr<ServiceWorkerContainer> container = navigator->ServiceWorker();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(window))) {
return NS_ERROR_FAILURE;
}
JSContext* cx = jsapi.cx();
return DispatchDOMEvent(cx, container);
}
private:
NS_IMETHOD
DispatchDOMEvent(JSContext* aCx, ServiceWorkerContainer* aTargetContainer)
{
AssertIsOnMainThread();
JS::Rooted<JS::Value> messageData(aCx);
ErrorResult rv;
Read(aTargetContainer->GetParentObject(), aCx, &messageData, rv);
if (NS_WARN_IF(rv.Failed())) {
xpc::Throw(aCx, rv.StealNSResult());
return NS_ERROR_FAILURE;
}
RootedDictionary<ServiceWorkerMessageEventInit> init(aCx);
init.mData = messageData;
init.mOrigin.Construct(EmptyString());
init.mLastEventId.Construct(EmptyString());
init.mPorts.Construct();
init.mPorts.Value().SetNull();
RefPtr<ServiceWorker> serviceWorker = aTargetContainer->GetController();
init.mSource.Construct();
if (serviceWorker) {
init.mSource.Value().SetValue().SetAsServiceWorker() = serviceWorker;
} else {
init.mSource.Value().SetNull();
}
RefPtr<ServiceWorkerMessageEvent> event =
ServiceWorkerMessageEvent::Constructor(aTargetContainer,
NS_LITERAL_STRING("message"), init, rv);
nsTArray<RefPtr<MessagePort>> ports = TakeTransferredPorts();
RefPtr<MessagePortList> portList =
new MessagePortList(static_cast<dom::Event*>(event.get()),
ports);
event->SetPorts(portList);
event->SetTrusted(true);
bool status = false;
aTargetContainer->DispatchEvent(static_cast<dom::Event*>(event.get()),
&status);
if (!status) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
};
} // namespace
void
ServiceWorkerClient::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
const Optional<Sequence<JS::Value>>& aTransferable,
ErrorResult& aRv)
{
WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(workerPrivate);
workerPrivate->AssertIsOnWorkerThread();
JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
if (aTransferable.WasPassed()) {
const Sequence<JS::Value>& realTransferable = aTransferable.Value();
JS::HandleValueArray elements =
JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(),
realTransferable.Elements());
JSObject* array = JS_NewArrayObject(aCx, elements);
if (!array) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
transferable.setObject(*array);
}
RefPtr<ServiceWorkerClientPostMessageRunnable> runnable =
new ServiceWorkerClientPostMessageRunnable(mWindowId);
runnable->Write(aCx, aMessage, transferable, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
aRv = NS_DispatchToMainThread(runnable);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
}