Index: gc_lang/fr/webext/background.js
==================================================================
--- gc_lang/fr/webext/background.js
+++ gc_lang/fr/webext/background.js
@@ -1,6 +1,6 @@
-// Background 
+// Background
 
 "use strict";
 
 function showError (e) {
     console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
@@ -7,11 +7,13 @@
 }
 
 /*
     Worker (separate thread to avoid freezing Firefox)
 */
-let xGCEWorker = new Worker("gce_worker.js");
+//let xGCEWorker = new Worker("gce_worker.js");
+var xGCESharedWorker = xGCESharedWorker || new SharedWorker(browser.extension.getURL("gce_sharedworker.js"), {type:"classic", credentials:"omit", name:"GrammarWorker"});
+var xGCEWorker = xGCESharedWorker.port;
 
 xGCEWorker.onmessage = function (e) {
     // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
     try {
         switch (e.data[0]) {
@@ -55,11 +57,11 @@
     }
     catch (e) {
         showError(e);
     }
 };
-
+xGCEWorker.start();
 xGCEWorker.postMessage(["init", {sExtensionPath: browser.extension.getURL("."), sOptions: "", sContext: "Firefox"}]);
 
 
 /*
     Messages from the extension (not the Worker)
@@ -156,11 +158,11 @@
                 url: browser.extension.getURL("panel/conjugueur.html"),
                 pinned: true
             });
             xConjTab.then(onCreated, onError);
             break;
-    }    
+    }
 });
 
 
 async function newwin () {
     console.log("Async on");
@@ -176,79 +178,5 @@
     browser.windows.update(xWin.id, { top:top, left:left, }); // firefox currently ignores top and left in .create(), so move it here
     console.log("Async done");
 }
 
 //newwin();
-
-
-/*
-    Worker (separate thread to avoid freezing Firefox)
-*/
-/*
-let xGCESharedWorker = new SharedWorker("gce_sharedworker.js");
-
-xGCESharedWorker.port.onmessage = function (e) {
-    // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
-    try {
-        switch (e.data[0]) {
-            case "grammar_errors":
-                console.log("GRAMMAR ERRORS (SHARE)");
-                console.log(e.data[1].aGrammErr);
-                //browser.runtime.sendMessage({sCommand: "grammar_errors", aGrammErr: e.data[1].aGrammErr});
-                break;
-            case "spelling_and_grammar_errors":
-                console.log("SPELLING AND GRAMMAR ERRORS (SHARE)");
-                console.log(e.data[1].aSpellErr);
-                console.log(e.data[1].aGrammErr);
-                break;
-            case "text_to_test_result":
-                console.log("TESTS RESULTS (SHARE)");
-                console.log(e.data[1]);
-                break;
-            case "fulltests_result":
-                console.log("TESTS RESULTS (SHARE)");
-                console.log(e.data[1]);
-                break;
-            case "options":
-                console.log("OPTIONS (SHARE)");
-                console.log(e.data[1]);
-                break;
-            case "tokens":
-                console.log("TOKENS (SHARE)");
-                console.log(e.data[1]);
-                let xLxgTab = browser.tabs.create({
-                    url: browser.extension.getURL("panel/lexicographer.html"),
-                });
-                xLxgTab.then(onCreated, onError);
-                break;
-            case "error":
-                console.log("ERROR (SHARE)");
-                console.log(e.data[1]);
-                break;
-            default:
-                console.log("Unknown command (SHARE): " + e.data[0]);
-        }
-    }
-    catch (e) {
-        showError(e);
-    }
-};
-
-console.log("Content script [worker]");
-console.log(xGCESharedWorker);
-
-
-//xGCESharedWorker.port.start();
-//console.log("Content script [port started]");
-
-xGCESharedWorker.port.postMessage(["init", {sExtensionPath: browser.extension.getURL("."), sOptions: "", sContext: "Firefox"}]);
-
-console.log("Content script [worker initialzed]");
-
-xGCESharedWorker.port.postMessage(["parse", {sText: "Vas... J’en aie mare...", sCountry: "FR", bDebug: false, bContext: false}]);
-//xGCESharedWorker.port.postMessage(["parseAndSpellcheck", {sText: oRequest.sText, sCountry: "FR", bDebug: false, bContext: false}]);
-//xGCESharedWorker.port.postMessage(["getListOfTokens", {sText: oRequest.sText}]);
-//xGCESharedWorker.port.postMessage(["textToTest", {sText: oRequest.sText, sCountry: "FR", bDebug: false, bContext: false}]);
-//xGCESharedWorker.port.postMessage(["fullTests"]);
-
-
-*/

ADDED   gc_lang/fr/webext/content_scripts/communicate.html
Index: gc_lang/fr/webext/content_scripts/communicate.html
==================================================================
--- /dev/null
+++ gc_lang/fr/webext/content_scripts/communicate.html
@@ -0,0 +1,6 @@
+<html>
+    <head>
+        <script src="/content_scripts/communicate.js"></script>
+    </head>
+    <body></body>
+</html>

ADDED   gc_lang/fr/webext/content_scripts/communicate.js
Index: gc_lang/fr/webext/content_scripts/communicate.js
==================================================================
--- /dev/null
+++ gc_lang/fr/webext/content_scripts/communicate.js
@@ -0,0 +1,70 @@
+
+
+console.log('[Iframe] Loaded');
+/*console.log(self);
+console.log(browser);
+console.log(location);
+console.log(window.parent.location);*/
+
+var sPathOrigin,
+    sPathExtension = browser.extension.getURL("");
+
+/*
+    Worker (separate thread to avoid freezing Firefox)
+*/
+var xGCESharedWorker = xGCESharedWorker || new SharedWorker(browser.extension.getURL("gce_sharedworker.js"), {type:"classic", credentials:"omit", name:"GrammarWorker"});
+var xGCEWorker = xGCESharedWorker.port;
+
+xGCESharedWorker.onerror = function(e) {
+    console.log('There is an error with your worker!');
+    console.log(typeof(e));
+    console.log(e);
+}
+
+xGCEWorker.onmessage = function (e) {
+    // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
+    try {
+        // On retransmet directement le message à la page
+        console.log("[Iframe] send from Message Worker ",sPathExtension);
+        window.postMessage({SharedWorker: e.data}, sPathExtension);
+    }
+    catch (e) {
+        console.error(e);
+    }
+};
+xGCEWorker.start();
+
+console.log("[Iframe] [worker]");
+console.log(xGCESharedWorker);
+
+//xGCEWorker.start();
+//console.log("Content script [port started]");
+
+xGCEWorker.postMessage(["init", {sExtensionPath: browser.extension.getURL(""), sOptions: "", sContext: "Firefox"}]);
+//xGCEWorker.postMessage(["parse", {sText: "Vas... J’en aie mare...", sCountry: "FR", bDebug: false, bContext: false}]);
+//xGCEWorker.postMessage(["parseAndSpellcheck", {sText: oRequest.sText, sCountry: "FR", bDebug: false, bContext: false}]);
+//xGCEWorker.postMessage(["getListOfTokens", {sText: oRequest.sText}]);
+//xGCEWorker.postMessage(["textToTest", {sText: oRequest.sText, sCountry: "FR", bDebug: false, bContext: false}]);
+//xGCEWorker.postMessage(["fullTests"]);
+
+
+console.log('[Iframe] Set receivedMessageWeb');
+function receivedMessageWeb (oEvent) {
+    // Pour être sûr que ça vient bien de notre iframe ;)
+    if (typeof oEvent.data.sPage !== "undefined" && oEvent.data.sPage === oEvent.origin) {
+        console.log('[Iframe] Create the Sharedworker ', oEvent.origin);
+        sPathOrigin = oEvent.origin;
+    } else if (sPathOrigin === oEvent.origin && typeof oEvent.data.SharedWorker === "undefined") {
+        console.log('[Iframe] received (no SharedWorker):', oEvent, oEvent.origin);
+        // Les messages reçus maintenant ont un SharedWorker fonctionnel
+        // On transmet au SharedWorker uniquement si ça vient de la page web et on s’assure que ce n’est pas une réponse du SharedWorker.
+        // TODO: Établir un protocole de communication afin de traiter uniquement les messages utiles
+        console.log('[Iframe] exec command with SharedWorker');
+        xGCEWorker.postMessage(oEvent.data);
+        console.log('[Iframe] end send message to worker');
+    }
+}
+
+window.addEventListener("message", receivedMessageWeb, false);
+
+console.log('[Iframe] END');

Index: gc_lang/fr/webext/content_scripts/modify_page.js
==================================================================
--- gc_lang/fr/webext/content_scripts/modify_page.js
+++ gc_lang/fr/webext/content_scripts/modify_page.js
@@ -1,125 +1,217 @@
 // Modify page
 
 "use strict";
 
-console.log("Content script [start]");
 
 function showError (e) {
     console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
 }
 
-/*
-    Worker (separate thread to avoid freezing Firefox)
-*/
-let xGCEWorker = new SharedWorker(browser.extension.getURL("../gce_sharedworker.js"));
-
-xGCEWorker.onerror = function(e) {
-    console.log('There is an error with your worker!');
-    console.log(typeof(e));
-    console.log(e);
-    for (let sParam in e) {
-        console.log(sParam);
-        console.log(e.sParam);
-    }
-}
-
-xGCEWorker.port.onmessage = function (e) {
-    // https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
-    try {
-        switch (e.data[0]) {
-            case "grammar_errors":
-                console.log("GRAMMAR ERRORS (SHARE)");
-                console.log(e.data[1].aGrammErr);
-                //browser.runtime.sendMessage({sCommand: "grammar_errors", aGrammErr: e.data[1].aGrammErr});
-                break;
-            case "spelling_and_grammar_errors":
-                console.log("SPELLING AND GRAMMAR ERRORS (SHARE)");
-                console.log(e.data[1].aSpellErr);
-                console.log(e.data[1].aGrammErr);
-                break;
-            case "text_to_test_result":
-                console.log("TESTS RESULTS (SHARE)");
-                console.log(e.data[1]);
-                break;
-            case "fulltests_result":
-                console.log("TESTS RESULTS (SHARE)");
-                console.log(e.data[1]);
-                break;
-            case "options":
-                console.log("OPTIONS (SHARE)");
-                console.log(e.data[1]);
-                break;
-            case "tokens":
-                console.log("TOKENS (SHARE)");
-                console.log(e.data[1]);
-                let xLxgTab = browser.tabs.create({
-                    url: browser.extension.getURL("panel/lexicographer.html"),
-                });
-                xLxgTab.then(onCreated, onError);
-                break;
-            case "error":
-                console.log("ERROR (SHARE)");
-                console.log(e.data[1]);
-                break;
-            default:
-                console.log("Unknown command (SHARE): " + e.data[0]);
-        }
+console.log("Content script [start]");
+
+/*
+* Pour effectuer différent action sur la page en cours
+*/
+function receivedMessageFromIframe (oEvent) {
+    if (typeof oEvent.data.SharedWorker !== "undefined") {
+        console.log('[Web] received (from iframe (Sharedworker)):', oEvent);
+        let [sCommand, answer] = oEvent.data.SharedWorker;
+        console.log(sCommand);
+        switch (sCommand) {
+            case "grammar_errors":
+                console.log(answer.aGrammErr);
+                for (let oErr of answer.aGrammErr) {
+                    console.log(oErr);
+                }
+                break;
+        }
+    }
+}
+
+/*
+* Inject a script to page site to define extension path
+*/
+/*var xScript = document.createElement('script');
+xScript.textContent = 'var sExtensionPath = "'+browser.extension.getURL("")+'";';
+document.body.appendChild(xScript);*/
+
+
+/*
+* Creation d'une iframe pour communiquer entre la page visitée et le Shareworker
+*/
+var sFrameID = browser.extension.getURL("").split('/')[2];
+var xIframe = document.createElement('iframe');
+let xFrameContent = null;
+xIframe.id = sFrameID;
+xIframe.src = browser.extension.getURL('content_scripts/communicate.html');
+xIframe.hidden = true;
+xIframe.onload= function () {
+    console.log('[Web] Init protocol de communication');
+    //var xFrameContent = xIframe.contentWindow;
+    xFrameContent = document.getElementById(sFrameID).contentWindow;
+    xFrameContent.addEventListener("message", receivedMessageFromIframe, false);
+    try {
+        //La frame est chargé on envoie l'initialisation du Sharedworker
+        console.log('[Web] Initialise the worker :s');
+        console.log('[Web] Domaine ext: '+browser.extension.getURL(""));
+        xFrameContent.postMessage({sPage: location.origin.trim("/")}, browser.extension.getURL(""));
+        //Un petit test pour débogage ;)
+        console.log('[Web] Test the worker :s');
+        //xFrameContent.postMessage(["parse", {sText: "Vas... J’en aie mare...", sCountry: "FR", bDebug: false, bContext: false}], browser.extension.getURL(""));
+        //Un test qui envoie a tout le monde
+        xFrameContent.postMessage(["all", {}], browser.extension.getURL(""));
+        //Un test qui envoie aux autres
+        xFrameContent.postMessage(["other", {}], browser.extension.getURL(""));
+    }
+    catch (e) {
+        console.error(e);
+    }
+}
+document.body.appendChild(xIframe);
+
+
+function loadImage (sContainerClass, sImagePath) {
+    let xRequest;
+    xRequest = new XMLHttpRequest();
+    xRequest.open('GET', browser.extension.getURL("")+sImagePath, false);
+    xRequest.responseType = "arraybuffer";
+    xRequest.send();
+    let blobTxt = new Blob([xRequest.response], {type: 'image/png'});
+    let img = document.createElement('img');
+    img.src = (URL || webkitURL).createObjectURL(blobTxt);
+    Array.filter(document.getElementsByClassName(sContainerClass), function (oElem) {
+        oElem.appendChild(img);
+    });
+}
+
+
+console.log('[Web] La suite des initialisations');
+
+let nWrapper = 0;
+let xConjPanel = null;
+let xTFPanel = null;
+let xLxgPanel = null;
+let xGCPanel = null;
+
+function wrapTextareas () {
+    let lNode = document.getElementsByTagName("textarea");
+    for (let xNode of lNode) {
+        createWrapper(xNode);
+    }
+}
+
+function createWrapper (xTextArea) {
+    try {
+        let xParentElement = xTextArea.parentElement;
+        let xWrapper = document.createElement("div");
+        xWrapper.style = "padding: 5px; color: hsl(210, 10%, 90%); background-color: hsl(210, 50%, 50%); border-radius: 3px;";
+        xWrapper.id = nWrapper + 1;
+        nWrapper += 1;
+        xParentElement.insertBefore(xWrapper, xTextArea);
+        xWrapper.appendChild(xTextArea); // move textarea in wrapper
+        let xToolbar = createWrapperToolbar(xTextArea);
+        xWrapper.appendChild(xToolbar);
+        loadImage("GrammalecteTitle", "img/logo-16.png");
+    }
+    catch (e) {
+        showError(e);
+    }
+}
+
+
+let sButtonStyle = "display: inline-block; padding: 0 5px; margin-left: 5px; background-color: hsl(210, 50%, 60%); border-radius: 2px; cursor: pointer;";
+
+function createWrapperToolbar (xTextArea) {
+    try {
+        let xToolbar = document.createElement("div");
+        xToolbar.style = "display: flex; justify-content: flex-end; margin-top: 5px; padding: 5px 10px;";
+        /*let xLogo = document.createElement("img");
+        xLogo.src = browser.extension.getURL("img/logo-16.png");
+        xTitle.appendChild(xLogo);*/
+
+        let xImage = document.createElement("span");
+        xImage.className = "GrammalecteTitle";
+        xToolbar.appendChild(xImage);
+
+        xToolbar.appendChild(document.createTextNode("Grammalecte"));
+        let xConjButton = document.createElement("div");
+        xConjButton.textContent = "Conjuguer";
+        xConjButton.style = sButtonStyle;
+        xConjButton.onclick = function() {
+            createConjPanel();
+        };
+        xToolbar.appendChild(xConjButton);
+        let xTFButton = document.createElement("div");
+        xTFButton.textContent = "Formater";
+        xTFButton.style = sButtonStyle;
+        xTFButton.onclick = function() {
+            createTFPanel(xTextArea);
+        };
+        xToolbar.appendChild(xTFButton);
+        let xLxgButton = document.createElement("div");
+        xLxgButton.textContent = "Analyser";
+        xLxgButton.style = sButtonStyle;
+        xLxgButton.onclick = function() {
+            createLxgPanel(xTextArea);
+        };
+        xToolbar.appendChild(xLxgButton);
+        let xGCButton = document.createElement("div");
+        xGCButton.textContent = "Corriger";
+        xGCButton.style = sButtonStyle;
+        xGCButton.onclick = function() {
+            createGCPanel(xTextArea);
+        };
+        xToolbar.appendChild(xGCButton);
+        return xToolbar;
     }
     catch (e) {
         showError(e);
     }
-};
-
-console.log("Content script [worker]");
-console.log(xGCEWorker);
-
-
-//xGCEWorker.port.start();
-//console.log("Content script [port started]");
-
-//xGCEWorker.port.postMessage(["init", {sExtensionPath: browser.extension.getURL("."), sOptions: "", sContext: "Firefox"}]);
-
-console.log("Content script [worker initialzed]");
-
-xGCEWorker.port.postMessage(["parse", {sText: "Vas... J’en aie mare...", sCountry: "FR", bDebug: false, bContext: false}]);
-//xGCEWorker.port.postMessage(["parseAndSpellcheck", {sText: oRequest.sText, sCountry: "FR", bDebug: false, bContext: false}]);
-//xGCEWorker.port.postMessage(["getListOfTokens", {sText: oRequest.sText}]);
-//xGCEWorker.port.postMessage(["textToTest", {sText: oRequest.sText, sCountry: "FR", bDebug: false, bContext: false}]);
-//xGCEWorker.port.postMessage(["fullTests"]);
-
-
-
-function wrapTextareas() {;
-    let lNode = document.getElementsByTagName("textarea");
-    for (let xNode of lNode) {
-        createGCButton(xNode);
-    }
-}
-
-function createGCButton (xActiveTextZone) {
-    let xParentElement = xActiveTextZone.parentElement;
-    let xGCButton = document.createElement("div");
-    xGCButton.textContent = "@";
-    xGCButton.title = "Grammalecte"
-    xGCButton.style = "padding: 5px; color: #FFF; background-color: hsla(210, 50%, 50%, 80%); border-radius: 3px; cursor: pointer";
-    xGCButton.onclick = function() {
-        console.log(xActiveTextZone.value);
-    };
-    xParentElement.insertBefore(xGCButton, xActiveTextZone);
-}
-
-function removeEverything () {
-    while (document.body.firstChild) {
-        document.body.firstChild.remove();
-    }
-}
-
-function change (param) {
-    document.getElementById("title").setAttribute("background-color", "#809060");
-    console.log("param: " + param);
-    document.getElementById("title").setAttribute("background-color", "#FF0000");
+}
+
+
+function createConjPanel () {
+    console.log("Conjugueur");
+    if (xConjPanel !== null) {
+        xConjPanel.style.display = "block";
+    } else {
+        // create the panel
+        xConjPanel = document.createElement("div");
+        xConjPanel.style = "position: fixed; left: 50%; top: 50%; z-index: 100; height: 400px; margin-top: -200px; width: 600px; margin-left: -300px; border-radius: 10px;"
+                         + " color: hsl(210, 10%, 4%); background-color: hsl(210, 20%, 90%); border: 10px solid hsla(210, 20%, 70%, .5);";
+        xConjPanel.textContent = "Conjugueur";
+        xConjPanel.setAttribute("draggable", true);
+        xConjPanel.appendChild(createCloseButton(xConjPanel));
+        document.body.appendChild(xConjPanel);
+    }
+}
+
+
+
+function createTFPanel (xTextArea) {
+    console.log("Formateur de texte");
+}
+
+function createLxgPanel (xTextArea) {
+    console.log("Analyse");
+}
+
+function createGCPanel (xTextArea) {
+    console.log("Correction grammaticale");
+    xFrameContent.postMessage(["parse", {sText: xTextArea.value, sCountry: "FR", bDebug: false, bContext: false}], browser.extension.getURL(""));
+}
+
+function createCloseButton (xParentNode) {
+    let xButton = document.createElement("div");
+    xButton.style = "float: right; width: 20px; padding: 5px 10px; color: hsl(210, 0%, 100%); text-align: center;"
+                  + "font-size: 20px; font-weight: bold; background-color: hsl(0, 80%, 50%); border-radius: 0 0 0 3px; cursor: pointer;";
+    xButton.textContent = "×";
+    xButton.onclick = function () {
+        xParentNode.style.display = "none";
+    }
+    return xButton;
 }
 
 
 /*
     Assign do_something() as a listener for messages from the extension.

Index: gc_lang/fr/webext/gce_sharedworker.js
==================================================================
--- gc_lang/fr/webext/gce_sharedworker.js
+++ gc_lang/fr/webext/gce_sharedworker.js
@@ -57,60 +57,97 @@
 /*
     Message Event Object
     https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent
 */
 
-let xPort = null;
+function showError (e) {
+    for (let sParam in e) {
+        console.log(sParam);
+        console.log(e[sParam]);
+    }
+}
+
+var xListPort = xListPort || [];
+//var xPort = null;
 
-onconnect = function(e) {
+self.addEventListener("connect", function(e){
     console.log("START CONNECTION");
-    xPort = e.ports[0];
+    var xPort = e.ports[0];
+    xListPort.push(xPort);
+
 
-    xPort.onmessage = function (e) {
+    xPort.addEventListener("message", function(e){
+        console.log("[Sharedworker] ONMESSAGE");
         console.log(e);
         console.log(e.data[0]);
+        let oReplyToSend;
         let oParam = e.data[1];
         switch (e.data[0]) {
             case "init":
-                loadGrammarChecker(oParam.sExtensionPath, oParam.sOptions, oParam.sContext);
+                oReplyToSend = loadGrammarChecker(oParam.sExtensionPath, oParam.sOptions, oParam.sContext);
                 break;
             case "parse":
-                parse(oParam.sText, oParam.sCountry, oParam.bDebug, oParam.bContext);
+                oReplyToSend = parse(oParam.sText, oParam.sCountry, oParam.bDebug, oParam.bContext);
                 break;
             case "parseAndSpellcheck":
-                parseAndSpellcheck(oParam.sText, oParam.sCountry, oParam.bDebug, oParam.bContext);
+                oReplyToSend = parseAndSpellcheck(oParam.sText, oParam.sCountry, oParam.bDebug, oParam.bContext);
                 break;
             case "getOptions":
-                getOptions();
+                oReplyToSend = getOptions();
                 break;
             case "getDefaultOptions":
-                getDefaultOptions();
+                oReplyToSend = getDefaultOptions();
                 break;
             case "setOptions":
-                setOptions(oParam.sOptions);
+                oReplyToSend = setOptions(oParam.sOptions);
                 break;
             case "setOption":
-                setOption(oParam.sOptName, oParam.bValue);
+                oReplyToSend = setOption(oParam.sOptName, oParam.bValue);
                 break;
             case "resetOptions":
-                resetOptions();
+                oReplyToSend = resetOptions();
                 break;
             case "textToTest":
-                textToTest(oParam.sText, oParam.sCountry, oParam.bDebug, oParam.bContext);
+                oReplyToSend = textToTest(oParam.sText, oParam.sCountry, oParam.bDebug, oParam.bContext);
                 break;
             case "fullTests":
-                fullTests();
+                oReplyToSend = fullTests();
                 break;
             case "getListOfTokens":
-                getListOfTokens(oParam.sText);
+                oReplyToSend = getListOfTokens(oParam.sText);
+                break;
+            case "other":
+                oReplyToSend = "Message to Other";
+                break;
+            case "all":
+                oReplyToSend = "Message to All";
                 break;
             default:
-                console.log("Unknown command: " + e.data[0]);
+                console.log("Unknown command: " + showError(e.data[0]));
+        }
+
+        console.log("[Sharedworker PortList] ",xListPort,this);
+        if ( e.data[0] == "all" ) {
+            console.log("[Sharedworker All] Number of client: "+xListPort.length);
+            xListPort.forEach(function(client){
+                client.postMessage(oReplyToSend);
+            });
+        } else if ( e.data[0] == "other" ) {
+            console.log("[Sharedworker Other] Number of client: "+xListPort.length);
+            xListPort.forEach(function(client){
+                if (client !== this){
+                    client.postMessage(oReplyToSend);
+                }
+            });
+        } else {
+            console.log("[Sharedworker Direct reply]");
+            this.postMessage(oReplyToSend);
         }
-    }
-    //xPort.start();
-}
+
+    });
+    xPort.start();
+});
 
 
 let oDict = null;
 let oTokenizer = null;
 let oLxg = null;
@@ -130,52 +167,52 @@
         oLxg = new Lexicographe(oDict);
         if (sGCOptions !== "") {
             gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
         }
         oTokenizer = new Tokenizer("fr");
-        tests();
+        //tests();
         // we always retrieve options from the gc_engine, for setOptions filters obsolete options
-        xPort.postMessage(["options", gc_engine.getOptions().gl_toString()]);
+        return ["options", gc_engine.getOptions().gl_toString()];
     }
     catch (e) {
         console.error(e.fileName + "\n" + e.name + "\nline: " + e.lineNumber + "\n" + e.message);
-        xPort.postMessage(["error", e.message]);
+        return ["error", e.message];
     }
 }
 
 function parse (sText, sCountry, bDebug, bContext) {
     let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
-    xPort.postMessage(["grammar_errors", {aGrammErr: aGrammErr}]);
+    return ["grammar_errors", {aGrammErr: aGrammErr}];
 }
 
 function parseAndSpellcheck (sText, sCountry, bDebug, bContext) {
     let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
     let aSpellErr = oTokenizer.getSpellingErrors(sText, oDict);
-    xPort.postMessage(["spelling_and_grammar_errors", {aGrammErr: aGrammErr, aSpellErr: aSpellErr}]);
+    return ["spelling_and_grammar_errors", {aGrammErr: aGrammErr, aSpellErr: aSpellErr}];
 }
 
 function getOptions () {
-    xPort.postMessage(["options", gc_engine.getOptions().gl_toString()]);
+    return ["options", gc_engine.getOptions().gl_toString()];
 }
 
 function getDefaultOptions () {
-    xPort.postMessage(["options", gc_engine.getDefaultOptions().gl_toString()]);
+    return ["options", gc_engine.getDefaultOptions().gl_toString()];
 }
 
 function setOptions (sGCOptions) {
     gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
-    xPort.postMessage(["options", gc_engine.getOptions().gl_toString()]);
+    return ["options", gc_engine.getOptions().gl_toString()];
 }
 
 function setOption (sOptName, bValue) {
     gc_engine.setOptions(new Map([ [sOptName, bValue] ]));
-    xPort.postMessage(["options", gc_engine.getOptions().gl_toString()]);
+    return ["options", gc_engine.getOptions().gl_toString()];
 }
 
 function resetOptions () {
     gc_engine.resetOptions();
-    xPort.postMessage(["options", gc_engine.getOptions().gl_toString()]);
+    return ["options", gc_engine.getOptions().gl_toString()];
 }
 
 function tests () {
     console.log(conj.getConj("devenir", ":E", ":2s"));
     console.log(mfsp.getMasForm("emmerdeuse", true));
@@ -187,25 +224,23 @@
     }
 }
 
 function textToTest (sText, sCountry, bDebug, bContext) {
     if (!gc_engine || !oDict) {
-        xPort.postMessage(["error", "# Error: grammar checker or dictionary not loaded."]);
-        return;
+        return ["error", "# Error: grammar checker or dictionary not loaded."];
     }
     let aGrammErr = gc_engine.parse(sText, sCountry, bDebug, bContext);
     let sMsg = "";
     for (let oErr of aGrammErr) {
         sMsg += text.getReadableError(oErr) + "\n";
     }
-    xPort.postMessage(["text_to_test_result", sMsg]);
+    return ["text_to_test_result", sMsg];
 }
 
 function fullTests (sGCOptions='{"nbsp":true, "esp":true, "unit":true, "num":true}') {
     if (!gc_engine || !oDict) {
-        xPort.postMessage(["error", "# Error: grammar checker or dictionary not loaded."]);
-        return;
+        return ["error", "# Error: grammar checker or dictionary not loaded."];
     }
     let dMemoOptions = gc_engine.getOptions();
     if (sGCOptions) {
         gc_engine.setOptions(helpers.objectToMap(JSON.parse(sGCOptions)));
     }
@@ -213,11 +248,11 @@
     for (let sRes of oTest.testParse()) {
         sMsg += sRes + "\n";
         console.log(sRes);
     }
     gc_engine.setOptions(dMemoOptions);
-    xPort.postMessage(["fulltests_result", sMsg]);
+    return ["fulltests_result", sMsg];
 }
 
 
 // Lexicographer
 
