Obtain DOM Node from CefContextMenuParams

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Obtain DOM Node from CefContextMenuParams

Postby mattdol » Fri May 25, 2018 2:07 pm

Hello,

I'm working on a problem where I want to right-click an element (node), and then select a context menu item that will send some information about that element via JSAPI request to the program that my CEF browser is embedded in (which is written in JavaScript).

Currently I am capturing and sending (via a JSAPI request) node information in OnFocusedNodeChanged, saving that data in my JS code as my "focused node", and then sending a JSAPI request from OnContextMenuCommand that acts as a trigger to do some action on the node information that's saved in the JS code.

This approach leaves a lot of room for things to get messed up, and I'm sending far more JSAPI requests than are necessary (since I don't need to do this right-click action on every element), so I'm wondering if there is a way to acquire a DOM Node from the CefContextMenuParams object, or any other parameter of any of the CefContextMenuHandler methods, so that I can obtain the node information and send it only when I need to from one of the CefContextMenuHandler methods.

While looking through the methods of CefContextMenuParams I noticed that many of the method descriptions contain the phrase "node that the context menu was invoked on". However, it does not appear that there is a method that will actually return the node itself. Is there a way to obtain the "node that the context menu was invoked on", and if not, can a new method be added to CefContextMenuParams that returns the node?

Thanks!
mattdol
Newbie
 
Posts: 6
Joined: Fri Jan 27, 2017 4:46 pm

Re: Obtain DOM Node from CefContextMenuParams

Postby magreenblatt » Fri May 25, 2018 3:08 pm

What node information specifically are you seeking? The node exists in the renderer process and the context menu is created in the browser process so any additional information would need to be included in the Chromium IPC or sent as a separate IPC like you're doing currently. You may find it easier to just create the context menu using JavaScript.
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: Obtain DOM Node from CefContextMenuParams

Postby mattdol » Fri May 25, 2018 3:26 pm

The information I want is basic node attribute stuff, like name, id, value, etc. My main concern is that I only want to be reading node attributes and sending JSAPI request when it's necessary, i.e. when I've right-clicked my context menu option to gather and send data about the selected node. I think I will attempt to implement the CefDOMVisitor interface, access it via the 'frame' parameter of OnContextMenuCommand, and use it to obtain the DOM Document and then the focused DOM Node, which I can then gather attributes from. If this doesn't work out I suppose I will look into handling the context menu in JS instead of with CEF.
mattdol
Newbie
 
Posts: 6
Joined: Fri Jan 27, 2017 4:46 pm

Re: Obtain DOM Node from CefContextMenuParams

Postby magreenblatt » Fri May 25, 2018 3:50 pm

It won't work. CefDom classes are only available in the renderer process.
magreenblatt
Site Admin
 
Posts: 12408
Joined: Fri May 29, 2009 6:57 pm

Re: Obtain DOM Node from CefContextMenuParams

Postby mattdol » Tue Jun 12, 2018 4:08 pm

Revisiting this post to share my solution for anyone else who happens upon this thread looking for a way to obtain the currently selected DOM node from the right-click context menu:

Prerequisites: Implementation of the CefDOMVisitor interface (including GenerateNodeData method listed below), familiarity with CEF IPC and messages.

1. From CefContextMenuHandler::OnContextMenuCommand call browser->SendProcessMessage(PID_RENDERER, msg).

2. In CefRenderProcessHandler::OnProcessMessageReceived, obtain the currently focused frame with browser->GetFocusedFrame(), initialize a CefDOMVisitor, and call the custom CefDOMVisitor method GenerateNodeData with the focused frame as an argument. This method will set the currently focused frame as the _focusedFrame member variable of your CefDOMVisitor class and then call VisitDOM.

Code: Select all
void CefDOMVisitor::GenerateNodeData(CefRefPtr<CefFrame> frame) {
    _focusedFrame = frame;
    _focusedFrame->VisitDOM(this);
}


3. CefDOMVisitor::Visit gets hit, inside of which you call document->GetFocusedNode() to get the currently focused (right-clicked) node.

4. Once you've gathered all the node data you need, use _focusedFrame->GetBrowser()->SendProcessMessage to send your node data to CefClient::OnProcessMessageReceived. Now the data of the currently right-clicked node is available in the browser process.
mattdol
Newbie
 
Posts: 6
Joined: Fri Jan 27, 2017 4:46 pm

Re: Obtain DOM Node from CefContextMenuParams

Postby ndesktop » Wed Jun 13, 2018 12:39 am

FocusedNode might not work in 100% of the cases. I'm not really sure about that, but in my experience focus and active element are not the same.

For focused element, one hint would be CefRenderProcessHandler::OnFocusedNodeChanged which might keep a map such as
focus_elements[(browser, frame)] = CefDOMNode (might need maintenance using OnBrowserDestroyed, though).

One might also try the CefContextMenuHandler::OnContextMenuCommand taking browser+frame+command ID (obviously), as well as event flags and CefContextMenuParams and coordinates.
CefContextMenuParams X,Y - relative to the render view - can also help in determine the DOM node (although CEF probably does not expose a document.elementFromPoint(x, y);). Most likely DevTools and "Inspect Element" command will give you the key.
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 78 guests