Google Search API Inside Firefox Extension - javascript

I am developing a firefox extension and I need to include the Google Search API. But I am encountering an error in the google.load('search','1') line. Can anyone tell what the problem is
Thanks.

I have the same problem, but according to what I can see in Google's JS code, it tries to add variable 'google' to window, but the extension is loaded when there is no window yet! So there will be no global google variable and therefore an error occurs when you try to fire google.load().
I think the solution is to load the script dynamically. I have just found an existing addon for transliteration:
h t t p s : / / addons.mozilla.org/pl/firefox/addon/8960
Look how they have solved the problem:
onPageLoad: function(event) {
var doc = event.originalTarget;
var ele = doc.createElement('script');
ele.setAttribute('type', 'text/javascript');
ele.setAttribute('src', 'h t t p : / / www.google.com/jsapi?key=internal');
}
onPageLoad is loaded when DOMContentLoaded event occures, so when the whole tree of the page is loaded (it seems it's a DOM equivalent to onLoad)
(Forgive me inserting spaces in links, but otherwise I would not be permitted to post them :])

If you've gathered all the JavaScript files and are packaging them with your Firefox extension locally, and google's load function was designed for loading JavaScript from a server then your problem is that you can't use the load mechanism in that library. Instead use Components.utils.import or mozIJSSubScriptLoader depending on the version of Firefox you're targeting.
This might require editing, extending or overwriting the code in Google's library.

Related

Javascript redirect not working in Edge browser when opened with android ActionView intent, but working after manual reload

Situation
In our Android app (Xamarin), we open a web page using an ActionView intent. The code looks like this:
Intent intent = new Intent((string)Intent.ActionView, Android.Net.Uri.Parse(args.url));
intent.AddFlags(ActivityFlags.NewTask);
The opened page at some point does a JS redirect, with a line like this:
window.location = '...';
We tried many different variations of that line, including window.location.href = '...', window.location.assign('...'); and some more. All show the same behavior.
Problem
This has worked fine for years now, in all browsers - but now we ran into a problem, when the browser on the android device is the Edge browser:
When the browser tab is initially opened by the intent, the window.location = '...' line in Javascript is just ignored by the browser. No error message - just ignored.
However, if that same browser tab with exactly the same URL is opened manually (either by reloading or by copying and pasting the URL), the JS redirect is executed just fine.
Question
How do we fix this, how do we make the JS redirect reliably work?
My guess is that we are running into a security feature, which prevents JS redirects in browser tabs that the user has never interacted with.
Is there something (maybe an intent flag?) to circumvent this? We already tried the flag GrantWriteUriPermission, but it did not help.
Possible duplicates
Android Browser Facebook Redirect Does Not Always Trigger Intent for URL :
The proposed situation of setting the URL on a link and faking a click on it did not work.
Microsoft Edge security
Microsoft Edge recently fixed an issue regarding XSS Targeting Non-Script Elements (June 24, 2021).
The vulnerability was found by two researcher when they visited a website in another language via the Microsoft Edge browser and attempted to translate the page. The goal of the recent fix by Microsoft is to avoid vulnerability regarding accessing dynamically to a content from a third party application and specifically in the case of browser redirection. They need to act quickly because the vulnerability is quite huge.
In order to mitigate a large class of potential cross-site scripting issues, the Microsoft Edge Extension system has incorporated the general concept of Content Security Policy (CSP)
Ok, but ... is there any solution?
Maybe you can find a solution to solve your issue here, in particular the part concerning the <button onclick="...">.
Inline code is considered harmful in concept of CSP and microsoft recommend some good practices :
1 - The clickHandler definition must be moved into an external JavaScript
2 - The inline event handler definitions must be rewritten in terms of addEventListener and extracted into your external js file. If you are currently starting your program using code like <body onload="main();">, consider replacing it by hooking into the DOMContentLoaded event of the document, or the load event of the window, depending on your requirements. Use the former, since it generally triggers more quickly.
3 - Function inside onclick call must be rewritten to avoid converting the string of function into JavaScript for running.
The code exemple of the external .js file cited in the documentation look like this :
function awesome() {
// Do something awesome!
}
function totallyAwesome() {
// do something TOTALLY awesome!
}
function awesomeTask() {
awesome();
totallyAwesome();
}
function clickHandler(e) {
setTimeout(awesomeTask, 1000);
}
function main() {
// Initialization work goes here.
}
// Add event listeners once the DOM has fully loaded by listening for the
// `DOMContentLoaded` event on the document, and adding your listeners to
// specific elements when it triggers.
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click',
clickHandler);
main();
});
Hope it's helps

Google Chrome extension run as if in console?

