mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Bug 1819767 - [devtools] Expose ChromeUtils.isDevToolsOpened to know if DevTools are debugging something in the current process. r=smaug,devtools-reviewers,jdescottes
This doesn't help know what particular resource DevTools is currently inspecting, but at least it helps know if it debugs something: * one or many BrowsingContext(s) for regular DevTools (you can use BrowsingContext.watchedByDevTools instead) * the whole process for the Browser Console/Toolbox Differential Revision: https://phabricator.services.mozilla.com/D173295
This commit is contained in:
parent
d577cf10cc
commit
4f2561f730
@ -394,6 +394,12 @@ var DevToolsServer = {
|
||||
connID = "server" + loader.id + ".conn" + this._nextConnID++ + ".";
|
||||
}
|
||||
|
||||
// Notify the platform code that DevTools is running in the current process
|
||||
// when we are wiring the very first connection
|
||||
if (!this.hasConnection()) {
|
||||
ChromeUtils.notifyDevToolsOpened();
|
||||
}
|
||||
|
||||
const conn = new DevToolsServerConnection(
|
||||
connID,
|
||||
transport,
|
||||
@ -425,13 +431,20 @@ var DevToolsServer = {
|
||||
delete this._connections[connection.prefix];
|
||||
this.emit("connectionchange", "closed", connection);
|
||||
|
||||
const hasConnection = this.hasConnection();
|
||||
|
||||
// Notify the platform code that we stopped running DevTools code in the current process
|
||||
if (!hasConnection) {
|
||||
ChromeUtils.notifyDevToolsClosed();
|
||||
}
|
||||
|
||||
// If keepAlive isn't explicitely set to true, destroy the server once its
|
||||
// last connection closes. Multiple JSWindowActor may use the same DevToolsServer
|
||||
// and in this case, let the server destroy itself once the last connection closes.
|
||||
// Otherwise we set keepAlive to true when starting a listening server, receiving
|
||||
// client connections. Typically when running server on phones, or on desktop
|
||||
// via `--start-debugger-server`.
|
||||
if (this.hasConnection() || this.keepAlive) {
|
||||
if (hasConnection || this.keepAlive) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,11 @@ async function testDevToolsServerInitialized() {
|
||||
false,
|
||||
"By default, the DevToolsServer isn't initialized not in content process"
|
||||
);
|
||||
await assertDevToolsOpened(
|
||||
tab,
|
||||
false,
|
||||
"By default, the DevTools are reported as closed"
|
||||
);
|
||||
|
||||
const commands = await CommandsFactory.forTab(tab);
|
||||
|
||||
@ -40,6 +45,11 @@ async function testDevToolsServerInitialized() {
|
||||
false,
|
||||
"Creating the commands isn't enough to initialize the DevToolsServer in content process"
|
||||
);
|
||||
await assertDevToolsOpened(
|
||||
tab,
|
||||
false,
|
||||
"DevTools are still reported as closed after having created the commands"
|
||||
);
|
||||
|
||||
await commands.targetCommand.startListening();
|
||||
|
||||
@ -48,6 +58,11 @@ async function testDevToolsServerInitialized() {
|
||||
true,
|
||||
"Initializing the TargetCommand will initialize the DevToolsServer in content process"
|
||||
);
|
||||
await assertDevToolsOpened(
|
||||
tab,
|
||||
true,
|
||||
"Initializing the TargetCommand will start reporting the DevTools as opened"
|
||||
);
|
||||
|
||||
await commands.destroy();
|
||||
|
||||
@ -61,6 +76,11 @@ async function testDevToolsServerInitialized() {
|
||||
false,
|
||||
"But destroying the commands ends up destroying the DevToolsServer in the content process"
|
||||
);
|
||||
await assertDevToolsOpened(
|
||||
tab,
|
||||
false,
|
||||
"Destroying the commands will report DevTools as being closed"
|
||||
);
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
DevToolsServer.destroy();
|
||||
@ -74,11 +94,13 @@ async function testDevToolsServerKeepAlive() {
|
||||
false,
|
||||
"Server not started in content process"
|
||||
);
|
||||
await assertDevToolsOpened(tab, false, "DevTools are reported as closed");
|
||||
|
||||
const commands = await CommandsFactory.forTab(tab);
|
||||
await commands.targetCommand.startListening();
|
||||
|
||||
await assertServerInitialized(tab, true, "Server started in content process");
|
||||
await assertDevToolsOpened(tab, true, "DevTools are reported as opened");
|
||||
|
||||
info("Set DevToolsServer.keepAlive to true in the content process");
|
||||
DevToolsServer.keepAlive = true;
|
||||
@ -92,6 +114,11 @@ async function testDevToolsServerKeepAlive() {
|
||||
true,
|
||||
"Server still running in content process"
|
||||
);
|
||||
await assertDevToolsOpened(
|
||||
tab,
|
||||
false,
|
||||
"DevTools are reported as close, even if the server is still running because there is no more client connected"
|
||||
);
|
||||
|
||||
ok(
|
||||
DevToolsServer.initialized,
|
||||
@ -113,6 +140,11 @@ async function testDevToolsServerKeepAlive() {
|
||||
false,
|
||||
"Server stopped in content process"
|
||||
);
|
||||
await assertDevToolsOpened(
|
||||
tab,
|
||||
false,
|
||||
"DevTools are reported as closed after destroying the second commands"
|
||||
);
|
||||
|
||||
ok(
|
||||
!DevToolsServer.initialized,
|
||||
@ -124,20 +156,27 @@ async function testDevToolsServerKeepAlive() {
|
||||
}
|
||||
|
||||
async function assertServerInitialized(tab, expected, message) {
|
||||
const isInitialized = await SpecialPowers.spawn(
|
||||
tab.linkedBrowser,
|
||||
[],
|
||||
function() {
|
||||
const { require } = ChromeUtils.importESModule(
|
||||
"resource://devtools/shared/loader/Loader.sys.mjs"
|
||||
);
|
||||
const {
|
||||
DevToolsServer,
|
||||
} = require("resource://devtools/server/devtools-server.js");
|
||||
return DevToolsServer.initialized;
|
||||
}
|
||||
);
|
||||
is(isInitialized, expected, message);
|
||||
await SpecialPowers.spawn(tab.linkedBrowser, [expected, message], function(
|
||||
_expected,
|
||||
_message
|
||||
) {
|
||||
const { require } = ChromeUtils.importESModule(
|
||||
"resource://devtools/shared/loader/Loader.sys.mjs"
|
||||
);
|
||||
const {
|
||||
DevToolsServer,
|
||||
} = require("resource://devtools/server/devtools-server.js");
|
||||
is(DevToolsServer.initialized, _expected, _message);
|
||||
});
|
||||
}
|
||||
|
||||
async function assertDevToolsOpened(tab, expected, message) {
|
||||
await SpecialPowers.spawn(tab.linkedBrowser, [expected, message], function(
|
||||
_expected,
|
||||
_message
|
||||
) {
|
||||
is(ChromeUtils.isDevToolsOpened(), _expected, _message);
|
||||
});
|
||||
}
|
||||
|
||||
async function setContentServerKeepAlive(tab, keepAlive, message) {
|
||||
|
@ -1858,4 +1858,28 @@ void ChromeUtils::GetAllPossibleUtilityActorNames(GlobalObject& aGlobal,
|
||||
aNames.AppendElement(WebIDLUtilityActorNameValues::GetString(idlName));
|
||||
}
|
||||
}
|
||||
|
||||
std::atomic<uint32_t> ChromeUtils::sDevToolsOpenedCount = 0;
|
||||
|
||||
/* static */
|
||||
bool ChromeUtils::IsDevToolsOpened() {
|
||||
return ChromeUtils::sDevToolsOpenedCount > 0;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool ChromeUtils::IsDevToolsOpened(GlobalObject& aGlobal) {
|
||||
return ChromeUtils::IsDevToolsOpened();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void ChromeUtils::NotifyDevToolsOpened(GlobalObject& aGlobal) {
|
||||
ChromeUtils::sDevToolsOpenedCount++;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void ChromeUtils::NotifyDevToolsClosed(GlobalObject& aGlobal) {
|
||||
MOZ_ASSERT(ChromeUtils::sDevToolsOpenedCount >= 1);
|
||||
ChromeUtils::sDevToolsOpenedCount--;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
@ -65,6 +65,11 @@ class ChromeUtils {
|
||||
static already_AddRefed<devtools::HeapSnapshot> ReadHeapSnapshot(
|
||||
GlobalObject& global, const nsAString& filePath, ErrorResult& rv);
|
||||
|
||||
static bool IsDevToolsOpened();
|
||||
static bool IsDevToolsOpened(GlobalObject& aGlobal);
|
||||
static void NotifyDevToolsOpened(GlobalObject& aGlobal);
|
||||
static void NotifyDevToolsClosed(GlobalObject& aGlobal);
|
||||
|
||||
static void NondeterministicGetWeakMapKeys(
|
||||
GlobalObject& aGlobal, JS::Handle<JS::Value> aMap,
|
||||
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
|
||||
@ -296,6 +301,10 @@ class ChromeUtils {
|
||||
|
||||
static void GetAllPossibleUtilityActorNames(GlobalObject& aGlobal,
|
||||
nsTArray<nsCString>& aNames);
|
||||
|
||||
private:
|
||||
// Number of DevTools session debugging the current process
|
||||
static std::atomic<uint32_t> sDevToolsOpenedCount;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -115,6 +115,26 @@ namespace ChromeUtils {
|
||||
[Throws, NewObject]
|
||||
HeapSnapshot readHeapSnapshot(DOMString filePath);
|
||||
|
||||
/**
|
||||
* Efficient way to know if DevTools are active in the current process.
|
||||
*
|
||||
* This doesn't help know what particular context is being debugged,
|
||||
* but can help strip off code entirely when DevTools aren't used at all.
|
||||
*
|
||||
* BrowsingContext.isWatchedByDevTools is a more precise way to know
|
||||
* when one precise tab is being debugged.
|
||||
*/
|
||||
boolean isDevToolsOpened();
|
||||
|
||||
/**
|
||||
* API exposed to DevTools JS code in order to know when devtools are being active in the current process.
|
||||
*
|
||||
* This API counts the number of calls to these methods, allowing to track many DevTools instances.
|
||||
*/
|
||||
undefined notifyDevToolsOpened();
|
||||
undefined notifyDevToolsClosed();
|
||||
|
||||
|
||||
/**
|
||||
* Return the keys in a weak map. This operation is
|
||||
* non-deterministic because it is affected by the scheduling of the
|
||||
|
Loading…
Reference in New Issue
Block a user