Bugzilla - Air Traffic Control

By Bryan Clark Uploaded Jun 7, 2009
var show_bug_regex = /^https:\/\/bugzilla\.mozilla\.org\/show_bug\.cgi\?id=(\d+)/;

function getBugXML(tab) {
  if ( tab.isClosed ) {
    stopCheckingTab(tab);
    return;
  }

  var show_bug_url = "https://bugzilla.mozilla.org/show_bug.cgi?id=";
  var show_bug_url_xml_args = "&ctype=xml&field=delta_ts";

  $.ajax({
    type: "GET",
    dataType: "xml",
//    ifModified: true,
    url: show_bug_url + tab.bug_id + show_bug_url_xml_args,
    success: function(xml_resp, textStatus) {
      var delta_ts = xml_resp.querySelector("bugzilla > bug > delta_ts");
      /* bugzilla returns delta_ts as 2009-06-05 14:14:24 PDT but Date.parse 
         doesn't like the dash so we munge away at it. */
      var delta_date = new Date(Date.parse(delta_ts.textContent.replace("-"," ","g")))
      if ( tab.bug_delta_date ) {
        if ( delta_date > tab.bug_delta_date ) {
          addNotification(tab);
        }
      }
      tab.bug_delta_date = delta_date;
    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {
      if (XMLHttpRequest.status == 200 && textStatus == "notmodified")
        return;
      /* some kind of real errror and we should log it */
      console.log("getBugXML:error", XMLHttpRequest, textStatus, errorThrown);
    }
    });
}

function areCheckingTab(tab) {
  return (tab.bug_interval_id && tab.bug_interval_id != null);
}

function startCheckingTab(tab) {
  if ( tab.isClosed ) {
    return;
  }
  tab.bug_interval_id = setInterval(function() { tab.bug_ajax(tab); }, tab.bug_interval_delay);
}
// XXX unused
function increaseCheckingTabInterval(tab) {
  clearInterval(tab.bug_interval_id);
  tab.bug_interval_id = null;
  tab.bug_interval_delay += 1000 * 60 * 4; /* add 4 minutes */
  startCheckingTab(tab);
}

function resetCheckingTabInterval(tab) {
  clearInterval(tab.bug_interval_id);
  tab.bug_interval_id = null;
  tab.bug_interval_delay += 1000 * 30; /* back to 30 seconds */
  startCheckingTab(tab);
}

function stopCheckingTab(tab) {
  clearInterval(tab.bug_interval_id);
  tab.bug_interval_id = null;
  tab.bug_xml = null;
}

function alreadyNotifiedTab(tab) {
  return (tab.bug_notified);
}

function notifiedNode(tab) {
 return ($('#bug_updates_notification', tab.contentDocument).length >= 1);
}

function addNotification(tab) {
  if ( ! alreadyNotifiedTab(tab) ) {
    /* double check the HTML hasn't been inserted */
    if ( ! notifiedNode(tab) ) {
      var new_notification = $("<div></div>", tab.contentDocument)
                             .attr('id', 'bug_updates_notification')
                             .css('border', '1px solid #fce94f')
                             .css('background-color', '#ffffe0')
                             .css('color', '#111')
                             .css('text-align', 'center')
                             .css('font-weight', 'bold')
                             .css('padding', '1ex')
                             .css('margin', '1ex 0ex');
      $("a[name='add_comment']", tab.contentDocument).append(new_notification);
    }
    $('#bug_updates_notification', tab.contentDocument)
      .append( $("<div>&mdash; This is air traffic control &mdash;</div>")
               .css('color', '#666')
               .css('font-size', 'x-small')
               .css('font-weight', 'normal')
             ).append( $("<div>Be advised, this bug has been updated.  Recommend you save and reload</div>") );
    /* XXX we want to offer a reload, but firefox would lose your settings 
       in an https page as shipped by default.  Please Fix!!  sigh...
      .append( $("<a href='javascript:document.reload();'>reload?</a>") );
    */
    tab.bug_notified = true;
    stopCheckingTab(tab);
  }
}

function init(tab) {
  // setup tab variables
  tab.bug_id = -1;
  tab.bug_notified = false;
  tab.bug_interval_id = null;
  tab.bug_interval_delay = 1000 * 30; /* 30 seconds, it's only ifModified... */
  tab.bug_ajax = function _getBugXML(tab) { getBugXML(tab); };
  tab.bug_delta_date = null;
}

jetpack.tabs.onReady(function(doc) {
  // here we setup our persistent check
  var match = this.url.match(show_bug_regex);
  if (match) {
    init(this);
    this.bug_id = match[1];
    startCheckingTab(this);
  } else {
    // just for good measure stop checking this tab
    stopCheckingTab(this);
  }
});

jetpack.tabs.onFocus(function() {
  // here we just double check out status
  var match = this.url.match(show_bug_regex);
  if (match) {

    /* if we've already notified then we aren't checking anymore */
    if ( alreadyNotifiedTab(this) )
      return;

    if ( ! areCheckingTab(this) ) {
      // they focused a url match that we haven't been checking!
      init(this);
      this.bug_id = match[1];
      startCheckingTab(this);
    } else {
      resetCheckingTabInterval(this);
    }
  } else {
    // just for good measure stop checking this tab
    stopCheckingTab(this);
  }
});