Gmail Chrome Extension "chrome.extension" undefined - javascript

I have a content script running inside the Gmail UI and I am injecting some new HTML at different points. This is all working, but to keep the code clean I wanted to insert pre-defined HTML markup into certain parts of the page in a single function call.
This all seems feasible using chrome.extension.getURL(), but when I was testing this, it looks like chrome.extension is undefined! I was unable to find anywhere in the documentation that says this shouldn't be defined and several places where it says it should.
I am using chrome Version 39.0.2171.95 (64-bit)
Here is what the chrome object looks like in the javascript console:
First off, anyone know why chrome.extension might be undefined? Secondly, is there another (perhaps better) way to do this? I'd rather not just programmatically inject a large amount HTML into the page in code using jQuery, etc. in the content script, but can resort to this if there is no other way.

If you're testing this in the console, you must be aware of the concept of the Isolated World. When you add a content script, it has a separate JavaScript context for itself that is isolated from the page.
At the top of the Console tab of Dev Tools, you'll see <top frame> in a dropdown. This is a dropdown that selects JS context it is executing in. It will list frames inside the document and all extensions that have content scripts injected.
The chrome object you show in the screenshot corresponds to what the webpage normally sees. If you switch context, you'll see a different picture:
In any case, if you are really executing chrome.extension.getURL() in the content script - it will be well defined.
Now, if you injected a <script> tag in the page and tried it in that code - it would fail again, since the code will be in the page context. See this question for this situation.
Finally, most of the Chrome API will not be exposed to content scripts for security reasons. If an API is undefined when it shouldn't be, you may need a background page to do the job for you.

Related

Javascript returns null in Chrome, HTML element in source

I am trying to read this HTML in the console in Chrome:
<span id="lblSummaryFreight">Kr 79</span>
Using this JS:
document.getElementById('lblSummaryFreight').innerHTML;
However, after the page has loaded, running this line returns null or invalid. If i inspect the element and then run the code, it works as intended and returns "Kr 79". So, is it some kind of DOM issue I am not aware of, or a browser-specific issue?
I am using this as a variable in Google Tag Manager, and it works in 50% of the cases. I don't have access to the source code of the webpage itself, so that's why I need to lean on this rather clunky way of getting the data.
A lot of posts on this suggest that this is because the script is fired before the DOM is ready, but I don't think this is an issue, as I am also testing this in the console after the page has loaded (and the HTML elements are present), and in Google Tag Manager I have specified that the tag should fire after DOM is ready.
Any clues?
Edit / Clarification: I can't alter the code of the page itself, only read the output source, which i am trying with JS via GTM
Don't seem to be able to resolve this issue, and as it seems to be the fault of some quirky source, I will try to figure out another way to get the data I need.
What I have learned:
The issue seems to be specific to Chrome, as it works in other browsers. This is supported by the fact that the GTM tag where this code is implemented returns correct values in ~50% of the cases
Testing the page in Android native browser, it will also return 'undefined'. After reloading the page that fires the tag, it returns correct value.
The whole DOM seems unavailable in the console. Tried also this:
document.getElementsByClassName('complete').length
Which returns 0, but there are around 10 instances of the class in the source. After inspecting anywhere on the page, it returns correct number.
Any delay in running the script won't help, only the symbolic inspecting of elements or reloading the page helps.
So my conclusion is that the way this webpage is built somehow goes against the grain of some browsers - it seems like the source goes out of the memory after the source is loaded. But this is way beyond my level of understanding.
Thanks all for all inputs!
It looks like an async issue. Try this:
//Using Jquery
$( document ).ready(function() {
document.getElementById('lblSummaryFreight').innerHTML;
});
or
//Add this at the end of the body, after all of your content
<script>
(function() {
document.getElementById('lblSummaryFreight').innerHTML;
})();
</script>
Try to change how the tag is fired in GTM. Fire them when Window Loaded, and try again.
Maybe the element is being changed in another js file.
Trying jQuery is a good point. I have had similar problems and jQuery have solved them all.

basic javascript alert not working in Intel XDK code editor

