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: add WebFrameMain.visibilityState #28706

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
6 changes: 6 additions & 0 deletions docs/api/web-frame-main.md
Expand Up @@ -182,3 +182,9 @@ This is not the same as the OS process ID; to read that use `frame.osProcessId`.
An `Integer` representing the unique frame id in the current renderer process.
Distinct `WebFrameMain` instances that refer to the same underlying frame will
have the same `routingId`.

#### `frame.visibilityState` _Readonly_

A `string` representing the [visibility state](https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState) of the frame.

See also how the [Page Visibility API](browser-window.md#page-visibility) is affected by other Electron APIs.
29 changes: 29 additions & 0 deletions shell/browser/api/electron_api_web_frame_main.cc
Expand Up @@ -30,6 +30,28 @@
#include "shell/common/node_includes.h"
#include "shell/common/v8_value_serializer.h"

namespace gin {

template <>
struct Converter<blink::mojom::PageVisibilityState> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
blink::mojom::PageVisibilityState val) {
std::string visibility;
switch (val) {
case blink::mojom::PageVisibilityState::kVisible:
visibility = "visible";
break;
case blink::mojom::PageVisibilityState::kHidden:
case blink::mojom::PageVisibilityState::kHiddenButPainting:
visibility = "hidden";
break;
}
return gin::ConvertToV8(isolate, visibility);
}
};

} // namespace gin

namespace electron {

namespace api {
Expand Down Expand Up @@ -228,6 +250,12 @@ GURL WebFrameMain::URL() const {
return render_frame_->GetLastCommittedURL();
}

blink::mojom::PageVisibilityState WebFrameMain::VisibilityState() const {
if (!CheckRenderFrame())
return blink::mojom::PageVisibilityState::kHidden;
return render_frame_->GetVisibilityState();
}

content::RenderFrameHost* WebFrameMain::Top() const {
if (!CheckRenderFrame())
return nullptr;
Expand Down Expand Up @@ -331,6 +359,7 @@ v8::Local<v8::ObjectTemplate> WebFrameMain::FillObjectTemplate(
.SetProperty("processId", &WebFrameMain::ProcessID)
.SetProperty("routingId", &WebFrameMain::RoutingID)
.SetProperty("url", &WebFrameMain::URL)
.SetProperty("visibilityState", &WebFrameMain::VisibilityState)
.SetProperty("top", &WebFrameMain::Top)
.SetProperty("parent", &WebFrameMain::Parent)
.SetProperty("frames", &WebFrameMain::Frames)
Expand Down
2 changes: 2 additions & 0 deletions shell/browser/api/electron_api_web_frame_main.h
Expand Up @@ -15,6 +15,7 @@
#include "gin/wrappable.h"
#include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/pinnable.h"
#include "third_party/blink/public/mojom/page/page_visibility_state.mojom-forward.h"

class GURL;

Expand Down Expand Up @@ -95,6 +96,7 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
int ProcessID() const;
int RoutingID() const;
GURL URL() const;
blink::mojom::PageVisibilityState VisibilityState() const;

content::RenderFrameHost* Top() const;
content::RenderFrameHost* Parent() const;
Expand Down
17 changes: 17 additions & 0 deletions spec-main/api-web-frame-main-spec.ts
Expand Up @@ -135,6 +135,23 @@ describe('webFrameMain module', () => {
});
});

describe('WebFrame.visibilityState', () => {
it('should match window state', async () => {
const w = new BrowserWindow({ show: true });
await w.loadURL('about:blank');
const webFrame = w.webContents.mainFrame;

expect(webFrame.visibilityState).to.equal('visible');
w.hide();

jkleinsc marked this conversation as resolved.
Show resolved Hide resolved
// Wait for visibility to propagate. If this ends up being flaky, we can
// look into binding WebContentsObserver::OnVisibilityChanged.
await new Promise(resolve => setTimeout(resolve, 10));

expect(webFrame.visibilityState).to.equal('hidden');
});
});

describe('WebFrame.executeJavaScript', () => {
it('can inject code into any subframe', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
Expand Down