PermissionStatus.cpp (3380B)
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/. */ 6 7 #include "mozilla/dom/PermissionStatus.h" 8 9 #include "PermissionStatusSink.h" 10 #include "PermissionUtils.h" 11 #include "mozilla/AsyncEventDispatcher.h" 12 #include "mozilla/Permission.h" 13 #include "mozilla/Services.h" 14 #include "nsGlobalWindowInner.h" 15 #include "nsIPermissionManager.h" 16 17 namespace mozilla::dom { 18 19 PermissionStatus::PermissionStatus(nsIGlobalObject* aGlobal, 20 PermissionName aName) 21 : DOMEventTargetHelper(aGlobal), 22 mName(aName), 23 mState(PermissionState::Denied) { 24 KeepAliveIfHasListenersFor(nsGkAtoms::onchange); 25 } 26 27 // https://w3c.github.io/permissions/#onchange-attribute and 28 // https://w3c.github.io/permissions/#query-method 29 RefPtr<PermissionStatus::SimplePromise> PermissionStatus::Init() { 30 mSink = CreateSink(); 31 MOZ_ASSERT(mSink); 32 33 return mSink->Init()->Then( 34 GetCurrentSerialEventTarget(), __func__, 35 [self = RefPtr(this)](const PermissionStatusSink::PermissionStatePromise:: 36 ResolveOrRejectValue& aResult) { 37 if (aResult.IsResolve()) { 38 self->mState = self->ComputeStateFromAction(aResult.ResolveValue()); 39 return SimplePromise::CreateAndResolve(NS_OK, __func__); 40 } 41 42 return SimplePromise::CreateAndReject(aResult.RejectValue(), __func__); 43 }); 44 } 45 46 PermissionStatus::~PermissionStatus() { 47 if (mSink) { 48 mSink->Disentangle(); 49 mSink = nullptr; 50 } 51 } 52 53 JSObject* PermissionStatus::WrapObject(JSContext* aCx, 54 JS::Handle<JSObject*> aGivenProto) { 55 return PermissionStatus_Binding::Wrap(aCx, this, aGivenProto); 56 } 57 58 nsLiteralCString PermissionStatus::GetPermissionType() const { 59 return PermissionNameToType(mName); 60 } 61 62 // https://w3c.github.io/permissions/#dfn-permissionstatus-update-steps 63 void PermissionStatus::PermissionChanged(uint32_t aAction) { 64 PermissionState newState = ComputeStateFromAction(aAction); 65 if (mState == newState) { 66 return; 67 } 68 69 mState = newState; 70 71 // Step 4: Queue a task on the permissions task source to fire an 72 // event named change at status. 73 RefPtr<AsyncEventDispatcher> eventDispatcher = 74 new AsyncEventDispatcher(this, u"change"_ns, CanBubble::eNo); 75 eventDispatcher->PostDOMEvent(); 76 } 77 78 void PermissionStatus::DisconnectFromOwner() { 79 IgnoreKeepAliveIfHasListenersFor(nsGkAtoms::onchange); 80 81 if (mSink) { 82 mSink->Disentangle(); 83 mSink = nullptr; 84 } 85 86 DOMEventTargetHelper::DisconnectFromOwner(); 87 } 88 89 void PermissionStatus::GetType(nsACString& aName) const { 90 aName.Assign(GetPermissionType()); 91 } 92 93 already_AddRefed<PermissionStatusSink> PermissionStatus::CreateSink() { 94 RefPtr<PermissionStatusSink> sink = 95 new PermissionStatusSink(this, mName, GetPermissionType()); 96 return sink.forget(); 97 } 98 99 PermissionState PermissionStatus::ComputeStateFromAction(uint32_t aAction) { 100 nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal(); 101 if (NS_WARN_IF(!global)) { 102 return PermissionState::Denied; 103 } 104 105 return ActionToPermissionState(aAction, mName, global); 106 } 107 108 } // namespace mozilla::dom