Bug 990812 - Allow a deeper frame message manager hierarchy than only global > window > tab r=smaug

This commit is contained in:
Tim Taubert 2014-05-23 14:52:36 +02:00
parent fdaf311981
commit ab4d658e1d
5 changed files with 121 additions and 85 deletions

View File

@ -93,6 +93,56 @@ MarkUserDataHandler(void* aNode, nsIAtom* aKey, void* aValue, void* aData)
}
}
static void
MarkChildMessageManagers(nsIMessageBroadcaster* aMM)
{
aMM->MarkForCC();
uint32_t tabChildCount = 0;
aMM->GetChildCount(&tabChildCount);
for (uint32_t j = 0; j < tabChildCount; ++j) {
nsCOMPtr<nsIMessageListenerManager> childMM;
aMM->GetChildAt(j, getter_AddRefs(childMM));
if (!childMM) {
continue;
}
nsCOMPtr<nsIMessageBroadcaster> strongNonLeafMM = do_QueryInterface(childMM);
nsIMessageBroadcaster* nonLeafMM = strongNonLeafMM;
nsCOMPtr<nsIMessageSender> strongTabMM = do_QueryInterface(childMM);
nsIMessageSender* tabMM = strongTabMM;
strongNonLeafMM = nullptr;
strongTabMM = nullptr;
childMM = nullptr;
if (nonLeafMM) {
MarkChildMessageManagers(nonLeafMM);
continue;
}
tabMM->MarkForCC();
//XXX hack warning, but works, since we know that
// callback is frameloader.
mozilla::dom::ipc::MessageManagerCallback* cb =
static_cast<nsFrameMessageManager*>(tabMM)->GetCallback();
if (cb) {
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
EventTarget* et = fl->GetTabChildGlobalAsEventTarget();
if (!et) {
continue;
}
static_cast<nsInProcessTabChildGlobal*>(et)->MarkForCC();
EventListenerManager* elm = et->GetExistingListenerManager();
if (elm) {
elm->MarkForCC();
}
}
}
}
static void
MarkMessageManagers()
{
@ -107,52 +157,8 @@ MarkMessageManagers()
}
nsIMessageBroadcaster* globalMM = strongGlobalMM;
strongGlobalMM = nullptr;
MarkChildMessageManagers(globalMM);
globalMM->MarkForCC();
uint32_t childCount = 0;
globalMM->GetChildCount(&childCount);
for (uint32_t i = 0; i < childCount; ++i) {
nsCOMPtr<nsIMessageListenerManager> childMM;
globalMM->GetChildAt(i, getter_AddRefs(childMM));
if (!childMM) {
continue;
}
nsCOMPtr<nsIMessageBroadcaster> strongWindowMM = do_QueryInterface(childMM);
nsIMessageBroadcaster* windowMM = strongWindowMM;
childMM = nullptr;
strongWindowMM = nullptr;
windowMM->MarkForCC();
uint32_t tabChildCount = 0;
windowMM->GetChildCount(&tabChildCount);
for (uint32_t j = 0; j < tabChildCount; ++j) {
nsCOMPtr<nsIMessageListenerManager> childMM;
windowMM->GetChildAt(j, getter_AddRefs(childMM));
if (!childMM) {
continue;
}
nsCOMPtr<nsIMessageSender> strongTabMM = do_QueryInterface(childMM);
nsIMessageSender* tabMM = strongTabMM;
childMM = nullptr;
strongTabMM = nullptr;
tabMM->MarkForCC();
//XXX hack warning, but works, since we know that
// callback is frameloader.
mozilla::dom::ipc::MessageManagerCallback* cb =
static_cast<nsFrameMessageManager*>(tabMM)->GetCallback();
if (cb) {
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
EventTarget* et = fl->GetTabChildGlobalAsEventTarget();
if (!et) {
continue;
}
static_cast<nsInProcessTabChildGlobal*>(et)->MarkForCC();
EventListenerManager* elm = et->GetExistingListenerManager();
if (elm) {
elm->MarkForCC();
}
}
}
}
if (nsFrameMessageManager::sParentProcessManager) {
nsFrameMessageManager::sParentProcessManager->MarkForCC();
uint32_t childCount = 0;

View File

@ -431,7 +431,7 @@ nsFrameMessageManager::LoadFrameScript(const nsAString& aURL,
aRunInGlobalScope = true;
if (aAllowDelayedLoad) {
if (IsGlobal() || IsWindowLevel()) {
if (IsGlobal() || IsBroadcaster()) {
// Cache for future windows or frames
mPendingScripts.AppendElement(aURL);
mPendingScriptsGlobalStates.AppendElement(aRunInGlobalScope);
@ -481,7 +481,7 @@ nsFrameMessageManager::GetDelayedFrameScripts(JSContext* aCx, JS::MutableHandle<
{
// Frame message managers may return an incomplete list because scripts
// that were loaded after it was connected are not added to the list.
if (!IsGlobal() && !IsWindowLevel()) {
if (!IsGlobal() && !IsBroadcaster()) {
NS_WARNING("Cannot retrieve list of pending frame scripts for frame"
"message managers as it may be incomplete");
return NS_ERROR_NOT_IMPLEMENTED;
@ -590,7 +590,7 @@ nsFrameMessageManager::SendMessage(const nsAString& aMessageName,
bool aIsSync)
{
NS_ASSERTION(!IsGlobal(), "Should not call SendSyncMessage in chrome");
NS_ASSERTION(!IsWindowLevel(), "Should not call SendSyncMessage in chrome");
NS_ASSERTION(!IsBroadcaster(), "Should not call SendSyncMessage in chrome");
NS_ASSERTION(!mParentManager, "Should not have parent manager in content!");
aRetval.setUndefined();
@ -1099,19 +1099,26 @@ nsFrameMessageManager::AddChildManager(nsFrameMessageManager* aManager)
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip = this;
nsRefPtr<nsFrameMessageManager> kungfuDeathGrip2 = aManager;
// We have parent manager if we're a window message manager.
// In that case we want to load the pending scripts from global
// message manager.
if (mParentManager) {
nsRefPtr<nsFrameMessageManager> globalMM = mParentManager;
for (uint32_t i = 0; i < globalMM->mPendingScripts.Length(); ++i) {
aManager->LoadFrameScript(globalMM->mPendingScripts[i], false,
globalMM->mPendingScriptsGlobalStates[i]);
}
LoadPendingScripts(this, aManager);
}
void
nsFrameMessageManager::LoadPendingScripts(nsFrameMessageManager* aManager,
nsFrameMessageManager* aChildMM)
{
// We have parent manager if we're a message broadcaster.
// In that case we want to load the pending scripts from all parent
// message managers in the hierarchy. Process the parent first so
// that pending scripts higher up in the hierarchy are loaded before others.
if (aManager->mParentManager) {
LoadPendingScripts(aManager->mParentManager, aChildMM);
}
for (uint32_t i = 0; i < mPendingScripts.Length(); ++i) {
aManager->LoadFrameScript(mPendingScripts[i], false,
mPendingScriptsGlobalStates[i]);
for (uint32_t i = 0; i < aManager->mPendingScripts.Length(); ++i) {
aChildMM->LoadFrameScript(aManager->mPendingScripts[i],
false,
aManager->mPendingScriptsGlobalStates[i]);
}
}
@ -1138,7 +1145,7 @@ nsFrameMessageManager::InitWithCallback(MessageManagerCallback* aCallback)
SetCallback(aCallback);
// First load global scripts by adding this to parent manager.
// First load parent scripts by adding this to parent manager.
if (mParentManager) {
mParentManager->AddChildManager(this);
}

View File

@ -173,10 +173,10 @@ public:
NS_ASSERTION(!mIsBroadcaster || !mCallback,
"Broadcasters cannot have callbacks!");
// This is a bit hackish. When parent manager is global, we want
// to attach the window message manager to it immediately.
// to attach the message manager to it immediately.
// Is it just the frame message manager which waits until the
// content process is running.
if (mParentManager && (mCallback || IsWindowLevel())) {
if (mParentManager && (mCallback || IsBroadcaster())) {
mParentManager->AddChildManager(this);
}
if (mOwnsCallback) {
@ -258,7 +258,7 @@ public:
mParentManager = aParent;
}
bool IsGlobal() { return mGlobal; }
bool IsWindowLevel() { return mParentManager && mParentManager->IsGlobal(); }
bool IsBroadcaster() { return mIsBroadcaster; }
static nsFrameMessageManager* GetParentProcessManager()
{
@ -296,6 +296,9 @@ protected:
nsFrameMessageManager* mParentManager;
nsTArray<nsString> mPendingScripts;
nsTArray<bool> mPendingScriptsGlobalStates;
void LoadPendingScripts(nsFrameMessageManager* aManager,
nsFrameMessageManager* aChildMM);
public:
static nsFrameMessageManager* sParentProcessManager;
static nsFrameMessageManager* sChildProcessManager;

View File

@ -1778,33 +1778,46 @@ nsPresContext::UIResolutionChangedInternal()
chromeWindow->GetMessageManager(getter_AddRefs(windowMM));
}
if (windowMM) {
uint32_t tabChildCount = 0;
windowMM->GetChildCount(&tabChildCount);
for (uint32_t j = 0; j < tabChildCount; ++j) {
nsCOMPtr<nsIMessageListenerManager> childMM;
windowMM->GetChildAt(j, getter_AddRefs(childMM));
if (!childMM) {
continue;
}
nsCOMPtr<nsIMessageSender> tabMM = do_QueryInterface(childMM);
mozilla::dom::ipc::MessageManagerCallback* cb =
static_cast<nsFrameMessageManager*>(tabMM.get())->GetCallback();
if (cb) {
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
PBrowserParent* remoteBrowser = fl->GetRemoteBrowser();
TabParent* remote = static_cast<TabParent*>(remoteBrowser);
if (remote) {
remote->UIResolutionChanged();
}
}
}
NotifyUIResolutionChanged(windowMM);
}
mDocument->EnumerateSubDocuments(UIResolutionChangedSubdocumentCallback,
nullptr);
}
void
nsPresContext::NotifyUIResolutionChanged(nsIMessageBroadcaster* aManager)
{
uint32_t tabChildCount = 0;
aManager->GetChildCount(&tabChildCount);
for (uint32_t j = 0; j < tabChildCount; ++j) {
nsCOMPtr<nsIMessageListenerManager> childMM;
aManager->GetChildAt(j, getter_AddRefs(childMM));
if (!childMM) {
continue;
}
nsCOMPtr<nsIMessageBroadcaster> nonLeafMM = do_QueryInterface(childMM);
if (nonLeafMM) {
NotifyUIResolutionChanged(nonLeafMM);
continue;
}
nsCOMPtr<nsIMessageSender> tabMM = do_QueryInterface(childMM);
mozilla::dom::ipc::MessageManagerCallback* cb =
static_cast<nsFrameMessageManager*>(tabMM.get())->GetCallback();
if (cb) {
nsFrameLoader* fl = static_cast<nsFrameLoader*>(cb);
PBrowserParent* remoteBrowser = fl->GetRemoteBrowser();
TabParent* remote = static_cast<TabParent*>(remoteBrowser);
if (remote) {
remote->UIResolutionChanged();
}
}
}
}
void
nsPresContext::EmulateMedium(const nsAString& aMediaType)
{

View File

@ -36,6 +36,7 @@
#include "prclist.h"
#include "nsThreadUtils.h"
#include "ScrollbarStyles.h"
#include "nsIMessageManager.h"
class nsBidiPresUtils;
class nsAString;
@ -784,6 +785,12 @@ public:
*/
NS_HIDDEN_(void) UIResolutionChanged();
/**
* Recursively notify all remote leaf descendants of a given message manager
* that the resolution of the user interface has changed.
*/
NS_HIDDEN_(void) NotifyUIResolutionChanged(nsIMessageBroadcaster* aManager);
/*
* Notify the pres context that a system color has changed
*/