зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1342927 - Fire a MozTabChildNotReady event on a frameloader if force-painting a tab without a TabChild. r=billm
MozReview-Commit-ID: D8vgvQ3MLJN --HG-- extra : rebase_source : 29192f938b57018eb947cb9d55a3ac3ab8621e76
This commit is contained in:
Родитель
10b5178104
Коммит
bae06d41c9
|
@ -4250,6 +4250,23 @@ ContentParent::RecvNotifyTabDestroying(const TabId& aTabId,
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
ContentParent::RecvTabChildNotReady(const TabId& aTabId)
|
||||
{
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
RefPtr<TabParent> tp =
|
||||
cpm->GetTopLevelTabParentByProcessAndTabId(this->ChildID(), aTabId);
|
||||
|
||||
if (!tp) {
|
||||
NS_WARNING("Couldn't find TabParent for TabChildNotReady message.");
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
tp->DispatchTabChildNotReadyEvent();
|
||||
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
nsTArray<TabContext>
|
||||
ContentParent::GetManagedTabContext()
|
||||
{
|
||||
|
|
|
@ -491,6 +491,8 @@ public:
|
|||
virtual mozilla::ipc::IPCResult RecvNotifyTabDestroying(const TabId& aTabId,
|
||||
const ContentParentId& aCpId) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvTabChildNotReady(const TabId& aTabId) override;
|
||||
|
||||
nsTArray<TabContext> GetManagedTabContext();
|
||||
|
||||
virtual POfflineCacheUpdateParent*
|
||||
|
|
|
@ -1022,6 +1022,9 @@ parent:
|
|||
*/
|
||||
async NotifyTabDestroying(TabId tabId,
|
||||
ContentParentId cpId);
|
||||
|
||||
async TabChildNotReady(TabId tabId);
|
||||
|
||||
/**
|
||||
* Starts an offline application cache update.
|
||||
* @param manifestURI
|
||||
|
|
|
@ -34,6 +34,7 @@ protocol PProcessHangMonitor
|
|||
parent:
|
||||
async HangEvidence(HangData data);
|
||||
async ClearHang();
|
||||
async Ready();
|
||||
|
||||
child:
|
||||
async TerminateScript();
|
||||
|
|
|
@ -12,11 +12,13 @@
|
|||
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/BackgroundHangMonitor.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/TabChild.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/ipc/TaskFactory.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/plugins/PluginBridge.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
@ -194,6 +196,8 @@ public:
|
|||
mDumpId.Truncate();
|
||||
}
|
||||
|
||||
void DispatchTabChildNotReady(TabId aTabId);
|
||||
|
||||
private:
|
||||
~HangMonitoredProcess() = default;
|
||||
|
||||
|
@ -213,6 +217,7 @@ public:
|
|||
|
||||
void Bind(Endpoint<PProcessHangMonitorParent>&& aEndpoint);
|
||||
|
||||
mozilla::ipc::IPCResult RecvReady() override;
|
||||
mozilla::ipc::IPCResult RecvHangEvidence(const HangData& aHangData) override;
|
||||
mozilla::ipc::IPCResult RecvClearHang() override;
|
||||
|
||||
|
@ -241,6 +246,8 @@ public:
|
|||
private:
|
||||
bool TakeBrowserMinidump(const PluginHangData& aPhd, nsString& aCrashId);
|
||||
|
||||
void DispatchTabChildNotReady(TabId aTabId);
|
||||
|
||||
void ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch);
|
||||
|
||||
void ShutdownOnThread();
|
||||
|
@ -250,6 +257,12 @@ private:
|
|||
// This field is read-only after construction.
|
||||
bool mReportHangs;
|
||||
|
||||
// This field is only accessed on the hang thread. Inits to
|
||||
// false, and will flip to true once the HangMonitorChild is
|
||||
// constructed in the child process, and sends a message saying
|
||||
// so.
|
||||
bool mReady;
|
||||
|
||||
// This field is only accessed on the hang thread.
|
||||
bool mIPCOpen;
|
||||
|
||||
|
@ -261,6 +274,7 @@ private:
|
|||
// Map from plugin ID to crash dump ID. Protected by mBrowserCrashDumpHashLock.
|
||||
nsDataHashtable<nsUint32HashKey, nsString> mBrowserCrashDumpIds;
|
||||
Mutex mBrowserCrashDumpHashLock;
|
||||
mozilla::ipc::TaskFactory<HangMonitorParent> mMainThreadTaskFactory;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -318,6 +332,11 @@ HangMonitorChild::InterruptCallback()
|
|||
if (tabChild) {
|
||||
js::AutoAssertNoContentJS nojs(mContext);
|
||||
tabChild->ForcePaint(forcePaintEpoch);
|
||||
} else {
|
||||
auto cc = ContentChild::GetSingleton();
|
||||
if (cc) {
|
||||
cc->SendTabChildNotReady(forcePaintTab);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -423,6 +442,8 @@ HangMonitorChild::Bind(Endpoint<PProcessHangMonitorChild>&& aEndpoint)
|
|||
|
||||
DebugOnly<bool> ok = aEndpoint.Bind(this);
|
||||
MOZ_ASSERT(ok);
|
||||
|
||||
Unused << SendReady();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -545,10 +566,12 @@ HangMonitorChild::ClearHangAsync()
|
|||
|
||||
HangMonitorParent::HangMonitorParent(ProcessHangMonitor* aMonitor)
|
||||
: mHangMonitor(aMonitor),
|
||||
mReady(false),
|
||||
mIPCOpen(true),
|
||||
mMonitor("HangMonitorParent lock"),
|
||||
mShutdownDone(false),
|
||||
mBrowserCrashDumpHashLock("mBrowserCrashDumpIds lock")
|
||||
mBrowserCrashDumpHashLock("mBrowserCrashDumpIds lock"),
|
||||
mMainThreadTaskFactory(this)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
mReportHangs = mozilla::Preferences::GetBool("dom.ipc.reportProcessHangs", false);
|
||||
|
@ -614,13 +637,38 @@ HangMonitorParent::ForcePaint(dom::TabParent* aTab, uint64_t aLayerObserverEpoch
|
|||
this, &HangMonitorParent::ForcePaintOnThread, id, aLayerObserverEpoch));
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::DispatchTabChildNotReady(TabId aTabId)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
if (!mProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
mProcess->DispatchTabChildNotReady(aTabId);
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitorParent::ForcePaintOnThread(TabId aTabId, uint64_t aLayerObserverEpoch)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
|
||||
if (mIPCOpen) {
|
||||
Unused << SendForcePaint(aTabId, aLayerObserverEpoch);
|
||||
if (mReady) {
|
||||
Unused << SendForcePaint(aTabId, aLayerObserverEpoch);
|
||||
} else {
|
||||
// We've never heard from the HangMonitorChild before, so
|
||||
// it's either not finished setting up, or has only recently
|
||||
// finished setting up. In either case, we're dealing with
|
||||
// a new content process that probably hasn't had time to
|
||||
// get the ContentChild, let alone the TabChild for aTabId,
|
||||
// set up, and so attempting to force paint on the non-existant
|
||||
// TabChild is not going to work. Instead, we tell the main
|
||||
// thread that we're waiting on a TabChild to be created.
|
||||
NS_DispatchToMainThread(
|
||||
mMainThreadTaskFactory.NewRunnableMethod(
|
||||
&HangMonitorParent::DispatchTabChildNotReady, aTabId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -718,6 +766,14 @@ HangMonitorParent::TakeBrowserMinidump(const PluginHangData& aPhd,
|
|||
return false;
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HangMonitorParent::RecvReady()
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(MessageLoop::current() == MonitorLoop());
|
||||
mReady = true;
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
HangMonitorParent::RecvHangEvidence(const HangData& aHangData)
|
||||
{
|
||||
|
@ -1058,6 +1114,17 @@ HangMonitoredProcess::UserCanceled()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
HangMonitoredProcess::DispatchTabChildNotReady(TabId aTabId)
|
||||
{
|
||||
MOZ_RELEASE_ASSERT(NS_IsMainThread());
|
||||
if (!mContentParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
Unused << mContentParent->RecvTabChildNotReady(aTabId);
|
||||
}
|
||||
|
||||
static bool
|
||||
InterruptCallback(JSContext* cx)
|
||||
{
|
||||
|
|
|
@ -3332,6 +3332,25 @@ TabParent::LiveResizeStopped()
|
|||
SuppressDisplayport(false);
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::DispatchTabChildNotReadyEvent()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsCOMPtr<mozilla::dom::EventTarget> target = do_QueryInterface(mFrameElement);
|
||||
if (!target) {
|
||||
NS_WARNING("Could not locate target for tab child not ready event.");
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<Event> event = NS_NewDOMEvent(mFrameElement, nullptr, nullptr);
|
||||
event->InitEvent(NS_LITERAL_STRING("MozTabChildNotReady"), true, false);
|
||||
event->SetTrusted(true);
|
||||
event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
|
||||
bool dummy;
|
||||
mFrameElement->DispatchEvent(event, &dummy);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FakeChannel::OnAuthAvailable(nsISupports *aContext, nsIAuthInformation *aAuthInfo)
|
||||
{
|
||||
|
|
|
@ -599,6 +599,8 @@ public:
|
|||
void LiveResizeStarted() override;
|
||||
void LiveResizeStopped() override;
|
||||
|
||||
void DispatchTabChildNotReadyEvent();
|
||||
|
||||
protected:
|
||||
bool ReceiveMessage(const nsString& aMessage,
|
||||
bool aSync,
|
||||
|
|
Загрузка…
Ссылка в новой задаче