From d375d57d33d5aeebb5ce62d9fc865bb09d5b1868 Mon Sep 17 00:00:00 2001 From: Cameron Kaiser Date: Tue, 3 Oct 2017 19:19:57 -0700 Subject: [PATCH] #388: M1354564 --- browser/base/content/tabbrowser.xml | 6 +++ .../xul/nsIDOMXULCommandDispatcher.idl | 5 +++ dom/xul/nsXULCommandDispatcher.cpp | 37 ++++++++++++++++++- dom/xul/nsXULCommandDispatcher.h | 3 ++ 4 files changed, 50 insertions(+), 1 deletion(-) diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 65aa8721a..4efa59e34 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1008,6 +1008,8 @@ var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex); if (this.mCurrentBrowser == newBrowser && !aForceUpdate) return; + if (!aForceUpdate) + document.commandDispatcher.lock(); /* if (!aForceUpdate) { @@ -1204,6 +1206,8 @@ this.tabContainer._setPositionalAttributes(); //if (!gMultiProcessBrowser) { + document.commandDispatcher.unlock(); + let event = new CustomEvent("TabSwitchDone", { bubbles: true, cancelable: true @@ -3203,6 +3207,8 @@ let remote = false; fromBrowser.setAttribute("type", "content-targetable"); } + document.commandDispatcher.unlock(); + let event = new CustomEvent("TabSwitchDone", { bubbles: true, cancelable: true diff --git a/dom/interfaces/xul/nsIDOMXULCommandDispatcher.idl b/dom/interfaces/xul/nsIDOMXULCommandDispatcher.idl index 7ece93561..6d51a9d65 100644 --- a/dom/interfaces/xul/nsIDOMXULCommandDispatcher.idl +++ b/dom/interfaces/xul/nsIDOMXULCommandDispatcher.idl @@ -31,4 +31,9 @@ interface nsIDOMXULCommandDispatcher : nsISupports void rewindFocus(); void advanceFocusIntoSubtree(in nsIDOMElement elt); attribute boolean suppressFocusScroll; + + // When locked, command updating is batched until unlocked. Always ensure that + // lock and unlock is called in a pair. + void lock(); + void unlock(); }; diff --git a/dom/xul/nsXULCommandDispatcher.cpp b/dom/xul/nsXULCommandDispatcher.cpp index 6a1a6630e..8cb82fe29 100644 --- a/dom/xul/nsXULCommandDispatcher.cpp +++ b/dom/xul/nsXULCommandDispatcher.cpp @@ -42,7 +42,7 @@ static LazyLogModule gCommandLog("nsXULCommandDispatcher"); //////////////////////////////////////////////////////////////////////// nsXULCommandDispatcher::nsXULCommandDispatcher(nsIDocument* aDocument) - : mDocument(aDocument), mUpdaters(nullptr) + : mDocument(aDocument), mUpdaters(nullptr), mLocked(false) { } @@ -351,6 +351,14 @@ nsXULCommandDispatcher::RemoveCommandUpdater(nsIDOMElement* aElement) NS_IMETHODIMP nsXULCommandDispatcher::UpdateCommands(const nsAString& aEventName) { + if (mLocked) { + if (!mPendingUpdates.Contains(aEventName)) { + mPendingUpdates.AppendElement(aEventName); + } + + return NS_OK; + } + nsAutoString id; nsCOMPtr element; GetFocusedElement(getter_AddRefs(element)); @@ -458,3 +466,30 @@ nsXULCommandDispatcher::SetSuppressFocusScroll(bool aSuppressFocusScroll) return NS_OK; } +NS_IMETHODIMP +nsXULCommandDispatcher::Lock() +{ + // Since locking is used only as a performance optimization, we don't worry + // about nested lock calls. If that does happen, it just means we will unlock + // and process updates earlier. + mLocked = true; + return NS_OK; +} + +NS_IMETHODIMP +nsXULCommandDispatcher::Unlock() +{ + if (mLocked) { + mLocked = false; + + // Handle any pending updates one at a time. In the unlikely case where a + // lock is added during the update, break out. + while (!mLocked && mPendingUpdates.Length() > 0) { + nsString name = mPendingUpdates.ElementAt(0); + mPendingUpdates.RemoveElementAt(0); + UpdateCommands(name); + } + } + + return NS_OK; +} diff --git a/dom/xul/nsXULCommandDispatcher.h b/dom/xul/nsXULCommandDispatcher.h index 9e64ad509..9780859f2 100644 --- a/dom/xul/nsXULCommandDispatcher.h +++ b/dom/xul/nsXULCommandDispatcher.h @@ -68,6 +68,9 @@ protected: bool Matches(const nsString& aList, const nsAString& aElement); + + bool mLocked; + nsTArray mPendingUpdates; }; #endif // nsXULCommandDispatcher_h__