Skip to content

Commit

Permalink
feat: webFrameMain.origin (#35438)
Browse files Browse the repository at this point in the history
  • Loading branch information
nornagon authored and miniak committed Sep 13, 2022
1 parent 178db41 commit 613ec9d
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 11 deletions.
10 changes: 10 additions & 0 deletions docs/api/web-frame-main.md
Expand Up @@ -144,6 +144,16 @@ ipcRenderer.on('port', (e, msg) => {

A `string` representing the current URL of the frame.

#### `frame.origin` _Readonly_

A `string` representing the current origin of the frame, serialized according
to [RFC 6454](https://www.rfc-editor.org/rfc/rfc6454). This may be different
from the URL. For instance, if the frame is a child window opened to
`about:blank`, then `frame.origin` will return the parent frame's origin, while
`frame.url` will return the empty string. Pages without a scheme/host/port
triple origin will have the serialized origin of `"null"` (that is, the string
containing the letters n, u, l, l).

#### `frame.top` _Readonly_

A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame`
Expand Down
7 changes: 7 additions & 0 deletions shell/browser/api/electron_api_web_frame_main.cc
Expand Up @@ -291,6 +291,12 @@ GURL WebFrameMain::URL() const {
return render_frame_->GetLastCommittedURL();
}

std::string WebFrameMain::Origin() const {
if (!CheckRenderFrame())
return std::string();
return render_frame_->GetLastCommittedOrigin().Serialize();
}

blink::mojom::PageVisibilityState WebFrameMain::VisibilityState() const {
if (!CheckRenderFrame())
return blink::mojom::PageVisibilityState::kHidden;
Expand Down Expand Up @@ -380,6 +386,7 @@ v8::Local<v8::ObjectTemplate> WebFrameMain::FillObjectTemplate(
.SetProperty("processId", &WebFrameMain::ProcessID)
.SetProperty("routingId", &WebFrameMain::RoutingID)
.SetProperty("url", &WebFrameMain::URL)
.SetProperty("origin", &WebFrameMain::Origin)
.SetProperty("visibilityState", &WebFrameMain::VisibilityState)
.SetProperty("top", &WebFrameMain::Top)
.SetProperty("parent", &WebFrameMain::Parent)
Expand Down
1 change: 1 addition & 0 deletions shell/browser/api/electron_api_web_frame_main.h
Expand Up @@ -108,6 +108,7 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
int ProcessID() const;
int RoutingID() const;
GURL URL() const;
std::string Origin() const;
blink::mojom::PageVisibilityState VisibilityState() const;

content::RenderFrameHost* Top() const;
Expand Down
72 changes: 61 additions & 11 deletions spec-main/api-web-frame-main-spec.ts
Expand Up @@ -2,11 +2,11 @@ import { expect } from 'chai';
import * as http from 'http';
import * as path from 'path';
import * as url from 'url';
import { BrowserWindow, WebFrameMain, webFrameMain, ipcMain } from 'electron/main';
import { BrowserWindow, WebFrameMain, webFrameMain, ipcMain, app, WebContents } from 'electron/main';
import { closeAllWindows } from './window-helpers';
import { emittedOnce, emittedNTimes } from './events-helpers';
import { AddressInfo } from 'net';
import { ifit, waitUntil } from './spec-helpers';
import { defer, ifit, waitUntil } from './spec-helpers';

describe('webFrameMain module', () => {
const fixtures = path.resolve(__dirname, '..', 'spec-main', 'fixtures');
Expand Down Expand Up @@ -39,7 +39,7 @@ describe('webFrameMain module', () => {
let webFrame: WebFrameMain;

beforeEach(async () => {
w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
w = new BrowserWindow({ show: false });
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
webFrame = w.webContents.mainFrame;
});
Expand Down Expand Up @@ -88,8 +88,8 @@ describe('webFrameMain module', () => {
});

describe('cross-origin', () => {
let serverA = null as unknown as Server;
let serverB = null as unknown as Server;
let serverA: Server;
let serverB: Server;

before(async () => {
serverA = await createServer();
Expand All @@ -112,7 +112,7 @@ describe('webFrameMain module', () => {

describe('WebFrame.url', () => {
it('should report correct address for each subframe', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
const webFrame = w.webContents.mainFrame;

Expand All @@ -122,9 +122,59 @@ describe('webFrameMain module', () => {
});
});

describe('WebFrame.origin', () => {
it('should be null for a fresh WebContents', () => {
const w = new BrowserWindow({ show: false });
expect(w.webContents.mainFrame.origin).to.equal('null');
});

it('should be file:// for file frames', async () => {
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(fixtures, 'blank.html'));
expect(w.webContents.mainFrame.origin).to.equal('file://');
});

it('should be http:// for an http frame', async () => {
const w = new BrowserWindow({ show: false });
const s = await createServer();
defer(() => s.server.close());
await w.loadURL(s.url);
expect(w.webContents.mainFrame.origin).to.equal(s.url.replace(/\/$/, ''));
});

it('should show parent origin when child page is about:blank', async () => {
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(fixtures, 'blank.html'));
const webContentsCreated: Promise<[unknown, WebContents]> = emittedOnce(app, 'web-contents-created') as any;
expect(w.webContents.mainFrame.origin).to.equal('file://');
await w.webContents.executeJavaScript('window.open("", null, "show=false"), null');
const [, childWebContents] = await webContentsCreated;
expect(childWebContents.mainFrame.origin).to.equal('file://');
});

it('should show parent frame\'s origin when about:blank child window opened through cross-origin subframe', async () => {
const w = new BrowserWindow({ show: false });
const serverA = await createServer();
const serverB = await createServer();
defer(() => {
serverA.server.close();
serverB.server.close();
});
await w.loadURL(serverA.url + '?frameSrc=' + encodeURIComponent(serverB.url));
const { mainFrame } = w.webContents;
expect(mainFrame.origin).to.equal(serverA.url.replace(/\/$/, ''));
const [childFrame] = mainFrame.frames;
expect(childFrame.origin).to.equal(serverB.url.replace(/\/$/, ''));
const webContentsCreated: Promise<[unknown, WebContents]> = emittedOnce(app, 'web-contents-created') as any;
await childFrame.executeJavaScript('window.open("", null, "show=false"), null');
const [, childWebContents] = await webContentsCreated;
expect(childWebContents.mainFrame.origin).to.equal(childFrame.origin);
});
});

describe('WebFrame IDs', () => {
it('has properties for various identifiers', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(subframesPath, 'frame.html'));
const webFrame = w.webContents.mainFrame;
expect(webFrame).to.have.ownProperty('url').that.is.a('string');
Expand Down Expand Up @@ -154,7 +204,7 @@ describe('webFrameMain module', () => {

describe('WebFrame.executeJavaScript', () => {
it('can inject code into any subframe', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
const webFrame = w.webContents.mainFrame;

Expand All @@ -167,7 +217,7 @@ describe('webFrameMain module', () => {

describe('WebFrame.reload', () => {
it('reloads a frame', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
const w = new BrowserWindow({ show: false });
await w.loadFile(path.join(subframesPath, 'frame.html'));
const webFrame = w.webContents.mainFrame;

Expand Down Expand Up @@ -200,7 +250,7 @@ describe('webFrameMain module', () => {
let w: BrowserWindow;

beforeEach(async () => {
w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
w = new BrowserWindow({ show: false });
});

// TODO(jkleinsc) fix this flaky test on linux
Expand Down Expand Up @@ -263,7 +313,7 @@ describe('webFrameMain module', () => {
});

it('can find each frame from navigation events', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
const w = new BrowserWindow({ show: false });

// frame-with-frame-container.html, frame-with-frame.html, frame.html
const didFrameFinishLoad = emittedNTimes(w.webContents, 'did-frame-finish-load', 3);
Expand Down

0 comments on commit 613ec9d

Please sign in to comment.