Register for your free account! | Forgot your password?

Go Back   elitepvpers > Coders Den > General Coding > Coding Tutorials
You last visited: Today at 21:43

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Tutorial für die Erstellung von Firefox-Add-ons

Discussion on Tutorial für die Erstellung von Firefox-Add-ons within the Coding Tutorials forum part of the General Coding category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: May 2014
Posts: 9
Received Thanks: 4
Tutorial für die Erstellung von Firefox-Add-ons

Da ich so etwas noch nicht gefunden habe und mir alles auf die harte Tour
selber beibringen musste, hier ein kleines Tutorial für die Erstellung eines
Firefox-Add-ons mit dem man die übertragenen Daten abfangen kann.

Dies kann genutzt werden, um bspw. bei Flash-Spielen die Antwort vom
Server mitzulesen. Diese Daten wiederum können Informationen enthalten,
die in den Flash-Clients nicht angezeigt werden oder die Daten sammeln,
um so seinen Fortschritt zu dokumentieren. Man kann natürlich auch die
Daten miteinander vergleichen und sich eine Mitteilung geben lassen,
welches der angebotenen Sachen am Besten ist, ohne selber im Kopf
rechnen zu müssen.

Die Möglichkeiten sind vielfältig aber um die Daten auszuwerten, sind
Programmierkenntnisse in Javascript nötig. Diese werde ich hier allerdings
nicht vermitteln, da die Daten von Spiel zu Spiel sehr unterschiedlich sind.
Allerdings gehe ich kurz darauf ein, welche Möglichkeiten es gibt, um den
Spielen ein paar Details zu entlocken.

Teil 1 - Erstellung des Add-ons

Die detailierte Anleitung ist hier zu finden:


Vorbereitung: Zuerst einmal die benötigte Software herunterladen.
  • Python (2.7.x, da 3.x.x nicht unterstützt wird):
  • Add-on SDK von Mozilla:
Nun Python installieren (bspw. in C:\Python27)
und das Add-on SDK entpacken (bspw. in C:\mozilla-addon-sdk-1.16).

Für die Entwicklung unseres Add-on legen wir ein Verzeichnis an
(bspw. C:\TestAddon) und wechseln in dieses Verzeichnis.

Als nächstes aktivieren wir das Add-on SDK mit diesem Befehl:
Code:
C:\mozilla-addon-sdk-1.16\bin\activate
Um ein Basis-Addon generieren zu lassen können wir folgenden Befehl nutzen:
Code:
cfx init
Damit haben wir bereits ein lauffähiges Add-on, das aber noch nichts macht.


Teil 2 - Erweiterung des Add-ons für den Zugriff auf die übertragenen Daten

Um es ein wenig übersichtlicher zu machen, können wir die Verzeichnisse
doc und test löschen. Die Datei package.json enthält grundlegende Daten,
wie den Namen des Add-ons und hier können auch Einstellungen konfiguriert
werden, die man später im Browser setzt und die man im Add-on verwenden
kann aber für unser Beispiel ist das nicht notwendig.

Nun nehmen wir eine png-Grafik in der Größe 16x16 Pixel
(bspw. )
und speichern sie im Verzeichnis data. Dort kopieren wir die Grafik zweimal
und benennen die drei Dateien so um:

Code:
testaddon-ico-gray-16.png
testaddon-ico-red-16.png
testaddon-ico-green-16.png
Dazu kommt noch JQuery 2.x ()
und anschließend wechseln wir eine Ebene zurück und ins Verzeichnis lib.
Dort füllen die Datei main.js mit folgendem Inhalt:

Code:
// Funktionen des SDK einbinden
var data = require("sdk/self").data;
var widgets = require("sdk/widget");

// Ueberwachungsfunktionalitaet einbinden
var observer = require("./observer");

// Icons fuer die Darstellung der verschiedenen Zustaende (gestartet, aktiviert, deaktiviert)
var initializeIcon = data.url("testaddon-ico-gray-16.png");
var deactivatedIcon = data.url("testaddon-ico-red-16.png");
var activatedIcon = data.url("testaddon-ico-green-16.png");

var active = false;

// Aktivierung der Ueberwachung
function activate() {
	if(!active) {
		// Der Ueberwachungsfunktion mitteilen, dass die Daten mitgelesen werden sollen
		observer.httpRequestObserver.register();
		// Das Icon fuer aktiv anzeigen
		widgetTestaddon.contentURL = activatedIcon;
		active = true;
	}
}

