Page 1 of 2

How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Thu Mar 19, 2020 2:04 am
by coater
when the mode of a shadow-root is closed, I cannot use element.shadowroot to visit elements in it.
Is it possible to visit them?

Keen for your help,Thank you!

----------
<input name="UserName" type="text" maxlength="64" id="UserName" #shadow-root (user-agent)<div pseudo="-webkit-input-placeholder" id="placeholder" </div>
---------
x=document.getElementById("UserName");
x.shadowRoot
[null]
even I use this:
procedure TIinformSearchFrm.Chromium1BeforeResourceLoad(Sender: TObject;
const browser: ICefBrowser; const frame: ICefFrame;
const request: ICefRequest; const callback: ICefRequestCallback;
out Result: TCefReturnValue);
begin

browser.MainFrame.ExecuteJavaScript('Element.prototype._attachShadow = Element.prototype.attachShadow;'
+ 'Element.prototype.attachShadow = function () {'
+ ' return this._attachShadow( { mode: "open" } );'
+ '};',browser.MainFrame.Url, 0 );

----It still not work! May because that it use the old shadow DOM standard?

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Thu Mar 19, 2020 9:39 am
by salvadordf
As far as I know it's not possible to access the Shadow DOM when it's closed. Read this for more information :

https://stackoverflow.com/questions/399 ... ation-mode

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Thu Mar 19, 2020 1:36 pm
by coater
is it possible to use visitdom to visit shadow root?
As we can see shadow root in developtools. How developtools works?

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Thu Mar 19, 2020 1:40 pm
by salvadordf
I don't know. I've never tried that.

Try the DOMVIsitor demo with your web page.

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Fri Mar 20, 2020 2:13 am
by coater
-------------it cannot obtain:
procedure DOMVisitor_OnDocAvailable(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument);
var
msg: ICefProcessMessage;
aEle: ICefDomNode;
aNodeStr: string;

aEle := document.GetElementById('UserName');//got it
if Assigned(aEle) then
if (aEle.Document.Document.AsMarkup <> '') then //true
aNodeStr := aEle.Document.Document.AsMarkup //no problem, but no shadowroot text
else aNodeStr := 'none' ;
---------
How devtool show user defined shadowroot if we checked 'show user agent shadow dom'?

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Fri Mar 20, 2020 10:40 am
by salvadordf
We only have methods to show and hide the DevTools. All the DevTools contents are generated internally in Chromium.

If the DevTools show the information you need perhaps you can use the DevTools protocol to extract it :
https://www.briskbard.com/forum/viewtop ... 992&p=4370

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Sat Mar 21, 2020 6:51 am
by coater
Thank you very much!
I found: when I choose element in a shadowroot in devtools, I can right click it, and then click 'store as global variable', I can obtain it in console(variable name is as 'temp1').
1. Now the problem is that how can I locate the element in shadowroot and then run 'store as global variable' command.
2. How can I enable this option(Elements->show user agent shadow DOM) in devtools automatically?


---------marked
https://magpcss.org/ceforum/viewtopic.php?f=6&t=11952
https://github.com/chromium/chromium/bl ... onfig.json
https://github.com/chromium/chromium/bl ... l-1.3.json :
{
"name": "getNodeForLocation",
"parameters": [
{ "name": "x", "type": "integer", "description": "X coordinate." },
{ "name": "y", "type": "integer", "description": "Y coordinate." },
{ "name": "includeUserAgentShadowDOM", "type": "boolean", "optional": true, "description": "False to skip to the nearest non-UA shadow root ancestor (default: false)." }
],
"returns": [
{ "name": "nodeId", "$ref": "NodeId", "description": "Id of the node at given coordinates." }
],
"description": "Returns node id at given location.",
"experimental": true
},
{
"name": "performSearch",
"parameters": [
{ "name": "query", "type": "string", "description": "Plain text or query selector or XPath search query." },
{ "name": "includeUserAgentShadowDOM", "type": "boolean", "optional": true, "description": "True to search in user agent shadow DOM." }
],
"returns": [
{ "name": "searchId", "type": "string", "description": "Unique search session identifier." },
{ "name": "resultCount", "type": "integer", "description": "Number of search results." }
],
"description": "Searches for a given string in the DOM tree. Use <code>getSearchResults</code> to access search results or <code>cancelSearch</code> to end this search session.",
"experimental": true
},

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Tue Mar 24, 2020 1:25 pm
by coater
I got it! :lol: :lol: :lol:
if you want get msg many times you can define aWebSocket outof the function to save time.
var amsg = JSON.stringify({
id: 0,
method: "DOM.enable"
});
x = AnsySocketSendReceiv('ws://localhost:1091/devtools/page/E30203CF7402C090C620DFEC7A9DEFEC' , amsg,0,2000 )