I'm trying to make a Google Chrome extension that pauses/plays the payer in DEEZER (www.deezer.com). I i manually run the code "playercontrol.doAction('next')" in the Google chrome JavaScript console, I can manipulate the deezer player, so i looked at the possibility of injecting the code into the Deezer web page with an extension but I haven't managed to do so successfully.
Is it possible to run JavaScript code in Deezer web page as if it were coming from the console in Google Chrome?
If so how?
The problems that you are facing here are the following:
You need to use content_scripts instead of running code from the background page.
Code run from the background page and code run as content scripts are "Sandboxed". This means that your code doesn't have access to the global variables created by the page. Your extension doesn't have access to it. THE GOOD NEWS IS that you can still do it. You have to be clever, though.
In your extension, you have to inject a new Script tag into the "head" of the page. You have to create a new script tag and append it to the head of the page. Before you append it, you need to set the "innerHTML" of the script tag to be the JavaScript that you want to run. Here is the gist of what you need to do.
var myJavaScript = "alert('hey guys');"; //You need to put your JS here.
var scriptTag = document.createElement("script");
scriptTag.innerHTML = myJavaScript;
document.head.appendChild(scriptTag);
This will put the new script tag into the head, which bypasses the security of the Chrome Extension. This will give the new script access to the regular global variables on the page, ie: you will have access to the 'playercontrol' object.
This feature has been deprecated by Chrome's security policy.

How to disable facebook hotkeys with Chrome extension?

