Bug 1125325 - Store TabParents with their WindowRoot. r=smaug

nsContentUtils::CallOnAllRemoteChildren calls a callback on all tabs
connected to a given window but it has only worked in Firefox e10s tabs.
This patch adds a list of (weak) references to each top-level document's
WindowRoot so that e.g. the nsPresContext can access them instead of
using nsContentUtils.  This provides a solution to the problem of finding remote PBrowsers generally.
This commit is contained in:
David Parks 2015-06-07 22:39:39 -07:00
Родитель c485e27130
Коммит eff33f4052
7 изменённых файлов: 121 добавлений и 8 удалений

Просмотреть файл

@ -7806,3 +7806,16 @@ nsContentUtils::FirePageShowEvent(nsIDocShellTreeItem* aItem,
doc->OnPageShow(true, aChromeEventHandler);
}
}
/* static */
already_AddRefed<nsPIWindowRoot>
nsContentUtils::GetWindowRoot(nsIDocument* aDoc)
{
if (aDoc) {
nsPIDOMWindow* win = aDoc->GetWindow();
if (win) {
return win->GetTopWindowRoot();
}
}
return nullptr;
}

Просмотреть файл

@ -99,6 +99,7 @@ class nsViewportInfo;
class nsWrapperCache;
class nsAttrValue;
class nsITransferable;
class nsPIWindowRoot;
struct JSPropertyDescriptor;
struct JSRuntime;
@ -2384,6 +2385,8 @@ public:
static void FirePageHideEvent(nsIDocShellTreeItem* aItem,
mozilla::dom::EventTarget* aChromeEventHandler);
static already_AddRefed<nsPIWindowRoot> GetWindowRoot(nsIDocument* aDoc);
private:
static bool InitializeEventTable();

Просмотреть файл

@ -9,14 +9,21 @@
#include "nsISupports.h"
#include "mozilla/dom/EventTarget.h"
#include "nsWeakReference.h"
class nsPIDOMWindow;
class nsIControllers;
class nsIController;
namespace mozilla {
namespace dom {
class TabParent;
}
}
#define NS_IWINDOWROOT_IID \
{ 0x728a2682, 0x55c0, 0x4860, \
{ 0x82, 0x6b, 0x0c, 0x30, 0x0a, 0xac, 0xaa, 0x60 } }
{ 0x238edca0, 0xb30d, 0x46d3, \
{ 0xb2, 0x6a, 0x17, 0xb6, 0x21, 0x28, 0x89, 0x7e } }
class nsPIWindowRoot : public mozilla::dom::EventTarget
{
@ -38,6 +45,15 @@ public:
virtual void SetParentTarget(mozilla::dom::EventTarget* aTarget) = 0;
virtual mozilla::dom::EventTarget* GetParentTarget() = 0;
// Stores a weak reference to the browser.
virtual void AddBrowser(mozilla::dom::TabParent* aBrowser) = 0;
virtual void RemoveBrowser(mozilla::dom::TabParent* aBrowser) = 0;
typedef void (*BrowserEnumerator)(mozilla::dom::TabParent* aTab, void* aArg);
// Enumerate all stored browsers that for which the weak reference is valid.
virtual void EnumerateBrowsers(BrowserEnumerator aEnumFunc, void* aArg) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIWindowRoot, NS_IWINDOWROOT_IID)

Просмотреть файл

@ -24,6 +24,7 @@
#include "nsIController.h"
#include "xpcpublic.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/dom/TabParent.h"
#ifdef MOZ_XUL
#include "nsIDOMXULElement.h"
@ -385,6 +386,46 @@ nsWindowRoot::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
return mozilla::dom::WindowRootBinding::Wrap(aCx, this, aGivenProto);
}
void
nsWindowRoot::AddBrowser(mozilla::dom::TabParent* aBrowser)
{
nsWeakPtr weakBrowser = do_GetWeakReference(static_cast<nsITabParent*>(aBrowser));
mWeakBrowsers.PutEntry(weakBrowser);
}
void
nsWindowRoot::RemoveBrowser(mozilla::dom::TabParent* aBrowser)
{
nsWeakPtr weakBrowser = do_GetWeakReference(static_cast<nsITabParent*>(aBrowser));
mWeakBrowsers.RemoveEntry(weakBrowser);
}
static PLDHashOperator
WeakBrowserEnumFunc(nsRefPtrHashKey<nsIWeakReference>* aKey, void* aArg)
{
nsTArray<nsRefPtr<TabParent>>* tabParents =
static_cast<nsTArray<nsRefPtr<TabParent>>*>(aArg);
nsCOMPtr<nsITabParent> tabParent(do_QueryReferent((*aKey).GetKey()));
TabParent* tab = TabParent::GetFrom(tabParent);
if (tab) {
tabParents->AppendElement(tab);
}
return PL_DHASH_NEXT;
}
void
nsWindowRoot::EnumerateBrowsers(BrowserEnumerator aEnumFunc, void* aArg)
{
// Collect strong references to all browsers in a separate array in
// case aEnumFunc alters mWeakBrowsers.
nsTArray<nsRefPtr<TabParent>> tabParents;
mWeakBrowsers.EnumerateEntries(WeakBrowserEnumFunc, &tabParents);
for (uint32_t i = 0; i < tabParents.Length(); ++i) {
aEnumFunc(tabParents[i], aArg);
}
}
///////////////////////////////////////////////////////////////////////////////////
already_AddRefed<EventTarget>