var amsg =JSON.stringify({
id: 1,
method: "DOM.getDocument",//{ "name": "pierce", "type": "boolean", "optional": true, "description": "Whether or not iframes and shadow roots should be traversed when returning the subtree (default is false)." }
params: {depth:-1, pierce: true}// { "name": "depth", "type": "integer", "optional": true, "description": "The maximum depth at which children should be retrieved, defaults to 1. Use -1 for the entire subtree or provide an integer larger than 0." },
});
AnsySocketSendReceiv('ws://localhost:1091/devtools/page/E30203CF7402C090C620DFEC7A9DEFEC' , amsg,1,2000 )
console.log(arecievedMsg );
//----------------------------------->
//ref: RECODA001 : jingyan.baidu.com/article/3c48dd342691aaa10be358fd.html
[code]
var arecievedMsg = '';
function AnsySocketSendReceiv(url, amsg, amsgID, aTimeOut){
if (typeof(aWebSocket) == "undefined") {var aWebSocket;};
//var url = 'ws://localhost:1091/devtools/page/E30203CF7402C090C620DFEC7A9DEFEC';

function ReceiveMessage(){
return new Promise((resolve) => {
aWebSocket.onmessage = function(e) {
try {

if ( (typeof(amsgID)!="undefined" && amsgID==(JSON.parse(e.data)).id) || typeof(amsgID) =="undefined" )
{
arecmessage = JSON.parse(e.data);
resolve(arecmessage );
}
}
catch(err) {
console.log(err.message);
}
};
} );
}

function ReceiveMessageWithTimeout(time){
return new Promise((resolve) => {
aWebSocket.onmessage = function(e) {
try {
if ( (typeof(amsgID)!="undefined" && amsgID==(JSON.parse(e.data)).id) || typeof(amsgID) =="undefined" )
{
resolve(JSON.parse(e.data));
}
}
catch(err) {
console.log(err.message);
}
};
setTimeout(function(){
resolve("received msg timeout ");
}, time)
} )
}


async function SendMessage(msg){
if ("WebSocket" in window )
{
if (typeof(aWebSocket) == "undefined" || !aWebSocket.constructor.toString().includes("function WebSocket()") )
{
aWebSocket = new WebSocket(url);
}
} else
{
alert("This browser does not support WebSocket");
return;
}
aWebSocket.onerror = function(e)
{
console.log("e")
}
aWebSocket.onclose = function(e)
{
console.log("connection closed ");
aWebSocket.close();
}
await new Promise((resolve) =>
{
aWebSocket.onopen = function(){
aWebSocket.send(msg);
resolve();
}
});
}


async function MessageSendReceive(){
var arecmessage;
SendMessage(amsg);
arecmessage = await ReceiveMessage();
arecievedMsg = arecmessage;
//console.log(arecmessage);
return arecmessage ;
console.log("Message recieved");
}

async function MessageSendReceivewithTime(atime){
var arecmessage;
SendMessage(amsg);
arecmessage = await ReceiveMessageWithTimeout(atime);
arecievedMsg = arecmessage;
console.log(arecievedMsg );
return arecmessage ;
console.log("Message recieved");
}

if (typeof(aTimeOut ) =="undefined" )
{
adata = MessageSendReceive();
}
else
{
if (aTimeOut.constructor.toString().includes("function Number()") )
{
adata = MessageSendReceivewithTime(aTimeOut);
} else {alert('please check out aTimeOut')}
}

return arecievedMsg;
}
[/code]

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Tue Mar 24, 2020 1:30 pm
by coater
//first DELPHI: GlobalCEFApp.RemoteDebuggingPort := 1091; // http://localhost:1091
//run cef4 browser,visit a web
//open another browser(marked as vistbrowser), visit: http://localhost:1091 toobtain PageID: such as:E30203CF7402C090C620DFEC7A9DEFEC
//visit: http://localhost:1091/devtools/inspecto ... EC7A9DEFEC
//you can open developer tools in browser, click network, you can see such: ws://localhost:1091/devtools/page/E30203CF7402C090C620DFEC7A9DEFEC
// in the list in network page, you can operate in vistbrowser then you can find much message sending and accepting,
//So,you can find something useful!!

Re: How to access a shadow-root( associated mode is "closed"? or using the old shadow DOM standard ?)

Posted: Tue Mar 24, 2020 7:01 pm
by shobits1
coater wrote: Tue Mar 24, 2020 1:30 pm //first DELPHI: GlobalCEFApp.RemoteDebuggingPort := 1091; // http://localhost:1091
//run cef4 browser,visit a web
//open another browser(marked as vistbrowser), visit: http://localhost:1091 toobtain PageID: such as:E30203CF7402C090C620DFEC7A9DEFEC
//visit: http://localhost:1091/devtools/inspecto ... EC7A9DEFEC
//you can open developer tools in browser, click network, you can see such: ws://localhost:1091/devtools/page/E30203CF7402C090C620DFEC7A9DEFEC
// in the list in network page, you can operate in vistbrowser then you can find much message sending and accepting,
//So,you can find something useful!!
in short you are using Chrome DevTools Protocol

https://chromedevtools.github.io/devtools-protocol/
https://github.com/aslushnikov/getting-started-with-cdp