I'm starting fresh with a new blank Intel project and I haven't even started coding yet. I'm just setting up my file tree and making sure the html and javascript pages are connected via the right anchors and script paths. My first .js file won't work though.
I've included a screen shot of test code and the errors. I know the syntax is correct because it works when I put it in <script> tags in the index.html file.
I'm getting "document not defined" and "alert not defined" errors or the js page though. I don't know what that means.
I've considered that my script tag src path in the index file is incorrect, but all the paths are relative in the commented out template script tags intel provides on the index page right out of the box, so why would I have to use an absolute path?
My path is: js/Test.js and it's the last script tag before the body.
Index.html file
*****UPDATE****
So I've tried a few things and it's still not working but I HAVE managed to get my errors down to just one inexplicable "missing semicolon", which will turn into an "unnecessary semicolon" error if I place it.
Any way as per the first screen shot you'll see that I wasn't placing the document object inside of an explicitly declared variable. Once I did that and accessed it through dot syntax instead of an equal sign then I stopped getting the error. I included this screenshot to show my work before I made the changes.
so the problem I went on to have is that unless every function or dom object was declared with "Var", I'd get an error. This includes the alert() function which I don't think I've ever seen needing to be declared that way, but I gave the code editor what it wanted and this last screenshot is the results. It's not working, BUT I'm not getting the errors I was before, except for the missing/unnecessary semicolon paradox. Removing it or including it throws an error.
JavaScript can be loaded before or after the HTML, however the way it is done is slightly different depending on how you do it.
For example if you wish to include your JavaScript files within the head of the HTML file then you must wrap your JavaScript code with either DOMContentLoaded or jQuery's $(document).ready().
The common misconception of using window.onload will not fix the issue where the elements have not loaded in correctly.
The Mozilla Developer Network states on this page:
The DOMContentLoaded event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading. A very different event - load - should be used only to detect a fully-loaded page. It is an incredibly popular mistake to use load where DOMContentLoaded would be much more appropriate, so be cautious.
That quote in itself should prove that onload should not be relied on if you want the full DOM to be loaded properly before you start manipulating it. Instead you should do the following:
Vanilla
document.addEventListener("DOMContentLoaded", function (e) {
/** DOM has been fully loaded here, so manipulation can begin. **/
/** Your code here. **/
});
jQuery
$(document).ready(function () {
/** DOM has been fully loaded here, so manipulation can begin. **/
/** Your code here. **/
});
Click this link to see the difference between vanilla and jQuery.
The second way you can load JavaScript is by having all the script tags within the body but after all the HTML, that way it is guaranteed to load after the HTML.
Example
Try this working example I quickly coded up.
HTML
Replace the content within the body tag of your HTML to the following:
<button id="myJsTest">Click Me!</button>
<div id="clickCounter">Click Count: 0</div>
Replace the contents of your JavaScript with the following:
JavaScript
document.addEventListener("DOMContentLoaded", function() {
var clickCount = 0;
document.getElementById("myJsTest").addEventListener("click", function() {
clickCount++;
document.getElementById("clickCounter").innerText = "Click Count: " + clickCount;
});
});
Then use the Emulate tab in Intel XDK to test it.
Additional Information
When I use Intel XDK and I have an error, I quickly load the file in to the browser and check the console. It can be a really helpful and effective way of squashing those pesky little bugs.
Try using window.alert as alert is defined in the window object.
The reason you're seeing all those "error" messages in the editor window is because you've got the various JSLint/Hint tools loaded in the editor. They're trying to keep you honest and save you lots of time in the debugger chasing potential syntax errors.
The editor inside the XDK is Brackets, it is using standard Brackets extensions to provide those JSLint/Hint tools. You can download it and run it standalone on your system and edit directly within it, you don't have to use the editor inside the XDK (or you can use any other editor you like).
Because the Lint/Hint tools only look at one file at a time, and because your app is normally spread over multiple files, they don't know much about about what's defined in your other files. Likewise, those hint/lint tools need to be told that you're using some of the standard global methods and properties that are expected to be found in a browser (but which may not be found in other JavaScript environments, because JavaScript is no longer limited to just a browser environment -- in fact, your XDK app, aka Cordova app, runs inside a "webview" not in a browser, but that's another story...)
So, you should follow some standard practice of setting up your JSHint/Lint directives at the top of your JS files. For example, this is a good starting point:
/*jslint browser:true, devel:true, white:true, vars:true */
/*global $:false, intel:false */
See the JSHint documentation for details... and see the "Blank Cordova Starter App" in the "Start a New Project" section of the Projects tab for a better blank template to start (there is no real difference between a blank template and a demo app, they are structured identically).
For a more complete and even more instructive app, see the "Hello, Cordova" sample app. Both of those apps can also be found on the Intel XDK GitHub repo.
You are adding the js file that is <script src="js/Test.js"></script> inside header tag.
So js will be first loaded and and it will attach all events to it. But when js is loaded button id="jsTest" is not present because DOM is not loaded.
Solutions :-You can follow either of the approach
Add your js files after DOM is ready
<body>
<button id ="js/Test.js">Test JS</button>
// other HTML tags
<script src = "js/Test.js></script>
</body>
Use window.onload
The load event fires at the end of the document loading process.
window.onload = testJsFile(){
//Your code goes here
}
I will prefer to use the first approach since that also address other issues like page loading time
Try to put the line outside your JS function
document.getElementById(......
inside your html page between
<script>HERE</script>
If this is still no working. Try to add onClick attribute to the button like this:
<button id="" onClick="testJsFile()">
Its also good to use google chrome element inspection while devlopping cuse it will give you error msg for all these things.

How to show panel with dynamic content (HTML) in it

I want to show drop-down menu with HTML content in it when the user presses my addon's button on browser's toolbar.
It seems that I need to use panel as suggested in the documentation but the problem is that my content is dynamic and can change over time while addon works. AFAIK panel can only work with predefined HTML files and change its content via scripts provided by contentScript property, but even then it is clearly stated in the documentation that it can lead to the non-approved addon:
Warning: Unless your content script is extremely simple and consists
only of a static string, don't use contentScript: if you do, you may
have problems getting your add-on approved on AMO.
Instead, keep the script in a separate file and load it using contentScriptFile. This makes your code easier to maintain, secure,
debug and review.
What can I do then?
The paragraph you quote refers to defining complex scripts inline with the contentScript parameter. If you use contentScriptFile to load the script which then modifies the HTML that should be fine.

Embedding a TinyMCE editor in PyQT QWebkit

as the question states, I wish to embed a tinymce editor in a PyQT webkit component.
As far as I understand, evaluateJavascript allows for js functions to be called.
However, when I try loading tinymce.min.js, the editor does not display anything at all. As suspected, when evaluating a javascript that 'loads' other javascript files, they don't actually get loaded.
At this point, I feel lost. I will try to manually load 'plugins' that will be specified in tinymce's init function and will update this.
Till that time, any help would be really appreciated.
EvaluateJavaScript does make javascript function calls, or embed a whole javascript file. The following details out the attempts to solve the problem:
The approach of first reading the tinyMCE.js file and then using that in an evaluatejavascript method embeds the javascript somewhere, and can't be sniffed out in a webkit console. When loading files using the evaluatejavascript method, any dependencies, such as the ones that tinymce require, are not loaded. I think it's because javascript calls are "attached" to the webkit but not embedded in the frame's DOM itself.
The second approach consists of creating a webkit page and loading an html file. The html file itself embeds the javascript, so the component works like a "browser". In tinymce's configuration, toolbars and unnecessary parts were hidden. TinyMCE version 3 worked well with PyQt4. When the 4th version was embedded in an html page however, textareas were not being converted to tinymce editors. The console itself shows 'undefined' error messages, deduced to the assumption that tinymce 4 uses different javascript syntax and a different compiler.
And so ends my quest to write a stand-alone webkit editor. :)

