Merge pull request #958 from agracio/apis

Additional APIs for WebContents
This commit is contained in:
Florian Rappl
2025-12-05 09:10:11 +01:00
committed by GitHub
6 changed files with 498 additions and 8 deletions

View File

@@ -123,7 +123,7 @@ public class WebContents : ApiBase
/// </summary>
public void OpenDevTools()
{
BridgeConnector.Socket.Emit("webContentsOpenDevTools", Id);
BridgeConnector.Socket.Emit("webContents-openDevTools", Id);
}
/// <summary>
@@ -132,7 +132,41 @@ public class WebContents : ApiBase
/// <param name="openDevToolsOptions"></param>
public void OpenDevTools(OpenDevToolsOptions openDevToolsOptions)
{
BridgeConnector.Socket.Emit("webContentsOpenDevTools", Id, openDevToolsOptions);
BridgeConnector.Socket.Emit("webContents-openDevTools", Id, openDevToolsOptions);
}
/// <summary>
/// Toggles the devtools.
/// </summary>
public void ToggleDevTools()
{
BridgeConnector.Socket.Emit("webContents-toggleDevTools", Id);
}
/// <summary>
/// Closes the devtools.
/// </summary>
public void CloseDevTools()
{
BridgeConnector.Socket.Emit("webContents-closeDevTools", Id);
}
/// <summary>
/// Returns boolean - Whether the devtools is opened.
/// </summary>
/// <returns></returns>
public bool IsDevToolsOpened()
{
return Task.Run(() => InvokeAsync<bool>()).Result;
}
/// <summary>
/// Returns boolean - Whether the devtools view is focused.
/// </summary>
/// <returns></returns>
public bool IsDevToolsFocused()
{
return Task.Run(() => InvokeAsync<bool>()).Result;
}
/// <summary>
@@ -280,4 +314,151 @@ public class WebContents : ApiBase
{
BridgeConnector.Socket.Emit("webContents-insertCSS", Id, isBrowserWindow, path);
}
/// <summary>
/// A number property that determines the zoom level for this web contents.
///The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively.
///The formula for this is scale := 1.2 ^ level.
/// </summary>
public int ZoomLevel
{
get
{
return Task.Run(() => this.InvokeAsync<int>()).Result;
}
set
{
BridgeConnector.Socket.Emit("webContents-zoomLevel-set", Id, value);
}
}
/// <summary>
/// A number property that determines the zoom factor for this web contents.
///The zoom factor is the zoom percent divided by 100, so 300% = 3.0.
/// </summary>
public double ZoomFactor
{
get
{
return Task.Run(() => this.InvokeAsync<double>()).Result;
}
set
{
BridgeConnector.Socket.Emit("webContents-zoomFactor-set", Id, value);
}
}
/// <summary>
/// Returns number - The current zoom factor.
/// </summary>
/// <returns></returns>
public Task<double> GetZoomFactorAsync() => InvokeAsync<double>();
/// <summary>
/// Changes the zoom factor to the specified factor.
/// Zoom factor is zoom percent divided by 100, so 300% = 3.0.
/// The factor must be greater than 0.0.
/// </summary>
/// <param name="factor"></param>
public void SetZoomFactor(double factor)
{
BridgeConnector.Socket.Emit("webContents-setZoomFactor", Id, factor);
}
/// <summary>
/// Returns number - The current zoom level.
/// </summary>
/// <returns></returns>
public Task<int> GetZoomLevelAsync() => InvokeAsync<int>();
/// <summary>
/// Changes the zoom level to the specified level.
/// The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively.
/// </summary>
/// <param name="level"></param>
public void SetZoomLevel(int level)
{
BridgeConnector.Socket.Emit("webContents-setZoomLevel", Id, level);
}
/// <summary>
/// Sets the maximum and minimum pinch-to-zoom level.
/// </summary>
/// <param name="minimumLevel"></param>
/// <param name="maximumLevel"></param>
public Task SetVisualZoomLevelLimitsAsync(int minimumLevel, int maximumLevel)
{
var tcs = new TaskCompletionSource();
BridgeConnector.Socket.Once("webContents-setVisualZoomLevelLimits-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-setVisualZoomLevelLimits", Id, minimumLevel, maximumLevel);
return tcs.Task;
}
/// <summary>
/// A boolean property that determines whether this page is muted.
/// </summary>
public bool AudioMuted
{
get
{
return Task.Run(() => this.InvokeAsync<bool>()).Result;
}
set
{
BridgeConnector.Socket.Emit("webContents-audioMuted-set", Id, value);
}
}
/// <summary>
/// Returns boolean - Whether this page has been muted.
/// </summary>
/// <returns></returns>
public Task<bool> IsAudioMutedAsync() => InvokeAsync<bool>();
/// <summary>
/// Returns boolean - Whether audio is currently playing.
/// </summary>
/// <returns></returns>
public Task<bool> IsCurrentlyAudibleAsync() => InvokeAsync<bool>();
/// <summary>
/// Mute the audio on the current web page.
/// </summary>
/// <param name="muted"></param>
public void SetAudioMuted(bool muted)
{
BridgeConnector.Socket.Emit("webContents-setAudioMuted", Id, muted);
}
/// <summary>
/// A string property that determines the user agent for this web page.
/// </summary>
public string UserAgent
{
get
{
return Task.Run(() => this.InvokeAsync<string>()).Result;
}
set
{
BridgeConnector.Socket.Emit("webContents-userAgent-set", Id, value);
}
}
/// <summary>
/// Returns string - The user agent for this web page.
/// </summary>
/// <returns></returns>
public Task<string> GetUserAgentAsync() => InvokeAsync<string>();
/// <summary>
/// Overrides the user agent for this web page.
/// </summary>
/// <param name="userAgent"></param>
public void SetUserAgent(string userAgent)
{
BridgeConnector.Socket.Emit("webContents-setUserAgent", Id, userAgent);
}
}

View File

@@ -78,7 +78,7 @@ module.exports = (socket) => {
electronSocket.emit("webContents-domReady" + id);
});
});
socket.on("webContentsOpenDevTools", (id, options) => {
socket.on("webContents-openDevTools", (id, options) => {
if (options) {
getWindowById(id).webContents.openDevTools(options);
}
@@ -315,6 +315,93 @@ module.exports = (socket) => {
const extension = await browserWindow.webContents.session.loadExtension(path, { allowFileAccess: allowFileAccess });
electronSocket.emit("webContents-session-loadExtension-completed", extension);
});
socket.on('webContents-getZoomFactor', (id) => {
const browserWindow = getWindowById(id);
const text = browserWindow.webContents.getZoomFactor();
electronSocket.emit('webContents-getZoomFactor-completed', text);
});
socket.on('webContents-setZoomFactor', (id, factor) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.setZoomFactor(factor);
});
socket.on('webContents-getZoomLevel', (id) => {
const browserWindow = getWindowById(id);
const content = browserWindow.webContents.getZoomLevel();
electronSocket.emit('webContents-getZoomLevel-completed', content);
});
socket.on('webContents-setZoomLevel', (id, level) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.setZoomLevel(level);
});
socket.on('webContents-setVisualZoomLevelLimits', async (id, minimumLevel, maximumLevel) => {
const browserWindow = getWindowById(id);
await browserWindow.webContents.setVisualZoomLevelLimits(minimumLevel, maximumLevel);
electronSocket.emit('webContents-setVisualZoomLevelLimits-completed');
});
socket.on('webContents-zoomLevel', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-zoomLevel-completed', browserWindow.webContents.zoomLevel);
});
socket.on('webContents-zoomLevel-set', (id, level) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.zoomLevel = level;
});
socket.on('webContents-zoomFactor', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-zoomFactor-completed', browserWindow.webContents.zoomFactor);
});
socket.on('webContents-zoomFactor-set', (id, factor) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.zoomFactor = factor;
});
socket.on("webContents-toggleDevTools", (id) => {
getWindowById(id).webContents.toggleDevTools();
});
socket.on("webContents-closeDevTools", (id) => {
getWindowById(id).webContents.closeDevTools();
});
socket.on("webContents-isDevToolsOpened", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isDevToolsOpened-completed', browserWindow.webContents.isDevToolsOpened());
});
socket.on("webContents-isDevToolsFocused", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isDevToolsFocused-completed', browserWindow.webContents.isDevToolsFocused());
});
socket.on("webContents-setAudioMuted", (id, muted) => {
getWindowById(id).webContents.setAudioMuted(muted);
});
socket.on("webContents-isAudioMuted", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isAudioMuted-completed', browserWindow.webContents.isAudioMuted());
});
socket.on("webContents-isCurrentlyAudible", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isCurrentlyAudible-completed', browserWindow.webContents.isCurrentlyAudible());
});
socket.on('webContents-audioMuted', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-audioMuted-completed', browserWindow.webContents.audioMuted);
});
socket.on('webContents-audioMuted-set', (id, muted) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.audioMuted = muted;
});
socket.on("webContents-getUserAgent", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-getUserAgent-completed', browserWindow.webContents.getUserAgent());
});
socket.on("webContents-setUserAgent", (id, userAgent) => {
getWindowById(id).webContents.setUserAgent(userAgent);
});
socket.on('webContents-userAgent', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-userAgent-completed', browserWindow.webContents.userAgent);
});
socket.on('webContents-userAgent-set', (id, userAgent) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.userAgent = userAgent;
});
function getWindowById(id) {
if (id >= 1000) {
return (0, browserView_1.browserViewMediateService)(id - 1000);

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
import { Socket } from "net";
import { BrowserWindow, BrowserView } from "electron";
import {BrowserWindow, BrowserView} from "electron";
import { browserViewMediateService } from "./browserView";
const fs = require("fs");
let electronSocket;
@@ -101,7 +101,7 @@ export = (socket: Socket) => {
});
});
socket.on("webContentsOpenDevTools", (id, options) => {
socket.on("webContents-openDevTools", (id, options) => {
if (options) {
getWindowById(id).webContents.openDevTools(options);
} else {
@@ -466,7 +466,116 @@ export = (socket: Socket) => {
}
);
function getWindowById(
socket.on('webContents-getZoomFactor', (id) => {
const browserWindow = getWindowById(id);
const text = browserWindow.webContents.getZoomFactor();
electronSocket.emit('webContents-getZoomFactor-completed', text);
});
socket.on('webContents-setZoomFactor', (id, factor) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.setZoomFactor(factor);
});
socket.on('webContents-getZoomLevel', (id) => {
const browserWindow = getWindowById(id);
const content = browserWindow.webContents.getZoomLevel();
electronSocket.emit('webContents-getZoomLevel-completed', content);
});
socket.on('webContents-setZoomLevel', (id, level) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.setZoomLevel(level);
});
socket.on('webContents-setVisualZoomLevelLimits', async (id, minimumLevel, maximumLevel) => {
const browserWindow = getWindowById(id);
await browserWindow.webContents.setVisualZoomLevelLimits(minimumLevel, maximumLevel);
electronSocket.emit('webContents-setVisualZoomLevelLimits-completed');
});
socket.on('webContents-zoomLevel', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-zoomLevel-completed', browserWindow.webContents.zoomLevel);
});
socket.on('webContents-zoomLevel-set', (id, level) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.zoomLevel = level;
});
socket.on('webContents-zoomFactor', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-zoomFactor-completed', browserWindow.webContents.zoomFactor);
});
socket.on('webContents-zoomFactor-set', (id, factor) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.zoomFactor = factor;
});
socket.on("webContents-toggleDevTools", (id) => {
getWindowById(id).webContents.toggleDevTools();
});
socket.on("webContents-closeDevTools", (id) => {
getWindowById(id).webContents.closeDevTools();
});
socket.on("webContents-isDevToolsOpened", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isDevToolsOpened-completed', browserWindow.webContents.isDevToolsOpened());
});
socket.on("webContents-isDevToolsFocused", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isDevToolsFocused-completed', browserWindow.webContents.isDevToolsFocused());
});
socket.on("webContents-setAudioMuted", (id, muted) => {
getWindowById(id).webContents.setAudioMuted(muted);
});
socket.on("webContents-isAudioMuted", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isAudioMuted-completed', browserWindow.webContents.isAudioMuted());
});
socket.on("webContents-isCurrentlyAudible", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-isCurrentlyAudible-completed', browserWindow.webContents.isCurrentlyAudible());
});
socket.on('webContents-audioMuted', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-audioMuted-completed', browserWindow.webContents.audioMuted);
});
socket.on('webContents-audioMuted-set', (id, muted) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.audioMuted = muted;
});
socket.on("webContents-getUserAgent", function (id) {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-getUserAgent-completed', browserWindow.webContents.getUserAgent());
});
socket.on("webContents-setUserAgent", (id, userAgent) => {
getWindowById(id).webContents.setUserAgent(userAgent);
});
socket.on('webContents-userAgent', (id) => {
const browserWindow = getWindowById(id);
electronSocket.emit('webContents-userAgent-completed', browserWindow.webContents.userAgent);
});
socket.on('webContents-userAgent-set', (id, userAgent) => {
const browserWindow = getWindowById(id);
browserWindow.webContents.userAgent = userAgent;
});
function getWindowById(
id: number
): Electron.BrowserWindow | Electron.BrowserView {
if (id >= 1000) {

View File

@@ -104,6 +104,7 @@
var test = await Electron.AutoUpdater.RequestHeadersAsync;
test.Should().BeNull();
Electron.AutoUpdater.RequestHeaders = headers;
await Task.Delay(500);
test = await Electron.AutoUpdater.RequestHeadersAsync;
test.Should().NotBeNull();
test.Count.Should().Be(1);

View File

@@ -1,3 +1,5 @@
using System.Runtime.InteropServices;
namespace ElectronNET.IntegrationTests.Tests
{
using ElectronNET.API.Entities;
@@ -75,9 +77,119 @@ namespace ElectronNET.IntegrationTests.Tests
[SkippableFact(Timeout = 20000)]
public async Task GetPrintersAsync_check()
{
Skip.If(Environment.GetEnvironmentVariable("GITHUB_TOKEN") != null, "Skipping printer test in CI environment.");
Skip.If(Environment.GetEnvironmentVariable("GITHUB_RUN_ID") != null, "Skipping printer test in CI environment.");
var info = await fx.MainWindow.WebContents.GetPrintersAsync();
info.Should().NotBeNull();
}
[Fact(Timeout = 20000)]
public async Task GetSetZoomFactor_check()
{
await fx.MainWindow.WebContents.GetZoomFactorAsync();
var ok = await fx.MainWindow.WebContents.GetZoomFactorAsync();
ok.Should().BeGreaterThan(0.0);
fx.MainWindow.WebContents.SetZoomFactor(2.0);
await Task.Delay(500);
ok = await fx.MainWindow.WebContents.GetZoomFactorAsync();
ok.Should().Be(2.0);
}
[Fact(Timeout = 20000)]
public async Task ZoomFactorProperty_check()
{
var ok = fx.MainWindow.WebContents.ZoomFactor;
ok.Should().Be(1.0);
fx.MainWindow.WebContents.ZoomFactor = 2.0;
ok = fx.MainWindow.WebContents.ZoomFactor;
ok.Should().Be(2.0);
}
[SkippableFact(Timeout = 20000)]
public async Task GetSetZoomLevel_check()
{
Skip.If(Environment.GetEnvironmentVariable("GITHUB_RUN_ID") != null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Skipping test on Windows CI.");
await fx.MainWindow.WebContents.GetZoomLevelAsync();
var ok = await fx.MainWindow.WebContents.GetZoomLevelAsync();
ok.Should().Be(0);
fx.MainWindow.WebContents.SetZoomLevel(2);
await Task.Delay(500);
ok = await fx.MainWindow.WebContents.GetZoomLevelAsync();
ok.Should().Be(2);
}
[Fact(Timeout = 20000)]
public async Task ZoomLevelProperty_check()
{
var ok = fx.MainWindow.WebContents.ZoomLevel;
ok.Should().Be(0);
fx.MainWindow.WebContents.ZoomLevel = 2;
ok = fx.MainWindow.WebContents.ZoomLevel;
ok.Should().Be(2);
}
[SkippableFact(Timeout = 20000)]
public async Task DevTools_check()
{
Skip.If(Environment.GetEnvironmentVariable("GITHUB_RUN_ID") != null && RuntimeInformation.IsOSPlatform(OSPlatform.OSX), "Skipping test on macOS CI.");
fx.MainWindow.WebContents.IsDevToolsOpened().Should().BeFalse();
fx.MainWindow.WebContents.OpenDevTools();
await Task.Delay(500);
fx.MainWindow.WebContents.IsDevToolsOpened().Should().BeTrue();
fx.MainWindow.WebContents.CloseDevTools();
await Task.Delay(500);
fx.MainWindow.WebContents.IsDevToolsOpened().Should().BeFalse();
fx.MainWindow.WebContents.ToggleDevTools();
await Task.Delay(500);
fx.MainWindow.WebContents.IsDevToolsOpened().Should().BeTrue();
}
[Fact(Timeout = 20000)]
public async Task GetSetAudioMuted_check()
{
fx.MainWindow.WebContents.SetAudioMuted(true);
await Task.Delay(500);
var ok = await fx.MainWindow.WebContents.IsAudioMutedAsync();
ok.Should().BeTrue();
fx.MainWindow.WebContents.SetAudioMuted(false);
await Task.Delay(500);
ok = await fx.MainWindow.WebContents.IsAudioMutedAsync();
ok.Should().BeFalse();
// Assuming no audio is playing, IsCurrentlyAudibleAsync should return false
// there is no way to play audio in this test
ok = await fx.MainWindow.WebContents.IsCurrentlyAudibleAsync();
ok.Should().BeFalse();
}
[SkippableFact(Timeout = 20000)]
public async Task AudioMutedProperty_check()
{
Skip.If(Environment.GetEnvironmentVariable("GITHUB_RUN_ID") != null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Skipping test on Windows CI.");
fx.MainWindow.WebContents.AudioMuted.Should().BeFalse();
fx.MainWindow.WebContents.AudioMuted = true;
fx.MainWindow.WebContents.AudioMuted.Should().BeTrue();
}
[SkippableFact(Timeout = 20000)]
public async Task GetSetUserAgent_check()
{
Skip.If(Environment.GetEnvironmentVariable("GITHUB_RUN_ID") != null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Skipping test on Windows CI.");
var ok = await fx.MainWindow.WebContents.GetUserAgentAsync();
ok.Should().NotBeNullOrEmpty();
fx.MainWindow.WebContents.SetUserAgent("MyUserAgent/1.0");
await Task.Delay(1000);
ok = await fx.MainWindow.WebContents.GetUserAgentAsync();
ok.Should().Be("MyUserAgent/1.0");
}
[SkippableFact(Timeout = 20000)]
public async Task UserAgentProperty_check()
{
Skip.If(Environment.GetEnvironmentVariable("GITHUB_RUN_ID") != null && RuntimeInformation.IsOSPlatform(OSPlatform.Windows), "Skipping test on Windows CI.");
fx.MainWindow.WebContents.UserAgent.Should().NotBeNullOrEmpty();
fx.MainWindow.WebContents.UserAgent = "MyUserAgent/1.0";
fx.MainWindow.WebContents.UserAgent.Should().Be("MyUserAgent/1.0");
}
}
}