diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 292266a53c51..72484093a570 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -651,6 +651,7 @@ Returns: * `params` Object * `x` Integer - x coordinate. * `y` Integer - y coordinate. + * `frame` WebFrameMain - Frame from which the context menu was invoked. * `linkURL` String - URL of the link that encloses the node the context menu was invoked on. * `linkText` String - Text associated with the link. May be an empty diff --git a/shell/browser/api/electron_api_web_contents.cc b/shell/browser/api/electron_api_web_contents.cc index 8246637e1271..1686544d2b9b 100644 --- a/shell/browser/api/electron_api_web_contents.cc +++ b/shell/browser/api/electron_api_web_contents.cc @@ -1287,7 +1287,7 @@ void WebContents::RendererResponsive( bool WebContents::HandleContextMenu(content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { - Emit("context-menu", std::make_pair(params, web_contents())); + Emit("context-menu", std::make_pair(params, render_frame_host)); return true; } diff --git a/shell/common/gin_converters/content_converter.cc b/shell/common/gin_converters/content_converter.cc index a9979d7f599c..78062b3a49a6 100644 --- a/shell/common/gin_converters/content_converter.cc +++ b/shell/common/gin_converters/content_converter.cc @@ -13,6 +13,7 @@ #include "shell/browser/web_contents_permission_helper.h" #include "shell/common/gin_converters/blink_converter.h" #include "shell/common/gin_converters/callback_converter.h" +#include "shell/common/gin_converters/frame_converter.h" #include "shell/common/gin_converters/gfx_converter.h" #include "shell/common/gin_converters/gurl_converter.h" #include "shell/common/gin_helper/dictionary.h" @@ -73,11 +74,13 @@ v8::Local Converter::ToV8( } // static -v8::Local Converter::ToV8( +v8::Local Converter::ToV8( v8::Isolate* isolate, - const ContextMenuParamsWithWebContents& val) { + const ContextMenuParamsWithRenderFrameHost& val) { const auto& params = val.first; + content::RenderFrameHost* render_frame_host = val.second; gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate); + dict.SetGetter("frame", render_frame_host); dict.Set("x", params.x); dict.Set("y", params.y); dict.Set("linkURL", params.link_url); diff --git a/shell/common/gin_converters/content_converter.h b/shell/common/gin_converters/content_converter.h index 61f846c987f8..26621c05a8e1 100644 --- a/shell/common/gin_converters/content_converter.h +++ b/shell/common/gin_converters/content_converter.h @@ -17,11 +17,12 @@ namespace content { struct ContextMenuParams; struct NativeWebKeyboardEvent; +class RenderFrameHost; class WebContents; } // namespace content -using ContextMenuParamsWithWebContents = - std::pair; +using ContextMenuParamsWithRenderFrameHost = + std::pair; namespace gin { @@ -32,9 +33,10 @@ struct Converter { }; template <> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - const ContextMenuParamsWithWebContents& val); +struct Converter { + static v8::Local ToV8( + v8::Isolate* isolate, + const ContextMenuParamsWithRenderFrameHost& val); }; template <> diff --git a/spec-main/api-web-contents-spec.ts b/spec-main/api-web-contents-spec.ts index 771abfc7c7e6..2de7273c0649 100644 --- a/spec-main/api-web-contents-spec.ts +++ b/spec-main/api-web-contents-spec.ts @@ -2056,6 +2056,28 @@ describe('webContents module', () => { }); }); + describe('context-menu event', () => { + afterEach(closeAllWindows); + it('emits when right-clicked in page', async () => { + const w = new BrowserWindow({ show: false }); + await w.loadFile(path.join(fixturesPath, 'pages', 'base-page.html')); + + const promise = emittedOnce(w.webContents, 'context-menu'); + + // Simulate right-click to create context-menu event. + const opts = { x: 0, y: 0, button: 'right' as any }; + w.webContents.sendInputEvent({ ...opts, type: 'mouseDown' }); + w.webContents.sendInputEvent({ ...opts, type: 'mouseUp' }); + + const [, params] = await promise; + + expect(params.pageURL).to.equal(w.webContents.getURL()); + expect(params.frame).to.be.an('object'); + expect(params.x).to.be.a('number'); + expect(params.y).to.be.a('number'); + }); + }); + it('emits a cancelable event before creating a child webcontents', async () => { const w = new BrowserWindow({ show: false,