зеркало из https://github.com/electron/electron.git
feat: webFrameMain.origin (#35438)
This commit is contained in:
Родитель
a7248af79e
Коммит
6ad679f540
|
@ -169,6 +169,16 @@ convenient when `nodeIntegrationInSubFrames` is not enabled.
|
||||||
|
|
||||||
A `string` representing the current URL of the frame.
|
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_
|
#### `frame.top` _Readonly_
|
||||||
|
|
||||||
A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame`
|
A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame`
|
||||||
|
|
|
@ -296,6 +296,12 @@ GURL WebFrameMain::URL() const {
|
||||||
return render_frame_->GetLastCommittedURL();
|
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 {
|
blink::mojom::PageVisibilityState WebFrameMain::VisibilityState() const {
|
||||||
if (!CheckRenderFrame())
|
if (!CheckRenderFrame())
|
||||||
return blink::mojom::PageVisibilityState::kHidden;
|
return blink::mojom::PageVisibilityState::kHidden;
|
||||||
|
@ -397,6 +403,7 @@ v8::Local<v8::ObjectTemplate> WebFrameMain::FillObjectTemplate(
|
||||||
.SetProperty("processId", &WebFrameMain::ProcessID)
|
.SetProperty("processId", &WebFrameMain::ProcessID)
|
||||||
.SetProperty("routingId", &WebFrameMain::RoutingID)
|
.SetProperty("routingId", &WebFrameMain::RoutingID)
|
||||||
.SetProperty("url", &WebFrameMain::URL)
|
.SetProperty("url", &WebFrameMain::URL)
|
||||||
|
.SetProperty("origin", &WebFrameMain::Origin)
|
||||||
.SetProperty("visibilityState", &WebFrameMain::VisibilityState)
|
.SetProperty("visibilityState", &WebFrameMain::VisibilityState)
|
||||||
.SetProperty("top", &WebFrameMain::Top)
|
.SetProperty("top", &WebFrameMain::Top)
|
||||||
.SetProperty("parent", &WebFrameMain::Parent)
|
.SetProperty("parent", &WebFrameMain::Parent)
|
||||||
|
|
|
@ -109,6 +109,7 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
|
||||||
int ProcessID() const;
|
int ProcessID() const;
|
||||||
int RoutingID() const;
|
int RoutingID() const;
|
||||||
GURL URL() const;
|
GURL URL() const;
|
||||||
|
std::string Origin() const;
|
||||||
blink::mojom::PageVisibilityState VisibilityState() const;
|
blink::mojom::PageVisibilityState VisibilityState() const;
|
||||||
|
|
||||||
content::RenderFrameHost* Top() const;
|
content::RenderFrameHost* Top() const;
|
||||||
|
|
|
@ -2,11 +2,11 @@ import { expect } from 'chai';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as url from 'url';
|
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 { closeAllWindows } from './window-helpers';
|
||||||
import { emittedOnce, emittedNTimes } from './events-helpers';
|
import { emittedOnce, emittedNTimes } from './events-helpers';
|
||||||
import { AddressInfo } from 'net';
|
import { AddressInfo } from 'net';
|
||||||
import { ifit, waitUntil } from './spec-helpers';
|
import { defer, ifit, waitUntil } from './spec-helpers';
|
||||||
|
|
||||||
describe('webFrameMain module', () => {
|
describe('webFrameMain module', () => {
|
||||||
const fixtures = path.resolve(__dirname, 'fixtures');
|
const fixtures = path.resolve(__dirname, 'fixtures');
|
||||||
|
@ -39,7 +39,7 @@ describe('webFrameMain module', () => {
|
||||||
let webFrame: WebFrameMain;
|
let webFrame: WebFrameMain;
|
||||||
|
|
||||||
beforeEach(async () => {
|
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'));
|
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
|
||||||
webFrame = w.webContents.mainFrame;
|
webFrame = w.webContents.mainFrame;
|
||||||
});
|
});
|
||||||
|
@ -88,8 +88,8 @@ describe('webFrameMain module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('cross-origin', () => {
|
describe('cross-origin', () => {
|
||||||
let serverA = null as unknown as Server;
|
let serverA: Server;
|
||||||
let serverB = null as unknown as Server;
|
let serverB: Server;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
serverA = await createServer();
|
serverA = await createServer();
|
||||||
|
@ -112,7 +112,7 @@ describe('webFrameMain module', () => {
|
||||||
|
|
||||||
describe('WebFrame.url', () => {
|
describe('WebFrame.url', () => {
|
||||||
it('should report correct address for each subframe', async () => {
|
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'));
|
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
|
|
||||||
|
@ -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, 'pages', '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, 'pages', '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', () => {
|
describe('WebFrame IDs', () => {
|
||||||
it('has properties for various identifiers', async () => {
|
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'));
|
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
expect(webFrame).to.have.ownProperty('url').that.is.a('string');
|
expect(webFrame).to.have.ownProperty('url').that.is.a('string');
|
||||||
|
@ -154,7 +204,7 @@ describe('webFrameMain module', () => {
|
||||||
|
|
||||||
describe('WebFrame.executeJavaScript', () => {
|
describe('WebFrame.executeJavaScript', () => {
|
||||||
it('can inject code into any subframe', async () => {
|
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'));
|
await w.loadFile(path.join(subframesPath, 'frame-with-frame-container.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
|
|
||||||
|
@ -165,7 +215,7 @@ describe('webFrameMain module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can resolve promise', async () => {
|
it('can resolve promise', async () => {
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
const w = new BrowserWindow({ show: false });
|
||||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
const p = () => webFrame.executeJavaScript('new Promise(resolve => setTimeout(resolve(42), 2000));');
|
const p = () => webFrame.executeJavaScript('new Promise(resolve => setTimeout(resolve(42), 2000));');
|
||||||
|
@ -174,7 +224,7 @@ describe('webFrameMain module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can reject with error', async () => {
|
it('can reject with error', async () => {
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
const w = new BrowserWindow({ show: false });
|
||||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
const p = () => webFrame.executeJavaScript('new Promise((r,e) => setTimeout(e("error!"), 500));');
|
const p = () => webFrame.executeJavaScript('new Promise((r,e) => setTimeout(e("error!"), 500));');
|
||||||
|
@ -195,7 +245,7 @@ describe('webFrameMain module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can reject when script execution fails', async () => {
|
it('can reject when script execution fails', async () => {
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
const w = new BrowserWindow({ show: false });
|
||||||
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
const p = () => webFrame.executeJavaScript('console.log(test)');
|
const p = () => webFrame.executeJavaScript('console.log(test)');
|
||||||
|
@ -205,7 +255,7 @@ describe('webFrameMain module', () => {
|
||||||
|
|
||||||
describe('WebFrame.reload', () => {
|
describe('WebFrame.reload', () => {
|
||||||
it('reloads a frame', async () => {
|
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'));
|
await w.loadFile(path.join(subframesPath, 'frame.html'));
|
||||||
const webFrame = w.webContents.mainFrame;
|
const webFrame = w.webContents.mainFrame;
|
||||||
|
|
||||||
|
@ -238,7 +288,7 @@ describe('webFrameMain module', () => {
|
||||||
let w: BrowserWindow;
|
let w: BrowserWindow;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
w = new BrowserWindow({ show: false, webPreferences: { contextIsolation: true } });
|
w = new BrowserWindow({ show: false });
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO(jkleinsc) fix this flaky test on linux
|
// TODO(jkleinsc) fix this flaky test on linux
|
||||||
|
@ -301,7 +351,7 @@ describe('webFrameMain module', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can find each frame from navigation events', async () => {
|
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
|
// frame-with-frame-container.html, frame-with-frame.html, frame.html
|
||||||
const didFrameFinishLoad = emittedNTimes(w.webContents, 'did-frame-finish-load', 3);
|
const didFrameFinishLoad = emittedNTimes(w.webContents, 'did-frame-finish-load', 3);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче