/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Mozilla Community QA Extension * * The Initial Developer of the Original Code is the Mozilla Corporation. * Portions created by the Initial Developer are Copyright (C) 2007 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Zach Lipton * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ document.addEventListener('load', function() { window.setInterval(qaNotifications.updateNotificationStore(), 3600000); }, false) var qaNotifications = { storageService : Components.classes["@mozilla.org/storage/service;1"] .getService(Ci.mozIStorageService), dbHandle : null, openDatabase : function() { var file = Cc["@mozilla.org/file/directory_service;1"] .getService(Ci.nsIProperties) .get("ProfD", Ci.nsIFile); file.append("mozqa.sqlite"); this.dbHandle = this.storageService.openDatabase(file); this.createNotificationTable(); }, closeDatabase : function() { // there's no way to actually close a database, but setting // the db reference to null will cause the db handle to become // elegible for GC which is about as good as it gets dbHandle = null; }, createNotificationTable : function() { this.db.executeSimpleSQL("CREATE TABLE if not exists notifications ( \ id text, \ datetime integer, \ firstNotification integer, \ secondNotification integer, \ serializedJSData string)"); }, updateNotificationStore : function() { var req = new XMLHttpRequest(); var url = qaPref.getPref('qa.extension.hermes.url', 'char'); req.open('GET', url, true); req.onreadystatechange = function(evt) { if (req.readyState == 4 && req.status == 200) { if (req.responseXML.getElementsByTagName('notifications') == null) return; var notifs = req.responseXML.getElementsByTagName('notification'); for (var i=0; i new Date().valueOf()) return; // nothing to see here, try again later var sth = this.db.createStatement("SELECT * FROM notifications"); var notifications = []; try { while (sth.executeStep()) { notifications.push(new Notification('json', MochiKit.Base.evalJSON( sth.getString(4)))); } } finally { sth.reset(); } if (notifications[0] && notifications[0].okToShow() == true) { notifications[0].displayToBox(); $('qa-notify').removeAttribute('hidden'); } // reset the interval timer qaPref.setPref(qaPref.prefBase+'.lastNotificationCheckTime', new Date().valueOf(), 'int'); }, showHideNotify: function(bool) { var notify = $('qa-notify'); if (bool == true) { notify.removeAttribute("hidden"); } else { notify.setAttribute("hidden", "true"); } }, getNotificationSettings : function(bool) { var prefs = qaPref.getPref(qaPref.prefBase+'.notificationSettings', 'char'); return prefs.split(","); }, }; qaNotifications.__defineGetter__('db', function() { if (this.dbHandle != null) return this.dbHandle; else { this.openDatabase(); return this.dbHandle; } }); function Notification() { } function Notification(type, data) { if (type == 'json') { this.id = data.id; this.notificationClass = data.notificationClass; this.type = data.type; this.headline = data.headline; this.datetime = MochiKit.DateTime.isoTimestamp(data.datetime); this.place = data.place; this.infotext = data.infotext; this.infolinktext = data.infolinktext; this.infolinkhref = data.infolinkhref; this.golinktext = data.golinktext; this.golinkhref = data.golinkhref; } else if (type == 'xml') { var notif = data; this.id = notif.getAttribute('id'); this.notificationClass = notif.getAttribute('class'); this.type = notif.getAttribute('type'); if (notif.getElementsByTagName('headline')[0] != null) this.headline = notif.getElementsByTagName('headline')[0].textContent; // eventinfo if (this.notificationClass == 'event') { var eventInfo = notif.getElementsByTagName('eventinfo')[0]; this.datetime = MochiKit.DateTime.isoTimestamp( eventInfo.getElementsByTagName('datetime')[0].textContent); this.place = eventInfo.getElementsByTagName('place')[0].textContent; } this.infotext = notif.getElementsByTagName('infotext')[0].textContent; this.infolinktext = notif.getElementsByTagName('infolink')[0].textContent; this.infolinkhref = notif.getElementsByTagName('infolink')[0] .getAttribute('href'); this.golinktext = notif.getElementsByTagName('golink')[0].textContent; this.golinkhref = notif.getElementsByTagName('golink')[0] .getAttribute('href'); } } Notification.prototype = { id : null, notificationClass : null, type : null, headline : null, datetime : null, place : null, infotext : null, infolinktext : null, infolinkhref : null, golinktext : null, golinkhref : null, hasHadFirstNotification : false, hasHadSecondNotification : false, serializedJSData : null, serializeToDb: function() { var query = qaNotifications.db.createStatement("SELECT id FROM notifications \ WHERE id = ?1"); query.bindStringParameter(0, this.id); var foundRow; while (query.executeStep()) { foundRow = 1; } query.reset(); if (foundRow == 1) { // it's already been inserted, so update return; } var sth = qaNotifications.db.createStatement("INSERT into notifications \ values (?1, ?2, ?3, ?4, ?5)"); sth.bindStringParameter(0, this.id); sth.bindStringParameter(1, this.datetime); sth.bindStringParameter(2, this.hasHadFirstNotification); sth.bindStringParameter(3, this.hasHadSecondNotification); // avoid having serialized data inside serialized data: this.serializedJSData = null; var jsData = MochiKit.Base.serializeJSON(this); sth.bindStringParameter(4, jsData); sth.execute(); }, displayToBox : function() { $('qa-notify-header').value=this.headline; if ($('qa-notify-text').firstChild) $('qa-notify-text').removeChild($('qa-notify-text').firstChild); $('qa-notify-text').appendChild(document.createTextNode(this.infotext)); $('qa-notify-infolink').value=this.infolinktext; $('qa-notify-infolink').href=this.infolinkhref; $('qa-notify-infolink').style.display = ''; if (this.notificationClass == 'event') { var inprogress = 0; $('qa-notify-event-datetime').value=this.datetime; $('qa-notify-event-place').value=this.place; $('qa-notify-event').style.display = ''; $('qa-notify-inprogress').style.display = 'none'; $('qa-notify-getstartedlink').value=this.golinktext; $('qa-notify-getstartedlink').href=this.golinkhref; if (inprogress == 1) { $('qa-notify-inprogress').style.display = ''; $('qa-notify-getstartedlink').style.display = ''; $('qa-notify-infolink').style.display = 'none'; } } }, okToShow : function() { var prefs = qaNotifications.getNotificationSettings(); if (prefs[0] == '1') // all notifications disabled return false; if (this.type == 'testday' && ! prefs[1] == '0') return true; if (this.type == 'bugday' && ! prefs[2] == '0') return true; if (this.type == 'prerelease' && ! prefs[3] == '0') return true; if (this.type == 'news' && ! prefs[4] == '0') return true; if (this.type == 'newbuilds' && ! prefs[5] == '0') return true; if (this.type == 'special' && ! prefs[6] == '0') return true; // catch all: return false; } };