Home | History | Annotate | Download | only in extensions
      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 // Custom bindings for the notifications API.
      6 var binding = require('binding').Binding.create('notifications');
      7 
      8 var sendRequest = require('sendRequest').sendRequest;
      9 var imageUtil = require('imageUtil');
     10 var lastError = require('lastError');
     11 
     12 function image_data_setter(context, key) {
     13   var f = function(val) {
     14     this[key] = val;
     15   };
     16   return $Function.bind(f, context);
     17 }
     18 
     19 function replaceNotificationOptionURLs(notification_details, callback) {
     20   // A URL Spec is an object with the following keys:
     21   //  path: The resource to be downloaded.
     22   //  width: (optional) The maximum width of the image to be downloaded.
     23   //  height: (optional) The maximum height of the image to be downloaded.
     24   //  callback: A function to be called when the URL is complete. It
     25   //    should accept an ImageData object and set the appropriate
     26   //    field in the output of create.
     27 
     28   // TODO(dewittj): Try to remove hard-coding of image sizes.
     29   // |iconUrl| might be optional for notification updates.
     30   var url_specs = [];
     31   if (notification_details.iconUrl) {
     32     $Array.push(url_specs, {
     33       path: notification_details.iconUrl,
     34       width: 80,
     35       height: 80,
     36       callback: image_data_setter(notification_details, 'iconBitmap')
     37     });
     38   }
     39 
     40   // |imageUrl| is optional.
     41   if (notification_details.imageUrl) {
     42     $Array.push(url_specs, {
     43       path: notification_details.imageUrl,
     44       width: 360,
     45       height: 540,
     46       callback: image_data_setter(notification_details, 'imageBitmap')
     47     });
     48   }
     49 
     50   // Each button has an optional icon.
     51   var button_list = notification_details.buttons;
     52   if (button_list && typeof button_list.length === 'number') {
     53     var num_buttons = button_list.length;
     54     for (var i = 0; i < num_buttons; i++) {
     55       if (button_list[i].iconUrl) {
     56         $Array.push(url_specs, {
     57           path: button_list[i].iconUrl,
     58           width: 16,
     59           height: 16,
     60           callback: image_data_setter(button_list[i], 'iconBitmap')
     61         });
     62       }
     63     }
     64   }
     65 
     66   if (!url_specs.length) {
     67     callback(true);
     68     return;
     69   }
     70 
     71   var errors = 0;
     72 
     73   imageUtil.loadAllImages(url_specs, {
     74     onerror: function(index) {
     75       errors++;
     76     },
     77     oncomplete: function(imageData) {
     78       if (errors > 0) {
     79         callback(false);
     80         return;
     81       }
     82       for (var index = 0; index < url_specs.length; index++) {
     83         var url_spec = url_specs[index];
     84         url_spec.callback(imageData[index]);
     85       }
     86       callback(true);
     87     }
     88   });
     89 }
     90 
     91 function genHandle(name, failure_function) {
     92   return function(id, input_notification_details, callback) {
     93     // TODO(dewittj): Remove this hack. This is used as a way to deep
     94     // copy a complex JSON object.
     95     var notification_details = JSON.parse(
     96         JSON.stringify(input_notification_details));
     97     var that = this;
     98     replaceNotificationOptionURLs(notification_details, function(success) {
     99       if (success) {
    100         sendRequest(that.name,
    101             [id, notification_details, callback],
    102             that.definition.parameters);
    103         return;
    104       }
    105       lastError.run(name,
    106                     'Unable to download all specified images.',
    107                     null,
    108                     failure_function, [callback, id])
    109     });
    110   };
    111 }
    112 
    113 var handleCreate = genHandle('notifications.create',
    114                              function(callback, id) { callback(id); });
    115 var handleUpdate = genHandle('notifications.update',
    116                              function(callback, id) { callback(false); });
    117 
    118 var notificationsCustomHook = function(bindingsAPI, extensionId) {
    119   var apiFunctions = bindingsAPI.apiFunctions;
    120   apiFunctions.setHandleRequest('create', handleCreate);
    121   apiFunctions.setHandleRequest('update', handleUpdate);
    122 };
    123 
    124 binding.registerCustomHook(notificationsCustomHook);
    125 
    126 exports.binding = binding.generate();
    127