Reputation: 22121
I am trying to set the active tab Url to a form field within an Iframe that I have injected on chrome.browserAction.onClicked
.
The problem is that I cannot access the iframe
from the content script
because of security policies (Different origin of main page and iframe).
The main web page is an external page. eg. wikipedia.com
This is what I have tried so far.
content_script.js
function onExtensionMessage(request) {
if (request['iconClicked'] != undefined) {
var extensionOrigin = 'chrome-extension://' + chrome.runtime.id;
if (!location.ancestorOrigins.contains(extensionOrigin)) {
var urlvalue = location.href;
var iframe = document.createElement('iframe');
iframe.setAttribute("id", "iFrameS");
iframe.src = chrome.runtime.getURL('popup.html');
iframe.addEventListener('load', function (e) {
// Either set the value of input element in Iframe
// here or pass an event to background.js and set it from there
chrome.extension.sendRequest({'frameloaded': true});
}, false);
document.body.appendChild(iframe);
}
return;
}
}
function initContentScript() {
chrome.extension.onRequest.addListener(onExtensionMessage);
}
initContentScript();
popup.html
<form method="post">
<input id="url" type="text">
</form>
When the extension icon has been clicked, I pass a message to the content script to inject the iframe, once it is loaded, I would want to set the field value.
I have referred this link Access iframe from content script but could not find a solution.
Any help would be appreciated.
Upvotes: 1
Views: 2107
Reputation: 42054
Because you want to set a value inside your Iframe created dynamically in a webpage in Chrome and you need to do this using only javascript you need to refer to postMessage to dispatch your data from the main page to the Iframe.
Immagine your main page like:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
iframe {
background: #FFF;
border: 3px solid #000;
width: 100%;
height: 50%;
}
</style>
<script>
window.onload = function() {
document.getElementById('titleH2').textContent = 'Main page: ' + window.location.href;
var myIframe = document.getElementById('myIframe').contentWindow;
document.getElementById('btnSend').addEventListener('click', function(e) {
e.preventDefault();
var dataToSendToIframe = {
inputValue: document.getElementById('testToSend').value,
inputId: 'url'
}
// post message to the Iframe running on other domain
myIframe.postMessage(dataToSendToIframe, 'http://localhost:63342');
});
}
</script>
</head>
<body>
<h2 id="titleH2">Main page:</h2>
<p>
<input id="testToSend" type="text">
</p>
<p>
<button id="btnSend">Send Message</button>
</p>
<iframe id="myIframe" src="http://localhost:63342/Projects/StackOverflow/z.html">
<p>Your browser does not support iframes.</p>
</body>
</html>
In this page you see an Iframe pointing to a different domain so you cannot act directly on the content inside for security reasons (refers to CORS). Using the postMessage you can send data to your Iframe simply:
myIframe.postMessage(dataToSendToIframe, 'http://localhost:63342');
On the other side, the Iframe (because you can controll it) must contain or be like to:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
</style>
<script>
window.onload = function() {
document.getElementById('titleH1').textContent = 'Iframe on different domain: ' + window.location.href;
var inputUrl = document.getElementById('url');
function receiveMessage(e) {
var origin = e.origin || e.originalEvent.origin;
// verify the message arrive from the right origin, if not reject
if (e.origin !== "http://localhost:33232")
return;
document.getElementById(e.data.inputId).value = e.data.inputValue;
}
window.addEventListener('message', receiveMessage);
}
</script>
</head>
<body>
<h1 id="titleH1">Iframe on different domain</h1>
<form method="post">
<input id="url" type="text">
</form>
</body>
</html>
In the Iframe you can see the listener for incoming messages:
function receiveMessage(e) {
You, in the listener, have to use the domain/origin to controll if accept or not the incoming message.
In the following a snapshot (from main page I write something in the input field and press the button and so a postmessage sends this data to the iframe running on a different domain setting the input field):
Upvotes: 1
Reputation: 2231
Dealing with IFrames and Content Script is not an easy task. There isn't a very official and good way to do it.
When I have to do some action in a particular IFrame and not eventual other loaded IFrame, I put a condition at the begining of the Injected Content Script.
if(_.contains(window.location.href, "myIframePage.html")) runOnIframe()
function runOnIframe()
{
// Do what you want
}
This way the runOnIframe
function will only run on the iframe that is loading myIframePage.html
Let a page with tow IFrames. The first one load http://google.com/
and the second one chrome.runtime.getURL('popup.html')
(your IFrame of course).
The page popup.html
contains an <input id="myInput" name="myInput">
.
To be able to modify the value of this input from the background script, you have to send a message to correct iframe. Chrome API doesn't allow (until future updates) to send a message to a spécifique IFrame in a page.
The trick is to do that in your injected Content Script :
contentScript.js
if(_contains(window.location.href, "myIframePage.html")) runOnIframe
function runOnIframe()
{
chrome.extension.onRequest.addListener(onExtensionMessage);
}
function onExtensionMessage(request)
{
if(request.destination !== "iframe.popup.html") return
document.getElementById("myInput").value = request.value
}
And in your background page, you simply have to send the object :
{
destination : "iframe.popup.html",
value : "Some value to put in the input"
}
The content of the destination can be what you want, it's only to recognize for who you have sent the message. This way you can send message to diferent iframe in the same page by changing this field.
Upvotes: 0
Reputation: 1563
if you need to pass simple data to your newly created iFrame, you can use query string in src of your iFrame.
when creating your iFrame:
var winLoc = window.location.href; //I think this is what you want to send to your iFrame and populate field value
iframe.src = chrome.runtime.getURL('popup.html?'+winLoc );
in your iFrame script split url:
var activeUrl = location.href.split('?')[1];
//activeUrl now contains passed data
this way you can concatenate as many "simple" data as you like
Upvotes: 2