I have already written a Hello World example extension. Now I am trying to write a Chrome extension to get a certain JavaScript variable's value, if it is declared.
So let's say there is a
var test = 'a';
in the source code. I would like to get that a value.
UPDATE: I do not have access to the "original" website's code, but I know that this variable is always there, and has a certain value, always different.
An alert would do. (Can I alert, from the extension's page?)
I saw that there are things like "permission" and "tabs" and I am not sure what might I be missing.
I tried to search, found something similar, but this example just doesn't do anything when I click on the link.
From a content script, you can't have access to a variable declared on the page.
Taken from the documentation:
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page.
The only way I see is to load the script source via XHR in the background page and parse it. Then you may use message passing if you want to send the result to your content script. Note that this solution won't work if the value of the variable has been changed by a subsequent script.
If you have control over that page you could put that value into a hidden HTML element on the page which your extension can then extract with a content script.
on the website:
var test a = 'a';
document.documentElement.dataset["a"] = a;
in the extension's content script:
var a = document.documentElement.dataset["a"];
Just make sure that the content script is executed after the script on the page (e.g. by adding "run_at": "document_end"in your manifest)
Related
I finished developing and testing my HTML intake form and it is working nicely with ajax, json, and validation, and mailing. To finalize the form for production, I attempted to move the JavaScript from the HTML page to an external file and provide a link to the file in the HTML page. The js file is called formjs.js, and the link to it was placed at the bottom of the HTML page as <script src="../js/formjs.js"></script>.
The way I moved the JavaScript is cutting the scripts and pasting to the new js page and same the page and linked to it in the HTML page as mentioned above.
Upon doing so, I received tons of error messages on the js page because many of the functions are looking for information that exists on the HTML and had no idea how to get it. For example, a document. For example, this following script:
var Server_response_value_failure = document.getElementById("server_response_value_failure");
gets the following error:this variable is assigned and value but was never used.
Another example:
end of function};
at the end of each function get the error message that unnecessary semicolon.
I am not sure how to link the formjs.js file back to the HTML. Otherwise, the form works perfectly fine if I leave the script on the HTML page.
its fine, its just eslint that gives these warnings. for example, it will complain if you declare a variable and assign a value but you dont use the variable later on.
or if you call a function that you declare "later down" in the file.
I don't know if this will help, but sometimes you want to put the entire body of your javascript file in round parenthesis like this
(function(...) {
...
})();
in the end, you put another round parenthesis. This basically acts like $.ready() in jQuery.
I don't know if this will help you. You might want to rewrite your code.
The usual way of adding Javascript to a page is by adding it to the document's <body> or <head> in either static HTML or something generated server-side.
I would like to generate dynamic Javascript, and add it to the document in a dynamic fashion; that is on-demand and during run-time. For example Javascript code transmitted over a WebSocket.
One option is to create a script element, add the string with script contents to the .text property, while finally adding the script to the document, like this:
var scriptContent = 'console.log("dynamic script");';
var s = document.createElement('script');
s.text = scriptContent;
document.body.appendChild(s);
This would work, but my concern is that the script is executed with the same URL/origin as the HTML document. Whereas, if it would be a separate file, invoked with the s.src parameter, it would show up under its own URL when looking at the browser console.
Why is this at all relevant? When using the browser console to debug and inspect, it usually tells you the name of the script and the line/column of the message printed to the console. For example, when opening the console, one might several console messages, with on the right side the origin and line/column information:
<domainname>:1:1
separate_js_file.js:14:20
This is the behavior that I desire because it makes it easy to distinguish what script has written something to the console. However, if adding Javascript dynamically to the page, it all gets 'advertised' under the main document, usually printed by the domainname, like domain.com:1:1.
What I would like is to change/pretend/masquerade the origin of the script, to pretend it was an external script. This way, not all lines printed to the console would be from origin domain.com:<line>:<column> but instead would be called specifically, like module1:<line>:<column>.
Is this at all possible?
I think you can append a source map at the end of the dynamic JS.
//# sourceURL=http://example.com/path/to/your/sourcemap.map
This works when using eval statements in Firefox and in with both injected script tags and evals in chrome. Might be a way to make Firefox understand it via script tags as well.
See https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map for the details.
See also Can't see dynamically loaded code in Chrome Developer Tools 22 for some more details.
I have a existing file ajax,js in my website that makes an ajax request and creates a global JSON object, searchResult using that response. Now I am creating a Chrome plugin, that requires this JSON Object inside it. I have a content script for the plugin viz. plugin.js and I want to include the object inside plugin.js file.
When I try to log window.searchResult from within plugin.js, it shows as undefined.
but when I use browser console, it shows the value as expected.
Please help me with this.
Problem
Chrome content scripts and the page's own scripts live in isolated worlds.
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page.
Your code works in the console, since you execute it by default in the page's context. To see what the extension sees, you need to switch it.
Solution 1a
First, the generic solution (works even if you don't control the webpage)
There is a way around this, by injecting some code directly into the page's "world" (or properly called, context).
After injecting the code, your page-level script needs to communicate with the content script to pass the data. It's possible with custom DOM events (as, as you remember, DOM is shared). The page-level script sends an event with the data in the event's details.
Alternatively, you can just attach the data to some DOM node, say, an invisible <div>.
Solution 1b
Since you said it's your page, you can skip the inject-into-the-page step and have a listener ready in the page's own code.
The content script sends a custom event to request the data, and the page answers passes the data back as described in 1a.
Solution 2
In theory, you don't even need a content script.
You can use the "externally_connectable" mechanism to speak with the page directly.
Note though that the page has to initiate the conversation.
I am trying to create a Chrome extension using CrossRider and am struggling with how to create a global variable.
My extension is essentially going to dynamically append a few JavaScript files to the page if a button is clicked, and I need it to also create a global variable and set some properties.
I tried the following:
appAPI.ready(function($) {
console.log('inside crossrider extension ready()');
window.foobar = 'barfoo';
return;
});
When I refresh the page, the message inside crossrider extension ready() is printed out to the console, so I know the extension is loaded and working, but when I try executing window.foobar or foobar in the console an error is thrown saying it's undefined.
This is my first time creating an extension, so what am I missing here? Why isn't the global variable I create inside of CrossRider's appAPI.ready() function available outside of it?
I can't find a duplicate target, so I'll explain what's happening.
I don't know the Crossrider terminology, but when a Chrome extension executes code in a page, this is called a Content Script.
However, the code does not execute in the same context as the page itself. It's called an isolated world and means, among other things, that the window object is not shared.
Content scripts execute in a special environment called an isolated world. They have access to the DOM of the page they are injected into, but not to any JavaScript variables or functions created by the page. It looks to each content script as if there is no other JavaScript executing on the page it is running on. The same is true in reverse: JavaScript running on the page cannot call any functions or access any variables defined by content scripts.
So if you want to set a variable accessible to the page, you need to set it in the page context. How? There are many ways, but they all amount to inserting a <script> element into the page.
var script = document.createElement('script');
script.textContent = "window.foobar = 'barfoo';";
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
All of that assumes that you don't control the page in question. If you do, there are other ways of communicating the the page, because DOM is shared. You can, for instance, raise a custom DOM event if the page listens to it.
I'm writing a Chrome extension, in my background.html page, it is injecting a js file with this command:
chrome.tabs.executeScript(null, {file: "mod.js"});
All of the code from this file is running on the page just fine, except for one function not being defined for an onclick property.
I am changing the innerHTML of Facebook's main page, the div that contains "top news" and "most recent"
I'm inserting this html:
"<a href='#' onclick='thisIsUndefined()'>
<span class='someClass'>
Better feed
</span>
</a>"
And right in the js file that is injected, thisIsUndefined is perfectly stated as:
function thisIsUndefined () {
alert("is it working yet?");
}
I even have another function in the file that I am using, but whenever I click the link that's inserted, the I get an error saying that it's undefined.
Exact error:
Uncaught ReferenceError: thisIsUndefined is not defined
Here's the whole file for reference:
http://texthmu.com/Devin/HMU%20ext/mod.js
Could you recommend any keywords like 'global' or 'var' that could fix the definition?
Scripts on the page and content scripts are isolated. They interact with the same DOM, but not directly with each other's variables. When you add onclick, it's going to look for that function in the site's scripts. The best way to do it would be to use document.createElement and then use onclick or addEventListener to attach your function. If you want to go the innerHTML route, append it to the DOM first, then find it and attach your event.
http://jsfiddle.net/EjYpQ/
You're a bit out of luck on that one due to Chrome's execution model:
Content scripts execute in a special
environment called an isolated world.
They have access to the DOM of the
page they are injected into, but not
to any JavaScript variables or
functions created by the page. It
looks to each content script as if
there is no other JavaScript executing
on the page it is running on. The same
is true in reverse: JavaScript running
on the page cannot call any functions
or access any variables defined by
content scripts.
(emphasis in bold)
Source: http://code.google.com/chrome/extensions/content_scripts.html#execution-environment
This is the best solution I found:
$("#elementID").click(function() {
myFunc();
});