Browse Source

feat: add frame to context-menu event params (#30831)

* feat: add frame to context-menu event params

* doc: rephrase frame description
Samuel Maddock 3 years ago
parent
commit
70c534fd14

+ 1 - 0
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

+ 1 - 1
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;
 }

+ 5 - 2
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<v8::Value> Converter<blink::mojom::MenuItem::Type>::ToV8(
 }
 
 // static
-v8::Local<v8::Value> Converter<ContextMenuParamsWithWebContents>::ToV8(
+v8::Local<v8::Value> Converter<ContextMenuParamsWithRenderFrameHost>::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);

+ 7 - 5
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<content::ContextMenuParams, content::WebContents*>;
+using ContextMenuParamsWithRenderFrameHost =
+    std::pair<content::ContextMenuParams, content::RenderFrameHost*>;
 
 namespace gin {
 
@@ -32,9 +33,10 @@ struct Converter<blink::mojom::MenuItem::Type> {
 };
 
 template <>
-struct Converter<ContextMenuParamsWithWebContents> {
-  static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
-                                   const ContextMenuParamsWithWebContents& val);
+struct Converter<ContextMenuParamsWithRenderFrameHost> {
+  static v8::Local<v8::Value> ToV8(
+      v8::Isolate* isolate,
+      const ContextMenuParamsWithRenderFrameHost& val);
 };
 
 template <>

+ 22 - 0
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,