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 already_AddRefed
<PermissionStatus
> PermissionStatus::Create(
21 nsPIDOMWindowInner
* aWindow
, PermissionName aName
, ErrorResult
& aRv
) {
22 RefPtr
<PermissionStatus
> status
= new PermissionStatus(aWindow
, aName
);
24 if (NS_WARN_IF(aRv
.Failed())) {
28 return status
.forget();
31 PermissionStatus::PermissionStatus(nsPIDOMWindowInner
* aWindow
,
33 : DOMEventTargetHelper(aWindow
),
35 mState(PermissionState::Denied
) {
36 KeepAliveIfHasListenersFor(nsGkAtoms::onchange
);
39 nsresult
PermissionStatus::Init() {
40 mObserver
= PermissionObserver::GetInstance();
41 if (NS_WARN_IF(!mObserver
)) {
42 return NS_ERROR_FAILURE
;
45 mObserver
->AddSink(this);
47 nsresult rv
= UpdateState();
48 if (NS_WARN_IF(NS_FAILED(rv
))) {
55 PermissionStatus::~PermissionStatus() {
57 mObserver
->RemoveSink(this);
61 JSObject
* PermissionStatus::WrapObject(JSContext
* aCx
,
62 JS::Handle
<JSObject
*> aGivenProto
) {
63 return PermissionStatus_Binding::Wrap(aCx
, this, aGivenProto
);
66 nsLiteralCString
PermissionStatus::GetPermissionType() {
67 return PermissionNameToType(mName
);
70 nsresult
PermissionStatus::UpdateState() {
71 nsCOMPtr
<nsPIDOMWindowInner
> window
= GetOwner();
72 if (NS_WARN_IF(!window
)) {
73 return NS_ERROR_FAILURE
;
76 RefPtr
<Document
> document
= window
->GetExtantDoc();
77 if (NS_WARN_IF(!document
)) {
78 return NS_ERROR_FAILURE
;
81 uint32_t action
= nsIPermissionManager::DENY_ACTION
;
83 PermissionDelegateHandler
* permissionHandler
=
84 document
->GetPermissionDelegateHandler();
85 if (NS_WARN_IF(!permissionHandler
)) {
86 return NS_ERROR_FAILURE
;
89 nsresult rv
= permissionHandler
->GetPermissionForPermissionsAPI(
90 GetPermissionType(), &action
);
91 if (NS_WARN_IF(NS_FAILED(rv
))) {
95 mState
= ActionToPermissionState(action
);
99 already_AddRefed
<nsIPrincipal
> PermissionStatus::GetPrincipal() const {
100 nsCOMPtr
<nsPIDOMWindowInner
> window
= GetOwner();
101 if (NS_WARN_IF(!window
)) {
105 Document
* doc
= window
->GetExtantDoc();
106 if (NS_WARN_IF(!doc
)) {
110 nsCOMPtr
<nsIPrincipal
> principal
=
111 Permission::ClonePrincipalForPermission(doc
->NodePrincipal());
112 NS_ENSURE_TRUE(principal
, nullptr);
114 return principal
.forget();
117 void PermissionStatus::PermissionChanged() {
118 nsCOMPtr
<nsPIDOMWindowInner
> window
= GetOwner();
119 if (NS_WARN_IF(!window
) || !window
->IsFullyActive()) {
122 auto oldState
= mState
;
124 if (mState
!= oldState
) {
125 RefPtr
<AsyncEventDispatcher
> eventDispatcher
=
126 new AsyncEventDispatcher(this, u
"change"_ns
, CanBubble::eNo
);
127 eventDispatcher
->PostDOMEvent();
131 void PermissionStatus::DisconnectFromOwner() {
132 IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onchange
);
135 mObserver
->RemoveSink(this);
139 DOMEventTargetHelper::DisconnectFromOwner();
142 } // namespace mozilla::dom