Chrome Devpanel Extension Communicating with Background Page - google-chrome

I have an extension to the chrome devtools panel. I can send messages to the page using chrome.devtools.inspectedWindow.eval ... but how do I receive messages in the dev panel? Specifically, I need my devpanel to hook into events that happen on the page. I can't get it to listen to events on my content script, nor the background page.
I've tried chrome.extension.sendMessage in the content script, along with chrome.extension.onMessage.addListener in the dev panel script. But sendMessage complains with Port error: Could not establish connection. Receiving end does not exist.
The issue persists with long-lived connections:
In content script or background page:
var port = chrome.extension.connect({name: "test"});
port.postMessage({msg: "testing"});
In dev tools panel javascript:
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
// never gets here
});
});
How can I listen for events that are triggered in my content script-- in my dev tool panel? A diagram like this from Firefox's Add-On SDK would be great: https://addons.mozilla.org/en-US/developers/docs/sdk/latest/static-files/media/content-scripting-overview.png

The goal is to create a channel ("port") for communication. It does not matter how the port is created, as long as the connection is correctly maintained.
The devtools script has to initiate the port, because the background script does not know when a devtools panel is created.
Here's a basic example, which shows a bidirectional communication method:
devtools.js
chrome.devtools.panels.create('Test', '/icon.png', '/panel.html', function(extensionPanel) {
var _window; // Going to hold the reference to panel.html's `window`
var data = [];
var port = chrome.runtime.connect({name: 'devtools'});
port.onMessage.addListener(function(msg) {
// Write information to the panel, if exists.
// If we don't have a panel reference (yet), queue the data.
if (_window) {
_window.do_something(msg);
} else {
data.push(msg);
}
});
extensionPanel.onShown.addListener(function tmp(panelWindow) {
extensionPanel.onShown.removeListener(tmp); // Run once only
_window = panelWindow;
// Release queued data
var msg;
while (msg = data.shift())
_window.do_something(msg);
// Just to show that it's easy to talk to pass a message back:
_window.respond = function(msg) {
port.postMessage(msg);
};
});
});
Now, the panel is capable of sending/receiving messages over a port. The panel's script (external script file, because of the CSP) may look like:
panel.js
function do_something(msg) {
document.body.textContent += '\n' + msg; // Stupid example, PoC
}
document.documentElement.onclick = function() {
// No need to check for the existence of `respond`, because
// the panel can only be clicked when it's visible...
respond('Another stupid example!');
};
Now, the background page's script:
background.js
var ports = [];
chrome.runtime.onConnect.addListener(function(port) {
if (port.name !== "devtools") return;
ports.push(port);
// Remove port when destroyed (eg when devtools instance is closed)
port.onDisconnect.addListener(function() {
var i = ports.indexOf(port);
if (i !== -1) ports.splice(i, 1);
});
port.onMessage.addListener(function(msg) {
// Received message from devtools. Do something:
console.log('Received message from devtools page', msg);
});
});
// Function to send a message to all devtools.html views:
function notifyDevtools(msg) {
ports.forEach(function(port) {
port.postMessage(msg);
});
}
To test, simply run notifyDevtools('Foo'); on the background page (e.g. via the console). In this demo, the message will be sent to all devtools. Upon receipt, the devtools panel will contain the received message.
Put the extension together using:
manifest.json
{
"name": "Test",
"manifest_version": 2,
"version": "1",
"devtools_page": "devtools.html",
"background":{"scripts":["background.js"]}
}
panel.html
<script src="panel.js"></script> <!-- Doctype etc not added for conciseness-->
devtools.html
<script src="devtools.js"></script>
See also
How to modify content under a devtools panel in a Chrome extension?
chrome.devtools API
Message passing: Long-lived connections
Content Security Policy in Chrome extensions ("Inline JavaScript (...) will not be executed. This restriction bans both inline <script> blocks and inline event handlers.")

Related

Can a website detect extensions that are installed using Developed Mode? [duplicate]

