function fetchChanges(update_id) {
  console.debug('fetching changes...');
  chrome.browserAction.setBadgeBackgroundColor({color: '#F00'});
  var query = localStorage['query'] ||
      (['is:open', 'reviewer:self', '-owner:self'].join('+') + '&o=LABELS');
  console.debug('query = ' + query);
  queryChangeList(query).then(
     function(result) {
          console.debug('got changes:', result.length);
          chrome.storage.local.set({'changes': result});

          // update timestamp/read state
          var updated = result.filter(function(o) { return o._number === update_id; }).pop().updated;
          chrome.storage.local.get('timestamps', function(items) {
              var timestamps = items.timestamps || {};
              timestamps[update_id] = updated;
              chrome.storage.local.set({'timestamps': timestamps});
            });
        }, function(e) {
          console.warn('failed to fetch changes:', e.message);
          delete chrome.storage.local.changes;
        });
}

function updateIcon(changes) {
  try {
    var unread = changes.filter(function(value, index, array) {return !value.reviewed;});
  } catch (e) {
  }
  chrome.browserAction.setBadgeText({text: unread && unread.length.toString() || '...'});
}

function onAlarm(alarm) {
  console.debug('background.onAlarm...');
  fetchChanges();
}

function favicon(url) {
  var split = url.split('://');
  var host = split.pop();
  if (!host) throw new Error;
  var scheme = split.pop();
  return (scheme ? scheme + '://' : '') + host.split('/').shift() + '/favicon.ico';
}

function onStartup() {
  console.debug('background.onStartup...');

  try {
    chrome.browserAction.setIcon({path: favicon(localStorage['api_endpoint'])});
  } catch (e) {
  }

  chrome.storage.local.get('changes', function(items) {
      updateIcon(items.changes);
    });
  fetchChanges();
  chrome.storage.local.get('refresh', function(items) {
      chrome.alarms.create('refresh', {periodInMinutes: items.refresh});
    });
  chrome.browserAction.setBadgeBackgroundColor({color: '#000'});
}

function onNavigate(details) {
  console.debug('onNavigate', details.url);
  try {
    var update_id = parseInt(details.url.match(/#\/c\/(\d+)/)[1]);
    fetchChanges(update_id);
  } catch (e) {
    console.warn('Failed to parse id for', details.url);
  }
}

chrome.alarms.onAlarm.addListener(onAlarm);
chrome.runtime.onStartup.addListener(onStartup);
chrome.runtime.onInstalled.addListener(onStartup);
chrome.runtime.onSuspend.addListener(function() {
    chrome.browserAction.setBadgeBackgroundColor({color: '#888'});
  });
chrome.runtime.onSuspendCanceled.addListener(function() {
    chrome.browserAction.setBadgeBackgroundColor({color: '#F0F'});
  });
chrome.storage.onChanged.addListener(function(changes, namespace) {
    for (key in changes) {
      var storageChange = changes[key];
      console.debug('Storage key "%s" in namespace "%s" changed. ' +
          'Old value was "%s", new value is "%s".',
          key,
          namespace,
          storageChange.oldValue,
          storageChange.newValue);
      if (key === 'changes') {
        updateIcon(storageChange.newValue);
      }
    }
  });
chrome.webNavigation.onReferenceFragmentUpdated.addListener(onNavigate, {
    url: [
        {hostSuffix: localStorage['api_endpoint'].split('://').pop()}
    ]
  });
chrome.webNavigation.onCommitted.addListener(onNavigate, {
    url: [
        {hostSuffix: localStorage['api_endpoint'].split('://').pop()}
    ]
  });

@@ -1555,24 +1555,156 @@
 on.ico';%0A%7D%0A%0A
+function getAlarmRefreshMinute() %7B%0A  return typeof localStorage.refresh !== 'undefined' ?%0A    parseInt(localStorage.refresh) : 5;%0A%7D%0A
 function onS
@@ -1988,68 +1988,8 @@
 ();%0A
-  chrome.storage.local.get('refresh', function(items) %7B%0A    
   ch
@@ -2040,29 +2040,31 @@
 es: 
-items.refresh%7D);%0A    
+getAlarmRefreshMinute()
 %7D);%0A

Switch chrome.storage.local.get to window.localStorage for refresh property (#11)