Home | History | Annotate | Download | only in google_now
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 'use strict';
      6 
      7 var MS_IN_SECOND = 1000;
      8 
      9 /**
     10  * Builds an object to manage notification card set.
     11  * @return {Object} Card set interface.
     12  */
     13 function buildCardSet() {
     14   var cardShowPrefix = 'card-show-';
     15   var cardHidePrefix = 'card-hide-';
     16 
     17   /**
     18    * Schedules hiding a notification.
     19    * @param {string} cardId Card ID.
     20    * @param {number=} opt_timeHide If specified, epoch time to hide the card. If
     21    *      undefined, the card will be kept shown at least until next update.
     22    */
     23   function scheduleHiding(cardId, opt_timeHide) {
     24     if (opt_timeHide === undefined)
     25       return;
     26 
     27     var alarmName = cardHidePrefix + cardId;
     28     var alarmInfo = {when: opt_timeHide};
     29     chrome.alarms.create(alarmName, alarmInfo);
     30   }
     31 
     32   /**
     33    * Shows a notification.
     34    * @param {string} cardId Card ID.
     35    * @param {Object} cardCreateInfo Google Now card represented as a set of
     36    *     parameters for showing a Chrome notification.
     37    */
     38   function showNotification(cardId, cardCreateInfo) {
     39     console.log('cardManager.showNotification ' + cardId + ' ' +
     40                 JSON.stringify(cardCreateInfo));
     41 
     42     if (cardCreateInfo.previousVersion !== cardCreateInfo.version) {
     43       try {
     44         // Delete a notification with the specified id if it already exists, and
     45         // then create a notification.
     46         instrumented.notifications.create(
     47             cardId,
     48             cardCreateInfo.notification,
     49             function(newNotificationId) {
     50               if (!newNotificationId || chrome.runtime.lastError) {
     51                 var errorMessage = chrome.runtime.lastError &&
     52                                    chrome.runtime.lastError.message;
     53                 console.error('notifications.create: ID=' + newNotificationId +
     54                               ', ERROR=' + errorMessage);
     55                 return;
     56               }
     57 
     58               scheduleHiding(cardId, cardCreateInfo.timeHide);
     59             });
     60       } catch (error) {
     61         console.error('Error in notifications.create: ' + error);
     62       }
     63     } else {
     64       try {
     65         // Update existing notification.
     66         instrumented.notifications.update(
     67             cardId,
     68             cardCreateInfo.notification,
     69             function(wasUpdated) {
     70               if (!wasUpdated || chrome.runtime.lastError) {
     71                 var errorMessage = chrome.runtime.lastError &&
     72                                    chrome.runtime.lastError.message;
     73                 console.error('notifications.update: UPDATED=' + wasUpdated +
     74                               ', ERROR=' + errorMessage);
     75                 return;
     76               }
     77 
     78               scheduleHiding(cardId, cardCreateInfo.timeHide);
     79             });
     80       } catch (error) {
     81         console.error('Error in notifications.update: ' + error);
     82       }
     83     }
     84   }
     85 
     86   /**
     87    * Updates/creates a card notification with new data.
     88    * @param {Object} card Google Now from the server.
     89    * @param {number=} previousVersion The version of the shown card with
     90    *     this id, if it exists, undefined otherwise.
     91    * @return {Object} Notification data entry for this card.
     92    */
     93   function update(card, previousVersion) {
     94     console.log('cardManager.update ' + JSON.stringify(card) + ' ' +
     95         previousVersion);
     96 
     97     if (typeof card.version != 'number') {
     98       console.log('cardCreateInfo.version is not a number');
     99       // Fix card version.
    100       card.version = previousVersion || 0;
    101     }
    102 
    103     // TODO(vadimt): Don't clear alarms etc that don't exist. Or make sure doing
    104     // this doesn't output an error to console.
    105     chrome.alarms.clear(cardHidePrefix + card.notificationId);
    106 
    107     var timeHide = card.trigger && card.trigger.hideTimeSec !== undefined ?
    108         Date.now() + card.trigger.hideTimeSec * MS_IN_SECOND : undefined;
    109     var cardCreateInfo = {
    110       notification: card.notification,
    111       timeHide: timeHide,
    112       version: card.version,
    113       previousVersion: previousVersion
    114     };
    115 
    116     var cardShowAlarmName = cardShowPrefix + card.notificationId;
    117     if (card.trigger && card.trigger.showTimeSec) {
    118       // Card needs to be shown later.
    119       console.log('cardManager.register: postponed');
    120       var alarmInfo = {
    121         when: Date.now() + card.trigger.showTimeSec * MS_IN_SECOND
    122       };
    123       chrome.alarms.create(cardShowAlarmName, alarmInfo);
    124     } else {
    125       // Card needs to be shown immediately.
    126       console.log('cardManager.register: immediate');
    127       chrome.alarms.clear(cardShowAlarmName);
    128       showNotification(card.notificationId, cardCreateInfo);
    129     }
    130 
    131     return {
    132       actionUrls: card.actionUrls,
    133       cardCreateInfo: cardCreateInfo,
    134       dismissalParameters: card.dismissal
    135     };
    136   }
    137 
    138   /**
    139    * Removes a card notification.
    140    * @param {string} cardId Card ID.
    141    */
    142   function clear(cardId) {
    143     console.log('cardManager.unregister ' + cardId);
    144 
    145     chrome.notifications.clear(cardId, function() {});
    146     chrome.alarms.clear(cardShowPrefix + cardId);
    147     chrome.alarms.clear(cardHidePrefix + cardId);
    148   }
    149 
    150   instrumented.alarms.onAlarm.addListener(function(alarm) {
    151     console.log('cardManager.onAlarm ' + JSON.stringify(alarm));
    152 
    153     if (alarm.name.indexOf(cardShowPrefix) == 0) {
    154       // Alarm to show the card.
    155       var cardId = alarm.name.substring(cardShowPrefix.length);
    156       instrumented.storage.local.get('notificationsData', function(items) {
    157         items.notificationsData = items.notificationsData || {};
    158         console.log('cardManager.onAlarm.get ' + JSON.stringify(items));
    159         var notificationData = items.notificationsData[cardId];
    160         if (!notificationData)
    161           return;
    162 
    163         showNotification(cardId, notificationData.cardCreateInfo);
    164       });
    165     } else if (alarm.name.indexOf(cardHidePrefix) == 0) {
    166       // Alarm to hide the card.
    167       var cardId = alarm.name.substring(cardHidePrefix.length);
    168       chrome.notifications.clear(cardId, function() {});
    169     }
    170   });
    171 
    172   return {
    173     update: update,
    174     clear: clear
    175   };
    176 }
    177