Exchanging data between content and injected script - javascript

I am trying to have a function in an injected script which gets some paramaters and forwards them to the content script, which in turn forwards it to the background script. I have read Chrome extension - retrieving Gmail's original message, but applying that code does not work properly. I have the following code which is injected.
window.postToContentScript = function(cmd, payload) {
var obj = {"command": cmd, "data": payload};
console.error(obj);
document.dispatchEvent(new CustomEvent('MyCustomEvent', {
detail: obj,
}));
}
When called, it logs my passed parameters to the console (so that's not an issue..). In the content script, I have the following code:
document.addEventListener("MyCustomEvent", function(e) {
console.error(e);
})
I would guess that it should actually contain an object with properties command and data, however the detail property of the event is just null. I realize that one way of approaching this is to add e.g. a hidden textarea into the document, filling that and subsequently reading it from the content script. However, this hardly seems as elegant as appending details to an event..
Any thoughts?

Related

Javascript PostMessage with JSON object as data

I have to post JSON object as data using javascript PostMessage method, below is the object that I would like to post:
{
"Type" : "Login"
}
I believe this method is used to between iframe implemented inside a website, the iframe source URL is different from the parent window, how do I implement it in code?
I have this sample code I used, but I don't understand how to it work and how can I test it. Appreciate if someone can help!!
Code:
#{
string jsonParameter = Newtonsoft.Json.JsonConvert.SerializeObject("Login");
}
var jsonData = "#Html.Raw(jsonParameter)";
parent.postMessage({ "Type": jsonData }, "*");
You are correct, PostMessage is used to send messages between ifames. The code you have given in your sample is intended to be used in a child iframe and it is sending a message to the parent iframe.
In the parent iframe You also need to listen for messages coming in, for example
window.addEventListener("message", (event) => {
console.log("Received data from child iframe ", event.data);
});
Assuming you are sending a static message, the code sample you have given that sends a message to the parent iframe can also be simplified as there is no need for the c#
parent.postMessage({ "Type": ""Login }, "*");
Please also note the second parameter to PostMessage should be an expected domain instead of "*" as it prevents malicious sites from intercepting messages. I would recomend reading the mdn page for more information https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

Cannot set property of undefined -- inserting text with javascript

I am currently trying to insert some text in a specific spot at a website, http://kawowii.com , however, I keep getting error messages. These error messages seem to originate from the section I am trying to select using javascript (variables txtClasses and styleClasses). The error messages are
Uncaught TypeError: Cannot set property 'textContent' of undefined
So, the variables seem to be undefined but I don't understand why. I have looked at the other answers and still cannot determine what is wrong.
Right now, I have
window.onload = function() {
var txtClasses = document.querySelectorAll("div.coord-control.leaflet-control");
txtClasses[0].textContent = "Server: UP Location:"
}
and I tried this
window.onload = function() {
var styleClasses = document.querySelectorAll(".coord-control leaflet-control");
function insertAfter1(referenceNode, newNode) {
referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
}
var brk = document.createElement("br");
insertAfter1(styleClasses[0], brk);
var div = document.createElement("div");
var textNode = document.createTextNode("Server: UP")
div.appendChild(textNode);
insertAfter1(brk, div);
}
My end goal is to change the website, kawowii.com , such that before Location :, it reads Server: UP using javascript.
I executed document.querySelectorAll("div.coord-control.leaflet-control"); on the website you provided, and it does in fact show an array with that element.
I think div.coord-control.leaflet-control is being inserted dynamically (perhaps after an AJAX request completes).
Therefore, you need to put your controlling logic inside the callback of the request:
whateverRequestIsInsertingThatElement.then(function() {
var txtClasses = document.querySelectorAll("div.coord-control.leaflet-control");
txtClasses[0].textContent = "Server: UP Location:"
});
I don't know if you're using promises or if the async method you're using provides a callback, but onload will happen in parallel with your async request, so you need to query for the dynamic element in the callback of the async request.
Not sure which API you're using to generate the map on your website, but usually any calls for location data will happen asynchronously (like the Google Maps API, for example). You can only manipulate dynamically generated DOM elements once the data has arrived.
Edit
You can see that the client is initially getting the configuration data from the route up/configuration. I would suggest looking for where that async call is being made in your source code, and then call querySelectorAll in its success handler.
I also see that in some of your sources, $.ajax is being called, so I assume somewhere in there, $.ajax is being called to the up/configuration route on your server.
So what I imagine happening is this:
You are querying your page for a your leaflet control but its returning an array of nothing. So when you try and access txtClasses[0] its undefined (since txtClasses.length == 0).
// this illustrates your problem
try {
// I am manually creating an empty array (your results)
var txtClasses = []
// this throws the error
txtClasses[0].bad = "throws an error";
} catch (e) {
// this just displays the error for you to see
document.getElementById("log").innerHTML += e.toString()
}
<div id="log"></div>
If you are expecting something back, you should check your selector is actually working (what I like to do is open up a web console and type my code right in there).
I noticed your selector changed in the first and second example too so make sure you read more about css selectors here.