@@ -229,12 +264,12 @@
             aRes = oLxg.getInfoForToken(oToken);
             if (aRes) {
                 aElem.push(aRes);
             }
         }
-        xPort.postMessage(["tokens", aElem]);
+        return ["tokens", aElem];
     }
     catch (e) {
         helpers.logerror(e);
-        xPort.postMessage(["error", e.message]);
+        return ["error", e.message];
     }
 }

Index: gc_lang/fr/webext/manifest.json
==================================================================
--- gc_lang/fr/webext/manifest.json
+++ gc_lang/fr/webext/manifest.json
@@ -42,11 +42,14 @@
   "web_accessible_resources": [
     "grammalecte/_dictionaries/French.json",
     "grammalecte/fr/conj_data.json",
     "grammalecte/fr/mfsp_data.json",
     "grammalecte/fr/phonet_data.json",
-    "grammalecte/fr/tests_data.json"
+    "grammalecte/fr/tests_data.json",
+    "content_scripts/communicate.html",
+    "content_scripts/communicate.js",
+    "img/logo-16.png"
   ],
   "permissions": [
     "activeTab",
     "contextMenus"
   ],

Index: gc_lang/fr/webext/panel/main.html
==================================================================
--- gc_lang/fr/webext/panel/main.html
+++ gc_lang/fr/webext/panel/main.html
@@ -36,10 +36,11 @@
 
       <div id="page">
 
         <section id="home_page" class="page">
           <h1>GRAMMALECTE</h1>
+          <a href="https://www.dicollecte.org/test.html">TEST TEXTAREA</a>
         </section>
 
         <section id="gc_page" class="page">
           <h1>CORRECTEUR GRAMMATICAL</h1>
           <div id="paragraphs_list"></div>