This is my example code to print esternal window location after 5sec:
<SCRIPT TYPE="text/javascript">
function Loaded()
{
var newPage=window.open('http://externaldomainurl','myWindow');
newPage.focus();
setTimeout(function(){urlCheck(newPage)}, 5000);
}
function urlCheck(newPage)
{
alert(newPage.location)
newPage.close();
}
</SCRIPT>
TEST
But nothing appear on alert.
Tnks
Access to data on other origins is restricted for security reasons. You can't monitor where a user has browsed to after they leave your site.
You can use postMessage and addEventListener('message', listener) to pass messages between the two origins if you are able to edit the code for both of them.
Related
I simply have to access an object that is a variable on the page that I am running my content script on from my Chrome Extension.
I know about the environments and their isolated worlds in which the content scripts and injected scripts run and that it's possible to get some variables using the injected scripts and then send them back.
I have searched for other answers regarding this question and most work for other type of variables and are the basic way of doing it but none currently work for accessing objects.
Any current solutions or workarounds?
EDIT: The solution that I used:
Content script:
//Sends an object from the page to the background page as a string
window.addEventListener("message", function(message) {
if (message.data.from == "myCS") {
chrome.runtime.sendMessage({
siteObject: message.data.prop
});
}
});
var myScript = document.createElement("script");
myScript.innerHTML = 'window.postMessage({from: "myCS", prop: JSON.stringify(OBJECT)},"*");';
document.body.appendChild(myScript);
Background.js:
//Info receiver
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
//When the content script sends the sites object to extract the needed data
if (message.siteObject !== undefined) {
console.log(message.siteObject);
//Process the data
}
});
You can try to inject a script tag in the page to access the object. If needed, you could use messaging to communicate with your extension. For example, assuming the object you want to access in your page is called pageObject:
content1.js
//this code will add a new property to the page's object
var myOwnData = "createdFromContentScript";
var myScript = document.createElement("script");
myScript.innerHTML = "pageObject.myOwnData = " + myOwnData;
document.body.appendChild(myScript);
content2.js
//this code will read a property from the existing object and send it to background page
window.addEventListener("message", function(message) {
if (message.data.from == "myCS") {
chrome.runtime.sendMessage({theProperty: message.data.prop});
}
});
var myScript = document.createElement("script");
myScript.innerHTML = 'window.postMessage({from: "myCS", prop: pageObject.existingProperty},"*");';
document.body.appendChild(myScript);
No, there is no way. There is no point having the isolated worlds for security and then there being a workaround whereby an extension can hack the content script and variables if it really needs to.
Presumably the object on the page interacts with the page or has some effect on the page or something on the page affects the state of the variable. You can trigger actions on the page (via the DOM) that might change the state of that variable but you should stop looking for ways to access variables directly.
Of course if the page author is cooperative then it's a different ball game - a mechanism could be provided in the author's script, a getter and setter mechanism. But somehow I doubt that's what you're after.
I have a iframe on my website which points to 3rd party page (i.e. Not on my domain and I don't have any control on their server).
I want to be able to just check if their website is being loaded properly inside the iframe or not. There can be cases where -
it gets blocked by some firewall
their service is down or something.
So that I can show a proper error message inside the iframe in that case. I was hoping that I can find out the iframe's response status code somehow. How can I achieve something like this?
Try this.
<script>
function checkIframeLoaded() {
// Get a handle to the iframe element
iframe = document.getElementById('your_iframe');
var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
// Check if loading is complete
if ( iframeDoc.readyState == 'complete' ) {
iframe.contentWindow.onload = function(){
alert("I am loaded");
};
// The loading is complete, call the function we want executed once the iframe is loaded
afterLoading();
return;
}
// If we are here, it is not loaded. Set things up so we check the status again in 100 milliseconds
window.setTimeout('checkIframeLoaded();', 100);
}
function afterLoading(){
alert("I am here");
}
</script>
<body onload="checkIframeLoaded();">
I am puzzling my way through my first 'putting it all together' Chrome extension, I'll describe what I am trying to do and then how I have been going about it with some script excerpts:
I have an options.html page and an options.js script that lets the user set a url in a textfield -- this gets stored using localStorage.
function load_options() {
var repl_adurl = localStorage["repl_adurl"];
default_img.src = repl_adurl;
tf_default_ad.value = repl_adurl;
}
function save_options() {
var tf_ad = document.getElementById("tf_default_ad");
localStorage["repl_adurl"] = tf_ad.value;
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click', save_options);
});
document.addEventListener('DOMContentLoaded', load_options );
My contentscript injects a script 'myscript' into the page ( so it can have access to the img elements from the page's html )
var s = document.createElement('script');
s.src = chrome.extension.getURL("myscript.js");
console.log( s.src );
(document.head||document.documentElement).appendChild(s);
s.parentNode.removeChild(s);
myscript.js is supposed to somehow grab the local storage data and that determines how the image elements are manipulated.
I don't have any trouble grabbing the images from the html source, but I cannot seem to access the localStorage data. I realize it must have to do with the two scripts having different environments but I am unsure of how to overcome this issue -- as far as I know I need to have myscript.js injected from contentscript.js because contentscript.js doesn't have access to the html source.
Hopefully somebody here can suggest something I am missing.
Thank you, I appreciate any help you can offer!
-Andy
First of all: You do not need an injected script to access the page's DOM (<img> elements). The DOM is already available to the content script.
Content scripts cannot directly access the localStorage of the extension's process, you need to implement a communication channel between the background page and the content script in order to achieve this. Fortunately, Chrome offers a simple message passing API for this purpose.
I suggest to use the chrome.storage API instead of localStorage. The advantage of chrome.storage is that it's available to content scripts, which allows you to read/set values without a background page. Currently, your code looks quite manageable, so switching from the synchronous localStorage to the asynchronous chrome.storage API is doable.
Regardless of your choice, the content script's code has to read/write the preferences asynchronously:
// Example of preference name, used in the following two content script examples
var key = 'adurl';
// Example using message passing:
chrome.extension.sendMessage({type:'getPref',key:key}, function(result) {
// Do something with result
});
// Example using chrome.storage:
chrome.storage.local.get(key, function(items) {
var result = items[key];
// Do something with result
});
As you can see, there's hardly any difference between the two. However, to get the first to work, you also have to add more logic to the background page:
// Background page
chrome.extension.onMessage.addListener(function(message, sender, sendResponse) {
if (message.type === 'getPref') {
var result = localStorage.getItem(message.key);
sendResponse(result);
}
});
On the other hand, if you want to switch to chrome.storage, the logic in your options page has to be slightly rewritten, because the current code (using localStorage) is synchronous, while chrome.storage is asynchronous:
// Options page
function load_options() {
chrome.storage.local.get('repl_adurl', function(items) {
var repl_adurl = items.repl_adurl;
default_img.src = repl_adurl;
tf_default_ad.value = repl_adurl;
});
}
function save_options() {
var tf_ad = document.getElementById('tf_default_ad');
chrome.storage.local.set({
repl_adurl: tf_ad.value
});
}
Documentation
chrome.storage (method get, method set)
Message passing (note: this page uses chrome.runtime instead chrome.extension. For backwards-compatibility with Chrome 25-, use chrome.extension (example using both))
A simple and practical explanation of synchronous vs asynchronous ft. Chrome extensions
we have the following situation:
in default.aspx we have a link:
test.
and the JS code:
function doPost() {
$.post('AnHttpHandlerPage.aspx',"{some_data:...}", function(data) {
if(data.indexOf("http://")==0)
window.open(data);
else{
var win=window.open();
with(win.document) {
open();
write(data); //-> how to execute this HTML code? The code also includes references to other js files.
close();
}
}
}).error(function(msg){document.write(msg.responseText);});
}
The callback can first be an url address or 2nd html code that must be executed.
Option 1 fits, but in option 2, a new window will be opened where the code has been written but not executed.
It's clear, since it happens in the stream, it can't be executed. So the question, how can you fix it? Maybe a refresh(), or similar?
Because of the requirement of the customer, the workflow can not be changed, so it must be solved within doPost().
EDIT
The response in case 2 is HTML like this. This part should be executed:
<HTML><HEAD>
<SCRIPT type=text/javascript src="http://code.jquery.com/jquery-latest.js">
</SCRIPT>
<SCRIPT type=text/javascript>
$(document).ready(function() {
do_something...
});
</SCRIPT>
</HEAD>
<BODY>
<FORM>...</FORM>
</BODY>
</HTML>
Please help. Thanks.
In your JS code it should be something like this:
function doPost() {
$.post('AnHttpHandlerPage.aspx',"{some_data:...}", function(data) {
//if(data.indexOf("http://")==0)
if (data.type!="url") //i will add a data type to my returned json so i can differentiate if its url or html to show on page.
window.open(); // I dont know why this is there. You should
else{
var win=window.open(data.url); //This data.url should spit out the whole page you want in new window. If its external it would be fine. if its internal maybe you can have an Action on one of your controllers that spit it with head body js css etc.
/* with(win.document) {
open();
write(data); //-> how to execute this HTML code? The code also includes references to other js files.
close(); */ // No need to write data to new window when its all html to be rendered by browser. Why is this a requirement.
}
}
}).error(function(msg){document.write(msg.responseText);});
}
The overall logic is this
You do your ajax call on doPost
Find out if data returned is of type url or anything that need to open in new window
If it is url type it would have a url (check if this is not null or empty or even a valid url) then open a new window with that url. Have a read of W3C window.open for parameters
If you want to open and close it for some reason just do that by keeping the window handle but you can do this on dom ready event of that new window otherwise you might end up closing it before its dom is completely loaded. (someone else might have better way)
If its not url type then you do your usual stuff on this page.
If this does not make sense lets discuss.
I have a widget that contains an iframe. The user can configure the url of this iframe, but if the url could not be loaded (it does not exists or the user does not have access to internet) then the iframe should failover to a default offline page.
The question is, how can I detect if the iframe could be loaded or not? I tried subscribing to the 'load' event, and, if this event is not fired after some time then I failover, but this only works in Firefox, since IE and Chrome fires the 'load' event when the "Page Not Found" is displayed.
I found the following link via Google: http://wordpressapi.com/2010/01/28/check-iframes-loaded-completely-browser/
Don't know if it solves the 'Page Not Found' issue.
<script type="javascript">
var iframe = document.createElement("iframe");
iframe.src = "http://www.your_iframe.com/";
if (navigator.userAgent.indexOf("MSIE") > -1 && !window.opera) {
iframe.onreadystatechange = function(){
if (iframe.readyState == "complete"){
alert("Iframe is now loaded.");
}
};
} else {
iframe.onload = function(){
alert("Iframe is now loaded.");
};
}
</script>
I haven't tried it myself, so I don't know if it works. Good luck!
Nowadays the browsers have a series of security limitations that keep you away from the content of an iframe (if it isnĀ“t of your domain).
If you really need that functionality, you have to build a server page that have to work as a proxy, that receive the url as a parameter, test if it is a valid url, and does the redirect or display the error page.
If you control the content of the iframe, the iframe can send a message to the parent.
parent.postMessage('iframeIsDone', '*');
The parent callback listens for the message.
var attachFuncEvent = "message";
var attachFunc = window.addEventListener ;
if (! window.addEventListener) {
attachFunc = window.attachEvent;
attachFuncEvent = "onmessage";
}
attachFunc(attachFuncEvent, function(event) {
if (event.data == 'iframeIsDone') { // iframe is done callback here
}
});
How about checking if the url is available and only then setting the actual url of the iframe?
e.g. with JQuery
var url = "google.com"
var loading_url = "/empty.html"
document.getElementById("iframe").src = loading_url;
$.ajax({
url: url,
type: 'GET',
complete: function(e, xhr, settings){
if(e.status === 200){
document.getElementById("iframe").src = url;
}
}
});
Edit:
This does not seem to work cross domain, the status code is 0 in those cases.
If you have control over the contents of the iframe (e.g. you can add arbitrary code to the page), you can try to implement a special function in each of them, then in your page, you call that function and catch an error (via window.onerror handler) if the function called via eval fails because the page didn't load.
Here's example code: http://www.tek-tips.com/viewthread.cfm?qid=1114265&page=420
After the onload fires, you can scavenge the content of the iframe to see if it contains a usefull page or not. You'd have to make this browser specifuc unfortunately because they all display a different "page not found" message.
For more info, take a look here at http://roneiv.wordpress.com/2008/01/18/get-the-content-of-an-iframe-in-javascript-crossbrowser-solution-for-both-ie-and-firefox/