The equivalent to a content script in a Firefox extension? - javascript

I am quite new to Firefox and its extensions. Is there something like a script using JavaScript that runs every time a page loads? My chrome extension injects a css file creating a link tag using js. How do I port this to Firefox?

You want the pageMod API.
var pageMod = require("page-mod");
pageMod.PageMod({
include: "*.example.org",
contentScript: 'window.alert("Page matches ruleset");'
});

You can use mozIJSSubScriptLoader to execute the JavaScript (chrome://myExtension/content/script.js) every time a webpage loads. Here is the sample code that you need to modify according to your chrome directory
window.addEventListener("load", function load(event){
window.removeEventListener("load", load, false); //remove listener, no longer needed
myExtension.init();
},false);
var myExtension = {
init: function() {
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent){
appcontent.addEventListener("DOMContentLoaded", myExtension.onPageLoad, true);
}
var messagepane = document.getElementById("messagepane"); // mail
if(messagepane){
messagepane.addEventListener("load", function(event) { myExtension.onPageLoad(event); }, true);
}
},
onPageLoad: function(aEvent) {
var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
// do something with the loaded page.
// doc.location is a Location object (see below for a link).
// You can use it to make your code executed on certain pages only.
var loader = Components.classes["#mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader);
loader.loadSubScript("chrome://myExtension/content/script.js", doc);
// add event listener for page unload
aEvent.originalTarget.defaultView.addEventListener("unload", function(event){ myExtension.onPageUnload(event); }, true);
},
onPageUnload: function(aEvent) {
// do something
}
};

I used to use Greasemonkey on Firefox. In fact, Chrome Extensions began as a mimic of Greasemonkey, and were the origin of content scripts.

Related

How to detect mixed content with angularjs?

I have an angularjs application running on tomcat, and behind a loadbalancer
If the app is requested via the loadbalancer with https, the balancer still requests the application internally via http, of course.
Problem: I'd like to hide one tab that shows mixed content in this case (because I have to embed external pdf links which do not support https, thus I'd like to hide them).
I cannot use $location.protocol() because the app is behind the loadbalancer and always only gets http.
Question: is there a chance I could detect if the browser is actually showing mixed content?
You can't detect it in the simple way. You can try to listen load event on iframe and set timeout, and when timeout triggered, block iframe because iframe didn't loaded like this (jsfiddle example):
checkMixedContent(urlToCheck, function(urlToCheck) {
// For example, change location
alert('ok');
// load iframe
}, function() {
alert('Error: resource timed out');
// hide iframe / show message
}, checkDelay);
function checkMixedContent(urlToCheck, successCallback, errorCallback, checkDelay, dontCheckOnError) {
checkDelay = checkDelay || 10000;
// 1. Create invisible iframe and append it to body
var iframeHelper = document.createElement("iframe");
iframeHelper.src = urlToCheck;
iframeHelper.height = 0;
iframeHelper.width = 0;
iframeHelper.style.visibility = 'hidden';
document.body.appendChild(iframeHelper);
// 2. Set time out and while content on iframeHelper.src should be definitely loaded
var checkTimeout = window.setTimeout(function() {
errorCallback(urlToCheck);
}, checkDelay);
var onLoad = function() {
window.clearTimeout(checkTimeout); // if OK - not show error => clearTimeout
iframeHelper.removeEventListener('load', onLoad);
iframeHelper.removeEventListener('error', onError);
document.body.removeChild(iframeHelper);
successCallback(urlToCheck);
};
var onError = function() {
window.clearTimeout(checkTimeout); // if OK - not show error => clearTimeout
iframeHelper.removeEventListener('load', onLoad);
iframeHelper.removeEventListener('error', onError);
document.body.removeChild(iframeHelper);
errorCallback(urlToCheck);
};
// 3. If everything is fine - "load" should be triggered
iframeHelper.addEventListener('load', onLoad);
// Turn "true" in case of "X-Frame-Options: SAMEORIGIN"
if (!dontCheckOnError) {
iframeHelper.addEventListener('error', onError);
}
}

Chrome extension: have an extension listen for an event on a page?

I have a chrome extension that im making for my site, currently i have the extension checking the database every minute for updates.
Is it possible to have the extension listen for an event on the actual page?
Something like this
this.trigger('sendUpdate', data) //this happened on the page
this.on(sendUpdate, function(){ //this is what the chrome extension listens for
//do stuff with data
})
you need to add a content_script. content_script have full access to the DOM and you can bind to all events on page
just add this to the menifest file
"content_scripts":[{
"matches":["http://*/*","https://*/*"],
"js":"your injected script.js"
}]
you can get more info https://developer.chrome.com/docs/extensions/mv2/content_scripts/
also from your question it looks like you going to be working with a custom event so your content_scrip js is going to be something similar to this
document.addEventListener('yourEventName', function(e){
//send message to ext
var someInformation = {/*your msg here*/}
chrome.extension.sendMessage(someInformation, function(response) {
//callback
});
}, false);
the background page should listen for a message.
chrome.extension.onMessage.addListener(function(myMessage, sender, sendResponse){
//do something that only the extension has privileges here
return true;
});
then you can trigger the Event from all scripts on the page...
var evt = document.createEvent('Event');
evt.initEvent('yourEventName', true, true);
var some_element = document;
some_element.dispatchEvent(evt);
For anyone reading this in 2023, the sendMessage method has moved to chrome.runtime.sendMessage.
See documentation for manifest v3 (MV3): https://developer.chrome.com/docs/extensions/mv3/messaging/

