Browse Source

feat: expose sessionId in debugger module (#24397)

Co-authored-by: deepak1556 <[email protected]>
trop[bot] 4 years ago
parent
commit
c32c69604a

+ 8 - 1
docs/api/debugger.md

@@ -52,6 +52,8 @@ Returns:
 * `method` String - Method name.
 * `params` any - Event parameters defined by the 'parameters'
    attribute in the remote debugging protocol.
+* `sessionId` String - Unique identifier of attached debugging session,
+   will match the value sent from `debugger.sendCommand`.
 
 Emitted whenever the debugging target issues an instrumentation event.
 
@@ -74,11 +76,16 @@ Returns `Boolean` - Whether a debugger is attached to the `webContents`.
 
 Detaches the debugger from the `webContents`.
 
-#### `debugger.sendCommand(method[, commandParams])`
+#### `debugger.sendCommand(method[, commandParams, sessionId])`
 
 * `method` String - Method name, should be one of the methods defined by the
    [remote debugging protocol][rdp].
 * `commandParams` any (optional) - JSON object with request parameters.
+* `sessionId` String (optional) - send command to the target with associated
+   debugging session id. The initial value can be obtained by sending
+   [Target.attachToTarget][attachToTarget] message.
+
+[attachToTarget]: https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-attachToTarget
 
 Returns `Promise<any>` - A promise that resolves with the response defined by
 the 'returns' attribute of the command description in the remote debugging protocol

+ 15 - 2
shell/browser/api/electron_api_debugger.cc

@@ -60,11 +60,13 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
     std::string method;
     if (!dict->GetString("method", &method))
       return;
+    std::string session_id;
+    dict->GetString("sessionId", &session_id);
     base::DictionaryValue* params_value = nullptr;
     base::DictionaryValue params;
     if (dict->GetDictionary("params", &params_value))
       params.Swap(params_value);
-    Emit("message", method, params);
+    Emit("message", method, params, session_id);
   } else {
     auto it = pending_requests_.find(id);
     if (it == pending_requests_.end())
@@ -152,14 +154,25 @@ v8::Local<v8::Promise> Debugger::SendCommand(gin::Arguments* args) {
   base::DictionaryValue command_params;
   args->GetNext(&command_params);
 
+  std::string session_id;
+  if (args->GetNext(&session_id) && session_id.empty()) {
+    promise.RejectWithErrorMessage("Empty session id is not allowed");
+    return handle;
+  }
+
   base::DictionaryValue request;
   int request_id = ++previous_request_id_;
   pending_requests_.emplace(request_id, std::move(promise));
   request.SetInteger("id", request_id);
   request.SetString("method", method);
-  if (!command_params.empty())
+  if (!command_params.empty()) {
     request.Set("params",
                 base::Value::ToUniquePtrValue(command_params.Clone()));
+  }
+
+  if (!session_id.empty()) {
+    request.SetString("sessionId", session_id);
+  }
 
   std::string json_args;
   base::JSONWriter::Write(request, &json_args);

+ 34 - 0
spec-main/api-debugger-spec.ts

@@ -193,5 +193,39 @@ describe('debugger module', () => {
         w.loadURL(`http://127.0.0.1:${(server.address() as AddressInfo).port}`);
       });
     });
+
+    it('uses empty sessionId by default', async () => {
+      w.webContents.loadURL('about:blank');
+      w.webContents.debugger.attach();
+      const onMessage = emittedOnce(w.webContents.debugger, 'message');
+      await w.webContents.debugger.sendCommand('Target.setDiscoverTargets', { discover: true });
+      const [, method, params, sessionId] = await onMessage;
+      expect(method).to.equal('Target.targetCreated');
+      expect(params.targetInfo.targetId).to.not.be.empty();
+      expect(sessionId).to.be.empty();
+      w.webContents.debugger.detach();
+    });
+
+    it('creates unique session id for each target', (done) => {
+      w.webContents.loadFile(path.join(__dirname, 'fixtures', 'sub-frames', 'debug-frames.html'));
+      w.webContents.debugger.attach();
+      let session: String;
+
+      w.webContents.debugger.on('message', (event, ...args) => {
+        const [method, params, sessionId] = args;
+        if (method === 'Target.targetCreated') {
+          w.webContents.debugger.sendCommand('Target.attachToTarget', { targetId: params.targetInfo.targetId, flatten: true }).then(result => {
+            session = result.sessionId;
+            w.webContents.debugger.sendCommand('Debugger.enable', {}, result.sessionId);
+          });
+        }
+        if (method === 'Debugger.scriptParsed') {
+          expect(sessionId).to.equal(session);
+          w.webContents.debugger.detach();
+          done();
+        }
+      });
+      w.webContents.debugger.sendCommand('Target.setDiscoverTargets', { discover: true });
+    });
   });
 });

+ 8 - 0
spec-main/fixtures/sub-frames/debug-frames.html

@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html lang="en">
+<body>
+  This is a frame, is has one child
+  <iframe src="./frame.html"></iframe>
+</body>
+<script src="./test.js"></script>
+</html>

+ 1 - 0
spec-main/fixtures/sub-frames/test.js

@@ -0,0 +1 @@
+console.log('hello');