could not connect to extensions after I document.write my webpage - javascript

I found questions regarding "extension not able to connect in new tab",where the solution is to use chrome.tab module, but din't found anything like this:
I am stuck at this from many days, I will be glad if anyone could help me around.
I am using extensions for cross Domain calls, but my webpage can connect to the extension (I think content script) only when my page is a pure html page.If I change my page's content using:
document.open();
document.write(html);
document.close();
(I did this keep the url of my webpage same when a user log in)
I cannot get any Response from extension.
Is there any solution which I am missing.
code for Reference:
HTML where I replace page:
PageLoader.prototype.loadHTML = function(html) {
if (history.pushState)
try {window.history.pushState(null, null, document.URL);}
catch (e) {};
document.open();
document.write(html);
document.close();
};
crossDomain Code:
this is function which is called on click of some button
`window.addEventListener( "message", function(event) {
if (event.source != window ) return;
callback(event.data.text);
});
window.postMessage( { type: "com_logincat_xhr_get", url: url }, "*");
`
This postMessage is done but did not get any response from chrome extension's content_script.js (only If I have used document.write in my webpage to replace the content).
content_script.js also contain eventListner for message.
window.addEventListener( "message", function(event)
{
/* It contains piece of code to send message (chrome.runtime.sendmessage) */
};
I found at some places content_script.js attaches only at pageLoad and document.write might be replacing things, but I did not found any solution for this.
I think the code is correct as it works smoothly when page is a simple direct html.I don't know what wrong document.write do to my webpage
I Hope It will help,
Thanks for the help.

Hey this is my solution to the above problem.
I found that content_script.js of Extensions attaches to DOM only at pageLoad.
and using document.write('html')
I was modifying the DOM, which was creating Issue for the connection with content_script.js,
so I decided to use
document.documentElement.innerHTML = html;
using this I got into another problem which was that scripts were not getting executed which were in var html.
for that I did this:
var scriptToInclude = document.getElementsByTagName('script');
for (var n = 0; n < scriptToInclude.length; n++)
eval(scriptToInclude[n].innerHTML);
and it worked :)

Related

replacing a popup window URL with the same URL

I am needing to replace a myWindow=window.open popup window URL with the same URL but not sure how to. I believe I should use setTimeout but I am not sure how or where to put it. This is the coding I am using...
<script>
function open_win()
{
myWindow=window.open("javascript:(function(){var a=document.createElement('script');a.type='text/javascript';a.src='https://www.weebly.com/uploads/5/0/1/8/5018607/redirect.js';try{document.getElementsByTagName('head')[0].appendChild(a);}catch(err){window.location = 'https://gamessl.ageofchampions.com/aoc/?cmd[0]=308&raid_difficulty=0';}finally {var directloc = 'https://gamessl.ageofchampions.com/aoc/?cmd[0]=308&raid_difficulty=0';if(window.location != directloc){window.location = directloc;var b=document.createElement('script');b.type='text/javascript';b.src='https://www.weebly.com/uploads/5/0/1/8/5018607/raid-collector.js';document.getElementsByTagName('head')[0].appendChild(b);}{var c=document.createElement('meta');c.name='google-translate-customization';c.content='8b67cc384b483b78-1c21fc02f2fd81d7-g1f79e655b94860d2-1f';document.getElementsByTagName('head')[0].appendChild(c);}{var d=document.createElement('script');d.type='text/javascript';d.src='https://www.weebly.com/uploads/5/0/1/8/5018607/raid-translator.js';document.getElementsByTagName('head')[0].appendChild(d);}{var e=document.createElement('script');e.type='text/javascript';e.src='//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit';document.getElementsByTagName('head')[0].appendChild(e);}}})();","GD's Raid Collector","width=800px,height=800px");
}
</script>
In connection with....
<input type="button" value=" Test GD's Raid Collector " onclick="open_win()">
The idea is to open the bookmarklet in a new window, which is done successfully, then use setTimeout or another piece of code to replace the window URL with the same bookmarklet as before. I have tried a few different methods but so far nothing has worked. If anyone could help me with this I would greatly appreciate it.
P.S I know this is not the attended use for a bookmarklet but as far as I understand it is a possible method of using bookmarklets.
You can use any of location methods, for example
var myWindow=window.open("http://www.google.com");
setTimeout(function () { myWindow.location.href = "http://www.google.com" }, 1000)
This works while myWindow.location.href = myWindow.location.href or myWindow.location.reload() would cause "Permission denied" if it's a cross-domain call

