Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / permission / StorageAccessPermissionStatus.cpp
bloba2129747fb6fc05bba39253d0c7ca4fed21c01f7
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 "mozilla/dom/StorageAccessPermissionStatus.h"
9 #include "mozilla/AntiTrackingUtils.h"
10 #include "mozilla/dom/WindowGlobalChild.h"
11 #include "mozilla/dom/BrowsingContext.h"
12 #include "mozilla/dom/FeaturePolicyUtils.h"
13 #include "mozilla/dom/PermissionStatus.h"
14 #include "mozilla/dom/PermissionStatusBinding.h"
15 #include "mozilla/dom/WorkerPrivate.h"
16 #include "mozilla/dom/WorkerRef.h"
17 #include "nsGlobalWindowInner.h"
18 #include "nsIPermissionManager.h"
19 #include "PermissionStatusSink.h"
21 namespace mozilla::dom {
23 class StorageAccessPermissionStatusSink final : public PermissionStatusSink {
24 Mutex mWorkerRefMutex;
26 // Protected by mutex.
27 // Created and released on worker-thread. Used also on main-thread.
28 RefPtr<WeakWorkerRef> mWeakWorkerRef MOZ_GUARDED_BY(mWorkerRefMutex);
30 public:
31 StorageAccessPermissionStatusSink(PermissionStatus* aPermissionStatus,
32 PermissionName aPermissionName,
33 const nsACString& aPermissionType)
34 : PermissionStatusSink(aPermissionStatus, aPermissionName,
35 aPermissionType),
36 mWorkerRefMutex("StorageAccessPermissionStatusSink::mWorkerRefMutex") {}
38 void Init() {
39 if (!NS_IsMainThread()) {
40 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
41 MOZ_ASSERT(workerPrivate);
43 MutexAutoLock lock(mWorkerRefMutex);
45 mWeakWorkerRef =
46 WeakWorkerRef::Create(workerPrivate, [self = RefPtr(this)]() {
47 MutexAutoLock lock(self->mWorkerRefMutex);
48 self->mWeakWorkerRef = nullptr;
49 });
53 protected:
54 bool MaybeUpdatedByOnMainThread(nsIPermission* aPermission) override {
55 return false;
58 bool MaybeUpdatedByNotifyOnlyOnMainThread(
59 nsPIDOMWindowInner* aInnerWindow) override {
60 NS_ENSURE_TRUE(aInnerWindow, false);
62 if (!mPermissionStatus) {
63 return false;
66 nsCOMPtr<nsPIDOMWindowInner> ownerWindow;
68 if (mSerialEventTarget->IsOnCurrentThread()) {
69 ownerWindow = mPermissionStatus->GetOwnerWindow();
70 } else {
71 MutexAutoLock lock(mWorkerRefMutex);
73 if (!mWeakWorkerRef) {
74 return false;
77 // If we have mWeakWorkerRef, we haven't received the WorkerRef
78 // notification yet.
79 WorkerPrivate* workerPrivate = mWeakWorkerRef->GetUnsafePrivate();
80 MOZ_ASSERT(workerPrivate);
82 ownerWindow = workerPrivate->GetAncestorWindow();
85 NS_ENSURE_TRUE(ownerWindow, false);
87 return ownerWindow->WindowID() == aInnerWindow->WindowID();
90 RefPtr<PermissionStatePromise> ComputeStateOnMainThread() override {
91 if (mSerialEventTarget->IsOnCurrentThread()) {
92 if (!mPermissionStatus) {
93 return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE,
94 __func__);
97 nsGlobalWindowInner* window = mPermissionStatus->GetOwnerWindow();
98 if (NS_WARN_IF(!window)) {
99 return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE,
100 __func__);
103 WindowGlobalChild* wgc = window->GetWindowGlobalChild();
104 if (NS_WARN_IF(!wgc)) {
105 return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE,
106 __func__);
109 // Perform a Permission Policy Request
110 if (!FeaturePolicyUtils::IsFeatureAllowed(window->GetExtantDoc(),
111 u"storage-access"_ns)) {
112 return PermissionStatePromise::CreateAndResolve(
113 nsIPermissionManager::PROMPT_ACTION, __func__);
116 return wgc->SendGetStorageAccessPermission(false)->Then(
117 GetMainThreadSerialEventTarget(), __func__,
118 [self = RefPtr(this)](uint32_t aAction) {
119 // We never reveal PermissionState::Denied here
120 return PermissionStatePromise::CreateAndResolve(
121 aAction == nsIPermissionManager::ALLOW_ACTION
122 ? aAction
123 : nsIPermissionManager::PROMPT_ACTION,
124 __func__);
126 [](mozilla::ipc::ResponseRejectReason aError) {
127 return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE,
128 __func__);
132 // For workers we already have the correct value in workerPrivate.
133 return InvokeAsync(mSerialEventTarget, __func__, [self = RefPtr(this)] {
134 if (!self->mPermissionStatus) {
135 return PermissionStatePromise::CreateAndReject(NS_ERROR_FAILURE,
136 __func__);
139 WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
140 MOZ_ASSERT(workerPrivate);
142 return PermissionStatePromise::CreateAndResolve(
143 workerPrivate->StorageAccess() == StorageAccess::eAllow
144 ? nsIPermissionManager::ALLOW_ACTION
145 : nsIPermissionManager::PROMPT_ACTION,
146 __func__);
151 StorageAccessPermissionStatus::StorageAccessPermissionStatus(
152 nsIGlobalObject* aGlobal)
153 : PermissionStatus(aGlobal, PermissionName::Storage_access) {}
155 already_AddRefed<PermissionStatusSink>
156 StorageAccessPermissionStatus::CreateSink() {
157 RefPtr<StorageAccessPermissionStatusSink> sink =
158 new StorageAccessPermissionStatusSink(this, Name(), GetPermissionType());
159 sink->Init();
160 return sink.forget();
163 } // namespace mozilla::dom