Emit message to add-on from content script onbeforeunload?

I have a content script which times how long a user views a page. To do this, I inject a content script into each page, start a timer and then emit a message back to the add-on when the onbeforeunload event is triggered.
The message never seems to get passed to the background script however.
Given that my main.js looks like this:
var pageMod = require('page-mod'),
self = require("self");
pageMod.PageMod({
include: "http://*",
contentScriptFile: [self.data.url('jquery.min.js'),
self.data.url('content.js')],
onAttach: function(worker) {
worker.port.on('pageView', function(request) {
console.log("Request received");
});
}
});
I can send a message to main.js using the following code no problem.
self.port.emit('pageView', { visitTime: time });
I run into a problem when I try to do it as the user leaves the page however. The message is never received when I do it like this:
$(window).bind('onbeforeunload', function(e) {
self.port.emit('pageView', { visitTime: time });
// This should prevent the user from seeing a dialog.
return undefined;
});
I've tried listening for beforeunload too, that doesn't work either. What could be the problem?
The window object that content scripts access in Firefox browser add-ons is a proxy object and can be a little temperamental. Using window.addEventListener will work.
window.addEventListener('beforeunload', function(e) {
# Do stuff then return undefined so no dialog pops up.
return undefined
});
The onbeforeUnload event is not synchronous, so the browser garbage collects the page before it is finished. Use a synchronous AJAX request:
function Data()
{
var client = new XMLHttpRequest();
client.open("GET", "/request", false); // third paramater indicates sync xhr
client.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
client.send({ visitTime: time });
client.onreadystatechange = emitter;
}
function emitter()
{
self.port.emit('pageView', { visitTime: time });
}
or return a string as an alternative.

Using gBrowser and observerService to find a tab on startup

I'm trying to create a firefox addon that will look for a certain page on startup and grab some info from it. I'm having trouble finding the page at load. Here's what I have so far:
var myfancyaddon = {
onLoad: function() {
var observerService = Components.classes["#mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
observerService.addObserver(function restored() {
observerService.removeObserver( restored, "sessionstore-windows-restored");
var browser = myfancyaddon.findMySite();
if (browser) {
alert("tree falling in the woods"); // THIS LINE NEVER RUNS
browser.contentWindow.addEventListener("load", function tab_loaded(){
browser.contentWindow.removeEventListener("load", tab_loaded(), false);
alert("mysite loaded!");
}, false);
}
}, "sessionstore-windows-restored", false);
},
findMySite: function() {
var browsers = gBrowser.browsers;
for ( var i = 0; i < browsers.length; i++ ) {
var browser = browsers[i];
if (!browser.currentURI.spec) continue;
if ( browser.currentURI.spec.match('^https?://(www\.)?mysite\.com/') ) return browser;
}
return null;
}
};
window.addEventListener("load", function ff_loaded(){
window.removeEventListener("load", ff_loaded, false); //remove listener, no longer needed
myfancyaddon.onLoad();
},false);
after some investigation it seems the currentURI.spec is "about:blank" for a short time before it becomes mysite.com. Any ideas?
Instead of filtering first and then adding the load listener, you could use gBrowser.addEventListener("DOMContentLoaded", myfunction, false); to listen for page loads on all tab documents and then only run your code based on the url.
https://developer.mozilla.org/en/XUL_School/Intercepting_Page_Loads
The "sessionstore-windows-restored" notification is sent when the tabs from the previous session have been restored and the loading in these tabs has been started (sometimes: "Don't load tabs until selected" option means that the load isn't even started in the background tabs). But the location of these tabs is still about:blank until the server is contacted because the address loaded might redirect or the server might be unreachable (meaning an internal redirect to about:neterror). Firefox only changes browser location when content is definitely being served from the new location.
It should be indeed better to intercept page loads rather than waiting for session restore.

How do I determine that all tabs have been loaded in Firefox?

I am writing a Firefox add-on and I need to be able to run some code after all the tabs have been loaded.
I tried something like:
window.addEventListener("load", function(e) {
gBrowser.addEventListener("load", function(ee) {
// code to run after all tabs have loaded
// thank user for installing my add-on
alert('Thank you for installing my add-on');
// add tab to my website
gBrowser.selectedTab = gBrowser.addTab("http://www.mywebsite.com/");
}, true);
}, false);
But this does not work because this will run the code for each tab after it is loaded. I want to wait until all of the tabs have loaded. I want to print an alert message when the Firefox restarts after the users installs my add-on. I also want to add a new tab to my website.
How do I do this?
I guess that you mean to wait until the session is restored when the browser starts up. There is a sessionstore-windows-restored notification sent out that you can listen to via observer service. Something like this:
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
var observer =
{
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIObserver]),
observe: function(subject, topic, data)
{
observerService.removeObserver(observer, "sessionstore-windows-restored");
addTabNow();
}
};
var observerService = Components.classes["#mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService);
observerService.addObserver(observer, "sessionstore-windows-restored", false);

Categories