--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -251,32 +251,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
// XXX tmp->mContextStack?
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentPrototype)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMasterPrototype)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCommandDispatcher)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrototypes)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLocalStore)
- if (tmp->mOverlayLoadObservers) {
- for (auto iter = tmp->mOverlayLoadObservers->Iter();
- !iter.Done();
- iter.Next()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mOverlayLoadObservers value");
- cb.NoteXPCOMChild(iter.Data());
- }
- }
- if (tmp->mPendingOverlayLoadNotifications) {
- for (auto iter = tmp->mPendingOverlayLoadNotifications->Iter();
- !iter.Done();
- iter.Next()) {
- NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mPendingOverlayLoadNotifications value");
- cb.NoteXPCOMChild(iter.Data());
- }
- }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULDocument, XMLDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommandDispatcher)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStore)
//XXX We should probably unlink all the objects we traverse.
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@@ -2349,19 +2333,16 @@ nsresult
XULDocument::DoneWalking()
{
NS_PRECONDITION(mPendingSheets == 0, "there are sheets to be loaded");
NS_PRECONDITION(!mStillWalking, "walk not done");
// XXXldb This is where we should really be setting the chromehidden
// attribute.
- /// ZZZ DOES THE ABOVE COMMENT NEED TO BE REMOVED
-
-
if (!mDocumentLoaded) {
// Make sure we don't reenter here from StartLayout(). Note that
// setting mDocumentLoaded to true here means that if StartLayout()
// causes ResumeWalk() to be reentered, we'll take the other branch of
// the |if (!mDocumentLoaded)| check above and since
// mInitialLayoutComplete will be false will follow the else branch
// there too. See the big comment there for how such reentry can
// happen.
@@ -2401,79 +2382,16 @@ XULDocument::DoneWalking()
NS_DOCUMENT_NOTIFY_OBSERVERS(EndLoad, (this));
// DispatchContentLoadedEvents undoes the onload-blocking we
// did in PrepareToWalk().
DispatchContentLoadedEvents();
mInitialLayoutComplete = true;
-
- // Walk the set of pending load notifications and notify any observers.
- // See below for detail.
- if (mPendingOverlayLoadNotifications) {
- nsInterfaceHashtable<nsURIHashKey,nsIObserver>* observers =
- mOverlayLoadObservers.get();
- for (auto iter = mPendingOverlayLoadNotifications->Iter();
- !iter.Done();
- iter.Next()) {
- nsIURI* aKey = iter.Key();
- iter.Data()->Observe(aKey, "xul-overlay-merged",
- EmptyString().get());
-
- if (observers) {
- observers->Remove(aKey);
- }
-
- iter.Remove();
- }
- }
- }
- else {
- if (mOverlayLoadObservers) {
- nsCOMPtr<nsIURI> overlayURI = mCurrentPrototype->GetURI();
- nsCOMPtr<nsIObserver> obs;
- if (mInitialLayoutComplete) {
- // We have completed initial layout, so just send the notification.
- mOverlayLoadObservers->Get(overlayURI, getter_AddRefs(obs));
- if (obs)
- obs->Observe(overlayURI, "xul-overlay-merged", EmptyString().get());
- mOverlayLoadObservers->Remove(overlayURI);
- }
- else {
- // If we have not yet displayed the document for the first time
- // (i.e. we came in here as the result of a dynamic overlay load
- // which was spawned by a binding-attached event caused by
- // StartLayout() on the master prototype - we must remember that
- // this overlay has been merged and tell the listeners after
- // StartLayout() is completely finished rather than doing so
- // immediately - otherwise we may be executing code that needs to
- // access XBL Binding implementations on nodes for which frames
- // have not yet been constructed because their bindings have not
- // yet been attached. This can be a race condition because dynamic
- // overlay loading can take varying amounts of time depending on
- // whether or not the overlay prototype is in the XUL cache. The
- // most likely effect of this bug is odd UI initialization due to
- // methods and properties that do not work.
- // XXXbz really, we shouldn't be firing binding constructors
- // until after StartLayout returns!
-
- if (!mPendingOverlayLoadNotifications) {
- mPendingOverlayLoadNotifications =
- new nsInterfaceHashtable<nsURIHashKey,nsIObserver>;
- }
-
- mPendingOverlayLoadNotifications->Get(overlayURI, getter_AddRefs(obs));
- if (!obs) {
- mOverlayLoadObservers->Get(overlayURI, getter_AddRefs(obs));
- NS_ASSERTION(obs, "null overlay load observer?");
- mPendingOverlayLoadNotifications->Put(overlayURI, obs);
- }
- }
- }
}
return NS_OK;
}
NS_IMETHODIMP
XULDocument::StyleSheetLoaded(StyleSheet* aSheet,
bool aWasAlternate,
@@ -2962,261 +2880,16 @@ XULDocument::AddAttributes(nsXULPrototyp
}
return NS_OK;
}
//----------------------------------------------------------------------
//
-// XULDocument::OverlayForwardReference
-//
-
-nsForwardReference::Result
-XULDocument::OverlayForwardReference::Resolve()
-{
- // Resolve a forward reference from an overlay element; attempt to
- // hook it up into the main document.
- nsresult rv;
- RefPtr<Element> target;
-
- nsIPresShell *shell = mDocument->GetShell();
- bool notify = shell && shell->DidInitialize();
-
- nsAutoString id;
- mOverlay->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
- if (id.IsEmpty()) {
- // mOverlay is a direct child of <overlay> and has no id.
- // Insert it under the root element in the base document.
- Element* root = mDocument->GetRootElement();
- if (!root) {
- return eResolve_Error;
- }
-
- rv = XULDocument::InsertElement(root, mOverlay, notify);
- if (NS_FAILED(rv)) return eResolve_Error;
-
- target = mOverlay;
- }
- else {
- // The hook-up element has an id, try to match it with an element
- // with the same id in the base document.
- target = mDocument->GetElementById(id);
-
- // If we can't find the element in the document, defer the hookup
- // until later.
- if (!target)
- return eResolve_Later;
-
- rv = Merge(target, mOverlay, notify);
- if (NS_FAILED(rv)) return eResolve_Error;
- }
-
- // Check if 'target' is still in our document --- it might not be!
- if (!notify && target->GetUncomposedDoc() == mDocument) {
- // Add child and any descendants to the element map
- // XXX this is bogus, the content in 'target' might already be
- // in the document
- rv = mDocument->AddSubtreeToDocument(target);
- if (NS_FAILED(rv)) return eResolve_Error;
- }
-
- if (MOZ_LOG_TEST(gXULLog, LogLevel::Debug)) {
- nsAutoCString idC;
- LossyCopyUTF16toASCII(id, idC);
- MOZ_LOG(gXULLog, LogLevel::Debug,
- ("xul: overlay resolved '%s'",
- idC.get()));
- }
-
- mResolved = true;
- return eResolve_Succeeded;
-}
-
-
-
-nsresult
-XULDocument::OverlayForwardReference::Merge(Element* aTargetElement,
- Element* aOverlayElement,
- bool aNotify)
-{
- // This function is given:
- // aTargetElement: the element in the document whose 'id' attribute
- // matches a toplevel node in our overlay.
- // aOverlayElement: the element in the overlay document that matches
- // an element in the actual document.
- // aNotify: whether or not content manipulation methods should
- // use the aNotify parameter. After the initial
- // reflow (i.e. in the dynamic overlay merge case),
- // we want all the content manipulation methods we
- // call to notify so that frames are constructed
- // etc. Otherwise do not, since that's during initial
- // document construction before StartLayout has been
- // called which will do everything for us.
- //
- // This function merges the tree from the overlay into the tree in
- // the document, overwriting attributes and appending child content
- // nodes appropriately. (See XUL overlay reference for details)
-
- nsresult rv;
-
- // Merge attributes from the overlay content node to that of the
- // actual document.
- uint32_t i;
- const nsAttrName* name;
- for (i = 0; (name = aOverlayElement->GetAttrNameAt(i)); ++i) {
- // We don't want to swap IDs, they should be the same.
- if (name->Equals(nsGkAtoms::id))
- continue;
-
- // In certain cases merging command or observes is unsafe, so don't.
- if (!aNotify) {
- if (aTargetElement->NodeInfo()->Equals(nsGkAtoms::observes,
- kNameSpaceID_XUL))
- continue;
-
- if (name->Equals(nsGkAtoms::observes) &&
- aTargetElement->HasAttr(kNameSpaceID_None, nsGkAtoms::observes))
- continue;
-
- if (name->Equals(nsGkAtoms::command) &&
- aTargetElement->HasAttr(kNameSpaceID_None, nsGkAtoms::command) &&
- !aTargetElement->NodeInfo()->Equals(nsGkAtoms::key,
- kNameSpaceID_XUL) &&
- !aTargetElement->NodeInfo()->Equals(nsGkAtoms::menuitem,
- kNameSpaceID_XUL))
- continue;
- }
-
- int32_t nameSpaceID = name->NamespaceID();
- nsAtom* attr = name->LocalName();
- nsAtom* prefix = name->GetPrefix();
-
- nsAutoString value;
- aOverlayElement->GetAttr(nameSpaceID, attr, value);
-
- // Element in the overlay has the 'removeelement' attribute set
- // so remove it from the actual document.
- if (attr == nsGkAtoms::removeelement && value.EqualsLiteral("true")) {
- nsCOMPtr<nsINode> parent = aTargetElement->GetParentNode();
- if (!parent) return NS_ERROR_FAILURE;
- parent->RemoveChildNode(aTargetElement, true);
- return NS_OK;
- }
-
- rv = aTargetElement->SetAttr(nameSpaceID, attr, prefix, value, aNotify);
- if (!NS_FAILED(rv) && !aNotify) {
- rv = mDocument->BroadcastAttributeChangeFromOverlay(
- aTargetElement, nameSpaceID, attr, prefix, value);
- }
- if (NS_FAILED(rv)) return rv;
- }
-
-
- // Walk our child nodes, looking for elements that have the 'id'
- // attribute set. If we find any, we must do a parent check in the
- // actual document to ensure that the structure matches that of
- // the actual document. If it does, we can call ourselves and attempt
- // to merge inside that subtree. If not, we just append the tree to
- // the parent like any other.
-
- uint32_t childCount = aOverlayElement->GetChildCount();
-
- // This must be a strong reference since it will be the only
- // reference to a content object during part of this loop.
- nsCOMPtr<nsIContent> currContent;
-
- for (i = 0; i < childCount; ++i) {
- currContent = aOverlayElement->GetFirstChild();
-
- nsAtom *idAtom = currContent->GetID();
-
- Element* elementInDocument = nullptr;
- if (idAtom) {
- nsDependentAtomString id(idAtom);
-
- if (!id.IsEmpty()) {
- nsIDocument *doc = aTargetElement->GetUncomposedDoc();
- //XXXsmaug should we use ShadowRoot::GetElementById()
- // if doc is null?
- if (!doc) return NS_ERROR_FAILURE;
-
- elementInDocument = doc->GetElementById(id);
- }
- }
-
- // The item has an 'id' attribute set, and we need to check with
- // the actual document to see if an item with this id exists at
- // this locale. If so, we want to merge the subtree under that
- // node. Otherwise, we just do an append as if the element had
- // no id attribute.
- if (elementInDocument) {
- // Given two parents, aTargetElement and aOverlayElement, we want
- // to call merge on currContent if we find an associated
- // node in the document with the same id as currContent that
- // also has aTargetNode as its parent.
-
- nsIContent* elementParent = elementInDocument->GetParent();
-
- nsAtom *parentID = elementParent->GetID();
- if (parentID && aTargetElement->GetID() == parentID) {
- // The element matches. "Go Deep!"
- //
- // Note that currContent is necessarily an element, because
- // elementInDocument can only be non-null when currContent has a
- // non-null ID.
- rv = Merge(elementInDocument, currContent->AsElement(), aNotify);
- if (NS_FAILED(rv)) return rv;
- nsIContent* firstChild = aOverlayElement->GetFirstChild();
- if (firstChild) {
- aOverlayElement->RemoveChildNode(firstChild, false);
- }
-
- continue;
- }
- }
-
- nsIContent* firstChild = aOverlayElement->GetFirstChild();
- if (firstChild) {
- aOverlayElement->RemoveChildNode(firstChild, false);
- }
-
- rv = InsertElement(aTargetElement, currContent, aNotify);
- if (NS_FAILED(rv)) return rv;
- }
-
- return NS_OK;
-}
-
-
-
-XULDocument::OverlayForwardReference::~OverlayForwardReference()
-{
- if (MOZ_LOG_TEST(gXULLog, LogLevel::Warning) && !mResolved) {
- nsAutoString id;
- mOverlay->GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
-
- nsAutoCString idC;
- LossyCopyUTF16toASCII(id, idC);
-
- nsIURI *protoURI = mDocument->mCurrentPrototype->GetURI();
-
- nsCOMPtr<nsIURI> docURI;
- mDocument->mChannel->GetOriginalURI(getter_AddRefs(docURI));
-
- MOZ_LOG(gXULLog, LogLevel::Warning,
- ("xul: %s overlay failed to resolve '%s' in %s",
- protoURI->GetSpecOrDefault().get(), idC.get(),
- docURI ? docURI->GetSpecOrDefault().get() : ""));
- }
-}
-
-
-//----------------------------------------------------------------------
-//
// XULDocument::BroadcasterHookup
//
nsForwardReference::Result
XULDocument::BroadcasterHookup::Resolve()
{
nsresult rv;
@@ -3254,54 +2927,16 @@ XULDocument::BroadcasterHookup::~Broadca
attributeC.get(),
broadcasteridC.get()));
}
}
//----------------------------------------------------------------------
nsresult
-XULDocument::BroadcastAttributeChangeFromOverlay(nsIContent* aNode,
- int32_t aNameSpaceID,
- nsAtom* aAttribute,
- nsAtom* aPrefix,
- const nsAString& aValue)
-{
- nsresult rv = NS_OK;
-
- if (!mBroadcasterMap || !CanBroadcast(aNameSpaceID, aAttribute))
- return rv;
-
- if (!aNode->IsElement())
- return rv;
-
- auto entry = static_cast<BroadcasterMapEntry*>
- (mBroadcasterMap->Search(aNode->AsElement()));
- if (!entry)
- return rv;
-
- // We've got listeners: push the value.
- for (size_t i = entry->mListeners.Length() - 1; i != (size_t)-1; --i) {
- BroadcastListener* bl = entry->mListeners[i];
-
- if ((bl->mAttribute != aAttribute) &&
- (bl->mAttribute != nsGkAtoms::_asterisk))
- continue;
-
- nsCOMPtr<Element> l = do_QueryReferent(bl->mListener);
- if (l) {
- rv = l->SetAttr(aNameSpaceID, aAttribute,
- aPrefix, aValue, false);
- if (NS_FAILED(rv)) return rv;
- }
- }
- return rv;
-}
-
-nsresult
XULDocument::FindBroadcaster(Element* aElement,
Element** aListener,
nsString& aBroadcasterID,
nsString& aAttribute,
Element** aBroadcaster)
{
mozilla::dom::NodeInfo *ni = aElement->NodeInfo();
*aListener = nullptr;
--- a/dom/xul/XULDocument.h
+++ b/dom/xul/XULDocument.h
@@ -233,23 +233,16 @@ protected:
nsresult
AddElementToDocumentPost(Element* aElement);
nsresult
ExecuteOnBroadcastHandlerFor(Element* aBroadcaster,
Element* aListener,
nsAtom* aAttr);
- nsresult
- BroadcastAttributeChangeFromOverlay(nsIContent* aNode,
- int32_t aNameSpaceID,
- nsAtom* aAttribute,
- nsAtom* aPrefix,
- const nsAString& aValue);
-
already_AddRefed<nsPIWindowRoot> GetWindowRoot();
static void DirectionChanged(const char* aPrefName, void* aData);
// pseudo constants
static int32_t gRefCnt;
static nsIRDFService* gRDFService;
@@ -444,40 +437,16 @@ protected:
virtual Phase GetPhase() override { return eHookup; }
virtual Result Resolve() override;
};
friend class BroadcasterHookup;
- /**
- * Used to hook up overlays
- */
- class OverlayForwardReference : public nsForwardReference
- {
- protected:
- XULDocument* mDocument; // [WEAK]
- nsCOMPtr<Element> mOverlay; // [OWNER]
- bool mResolved;
-
- nsresult Merge(Element* aTargetNode, Element* aOverlayNode, bool aNotify);
-
- public:
- OverlayForwardReference(XULDocument* aDocument, Element* aOverlay)
- : mDocument(aDocument), mOverlay(aOverlay), mResolved(false) {}
-
- virtual ~OverlayForwardReference();
-
- virtual Phase GetPhase() override { return eConstruction; }
- virtual Result Resolve() override;
- };
-
- friend class OverlayForwardReference;
-
// The out params of FindBroadcaster only have values that make sense when
// the method returns NS_FINDBROADCASTER_FOUND. In all other cases, the
// values of the out params should not be relied on (though *aListener and
// *aBroadcaster do need to be released if non-null, of course).
nsresult
FindBroadcaster(Element* aElement,
Element** aListener,
nsString& aBroadcasterID,
@@ -577,19 +546,16 @@ protected:
friend class CachedChromeStreamListener;
/**
* A map from a broadcaster element to a list of listener elements.
*/
PLDHashTable* mBroadcasterMap;
- nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mOverlayLoadObservers;
- nsAutoPtr<nsInterfaceHashtable<nsURIHashKey,nsIObserver> > mPendingOverlayLoadNotifications;
-
bool mInitialLayoutComplete;
class nsDelayedBroadcastUpdate
{
public:
nsDelayedBroadcastUpdate(Element* aBroadcaster,
Element* aListener,
const nsAString &aAttr)