diff options
Diffstat (limited to 'extensions/permissions/PermissionDelegateHandler.h')
-rw-r--r-- | extensions/permissions/PermissionDelegateHandler.h | 203 |
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..ce52b95f3b --- /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 = 13; + + 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 |