I am in the process of building a Chrome extension, and for the whole thing to work the way I would like it to, I need an external JavaScript script to be able to detect if a user has my extension installed.
For example: A user installs my plugin, then goes to a website with my script on it. The website detects that my extension is installed and updates the page accordingly.
Is this possible?
Chrome now has the ability to send messages from the website to the extension.
So in the extension background.js (content.js will not work) add something like:
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
if (request) {
if (request.message) {
if (request.message == "version") {
sendResponse({version: 1.0});
}
}
}
return true;
});
This will then let you make a call from the website:
var hasExtension = false;
chrome.runtime.sendMessage(extensionId, { message: "version" },
function (reply) {
if (reply) {
if (reply.version) {
if (reply.version >= requiredVersion) {
hasExtension = true;
}
}
}
else {
hasExtension = false;
}
});
You can then check the hasExtension variable. The only drawback is the call is asynchronous, so you have to work around that somehow.
Edit:
As mentioned below, you'll need to add an entry to the manifest.json listing the domains that can message your addon. Eg:
"externally_connectable": {
"matches": ["*://localhost/*", "*://your.domain.com/*"]
},
2021 Update:
chrome.runtime.sendMessage will throw the following exception in console if the extension isn't installed or it's disabled.
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist
To fix this, add this validation inside the sendMessage callback
if (chrome.runtime.lastError) {
// handle error
}
I am sure there is a direct way (calling functions on your extension directly, or by using the JS classes for extensions), but an indirect method (until something better comes along):
Have your Chrome extension look for a specific DIV or other element on your page, with a very specific ID.
For example:
<div id="ExtensionCheck_JamesEggersAwesomeExtension"></div>
Do a getElementById and set the innerHTML to the version number of your extension or something. You can then read the contents of that client-side.
Again though, you should use a direct method if there is one available.
EDIT: Direct method found!!
Use the connection methods found here: https://developer.chrome.com/extensions/extension#global-events
Untested, but you should be able to do...
var myPort=chrome.extension.connect('yourextensionid_qwerqweroijwefoijwef', some_object_to_send_on_connect);
Another method is to expose a web-accessible resource, though this will allow any website to test if your extension is installed.
Suppose your extension's ID is aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, and you add a file (say, a transparent pixel image) as test.png in your extension's files.
Then, you expose this file to the web pages with web_accessible_resources manifest key:
"web_accessible_resources": [
"test.png"
],
In your web page, you can try to load this file by its full URL (in an <img> tag, via XHR, or in any other way):
chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.png
If the file loads, then the extension is installed. If there's an error while loading this file, then the extension is not installed.
// Code from https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/8ArcsWMBaM4/2GKwVOZm1qMJ
function detectExtension(extensionId, callback) {
var img;
img = new Image();
img.src = "chrome-extension://" + extensionId + "/test.png";
img.onload = function() {
callback(true);
};
img.onerror = function() {
callback(false);
};
}
Of note: if there is an error while loading this file, said network stack error will appear in the console with no possibility to silence it. When Chromecast used this method, it caused quite a bit of controversy because of this; with the eventual very ugly solution of simply blacklisting very specific errors from Dev Tools altogether by the Chrome team.
Important note: this method will not work in Firefox WebExtensions. Web-accessible resources inherently expose the extension to fingerprinting, since the URL is predictable by knowing the ID. Firefox decided to close that hole by assigning an instance-specific random URL to web accessible resources:
The files will then be available using a URL like:
moz-extension://<random-UUID>/<path/to/resource>
This UUID is randomly generated for every browser instance and is not your extension's ID. This prevents websites from fingerprinting the extensions a user has installed.
However, while the extension can use runtime.getURL() to obtain this address, you can't hard-code it in your website.
I thought I would share my research on this.
I needed to be able to detect if a specific extension was installed for some file:/// links to work.
I came across this article here
This explained a method of getting the manifest.json of an extension.
I adjusted the code a bit and came up with:
function Ext_Detect_NotInstalled(ExtName, ExtID) {
console.log(ExtName + ' Not Installed');
if (divAnnounce.innerHTML != '')
divAnnounce.innerHTML = divAnnounce.innerHTML + "<BR>"
divAnnounce.innerHTML = divAnnounce.innerHTML + 'Page needs ' + ExtName + ' Extension -- to intall the LocalLinks extension click here';
}
function Ext_Detect_Installed(ExtName, ExtID) {
console.log(ExtName + ' Installed');
}
var Ext_Detect = function (ExtName, ExtID) {
var s = document.createElement('script');
s.onload = function () { Ext_Detect_Installed(ExtName, ExtID); };
s.onerror = function () { Ext_Detect_NotInstalled(ExtName, ExtID); };
s.src = 'chrome-extension://' + ExtID + '/manifest.json';
document.body.appendChild(s);
}
var is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;
if (is_chrome == true) {
window.onload = function () { Ext_Detect('LocalLinks', 'jllpkdkcdjndhggodimiphkghogcpida'); };
}
With this you should be able to use Ext_Detect(ExtensionName,ExtensionID) to detect the installation of any number of extensions.
Another possible solution if you own the website is to use inline installation.
if (chrome.app.isInstalled) {
// extension is installed.
}
I know this an old question but this way was introduced in Chrome 15 and so I thought Id list it for anyone only now looking for an answer.
Here is an other modern approach:
const checkExtension = (id, src, callback) => {
let e = new Image()
e.src = 'chrome-extension://'+ id +'/'+ src
e.onload = () => callback(1), e.onerror = () => callback(0)
}
// "src" must be included to "web_accessible_resources" in manifest.json
checkExtension('gighmmpiobklfepjocnamgkkbiglidom', 'icons/icon24.png', (ok) => {
console.log('AdBlock: %s', ok ? 'installed' : 'not installed')
})
checkExtension('bhlhnicpbhignbdhedgjhgdocnmhomnp', 'images/checkmark-icon.png', (ok) => {
console.log('ColorZilla: %s', ok ? 'installed' : 'not installed')
})
I used the cookie method:
In my manifest.js file I included a content script that only runs on my site:
"content_scripts": [
{
"matches": [
"*://*.mysite.co/*"
],
"js": ["js/mysite.js"],
"run_at": "document_idle"
}
],
in my js/mysite.js I have one line:
document.cookie = "extension_downloaded=True";
and in my index.html page I look for that cookie.
if (document.cookie.indexOf('extension_downloaded') != -1){
document.getElementById('install-btn').style.display = 'none';
}
You could have the extension set a cookie and have your websites JavaScript check if that cookie is present and update accordingly. This and probably most other methods mentioned here could of course be cirvumvented by the user, unless you try and have the extension create custom cookies depending on timestamps etc, and have your application analyze them server side to see if it really is a user with the extension or someone pretending to have it by modifying his cookies.
There's another method shown at this Google Groups post. In short, you could try detecting whether the extension icon loads successfully. This may be helpful if the extension you're checking for isn't your own.
Webpage interacts with extension through background script.
manifest.json:
"background": {
"scripts": ["background.js"],
"persistent": true
},
"externally_connectable": {
"matches": ["*://(domain.ext)/*"]
},
background.js:
chrome.runtime.onMessageExternal.addListener(function(msg, sender, sendResponse) {
if ((msg.action == "id") && (msg.value == id))
{
sendResponse({id : id});
}
});
page.html:
<script>
var id = "some_ext_id";
chrome.runtime.sendMessage(id, {action: "id", value : id}, function(response) {
if(response && (response.id == id)) //extension installed
{
console.log(response);
}
else //extension not installed
{
console.log("Please consider installig extension");
}
});
</script>
Your extension could interact with the website (e.g. changing variables) and your website could detect this.
But there should be a better way to do this. I wonder how Google is doing it on their extension gallery (already installed applications are marked).
Edit:
The gallery use the chrome.management.get function. Example:
chrome.management.get("mblbciejcodpealifnhfjbdlkedplodp", function(a){console.log(a);});
But you can only access the method from pages with the right permissions.
A lot of the answers here so far are Chrome only or incur an HTTP overhead penalty. The solution that we are using is a little different:
1. Add a new object to the manifest content_scripts list like so:
{
"matches": ["https://www.yoursite.com/*"],
"js": [
"install_notifier.js"
],
"run_at": "document_idle"
}
This will allow the code in install_notifier.js to run on that site (if you didn't already have permissions there).
2. Send a message to every site in the manifest key above.
Add something like this to install_notifier.js (note that this is using a closure to keep the variables from being global, but that's not strictly necessary):
// Dispatch a message to every URL that's in the manifest to say that the extension is
// installed. This allows webpages to take action based on the presence of the
// extension and its version. This is only allowed for a small whitelist of
// domains defined in the manifest.
(function () {
let currentVersion = chrome.runtime.getManifest().version;
window.postMessage({
sender: "my-extension",
message_name: "version",
message: currentVersion
}, "*");
})();
Your message could say anything, but it's useful to send the version so you know what you're dealing with. Then...
3. On your website, listen for that message.
Add this to your website somewhere:
window.addEventListener("message", function (event) {
if (event.source == window &&
event.data.sender &&
event.data.sender === "my-extension" &&
event.data.message_name &&
event.data.message_name === "version") {
console.log("Got the message");
}
});
This works in Firefox and Chrome, and doesn't incur HTTP overhead or manipulate the page.
You could also use a cross-browser method what I have used.
Uses the concept of adding a div.
in your content script (whenever the script loads, it should do this)
if ((window.location.href).includes('*myurl/urlregex*')) {
$('html').addClass('ifextension');
}
in your website you assert something like,
if (!($('html').hasClass('ifextension')){}
And throw appropriate message.
If you have control over the Chrome extension, you can try what I did:
// Inside Chrome extension
var div = document.createElement('div');
div.setAttribute('id', 'myapp-extension-installed-div');
document.getElementsByTagName('body')[0].appendChild(div);
And then:
// On web page that needs to detect extension
if ($('#myapp-extension-installed-div').length) {
}
It feels a little hacky, but I couldn't get the other methods to work, and I worry about Chrome changing its API here. It's doubtful this method will stop working any time soon.
If you're trying to detect any extension from any website,
This post helped: https://ide.hey.network/post/5c3b6c7aa7af38479accc0c7
Basically, the solution would be to simply try to get a specific file (manifest.json or an image) from the extension by specifying its path. Here's what I used. Definitely working:
const imgExists = function(_f, _cb) {
const __i = new Image();
__i.onload = function() {
if (typeof _cb === 'function') {
_cb(true);
}
}
__i.onerror = function() {
if (typeof _cb === 'function') {
_cb(false);
}
}
__i.src = _f;
__i = null;
});
try {
imgExists("chrome-extension://${CHROME_XT_ID}/xt_content/assets/logo.png", function(_test) {
console.log(_test ? 'chrome extension installed !' : 'chrome extension not installed..');
ifrm.xt_chrome = _test;
// use that information
});
} catch (e) {
console.log('ERROR', e)
}
Here is how you can detect a specific Extension installed and show a warning message.
First you need to open the manifest file of the extension by going to chrome-extension://extension_id_here_hkdppipefbchgpohn/manifest.json and look for any file name within "web_accessible_resources" section.
<div class="chromewarning" style="display:none">
<script type="text/javascript">
$.get("chrome-extension://extension_id_here_hkdppipefbchgpohn/filename_found_in_ web_accessible_resources.png").done(function () {
$(".chromewarning").show();
}).fail(function () {
// alert("failed.");
});
</script>
<p>We have detected a browser extension that conflicts with learning modules in this course.</p>
</div>
Chrome Extension Manifest v3:
const isFirefox = chrome.runtime.OnInstalledReason.CHROME_UPDATE != "chrome_update";
For FireFox, I believe chrome.runtime.OnInstalledReason.BROWSER_UPDATE will be "browser_update": https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/OnInstalledReason

how to show the notification on certain websites extension page action

I'm developing an extension page action that works on certain websites I want to add a notification whenever the user visits the website specific i'm not satisfied just with the icon in the address bar, how do the notification appears when the user accesses the specific site ?
I have these codes
background, to show the icon in specific sites in the address bar
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (~tab.url.indexOf('specificsite.com.br')) {
chrome.pageAction.show(tabId);
}
});
Code for notification
createNotification();
audioNotification();
function audioNotification(){
var yourSound = new Audio('alert.mp3');
yourSound.play();
}
function createNotification(){
var opt = {type: "basic",title: "Your Title",message: "Your message",iconUrl: "128.png"}
chrome.notifications.create("notificationName",opt,function(){});
//include this line if you want to clear the notification after 5 seconds
setTimeout(function(){chrome.notifications.clear("notificationName",function(){});},10000);
}
You can use message passing to get it done by content scripts to detect the switch on certain websites, then notify the background page in order to display the notification for that page. Your content script should send a message using chrome.runtime.sendMessage, and the background page should listen using chrome.runtime.onMessage.addListener:
I created the sample code and tested it works with me:
Content script(myscript.js):
if(onCertainWebsitesNeedNotificationAppearTrue) {
// send message to background script
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
});
}
Background page:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
//alert("good");
if (request.greeting == "hello")
createNotification();
});
function createNotification(){
var opt = {type: "basic",title: "Your Title",message: "Your message",iconUrl: "128.png"}
chrome.notifications.create("notificationName",opt,function(){});
//include this line if you want to clear the notification after 5 seconds
setTimeout(function(){chrome.notifications.clear("notificationName",function(){});},10000);
}
Also keep in mind to register your content script's code and permissions in manifest like:
"permissions": ["notifications"],
"content_scripts": [
{
"matches": ["http://www.certainwebsiteone.com/*", "http://certainwebsitetwo.com/*"],
"js": ["myscript.js"]
}
]

