OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Custom bindings for the notifications API. | 5 // Custom bindings for the notifications API. |
6 // | 6 // |
7 var binding = require('binding').Binding.create('notifications'); | 7 var binding = require('binding').Binding.create('notifications'); |
8 | 8 |
9 var sendRequest = require('sendRequest').sendRequest; | 9 var sendRequest = require('sendRequest').sendRequest; |
10 var imageUtil = require('imageUtil'); | 10 var imageUtil = require('imageUtil'); |
11 var lastError = require('lastError'); | 11 var lastError = require('lastError'); |
12 var notificationsPrivate = requireNative('notifications_private'); | 12 var notificationsPrivate = requireNative('notifications_private'); |
13 | 13 |
14 function imageDataSetter(context, key) { | 14 function imageDataSetter(context) { |
15 var f = function(val) { | 15 var f = function(val) { |
16 this[key] = val; | 16 this.src = val; |
17 }; | 17 }; |
18 return $Function.bind(f, context); | 18 return $Function.bind(f, context); |
19 } | 19 } |
20 | 20 |
| 21 function getUrlsForBitmapList(notificationBitmapList, imageSize, scaleFactor) { |
| 22 // Returns a list of specs to be used by the image util library. |
| 23 var rv = []; |
| 24 $Array.forEach(notificationBitmapList, function(bitmap) { |
| 25 if (typeof bitmap.src === 'string' || |
| 26 bitmap.src instanceof $String.self) { |
| 27 $Array.push(rv, { |
| 28 path: bitmap.src, |
| 29 width: imageSize.width * scaleFactor, |
| 30 height: imageSize.height * scaleFactor, |
| 31 scale: bitmap.density || 1.0, |
| 32 callback: imageDataSetter(bitmap) |
| 33 }); |
| 34 } |
| 35 }); |
| 36 return rv; |
| 37 } |
| 38 |
21 // A URL Spec is an object with the following keys: | 39 // A URL Spec is an object with the following keys: |
22 // path: The resource to be downloaded. | 40 // path: The resource to be downloaded. |
23 // width: (optional) The maximum width of the image to be downloaded in device | 41 // width: (optional) The maximum width of the image to be downloaded in device |
24 // pixels. | 42 // pixels. |
25 // height: (optional) The maximum height of the image to be downloaded in | 43 // height: (optional) The maximum height of the image to be downloaded in |
26 // device pixels. | 44 // device pixels. |
27 // callback: A function to be called when the URL is complete. It | 45 // callback: A function to be called when the URL is complete. It |
28 // should accept an ImageData object and set the appropriate | 46 // should accept an ImageData object and set the appropriate |
29 // field in |notificationDetails|. | 47 // field in |notificationDetails|. |
30 function getUrlSpecs(imageSizes, notificationDetails) { | 48 function getUrlSpecs(imageSizes, notificationDetails) { |
31 var urlSpecs = []; | 49 var urls = $Array.concat( |
32 | 50 getUrlsForBitmapList( |
33 // |iconUrl| might be optional for notification updates. | 51 notificationDetails.iconReps, |
34 if (notificationDetails.iconUrl) { | 52 imageSizes.icon, |
35 $Array.push(urlSpecs, { | 53 imageSizes.scaleFactor), |
36 path: notificationDetails.iconUrl, | 54 getUrlsForBitmapList( |
37 width: imageSizes.icon.width * imageSizes.scaleFactor, | 55 notificationDetails.imageReps, |
38 height: imageSizes.icon.height * imageSizes.scaleFactor, | 56 imageSizes.image, |
39 callback: imageDataSetter(notificationDetails, 'iconBitmap') | 57 imageSizes.scaleFactor)); |
40 }); | 58 for (var i = 0; i < notificationDetails.buttons.length; i++) { |
| 59 urls = $Array.concat( |
| 60 urls, |
| 61 getUrlsForBitmapList( |
| 62 notificationDetails.buttons[i].iconReps, |
| 63 imageSizes.buttonIcon, |
| 64 imageSizes.scaleFactor)); |
41 } | 65 } |
42 | 66 |
43 // |imageUrl| is optional. | 67 return urls; |
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 } | 68 } |
71 | 69 |
72 function replaceNotificationOptionURLs(notification_details, callback) { | 70 function replaceNotificationOptionURLs(notification_details, callback) { |
73 var imageSizes = notificationsPrivate.GetNotificationImageSizes(); | 71 var imageSizes = notificationsPrivate.GetNotificationImageSizes(); |
74 var url_specs = getUrlSpecs(imageSizes, notification_details); | 72 var url_specs = getUrlSpecs(imageSizes, notification_details); |
75 if (!url_specs.length) { | 73 if (!url_specs.length) { |
76 callback(true); | 74 callback(true); |
77 return; | 75 return; |
78 } | 76 } |
79 | 77 |
(...skipping 11 matching lines...) Expand all Loading... |
91 for (var index = 0; index < url_specs.length; index++) { | 89 for (var index = 0; index < url_specs.length; index++) { |
92 var url_spec = url_specs[index]; | 90 var url_spec = url_specs[index]; |
93 url_spec.callback(imageData[index]); | 91 url_spec.callback(imageData[index]); |
94 } | 92 } |
95 callback(true); | 93 callback(true); |
96 } | 94 } |
97 }); | 95 }); |
98 } | 96 } |
99 | 97 |
100 function genHandle(name, failure_function) { | 98 function genHandle(name, failure_function) { |
101 return function(id, input_notification_details, callback) { | 99 return function(id, 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; | 100 var that = this; |
107 replaceNotificationOptionURLs(notification_details, function(success) { | 101 replaceNotificationOptionURLs(notification_details, function(success) { |
108 if (success) { | 102 if (success) { |
109 sendRequest(that.name, | 103 sendRequest(that.name, |
110 [id, notification_details, callback], | 104 [id, notification_details, callback], |
111 that.definition.parameters); | 105 that.definition.parameters); |
112 return; | 106 return; |
113 } | 107 } |
114 lastError.run(name, | 108 lastError.run(name, |
115 'Unable to download all specified images.', | 109 'Unable to download all specified images.', |
116 null, | 110 null, |
117 failure_function, [callback, id]) | 111 failure_function, [callback, id]); |
118 }); | 112 }); |
119 }; | 113 }; |
120 } | 114 } |
121 | 115 |
| 116 function translateBitmapUrls(id, input_options, callback) { |
| 117 // TODO(dewittj): Remove this hack. This is used as a way to deep |
| 118 // copy a complex JSON object. |
| 119 var options = JSON.parse(JSON.stringify(input_options)); |
| 120 |
| 121 options.iconReps = options.iconReps || []; |
| 122 if (options.iconUrl) { |
| 123 $Array.splice(options.iconReps, 0, 0, {density: 1.0, src: options.iconUrl}); |
| 124 } |
| 125 |
| 126 options.imageReps = options.imageReps || []; |
| 127 if (options.imageUrl) { |
| 128 $Array.splice(options.imageReps, 0, 0, |
| 129 {density: 1.0, src: options.imageUrl}); |
| 130 } |
| 131 |
| 132 options.buttons = options.buttons || []; |
| 133 for (var i = 0; i < options.buttons.length; i++) { |
| 134 options.buttons[i].iconReps = options.buttons[i].iconReps || []; |
| 135 if (options.buttons[i].iconUrl) { |
| 136 $Array.splice( |
| 137 options.buttons[i].iconReps, |
| 138 0, |
| 139 0, |
| 140 {density: 1.0, src: options.buttons[i].iconUrl}); |
| 141 } |
| 142 } |
| 143 |
| 144 return [id, options, callback]; |
| 145 } |
| 146 |
122 var handleCreate = genHandle('notifications.create', | 147 var handleCreate = genHandle('notifications.create', |
123 function(callback, id) { callback(id); }); | 148 function(callback, id) { callback(id); }); |
124 var handleUpdate = genHandle('notifications.update', | 149 var handleUpdate = genHandle('notifications.update', |
125 function(callback, id) { callback(false); }); | 150 function(callback, id) { callback(false); }); |
126 | |
127 var notificationsCustomHook = function(bindingsAPI, extensionId) { | 151 var notificationsCustomHook = function(bindingsAPI, extensionId) { |
128 var apiFunctions = bindingsAPI.apiFunctions; | 152 var apiFunctions = bindingsAPI.apiFunctions; |
| 153 apiFunctions.setUpdateArgumentsPostValidate('create', translateBitmapUrls); |
129 apiFunctions.setHandleRequest('create', handleCreate); | 154 apiFunctions.setHandleRequest('create', handleCreate); |
| 155 apiFunctions.setUpdateArgumentsPostValidate('update', translateBitmapUrls); |
130 apiFunctions.setHandleRequest('update', handleUpdate); | 156 apiFunctions.setHandleRequest('update', handleUpdate); |
131 }; | 157 }; |
132 | 158 |
133 binding.registerCustomHook(notificationsCustomHook); | 159 binding.registerCustomHook(notificationsCustomHook); |
134 | 160 |
135 exports.binding = binding.generate(); | 161 exports.binding = binding.generate(); |
OLD | NEW |