I can access a Chrome App Webview HTML with:
webview.executeScript(
{code: 'document.documentElement.innerHTML'},
function(results) {
// results[0] would have the webview's innerHTML.
});
But I would like to get the value of global variables in the Guest like so:
webview.executeScript(
{code: 'window.globalVar'},
function(results) {
// results[0] should have the webview's value of "globalVar".
});
How can I do this?
I can access a Chrome App Webview HTML with:
webview.executeScript(
{code: 'document.documentElement.innerHTML'},
function(results) {
// results[0] would have the webview's innerHTML.
});
But I would like to get the value of global variables in the Guest like so:
webview.executeScript(
{code: 'window.globalVar'},
function(results) {
// results[0] should have the webview's value of "globalVar".
});
How can I do this?
window
objects of the page and the content script are isolated. It does not matter whether it's a webview. But you can access the "real" window
by injecting a page-level script.
– Xan
Commented
Nov 10, 2014 at 22:48
An answer to summarize the steps required.
1) You inject a content script with webview.executeScript()
into the embedded page.
2) Since the page's real window
is isolated, you need a page-level script to access it. You inject it with a <script>
tag as discussed here.
3) The page-level script can access the window
object, but cannot talk to the app script. However, it can fire a custom DOM event, that the content script can catch. Discussed here.
4) Finally, from the content script you need to send a message to your app script. The content script calls chrome.runtime.sendMessage
, while the app script listens with chrome.runtime.onMessage
.chrome.runtime.sendMessage
does not seem to be available to webview content scripts injected with webview.executeScript()
. A workaround is to use postMessage
as described here.
It's a bit of an onion structure, that's why you need 2 steps "in" and 2 steps "out". You can't really do it in the return value that's passed to the executeScript
callback, since at least one of the "out" steps will be asynchronous.
You can inject a script that inserts a DOM node with the global variable's value. Then you return that node's innerHTML and you have your value right away without using a callback:
var code = "script = document.createElement('script'); script.text=\"var n=document.createElement('span');n.style.display='none';n.id='my-id';n.innerHTML=window.globalVar;document.body.appendChild(n)\"; document.head.appendChild(script);document.getElementById('my-id').innerHTML"
webview.executeScript(
{code: code},
function(results) {
console.log(results[0]);
});
Just use an ID for the DOM node that is not used and you should be fine. It works for me.