How can I pass data between two Chrome apps?

I have created two Chrome apps and I want to pass some data (string format) from one Chrome app to another Chrome app. Appreciate if someone can help me with showing the correct way of doing this?
It's an RTFM question.
From Messaging documentation (note that it mentions extensions, but it works for apps):
In addition to sending messages between different components in your extension, you can use the messaging API to communicate with other extensions. This lets you expose a public API that other extensions can take advantage of.
You need to send messages using chrome.runtime.sendMessage (using app ID) and receive them using chrome.runtime.onMessageExternal event. If required, long-lived connections can also be established.
// App 1
var app2id = "abcdefghijklmnoabcdefhijklmnoab2";
chrome.runtime.onMessageExternal.addListener(
// This should fire even if the app is not running, as long as it is
// included in the event page (background script)
function(request, sender, sendResponse) {
if(sender.id == app2id && request.data) {
// Use data passed
// Pass an answer with sendResponse() if needed
}
}
);
// App 2
var app1id = "abcdefghijklmnoabcdefhijklmnoab1";
chrome.runtime.sendMessage(app1id, {data: /* some data */},
function(response) {
if(response) {
// Installed and responded
} else {
// Could not connect; not installed
// Maybe inspect chrome.runtime.lastError
}
}
);

Chromecast Launch, what's with the DIAL parameters? Aren't I runing MY application, not some registered standard?