Need help removing iFrame hack from website?

Ok, so somewhere on my site is a Javascript file that after a few seconds, injects an iframe to an unknown site into the page. What it injects fails miserably and the HTML is a bit messed up, but it's concerning because the iframe src has changed since the last time I checked.
Code Injected:
<divstyle="height:2px;width:111px;">
<iframe style="height:2px;width:111px;" src="http://nleskoettf.com/index.php?tp=001e4bb7b4d7333d"></iframe>
</divstyle="height:2px;width:111px;">
For an up-close and personal glance: http://caseconsultant.com is where it injects (see bottom of page). Don't worry, the URL in the iframe src is dead (downforeveryone.com/nleskoettf.com), it's not even a working website which is the really confusing part.
Anyone know how I can track back the injected HTML to the source?
Anyone able to do that?
You may use a tool like Noscript to block domains for scripting and localize the script that injected the iframe.
Then you will see that the iframe will not be present when you block twitter.com
There is a function inside http://caseconsultant.com/wp-content/plugins/contact-form-7/scripts.js?ver=2.3.1 (see the last line) that loads some JSON-data from twitter and creates the iframe(maybe using data from the twitter-response, may be a reason for the changing url).
This also may be interesting to you: Is this dangerous Javascript? (It's the same function)
I'm not sure if this is malware, maybe there is only a bug inside the function that creates invalid HTML/URL
But the function has nothing to do with a contact-form, and also isn't a part of the original scripts.js(you'll find it here: http://downloads.wordpress.org/plugin/contact-form-7.2.3.1.zip ), so I'm afraid the site has been hacked(except you put the function there on your own).
So what you can do:
Read this (removing the function will not be sufficient, as long as you didn't remove the vulnerability)
Check the Server-Logs, script.js has been modified on 11 Nov 2011 19:57:00 GMT , has there been something suspicious-looking? If not you may assume there is no server-side vulnerability(but server-logs can be modified too), ....
Change your FTP-Password
Scan your PC for malware
I'd recommend using Chrome's Developer Tools to figure this out. If you load your site in Chrome, you can then open the tools by hitting the wrench button, then Tools -> Developer Tools (Or Ctrl+Shift+I).
From there, you can use the Resources tab to see everything thats being loaded for that page, or the Scripts tab to focus on just javascript. For this problem, neither of those seem that useful, so I recommend a different method: breaking on DOM changes. Take a look in the Elements tab, right click on the <body> tag and choose Break on subtree modifications. Then, refresh the page (might need to refresh twice, Chrome bugged out for me on the first time).
You should arrive at a call to jQuery.append in the Scripts window (if not, hit F10 until you are, sometimes Chrome picks up on more or less modifications on load), and if you look at the a variable under Local in the Scope Variables sub-window, you'll see that this is trying to insert the offending div/iframe.
Now you can step through the javascript using the buttons at the top-right, or F10 and F11. If you hit F10 a few times ('Step Over'), you'll end up in the offending script, referred to by Chrome as '(program)' (means its been dynamically loaded). This has been obfuscated, so its a bit hard to read/understand, but you can use the console window to run things from the script.
For instance, the jsn function is being used to translate obfuscated text. You can use this to see all of the different strings it is using, for instance on this line:
jsg = jsn('Ch') + jsp(jsb).substring(0, jsa) + '.com/' + jsAJ($);
That constructs the url for the iframe.
This means we've identified the offending script for sure, but the fact that this is identified as '(program)' by Chrome means it has been loaded dynamically into memory to be run. This means the actual script part is most likely compressed and further obfuscated somewhere in your other script files. If you look through those script files in the Resources file, you should be able to find a line or lines that don't fit in, that look very obfuscated/compressed, and are perhaps inside of an inline function call, IE:
(function() { ... } )();
They may also look somewhat similar to the script file inside the '(program)' view. It can also help to search for things that would be hard to compress/optimize further, such as the obfuscated strings. I searched for one of those strings, haDWDosestnsdlDjfqcq, and found it at the bottom of scripts.js. Delete that line and your site should be fine!
I recently had this happen, iframe injections into the javascript files (and others!). First thing I did was a grep -n for the url on my entire server to find every instance of the injection. Just one line and fairly simple to remove. Then came the matter of tracking it down.
It turns out it was a rogue apache module that had been planted due to a vulnerability. In my case it was mod_aclr.so
Go through your /usr/lib/httpd/modules/ or /usr/lib64/httpd/modules/ directory and compare your list to the list of real apache modules here: http://httpd.apache.org/docs/2.2/mod/
If you have some modules that don't appear on that list, vi them to see what they contain, or simply do a google search to see if they are affiliated with actual modules. In my case, mod_aclr.so returned about 10 pages of Russian commentary, so I quarantined it and will be watching to see what happens now.
Here's a good writeup on the subject: http://blog.unmaskparasites.com/2012/09/10/malicious-apache-module-injects-iframes/

Categories

Resources