PermissionObserver.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "PermissionObserver.h"
  6. #include "mozilla/dom/PermissionStatus.h"
  7. #include "mozilla/Services.h"
  8. #include "mozilla/UniquePtr.h"
  9. #include "nsIObserverService.h"
  10. #include "nsIPermission.h"
  11. #include "PermissionUtils.h"
  12. namespace mozilla {
  13. namespace dom {
  14. namespace {
  15. PermissionObserver* gInstance = nullptr;
  16. } // namespace
  17. NS_IMPL_ISUPPORTS(PermissionObserver,
  18. nsIObserver,
  19. nsISupportsWeakReference)
  20. PermissionObserver::PermissionObserver()
  21. {
  22. MOZ_ASSERT(!gInstance);
  23. }
  24. PermissionObserver::~PermissionObserver()
  25. {
  26. MOZ_ASSERT(mSinks.IsEmpty());
  27. MOZ_ASSERT(gInstance == this);
  28. gInstance = nullptr;
  29. }
  30. /* static */ already_AddRefed<PermissionObserver>
  31. PermissionObserver::GetInstance()
  32. {
  33. RefPtr<PermissionObserver> instance = gInstance;
  34. if (!instance) {
  35. instance = new PermissionObserver();
  36. nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
  37. if (NS_WARN_IF(!obs)) {
  38. return nullptr;
  39. }
  40. nsresult rv = obs->AddObserver(instance, "perm-changed", true);
  41. if (NS_WARN_IF(NS_FAILED(rv))) {
  42. return nullptr;
  43. }
  44. gInstance = instance;
  45. }
  46. return instance.forget();
  47. }
  48. void
  49. PermissionObserver::AddSink(PermissionStatus* aSink)
  50. {
  51. MOZ_ASSERT(aSink);
  52. MOZ_ASSERT(!mSinks.Contains(aSink));
  53. mSinks.AppendElement(aSink);
  54. }
  55. void
  56. PermissionObserver::RemoveSink(PermissionStatus* aSink)
  57. {
  58. MOZ_ASSERT(aSink);
  59. MOZ_ASSERT(mSinks.Contains(aSink));
  60. mSinks.RemoveElement(aSink);
  61. }
  62. void
  63. PermissionObserver::Notify(PermissionName aName, nsIPrincipal& aPrincipal)
  64. {
  65. for (auto* sink : mSinks) {
  66. if (sink->mName != aName) {
  67. continue;
  68. }
  69. nsCOMPtr<nsIPrincipal> sinkPrincipal = sink->GetPrincipal();
  70. if (NS_WARN_IF(!sinkPrincipal) || !aPrincipal.Equals(sinkPrincipal)) {
  71. continue;
  72. }
  73. sink->PermissionChanged();
  74. }
  75. }
  76. NS_IMETHODIMP
  77. PermissionObserver::Observe(nsISupports* aSubject,
  78. const char* aTopic,
  79. const char16_t* aData)
  80. {
  81. MOZ_ASSERT(!strcmp(aTopic, "perm-changed"));
  82. if (mSinks.IsEmpty()) {
  83. return NS_OK;
  84. }
  85. nsCOMPtr<nsIPermission> perm = do_QueryInterface(aSubject);
  86. if (!perm) {
  87. return NS_OK;
  88. }
  89. nsCOMPtr<nsIPrincipal> principal;
  90. perm->GetPrincipal(getter_AddRefs(principal));
  91. if (!principal) {
  92. return NS_OK;
  93. }
  94. nsAutoCString type;
  95. perm->GetType(type);
  96. Maybe<PermissionName> permission = TypeToPermissionName(type.get());
  97. if (permission) {
  98. Notify(permission.value(), *principal);
  99. }
  100. return NS_OK;
  101. }
  102. } // namespace dom
  103. } // namespace mozilla