// Deaktivierung der Ueberwachung
function deactivate() {
	if(active) {
		// Der Ueberwachungsfunktion mitteilen, dass keine Daten mehr mitgelesen werden
		observer.httpRequestObserver.unregister();
		// Das Icon fuer inaktiv anzeigen
		widgetTestaddon.contentURL = deactivatedIcon;
		active = false;
	}
}

// Darstellung des Add-ons im Add-on Bereich von Firefox
var widgetTestaddon = widgets.Widget({
	id: "widgetTestaddon",
	label: "Test-Addon",
	contentURL: initializeIcon,
	// Ein- oder Ausschalten des Add-ons durch klick auf das Icon
	onClick: function (event) {
		if(active) {
			deactivate();
		} else {
			activate();
		}
	}
});

exports.main = function (options, callbacks) {
};

// Wenn das Add-on entfernt wird, die Ueberwachung beenden
exports.onUnload = function (reason) {
	deactivate();
};

Die Zeile var observer = require("./observer"); verweist auf die Datei observer.js,
die wir als nächstes im Verzeichnis lib anlegen werden und zwar mit folgendem Inhalt:

Code:
const {Cc, Ci, Cr} = require("chrome");
var observerService = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);

// Script, mit dem die Daten zur Anzeige-Aufbereitung geschickt werden
var sender = require("./sender");

// Damit nicht jede Antwort vom Server mitgelesen werden muss, sollten hier Filter definiert werden:
// Filter fuer URLs die bspw. http://server.de/api.php lauten koennten, um Antworten vom Server abzugreifen
var apiUrl = "server.de/api.php";
// Filter fuer URLs die bspw. http://server.de/test_resources/de_textfile.txt lauten koennten, um Texte abzugreifen
var txtUrl = "server.de/test_resources/de_";
// Filter fuer URLs die bspw. http://images.server.de/supergame/battleimages/armor.png lauten koennten, um Grafikdateien abzugreifen
var gfxUrl = "images.server.de/supergame/battleimages";

// Fuer den Test greifen wir alle(!) Antworten ab, die bei Anfragen an .php zurueck kommen.
var testUrl = ".php";

