Hilfe beim Erstellen einer Webextension

  • Ich möchte eine Webextension erstellen und bräuchte dafür dringend Hilfe :oops:
    Das Grundgerüst habe ich schon und sie funktioniert auch, aber ich möchte sie gerne noch mit mehr Möglichkeiten ausstatten.
    Es geht um die Deaktivierung der "Page Visibility API"
    Dazu gibt es zwar schon Erweiterungen, aber diese sind entweder auf bestimmte Seiten wie youtube/vimeo beschränkt (https://addons.mozilla.org/de/firefox/add…round-play-fix/) oder sie funktionieren nicht korrekt bei manchen Seiten wie https://addons.mozilla.org/de/firefox/add…age-visibility/ die zb. auf dieser Seite http://daniemon.com/tech/webapps/page-visibility/ wenn ich dort das Video pausiere und dann den Tab wechsele, dann spielt es plötzlich im Hintergrund weiter.

    Bisher besteht meine Erweiterung aus:

    ● Ordner "icons" mit "border-48.png"
    ● content_script.js

    Code
    Object.defineProperties(document.wrappedJSObject,{ 'hidden': {value: false}, 'visibilityState': {value: 'visible'} });
    window.addEventListener( 'visibilitychange', evt => evt.stopImmediatePropagation(), true);


    ● manifest.json

    Was ich noch möchte (in der Reihenfolge der Wichtigkeit)
    1. Dass ich umschalten kann zwischen aktiv und inaktiv beim Icon in der Leiste (ja, dafür bastle ich dann neuesicon.png für das inaktive
    2. Dass beim Umschalten der aktive Tab neu geladen wird (default)
    3. Eine Einstellung, in der man den Haken setzen kann ob beim Umschalten von aktiv/inaktiv der aktive Tab neu geladen wird. Standardmäßig sollen beide Haken drin sein.
    4. Eine White/Blacklist soll möglich sein

    für Punkt 3 und 4 ist es in der Erweiterung https://addons.mozilla.org/de/firefox/add…script-toggler/ genauso wie ich es für meine obige haben möchte
    [attachment=0]js-toggle.jpg[/attachment]

    Kann mir da bitte jemand helfen? oder ist mein Vorhaben zu kompliziert für mich dummy? :mrgreen:

    EDIT: Link berichtigt

  • Hi,

    deine vier Punkte sind alle machbar, das ist nicht das Problem. Das Problem ist viel mehr, dass Lösungen für alles zu präsentieren im Endeffekt bedeutet, den größten Teil der Erweiterung zu entwickeln. Das wäre zeitlich für mich ein zu große Herausforderung in Anbetracht dessen, dass ich tausend andere Dinge zu erledigen habe, inklusive einem Umzug, der nächste Woche ansteht. :)

    Daher versuche ich mal, zumindest ein paar Ansätze zu liefern. Schau mal, wie weit dich das bringt. Dann sehen wir weiter.

    1. Grundsätzlich gibt es zwei Möglichkeiten für einen Button: Die browserAction-API erlaubt dir das Hinzufügen eines Buttons zur Symbolleiste. Ich denke, dass das genau das ist, was du im Sinn hattest. Die pageAction-API ist für das Hinzufügen eines Symbols zur Adressleiste beziehungsweise dem Menü hinter den drei Punkten in der Adressleiste. Sinnvoll wäre die browserAction-API für alles, was global wirkt, die pageAction-API für alles, was einen konkreten Bezug zu einer einzelnen Website hat. Das heißt, wenn du bei Klick auf den Button das Feature für alle Webseiten aktivieren möchtest und nicht möchtest, dass man das für jede Webseite neu anklicken muss, ist die browserAction-API rein von der Idee her die bessere Wahl. Technisch ist das egal. Du kannst nehmen, was du willst. Es ist nur eine Entscheidung für die sinnvollere Wahl.

    Manifest: https://developer.mozilla.org/en-US/docs/Moz…/browser_action
    JS-API: https://developer.mozilla.org/en-US/docs/Moz…I/browserAction

    In der JS-API wird insbesondere browserAction.setIcon() interessant sein.

    2. Kurze Antwort: browser.tabs.reload(), siehe https://developer.mozilla.org/en-US/docs/Moz…API/tabs/reload

    3. Zum Speichern von Einstellungen benötigst du die storage-Berechtigung:
    https://developer.mozilla.org/en-US/docs/Moz…son/permissions

    options_ui zum Implementieren der Einstellungs-Oberfläche:
    https://developer.mozilla.org/en-US/docs/Moz…json/options_ui

    Laden und Speichern von Einstellung geht via browser.storage.local.get() respektive browser.storage.local.set():

    https://developer.mozilla.org/en-US/docs/Moz…StorageArea/get
    https://developer.mozilla.org/en-US/docs/Moz…StorageArea/set

    4. Eine komma-separierte Liste von Domains ist kein schöner Ansatz, aber von der Implementierung sicher der Einfachste, weil man nicht viel Oberfläche zu bauen braucht. Letztlich hängt das mit Punkt 3 zusammen. Du musst Einstellungen auslesen sowie ausgeben und Einstellungen speichern. Und wenn es um die Anwendung deines Features geht, musst du die Einstellung auslesen, den Text-Inhalt in ein Array mit allen Domains umwandeln und dann schauen, ob die aktuelle Domain in dem Array drin ist und entsprechend deinen Code ausführen oder nicht ausführen.

    Wenn du einen String wie den folgenden hast:

    let whitelist = "example.com, camp-firefox.de, mozilla.de"

    bekommst du so ein Array mit den Domains:

    Code
    let domains = whitelist.split(',').map(function (domain) {
      return domain.trim();
    });

    Und kannst dann prüfen:

    Code
    if (domains.includes(window.location.href)) {
      // URL ist in Liste, führe Code aus
    }
    else {
      // URL ist nicht in Liste, führe anderen Code aus
    }
  • Danke erstmal, ich werde mir das in der nächsten Zeit zur Gemüte führen und mich näher damit beschäftigen.
    Fragen werden sicherlich noch kommen von meiner Seite aus :D
    Ich fürchte allerdings fast, das Vorhaben ist zu groß für mich...

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

  • Ich werde versuchen, Fragen bestmöglich zu beantworten, sofern möglich. ;)

    Nur noch eine Ergänzung, weil ich mir vorhin die Beispiele nicht angesehen hatte:

    oder sie funktionieren nicht korrekt bei manchen Seiten wie https://addons.mozilla.org/de/firefox/addon/visibility/ die zb. auf dieser Seite http://daniemon.com/tech/webapps/page-visibility/ wenn ich dort das Video pausiere und dann den Tab wechsele, dann spielt es plötzlich im Hintergrund weiter.

    Das ist kein Wunder, weil das Add-on mit der Page Visibility API überhaupt nichts zu tun hat. Das ist ein griechisches SEO-Tool. ;)

    Aber danke für die Gelegenheit zu prüfen, ob ich Griechisch noch lesen kann. Das klappt immer noch fließend. :D (Übersetzen nicht, ich hatte früher antike Texte übersetzt. Ganz andere Baustelle. ;) )

  • So, ich habe mich mal etwas näher beschäftigt und fest gestellt ich muss wohl kleiner anfangen, also erst einmal nur Punkt 1, der Rest kann dann vielleicht folgen.

    Ich scheitere allerdings am content_script.js.

    Mir ist nicht klar was da an Code rein muss:/

    Ich habe mir mal die Erweiterung Toggle Fonts angesehen, da dort die Umschaltung so schön genau das macht wie ich es haben möchte, und der Quellcode recht kurz ist.

    Ich habe es soweit auch auf meine Erweiterung übertragen können bezüglich Buttons, Klicks, Sprache usw. nur der eigentliche Inhalt ist mein Problem.

    Der (verkürzte) Inhalt von Toggle Fonts ist

    Jetzt meine Frage: was muss da stehen, damit es nicht die Schriftart an/aus schaltet, sondern die "Page Visibility API" ?

    Es gibt auch hier im Forum ein Skript für Tampermonkey, was ich mir auch angehen habe, in der Hoffnung, dort etwas heraus lesen zu können, aber auch da scheitere ich:| Ich habe einfach zu wenig Ahnung von der Materie.

    Ist mein Vorhaben eine zu große Nummer für mich, oder kannst du mir doch helfen, Sören Hentzschel ?

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

    Einmal editiert, zuletzt von Zitronella (13. August 2019 um 13:36)

  • klar, mache ich. Wobei ich _locales noch nicht angepasst habe, aber das bekomme ich wahrscheinlich alleine hin.

    EDIT: ich habe noch einmal verändert und zwei Skripte drin

    In background.js ist der Code von Toggle Fonts drin in der content_script.js ist der einfache Code aus Beitrag #1 drin

    Definiert/gelistet habe ich beide in der manifest.json nur haben sie überhaupt keinen Bezug zueinander und ich weiß nicht wie ich die beiden verbinde.

    Sprich, momentan ist es so, dass per Klick auf den Button die Schriftart umgestellt wird und ansonsten auf Seiten wie http://daniemon.com/tech/webapps/page-visibility/ die Erkennung ob Tab im Vordergrund ist, ausgeschaltet ist.

  • klar, mache ich. Wobei ich _locales noch nicht angepasst habe, aber das bekomme ich wahrscheinlich alleine hin.

    Dafür schon mal ein dickes Lob als Vorschusslorbeer. Leider halten es viele Add-on-Entwickler nicht für selbstverständlich Lokalisierbarkeit zu gewährleisten.

    Übersetzer für Obersorbisch und Niedersorbisch auf pontoon.mozilla.org u.a. für Firefox, Firefox für Android, Firefox für iOS, Firefox Klar/Focus für iOS und Android, Thunderbird, Pootle, Django, LibreOffice, LibreOffice Onlinehilfe, WordPress

  • Versuche mal Folgendes:

    manifest.json:

    Den content_scripts-Part habe ich entfernt, weil wir das dynamisch zur Laufzeit setzen wollen. Außerdem habe ich die permissions geändert, da wir die  browserSettings-API nicht verwenden. Wir benötigen einmal eine passende Hosts-Permission, das ist *://*/*, entsprechend dem matches, was du vorher content_scripts hattest, und einmal storage, damit wir die Einstellung speichern können.

    background.js:

    Hier verwende ich die contentScripts-API, da wir ja nicht mehr content_scripts im Manifest nutzen.

    Funktionsweise: Wir lesen aus den gespeicherten Einstellungen aus, ob das Script aktiviert ist oder nicht, und speichern bei Klick auf den Button den umgekehrten Wert ab.

    Wird die Funktion aktiviert, wird content_script.js registriert, wird die Funktion deaktiviert, wird das Script wieder "un-registriert". Titel und Badge wird wie im ursprünglichen Code bei Klick auf den Button angepasst.

    Ich habe noch die Abfragen zwecks Android entfernt, weil Erweiterungen für Android derzeit eh kein spannendes Thema sind.

    Zu beachten ist, dass du nach Klick auf den Button die Tabs neu laden musst, damit die Änderung wirkt, da das Script mit Laden des Tabs eingefügt wird (oder nicht eingefügt wird). Nur durch Klicken des Buttons ändert sich nicht, was bereits geladen ist.

  • Wow, das ist ja mal richtig klasse. Ich kopiere auch nicht nur blind ab sondern versuche auch zu verstehen, schließlich möchte ich auch etwas dabei lernen. Da danke ich dir besonders auch für die zusätzlichen Erklärungen.:thumbup:

    Auf jeden Fall funktioniert das alles genau so wie ich es mir vorgestellt hatte. Eine Datei, die die eigentliche Inhaltsdatei bei Klick aktiviert/deaktiviert. Dass ich die Seite neu laden muss um die Wirkung zu sehen, ist klar, das sind dann die nächsten Schritte, dass die Seite/Tab dadurch auch gleich mit neu geladen wird. Aber erst einmal wollte ich das Grundgerüst haben und das ist hiermit erstellt.

    Nun kann ich mich an die Anpassungen/Übersetzungen/Feinschliffe machen. ;)

    Was mich wundert, ich habe mir bestimmt über 50 Erweiterungen angesehen und nichts vergleichbares gefunden. Meist bestanden sie (zumindest die kleineren) nur aus einer background.js Datei, in der dann alles drin stand. Keine einzige hatte was von

    let registered = null;  drin stehen, auch nicht die Beispieldateien, die es dort im Paket gibt. In Verbindung mit

    async function ToolbarButtonClicked spuckt nicht mal Google was brauchbares dazu aus.

    Insofern hätte ich das niemals alleine hin bekommen.

    Das bedeutet also auch, dass man ähnliche Scripte in die content_script.js rein machen könnte wie das Originale und es würde wohl funktionieren?:huh:

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

  • Dafür schon mal ein dickes Lob als Vorschusslorbeer. Leider halten es viele Add-on-Entwickler nicht für selbstverständlich Lokalisierbarkeit zu gewährleisten.

    Danke. Aber ich bin ja auch kein Entwickler. Ich fummel nur rum und irgendwann mit viel Hilfe kommt vielleicht was brauchbares dabei raus :D

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

  • ähnliche Scripte in die content_script.js rein machen könnte

    oha, ich bin immer mehr begeistert. Das funktioniert. Ich habe einen Code auf Github gefunden, der zusätzlich noch

    window.onfocus() and window.onblur aus schaltet. In die content.js rein getan (ja ich habe die mal umbenannt) und es funktioniert ^^

    Ist es sinnvoll auf Github dazu ein Projekt (oder wie man das nennt) zu starten um die ganze Code Klauerei zu dokumentieren? Dann könnte ich, wenn die Erweiterung irgendwann mal auf AMO ist auch auf die Github Seite verweisen für den Quelltext. Wobei wenn es wirklich zu Problemen kommt habe ich doch keine Ahnung wie man Fehler ausbügelt.?(

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

  • Danke. Aber ich bin ja auch kein Entwickler. Ich fummel nur rum und irgendwann mit viel Hilfe kommt vielleicht was brauchbares dabei raus :D

    Macht nichts, der gute Wille zählt. Mir reicht es schon, wenn ich mir einbilden kann, dass du das extra für mich machst. :D

    Übersetzer für Obersorbisch und Niedersorbisch auf pontoon.mozilla.org u.a. für Firefox, Firefox für Android, Firefox für iOS, Firefox Klar/Focus für iOS und Android, Thunderbird, Pootle, Django, LibreOffice, LibreOffice Onlinehilfe, WordPress

  • Schön, dass das funktioniert. :)

    Was mich wundert, ich habe mir bestimmt über 50 Erweiterungen angesehen und nichts vergleichbares gefunden. Meist bestanden sie (zumindest die kleineren) nur aus einer background.js Datei, in der dann alles drin stand.

    Ich habe keine Ahnung, was es so an Erweiterungen gibt, weil ich eigentlich nie nach Erweiterungen suche. Vielleicht ist das kein so häufiger Anwendungsfall, Content-Scripts per Schaltfläche an- und abschaltbar zu machen. Die Erweiterung, welche du als Basis genommen hattest, war ja auch insofern anders, als dass diese kein Content-Script benötigte, sondern eine Firefox-Einstellung geändert hat.

    Keine einzige hatte was von let registered = null; drin stehen, auch nicht die Beispieldateien, die es dort im Paket gibt.

    Im Endeffekt habe ich das angewendet, was hier in Prosa steht:

    https://developer.mozilla.org/en-US/docs/Moz…/contentScripts

    Man muss das Resultat von browser.contentScripts.register einer Variablen zuordnen, wenn man auf eben jenes Objekt später die unregister()-Methode anwenden will. Und die Variable hab ich ganz oben im Script deklariert, damit sie global verfügbar ist. Es soll ja bei jedem Klick auf die Schaltfläche das gleiche Objekt benutzt werden.

    In Verbindung mit async function ToolbarButtonClicked spuckt nicht mal Google was brauchbares dazu aus.

    Das ist nicht verwunderlich. Dieses ToolbarButtonClicked() ist ja eine Funktion der Erweiterung, die hat er der Entwickler der Erweiterung so genannt und könnte auch HansPeter() heißen. Dazu wird man nicht viel finden. Und das async muss vor jedem function stehen, wenn await verwendet wird. Das wiederum ist also sehr allgemein.

    Das bedeutet also auch, dass man ähnliche Scripte in die content_script.js rein machen könnte wie das Originale und es würde wohl funktionieren? 8|

    Ja, nach dem Prinzip kannst du theoretisch jedes Script, welches auf Websites wirken soll, per Button ein- und ausschaltbar machen.

  • Ist es sinnvoll auf Github dazu ein Projekt (oder wie man das nennt) zu starten um die ganze Code Klauerei zu dokumentieren? Dann könnte ich, wenn die Erweiterung irgendwann mal auf AMO ist auch auf die Github Seite verweisen für den Quelltext. Wobei wenn es wirklich zu Problemen kommt habe ich doch keine Ahnung wie man Fehler ausbügelt.

    Letztlich musst du wissen, wie du deine Sachen organisierst. Für mich persönlich ist Git unverzichtbar, wenn es um Programmier-Arbeiten geht. Aber das erfordert halt auch wieder ein paar Kenntnisse darüber, wie man das verwendet. Das hängt also in erster Linie davon ab, ob du die Bereitschaft hast, dich damit auch noch zu befassen.

  • Ich lasse das erst einmal mit Github, einen Account habe ich dort zwar, aber wenn dann nur um dort mal einen Bugreport zu melden.

    Ich habe nun in background.js die Zeilen

    JavaScript
        badgeText = 'X';
        badgeTitle = 'title_enabled';
      }
      else {
        badgeText = '';
        badgeTitle = 'title_disabled';

    ergänzt mit browser.tabs.reload();

    JavaScript
        badgeText = 'X';
        badgeTitle = 'title_enabled';
        browser.tabs.reload();
      }
      else {
        badgeText = '';
        badgeTitle = 'title_disabled';
        browser.tabs.reload();

    das funktioniert auch wunderbar, der aktuelle Tab wird neu geladen. Nun meine Frage: ist es sinnvoll das so zu machen, oder sollte ich stattdessen besser browser.tabs.reload({bypassCache: true}); nehmen?

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

  • Ich denke nicht, dass bypassCache notwendig ist.

    Wenn du browser.tabs.reload(); sowohl im if als auch im else verwendest, also tatsächlich immer, dann kannst du das aus diesem Konstrukt ganz herausziehen.

    Sprich statt:

    JavaScript
    if (condition) {
        // other code…
        browser.tabs.reload();
    }
    else {
        // other code…
        browser.tabs.reload();
    }

    so:

    JavaScript
    if (condition) {
        // other code…
    }
    else {
        // other code…
    }
    
    browser.tabs.reload();
  • Ich komme immer mit den Klammern durcheinander. Gibt es Nachteile wenn ich es nicht herausziehe aus dem Konstrukt? Für mich ist es als Laien übersichtlicher wenn es so wie ich oben postete 2x drin ist. Aber wenns falsch ist, und/oder irgendwelche Nachteile bringt dann mache ich es natürlich so wie du sagst.

    Wäre das dann so?

    Weil wenn ich es eine Klammer vorher einfüge, lädt es nur nach else

    Hilfe auch im deutschsprachigen Matrix-Chat möglich oder im IRC-Chat
    Meine Anleitungstexte dürfen gerne "geklaut" und weiter verwendet/kopiert werden ;)

  • Gibt es Nachteile wenn ich es nicht herausziehe aus dem Konstrukt? Für mich ist es als Laien übersichtlicher wenn es so wie ich oben postete 2x drin ist. Aber wenns falsch ist, und/oder irgendwelche Nachteile bringt dann mache ich es natürlich so wie du sagst.

    Vom Code her macht es keinen Unterschied, nur von der Code-Qualität: Wir sprechen jetzt von einer einzelnen Zeile. Aber lass deinen Code wachsen und du hast plötzlich 15 Zeilen an dieser Stelle, die in beiden Fällen absolut identisch sind. Je mehr Code man dupliziert, desto unübersichtlicher und schwieriger zu warten wird es für dich.

    Wäre das dann so?

    Korrekt.

    Weil wenn ich es eine Klammer vorher einfüge, lädt es nur nach else

    Wäre es eine Klammer vorher, dann wäre es ja auch innerhalb des else-Blockes, deswegen würde es nur in dem Fall ausgeführt werden. Deswegen ist Code-Einrückung wichtig. Wenn sich öffnende und dazu passende schließende Klammer immer auf der gleichen Achse befinden, sieht man, was wozu gehört. ;)