Bug 1652785 - Extract title, uri, window id for content processes;r=froydnj

Differential Revision: https://phabricator.services.mozilla.com/D87972
This commit is contained in:
David Teller 2020-09-07 10:26:30 +00:00
parent 74240111ef
commit 7ffc3a3d91
7 changed files with 156 additions and 10 deletions

View File

@ -31,11 +31,14 @@
#include "mozilla/dom/JSActorService.h"
#include "mozilla/dom/MediaMetadata.h"
#include "mozilla/dom/MediaSessionBinding.h"
#include "mozilla/dom/PBrowserParent.h"
#include "mozilla/dom/PWindowGlobalParent.h"
#include "mozilla/dom/Performance.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/ReportingHeader.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
#include "mozilla/dom/WindowGlobalParent.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
@ -810,7 +813,8 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
requests.EmplaceBack(
/* aPid = */ base::GetCurrentProcId(),
/* aProcessType = */ ProcType::Browser,
/* aOrigin = */ ""_ns);
/* aOrigin = */ ""_ns,
/* aWindowInfo = */ nsTArray<WindowInfo>());
mozilla::ipc::GeckoChildProcessHost::GetAll(
[&requests,
@ -825,6 +829,8 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
base::ProcessId childPid = base::GetProcId(handle);
int32_t childId = 0;
mozilla::ProcType type = mozilla::ProcType::Unknown;
nsTArray<WindowInfo> windows;
switch (aGeckoProcess->GetProcessType()) {
case GeckoProcessType::GeckoProcessType_Content: {
ContentParent* contentParent = nullptr;
@ -841,6 +847,35 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
// FIXME: When can this happen?
return;
}
// Attach DOM window information to the process.
for (const auto& browserParentWrapper :
contentParent->ManagedPBrowserParent()) {
for (const auto& windowGlobalParentWrapper :
browserParentWrapper.GetKey()
->ManagedPWindowGlobalParent()) {
// WindowGlobalParent is the only immediate subclass of
// PWindowGlobalParent.
auto* windowGlobalParent = static_cast<WindowGlobalParent*>(
windowGlobalParentWrapper.GetKey());
nsString documentTitle;
windowGlobalParent->GetDocumentTitle(documentTitle);
WindowInfo* window = windows.EmplaceBack(
fallible,
/* aOuterWindowId = */ windowGlobalParent->OuterWindowId(),
/* aDocumentURI = */ windowGlobalParent->GetDocumentURI(),
/* aDocumentTitle = */ std::move(documentTitle),
/* aIsProcessRoot = */ windowGlobalParent->IsProcessRoot(),
/* aIsInProcess = */ windowGlobalParent->IsInProcess());
if (!window) {
// That's bad sign, but we don't have a good place to return
// an OOM error from.
return;
}
}
}
// Converting the remoteType into a ProcType.
// Ideally, the remoteType should be strongly typed
// upstream, this would make the conversion less brittle.
@ -922,6 +957,7 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
/* aPid = */ childPid,
/* aProcessType = */ type,
/* aOrigin = */ origin,
/* aWindowInfo = */ std::move(windows),
/* aChild = */ childId
#ifdef XP_MACOSX
,
@ -976,6 +1012,19 @@ already_AddRefed<Promise> ChromeUtils::RequestProcInfo(GlobalObject& aGlobal,
childInfo->mChildID = sysProcInfo.childId;
childInfo->mOrigin = sysProcInfo.origin;
childInfo->mType = ProcTypeToWebIDL(sysProcInfo.type);
for (const auto& source : sysProcInfo.windows) {
auto* dest = childInfo->mWindows.AppendElement(fallible);
if (!dest) {
domPromise->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
return;
}
dest->mOuterWindowId = source.outerWindowId;
dest->mDocumentURI = source.documentURI;
dest->mDocumentTitle = source.documentTitle;
dest->mIsProcessRoot = source.isProcessRoot;
dest->mIsInProcess = source.isInProcess;
}
}
}

View File

@ -530,6 +530,24 @@ dictionary ThreadInfoDictionary {
unsigned long long cpuKernel = 0;
};
dictionary WindowInfoDictionary {
// Window ID, as known to the parent process.
unsigned long long outerWindowId = 0;
// URI of the document loaded in the window.
URI? documentURI = null;
// Title of the document loaded in the window.
// Commonly empty for subframes.
DOMString documentTitle = "";
// `true` if this window is the root for the process.
boolean isProcessRoot = false;
// `true` if this is loaded in the same process as the parent, `false` otherwise.
boolean isInProcess = false;
};
/**
* Information on a child process.
*
@ -579,6 +597,9 @@ dictionary ChildProcInfoDictionary {
// Type of this child process.
WebIDLProcType type = "web";
// The windows implemented by this process.
sequence<WindowInfoDictionary> windows = [];
};
/**

View File

@ -61,6 +61,38 @@ struct ThreadInfo {
uint64_t cpuKernel = 0;
};
// Info on a DOM window.
struct WindowInfo {
explicit WindowInfo()
: outerWindowId(0),
documentURI(nullptr),
documentTitle(u""_ns),
isProcessRoot(false),
isInProcess(false) {}
WindowInfo(uint64_t aOuterWindowId, nsIURI* aDocumentURI,
nsAString&& aDocumentTitle, bool aIsProcessRoot, bool aIsInProcess)
: outerWindowId(aOuterWindowId),
documentURI(aDocumentURI),
documentTitle(std::move(aDocumentTitle)),
isProcessRoot(aIsProcessRoot),
isInProcess(aIsInProcess) {}
// Internal window id.
const uint64_t outerWindowId;
// URI of the document.
const nsCOMPtr<nsIURI> documentURI;
// Title of the document.
const nsString documentTitle;
// True if this is the toplevel window of the process.
// Note that this may be an iframe from another process.
const bool isProcessRoot;
const bool isInProcess;
};
struct ProcInfo {
// Process Id
base::ProcessId pid = 0;
@ -82,6 +114,8 @@ struct ProcInfo {
uint64_t cpuKernel = 0;
// Threads owned by this process.
CopyableTArray<ThreadInfo> threads;
// DOM windows represented by this process.
CopyableTArray<WindowInfo> windows;
};
typedef MozPromise<mozilla::HashMap<base::ProcessId, ProcInfo>, nsresult, true>
@ -99,7 +133,8 @@ typedef MozPromise<mozilla::HashMap<base::ProcessId, ProcInfo>, nsresult, true>
*/
struct ProcInfoRequest {
ProcInfoRequest(base::ProcessId aPid, ProcType aProcessType,
const nsACString& aOrigin, uint32_t aChildId = 0
const nsACString& aOrigin, nsTArray<WindowInfo>&& aWindowInfo,
uint32_t aChildId = 0
#ifdef XP_MACOSX
,
mach_port_t aChildTask = 0
@ -108,6 +143,7 @@ struct ProcInfoRequest {
: pid(aPid),
processType(aProcessType),
origin(aOrigin),
windowInfo(std::move(aWindowInfo)),
childId(aChildId)
#ifdef XP_MACOSX
,
@ -118,6 +154,7 @@ struct ProcInfoRequest {
const base::ProcessId pid;
const ProcType processType;
const nsCString origin;
const nsTArray<WindowInfo> windowInfo;
// If the process is a child, its child id, otherwise `0`.
const int32_t childId;
#ifdef XP_MACOSX

View File

@ -45,6 +45,7 @@ RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
info.childId = request.childId;
info.type = request.processType;
info.origin = std::move(request.origin);
info.windows = std::move(request.windowInfo);
struct proc_bsdinfo proc;
if ((unsigned long)proc_pidinfo(request.pid, PROC_PIDTBSDINFO, 0, &proc,
PROC_PIDTBSDINFO_SIZE) < PROC_PIDTBSDINFO_SIZE) {

View File

@ -248,6 +248,7 @@ RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
info.childId = request.childId;
info.type = request.processType;
info.origin = request.origin;
info.windows = std::move(request.windowInfo);
// Let's look at the threads
nsCString taskPath;

View File

@ -16,7 +16,16 @@ const isFissionEnabled = Services.prefs.getBoolPref("fission.autostart");
const SAMPLE_SIZE = 10;
add_task(async function test_proc_info() {
waitForExplicitFinish();
console.log("YORIC", "Test starts");
// Open a few `about:home` tabs, they'll end up in `privilegedabout`.
let tabsAboutHome = [];
for (let i = 0; i < 5; ++i) {
let tab = BrowserTestUtils.addTab(gBrowser, "about:home");
tabsAboutHome.push(tab);
gBrowser.selectedTab = tab;
await BrowserTestUtils.browserLoaded(tab.linkedBrowser);
}
await BrowserTestUtils.withNewTab(
{ gBrowser, url: DUMMY_URL },
async function(browser) {
@ -98,16 +107,15 @@ add_task(async function test_proc_info() {
}
// We only check other properties on the `privilegedabout` subprocess, which
// as of this writing is hosting the page we test, so should be active and
// available. If we ever move `about:processes` to another process type, we'll
// need to update this test.
var hasSocketProcess = false;
// as of this writing is always active and available.
var hasPrivilegedAbout = false;
var numberOfAboutTabs = 0;
for (i = 0; i < parentProc.children.length; i++) {
let childProc = parentProc.children[i];
if (childProc.type != "privilegedabout") {
continue;
}
hasSocketProcess = true;
hasPrivilegedAbout = true;
Assert.ok(
childProc.residentUniqueSize > 0,
"Resident-unique-size was set"
@ -117,17 +125,45 @@ add_task(async function test_proc_info() {
`Resident-unique-size should be bounded by resident-set-size ${childProc.residentUniqueSize} <= ${childProc.residentSetSize}`
);
// Once we have found the socket process, bailout.
for (var win of childProc.windows) {
if (win.documentURI.spec != "about:home") {
// We're only interested in about:home for this test.
continue;
}
numberOfAboutTabs++;
Assert.ok(
win.outerWindowId > 0,
`ContentParentID should be > 0 ${win.outerWindowId}`
);
if (win.documentTitle) {
// Unfortunately, we sometimes reach this point before the document is fully loaded, so
// `win.documentTitle` may still be empty.
Assert.equal(win.documentTitle, "New Tab");
}
}
Assert.ok(
numberOfAboutTabs >= tabsAboutHome.length,
"We have found at least as many about:home tabs as we opened"
);
// Once we have verified the privileged about process, bailout.
break;
}
Assert.ok(hasSocketProcess, "We have found the socket process");
Assert.ok(
hasPrivilegedAbout,
"We have found the privileged about process"
);
}
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1529023
if (!MAC) {
Assert.greater(cpuThreads, 0, "Got some cpu time in the threads");
}
Assert.greater(cpuUser, 0, "Got some cpu time");
for (let tab of tabsAboutHome) {
BrowserTestUtils.removeTab(tab);
}
}
);
});

View File

@ -85,6 +85,7 @@ RefPtr<ProcInfoPromise> GetProcInfo(nsTArray<ProcInfoRequest>&& aRequests) {
info.childId = request.childId;
info.type = request.processType;
info.origin = request.origin;
info.windows = std::move(request.windowInfo);
info.filename.Assign(filename);
info.cpuKernel = ToNanoSeconds(kernelTime);
info.cpuUser = ToNanoSeconds(userTime);