From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- dom/base/MaybeCrossOriginObject.h | 354 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 dom/base/MaybeCrossOriginObject.h (limited to 'dom/base/MaybeCrossOriginObject.h') diff --git a/dom/base/MaybeCrossOriginObject.h b/dom/base/MaybeCrossOriginObject.h new file mode 100644 index 0000000000..5a75e70dce --- /dev/null +++ b/dom/base/MaybeCrossOriginObject.h @@ -0,0 +1,354 @@ +/* -*- Mode: C++; tab-width: 8; 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/. */ + +#ifndef mozilla_dom_MaybeCrossOriginObject_h +#define mozilla_dom_MaybeCrossOriginObject_h + +/** + * Shared infrastructure for WindowProxy and Location objects. These + * are the objects that can be accessed cross-origin in the HTML + * specification. + * + * This class can be inherited from by the relevant proxy handlers to + * help implement spec algorithms. + * + * The algorithms this class implements come from + * , + * , + * and + * . + * + * The class is templated on its base so we can directly implement the things + * that should have identical implementations for WindowProxy and Location. The + * templating is needed because WindowProxy needs to be a wrapper and Location + * shouldn't be one. + */ + +#include "js/Class.h" +#include "js/TypeDecls.h" +#include "nsStringFwd.h" +#include "mozilla/Maybe.h" + +namespace mozilla::dom { + +/** + * "mAttributes" and "mMethods" are the cross-origin attributes and methods we + * care about, which should get defined on holders. + * + * "mChromeOnlyAttributes" and "mChromeOnlyMethods" are the cross-origin + * attributes and methods we care about, which should get defined on holders + * for the chrome realm, in addition to the properties that are in + * "mAttributes" and "mMethods". + */ +struct CrossOriginProperties { + const JSPropertySpec* mAttributes; + const JSFunctionSpec* mMethods; + const JSPropertySpec* mChromeOnlyAttributes; + const JSFunctionSpec* mChromeOnlyMethods; +}; + +// Methods that MaybeCrossOriginObject wants that do not depend on the "Base" +// template parameter. We can avoid having multiple instantiations of them by +// pulling them out into this helper class. +class MaybeCrossOriginObjectMixins { + public: + /** + * Implementation of + * . + * "cx" and "obj" may or may not be same-compartment and even when + * same-compartment may not be same-Realm. "obj" can be a WindowProxy, a + * Window, or a Location. + */ + static bool IsPlatformObjectSameOrigin(JSContext* cx, JSObject* obj); + + protected: + /** + * Implementation of + * . + * + * "cx" and "obj" are expected to be different-Realm here, and may be + * different-compartment. "obj" can be a "WindowProxy" or a "Location" or a + * cross-process proxy for one of those. + */ + bool CrossOriginGetOwnPropertyHelper( + JSContext* cx, JS::Handle obj, JS::Handle id, + JS::MutableHandle> desc) const; + + /** + * Implementation of + * . + * + * This should be called at the end of getOwnPropertyDescriptor + * methods in the cross-origin case. + * + * "cx" and "obj" are expected to be different-Realm here, and may + * be different-compartment. "obj" can be a "WindowProxy" or a + * "Location" or a cross-process proxy for one of those. + */ + static bool CrossOriginPropertyFallback( + JSContext* cx, JS::Handle obj, JS::Handle id, + JS::MutableHandle> desc); + + /** + * Implementation of + * . + * + * "cx" and "obj" are expected to be different-Realm here and may be + * different-compartment. "obj" can be a "WindowProxy" or a + * "Location" or a cross-process proxy for one of those. + * + * "receiver" will be in the compartment of "cx". The return value will + * be in the compartment of "cx". + */ + static bool CrossOriginGet(JSContext* cx, JS::Handle obj, + JS::Handle receiver, + JS::Handle id, + JS::MutableHandle vp); + + /** + * Implementation of + * . + * + * "cx" and "obj" are expected to be different-Realm here and may be + * different-compartment. "obj" can be a "WindowProxy" or a + * "Location" or a cross-process proxy for one of those. + * + * "receiver" and "v" will be in the compartment of "cx". + */ + static bool CrossOriginSet(JSContext* cx, JS::Handle obj, + JS::Handle id, JS::Handle v, + JS::Handle receiver, + JS::ObjectOpResult& result); + + /** + * Utility method to ensure a holder for cross-origin properties for the + * current global of the JSContext. + * + * When this is called, "cx" and "obj" are _always_ different-Realm, because + * this is only used in cross-origin situations. The "holder" return value is + * always in the Realm of "cx". + * + * "obj" is the object which has space to store the collection of holders in + * the given slot. + * + * "properties" are the cross-origin attributes and methods we care about, + * which should get defined on holders. + */ + static bool EnsureHolder(JSContext* cx, JS::Handle obj, + size_t slot, const CrossOriginProperties& properties, + JS::MutableHandle holder); + + /** + * Ensures we have a holder object for the current Realm. When this is + * called, "obj" is guaranteed to not be same-Realm with "cx", because this + * is only used for cross-origin cases. + * + * Subclasses are expected to implement this by calling our static + * EnsureHolder with the appropriate arguments. + */ + virtual bool EnsureHolder(JSContext* cx, JS::Handle proxy, + JS::MutableHandle holder) const = 0; + + /** + * Report a cross-origin denial for a property named by aId. Always + * returns false, so it can be used as "return + * ReportCrossOriginDenial(...);". + */ + static bool ReportCrossOriginDenial(JSContext* aCx, JS::Handle aId, + const nsACString& aAccessType); +}; + +// A proxy handler for objects that may be cross-origin objects. Whether they +// actually _are_ cross-origin objects can change dynamically if document.domain +// is set. +template +class MaybeCrossOriginObject : public Base, + public MaybeCrossOriginObjectMixins { + protected: + template + constexpr MaybeCrossOriginObject(Args&&... aArgs) + : Base(std::forward(aArgs)...) {} + + /** + * Implementation of [[GetPrototypeOf]] as defined in + * + * and + * . + * + * Our prototype-storage model looks quite different from the spec's, so we + * need to implement some hooks that don't directly map to the spec. + * + * "proxy" is the WindowProxy or Location involved. It may or may not be + * same-compartment with cx. + * + * "protop" is the prototype value (possibly null). It is guaranteed to be + * same-compartment with cx after this function returns successfully. + */ + bool getPrototype(JSContext* cx, JS::Handle proxy, + JS::MutableHandle protop) const final; + + /** + * Hook for doing the OrdinaryGetPrototypeOf bits that [[GetPrototypeOf]] does + * in the spec. Location and WindowProxy store that information somewhat + * differently. + * + * The prototype should come from the Realm of "cx". + */ + virtual JSObject* getSameOriginPrototype(JSContext* cx) const = 0; + + /** + * Implementation of [[SetPrototypeOf]] as defined in + * + * and + * . + * + * "proxy" is the WindowProxy or Location object involved. It may or may not + * be same-compartment with "cx". + * + * "proto" is the new prototype object (possibly null). It must be + * same-compartment with "cx". + */ + bool setPrototype(JSContext* cx, JS::Handle proxy, + JS::Handle proto, + JS::ObjectOpResult& result) const final; + + /** + * Our non-standard getPrototypeIfOrdinary hook. + */ + bool getPrototypeIfOrdinary(JSContext* cx, JS::Handle proxy, + bool* isOrdinary, + JS::MutableHandle protop) const final; + + /** + * Our non-standard setImmutablePrototype hook. + */ + bool setImmutablePrototype(JSContext* cx, JS::Handle proxy, + bool* succeeded) const final; + + /** + * Implementation of [[IsExtensible]] as defined in + * + * and + * . + */ + bool isExtensible(JSContext* cx, JS::Handle proxy, + bool* extensible) const final; + + /** + * Implementation of [[PreventExtensions]] as defined in + * + * and + * . + */ + bool preventExtensions(JSContext* cx, JS::Handle proxy, + JS::ObjectOpResult& result) const final; + + /** + * Implementation of [[GetOwnProperty]] is completely delegated to subclasses. + * + * "proxy" is the WindowProxy or Location object involved. It may or may not + * be same-compartment with cx. + */ + bool getOwnPropertyDescriptor( + JSContext* cx, JS::Handle proxy, JS::Handle id, + JS::MutableHandle> desc) const override = 0; + + /** + * Implementation of [[DefineOwnProperty]] as defined in + * + * and + * . + * "proxy" is the WindowProxy or Location object involved. It may or may not + * be same-compartment with cx. + * + */ + bool defineProperty(JSContext* cx, JS::Handle proxy, + JS::Handle id, + JS::Handle desc, + JS::ObjectOpResult& result) const final; + + /** + * Some of our base classes define _another_ virtual defineProperty, and we + * get overloaded-virtual warnings as a result due to us hiding it, if we + * don't pull it in here. + */ + using Base::defineProperty; + + /** + * Hook for handling the same-origin case in defineProperty. + * + * "proxy" is the WindowProxy or Location object involved. It will be + * same-compartment with cx. + * + * "desc" is a the descriptor being defined. It will be same-compartment with + * cx. + */ + virtual bool definePropertySameOrigin(JSContext* cx, + JS::Handle proxy, + JS::Handle id, + JS::Handle desc, + JS::ObjectOpResult& result) const = 0; + + /** + * Implementation of [[Get]] is completely delegated to subclasses. + * + * "proxy" is the WindowProxy or Location object involved. It may or may not + * be same-compartment with "cx". + * + * "receiver" is the receiver ("this") for the get. It will be + * same-compartment with "cx" + * + * "vp" is the return value. It will be same-compartment with "cx". + */ + bool get(JSContext* cx, JS::Handle proxy, + JS::Handle receiver, JS::Handle id, + JS::MutableHandle vp) const override = 0; + + /** + * Implementation of [[Set]] is completely delegated to subclasses. + * + * "proxy" is the WindowProxy or Location object involved. It may or may not + * be same-compartment with "cx". + * + * "v" is the value being set. It will be same-compartment with "cx". + * + * "receiver" is the receiver ("this") for the set. It will be + * same-compartment with "cx". + */ + bool set(JSContext* cx, JS::Handle proxy, JS::Handle id, + JS::Handle v, JS::Handle receiver, + JS::ObjectOpResult& result) const override = 0; + + /** + * Implementation of [[Delete]] is completely delegated to subclasses. + * + * "proxy" is the WindowProxy or Location object involved. It may or may not + * be same-compartment with "cx". + */ + bool delete_(JSContext* cx, JS::Handle proxy, JS::Handle id, + JS::ObjectOpResult& result) const override = 0; + + /** + * Spidermonkey-internal hook for enumerating objects. + */ + bool enumerate(JSContext* cx, JS::Handle proxy, + JS::MutableHandleVector props) const final; + + // Cross origin objects should not participate in private fields. + virtual bool throwOnPrivateField() const override { return true; } + + /** + * Spidermonkey-internal hook used by Object.prototype.toString. Subclasses + * need to implement this, because we don't know what className they want. + * Except in the cross-origin case, when we could maybe handle it... + */ + const char* className(JSContext* cx, + JS::Handle proxy) const override = 0; +}; + +} // namespace mozilla::dom + +#endif /* mozilla_dom_MaybeCrossOriginObject_h */ -- cgit v1.2.3