I have created a Chrome extension that uses the hotkeys [Alt]+[0...9] only to discover facebook uses the same hotkeys. Is there any way possible my extension could disable facebook's hotkeys so that mine fire alone? I'm fairly certain I have identified the code facebook uses to implement their [Alt]+[0...9] hotkeys:
document.documentElement.onkeydown=function(a){a=a||window.event;var b=a.target||a.srcElement;var c=a.keyCode==13&&!a.altKey&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&CSS.hasClass...
This is in a script called from the head of the root document. I have tried the following to disable them:
//contents script:
$().ready( function() {
document.documentElement.onkeydown = '';
});
and even
$().ready( function() {
document.documentElement.onkeydown = function(e){};
});
I am guessing further that the reason neither of these attempts work is because although Chrome extension content scripts share a DOM with any webpage on which they run, perhaps they do not share coding environments? Any insight would be appreciated!
Chrome's Content scripts are executed in a Sandboxed environment [source]. There is no direct way to communicate with the global (window) object.
Another common pitfall is that the developer forgets how/when the script is injected.
By default, the script is injected at a point called "document_idle". At this point, the document is not busy (DOMContentLoaded has fired, window.onload may or may not have fired).
As a result, the functions in the script may be overwritten immediately after declaration.
To inject a small script, I recommend to add the code directly to the Content Script:
var actualCode = '/* Code here (see below for inspiration) */';
var script = document.createElement('script');
script.appendChild(document.createTextNode(actualCode));
(document.head || document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
If you want to make sure that the method is not going to be overwritten, you can use Object.defineProperty, to define an immutable property:
Object.defineProperty(document.documentElement, 'onkeydown', {
value: function() {},
writable: false, /* Cannot be overwritten, default false */
configurable: false, /* Cannot be deleted, or modified */
enumerable: true /* Does not really matter. If true, it's visible in
a for-loop. If false, it's not*/
});
The previously mentioned method is supported in Firefox 4+ and at least Chrome 5+. If you want to also support Firefox 2+ and Chrome 1+, you can play with the __defineSetter__, to prevent onkeydown from being defined:
document.documentElement.__defineSetter__('onkeydown', function(){});
Your intuition is correct, the JavaScript that runs from a content script as part of a Chrome Extension is run in a sandbox that does not have access to the JavaScript that is executed in the containing page.
Per the Chrome doc on Content Scripts:
However, content scripts have some limitations. They cannot:
* Use chrome.* APIs (except for parts of chrome.extension)
* Use variables or functions defined by their extension's pages
* Use variables or functions defined by web pages or by other content scripts
First off, I would recommend that you consider different shortcut keys. Overriding the functionality of existing shortcut keys for your own extension could provide a jarring user experience for someone that is expecting the Facebook shortcut key. Imagine if an extension overrode the ctrl-c and ctrl-p shortcuts that are a part of the desktop OS for copy and paste - I think you would have some upset users that would probably remove the thing that changed the behavior they learned prior.
However, if you are insistent, then here is a workaround to loading JavaScript that will execute in the context of the containing page:
Edit: Updated per comment to reference JS file in a plugin instead of one hosted on the web
First, you will need to create a JavaScript file in your chrome plugin: override-fb-hotkeys.js.
First, you will need to host a JavaScript file somewhere on the web that contains the script that you want to execute in the page, let us say you host it at: http://example.com/override-fb-hotkeys.js.
Then, from your content script, you can insert a script tag into the DOM that references your JavaScript file, something like this:
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.setAttribute("async", true);
script.setAttribute("src", chrome.extension.getURL("override-fb-hotkeys.js")); //Assuming your host supports both http and https
var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
head.insertBefore(script, head.firstChild)
The JavaScript will then be fetched and executed in the context of the containing page, not the sandboxed code from the Chrome plugin.
This is how you can do it using jQuery
Remove all shortcuts for any webpage:
$('[accessKey]').attr('accessKey','')

CKEditor variable is available in console, but not from a Chrome userscript?

I'm writing a Chrome userscript to locally auto-save content in a CKEditor. I'm using this CKEditor auto-save plugin as inspiration.
I have written a function that fires every half second (via an interval) to register the CKEditor event handler:
var intervalId = window.setInterval(function() {
if (CKEDITOR) {
window.clearInterval(intervalId);
CKEDITOR.plugins.add("user-script-auto-save", {
init : function(editor) {
editor.on('key', startTimer);
}
});
}
}, 500);
However, it never properly completes, and complains that "CKEDITOR is undefined" on the if (CKEDITOR) statement.
Meanwhile, if I drop into Chrome's console and type CKEDITOR, the console prints out the expected object.
What am I missing? The editor is embedded within an iframe; might that have an impact on scoping? Or am I fighting against Chrome's sandboxing here? And if so, is there some other way I can dig into CKEditor to pull out the content every second or something to do the auto-saves?
I have not yet tried the script in Firefox; that's next on my list.
Worth noting: I'm a long-time JavaScript novice. So I could easily be doing something dumb with scoping or something like that.
According to this little tutorial video on YouTube, all the 3 "devices" are separated from each other in order to prevent XSS attacks from the user script to the browser / website and vice versa. Although the user scripts / content scripts are running in the website's context, they are still kept separated from the actual website script context. You can easily acknowledge this by simply trying to access for example jQuery from a content script. Just as the CKEditor, it will not be available.
So what I've come up with in order to deal with this is using the content script to include external JavaScripts in the head tag. AFAIK, this is not possible for files directly in the extension's root directory, so I've taken a remote server to host my files.
I'm not sure if this is the best approach and I think it is an ugly bypass, possibly way to powerfull and disabled by the Chromium Project some time.
(Edited by OP, so I can select this answer and route karma appropriately)
This answer, combined with some of the suggestions and links in the comments, ended up getting me to where I needed to be.
I ended up with the following function:
var insertScriptIntoDocument = function(scriptUrl, doc) {
// inspired by http://blog.afterthedeadline.com/2010/05/14/how-to-jump-through-hoops-and-make-a-chrome-extension/
var scriptText = doc.createTextNode(
'(function(loc) { \
var embeddedScript = document.createElement("script"); \
embeddedScript.type = "text/javascript"; \
embeddedScript.src = loc; \
document.getElementsByTagName("head")[0].appendChild(embeddedScript); \
})("' + scriptUrl + '");');
var injectorElement = doc.createElement('script');
injectorElement.appendChild(scriptText);
doc.body.appendChild(injectorElement);
};
Usage looks like so:
var embeddedScriptUrl = chrome.extension.getURL("embedded-script.js");
insertScriptIntoDocument(embeddedScriptUrl, document);
For now, I'm executing this from within a Chrome extension, but I suspect that the pattern might work in a GreaseMonkey script deployed via the Chrome TamperMonkey extension provided that the URL of the script to be embedded was hosted somewhere reachable.
FTR, as it turns out, I did not actually need to get to the iframe -- the CKEDITOR variable was defined in the top-level document, but was simply not visible because of the rules of the Chrome sandbox

How to debug JavaScript files which are loaded dynmically?

Currently the web application I am working on loads in a number of script files using jQuery.Load() when the document DOM is ready. However, if those script files have syntax errors, neither Firebug or IE Developer Tool can reliably shows the line with error or give some really huge line numbers.
How can I debug such scripts? Or should I load them via script tags until I have verified that they are bug free?
firebug plugin for mozilla has a inbuilt javascript debugging tool. Which can be used for the purpose mentioned
I had exactly the same problem with YUI3. I reverted back to the admittedly less cool but more stable approach of including the required files - YUI3 has a neat tool for giving you all those script tags - i don't know if it's the same for JQuery. Sorry that's probably not that helpful!
Load them in by dynamically adding a script tag for them (using the DOM), that should do the trick:
var newScript;
var loadFunc = function ()
{
alert("External Javascript File has been loaded");
};
newScript = document.createElement('script');
newScript.setAttribute('type','text/javascript');
newScript.setAttribute('src');
newScript.onreadystatechange = function() //IE triggers this event when the file is loaded
{
if (newScript.readyState == 'complete' || newScript.readyState == 'loaded')
loadFunc();
};
newScript.onload = loadFunc; //Other browsers trigger this one
document.getElementsByTagName('head')[0].appendChild(newScript);

Categories

Resources