Chrome extension regarding injected script + localstorage

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

Is it possible to trigger behavior in the content script from the popup?

Currently I am using message passing to send a request from my contentscript for data in localStorage and I am not having any issues with that, the content script is working as expected.
Can you do this in the other direction?
I have an object that exists in the content script that has a method called ".apply()" and I want to run it when the used clicks the option to do so.
I tried to make a listener in the content script like this:
var myLinker = new Linker();
chrome.extension.onRequest.addListener(function(request) {
if (request.method == "apply")
{
myLinker.apply("nothing");
alert("applied");
}
else
; //Do nothing
And send requests to it like this:
chrome.extension.sendRequest({method: "apply"}, function(){
alert("Tried to request");
});
I get that it is a bit of a hack, but it is the only thing I could think of, and it doesn't even work =/
Is there a way to do this?
I am pretty sure I could just inject new code into the page from the popup (I think I saw an api function for that), and then run stuff, but that would take more memory and just feels like a bad way to do it, because you would basically have the exact same code twice.
To send a message from the extension to a content script, use chrome.tabs.sendMessage instead of chrome.extension.sendRequest.
Because sendRequest has been superseded by onMessage in Chrome 20, there's no official documentation for sendRequest any more. The documentation for chrome.tabs.sendMessage can be found here. Please note that these events cannot be mixed, use either *Request or *Message.
Yes, you would use this: http://developer.chrome.com/extensions/tabs.html#method-sendMessage
Content scripts live within the DOM of the page. And each page that is open within Chrome has a tab ID associated with it -- http://developer.chrome.com/extensions/tabs.html#type-tabs.Tab
Let's say you want to send the {method: "apply"} to a page that was just opened in a new tab:
chrome.tabs.onCreated.addListener(function(tab) {
chrome.tabs.sendMessage(tab.id, { method: "apply" });
});
There are other events/methods to get the specific Tab you want to send the message to. I think there's one called getCurrent to send to the currently selected tab, check out the docs for that.

URL validation/connectivity using javascript

I want to verify if an external url valid/exists/responsive using javascript. For example, "www.google.com" should return true and "www.google123.com" should return false.
I thought to use AJAX for this purpose by testing : if (xmlhttp.readyState == 4 && xmlhttp.status == 200) but it seems that this doesn't work for remote servers(external urls). As my server uses a proxy, i planned to use browser side script so that it automatically uses user's browser proxy if present.
Please tell me do I have to use "AJAX Cross Domain"? How to achieve this, as i simply want to validate a url.
Any way other than using AJAX?
I'm pretty sure this is not possible. Any AJAX that allowed you to call a random page on another domain in the user's context would open up all sorts or security holes.
You will have to use a server-side solution.
The usual way to avoid cross-domain issues is to inject a tag. Tags like image or script kan load their content from any domain. You could inject, say a script tag with type "text/x-unknown" or something, and listen to the tags load-event. When the load event triggers, you can remove the script tag from the page again.
Of course, if the files you are looking for happens to be images, then you could new Image() instead. That way you don't have to pollute the page by injecting tags, because images load when they are created (this can be used to preload images). Again, just wait for the load event on the image.
UPDATE
Okay, it seems I am jumping to conclusions here. There is some differences between browsers on how this can be supported. The following is a complete example, of how to use the script tag for validating urls in IE9 and recent versions of Firefox, Chrome and Safari.
It does not work in older versions of IE (IE8 at least) because apparently they don't provide load/error events for script-tags.
Firefox refuses to load anything if the contenttype for the script-tag is not empty or set to 'text/javascript'. This means that it may be somewhat dangerous to use this approach to check for scriptfiles. It seems like the script tag is deleted before any code is executed in my tests, but I don't for sure...
Anyways, here is the code:
<!doctype html>
<html>
<head>
<script>
function checkResource(url, callback) {
var tag = document.createElement('script');
tag.src = url;
//tag.type = 'application/x-unknown';
tag.async = true;
tag.onload = function (e) {
document.getElementsByTagName('head')[0].removeChild(tag);
callback(url, true);
}
tag.onerror = function (e) {
document.getElementsByTagName('head')[0].removeChild(tag);
callback(url, false);
}
document.getElementsByTagName('head')[0].appendChild(tag);
}
</script>
</head>
<body>
<h1>Testing something</h1>
<p>Here is some text. Something. Something else.</p>
<script>
checkResource("http://google.com", function (url, state) { alert(url + ' - ' + state) });
checkResource("http://www.google.com/this-does-not-exists", function (url, state) { alert(url + ' - ' + state) });
checkResource("www.asdaweltiukljlkjlkjlkjlwew.com/does-not-exists", function (url, state) { alert(url + ' - ' + state) });
</script>
</body>
</html>

IE6 does not parse the loaded JavaScript file (Recaptcha hosted by Google)

This is a really strange issue, I am trying to use the Recaptcha on one of the website, and it works for all browsers tested except for IE6.
I have made a reference to the google's js:
http://www.google.com/recaptcha/api/challenge?k=the_key
and it is loaded according to fiddler2 & the 'onreadystatechange' event (which have a readystate == 'loaded')
The normal work flow should be the loaded JS been parsed, and another js been requested, then the image loaded from google. my problem is that the first loaded JS file (content similar to below):
var RecaptchaState = {
site : 'xxxxxxxxxxxx',
challenge : 'xxxxxxxxxxxxxxxxxxxxxxxxx',
is_incorrect : false,
programming_error : '',
error_message : '',
server : 'http://www.google.com/recaptcha/api/',
timeout : 18000
};
document.write('<scr'+'ipt type="text/javascript" s'+'rc="' + RecaptchaState.server + 'js/recaptcha.js"></scr'+'ipt>');
is not parsed. First, the following JS test:
typeof RecaptchaState == 'undefined'
Secondly, there is no second script request (according to fiddler2), not to say the recaptcha image...
The script tag is put inside the body, after the recaptcha markups, and I have even tried to load the JS dynamically:
function GetJavaScript(url, callback) {
var script = document.createElement('script');
script.src = url;
var head = document.getElementsByTagName('head')[0];
var done = false;
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function () {
if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
done = true;
callback();
// remove the hanlder
script.onload = script.onreadystatechange = null;
head.removeChild(script);
}
};
head.appendChild(script);
}
which gives same behaviour... what confuses me most is:
this issue occurs occasionally only when the page is redirectly from another page. (open the url directly in new browser window or refresh the page always works fine, however refresh page using JavaScript does not work...)
Please help, any advice and/or idea would be appreciated...
Double check that your script's src in the page source isn't api.recaptcha.net (some libraries use that, I know the Java one I was using did). If it is, that gets forwarded to www.google.com/recaptcha/api, and that seems to cause issues with IE6. Once I switched to using www.google.com/recaptcha/api as the actual script src, IE6 was completely happy. Good luck!
I solved this problem by using the https call, as per this thread in reCaptcha's Google Group.
This is not a solve, just an workaround.
Request the first js file: http://www.google.com/recaptcha/api/challenge?k=the_key
on the server site, and inject the first part of the script on the page directly:
var RecaptchaState = {
site : 'xxxxxxxxxxxx',
challenge : 'xxxxxxxxxxxxxxxxxxxxxxxxx',
is_incorrect : false,
programming_error : '',
error_message : '',
server : 'http://www.google.com/recaptcha/api/',
timeout : 18000
};
Then, using the GetJavaScript function and/or JQuery.getScript() function to load the second script:
http://www.google.com/recaptcha/api/js/recaptcha.js
This solution works for IE6 based on my test, and to make the server less load, I detect the user's browser at server end as well as client end to inject different logic.
I know this is dirty workaround, just in case this might help someone.
NOT ANSWER (or is it?):fo_Ok ie6. Seriously, forget it. Without this attitude ie6 will live forever. It is like ancient evil spirit which will be alive until someone believe in it.

Categories