Skip to content

Commit 7a77619

Browse files
authored
feat: expose sessionId in debugger module (electron#24399)
1 parent 93a9512 commit 7a77619

File tree

5 files changed

+66
-3
lines changed

5 files changed

+66
-3
lines changed

docs/api/debugger.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ Returns:
5252
* `method` String - Method name.
5353
* `params` any - Event parameters defined by the 'parameters'
5454
attribute in the remote debugging protocol.
55+
* `sessionId` String - Unique identifier of attached debugging session,
56+
will match the value sent from `debugger.sendCommand`.
5557

5658
Emitted whenever the debugging target issues an instrumentation event.
5759

@@ -74,11 +76,16 @@ Returns `Boolean` - Whether a debugger is attached to the `webContents`.
7476

7577
Detaches the debugger from the `webContents`.
7678

77-
#### `debugger.sendCommand(method[, commandParams])`
79+
#### `debugger.sendCommand(method[, commandParams, sessionId])`
7880

7981
* `method` String - Method name, should be one of the methods defined by the
8082
[remote debugging protocol][rdp].
8183
* `commandParams` any (optional) - JSON object with request parameters.
84+
* `sessionId` String (optional) - send command to the target with associated
85+
debugging session id. The initial value can be obtained by sending
86+
[Target.attachToTarget][attachToTarget] message.
87+
88+
[attachToTarget]: https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-attachToTarget
8289

8390
Returns `Promise<any>` - A promise that resolves with the response defined by
8491
the 'returns' attribute of the command description in the remote debugging protocol

shell/browser/api/electron_api_debugger.cc

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
5454
std::string method;
5555
if (!dict->GetString("method", &method))
5656
return;
57+
std::string session_id;
58+
dict->GetString("sessionId", &session_id);
5759
base::DictionaryValue* params_value = nullptr;
5860
base::DictionaryValue params;
5961
if (dict->GetDictionary("params", &params_value))
6062
params.Swap(params_value);
61-
Emit("message", method, params);
63+
Emit("message", method, params, session_id);
6264
} else {
6365
auto it = pending_requests_.find(id);
6466
if (it == pending_requests_.end())
@@ -146,14 +148,25 @@ v8::Local<v8::Promise> Debugger::SendCommand(mate::Arguments* args) {
146148
base::DictionaryValue command_params;
147149
args->GetNext(&command_params);
148150

151+
std::string session_id;
152+
if (args->GetNext(&session_id) && session_id.empty()) {
153+
promise.RejectWithErrorMessage("Empty session id is not allowed");
154+
return handle;
155+
}
156+
149157
base::DictionaryValue request;
150158
int request_id = ++previous_request_id_;
151159
pending_requests_.emplace(request_id, std::move(promise));
152160
request.SetInteger("id", request_id);
153161
request.SetString("method", method);
154-
if (!command_params.empty())
162+
if (!command_params.empty()) {
155163
request.Set("params",
156164
base::Value::ToUniquePtrValue(command_params.Clone()));
165+
}
166+
167+
if (!session_id.empty()) {
168+
request.SetString("sessionId", session_id);
169+
}
157170

158171
std::string json_args;
159172
base::JSONWriter::Write(request, &json_args);

spec-main/api-debugger-spec.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,5 +225,39 @@ describe('debugger module', () => {
225225
w.loadURL(`http://127.0.0.1:${(server.address() as AddressInfo).port}`)
226226
})
227227
})
228+
229+
it('uses empty sessionId by default', async () => {
230+
w.webContents.loadURL('about:blank')
231+
w.webContents.debugger.attach()
232+
const onMessage = emittedOnce(w.webContents.debugger, 'message')
233+
await w.webContents.debugger.sendCommand('Target.setDiscoverTargets', { discover: true })
234+
const [, method, params, sessionId] = await onMessage
235+
expect(method).to.equal('Target.targetCreated')
236+
expect(params.targetInfo.targetId).to.not.be.empty()
237+
expect(sessionId).to.be.empty()
238+
w.webContents.debugger.detach()
239+
})
240+
241+
it('creates unique session id for each target', (done) => {
242+
w.webContents.loadFile(path.join(__dirname, 'fixtures', 'sub-frames', 'debug-frames.html'))
243+
w.webContents.debugger.attach()
244+
let session: String
245+
246+
w.webContents.debugger.on('message', (event, ...args) => {
247+
const [method, params, sessionId] = args
248+
if (method === 'Target.targetCreated') {
249+
w.webContents.debugger.sendCommand('Target.attachToTarget', { targetId: params.targetInfo.targetId, flatten: true }).then(result => {
250+
session = result.sessionId
251+
w.webContents.debugger.sendCommand('Debugger.enable', {}, result.sessionId)
252+
})
253+
}
254+
if (method === 'Debugger.scriptParsed') {
255+
expect(sessionId).to.equal(session)
256+
w.webContents.debugger.detach()
257+
done()
258+
}
259+
})
260+
w.webContents.debugger.sendCommand('Target.setDiscoverTargets', { discover: true })
261+
})
228262
})
229263
})
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<body>
4+
This is a frame, is has one child
5+
<iframe src="./frame.html"></iframe>
6+
</body>
7+
<script src="./test.js"></script>
8+
</html>

spec-main/fixtures/sub-frames/test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
console.log('hello');

0 commit comments

Comments
 (0)