Bug 1946787 - Avoid creating redundant GradientCache::OnMaxEntriesBreached tasks...
[gecko.git] / dom / clients / api / Client.cpp
blobc3dd6175deb305275d2f8155656cc303d378145d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "Client.h"
9 #include "ClientDOMUtil.h"
10 #include "mozilla/dom/ClientHandle.h"
11 #include "mozilla/dom/ClientIPCTypes.h"
12 #include "mozilla/dom/ClientManager.h"
13 #include "mozilla/dom/ClientState.h"
14 #include "mozilla/dom/DOMMozPromiseRequestHolder.h"
15 #include "mozilla/dom/MessagePortBinding.h"
16 #include "mozilla/dom/Promise.h"
17 #include "mozilla/dom/WorkerScope.h"
18 #include "nsIDUtils.h"
19 #include "nsIGlobalObject.h"
21 namespace mozilla::dom {
23 using mozilla::dom::ipc::StructuredCloneData;
25 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozilla::dom::Client);
26 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozilla::dom::Client);
27 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(mozilla::dom::Client, mGlobal);
29 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(mozilla::dom::Client)
30 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
31 NS_INTERFACE_MAP_ENTRY(nsISupports)
32 NS_INTERFACE_MAP_END
34 void Client::EnsureHandle() {
35 NS_ASSERT_OWNINGTHREAD(mozilla::dom::Client);
36 if (!mHandle) {
37 mHandle = ClientManager::CreateHandle(ClientInfo(mData->info()),
38 mGlobal->SerialEventTarget());
42 Client::Client(nsIGlobalObject* aGlobal, const ClientInfoAndState& aData)
43 : mGlobal(aGlobal), mData(MakeUnique<ClientInfoAndState>(aData)) {
44 MOZ_DIAGNOSTIC_ASSERT(mGlobal);
47 TimeStamp Client::CreationTime() const { return mData->info().creationTime(); }
49 TimeStamp Client::LastFocusTime() const {
50 if (mData->info().type() != ClientType::Window) {
51 return TimeStamp();
53 return mData->state().get_IPCClientWindowState().lastFocusTime();
56 StorageAccess Client::GetStorageAccess() const {
57 ClientState state(ClientState::FromIPC(mData->state()));
58 return state.GetStorageAccess();
61 JSObject* Client::WrapObject(JSContext* aCx,
62 JS::Handle<JSObject*> aGivenProto) {
63 if (mData->info().type() == ClientType::Window) {
64 return WindowClient_Binding::Wrap(aCx, this, aGivenProto);
66 return Client_Binding::Wrap(aCx, this, aGivenProto);
69 nsIGlobalObject* Client::GetParentObject() const { return mGlobal; }
71 void Client::GetUrl(nsAString& aUrlOut) const {
72 CopyUTF8toUTF16(mData->info().url(), aUrlOut);
75 void Client::GetId(nsAString& aIdOut) const {
76 aIdOut = NSID_TrimBracketsUTF16(mData->info().id());
79 ClientType Client::Type() const { return mData->info().type(); }
81 FrameType Client::GetFrameType() const { return mData->info().frameType(); }
83 void Client::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
84 const Sequence<JSObject*>& aTransferable,
85 ErrorResult& aRv) {
86 MOZ_ASSERT(!NS_IsMainThread());
87 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
88 MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
89 MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
90 workerPrivate->AssertIsOnWorkerThread();
92 JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue());
93 aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable,
94 &transferable);
95 if (aRv.Failed()) {
96 return;
99 StructuredCloneData data;
100 data.Write(aCx, aMessage, transferable, JS::CloneDataPolicy(), aRv);
101 if (aRv.Failed()) {
102 return;
105 EnsureHandle();
106 mHandle->PostMessage(data, workerPrivate->GetServiceWorkerDescriptor());
109 void Client::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage,
110 const StructuredSerializeOptions& aOptions,
111 ErrorResult& aRv) {
112 PostMessage(aCx, aMessage, aOptions.mTransfer, aRv);
115 VisibilityState Client::GetVisibilityState() const {
116 return mData->state().get_IPCClientWindowState().visibilityState();
119 bool Client::Focused() const {
120 return mData->state().get_IPCClientWindowState().focused();
123 already_AddRefed<Promise> Client::Focus(CallerType aCallerType,
124 ErrorResult& aRv) {
125 MOZ_ASSERT(!NS_IsMainThread());
126 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
127 MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
128 MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
129 workerPrivate->AssertIsOnWorkerThread();
131 RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
132 if (aRv.Failed()) {
133 return outerPromise.forget();
136 if (!workerPrivate->GlobalScope()->WindowInteractionAllowed()) {
137 outerPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR);
138 return outerPromise.forget();
141 EnsureHandle();
143 IPCClientInfo ipcClientInfo(mData->info());
144 auto holder =
145 MakeRefPtr<DOMMozPromiseRequestHolder<ClientStatePromise>>(mGlobal);
147 mHandle->Focus(aCallerType)
148 ->Then(
149 mGlobal->SerialEventTarget(), __func__,
150 [ipcClientInfo, holder, outerPromise](const ClientState& aResult) {
151 holder->Complete();
152 NS_ENSURE_TRUE_VOID(holder->GetParentObject());
153 RefPtr<Client> newClient =
154 new Client(holder->GetParentObject(),
155 ClientInfoAndState(ipcClientInfo, aResult.ToIPC()));
156 outerPromise->MaybeResolve(newClient);
158 [holder, outerPromise](const CopyableErrorResult& aResult) {
159 holder->Complete();
160 // MaybeReject needs a non-const-ref result, so make a copy.
161 outerPromise->MaybeReject(CopyableErrorResult(aResult));
163 ->Track(*holder);
165 return outerPromise.forget();
168 already_AddRefed<Promise> Client::Navigate(const nsAString& aURL,
169 ErrorResult& aRv) {
170 MOZ_ASSERT(!NS_IsMainThread());
171 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
172 MOZ_DIAGNOSTIC_ASSERT(workerPrivate);
173 MOZ_DIAGNOSTIC_ASSERT(workerPrivate->IsServiceWorker());
174 workerPrivate->AssertIsOnWorkerThread();
176 RefPtr<Promise> outerPromise = Promise::Create(mGlobal, aRv);
177 if (aRv.Failed()) {
178 return outerPromise.forget();
181 ClientNavigateArgs args(mData->info(), NS_ConvertUTF16toUTF8(aURL),
182 workerPrivate->GetLocationInfo().mHref,
183 workerPrivate->GetServiceWorkerDescriptor().ToIPC());
184 RefPtr<Client> self = this;
186 StartClientManagerOp(
187 &ClientManager::Navigate, args, mGlobal,
188 [self, outerPromise](const ClientOpResult& aResult) {
189 if (aResult.type() != ClientOpResult::TClientInfoAndState) {
190 outerPromise->MaybeResolve(JS::NullHandleValue);
191 return;
193 RefPtr<Client> newClient =
194 new Client(self->mGlobal, aResult.get_ClientInfoAndState());
195 outerPromise->MaybeResolve(newClient);
197 [self, outerPromise](const CopyableErrorResult& aResult) {
198 // MaybeReject needs a non-const-ref result, so make a copy.
199 outerPromise->MaybeReject(CopyableErrorResult(aResult));
202 return outerPromise.forget();
205 } // namespace mozilla::dom