feat: webFrameMain.fromFrameToken (#47942)
* feat: webFrameMain.fromFrameToken Co-authored-by: Samuel Maddock <smaddock@slack-corp.com> * refactor: return null instead of undefined Co-authored-by: Samuel Maddock <smaddock@slack-corp.com> * docs: mention renderer webFrame property Co-authored-by: Samuel Maddock <smaddock@slack-corp.com> * chore: undo null->undefined in wfm.fromId api this will be updated in another pr Co-authored-by: Samuel Maddock <smaddock@slack-corp.com> --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Samuel Maddock <smaddock@slack-corp.com>
This commit is contained in:
parent
f3774d578d
commit
a7b6145f3b
5 changed files with 55 additions and 3 deletions
|
@ -66,6 +66,16 @@ These methods can be accessed from the `webFrameMain` module:
|
||||||
Returns `WebFrameMain | undefined` - A frame with the given process and routing IDs,
|
Returns `WebFrameMain | undefined` - A frame with the given process and routing IDs,
|
||||||
or `undefined` if there is no WebFrameMain associated with the given IDs.
|
or `undefined` if there is no WebFrameMain associated with the given IDs.
|
||||||
|
|
||||||
|
### `webFrameMain.fromFrameToken(processId, frameToken)`
|
||||||
|
|
||||||
|
* `processId` Integer - An `Integer` representing the internal ID of the process which owns the frame.
|
||||||
|
* `frameToken` string - A `string` token identifying the unique frame. Can also
|
||||||
|
be retrieved in the renderer process via
|
||||||
|
[`webFrame.frameToken`](web-frame.md#webframeframetoken-readonly).
|
||||||
|
|
||||||
|
Returns `WebFrameMain | null` - A frame with the given process and frame token,
|
||||||
|
or `null` if there is no WebFrameMain associated with the given IDs.
|
||||||
|
|
||||||
## Class: WebFrameMain
|
## Class: WebFrameMain
|
||||||
|
|
||||||
Process: [Main](../glossary.md#main-process)<br />
|
Process: [Main](../glossary.md#main-process)<br />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
|
import { IpcMainImpl } from '@electron/internal/browser/ipc-main-impl';
|
||||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||||
|
|
||||||
const { WebFrameMain, fromId } = process._linkedBinding('electron_browser_web_frame_main');
|
const { WebFrameMain, fromId, fromFrameToken } = process._linkedBinding('electron_browser_web_frame_main');
|
||||||
|
|
||||||
Object.defineProperty(WebFrameMain.prototype, 'ipc', {
|
Object.defineProperty(WebFrameMain.prototype, 'ipc', {
|
||||||
get () {
|
get () {
|
||||||
|
@ -43,5 +43,6 @@ WebFrameMain.prototype.postMessage = function (...args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
fromId
|
fromId,
|
||||||
|
fromFrameToken
|
||||||
};
|
};
|
||||||
|
|
|
@ -641,6 +641,31 @@ v8::Local<v8::Value> FromID(gin_helper::ErrorThrower thrower,
|
||||||
return WebFrameMain::From(thrower.isolate(), rfh).ToV8();
|
return WebFrameMain::From(thrower.isolate(), rfh).ToV8();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v8::Local<v8::Value> FromFrameToken(gin_helper::ErrorThrower thrower,
|
||||||
|
int render_process_id,
|
||||||
|
std::string render_frame_token) {
|
||||||
|
if (!electron::Browser::Get()->is_ready()) {
|
||||||
|
thrower.ThrowError("WebFrameMain is available only after app ready");
|
||||||
|
return v8::Null(thrower.isolate());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto token = base::Token::FromString(render_frame_token);
|
||||||
|
if (!token)
|
||||||
|
return v8::Null(thrower.isolate());
|
||||||
|
auto unguessable_token =
|
||||||
|
base::UnguessableToken::Deserialize(token->high(), token->low());
|
||||||
|
if (!unguessable_token)
|
||||||
|
return v8::Null(thrower.isolate());
|
||||||
|
auto frame_token = blink::LocalFrameToken(unguessable_token.value());
|
||||||
|
|
||||||
|
auto* rfh = content::RenderFrameHost::FromFrameToken(
|
||||||
|
content::GlobalRenderFrameHostToken(render_process_id, frame_token));
|
||||||
|
if (!rfh)
|
||||||
|
return v8::Null(thrower.isolate());
|
||||||
|
|
||||||
|
return WebFrameMain::From(thrower.isolate(), rfh).ToV8();
|
||||||
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> FromIdIfExists(gin_helper::ErrorThrower thrower,
|
v8::Local<v8::Value> FromIdIfExists(gin_helper::ErrorThrower thrower,
|
||||||
int render_process_id,
|
int render_process_id,
|
||||||
int render_frame_id) {
|
int render_frame_id) {
|
||||||
|
@ -677,6 +702,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||||
gin_helper::Dictionary dict{isolate, exports};
|
gin_helper::Dictionary dict{isolate, exports};
|
||||||
dict.Set("WebFrameMain", WebFrameMain::GetConstructor(isolate, context));
|
dict.Set("WebFrameMain", WebFrameMain::GetConstructor(isolate, context));
|
||||||
dict.SetMethod("fromId", &FromID);
|
dict.SetMethod("fromId", &FromID);
|
||||||
|
dict.SetMethod("fromFrameToken", &FromFrameToken);
|
||||||
dict.SetMethod("_fromIdIfExists", &FromIdIfExists);
|
dict.SetMethod("_fromIdIfExists", &FromIdIfExists);
|
||||||
dict.SetMethod("_fromFtnIdIfExists", &FromFtnIdIfExists);
|
dict.SetMethod("_fromFtnIdIfExists", &FromFtnIdIfExists);
|
||||||
}
|
}
|
||||||
|
|
|
@ -496,6 +496,19 @@ describe('webFrameMain module', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('webFrameMain.fromFrameToken', () => {
|
||||||
|
it('returns null for unknown IDs', () => {
|
||||||
|
expect(webFrameMain.fromFrameToken(0, '')).to.be.null();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can find existing frame', async () => {
|
||||||
|
const w = new BrowserWindow({ show: false });
|
||||||
|
const { mainFrame } = w.webContents;
|
||||||
|
const frame = webFrameMain.fromFrameToken(mainFrame.processId, mainFrame.frameToken);
|
||||||
|
expect(frame).to.equal(mainFrame);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('webFrameMain.collectJavaScriptCallStack', () => {
|
describe('webFrameMain.collectJavaScriptCallStack', () => {
|
||||||
let server: Server;
|
let server: Server;
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
|
4
typings/internal-ambient.d.ts
vendored
4
typings/internal-ambient.d.ts
vendored
|
@ -133,7 +133,8 @@ declare namespace NodeJS {
|
||||||
|
|
||||||
interface WebFrameMainBinding {
|
interface WebFrameMainBinding {
|
||||||
WebFrameMain: typeof Electron.WebFrameMain;
|
WebFrameMain: typeof Electron.WebFrameMain;
|
||||||
fromId(processId: number, routingId: number): Electron.WebFrameMain;
|
fromId(processId: number, routingId: number): Electron.WebFrameMain | undefined;
|
||||||
|
fromFrameToken(processId: number, frameToken: string): Electron.WebFrameMain | null;
|
||||||
_fromIdIfExists(processId: number, routingId: number): Electron.WebFrameMain | null;
|
_fromIdIfExists(processId: number, routingId: number): Electron.WebFrameMain | null;
|
||||||
_fromFtnIdIfExists(frameTreeNodeId: number): Electron.WebFrameMain | null;
|
_fromFtnIdIfExists(frameTreeNodeId: number): Electron.WebFrameMain | null;
|
||||||
}
|
}
|
||||||
|
@ -153,6 +154,7 @@ declare namespace NodeJS {
|
||||||
|
|
||||||
interface WebFrameBinding {
|
interface WebFrameBinding {
|
||||||
mainFrame: InternalWebFrame;
|
mainFrame: InternalWebFrame;
|
||||||
|
WebFrame: Electron.WebFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataPipe = {
|
type DataPipe = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue