PermissionUtils.cpp (3192B)
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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "PermissionUtils.h" 8 9 #include "mozilla/dom/Document.h" 10 #include "nsIPermissionManager.h" 11 12 namespace mozilla::dom { 13 14 static const nsLiteralCString kPermissionTypes[] = { 15 // clang-format off 16 "geo"_ns, 17 "desktop-notification"_ns, 18 // Alias `push` to `desktop-notification`. 19 "desktop-notification"_ns, 20 "persistent-storage"_ns, 21 // "midi" is the only public permission but internally we have both "midi" 22 // and "midi-sysex" (and yes, this is confusing). 23 "midi"_ns, 24 "storage-access"_ns, 25 "screen-wake-lock"_ns, 26 "camera"_ns, 27 "microphone"_ns 28 // clang-format on 29 }; 30 31 const size_t kPermissionNameCount = ContiguousEnumSize<PermissionName>::value; 32 33 static_assert(std::size(kPermissionTypes) == kPermissionNameCount, 34 "kPermissionTypes and PermissionName count should match"); 35 36 const nsLiteralCString& PermissionNameToType(PermissionName aName) { 37 MOZ_ASSERT((size_t)aName < std::size(kPermissionTypes)); 38 return kPermissionTypes[static_cast<size_t>(aName)]; 39 } 40 41 Maybe<PermissionName> TypeToPermissionName(const nsACString& aType) { 42 // Annoyingly, "midi-sysex" is an internal permission. The public permission 43 // name is "midi" so we have to special-case it here... 44 if (aType.Equals("midi-sysex"_ns)) { 45 return Some(PermissionName::Midi); 46 } 47 48 // "storage-access" permissions are also annoying and require a special case. 49 if (StringBeginsWith(aType, "3rdPartyStorage^"_ns) || 50 StringBeginsWith(aType, "3rdPartyFrameStorage^"_ns)) { 51 return Some(PermissionName::Storage_access); 52 } 53 54 for (size_t i = 0; i < std::size(kPermissionTypes); ++i) { 55 if (kPermissionTypes[i].Equals(aType)) { 56 return Some(static_cast<PermissionName>(i)); 57 } 58 } 59 60 return Nothing(); 61 } 62 63 PermissionState ActionToPermissionState(uint32_t aAction, PermissionName aName, 64 nsIGlobalObject* aGlobal) { 65 MOZ_ASSERT(aGlobal); 66 67 switch (aAction) { 68 case nsIPermissionManager::ALLOW_ACTION: 69 return PermissionState::Granted; 70 71 case nsIPermissionManager::DENY_ACTION: 72 return PermissionState::Denied; 73 74 case nsIPermissionManager::PROMPT_ACTION: 75 if ((aName == PermissionName::Camera || 76 aName == PermissionName::Microphone) && 77 !aGlobal->ShouldResistFingerprinting(RFPTarget::MediaDevices)) { 78 // A persisted PROMPT_ACTION means the user chose "Always Ask" 79 // which shows as "granted" to prevent websites from priming the 80 // user to escalate permission any further. 81 // Revisit if https://github.com/w3c/permissions/issues/414 reopens. 82 // 83 // This feature is not offered in resist-fingerprinting mode. 84 return PermissionState::Granted; 85 } 86 return PermissionState::Prompt; 87 88 default: 89 return PermissionState::Prompt; 90 } 91 } 92 93 } // namespace mozilla::dom