notifications_custom_bindings.js revision 558790d6acca3451cf3a6b497803a5f07d0bec58
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.
6var binding = require('binding').Binding.create('notifications');
7
8var sendRequest = require('sendRequest').sendRequest;
9var imageUtil = require('imageUtil');
10var lastError = require('lastError');
11
12function image_data_setter(context, key) {
13  var f = function(val) {
14    this[key] = val;
15  };
16  return $Function.bind(f, context);
17}
18
19function 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
91function 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
113var handleCreate = genHandle('notifications.create',
114                             function(callback, id) { callback(id); });
115var handleUpdate = genHandle('notifications.update',
116                             function(callback, id) { callback(false); });
117
118var notificationsCustomHook = function(bindingsAPI, extensionId) {
119  var apiFunctions = bindingsAPI.apiFunctions;
120  apiFunctions.setHandleRequest('create', handleCreate);
121  apiFunctions.setHandleRequest('update', handleUpdate);
122};
123
124binding.registerCustomHook(notificationsCustomHook);
125
126exports.binding = binding.generate();
127