Bug 1852740: add tests for the `fetchpriority` attribute in Link headers. r=necko...
[gecko.git] / dom / permission / PermissionStatus.cpp
blob87f417a07b8071d542e112c5516ebbac36c091b4
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/PermissionStatus.h"
8 #include "mozilla/PermissionDelegateHandler.h"
10 #include "mozilla/AsyncEventDispatcher.h"
11 #include "mozilla/Permission.h"
12 #include "mozilla/Services.h"
13 #include "nsIPermissionManager.h"
14 #include "PermissionObserver.h"
15 #include "PermissionUtils.h"
17 namespace mozilla::dom {
19 /* static */
20 RefPtr<PermissionStatus::CreatePromise> PermissionStatus::Create(
21 nsPIDOMWindowInner* aWindow, PermissionName aName) {
22 RefPtr<PermissionStatus> status = new PermissionStatus(aWindow, aName);
23 return status->Init()->Then(
24 GetMainThreadSerialEventTarget(), __func__,
25 [status](nsresult aOk) {
26 MOZ_ASSERT(NS_SUCCEEDED(aOk));
27 return MozPromise<RefPtr<PermissionStatus>, nsresult,
28 true>::CreateAndResolve(status, __func__);
30 [](nsresult aError) {
31 MOZ_ASSERT(NS_FAILED(aError));
32 return MozPromise<RefPtr<PermissionStatus>, nsresult,
33 true>::CreateAndReject(aError, __func__);
34 });
37 PermissionStatus::PermissionStatus(nsPIDOMWindowInner* aWindow,
38 PermissionName aName)
39 : DOMEventTargetHelper(aWindow),
40 mName(aName),
41 mState(PermissionState::Denied) {
42 KeepAliveIfHasListenersFor(nsGkAtoms::onchange);
45 RefPtr<PermissionStatus::SimplePromise> PermissionStatus::Init() {
46 mObserver = PermissionObserver::GetInstance();
47 if (NS_WARN_IF(!mObserver)) {
48 return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
51 mObserver->AddSink(this);
53 return UpdateState();
56 PermissionStatus::~PermissionStatus() {
57 if (mObserver) {
58 mObserver->RemoveSink(this);
62 JSObject* PermissionStatus::WrapObject(JSContext* aCx,
63 JS::Handle<JSObject*> aGivenProto) {
64 return PermissionStatus_Binding::Wrap(aCx, this, aGivenProto);
67 nsLiteralCString PermissionStatus::GetPermissionType() {
68 return PermissionNameToType(mName);
71 RefPtr<PermissionStatus::SimplePromise> PermissionStatus::UpdateState() {
72 nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
73 if (NS_WARN_IF(!window)) {
74 return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
77 RefPtr<Document> document = window->GetExtantDoc();
78 if (NS_WARN_IF(!document)) {
79 return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
82 uint32_t action = nsIPermissionManager::DENY_ACTION;
84 PermissionDelegateHandler* permissionHandler =
85 document->GetPermissionDelegateHandler();
86 if (NS_WARN_IF(!permissionHandler)) {
87 return SimplePromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
90 nsresult rv = permissionHandler->GetPermissionForPermissionsAPI(
91 GetPermissionType(), &action);
92 if (NS_WARN_IF(NS_FAILED(rv))) {
93 return SimplePromise::CreateAndReject(rv, __func__);
96 mState = ActionToPermissionState(action);
97 return SimplePromise::CreateAndResolve(NS_OK, __func__);
101 bool PermissionStatus::MaybeUpdatedBy(nsIPermission* aPermission) const {
102 NS_ENSURE_TRUE(aPermission, false);
103 nsCOMPtr<nsPIDOMWindowInner> window = GetOwner();
104 if (NS_WARN_IF(!window)) {
105 return false;
108 Document* doc = window->GetExtantDoc();
109 if (NS_WARN_IF(!doc)) {
110 return false;
113 nsCOMPtr<nsIPrincipal> principal =
114 Permission::ClonePrincipalForPermission(doc->NodePrincipal());
115 NS_ENSURE_TRUE(principal, false);
116 nsCOMPtr<nsIPrincipal> permissionPrincipal;
117 aPermission->GetPrincipal(getter_AddRefs(permissionPrincipal));
118 if (!permissionPrincipal) {
119 return false;
121 return permissionPrincipal->Equals(principal);
124 bool PermissionStatus::MaybeUpdatedByNotifyOnly(
125 nsPIDOMWindowInner* aInnerWindow) const {
126 return false;
129 void PermissionStatus::PermissionChanged() {
130 auto oldState = mState;
131 RefPtr<PermissionStatus> self(this);
132 UpdateState()->Then(
133 GetMainThreadSerialEventTarget(), __func__,
134 [self, oldState]() {
135 if (self->mState != oldState) {
136 RefPtr<AsyncEventDispatcher> eventDispatcher =
137 new AsyncEventDispatcher(self.get(), u"change"_ns,
138 CanBubble::eNo);
139 eventDispatcher->PostDOMEvent();
142 []() {
147 void PermissionStatus::DisconnectFromOwner() {
148 IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onchange);
150 if (mObserver) {
151 mObserver->RemoveSink(this);
152 mObserver = nullptr;
155 DOMEventTargetHelper::DisconnectFromOwner();
158 } // namespace mozilla::dom