Add testing/scripts/OWNERS
[chromium-blink-merge.git] / chrome / renderer / resources / extensions / notifications_custom_bindings.js
blobeebf2900920287f0b539b04e32d48e6219a2c444
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.
5 // Custom bindings for the notifications API.
6 //
7 var binding = require('binding').Binding.create('notifications');
9 var sendRequest = require('sendRequest').sendRequest;
10 var imageUtil = require('imageUtil');
11 var lastError = require('lastError');
12 var notificationsPrivate = requireNative('notifications_private');
14 function imageDataSetter(context, key) {
15   var f = function(val) {
16     this[key] = val;
17   };
18   return $Function.bind(f, context);
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|.
30 function getUrlSpecs(imageSizes, notificationDetails) {
31   var urlSpecs = [];
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   }
43   // |appIconMaskUrl| is optional.
44   if (notificationDetails.appIconMaskUrl) {
45     $Array.push(urlSpecs, {
46       path: notificationDetails.appIconMaskUrl,
47       width: imageSizes.appIconMask.width * imageSizes.scaleFactor,
48       height: imageSizes.appIconMask.height * imageSizes.scaleFactor,
49       callback: imageDataSetter(notificationDetails, 'appIconMaskBitmap')
50     });
51   }
53   // |imageUrl| is optional.
54   if (notificationDetails.imageUrl) {
55     $Array.push(urlSpecs, {
56       path: notificationDetails.imageUrl,
57       width: imageSizes.image.width * imageSizes.scaleFactor,
58       height: imageSizes.image.height * imageSizes.scaleFactor,
59       callback: imageDataSetter(notificationDetails, 'imageBitmap')
60     });
61   }
63   // Each button has an optional icon.
64   var buttonList = notificationDetails.buttons;
65   if (buttonList && typeof buttonList.length === 'number') {
66     var numButtons = buttonList.length;
67     for (var i = 0; i < numButtons; i++) {
68       if (buttonList[i].iconUrl) {
69         $Array.push(urlSpecs, {
70           path: buttonList[i].iconUrl,
71           width: imageSizes.buttonIcon.width * imageSizes.scaleFactor,
72           height: imageSizes.buttonIcon.height * imageSizes.scaleFactor,
73           callback: imageDataSetter(buttonList[i], 'iconBitmap')
74         });
75       }
76     }
77   }
79   return urlSpecs;
82 function replaceNotificationOptionURLs(notification_details, callback) {
83   var imageSizes = notificationsPrivate.GetNotificationImageSizes();
84   var url_specs = getUrlSpecs(imageSizes, notification_details);
85   if (!url_specs.length) {
86     callback(true);
87     return;
88   }
90   var errors = 0;
92   imageUtil.loadAllImages(url_specs, {
93     onerror: function(index) {
94       errors++;
95     },
96     oncomplete: function(imageData) {
97       if (errors > 0) {
98         callback(false);
99         return;
100       }
101       for (var index = 0; index < url_specs.length; index++) {
102         var url_spec = url_specs[index];
103         url_spec.callback(imageData[index]);
104       }
105       callback(true);
106     }
107   });
110 function genHandle(name, failure_function) {
111   return function(id, input_notification_details, callback) {
112     // TODO(dewittj): Remove this hack. This is used as a way to deep
113     // copy a complex JSON object.
114     var notification_details = JSON.parse(
115         JSON.stringify(input_notification_details));
116     var that = this;
117     replaceNotificationOptionURLs(notification_details, function(success) {
118       if (success) {
119         sendRequest(that.name,
120             [id, notification_details, callback],
121             that.definition.parameters);
122         return;
123       }
124       lastError.run(name,
125                     'Unable to download all specified images.',
126                     null,
127                     failure_function, [callback, id])
128     });
129   };
132 var handleCreate = genHandle('notifications.create',
133                              function(callback, id) { callback(id); });
134 var handleUpdate = genHandle('notifications.update',
135                              function(callback, id) { callback(false); });
137 var notificationsCustomHook = function(bindingsAPI, extensionId) {
138   var apiFunctions = bindingsAPI.apiFunctions;
139   apiFunctions.setHandleRequest('create', handleCreate);
140   apiFunctions.setHandleRequest('update', handleUpdate);
143 binding.registerCustomHook(notificationsCustomHook);
145 exports.binding = binding.generate();