// Anlegen des Observers, der die uebertragenen Daten mitliest
var httpRequestObserver = {

	isRegistered : false,

	observe: function (subject, topic, data) {
		// Pruefen, ob uns das Topic (Anfrage an den Server / Antwort vom Server / Antwort vom Browser-Cache, ...) interessiert
		if (this.getTopicType(topic) == 1) {
			var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
			var url = httpChannel.originalURI.spec;
			// Pruefen, welche URL aufgerufen wurde und ob uns die Antwort interessiert
			var reqType = this.getReqType(url);
			if(reqType > 0) {
				// Uebertragungsmethode pruefen (bei GET interessiert uns nur die URL,
				// an die die Anfrage geschickt wurde und bei POST auch die Daten)
				if(httpChannel.requestMethod == "GET") {
					// Erzeugen unseres Listeners, um die Uebertragung abzuhoeren
					var newListener = new TestListener(reqType, url, 0, "");
					subject.QueryInterface(Ci.nsITraceableChannel);
					newListener.originalListener = subject.setNewListener(newListener);
				} else if(httpChannel.requestMethod == "POST") {
					var channel = httpChannel.QueryInterface(Ci.nsIUploadChannel).uploadStream;
					channel.QueryInterface(Ci.nsISeekableStream).seek(Ci.nsISeekableStream.NS_SEEK_SET, 0);
					var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
					stream.setInputStream(channel);
					// Auslesen der an den Server gesendeten Daten
					var postBytes = stream.readByteArray(stream.available());
					var postStr = decodeURIComponent(String.fromCharCode.apply(null, postBytes));
					// Pruefen, welcher Inhalt gesendet wurde und ob uns die Antwort interessiert
					var postType = this.getPostType(postStr);
					if(postType > 0) {
						// Erzeugen unseres Listeners, um die Uebertragung abzuhoeren
						var newListener = new TestListener(reqType, url, postType, postStr);
						subject.QueryInterface(Ci.nsITraceableChannel);
						newListener.originalListener = subject.setNewListener(newListener);
					}
				}
			}
		} else if (this.getTopicType(topic) == -1) {
			// Wenn der Browser beendet wird, die Beobachtung beenden
			this.unregister();
			return;
		}
	},

	// Abfragen des Topics und zurueckgeben einer ID, die dem Topic entspricht.
	// Im Beispiel ist -1 bei Beendigung des Browsers und 1 bei Antworten vom Server (response),
	// Antworten aus dem Browser-Cache (cached-response) oder gemischte Antworten (merged-response)
	// bzw. 0 fuer den Rest
	getTopicType: function(topic) {
		if(topic == "http-on-examine-response" || topic == "http-on-examine-merged-response" || topic == "http-on-examine-cached-response") {
			return 1;
		} else if(topic == "quit-application") {
			return -1;
		}
		return 0;
	},

	// Abfragen der verschiedenen URLs und zurueckgeben einer ID, die der URL entspricht.
	// Im Beispiel ist dies 1 fuer API-URLs und 2 fuer Resource-URLs bzw. 0 fuer den Rest.
	getReqType: function(url) {
		if(url.indexOf(testUrl) > -1 || url.indexOf(apiUrl) > -1) {
			return 1;
		} else if(url.indexOf(txtUrl) > -1 || url.indexOf(gfxUrl) > -1) {
			return 2;
		}
		return 0;
	},

	// Abfragen der Inhalte der Anfrage an den Server und zurueckgeben einer ID, die dem Inhalt entspricht.
	// Im Beispiel ist dies 0 fuer den Rest.
	getPostType: function(postStr) {
		return 0;
	},

	// Registrieren unseres Observers, um auf das Beenden des Browsers und auf Antworten vom Server/Cache zu reagieren
	register: function() {
		if(this.isRegistered) {
			console.log("already registered");
		} else {
			observerService.addObserver(this, "quit-application", false);
			observerService.addObserver(this, "http-on-examine-response", false);
			observerService.addObserver(this, "http-on-examine-merged-response", false);
			observerService.addObserver(this, "http-on-examine-cached-response", false);
			this.isRegistered = true;
		}
	},

	// Zurueckziehen unseres Observers
	unregister: function() {
		if(this.isRegistered) {
			observerService.removeObserver(this, "quit-application");
			observerService.removeObserver(this, "http-on-examine-response");
			observerService.removeObserver(this, "http-on-examine-merged-response");
			observerService.removeObserver(this, "http-on-examine-cached-response");
			this.isRegistered = false;
		} else {
			console.log("already unregistered");
		}
	},

	QueryInterface: function(aIID) {
		if (aIID.equals(Ci.nsIObserver) || aIID.equals(Ci.nsISupports)) {
			return this;
		}
		throw Cr.NS_NOINTERFACE;
	}
}
exports.httpRequestObserver = httpRequestObserver;

// Der Daten-Container fuer die uebertragenen Daten
function TestListener(reqType, url, postType, postStr) {
	this.requestedType = reqType;
	this.requestedUrl = url;
	this.postedType = postType;
	this.postedData = postStr;
	this.receivedData = [];
}