The following code displays a proper list of available chromecast devices on my network. But when I click on the links, the application never launches. There are a couple of things that I'm quite confused about that may or may not be related to this question:
If I'm making my own custom application, what's with the DIAL parameters and why do I have to pass them? I don't want to write an app for the DIAL standard... this is MY app.
Again related to the DIAL parameters, if I search for devices with any other query other than "YouTube" (a DIAL parameter), the list always comes up blank. I suppose I shouldn't care, as long as the device is listed... but again... the app won't launch.
It should be noted that my sender app is a chrome webpage.
I'm a bit confused as to where my "appid" goes int he launch parameters,'
<html data-cast-api-enabled="true">
<body>
hi!<BR/>
<script>
var cast_api, cv_activity;
if (window.cast && window.cast.isAvailable) {
// Cast is known to be available
initializeApi();
} else {
// Wait for API to post a message to us
window.addEventListener("message", function(event) {
if (event.source == window && event.data &&
event.data.source == "CastApi" &&
event.data.event == "Hello")
{
//document.write("Initialize via message.<br/>");
initializeApi();
//document.write("Api initialized via message.");
};
});
};
initializeApi = function() {
cast_api = new cast.Api();
cast_api.addReceiverListener("YouTube", onReceiverList);
};
var g_list;
onReceiverList = function(list) {
g_list = list;
// If the list is non-empty, show a widget with
// the friendly names of receivers.
// When a receiver is picked, invoke doLaunch with the receiver.
document.write("Receivers: "+list.length+"<br/>");
var t;
for(t=0;t<list.length;t++)
document.write('found:'+list[t].name+' ' +list[t].id+'<br/>');
};
onLaunch = function(activity) {
if (activity.status == "running") {
cv_activity = activity;
// update UI to reflect that the receiver has received the
// launch command and should start video playback.
} else if (activity.status == "error") {
cv_activity = null;
}
};
function launchy(idx)
{
doLaunch(g_list[idx]);
}
doLaunch = function(receiver) {
var request = new window.cast.LaunchRequest(">>>>>what REALLY goes here?<<<<<<< ", receiver);
request.parameters = "v=abcdefg";
request.description = new window.cast.LaunchDescription();
request.description.text = "My Cat Video";
request.description.url = "http://my.website.get.your.own/chomecast/test.php";
cast_api.launch(request, onLaunch);
};
stopPlayback = function() {
if (cv_activity) {
cast_api.stopActivity(cv_activity.activityId);
}
};
</script>
</body>
</html>
The part marked "what really goes here?" is the part that I THINK is wrong... I couldn't be completely wrong. My device is white listed, I have an appid (which I thought might go in that slot)... The documentation merely says ActivityType DIAL Parmeters are valid, mandatory.
The first argument to the LaunchRequest is your App ID, the one that you have received in an email as part of whitelisting process. Also, the "YouTube" in the initialize method should also be replaced with the same App ID.
I strongly suggest you look at the sample that is on GitHub for chrome sender to see how you can send a request to load a media on a cast device.

