Bug 1646505 - Fix about:performance for Fission. r=tarek

With fission it's not possible to use
nsPIDOMWindowOuter::GetInProcessTop and expect to find the top-level
window, since it might be in another process. Instead we use
BrowsingContext::Top. Another issue is that it's not possible to
traverse children by recursively calling GetTabSizes, instead we need
to use BrowsingContext traversal mechanics.

Memory reporting is a bit tricky, since now doc gropus belonging to a
cross process top level browsing context needs to report it's memory
usage and can't skip it, so this is also handled.

Differential Revision: https://phabricator.services.mozilla.com/D97312
This commit is contained in:
Andreas Farre 2020-12-11 15:56:23 +00:00
Родитель cbf9cc6b39
Коммит 1b5787e10a
4 изменённых файлов: 93 добавлений и 49 удалений

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

@ -12,9 +12,11 @@
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/Telemetry.h"
#include "mozilla/ThrottledEventQueue.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/JSExecutionManager.h"
#include "mozilla/dom/WindowContext.h"
#include "nsDOMMutationObserver.h"
#include "nsIDirectTaskDispatcher.h"
#include "nsProxyRelease.h"
@ -220,38 +222,35 @@ RefPtr<PerformanceInfoPromise> DocGroup::ReportPerformanceInfo() {
uint64_t windowID = 0;
uint16_t count = 0;
uint64_t duration = 0;
bool isTopLevel = false;
nsCString host;
nsCOMPtr<nsPIDOMWindowOuter> top;
RefPtr<AbstractThread> mainThread;
bool isTopLevel = false;
RefPtr<BrowsingContext> top;
RefPtr<AbstractThread> mainThread =
AbstractMainThreadFor(TaskCategory::Performance);
// iterating on documents until we find the top window
for (const auto& document : *this) {
nsCOMPtr<Document> doc = document;
MOZ_ASSERT(doc);
nsCOMPtr<nsIURI> docURI = doc->GetDocumentURI();
if (!docURI) {
continue;
}
docURI->GetHost(host);
// If the host is empty, using the url
if (host.IsEmpty()) {
host = docURI->GetSpecOrDefault();
nsCOMPtr<nsIURI> docURI = document->GetDocumentURI();
if (!docURI) {
continue;
}
docURI->GetHost(host);
if (host.IsEmpty()) {
host = docURI->GetSpecOrDefault();
}
}
// looking for the top level document URI
nsPIDOMWindowOuter* win = doc->GetWindow();
if (!win) {
BrowsingContext* context = document->GetBrowsingContext();
if (!context) {
continue;
}
top = win->GetInProcessTop();
if (!top) {
continue;
}
windowID = top->WindowID();
isTopLevel = win->GetBrowsingContext()->IsTop();
mainThread = AbstractMainThreadFor(TaskCategory::Performance);
top = context->Top();
isTopLevel = context->IsTop();
windowID = top->GetCurrentWindowContext()->OuterWindowId();
break;
}
};
MOZ_ASSERT(!host.IsEmpty());
duration = mPerformanceCounter->GetExecutionDuration();
@ -268,7 +267,7 @@ RefPtr<PerformanceInfoPromise> DocGroup::ReportPerformanceInfo() {
}
}
if (!isTopLevel) {
if (!isTopLevel && top && top->IsInProcess()) {
return PerformanceInfoPromise::CreateAndResolve(
PerformanceInfo(host, pid, windowID, duration,
mPerformanceCounter->GetID(), false, isTopLevel,
@ -279,8 +278,8 @@ RefPtr<PerformanceInfoPromise> DocGroup::ReportPerformanceInfo() {
MOZ_ASSERT(mainThread);
RefPtr<DocGroup> self = this;
return CollectMemoryInfo(top, mainThread)
return (isTopLevel ? CollectMemoryInfo(top, mainThread)
: CollectMemoryInfo(self, mainThread))
->Then(
mainThread, __func__,
[self, host, pid, windowID, duration, isTopLevel,

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

@ -6,8 +6,10 @@
#include "WorkerDebugger.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/MessageEvent.h"
#include "mozilla/dom/MessageEventBinding.h"
#include "mozilla/dom/WindowContext.h"
#include "mozilla/AbstractThread.h"
#include "mozilla/PerformanceUtils.h"
#include "nsProxyRelease.h"
@ -457,7 +459,7 @@ void WorkerDebugger::ReportErrorToDebuggerOnMainThread(
RefPtr<PerformanceInfoPromise> WorkerDebugger::ReportPerformanceInfo() {
AssertIsOnMainThread();
nsCOMPtr<nsPIDOMWindowOuter> top;
RefPtr<BrowsingContext> top;
RefPtr<WorkerDebugger> self = this;
#if defined(XP_WIN)
@ -476,12 +478,12 @@ RefPtr<PerformanceInfoPromise> WorkerDebugger::ReportPerformanceInfo() {
}
nsPIDOMWindowInner* win = wp->GetWindow();
if (win) {
nsPIDOMWindowOuter* outer = win->GetOuterWindow();
if (outer) {
top = outer->GetInProcessTop();
BrowsingContext* context = win->GetBrowsingContext();
if (context) {
top = context->Top();
if (top) {
windowID = top->WindowID();
isTopLevel = outer->GetBrowsingContext()->IsTop();
windowID = top->GetCurrentWindowContext()->OuterWindowId();
isTopLevel = context->IsTop();
}
}
}

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

@ -82,37 +82,73 @@ void AddWindowTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
aSizes->mOther += sizes.mOther;
}
nsresult GetTabSizes(nsGlobalWindowOuter* aWindow, nsTabSizes* aSizes) {
// Add the window (and inner window) sizes. Might be cached.
AddWindowTabSizes(aWindow, aSizes);
BrowsingContext* bc = aWindow->GetBrowsingContext();
if (!bc) {
nsresult GetTabSizes(BrowsingContext* aContext, nsTabSizes* aSizes) {
if (!aContext) {
return NS_OK;
}
// Add the window (and inner window) sizes. Might be cached.
nsGlobalWindowOuter* window =
nsGlobalWindowOuter::Cast(aContext->GetDOMWindow());
if (window) {
AddWindowTabSizes(window, aSizes);
}
// Measure this window's descendents.
for (const auto& frame : bc->Children()) {
if (auto* childWin = nsGlobalWindowOuter::Cast(frame->GetDOMWindow())) {
MOZ_TRY(GetTabSizes(childWin, aSizes));
}
for (const auto& child : aContext->Children()) {
MOZ_TRY(GetTabSizes(child, aSizes));
}
return NS_OK;
}
RefPtr<MemoryPromise> CollectMemoryInfo(
const nsCOMPtr<nsPIDOMWindowOuter>& aWindow,
const RefPtr<DocGroup>& aDocGroup,
const RefPtr<AbstractThread>& aEventTarget) {
// Getting Dom sizes. -- XXX should we reimplement GetTabSizes to async here ?
nsGlobalWindowOuter* window = nsGlobalWindowOuter::Cast(aWindow);
nsTabSizes sizes;
nsresult rv = GetTabSizes(window, &sizes);
for (const auto& document : *aDocGroup) {
nsGlobalWindowOuter* window =
document ? nsGlobalWindowOuter::Cast(document->GetWindow()) : nullptr;
if (window) {
AddWindowTabSizes(window, &sizes);
}
}
BrowsingContextGroup* group = aDocGroup->GetBrowsingContextGroup();
// Getting GC Heap Usage
uint64_t GCHeapUsage = 0;
JSObject* object = group->GetWrapper();
if (object != nullptr) {
GCHeapUsage = js::GetGCHeapUsageForObjectZone(object);
}
// Getting Media sizes.
return GetMediaMemorySizes()->Then(
aEventTarget, __func__,
[GCHeapUsage, sizes](const MediaMemoryInfo& media) {
return MemoryPromise::CreateAndResolve(
PerformanceMemoryInfo(media, sizes.mDom, sizes.mStyle, sizes.mOther,
GCHeapUsage),
__func__);
},
[](const nsresult rv) {
return MemoryPromise::CreateAndReject(rv, __func__);
});
}
RefPtr<MemoryPromise> CollectMemoryInfo(
const RefPtr<BrowsingContext>& aContext,
const RefPtr<AbstractThread>& aEventTarget) {
// Getting Dom sizes. -- XXX should we reimplement GetTabSizes to async here ?
nsTabSizes sizes;
nsresult rv = GetTabSizes(aContext, &sizes);
if (NS_FAILED(rv)) {
return MemoryPromise::CreateAndReject(rv, __func__);
}
// Getting GC Heap Usage
JSObject* obj = window->GetGlobalJSObject();
JSObject* obj = aContext->GetWrapper();
uint64_t GCHeapUsage = 0;
if (obj != nullptr) {
GCHeapUsage = js::GetGCHeapUsageForObjectZone(obj);

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

@ -11,7 +11,10 @@
class nsPIDOMWindowOuter;
namespace mozilla {
namespace dom {
class BrowsingContext;
class DocGroup;
} // namespace dom
/**
* Returns an array of promises to asynchronously collect all performance
* info in the current process.
@ -22,7 +25,11 @@ nsTArray<RefPtr<PerformanceInfoPromise>> CollectPerformanceInfo();
* Asynchronously collects memory info for a given window
*/
RefPtr<MemoryPromise> CollectMemoryInfo(
const nsCOMPtr<nsPIDOMWindowOuter>& aWindow,
const RefPtr<dom::BrowsingContext>& aContext,
const RefPtr<AbstractThread>& aEventTarget);
RefPtr<MemoryPromise> CollectMemoryInfo(
const RefPtr<dom::DocGroup>& aDocGroup,
const RefPtr<AbstractThread>& aEventTarget);
} // namespace mozilla