Closed ilanc closed 7 years ago
Just use
var myframe=document.querySelector('#<frameId>');
var findme=myframe.contentDocument.querySelector.querySelector('#findme');
Thanks @anuraagvaidya! This works:
document.querySelector('iframe').contentDocument.querySelector('#findme')
That works as long as it doesn't violate the SOP (as in your prototype). The general solution is to pass the proper contextId
to Runtime.evaluate
. You can keep track of execution contexts with the Runtime.executionContextCreated event.
Please let me know if this solves your issue/answers your questions. :)
Yup all resolved - many thanks for pointing that out.
@cyrus-and I can't seem to find a way to actually execute JavaScript in any attached frames and getFrameTree doesn't seem to regularly report what I would expect (no childFrames).
Expected:
[addScriptToEvaluateOnNewDocument] in frame for url https://output.jsbin.com/guwojab
[Runtime.evaluate] in frame for url https://output.jsbin.com/guwojab
[addScriptToEvaluateOnNewDocument] in frame for url https://example.com
[Runtime.evaluate] in frame for url https://example.com
Actual:
[addScriptToEvaluateOnNewDocument] in frame for url https://output.jsbin.com/guwojab
[Runtime.evaluate] in frame for url https://output.jsbin.com/guwojab
Versions:
├─┬ chrome-launcher@0.10.5
├─┬ chrome-remote-interface@0.26.1
I'm sure I'm missing something obvious, any help you can give would be great. The script below should be sufficient to reproduce, it requests https://output.jsbin.com/guwojab which includes an iframe for https://example.com.
const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');
(async function () {
const chrome = await chromeLauncher.launch({
chromeFlags: [
'--window-size=1024,762',
'--user-data-dir=/tmp/foobar',
'--enable-logging',
'--auto-open-devtools-for-tabs'
]
});
const protocol = await CDP({ port: chrome.port });
const { Page, Runtime } = protocol;
await Promise.all([Page.enable(), Runtime.enable()]);
Runtime.consoleAPICalled(({ args, type }) => console[type].apply(console, args.map(a => a.value)));
Page.navigate({ url: 'https://output.jsbin.com/guwojab' });
await Page.addScriptToEvaluateOnNewDocument({
source: `console.log('[addScriptToEvaluateOnNewDocument] in frame for url ' + document.URL);`
});
Runtime.executionContextCreated(async evt => {
await Runtime.evaluate({
contextId: evt.context.id,
expression: `console.log('[Runtime.evaluate] in frame for url ' + document.URL);`
});
})
Page.loadEventFired(async evt => {
const tree = await Page.getFrameTree();
console.log(tree);
});
})();
@jsoverson It's possible that chrome is using Site Isolation aka OOPIF (out of process iframes) for this jsbin iframe. In that case, the iframe is a brand new target.
Hypothetically you can disable OOPIF with -disable-features=IsolateOrigins,site-per-process
but I haven't verified this still works. If you can easily disable it, then the child frames should exist as you expect.
Thanks @paulirish, --disable-features=IsolateOrigins,site-per-process
gives me the behavior I was expecting. I was banging my head against that for quite a long time, a warning or notice on Page.getFrameTree()
may be worthwhile in order to save people the headache in the future.
Thanks again 🙂
In the event that Chrome is using this feature, how does DevTools access these multiple frame contexts? Can we perform that same operation using chrome-remote-interface somehow?
@lachesis you can see the protocol messages used by DevTools by inspecting the inspector.
Hi Andrea, I'd like to be able to access elements contained within an iframe. It doesn't look like this is possible using chrome-remote-interface atm however it is possible using selenium/chromedriver, and of course within chrome it's possible to change the frame in the devtools.
My questions are:
I put together a prototype to demonstrate how you can find elements inside an iframe using selenium/chromedriver (nb python implementation):
The code does the following:
document.querySelector('#findme').innerText
)I've started looking into the chromedriver source but have not yet figured out what they're doing:
ExecuteSwitchToFrame
SwitchToSubFrame