зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
74240111ef
Коммит
7ffc3a3d91
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = [];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче