feat: add transparent
webpreference to webview (#40301)
* feat: add transparent option to WebContents * feat: add transparent attribute to webview * test: add tests for webview transparent attribute * docs: add transparent attribute to webview docs * fix: run tests on macOS only * refactor: remove unneeded html tag * fix: only apply transparent option to guests * refactor: correct comment * refactor: use opaque instead Retains current webview behaviour by default. * fix: correct variable name to guest_opaque_ * refactor: use transparent webpreference * docs: remove unused web preference * fix: uncomment condition for transparency test * docs: converted to list format and linked to MDN * fix: make webviews transparent by default again * fix: rebase error --------- Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
This commit is contained in:
parent
8c71e2adc9
commit
5086071294
5 changed files with 106 additions and 3 deletions
|
@ -221,7 +221,9 @@ windows. Popups are disabled by default.
|
||||||
```
|
```
|
||||||
|
|
||||||
A `string` which is a comma separated list of strings which specifies the web preferences to be set on the webview.
|
A `string` which is a comma separated list of strings which specifies the web preferences to be set on the webview.
|
||||||
The full list of supported preference strings can be found in [BrowserWindow](browser-window.md#new-browserwindowoptions).
|
The full list of supported preference strings can be found in [BrowserWindow](browser-window.md#new-browserwindowoptions). In addition, webview supports the following preferences:
|
||||||
|
|
||||||
|
* `transparent` boolean (optional) - Whether to enable background transparency for the guest page. Default is `true`. **Note:** The guest page's text and background colors are derived from the [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) of its root element. When transparency is enabled, the text color will still change accordingly but the background will remain transparent.
|
||||||
|
|
||||||
The string follows the same format as the features string in `window.open`.
|
The string follows the same format as the features string in `window.open`.
|
||||||
A name by itself is given a `true` boolean value.
|
A name by itself is given a `true` boolean value.
|
||||||
|
|
|
@ -822,6 +822,9 @@ WebContents::WebContents(v8::Isolate* isolate,
|
||||||
// Get type
|
// Get type
|
||||||
options.Get("type", &type_);
|
options.Get("type", &type_);
|
||||||
|
|
||||||
|
// Get transparent for guest view
|
||||||
|
options.Get("transparent", &guest_transparent_);
|
||||||
|
|
||||||
bool b = false;
|
bool b = false;
|
||||||
if (options.Get(options::kOffscreen, &b) && b)
|
if (options.Get(options::kOffscreen, &b) && b)
|
||||||
type_ = Type::kOffScreen;
|
type_ = Type::kOffScreen;
|
||||||
|
@ -3778,7 +3781,7 @@ void WebContents::SetImageAnimationPolicy(const std::string& new_policy) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebContents::SetBackgroundColor(absl::optional<SkColor> maybe_color) {
|
void WebContents::SetBackgroundColor(absl::optional<SkColor> maybe_color) {
|
||||||
SkColor color = maybe_color.value_or(type_ == Type::kWebView ||
|
SkColor color = maybe_color.value_or((IsGuest() && guest_transparent_) ||
|
||||||
type_ == Type::kBrowserView
|
type_ == Type::kBrowserView
|
||||||
? SK_ColorTRANSPARENT
|
? SK_ColorTRANSPARENT
|
||||||
: SK_ColorWHITE);
|
: SK_ColorWHITE);
|
||||||
|
|
|
@ -801,6 +801,9 @@ class WebContents : public ExclusiveAccessContext,
|
||||||
// The type of current WebContents.
|
// The type of current WebContents.
|
||||||
Type type_ = Type::kBrowserWindow;
|
Type type_ = Type::kBrowserWindow;
|
||||||
|
|
||||||
|
// Weather the guest view should be transparent
|
||||||
|
bool guest_transparent_ = true;
|
||||||
|
|
||||||
int32_t id_;
|
int32_t id_;
|
||||||
|
|
||||||
// Request id used for findInPage request.
|
// Request id used for findInPage request.
|
||||||
|
|
15
spec/fixtures/pages/flex-webview.html
vendored
Normal file
15
spec/fixtures/pages/flex-webview.html
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<style>
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
webview {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,6 +1,6 @@
|
||||||
import * as path from 'node:path';
|
import * as path from 'node:path';
|
||||||
import * as url from 'node:url';
|
import * as url from 'node:url';
|
||||||
import { BrowserWindow, session, ipcMain, app, WebContents } from 'electron/main';
|
import { BrowserWindow, session, ipcMain, app, WebContents, screen } from 'electron/main';
|
||||||
import { closeAllWindows } from './lib/window-helpers';
|
import { closeAllWindows } from './lib/window-helpers';
|
||||||
import { emittedUntil } from './lib/events-helpers';
|
import { emittedUntil } from './lib/events-helpers';
|
||||||
import { ifit, ifdescribe, defer, itremote, useRemoteContext, listen } from './lib/spec-helpers';
|
import { ifit, ifdescribe, defer, itremote, useRemoteContext, listen } from './lib/spec-helpers';
|
||||||
|
@ -9,6 +9,7 @@ import * as http from 'node:http';
|
||||||
import * as auth from 'basic-auth';
|
import * as auth from 'basic-auth';
|
||||||
import { once } from 'node:events';
|
import { once } from 'node:events';
|
||||||
import { setTimeout } from 'node:timers/promises';
|
import { setTimeout } from 'node:timers/promises';
|
||||||
|
import { areColorsSimilar, captureScreen, HexColors, getPixelColor } from './lib/screen-helpers';
|
||||||
|
|
||||||
declare let WebView: any;
|
declare let WebView: any;
|
||||||
const features = process._linkedBinding('electron_common_features');
|
const features = process._linkedBinding('electron_common_features');
|
||||||
|
@ -773,6 +774,85 @@ describe('<webview> tag', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('webpreferences attribute', () => {
|
||||||
|
const WINDOW_BACKGROUND_COLOR = '#55ccbb';
|
||||||
|
|
||||||
|
let w: BrowserWindow;
|
||||||
|
before(async () => {
|
||||||
|
w = new BrowserWindow({
|
||||||
|
webPreferences: {
|
||||||
|
webviewTag: true,
|
||||||
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await w.loadURL(`file://${fixtures}/pages/flex-webview.html`);
|
||||||
|
w.setBackgroundColor(WINDOW_BACKGROUND_COLOR);
|
||||||
|
});
|
||||||
|
afterEach(async () => {
|
||||||
|
await w.webContents.executeJavaScript(`{
|
||||||
|
for (const el of document.querySelectorAll('webview')) el.remove();
|
||||||
|
}`);
|
||||||
|
});
|
||||||
|
after(() => w.close());
|
||||||
|
|
||||||
|
// Linux and arm64 platforms (WOA and macOS) do not return any capture sources
|
||||||
|
ifit(process.platform === 'darwin' && process.arch === 'x64')('is transparent by default', async () => {
|
||||||
|
await loadWebView(w.webContents, {
|
||||||
|
src: 'data:text/html,foo'
|
||||||
|
});
|
||||||
|
|
||||||
|
await setTimeout(1000);
|
||||||
|
|
||||||
|
const display = screen.getPrimaryDisplay();
|
||||||
|
const screenCapture = await captureScreen();
|
||||||
|
const centerColor = getPixelColor(screenCapture, {
|
||||||
|
x: display.size.width / 2,
|
||||||
|
y: display.size.height / 2
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(areColorsSimilar(centerColor, WINDOW_BACKGROUND_COLOR)).to.be.true();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Linux and arm64 platforms (WOA and macOS) do not return any capture sources
|
||||||
|
ifit(process.platform === 'darwin' && process.arch === 'x64')('remains transparent when set', async () => {
|
||||||
|
await loadWebView(w.webContents, {
|
||||||
|
src: 'data:text/html,foo',
|
||||||
|
webpreferences: 'transparent=yes'
|
||||||
|
});
|
||||||
|
|
||||||
|
await setTimeout(1000);
|
||||||
|
|
||||||
|
const display = screen.getPrimaryDisplay();
|
||||||
|
const screenCapture = await captureScreen();
|
||||||
|
const centerColor = getPixelColor(screenCapture, {
|
||||||
|
x: display.size.width / 2,
|
||||||
|
y: display.size.height / 2
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(areColorsSimilar(centerColor, WINDOW_BACKGROUND_COLOR)).to.be.true();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Linux and arm64 platforms (WOA and macOS) do not return any capture sources
|
||||||
|
ifit(process.platform === 'darwin' && process.arch === 'x64')('can disable transparency', async () => {
|
||||||
|
await loadWebView(w.webContents, {
|
||||||
|
src: 'data:text/html,foo',
|
||||||
|
webpreferences: 'transparent=no'
|
||||||
|
});
|
||||||
|
|
||||||
|
await setTimeout(1000);
|
||||||
|
|
||||||
|
const display = screen.getPrimaryDisplay();
|
||||||
|
const screenCapture = await captureScreen();
|
||||||
|
const centerColor = getPixelColor(screenCapture, {
|
||||||
|
x: display.size.width / 2,
|
||||||
|
y: display.size.height / 2
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(areColorsSimilar(centerColor, HexColors.WHITE)).to.be.true();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('permission request handlers', () => {
|
describe('permission request handlers', () => {
|
||||||
let w: BrowserWindow;
|
let w: BrowserWindow;
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
|
Loading…
Reference in a new issue