Просмотреть файл

@ -69,6 +69,10 @@ public:
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsWindowRoot,
nsIDOMEventTarget)
virtual void AddBrowser(mozilla::dom::TabParent* aBrowser);
virtual void RemoveBrowser(mozilla::dom::TabParent* aBrowser);
virtual void EnumerateBrowsers(BrowserEnumerator aEnumFunc, void *aArg);
protected:
virtual ~nsWindowRoot();
@ -84,6 +88,10 @@ protected:
nsCOMPtr<nsIDOMNode> mPopupNode; // [OWNER]
nsCOMPtr<mozilla::dom::EventTarget> mParent;
// The TabParents that are currently registered with this top-level window.
typedef nsTHashtable<nsRefPtrHashKey<nsIWeakReference>> WeakBrowserTable;
WeakBrowserTable mWeakBrowsers;
};
extern already_AddRefed<mozilla::dom::EventTarget>

Просмотреть файл

@ -334,9 +334,27 @@ TabParent::SetOwnerElement(Element* aElement)
// If we held previous content then unregister for its events.
RemoveWindowListeners();
// If we change top-level documents then we need to change our
// registration with them.
nsRefPtr<nsPIWindowRoot> curTopLevelWin, newTopLevelWin;
if (mFrameElement) {
curTopLevelWin = nsContentUtils::GetWindowRoot(mFrameElement->OwnerDoc());
}
if (aElement) {
newTopLevelWin = nsContentUtils::GetWindowRoot(aElement->OwnerDoc());
}
bool isSameTopLevelWin = curTopLevelWin == newTopLevelWin;
if (curTopLevelWin && !isSameTopLevelWin) {
curTopLevelWin->RemoveBrowser(this);
}
// Update to the new content, and register to listen for events from it.
mFrameElement = aElement;
if (newTopLevelWin && !isSameTopLevelWin) {
newTopLevelWin->AddBrowser(this);
}
AddWindowListeners();
TryCacheDPIAndScale();
}
@ -1001,6 +1019,7 @@ TabParent::UIResolutionChanged()
// TryCacheDPIAndScale()'s cache is keyed off of
// mDPI being greater than 0, so this invalidates it.
mDPI = -1;
TryCacheDPIAndScale();
unused << SendUIResolutionChanged();
}
}

Просмотреть файл

@ -1822,9 +1822,24 @@ nsPresContext::UIResolutionChangedSubdocumentCallback(nsIDocument* aDocument,
}
static void
NotifyUIResolutionChanged(TabParent* aTabParent, void* aArg)
NotifyTabUIResolutionChanged(TabParent* aTab, void *aArg)
{
aTabParent->UIResolutionChanged();
aTab->UIResolutionChanged();
}
static void
NotifyChildrenUIResolutionChanged(nsIDOMWindow* aWindow)
{
nsCOMPtr<nsPIDOMWindow> piWin = do_QueryInterface(aWindow);
if (!piWin) {
return;
}
nsCOMPtr<nsIDocument> doc = piWin->GetExtantDoc();
nsRefPtr<nsPIWindowRoot> topLevelWin = nsContentUtils::GetWindowRoot(doc);
if (!topLevelWin) {
return;
}
topLevelWin->EnumerateBrowsers(NotifyTabUIResolutionChanged, nullptr);
}
void
@ -1837,10 +1852,8 @@ nsPresContext::UIResolutionChangedInternal()
AppUnitsPerDevPixelChanged();
}
// Recursively notify all remote leaf descendants that the
// resolution of the user interface has changed.
nsContentUtils::CallOnAllRemoteChildren(mDocument->GetWindow(),
NotifyUIResolutionChanged, nullptr);
// Recursively notify all remote leaf descendants of the change.
NotifyChildrenUIResolutionChanged(mDocument->GetWindow());
mDocument->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback,
nullptr);