TestListener.prototype = {
	originalListener: null,

	requestedType: 0,	// ID der abgerufenen Daten (siehe getReqType: function(url))
	requestedUrl: "",	// Aufgerufene URL
	postedType: 0,		// ID der gesendeten Daten (siehe getPostType: function(postStr))
	postedData: "",		// Daten, die an den Server gesendet wurden
	receivedData: [],	// Daten, die vom Server empfangen wurden

	// Wenn Daten-Pakete vom Server ankommen, wird diese Methode aufgerufen
	onDataAvailable: function(request, context, inputStream, offset, count) {
		if(this.requestedType == 1) {
			// Wenn die Daten vom Typ 1 (Server-Daten) sind, werden diese aufbereitet
			var binaryInputStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(Ci.nsIBinaryInputStream);
			binaryInputStream.setInputStream(inputStream);

			var storageStream = Cc["@mozilla.org/storagestream;1"].createInstance(Ci.nsIStorageStream);

			// 8192 entspricht der Segment-Groesse in Bytes und count ist die maximale Groesse des Datenstroms in Bytes
			storageStream.init(8192, count, null);

			var binaryOutputStream = Cc["@mozilla.org/binaryoutputstream;1"].createInstance(Ci.nsIBinaryOutputStream);

			binaryOutputStream.setOutputStream(storageStream.getOutputStream(0));

			// Ankommende Daten 1:1 kopieren
			var data = binaryInputStream.readBytes(count);

			// Daten an den Flash-Client weiterreichen
			binaryOutputStream.writeBytes(data, count);
			this.originalListener.onDataAvailable(request, context, storageStream.newInputStream(0), offset, count);

			// Eine Kopie der Daten behalten und zu den bereits gesammelten Pakten hinzufuegen
			this.receivedData.push(data);
		} else {
			// Bei Typ 2 (Texte oder Bilder) interessiert uns der Inhalt nicht
			// Daten an den Flash-Client weiterreichen
			this.originalListener.onDataAvailable(request, context, inputStream, offset, count);
		}
	},

	// Wenn die Datenuebertragung beginnt, wird diese Methode aufgerufen
	onStartRequest: function (request, context) {
		// Signal fuer den Beginn der Uebertragung weitergeben
		this.originalListener.onStartRequest(request, context);
	},

	// Wenn die Datenuebertragung endet, wird diese Methode aufgerufen
	onStopRequest: function (request, context, statusCode) {
		// Signal fuer das Ende der Uebertragung weitergeben
		this.originalListener.onStopRequest(request, context, statusCode);

		// Wenn wir alle Pakete haben, die gesammelten Daten zur Anzeige-Aufbereitung schicken
		sender.scanData(this.requestedType, this.requestedUrl, this.postedType, this.postedData, this.receivedData.join(''));
	},

	QueryInterface: function (aIID) {
		if (aIID.equals(Ci.nsIStreamListener) || aIID.equals(Ci.nsISupports)) {
			return this;
		}
		throw Cr.NS_NOINTERFACE;
	}
}
Die Zeile var sender = require("./sender"); verweist auf eine weitere Datei sender.js,
die wir als nächstes im Verzeichnis lib anlegen werden und zwar mit folgendem Inhalt:

Code:
// Funktionen des SDK einbinden
var data = require("sdk/self").data;
var tabs = require('sdk/tabs');

var myTab = -1;
var worker = undefined;

// Wenn der Observer die Daten erhalten hat, kommen wir hier an
function scanData(reqType, url, postType, post, daten) {
	// Je nach Inhalt (Daten oder Resourcen) senden wir einen anderen Befehl
	if(reqType == 1) {
		sendData("zeigeDaten", [daten, url]);
	} else if(reqType == 2) {
		sendData("zeigeUrl", [reqType, url]);
	}
}
exports.scanData = scanData;

// Dies Funktion dient zum Senden der Befehle
function sendData(action, daten) {
	// Wenn der Ausgabe-Tab noch nicht geoeffnet ist, oeffnen
	if(myTab == -1) {
		myTab = 0;
		tabs.open({
			url: data.url("ausgabe.html"),
			inBackground: true,
			isPinned: false,
			// Im Tab einen Worker erzeugen, der auf Befehle und Daten wartet
			onReady: function onOpen(tab) {
				worker = tab.attach({
					// Es werden JavaScripte eingebunden, die miteinander arbeiten sollen,
					// da im anzeige.js bspw. JQuery verwendet wird.
					contentScriptFile: [
						data.url("jquery-2.1.1.min.js"),
						data.url("anzeige.js")
					]
				});
				// Der Befehl und die Daten werden an den Worker geschickt
				worker.port.emit(action, daten);
			},
			// Wenn der Tab geschlossen wird, den Worker zuruecksetzen
			onClose: function onClose(tab) {
				myTab = -1;
				worker = undefined;
			}
		});
	} else if(worker != undefined) {
		// Der Befehl und die Daten werden an den Worker geschickt
		worker.port.emit(action, daten);
	}
}

Damit ist der Ordner lib vollständig und wir wechseln zurück in den Ordner data.

Die Zeilen data.url("ausgabe.html") und data.url("anzeige.js") sagen bereits, welche
Dateien hier anzulegen sind. Beginnen wir mit ausgabe.html und folgendem Inhalt:

Code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<meta charset="utf-8">
	<title>Test</title>
</head>
<body>
	<h1>Test</h1>
	<div id="daten"></div>
	<div id="urls"></div>
</body>
</html>
Als nächstes folgt die Datei anzeige.js mit diesem Inhalt:

Code:
self.port.on("zeigeDaten", function(daten) {
	$("#daten").html(daten[0] + ":<br />" + daten[1]);
});

