summaryrefslogtreecommitdiffstats
path: root/extensions/permissions/PermissionDelegateHandler.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--extensions/permissions/PermissionDelegateHandler.h203
1 files changed, 203 insertions, 0 deletions
diff --git a/extensions/permissions/PermissionDelegateHandler.h b/extensions/permissions/PermissionDelegateHandler.h
new file mode 100644
index 0000000000..a07fbceaeb
--- /dev/null
+++ b/extensions/permissions/PermissionDelegateHandler.h
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Permission delegate handler provides a policy of how top-level can
+ * delegate permission to embedded iframes.
+ *
+ * This class includes a mechanism to delegate permission using feature
+ * policy. Feature policy will assure that only cross-origin iframes which
+ * have been explicitly granted access will have the opportunity to request
+ * permission.
+ *
+ * For example if an iframe has not been granted access to geolocation by
+ * Feature Policy, geolocation request from the iframe will be automatically
+ * denied. if the top-level origin already has access to geolocation and the
+ * iframe has been granted access to geolocation by Feature Policy, the iframe
+ * will also have access to geolocation. If the top-level frame did not have
+ * access to geolocation, and the iframe has been granted access to geolocation
+ * by Feature Policy, a request from the cross-origin iframe would trigger a
+ * prompt using of the top-level origin.
+ */
+
+#ifndef mozilla_PermissionDelegateHandler_h
+#define mozilla_PermissionDelegateHandler_h
+
+#include "mozilla/Array.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsISupports.h"
+#include "nsIPermissionDelegateHandler.h"
+#include "nsIPermissionManager.h"
+#include "nsCOMPtr.h"
+
+class nsIPrincipal;
+class nsIContentPermissionRequest;
+
+namespace mozilla {
+namespace dom {
+class Document;
+class WindowContext;
+} // namespace dom
+
+class PermissionDelegateHandler final : public nsIPermissionDelegateHandler {
+ public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(PermissionDelegateHandler)
+
+ NS_DECL_NSIPERMISSIONDELEGATEHANDLER
+
+ explicit PermissionDelegateHandler() = default;
+ explicit PermissionDelegateHandler(mozilla::dom::Document* aDocument);
+
+ static constexpr size_t DELEGATED_PERMISSION_COUNT = 12;
+
+ typedef struct DelegatedPermissionList {
+ Array<uint32_t, DELEGATED_PERMISSION_COUNT> mPermissions;
+
+ bool operator==(const DelegatedPermissionList& aOther) const {
+ return mPermissions == aOther.mPermissions;
+ }
+ } DelegatedPermissionList;
+
+ bool Initialize();
+
+ /*
+ * Indicates if we has the right to make permission request with aType
+ */
+ bool HasPermissionDelegated(const nsACString& aType) const;
+
+ /*
+ * Get permission state, which applied permission delegate policy.
+ *
+ * @param aType the permission type to get
+ * @param aPermission out argument which will be a permission type that we
+ * will return from this function.
+ * @param aExactHostMatch whether to look for the exact host name or also for
+ * subdomains that can have the same permission.
+ */
+ nsresult GetPermission(const nsACString& aType, uint32_t* aPermission,
+ bool aExactHostMatch);
+
+ /*
+ * Get permission state for permission api, which applied
+ * permission delegate policy.
+ *
+ * @param aType the permission type to get
+ * @param aExactHostMatch whether to look for the exact host name or also for
+ * subdomains that can have the same permission.
+ * @param aPermission out argument which will be a permission type that we
+ * will return from this function.
+ */
+ nsresult GetPermissionForPermissionsAPI(const nsACString& aType,
+ uint32_t* aPermission);
+
+ enum PermissionDelegatePolicy {
+ /* Always delegate permission from top level to iframe and the iframe
+ * should use top level origin to get/set permission.*/
+ eDelegateUseTopOrigin,
+
+ /* Permission is delegated using Feature Policy. Permission is denied by
+ * default in cross origin iframe and the iframe only could get/set
+ * permission if there's allow attribute set in iframe. e.g allow =
+ * "geolocation" */
+ eDelegateUseFeaturePolicy,
+
+ /* Persistent denied permissions in cross origin iframe */
+ ePersistDeniedCrossOrigin,
+
+ /* This is the old behavior of cross origin iframe permission. The
+ * permission delegation should not have an effect on iframe. The cross
+ * origin iframe get/set permissions by its origin */
+ eDelegateUseIframeOrigin,
+ };
+
+ /*
+ * Indicates matching between Feature Policy and Permissions name defined in
+ * Permissions Manager, not DOM Permissions API. Permissions API exposed in
+ * DOM only supports "geo" at the moment but Permissions Manager also supports
+ * "camera", "microphone".
+ */
+ typedef struct {
+ const char* mPermissionName;
+ const char16_t* mFeatureName;
+ PermissionDelegatePolicy mPolicy;
+ } PermissionDelegateInfo;
+
+ /**
+ * The loader maintains a weak reference to the document with
+ * which it is initialized. This call forces the reference to
+ * be dropped.
+ */
+ void DropDocumentReference() { mDocument = nullptr; }
+
+ /*
+ * Helper function to return the delegate info value for aPermissionName.
+ * @param aPermissionName the permission name to get
+ */
+ static const PermissionDelegateInfo* GetPermissionDelegateInfo(
+ const nsAString& aPermissionName);
+
+ /*
+ * Helper function to return the delegate principal. This will return nullptr,
+ * or request's principal or top level principal based on the delegate policy
+ * will be applied for a given type.
+ * We use this function when prompting, no need to perform permission check
+ * (deny/allow).
+ *
+ * @param aType the permission type to get
+ * @param aRequest The request which the principal is get from.
+ * @param aResult out argument which will be a principal that we
+ * will return from this function.
+ */
+ static nsresult GetDelegatePrincipal(const nsACString& aType,
+ nsIContentPermissionRequest* aRequest,
+ nsIPrincipal** aResult);
+
+ /**
+ * Populate all delegated permissions to the WindowContext of the associated
+ * document. We only populate the permissions for the top-level content.
+ */
+ void PopulateAllDelegatedPermissions();
+
+ /**
+ * Update the given delegated permission to the WindowContext. We only
+ * update it for the top-level content.
+ */
+ void UpdateDelegatedPermission(const nsACString& aType);
+
+ private:
+ ~PermissionDelegateHandler() = default;
+
+ /*
+ * Check whether the permission is blocked by FeaturePolicy directive.
+ * Default allowlist for a featureName of permission used in permissions
+ * delegate should be set to eSelf, to ensure that permission is denied by
+ * default and only have the opportunity to request permission with allow
+ * attribute.
+ */
+ bool HasFeaturePolicyAllowed(const PermissionDelegateInfo* info) const;
+
+ /**
+ * A helper function to test the permission and set the result to the given
+ * list. It will return true if the permission is changed, otherwise false.
+ */
+ bool UpdateDelegatePermissionInternal(
+ PermissionDelegateHandler::DelegatedPermissionList& aList,
+ const nsACString& aType, size_t aIdx,
+ nsresult (NS_STDCALL nsIPermissionManager::*aTestFunc)(nsIPrincipal*,
+ const nsACString&,
+ uint32_t*));
+
+ // A weak pointer to our document. Nulled out by DropDocumentReference.
+ mozilla::dom::Document* mDocument;
+
+ nsCOMPtr<nsIPrincipal> mPrincipal;
+ RefPtr<nsIPermissionManager> mPermissionManager;
+};
+
+} // namespace mozilla
+
+#endif // mozilla_PermissionDelegateHandler_h