Permissions.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 "mozilla/dom/Permissions.h"
  6. #include "mozilla/dom/ContentChild.h"
  7. #include "mozilla/dom/PermissionsBinding.h"
  8. #include "mozilla/dom/Promise.h"
  9. #include "mozilla/Services.h"
  10. #include "nsIPermissionManager.h"
  11. #include "PermissionStatus.h"
  12. #include "PermissionUtils.h"
  13. namespace mozilla {
  14. namespace dom {
  15. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Permissions)
  16. NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  17. NS_INTERFACE_MAP_ENTRY(nsISupports)
  18. NS_INTERFACE_MAP_END
  19. NS_IMPL_CYCLE_COLLECTING_ADDREF(Permissions)
  20. NS_IMPL_CYCLE_COLLECTING_RELEASE(Permissions)
  21. NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Permissions, mWindow)
  22. Permissions::Permissions(nsPIDOMWindowInner* aWindow)
  23. : mWindow(aWindow)
  24. {
  25. }
  26. Permissions::~Permissions()
  27. {
  28. }
  29. JSObject*
  30. Permissions::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
  31. {
  32. return PermissionsBinding::Wrap(aCx, this, aGivenProto);
  33. }
  34. namespace {
  35. already_AddRefed<PermissionStatus>
  36. CreatePermissionStatus(JSContext* aCx,
  37. JS::Handle<JSObject*> aPermission,
  38. nsPIDOMWindowInner* aWindow,
  39. ErrorResult& aRv)
  40. {
  41. PermissionDescriptor permission;
  42. JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission));
  43. if (NS_WARN_IF(!permission.Init(aCx, value))) {
  44. aRv.NoteJSContextException(aCx);
  45. return nullptr;
  46. }
  47. switch (permission.mName) {
  48. case PermissionName::Geolocation:
  49. case PermissionName::Notifications:
  50. case PermissionName::Push:
  51. return PermissionStatus::Create(aWindow, permission.mName, aRv);
  52. default:
  53. MOZ_ASSERT_UNREACHABLE("Unhandled type");
  54. aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
  55. return nullptr;
  56. }
  57. }
  58. } // namespace
  59. already_AddRefed<Promise>
  60. Permissions::Query(JSContext* aCx,
  61. JS::Handle<JSObject*> aPermission,
  62. ErrorResult& aRv)
  63. {
  64. nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
  65. if (!global) {
  66. aRv.Throw(NS_ERROR_UNEXPECTED);
  67. return nullptr;
  68. }
  69. RefPtr<PermissionStatus> status =
  70. CreatePermissionStatus(aCx, aPermission, mWindow, aRv);
  71. if (NS_WARN_IF(aRv.Failed())) {
  72. MOZ_ASSERT(!status);
  73. return nullptr;
  74. }
  75. MOZ_ASSERT(status);
  76. RefPtr<Promise> promise = Promise::Create(global, aRv);
  77. if (NS_WARN_IF(aRv.Failed())) {
  78. return nullptr;
  79. }
  80. promise->MaybeResolve(status);
  81. return promise.forget();
  82. }
  83. /* static */ nsresult
  84. Permissions::RemovePermission(nsIPrincipal* aPrincipal, const char* aPermissionType)
  85. {
  86. MOZ_ASSERT(XRE_IsParentProcess());
  87. nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
  88. if (NS_WARN_IF(!permMgr)) {
  89. return NS_ERROR_FAILURE;
  90. }
  91. return permMgr->RemoveFromPrincipal(aPrincipal, aPermissionType);
  92. }
  93. already_AddRefed<Promise>
  94. Permissions::Revoke(JSContext* aCx,
  95. JS::Handle<JSObject*> aPermission,
  96. ErrorResult& aRv)
  97. {
  98. nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
  99. if (!global) {
  100. aRv.Throw(NS_ERROR_UNEXPECTED);
  101. return nullptr;
  102. }
  103. PermissionDescriptor permission;
  104. JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission));
  105. if (NS_WARN_IF(!permission.Init(aCx, value))) {
  106. aRv.NoteJSContextException(aCx);
  107. return nullptr;
  108. }
  109. RefPtr<Promise> promise = Promise::Create(global, aRv);
  110. if (NS_WARN_IF(aRv.Failed())) {
  111. return nullptr;
  112. }
  113. nsCOMPtr<nsIDocument> document = mWindow->GetExtantDoc();
  114. if (!document) {
  115. promise->MaybeReject(NS_ERROR_UNEXPECTED);
  116. return promise.forget();
  117. }
  118. nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
  119. if (NS_WARN_IF(!permMgr)) {
  120. promise->MaybeReject(NS_ERROR_FAILURE);
  121. return promise.forget();
  122. }
  123. const char* permissionType = PermissionNameToType(permission.mName);
  124. nsresult rv;
  125. if (XRE_IsParentProcess()) {
  126. rv = RemovePermission(document->NodePrincipal(), permissionType);
  127. } else {
  128. // Permissions can't be removed from the content process. Send a message
  129. // to the parent; `ContentParent::RecvRemovePermission` will call
  130. // `RemovePermission`.
  131. ContentChild::GetSingleton()->SendRemovePermission(
  132. IPC::Principal(document->NodePrincipal()), nsDependentCString(permissionType), &rv);
  133. }
  134. if (NS_WARN_IF(NS_FAILED(rv))) {
  135. promise->MaybeReject(rv);
  136. return promise.forget();
  137. }
  138. RefPtr<PermissionStatus> status =
  139. CreatePermissionStatus(aCx, aPermission, mWindow, aRv);
  140. if (NS_WARN_IF(aRv.Failed())) {
  141. MOZ_ASSERT(!status);
  142. return nullptr;
  143. }
  144. MOZ_ASSERT(status);
  145. promise->MaybeResolve(status);
  146. return promise.forget();
  147. }
  148. } // namespace dom
  149. } // namespace mozilla