diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index f0409a8c7218..18d70ab907f2 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -2650,4 +2650,10 @@ nsINode::OwnerDocAsNode() const return OwnerDoc(); } +inline mozilla::dom::ParentObject +nsINode::GetParentObject() const +{ + return GetParentObjectInternal(OwnerDoc()); +} + #endif /* nsIDocument_h___ */ diff --git a/content/base/public/nsINode.h b/content/base/public/nsINode.h index dee37680c515..300a95690056 100644 --- a/content/base/public/nsINode.h +++ b/content/base/public/nsINode.h @@ -20,6 +20,7 @@ #include "mozilla/dom/EventTarget.h" // for base class #include "js/TypeDecls.h" // for Handle, Value, JSObject, JSContext #include "mozilla/dom/DOMString.h" +#include "mozilla/dom/BindingDeclarations.h" // Including 'windows.h' will #define GetClassInfo to something else. #ifdef XP_WIN @@ -392,18 +393,18 @@ protected: return nullptr; } -public: - nsIDocument* GetParentObject() const - { - // Make sure that we get the owner document of the content node, in case - // we're in document teardown. If we are, it's important to *not* use - // globalObj as the node's parent since that would give the node the - // principal of globalObj (i.e. the principal of the document that's being - // loaded) and not the principal of the document that's being unloaded. - // See http://bugzilla.mozilla.org/show_bug.cgi?id=227417 - return OwnerDoc(); + // Subclasses that wish to override the parent behavior should return the + // result of GetParentObjectIntenral, which handles the XBL scope stuff. + // + mozilla::dom::ParentObject GetParentObjectInternal(nsINode* aNativeParent) const { + mozilla::dom::ParentObject p(aNativeParent); + p.mUseXBLScope = ChromeOnlyAccess(); + return p; } +public: + mozilla::dom::ParentObject GetParentObject() const; // Implemented in nsIDocument.h + /** * Return whether the node is an Element node */ diff --git a/content/base/src/nsINode.cpp b/content/base/src/nsINode.cpp index fa014abe28e5..d6b84d3979a2 100644 --- a/content/base/src/nsINode.cpp +++ b/content/base/src/nsINode.cpp @@ -2594,19 +2594,8 @@ nsINode::WrapObject(JSContext *aCx, JS::Handle aScope) } JS::Rooted obj(aCx, WrapNode(aCx, aScope)); - if (obj && ChromeOnlyAccess() && - !nsContentUtils::IsSystemPrincipal(NodePrincipal()) && - xpc::AllowXBLScope(js::GetObjectCompartment(obj))) - { - // Create a new wrapper and cache it. - JSAutoCompartment ac(aCx, obj); - JSObject* wrapper = xpc::WrapperFactory::WrapSOWObject(aCx, obj); - if (!wrapper) { - ClearWrapper(); - return nullptr; - } - dom::SetSystemOnlyWrapper(obj, this, *wrapper); - } + MOZ_ASSERT_IF(ChromeOnlyAccess(), + xpc::IsInXBLScope(obj) || !xpc::UseXBLScope(js::GetObjectCompartment(obj))); return obj; } diff --git a/content/html/content/src/HTMLLegendElement.h b/content/html/content/src/HTMLLegendElement.h index 33c1e4ad01ce..b3f98cc8e4d0 100644 --- a/content/html/content/src/HTMLLegendElement.h +++ b/content/html/content/src/HTMLLegendElement.h @@ -78,9 +78,9 @@ public: SetHTMLAttr(nsGkAtoms::align, aAlign, aError); } - nsINode* GetParentObject() { + ParentObject GetParentObject() { Element* form = GetFormElement(); - return form ? static_cast(form) + return form ? GetParentObjectInternal(form) : nsGenericHTMLElement::GetParentObject(); } diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index edc6a5a63e3f..af726d75d333 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1927,12 +1927,14 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsGenericHTMLFormElement, nsGenericHTMLElement, nsIFormControl) -nsINode* +mozilla::dom::ParentObject nsGenericHTMLFormElement::GetParentObject() const { // We use the parent chain to implement the scope for event handlers. - return mForm ? static_cast(mForm) - : static_cast(OwnerDoc()); + if (mForm) { + return GetParentObjectInternal(mForm); + } + return nsGenericHTMLElement::GetParentObject(); } bool diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 42f015486b80..cdb4f0020214 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -1280,7 +1280,7 @@ public: NS_DECL_ISUPPORTS_INHERITED - nsINode* GetParentObject() const; + mozilla::dom::ParentObject GetParentObject() const; virtual bool IsNodeOfType(uint32_t aFlags) const MOZ_OVERRIDE; virtual void SaveSubtreeState() MOZ_OVERRIDE; diff --git a/content/xul/content/src/nsXULElement.h b/content/xul/content/src/nsXULElement.h index 49b9aa3de1ce..c1a2a689d77b 100644 --- a/content/xul/content/src/nsXULElement.h +++ b/content/xul/content/src/nsXULElement.h @@ -598,11 +598,11 @@ public: void SwapFrameLoaders(nsXULElement& aOtherOwner, mozilla::ErrorResult& rv); // For XUL, the parent is the parent element, if any - nsINode* GetParentObject() const + mozilla::dom::ParentObject GetParentObject() const { Element* parent = GetParentElement(); if (parent) { - return parent; + return GetParentObjectInternal(parent); } return nsStyledElement::GetParentObject(); } diff --git a/dom/bindings/BindingDeclarations.h b/dom/bindings/BindingDeclarations.h index e2fa580d0454..9f2a915daecf 100644 --- a/dom/bindings/BindingDeclarations.h +++ b/dom/bindings/BindingDeclarations.h @@ -467,22 +467,26 @@ struct ParentObject { template ParentObject(T* aObject) : mObject(aObject), - mWrapperCache(GetWrapperCache(aObject)) + mWrapperCache(GetWrapperCache(aObject)), + mUseXBLScope(false) {} template class SmartPtr> ParentObject(const SmartPtr& aObject) : mObject(aObject.get()), - mWrapperCache(GetWrapperCache(aObject.get())) + mWrapperCache(GetWrapperCache(aObject.get())), + mUseXBLScope(false) {} ParentObject(nsISupports* aObject, nsWrapperCache* aCache) : mObject(aObject), - mWrapperCache(aCache) + mWrapperCache(aCache), + mUseXBLScope(false) {} nsISupports* const mObject; nsWrapperCache* const mWrapperCache; + bool mUseXBLScope; }; } // namespace dom diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h index ade25f78cb1e..92735ea4117a 100644 --- a/dom/bindings/BindingUtils.h +++ b/dom/bindings/BindingUtils.h @@ -993,6 +993,19 @@ GetParentPointer(const ParentObject& aObject) return aObject.mObject; } +template +inline bool +GetUseXBLScope(T* aParentObject) +{ + return false; +} + +inline bool +GetUseXBLScope(const ParentObject& aParentObject) +{ + return aParentObject.mUseXBLScope; +} + template inline void ClearWrapper(T* p, nsWrapperCache* cache) @@ -1234,13 +1247,30 @@ struct WrapNativeParentHelper template static inline JSObject* WrapNativeParent(JSContext* cx, JS::Handle scope, T* p, - nsWrapperCache* cache) + nsWrapperCache* cache, bool useXBLScope = false) { if (!p) { return scope; } - return WrapNativeParentHelper::Wrap(cx, scope, p, cache); + JSObject* parent = WrapNativeParentHelper::Wrap(cx, scope, p, cache); + if (!useXBLScope) { + return parent; + } + + // If useXBLScope is true, it means that the canonical reflector for this + // native object should live in the XBL scope. + if (xpc::IsInXBLScope(parent)) { + return parent; + } + JS::Rooted rootedParent(cx, parent); + JS::Rooted xblScope(cx, xpc::GetXBLScope(cx, rootedParent)); + JSAutoCompartment ac(cx, xblScope); + if (NS_WARN_IF(!JS_WrapObject(cx, &rootedParent))) { + return nullptr; + } + + return rootedParent; } // Wrapping of our native parent, when we don't want to explicitly pass in @@ -1249,7 +1279,7 @@ template static inline JSObject* WrapNativeParent(JSContext* cx, JS::Handle scope, const T& p) { - return WrapNativeParent(cx, scope, GetParentPointer(p), GetWrapperCache(p)); + return WrapNativeParent(cx, scope, GetParentPointer(p), GetWrapperCache(p), GetUseXBLScope(p)); } // A way to differentiate between nodes, which use the parent object