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
{
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__
);
31 MOZ_ASSERT(NS_FAILED(aError
));
32 return MozPromise
<RefPtr
<PermissionStatus
>, nsresult
,
33 true>::CreateAndReject(aError
, __func__
);
37 PermissionStatus::PermissionStatus(nsPIDOMWindowInner
* aWindow
,
39 : DOMEventTargetHelper(aWindow
),
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);
56 PermissionStatus::~PermissionStatus() {
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
)) {
108 Document
* doc
= window
->GetExtantDoc();
109 if (NS_WARN_IF(!doc
)) {
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
) {
121 return permissionPrincipal
->Equals(principal
);
124 bool PermissionStatus::MaybeUpdatedByNotifyOnly(
125 nsPIDOMWindowInner
* aInnerWindow
) const {
129 void PermissionStatus::PermissionChanged() {
130 auto oldState
= mState
;
131 RefPtr
<PermissionStatus
> self(this);
133 GetMainThreadSerialEventTarget(), __func__
,
135 if (self
->mState
!= oldState
) {
136 RefPtr
<AsyncEventDispatcher
> eventDispatcher
=
137 new AsyncEventDispatcher(self
.get(), u
"change"_ns
,
139 eventDispatcher
->PostDOMEvent();
147 void PermissionStatus::DisconnectFromOwner() {
148 IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onchange
);
151 mObserver
->RemoveSink(this);
155 DOMEventTargetHelper::DisconnectFromOwner();
158 } // namespace mozilla::dom