From a1ba283cde7e8cec1eec73fc4bb19ad4a1f8f734 Mon Sep 17 00:00:00 2001 From: Tim Taubert Date: Fri, 23 May 2014 14:51:56 +0200 Subject: [PATCH] Bug 990812 - Add nsIDOMChromeWindow.getGroupMessageManager() API r=smaug --- dom/base/nsGlobalWindow.cpp | 38 ++++++++++++++++++++++ dom/base/nsGlobalWindow.h | 23 ++++++++++++- dom/interfaces/base/nsIDOMChromeWindow.idl | 8 ++++- dom/webidl/Window.webidl | 7 ++++ 4 files changed, 74 insertions(+), 2 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index aab6b2ba6ce..9c8997dc3f6 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -13115,6 +13115,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow, nsGlobalWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserDOMWindow) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroupMessageManagers) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END @@ -13126,6 +13127,10 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow, tmp->mMessageManager.get())->Disconnect(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager) } + + tmp->mGroupMessageManagers.EnumerateRead(DisconnectGroupMessageManager, nullptr); + tmp->mGroupMessageManagers.Clear(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers) NS_IMPL_CYCLE_COLLECTION_UNLINK_END DOMCI_DATA(ChromeWindow, nsGlobalChromeWindow) @@ -13494,6 +13499,39 @@ nsGlobalWindow::GetMessageManager(ErrorResult& aError) return myself->mMessageManager; } +NS_IMETHODIMP +nsGlobalChromeWindow::GetGroupMessageManager(const nsAString& aGroup, + nsIMessageBroadcaster** aManager) +{ + ErrorResult rv; + NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv)); + return rv.ErrorCode(); +} + +nsIMessageBroadcaster* +nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup, + ErrorResult& aError) +{ + FORWARD_TO_INNER_OR_THROW(GetGroupMessageManager, (aGroup, aError), aError, nullptr); + MOZ_ASSERT(IsChromeWindow()); + + nsGlobalChromeWindow* myself = static_cast(this); + nsCOMPtr messageManager = + myself->mGroupMessageManagers.Get(aGroup); + + if (!messageManager) { + nsFrameMessageManager* parent = + static_cast(GetMessageManager(aError)); + + messageManager = new nsFrameMessageManager(nullptr, + parent, + MM_CHROME | MM_BROADCASTER); + myself->mGroupMessageManagers.Put(aGroup, messageManager); + } + + return messageManager; +} + // nsGlobalModalWindow implementation // QueryInterface implementation for nsGlobalModalWindow diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 82e4e0e99a0..8a356a6fa12 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -12,6 +12,7 @@ #include "nsTHashtable.h" #include "nsHashKeys.h" #include "nsRefPtrHashtable.h" +#include "nsInterfaceHashtable.h" // Local Includes // Helper Classes @@ -1006,6 +1007,8 @@ public: void NotifyDefaultButtonLoaded(mozilla::dom::Element& aDefaultButton, mozilla::ErrorResult& aError); nsIMessageBroadcaster* GetMessageManager(mozilla::ErrorResult& aError); + nsIMessageBroadcaster* GetGroupMessageManager(const nsAString& aGroup, + mozilla::ErrorResult& aError); void BeginWindowMove(mozilla::dom::Event& aMouseDownEvent, mozilla::dom::Element* aPanel, mozilla::ErrorResult& aError); @@ -1621,16 +1624,32 @@ public: NS_DECL_NSIDOMCHROMEWINDOW nsGlobalChromeWindow(nsGlobalWindow *aOuterWindow) - : nsGlobalWindow(aOuterWindow) + : nsGlobalWindow(aOuterWindow), + mGroupMessageManagers(1) { mIsChrome = true; mCleanMessageManager = true; } + static PLDHashOperator + DisconnectGroupMessageManager(const nsAString& aKey, + nsIMessageBroadcaster* aMM, + void* aUserArg) + { + if (aMM) { + static_cast(aMM)->Disconnect(); + } + return PL_DHASH_NEXT; + } + ~nsGlobalChromeWindow() { NS_ABORT_IF_FALSE(mCleanMessageManager, "chrome windows may always disconnect the msg manager"); + + mGroupMessageManagers.EnumerateRead(DisconnectGroupMessageManager, nullptr); + mGroupMessageManagers.Clear(); + if (mMessageManager) { static_cast( mMessageManager.get())->Disconnect(); @@ -1652,10 +1671,12 @@ public: using nsGlobalWindow::Restore; using nsGlobalWindow::NotifyDefaultButtonLoaded; using nsGlobalWindow::GetMessageManager; + using nsGlobalWindow::GetGroupMessageManager; using nsGlobalWindow::BeginWindowMove; nsCOMPtr mBrowserDOMWindow; nsCOMPtr mMessageManager; + nsInterfaceHashtable mGroupMessageManagers; }; /* diff --git a/dom/interfaces/base/nsIDOMChromeWindow.idl b/dom/interfaces/base/nsIDOMChromeWindow.idl index 4c4561743e3..9118a0f801f 100644 --- a/dom/interfaces/base/nsIDOMChromeWindow.idl +++ b/dom/interfaces/base/nsIDOMChromeWindow.idl @@ -10,7 +10,7 @@ interface nsIDOMElement; interface nsIDOMEvent; interface nsIMessageBroadcaster; -[scriptable, uuid(0c10226f-8abb-4345-aa6b-2780a6f4687e)] +[scriptable, uuid(78bdcb41-1efa-409f-aaba-70842213f80f)] interface nsIDOMChromeWindow : nsISupports { const unsigned short STATE_MAXIMIZED = 1; @@ -45,6 +45,12 @@ interface nsIDOMChromeWindow : nsISupports readonly attribute nsIMessageBroadcaster messageManager; + /** + * Returns the message manager identified by the given group name that + * manages all frame loaders belonging to that group. + */ + nsIMessageBroadcaster getGroupMessageManager(in AString group); + /** * On some operating systems, we must allow the window manager to * handle window dragging. This function tells the window manager to diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index b8469742647..8d7a6f5af03 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -433,6 +433,13 @@ interface ChromeWindow { [Throws, Func="nsGlobalWindow::IsChromeWindow"] readonly attribute nsIMessageBroadcaster messageManager; + /** + * Returns the message manager identified by the given group name that + * manages all frame loaders belonging to that group. + */ + [Throws, Func="nsGlobalWindow::IsChromeWindow"] + nsIMessageBroadcaster getGroupMessageManager(DOMString aGroup); + /** * On some operating systems, we must allow the window manager to * handle window dragging. This function tells the window manager to