Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow inspection of specific shared workers #20389

Merged
merged 1 commit into from Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/api/structures/shared-worker-info.md
@@ -0,0 +1,4 @@
# SharedWorkerInfo Object

* `id` String - The unique id of the shared worker.
* `url` String - The url of the shared worker.
10 changes: 10 additions & 0 deletions docs/api/web-contents.md
Expand Up @@ -1461,6 +1461,16 @@ Starts inspecting element at position (`x`, `y`).

Opens the developer tools for the shared worker context.

#### `contents.inspectSharedWorkerById(workerId)`

* `workerId` String

Inspects the shared worker based on its ID.

#### `contents.getAllSharedWorkers()`

Returns [`SharedWorkerInfo[]`](structures/shared-worker-info.md) - Information about all Shared Workers.

#### `contents.inspectServiceWorker()`

Opens the developer tools for the service worker context.
Expand Down
1 change: 1 addition & 0 deletions filenames.auto.gni
Expand Up @@ -110,6 +110,7 @@ auto_filenames = {
"docs/api/structures/remove-password.md",
"docs/api/structures/scrubber-item.md",
"docs/api/structures/segmented-control-segment.md",
"docs/api/structures/shared-worker-info.md",
"docs/api/structures/shortcut-details.md",
"docs/api/structures/size.md",
"docs/api/structures/stream-protocol-response.md",
Expand Down
54 changes: 54 additions & 0 deletions shell/browser/api/atom_api_web_contents.cc
Expand Up @@ -8,6 +8,7 @@
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/message_loop/message_loop_current.h"
#include "base/no_destructor.h"
Expand Down Expand Up @@ -298,6 +299,18 @@ struct Converter<electron::api::WebContents::Type> {
}
};

template <>
struct Converter<scoped_refptr<content::DevToolsAgentHost>> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const scoped_refptr<content::DevToolsAgentHost>& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("id", val->GetId());
dict.Set("url", val->GetURL().spec());
return dict.GetHandle();
}
};

} // namespace mate

namespace electron {
Expand Down Expand Up @@ -1569,6 +1582,44 @@ void WebContents::InspectElement(int x, int y) {
managed_web_contents()->InspectElement(x, y);
}

void WebContents::InspectSharedWorkerById(const std::string& workerId) {
if (type_ == Type::REMOTE)
return;

if (!enable_devtools_)
return;

for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() ==
content::DevToolsAgentHost::kTypeSharedWorker) {
if (agent_host->GetId() == workerId) {
OpenDevTools(nullptr);
managed_web_contents()->AttachTo(agent_host);
break;
}
}
}
}

std::vector<scoped_refptr<content::DevToolsAgentHost>>
WebContents::GetAllSharedWorkers() {
std::vector<scoped_refptr<content::DevToolsAgentHost>> shared_workers;

if (type_ == Type::REMOTE)
return shared_workers;

if (!enable_devtools_)
return shared_workers;

for (const auto& agent_host : content::DevToolsAgentHost::GetOrCreateAll()) {
if (agent_host->GetType() ==
content::DevToolsAgentHost::kTypeSharedWorker) {
shared_workers.push_back(agent_host);
}
}
return shared_workers;
}

void WebContents::InspectSharedWorker() {
if (type_ == Type::REMOTE)
return;
Expand Down Expand Up @@ -2493,6 +2544,9 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
.SetMethod("inspectSharedWorker", &WebContents::InspectSharedWorker)
.SetMethod("inspectSharedWorkerById",
&WebContents::InspectSharedWorkerById)
.SetMethod("getAllSharedWorkers", &WebContents::GetAllSharedWorkers)
#if BUILDFLAG(ENABLE_PRINTING)
.SetMethod("_print", &WebContents::Print)
.SetMethod("_getPrinters", &WebContents::GetPrinterList)
Expand Down
3 changes: 3 additions & 0 deletions shell/browser/api/atom_api_web_contents.h
Expand Up @@ -13,6 +13,7 @@
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "content/common/cursors/webcursor.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
Expand Down Expand Up @@ -171,6 +172,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
void DisableDeviceEmulation();
void InspectElement(int x, int y);
void InspectSharedWorker();
void InspectSharedWorkerById(const std::string& workerId);
std::vector<scoped_refptr<content::DevToolsAgentHost>> GetAllSharedWorkers();
void InspectServiceWorker();
void SetIgnoreMenuShortcuts(bool ignore);
void SetAudioMuted(bool muted);
Expand Down
36 changes: 36 additions & 0 deletions spec-main/api-web-contents-spec.ts
Expand Up @@ -1479,4 +1479,40 @@ describe('webContents module', () => {
expect(val).to.equal('test value', 'value should eventually become the pasted value')
})
})

describe('Shared Workers', () => {
afterEach(closeAllWindows)

it('can get multiple shared workers', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } })

const ready = emittedOnce(ipcMain, 'ready')
w.loadFile(path.join(fixturesPath, 'api', 'shared-worker', 'shared-worker.html'))
await ready

const sharedWorkers = w.webContents.getAllSharedWorkers()

expect(sharedWorkers).to.have.lengthOf(2)
expect(sharedWorkers[0].url).to.contain('shared-worker')
expect(sharedWorkers[1].url).to.contain('shared-worker')
})

it('can inspect a specific shared worker', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } })

const ready = emittedOnce(ipcMain, 'ready')
w.loadFile(path.join(fixturesPath, 'api', 'shared-worker', 'shared-worker.html'))
await ready

const sharedWorkers = w.webContents.getAllSharedWorkers()

const devtoolsOpened = emittedOnce(w.webContents, 'devtools-opened')
w.webContents.inspectSharedWorkerById(sharedWorkers[0].id)
await devtoolsOpened

const devtoolsClosed = emittedOnce(w.webContents, 'devtools-closed')
w.webContents.closeDevTools()
await devtoolsClosed
})
})
})
25 changes: 25 additions & 0 deletions spec/fixtures/api/shared-worker/shared-worker.html
@@ -0,0 +1,25 @@
<html>
<body>
<script>
const { ipcRenderer } = require('electron')

const worker1 = new SharedWorker('./shared-worker1.js')
const worker2 = new SharedWorker('./shared-worker2.js')

worker1.port.start()
worker2.port.start()

const promise1 = new Promise(resolve => {
worker1.port.onmessage = resolve
})

const promise2 = new Promise(resolve => {
worker2.port.onmessage = resolve
})

Promise.all([promise1, promise2]).then(() => {
ipcRenderer.send('ready')
})
</script>
</body>
</html>
4 changes: 4 additions & 0 deletions spec/fixtures/api/shared-worker/shared-worker1.js
@@ -0,0 +1,4 @@
self.onconnect = function (e) {
const port = e.ports[0]
port.postMessage('ready')
}
4 changes: 4 additions & 0 deletions spec/fixtures/api/shared-worker/shared-worker2.js
@@ -0,0 +1,4 @@
self.onconnect = function (e) {
const port = e.ports[0]
port.postMessage('ready')
}