access iframe content from a chrome's extension content script

I'm doing a plugin to do some transformations to the interface. I keep getting unsafe javascript attempt to access frame with url.... Domains, protocols and ports must match (typical cross site issue)
But being an extension it should have access to the iframe's content http://code.google.com/chrome/extensions/content_scripts.html ...
Doesn anyone know how to access it's contents so they can be capturable?
There's generally no direct way of accessing a different-origin window object. If you want to securely communicate between content scripts in different frames, you have to send a message to the background page which in turn sends the message back to the tab.
Here is an example:
Part of manifest.json:
"background": {"scripts":["bg.js"]},
"content_scripts": [
{"js": ["main.js"], "matches": ["<all_urls>"]},
{"js": ["sub.js"], "matches": ["<all_urls>"], "all_frames":true}
]
main.js:
var isTop = true;
chrome.runtime.onMessage.addListener(function(details) {
alert('Message from frame: ' + details.data);
});
sub.js:
if (!window.isTop) { // true or undefined
// do something...
var data = 'test';
// Send message to top frame, for example:
chrome.runtime.sendMessage({sendBack:true, data:data});
}
Background script 'bg.js':
chrome.runtime.onMessage.addListener(function(message, sender) {
if (message.sendBack) {
chrome.tabs.sendMessage(sender.tab.id, message.data);
}
});
An alternative method is to use chrome.tabs.executeScript in bg.js to trigger a function in the main content script.
Relevant documentation
Message passing c.runtime.sendMessage / c.tabs.sendMessage / c.runtime.onMessage
MessageSender and Tab types.
Content scripts
chrome.tabs.executeScript
I understand that this is an old question but I recently spent half a day in order to solve it.
Usually creating of a iframe looks something like that:
var iframe = document.createElement('iframe');
iframe.src = chrome.extension.getURL('iframe-content-page.html');
This frame will have different origin with a page and you will not be able to obtain its DOM. But if you create iframe just for css isolation you can do this in another way:
var iframe = document.createElement('iframe');
document.getElementById("iframe-parent").appendChild(iframe);
iframe.contentDocument.write(getFrameHtml('html/iframe-content-page.html'));
.......
function getFrameHtml(htmlFileName) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", chrome.extension.getURL(html/htmlFileName), false);
xmlhttp.send();
return xmlhttp.responseText;
}
.......
"web_accessible_resources": [
"html/htmlFileName.html",
"styles/*",
"fonts/*"
]
After that you can use iframe.contentDocument to access to iframe's DOM