var urls = [];
self.port.on("zeigeUrl", function(daten) {
	urls.push(daten[0]);
	$("#urls").html(
		$("<ul />", {
			"html": "<li>" + urls.join("</li><li>") + "</li>"
		})
	);
});
Diese beiden Dateien sollten ziemlich selbsterklärend sein. Im HTML legen wir einfach
Div-Sektionen mit IDs an, um diese aus dem JavaScript heraus mit Inhalten zu füllen.

Das JavaScript enthält mit self.port.on einen Empfänger für Befehle aus der Datei
sender.js und zwar im gleichen Format, wie wir dort sendData(action, daten) aufrufen.

Damit ist das Addon auch schon fertig. Falls das SDK beendet wurde, mit dem Befehl
Code:
D:\mozilla-addon-sdk-1.16\bin\activate
wieder aktivieren und anschließend kann mit dem Befehl
Code:
cfx run
das Add-on getestet werden. Wenn alles richtig gemacht wurde, öffnet sich ein Firefox-Fenster.
Dort auf das Icon des Add-ons klicken und eine Seite mit php (bspw. aufrufen.
Nun müsste ein neuer Tab aufgehen, in dem die aufgerufene URL und die empfangenen
Daten angezeigt werden. Wenn das funktioniert, kann mit dem Befehl
Code:
cfx xpi
eine XPI-Datei erzeugt werden, die man einfach auf den Firefox ziehen kann und schon
ist das Add-on im Browser installiert.

Nun kann das Add-on beliebig erweitert und für die entsprechenden Browser-Games
angepasst werden.

Teil 3 - Weitere Tools

Hier noch ein paar Links zu Hilfmitteln, um den Flash-Spielen ein wenig unter die
Haube zu schauen und sich Inspiration zu holen, wie man sein Add-on aufpeppen kann.
Attached Files
File Type: zip TestAddon.zip (77.8 KB, 2 views)
Nuwisha is offline  
Thanks
2 Users
Old 06/29/2014, 02:46   #2


 
MrSm!th's Avatar
 
elite*gold: 7110
Join Date: Jun 2009
Posts: 28,902
Received Thanks: 25,407
Arrow Web Development -> Coding Tutorials

#moved
MrSm!th is offline  
Thanks
1 User
Old 07/05/2014, 18:04   #3
 
elite*gold: 0
Join Date: May 2014
Posts: 335
Received Thanks: 6
thank you
Ist_das_noch_Fastfood? is offline  
Thanks
1 User
Reply


Similar Threads Similar Threads
Suche Tutorial .so erstellung
09/24/2013 - Metin2 Private Server - 0 Replies
Hey, ich suche ein Tutorial zur .so erstellung wo nicht die hälfte gelöscht wurde :S Auserdem finde ich nirgends die ddetour.h Datei. Ich hoffe i-wer kann mir helfen ;) MFG Luoo
WBB Design erstellung Tutorial
06/20/2011 - Tutorials - 0 Replies
Hallo elitepvpers, ich wollte euch heute mal meine Tutorialreihe vorstellen die davon handelt wie man sich ein WBB Design erstellt. Hier meine Videos: YouTube - &#x202a;Kanal von FrEEzYDesign&#x202c;&rlm; Viel Spaß beim schauen.
Firefox New Tutorial Part 1
06/09/2011 - 9Dragons - 17 Replies
Please see the picture http://farm3.static.flickr.com/2757/4358258973_18 bf2b1df8_o.png You can download here this hack http://www.mediafire.com/?vjjn1ynktgy
[Tutorial] Firefox-Downloads schneller machen!
04/12/2011 - Tutorials - 8 Replies
Ich zeige euch hier ein Add-On für Firefox, welches eure Downloadrate erhöht. Was brauche ich? -Leseverständnis -Einen Computer -Internetanschluss -Firefox -Das Add-On *klick*
[S]Tutorial zu Desing erstellung [B]e*gold
04/04/2011 - elite*gold Trading - 4 Replies
Hei Leute, Ich suche ein Tutorial wie man sich ein Wbb Lite Design erstellt. Mit allem was dazu gehört. Biete: 10 e*gold. Postet einfach den Link und nen Treasures und wenn ich das TuT gut finde bekommt ihr 10 e*gold.



All times are GMT +1. The time now is 21:43.


Powered by vBulletin®
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2025 elitepvpers All Rights Reserved.