diff options
Diffstat (limited to 'comm/mailnews/search/src/PeriodicFilterManager.jsm')
-rw-r--r-- | comm/mailnews/search/src/PeriodicFilterManager.jsm | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/comm/mailnews/search/src/PeriodicFilterManager.jsm b/comm/mailnews/search/src/PeriodicFilterManager.jsm new file mode 100644 index 0000000000..3d6f52c504 --- /dev/null +++ b/comm/mailnews/search/src/PeriodicFilterManager.jsm @@ -0,0 +1,202 @@ +/* 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/. */ + +/* + * Execute periodic filters at the correct rate. + * + * The only external call required for this is setupFiltering(). This should be + * called before the mail-startup-done notification. + */ + +const EXPORTED_SYMBOLS = ["PeriodicFilterManager"]; + +const { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +const log = console.createInstance({ + prefix: "mail.periodicfilters", + maxLogLevel: "Warn", + maxLogLevelPref: "mail.periodicfilters.loglevel", +}); + +var PeriodicFilterManager = { + _timer: null, + _checkRateMilliseconds: 60000, // How often do we check if servers are ready to run? + _defaultFilterRateMinutes: Services.prefs + .getDefaultBranch("") + .getIntPref("mail.server.default.periodicFilterRateMinutes"), + _initialized: false, // Has this been initialized? + _running: false, // Are we executing filters already? + + // Initial call to begin startup. + setupFiltering() { + if (this._initialized) { + return; + } + + this._initialized = true; + Services.obs.addObserver(this, "mail-startup-done"); + }, + + // Main call to start the periodic filter process + init() { + log.info("PeriodicFilterManager init()"); + // set the next filter time + for (let server of MailServices.accounts.allServers) { + let nowTime = parseInt(Date.now() / 60000); + // Make sure that the last filter time of all servers was in the past. + let lastFilterTime = server.getIntValue("lastFilterTime"); + // Schedule next filter run. + let nextFilterTime = + lastFilterTime < nowTime + ? lastFilterTime + this.getServerPeriod(server) + : nowTime; + server.setIntValue("nextFilterTime", nextFilterTime); + } + + // kickoff the timer to run periodic filters + this._timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); + this._timer.initWithCallback( + this, + this._checkRateMilliseconds, + Ci.nsITimer.TYPE_REPEATING_SLACK + ); + Services.obs.addObserver(this, "quit-application-granted"); + }, + + /** + * Periodic callback to check if any periodic filters need to be run. + * + * The periodic filter manager does not guarantee that filters will be run + * precisely at the specified interval. + * The server may be busy (e.g. downloading messages) or another filter run + * is still ongoing, in which cases running periodic filter of any server + * may be postponed. + */ + notify(timer) { + log.debug("PeriodicFilterManager timer callback"); + if (this._running) { + log.debug("PeriodicFilterManager Previous filter run still executing"); + return; + } + this._running = true; + let nowTime = parseInt(Date.now() / 60000); + for (let server of MailServices.accounts.allServers) { + if (!server.canHaveFilters) { + continue; + } + if (server.getIntValue("nextFilterTime") > nowTime) { + continue; + } + if (server.serverBusy) { + continue; + } + + // Schedule next time this account's filters should be run. + server.setIntValue( + "nextFilterTime", + nowTime + this.getServerPeriod(server) + ); + server.setIntValue("lastFilterTime", nowTime); + + // Build a temporary list of periodic filters. + // XXX TODO: make applyFiltersToFolders() take a filterType instead (bug 1551043). + let curFilterList = server.getFilterList(null); + let tempFilterList = MailServices.filters.getTempFilterList( + server.rootFolder + ); + let numFilters = curFilterList.filterCount; + tempFilterList.loggingEnabled = curFilterList.loggingEnabled; + tempFilterList.logStream = curFilterList.logStream; + let newFilterIndex = 0; + for (let i = 0; i < numFilters; i++) { + let curFilter = curFilterList.getFilterAt(i); + // Only add enabled, UI visible filters that are of the Periodic type. + if ( + curFilter.enabled && + !curFilter.temporary && + curFilter.filterType & Ci.nsMsgFilterType.Periodic + ) { + tempFilterList.insertFilterAt(newFilterIndex, curFilter); + newFilterIndex++; + } + } + if (newFilterIndex == 0) { + continue; + } + let foldersToFilter = server.rootFolder.getFoldersWithFlags( + Ci.nsMsgFolderFlags.Inbox + ); + if (foldersToFilter.length == 0) { + continue; + } + + log.debug( + "PeriodicFilterManager apply periodic filters to server " + + server.prettyName + ); + MailServices.filters.applyFiltersToFolders( + tempFilterList, + foldersToFilter, + null + ); + } + this._running = false; + }, + + /** + * Gets the periodic filter interval for the given server. + * If the server's interval is not sane, clean it up. + * + * @param {nsIMsgIncomingServer} server - The server to return interval for. + */ + getServerPeriod(server) { + const minimumPeriodMinutes = 1; + let serverRateMinutes = server.getIntValue("periodicFilterRateMinutes"); + // Check if period is too short. + if (serverRateMinutes < minimumPeriodMinutes) { + // If the server.default pref is too low, clear that one first. + if ( + Services.prefs.getIntPref( + "mail.server.default.periodicFilterRateMinutes" + ) == serverRateMinutes + ) { + Services.prefs.clearUserPref( + "mail.server.default.periodicFilterRateMinutes" + ); + } + // If the server still has its own specific value and it is still too low, sanitize it. + if ( + server.getIntValue("periodicFilterRateMinutes") < minimumPeriodMinutes + ) { + server.setIntValue( + "periodicFilterRateMinutes", + this._defaultFilterRateMinutes + ); + } + + return this._defaultFilterRateMinutes; + } + + return serverRateMinutes; + }, + + observe(subject, topic, data) { + Services.obs.removeObserver(this, topic); + if (topic == "mail-startup-done") { + this.init(); + } else if (topic == "quit-application-granted") { + this.shutdown(); + } + }, + + shutdown() { + log.info("PeriodicFilterManager shutdown"); + if (this._timer) { + this._timer.cancel(); + this._timer = null; + } + }, +}; |