diff -Nru tbsync-1.5/bootstrap.js tbsync-1.7/bootstrap.js --- tbsync-1.5/bootstrap.js 2019-02-08 16:43:08.000000000 +0000 +++ tbsync-1.7/bootstrap.js 2019-02-26 16:25:49.000000000 +0000 @@ -15,31 +15,20 @@ Components.utils.import("resource://gre/modules/Task.jsm"); Components.utils.import("resource://gre/modules/osfile.jsm"); -let window = null; - //Observer to catch loading of thunderbird main window let onLoadObserver = { observe: function(aSubject, aTopic, aData) { - if (window === null) { - window = Services.wm.getMostRecentWindow("mail:3pane"); - if (window) { - //init TbSync - window.tbSync = tbSync; - tbSync.init(window); - } else { - tbSync.dump("FAIL", "Could not init TbSync, because mail:3pane window not found."); - } + let mainWindow = Services.wm.getMostRecentWindow("mail:3pane"); + if (mainWindow) { + //init TbSync + mainWindow.tbSyncReference = tbSync; + tbSync.init(mainWindow); + } else { + tbSync.dump("FAIL", "Could not init TbSync, because mail:3pane window not found."); } } } -let onLoadDoneObserver = { - observe: function(aSubject, aTopic, aData) { - forEachOpenWindow(loadIntoWindow); - Services.wm.addListener(WindowListener); - } -} - function install(data, reason) { } @@ -61,7 +50,6 @@ branch.setIntPref("log.userdatalevel", 0); //0 - metadata (no incomming xml/wbxml, only parsed data without userdata (except failing items)) 1 - including userdata, 2 - raw xml , 3 - raw wbxml Components.utils.import("chrome://tbsync/content/tbsync.jsm"); - Components.utils.import("chrome://tbsync/content/OverlayManager.jsm"); //Map local writeAsyncJSON into tbSync tbSync.writeAsyncJSON = writeAsyncJSON; @@ -69,10 +57,8 @@ //add startup observers Services.obs.addObserver(onLoadObserver, "mail-startup-done", false); Services.obs.addObserver(onLoadObserver, "tbsync.init", false); - Services.obs.addObserver(onLoadDoneObserver, "tbsync.init.done", false); tbSync.addonData = data; - tbSync.overlayManager = new OverlayManager(data, {verbose:0}); if (reason != APP_STARTUP) { //during startup, we wait until mail-startup-done fired, for all other reasons we need to fire our own init @@ -92,12 +78,12 @@ //remove startup observer Services.obs.removeObserver(onLoadObserver, "mail-startup-done"); Services.obs.removeObserver(onLoadObserver, "tbsync.init"); - Services.obs.removeObserver(onLoadDoneObserver, "tbsync.init.done"); //call cleanup of the tbSync module - forEachOpenWindow(unloadFromWindow); - Services.wm.removeListener(WindowListener); tbSync.cleanup(); + + let mainWindow = Services.wm.getMostRecentWindow("mail:3pane"); + delete mainWindow.tbSyncReference; //abort write timers and write current file content to disk if (tbSync.enabled) { @@ -124,55 +110,6 @@ - -function forEachOpenWindow(todo) // Apply a function to all open windows -{ - var windows = Services.wm.getEnumerator(null); - while (windows.hasMoreElements()) { - todo(windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow)); - } -} - -function loadIntoWindow(window) { - //do not inject into main window, because we have done that in tbSync.init() to provide an option to the user to get the Ooops message, - //in case something went wrong during init (and we do not reach this point) - if (window.location.href != "chrome://messenger/content/messenger.xul" && tbSync.overlayManager.hasRegisteredOverlays(window)) { - window.tbSync = tbSync; - tbSync.overlayManager.injectAllOverlays(window); - } -} - -function unloadFromWindow(window) { - if (tbSync.overlayManager.hasRegisteredOverlays(window)) { - tbSync.overlayManager.removeAllOverlays(window); - window.tbSync = null; - } -} - -var WindowListener = -{ - onOpenWindow: function(xulWindow) - { - var window = xulWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow); - function onWindowLoad() - { - window.removeEventListener("load", onWindowLoad); - loadIntoWindow(window); - } - window.addEventListener("load", onWindowLoad); - }, - onCloseWindow: function(xulWindow) { }, - onWindowTitleChange: function(xulWindow, newTitle) { } -}; - -/* - could be replaced in TB61: - - https://dxr.mozilla.org/comm-central/rev/18881dd127e3b0c0d3f97390c9094e309d4dd9c1/mail/test/resources/jsbridge/jsbridge/extension/bootstrap.js#17 - - https://dxr.mozilla.org/comm-central/rev/18881dd127e3b0c0d3f97390c9094e309d4dd9c1/common/src/extensionSupport.jsm#151 -*/ - - - function writeAsyncJSON (obj, filename) { let filepath = tbSync.getAbsolutePath(filename); diff -Nru tbsync-1.5/content/abServerSearch.js tbsync-1.7/content/abServerSearch.js --- tbsync-1.5/content/abServerSearch.js 2019-02-08 16:43:08.000000000 +0000 +++ tbsync-1.7/content/abServerSearch.js 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -/* - * This file is part of TbSync. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - - "use strict"; - -Components.utils.import("resource://gre/modules/Task.jsm"); - -//this is used in multiple places (addressbook + contactsidebar) so we cannot use objects of tbSync to store states, but need to store distinct variables -//in the window scope -> window.tbSync_XY - -var serverSearch = {}; - -serverSearch.eventHandlerWindowReference = function (window) { - this.window = window; - - this.removeEventListener = function (element, type, bubble) { - element.removeEventListener(type, this, bubble); - }; - - this.addEventListener = function (element, type, bubble) { - element.addEventListener(type, this, bubble); - }; - - this.handleEvent = function(event) { - switch(event.type) { - case 'input': - serverSearch.onSearchInputChanged(this.window); - break; - case "select": - { - serverSearch.clearServerSearchResults(this.window); - let searchbox = window.document.getElementById("peopleSearchInput"); - let target = window.GetSelectedDirectory(); - if (searchbox && target) { - let folders = tbSync.db.findFoldersWithSetting("target", target); - if (folders.length == 1 && tbSync[tbSync.db.getAccountSetting(folders[0].account, "provider")].abServerSearch) { - searchbox.setAttribute("placeholder", tbSync.getLocalizedMessage("addressbook.searchgal::" + tbSync.db.getAccountSetting(folders[0].account, "accountname"))); - } else { - searchbox.setAttribute("placeholder", tbSync.getLocalizedMessage((target == "moz-abdirectory://?") ? "addressbook.searchall" : "addressbook.searchthis")); - } - } - } - break; - } - }; - return this; -} - -serverSearch.searchValuePoll = function (window, searchbox) { - let value = searchbox.value; - if (window.tbSync_searchValue != "" && value == "") { - serverSearch.clearServerSearchResults(window); - } - window.tbSync_searchValue = value; -} - -serverSearch.onInjectIntoAddressbook = function (window) { - window.tbSync_eventHandler = serverSearch.eventHandlerWindowReference(window); - - let searchbox = window.document.getElementById("peopleSearchInput"); - if (searchbox) { - window.tbSync_searchValue = searchbox.value; - window.tbSync_searchValuePollHandler = window.setInterval(function(){serverSearch.searchValuePoll(window, searchbox)}, 200); - window.tbSync_eventHandler.addEventListener(searchbox, "input", false); - } - - let dirtree = window.document.getElementById("dirTree"); - if (dirtree) { - window.tbSync_eventHandler.addEventListener(dirtree, "select", false); - } -} - -serverSearch.onRemoveFromAddressbook = function (window) { - let searchbox = window.document.getElementById("peopleSearchInput"); - if (searchbox) { - window.tbSync_eventHandler.removeEventListener(searchbox, "input", false); - window.clearInterval(window.tbSync_searchValuePollHandler); - } - - let dirtree = window.document.getElementById("dirTree"); - if (dirtree) { - window.tbSync_eventHandler.removeEventListener(dirtree, "select", false); - } -} - -serverSearch.clearServerSearchResults = function (window) { - let target = window.GetSelectedDirectory(); - if (target == "moz-abdirectory://?") return; //global search not yet(?) supported - - let addressbook = tbSync.getAddressBookObject(target); - if (addressbook) { - try { - let oldresults = addressbook.getCardsFromProperty("X-Server-Searchresult", "TbSync", true); - let cardsToDelete = Components.classes["@mozilla.org/array;1"].createInstance(Components.interfaces.nsIMutableArray); - while (oldresults.hasMoreElements()) { - cardsToDelete.appendElement(oldresults.getNext(), false); - } - addressbook.deleteCards(cardsToDelete); - } catch (e) { - //if getCardsFromProperty is not implemented, do nothing - } - } -} - -serverSearch.onSearchInputChanged = Task.async (function* (window) { - let target = window.GetSelectedDirectory(); - if (target == "moz-abdirectory://?") return; //global search not yet(?) supported - - let folders = tbSync.db.findFoldersWithSetting("target", target); - if (folders.length == 1) { - let searchbox = window.document.getElementById("peopleSearchInput"); - let query = searchbox.value; - let addressbook = tbSync.getAddressBookObject(target); - - let account = folders[0].account; - let provider = tbSync.db.getAccountSetting(account, "provider"); - let accountname = tbSync.db.getAccountSetting(account, "accountname"); - if (tbSync[provider].abServerSearch) { - - if (query.length<3) { - //delete all old results - serverSearch.clearServerSearchResults(window); - window.onEnterInSearchBar(); - } else { - window.tbSync_serverSearchNextQuery = query; - if (window.tbSync_serverSearchBusy) { - } else { - window.tbSync_serverSearchBusy = true; - while (window.tbSync_serverSearchBusy) { - - yield tbSync.sleep(1000); - let currentQuery = window.tbSync_serverSearchNextQuery; - window.tbSync_serverSearchNextQuery = ""; - let results = yield tbSync[provider].abServerSearch (account, currentQuery, "search"); - - //delete all old results - serverSearch.clearServerSearchResults(window); - - for (let count = 0; count < results.length; count++) { - let newItem = Components.classes["@mozilla.org/addressbook/cardproperty;1"].createInstance(Components.interfaces.nsIAbCard); - for (var prop in results[count].properties) { - if (results[count].properties.hasOwnProperty(prop)) { - newItem.setProperty(prop, results[count].properties[prop]); - } - } - newItem.setProperty("X-Server-Searchresult", "TbSync"); - addressbook.addCard(newItem); - } - window.onEnterInSearchBar(); - if (window.tbSync_serverSearchNextQuery == "") window.tbSync_serverSearchBusy = false; - } - } - } - } - } -}) diff -Nru tbsync-1.5/content/manager/accounts.js tbsync-1.7/content/manager/accounts.js --- tbsync-1.5/content/manager/accounts.js 2019-02-08 16:43:08.000000000 +0000 +++ tbsync-1.7/content/manager/accounts.js 2019-02-26 16:25:49.000000000 +0000 @@ -547,7 +547,7 @@ */ updateAccountSyncStateObserver: { observe: function (aSubject, aTopic, aData) { - if (aData != "") { + if (aData) { //since we want rotating arrows on each syncstate change, we need to run this on each syncstate tbSyncAccounts.updateAccountStatus(aData); } diff -Nru tbsync-1.5/content/manager/installProvider.xul tbsync-1.7/content/manager/installProvider.xul --- tbsync-1.5/content/manager/installProvider.xul 2019-02-08 16:43:08.000000000 +0000 +++ tbsync-1.7/content/manager/installProvider.xul 2019-02-26 16:25:49.000000000 +0000 @@ -21,7 +21,7 @@ &manager.installprovider.link; - + diff -Nru tbsync-1.5/content/OverlayManager.jsm tbsync-1.7/content/OverlayManager.jsm --- tbsync-1.5/content/OverlayManager.jsm 2019-02-08 16:43:08.000000000 +0000 +++ tbsync-1.7/content/OverlayManager.jsm 2019-02-26 16:25:49.000000000 +0000 @@ -14,8 +14,7 @@ Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Task.jsm"); -function OverlayManager(addonData, options = {}) { - this.addonData = addonData; +function OverlayManager(options = {}) { this.registeredOverlays = {}; this.overlays = {}; this.stylesheets = {}; @@ -28,12 +27,50 @@ +/* + could be replaced in TB61: + - https://dxr.mozilla.org/comm-central/rev/18881dd127e3b0c0d3f97390c9094e309d4dd9c1/mail/test/resources/jsbridge/jsbridge/extension/bootstrap.js#17 + - https://dxr.mozilla.org/comm-central/rev/18881dd127e3b0c0d3f97390c9094e309d4dd9c1/common/src/extensionSupport.jsm#151 +*/ + this.windowListener = { + that : this, + onOpenWindow: function(xulWindow) { + let window = xulWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow); + + function onWindowLoad() { + //window.removeEventListener("load", onWindowLoad); + this.injectAllOverlays(window); + } + window.addEventListener("load", onWindowLoad.bind(this.that)); + }, + onCloseWindow: function(xulWindow) { }, + onWindowTitleChange: function(xulWindow, newTitle) { } + }; + + this.startObserving = function () { + let windows = Services.wm.getEnumerator(null); + while (windows.hasMoreElements()) { + let window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow); + //inject overlays for this window + this.injectAllOverlays(window); + } + Services.wm.addListener(this.windowListener); + }; + this.stopObserving = function () { + Services.wm.removeListener(this.windowListener); + let windows = Services.wm.getEnumerator(null); + while (windows.hasMoreElements()) { + let window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow); + //remove overlays (if any) + this.removeAllOverlays(window); + } + }; this.hasRegisteredOverlays = function (window) { return this.registeredOverlays.hasOwnProperty(window.location.href); @@ -98,90 +135,118 @@ + this.injectAllOverlays = function (window, _href = null) { + let href = (_href === null) ? window.location.href : _href; + for (let i=0; this.registeredOverlays[href] && i < this.registeredOverlays[href].length; i++) { + this.injectOverlay(window, this.registeredOverlays[href][i]); + } + }; + this.removeAllOverlays = function (window) { + if (!this.hasRegisteredOverlays(window)) + return; + + for (let i=0; i < this.registeredOverlays[window.location.href].length; i++) { + this.removeOverlay(window, this.registeredOverlays[window.location.href][i]); + } + }; - this.injectAllOverlays = function (window, _href = null) { - let href = (_href === null) ? window.location.href : _href; - for (let i=0; this.registeredOverlays[href] && i < this.registeredOverlays[href].length; i++) { - if (this.options.verbose>2) Services.console.logStringMessage("[OverlayManager] Injecting: " + this.registeredOverlays[href][i]); - let rootNode = this.overlays[this.registeredOverlays[href][i]]; - if (rootNode) { - let overlayNode = rootNode.documentElement; - if (overlayNode) { - //get and load scripts - let scripts = this.getScripts(rootNode, overlayNode); - for (let i=0; i < scripts.length; i++){ - if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Loading: " + scripts[i]); - Services.scriptloader.loadSubScript(scripts[i], window); - } + this.injectOverlay = function (window, overlay) { + if (!window.hasOwnProperty("injectedOverlays")) window.injectedOverlays = []; - //eval onbeforeinject, if that returns false, inject is aborted - let inject = true; - if (overlayNode.hasAttribute("onbeforeinject")) { - let onbeforeinject = overlayNode.getAttribute("onbeforeinject"); - if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Executing: " + onbeforeinject); - // the source for this eval is part of this XPI, cannot be changed by user. - inject = window.eval(onbeforeinject); - } + if (window.injectedOverlays.includes(overlay)) { + if (this.options.verbose>2) Services.console.logStringMessage("[OverlayManager] NOT Injecting: " + overlay); + return; + } + + let rootNode = this.overlays[overlay]; - if (inject) { - //get urls of stylesheets to add preloaded files - let styleSheetUrls = this.getStyleSheetUrls(rootNode); - for (let i=0; i3) Services.console.logStringMessage("[OverlayManager] Stylesheet: " + styleSheetUrls[i]); - } - - this.insertXulOverlay(window, overlayNode.children); - - //execute oninject - if (overlayNode.hasAttribute("oninject")) { - let oninject = overlayNode.getAttribute("oninject"); - if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Executing: " + oninject); - // the source for this eval is part of this XPI, cannot be changed by user. - window.eval(oninject); - } + if (rootNode) { + let overlayNode = rootNode.documentElement; + if (overlayNode) { + //get and load scripts + let scripts = this.getScripts(rootNode, overlayNode); + for (let i=0; i < scripts.length; i++){ + if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Loading: " + scripts[i]); + Services.scriptloader.loadSubScript(scripts[i], window); + } + + //eval onbeforeinject, if that returns false, inject is aborted + let inject = true; + if (overlayNode.hasAttribute("onbeforeinject")) { + let onbeforeinject = overlayNode.getAttribute("onbeforeinject"); + if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Executing: " + onbeforeinject); + // the source for this eval is part of this XPI, cannot be changed by user. + inject = window.eval(onbeforeinject); + } + + if (inject) { + if (this.options.verbose>2) Services.console.logStringMessage("[OverlayManager] Injecting: " + overlay); + window.injectedOverlays.push(overlay); + + //get urls of stylesheets to add preloaded files + let styleSheetUrls = this.getStyleSheetUrls(rootNode); + for (let i=0; i3) Services.console.logStringMessage("[OverlayManager] Stylesheet: " + styleSheetUrls[i]); + } + + this.insertXulOverlay(window, overlayNode.children); + + //execute oninject + if (overlayNode.hasAttribute("oninject")) { + let oninject = overlayNode.getAttribute("oninject"); + if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Executing: " + oninject); + // the source for this eval is part of this XPI, cannot be changed by user. + window.eval(oninject); } } } } }; - - this.removeAllOverlays = function (window) { - for (let i=0; i < this.registeredOverlays[window.location.href].length; i++) { - if (this.options.verbose>2) Services.console.logStringMessage("[OverlayManager] Removing: " + this.registeredOverlays[window.location.href][i]); - -// let rootNode = this.getDataFromXULString(window, this.overlays[this.registeredOverlays[window.location.href][i]]); - let rootNode = this.overlays[this.registeredOverlays[window.location.href][i]]; - let overlayNode = rootNode.documentElement; - - if (overlayNode.hasAttribute("onremove")) { - let onremove = overlayNode.getAttribute("onremove"); - if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Executing: " + onremove); - // the source for this eval is part of this XPI, cannot be changed by user. - window.eval(onremove); - } - this.removeXulOverlay(window, overlayNode.children); + this.removeOverlay = function (window, overlay) { + if (!window.hasOwnProperty("injectedOverlays")) window.injectedOverlays = []; - //get urls of stylesheets to remove styte tag - let styleSheetUrls = this.getStyleSheetUrls(rootNode); - for (let i=0; i2) Services.console.logStringMessage("[OverlayManager] NOT Removing: " + overlay); + return; + } + + if (this.options.verbose>2) Services.console.logStringMessage("[OverlayManager] Removing: " + overlay); + window.injectedOverlays = window.injectedOverlays.filter(e => (e != overlay)); + +// let rootNode = this.getDataFromXULString(window, this.overlays[overlay]); + let rootNode = this.overlays[overlay]; + let overlayNode = rootNode.documentElement; + + if (overlayNode.hasAttribute("onremove")) { + let onremove = overlayNode.getAttribute("onremove"); + if (this.options.verbose>3) Services.console.logStringMessage("[OverlayManager] Executing: " + onremove); + // the source for this eval is part of this XPI, cannot be changed by user. + window.eval(onremove); + } + + this.removeXulOverlay(window, overlayNode.children); + + //get urls of stylesheets to remove styte tag + let styleSheetUrls = this.getStyleSheetUrls(rootNode); + for (let i=0; i - - - - -