From 3cdb74e9bd1e44776adb7fefdede19ed85b028f5 Mon Sep 17 00:00:00 2001 From: "trop[bot]" <37223003+trop[bot]@users.noreply.github.com> Date: Mon, 30 Aug 2021 12:43:45 -0400 Subject: [PATCH] feat: add webContents.fromDevToolsTargetId() (#30732) * feat: add webContents.fromDevToolsTargetId() * refactor: avoid using FromOrCreate Co-authored-by: samuelmaddock --- docs/api/web-contents.md | 20 +++++++++++++++++++ lib/browser/api/web-contents.ts | 4 ++++ .../browser/api/electron_api_web_contents.cc | 11 ++++++++++ spec-main/api-web-contents-spec.ts | 18 +++++++++++++++++ 4 files changed, 53 insertions(+) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 98188c837e098..f501b38d704ed 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -45,6 +45,26 @@ returns `null`. Returns `WebContents` | undefined - A WebContents instance with the given ID, or `undefined` if there is no WebContents associated with the given ID. +### `webContents.fromDevToolsTargetId(targetId)` + +* `targetId` String - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance. + +Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or +`undefined` if there is no WebContents associated with the given TargetID. + +When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/), +it can be useful to lookup a WebContents instance based on its assigned TargetID. + +```js +async function lookupTargetId (browserWindow) { + const wc = browserWindow.webContents + await wc.debugger.attach('1.3') + const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo') + const { targetId } = targetInfo + const targetWebContents = await webContents.fromDevToolsTargetId(targetId) +} +``` + ## Class: WebContents > Render and control the contents of a BrowserWindow instance. diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts index 245b1a3b27579..a553df6a8d2bb 100644 --- a/lib/browser/api/web-contents.ts +++ b/lib/browser/api/web-contents.ts @@ -769,6 +769,10 @@ export function fromId (id: string) { return binding.fromId(id); } +export function fromDevToolsTargetId (targetId: string) { + return binding.fromDevToolsTargetId(targetId); +} + export function getFocusedWebContents () { let focused = null; for (const contents of binding.getAllWebContents()) { diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 8421015dd11fc..b69fa9aebecc5 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -3909,6 +3909,16 @@ gin::Handle WebContentsFromID(v8::Isolate* isolate, int32_t id) { : gin::Handle(); } +gin::Handle WebContentsFromDevToolsTargetID( + v8::Isolate* isolate, + std::string target_id) { + auto agent_host = content::DevToolsAgentHost::GetForId(target_id); + WebContents* contents = + agent_host ? WebContents::From(agent_host->GetWebContents()) : nullptr; + return contents ? gin::CreateHandle(isolate, contents) + : gin::Handle(); +} + std::vector> GetAllWebContentsAsV8( v8::Isolate* isolate) { std::vector> list; @@ -3927,6 +3937,7 @@ void Initialize(v8::Local exports, gin_helper::Dictionary dict(isolate, exports); dict.Set("WebContents", WebContents::GetConstructor(context)); dict.SetMethod("fromId", &WebContentsFromID); + dict.SetMethod("fromDevToolsTargetId", &WebContentsFromDevToolsTargetID); dict.SetMethod("getAllWebContents", &GetAllWebContentsAsV8); } diff --git a/spec-main/api-web-contents-spec.ts b/spec-main/api-web-contents-spec.ts index 9490b709856f9..395265dd5ce71 100644 --- a/spec-main/api-web-contents-spec.ts +++ b/spec-main/api-web-contents-spec.ts @@ -47,6 +47,24 @@ describe('webContents module', () => { }); }); + describe('fromDevToolsTargetId()', () => { + it('returns WebContents for attached DevTools target', async () => { + const w = new BrowserWindow({ show: false }); + await w.loadURL('about:blank'); + try { + await w.webContents.debugger.attach('1.3'); + const { targetInfo } = await w.webContents.debugger.sendCommand('Target.getTargetInfo'); + expect(webContents.fromDevToolsTargetId(targetInfo.targetId)).to.equal(w.webContents); + } finally { + await w.webContents.debugger.detach(); + } + }); + + it('returns undefined for an unknown id', () => { + expect(webContents.fromDevToolsTargetId('nope')).to.be.undefined(); + }); + }); + describe('will-prevent-unload event', function () { afterEach(closeAllWindows); it('does not emit if beforeunload returns undefined in a BrowserWindow', async () => {