Firefox extension interacting with the DOM

May be my logic is wrong but I'm trying to send and receive datas between my extension and the content.
So I start with something like this to send data from my content to my extension :
var images_elements = [];
tabs.activeTab.attach({
contentScript: "postMessage(document.getElementsByTagName('img'));",
onMessage: function (message) {
images_elements = message;
}
});
Obviously, it doesn't work.
How can I do something like this ? And How can I did it in the other way, example make something on this elements after making a require("sdk/request").Request and replace them in the content.
You can send data, but the API accept only data that is JSON-serializable value.
DOM nodes are not in that category, that's why it doesn't work.

How to override variable parameter loaded from another script

I have a script that loads the code dynamically. It is kind of a search engine. When I press a search button, the action gets triggered and a new page opens with many parameters.
I want to override one of the parameters generated with the script in the new URL. JS code is quite big and hard to read, but I have found the important part in the Firebug DOM editor.
This is the pattern of the URL generated when you perform the search:
http://www.example.com/...?ParameterOne=123&ParameterTwo=Two&ThisParameter=Sth&ParameterFour=Four...
What I want to edit is "ThisParameter" and change its value. This is the part edited in the DOM that does what I want:
Foobar = {
_options: [],
...
var options = {"ParameterOne":123,"ParameterTwo":"Two","ThisParameter":"ABC","ParameterFour":Four,...}
...
And this is the output of "ThisParameter" when you choose "Copy path" in Firebug's DOM tab:
_options[0].ThisParameter
I am wondering it this is possible at all. What makes me think that it is, is the fact that I can change this parameter in Firebug and it works perfectly. So, if Firebug can edit it, there should be a way to influence it with another script.
Looking forward to any suggestions, thank you in advance!
Since you cannot edit the dynamic script you have the following options:
You have to try to give the script the correct input and hope it uses your value.
Add a script to the results page which will read the url and arguments, change it and redirect, as we discussed here. (If you put everything in functions it should not conflict with the dynamic script if the functions are uniquely named.)
You could try adding something like this jQuery code to the page with the search button:
$('input[name=search_button_name]').click(function(e) {
e.preventDefault();
var form_search = $('#search_form_id');
$('<input>').attr({
type: 'hidden',
name: 'ThisParameter',
value: 'SomethingElse'
}).appendTo(form_search);
f.submit();
});
You can override any js function and method, or wrap you code around it. The easiest thing would be to look at the code you get and once it gets loaded, you re-declare a method with your own functionality.
I you are trying to replace a parameter in a specific jquery request, you can even wrap around the jquerys ajax method:
var jquery_ajax = $.ajax
$.ajax = function(options){
// parse only a specific occurence
if(options.url.indexOf("example.com") > -1) {
// change the url/params object - depending on where the parameter is
options.params.ThisParameter = "My Custom value"
}
// call the original jquery ajax function
jquery_ajax(options);
}
But it would be a lot cleaner to override the method that builds the ajax request rather than the ajax request itself.
I would investigate further on the scope of the variable options (var options), is it global? i.e. if you type 'options' in the Firebug console, does it display its properties?
If so, you could then access it via your own script and change is value, e.g.
options.ThisParameter = 'my-own-value';
You might hook your script to the click event of the search button.
I hope this helps, it could be more specific maybe if you have some sample code somewhere.

document.write in jsonp callback

I am making a cross domain request using script tag hack and jsonp. In the callback function, I want to write the data received to DOM using document.write().
I know that I should use appendChild/innerHTML instead of doc.write(). My constraint is I do not have a class/id hook to the element I want to write to. I can only rely on document.write() to write "in place".
Following code is included in HTML div in a script tag.:
function request_jsonp(){
var script = document.createElement('script');
var server_path = 'http://somedomain.com/?q=querystring&callback=request_callback';
script.setAttribute('src', server_path);
document.getElementsByTagName('head')[0].appendChild(script);
console.log('data requested');
// document.write('hello world'); // this gets written
}
function request_callback(data){
console.log('data received');
document.write(data);
}
request_jsonp();
window.onload = function(){
console.log('onload fired');
}
/*
above code prints
data requested
data received
onload fired
*/
Basically document.write does not work even with a static string inside the callback function. I thought that if document.write is called before onload, it inserts text in the page as noted here JavaScript and HTML Script Tags
What is preventing the document.write() to write to DOM? Also, is there a better approach to do this?
You should note that document.write(); calls an implicit document.open();, thus, in effect, clearing everything you have had in the document so far.
It is impossible to add content to a document using document.write();. It is, however, possible to use document.write(); to write an entire document.
You have several possible solutions:
You can pass the target element as a GET parameter, as #kirilloid noted.
You can insert an IFrame object at the desired place, and use myIFrame.document.write(); to update its content.
This is basically happening because you are updating the content of a container that is the parent to your script code, and as such, is not closed yet.
Either that, or I'm entirely off track here which, let's face it, is entirely possible. ;-)

Categories

Resources