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:
Mike Conley 2017-02-28 17:22:02 -05:00
Родитель 10b5178104
Коммит bae06d41c9
7 изменённых файлов: 113 добавлений и 2 удалений

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

@ -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,