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