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.data = 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.data === 'string' || |
| 26 bitmap.data instanceof $String.self) { |
| 27 $Array.push(rv, { |
| 28 path: bitmap.data, |
| 29 width: imageSize.width * scaleFactor, |
| 30 height: imageSize.height * scaleFactor, |
| 31 scale: bitmap.scale || 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.icons, |
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.images, |
38 height: imageSizes.icon.height * imageSizes.scaleFactor, | 56 imageSizes.image)); |
39 callback: imageDataSetter(notificationDetails, 'iconBitmap') | 57 for (var i = 0; i < notificationDetails.buttons.length; i++) { |
40 }); | 58 urls = $Array.concat( |
| 59 urls, |
| 60 getUrlsForBitmapList( |
| 61 notificationDetails.buttons[i].icons, |
| 62 imageSizes.buttonIcon)); |
41 } | 63 } |
42 | 64 |
43 // |imageUrl| is optional. | 65 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 } | 66 } |
71 | 67 |
72 function replaceNotificationOptionURLs(notification_details, callback) { | 68 function replaceNotificationOptionURLs(notification_details, callback) { |
73 var imageSizes = notificationsPrivate.GetNotificationImageSizes(); | 69 var imageSizes = notificationsPrivate.GetNotificationImageSizes(); |
74 var url_specs = getUrlSpecs(imageSizes, notification_details); | 70 var url_specs = getUrlSpecs(imageSizes, notification_details); |
75 if (!url_specs.length) { | 71 if (!url_specs.length) { |
76 callback(true); | 72 callback(true); |
77 return; | 73 return; |
78 } | 74 } |
79 | 75 |
(...skipping 11 matching lines...) Expand all Loading... |
91 for (var index = 0; index < url_specs.length; index++) { | 87 for (var index = 0; index < url_specs.length; index++) { |
92 var url_spec = url_specs[index]; | 88 var url_spec = url_specs[index]; |
93 url_spec.callback(imageData[index]); | 89 url_spec.callback(imageData[index]); |
94 } | 90 } |
95 callback(true); | 91 callback(true); |
96 } | 92 } |
97 }); | 93 }); |
98 } | 94 } |
99 | 95 |
100 function genHandle(name, failure_function) { | 96 function genHandle(name, failure_function) { |
101 return function(id, input_notification_details, callback) { | 97 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; | 98 var that = this; |
107 replaceNotificationOptionURLs(notification_details, function(success) { | 99 replaceNotificationOptionURLs(notification_details, function(success) { |
108 if (success) { | 100 if (success) { |
109 sendRequest(that.name, | 101 sendRequest(that.name, |
110 [id, notification_details, callback], | 102 [id, notification_details, callback], |
111 that.definition.parameters); | 103 that.definition.parameters); |
112 return; | 104 return; |
113 } | 105 } |
114 lastError.run(name, | 106 lastError.run(name, |
115 'Unable to download all specified images.', | 107 'Unable to download all specified images.', |
116 null, | 108 null, |
117 failure_function, [callback, id]) | 109 failure_function, [callback, id]); |
118 }); | 110 }); |
119 }; | 111 }; |
120 } | 112 } |
121 | 113 |
| 114 function translateBitmapUrls(id, input_options, callback) { |
| 115 var args = $Array.slice(arguments); |
| 116 |
| 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.icons = options.icons || []; |
| 122 if (options.iconUrl) { |
| 123 $Array.splice(options.icons, 0, 0, {scale: 1.0, data: options.iconUrl}); |
| 124 } |
| 125 |
| 126 options.images = options.images || []; |
| 127 if (options.imageUrl) { |
| 128 $Array.splice(options.images, 0, 0, {scale: 1.0, data: options.imageUrl}); |
| 129 } |
| 130 |
| 131 options.buttons = options.buttons || []; |
| 132 for (var i = 0; i < options.buttons.length; i++) { |
| 133 options.buttons[i].icons = options.buttons[i].icons || []; |
| 134 if (options.buttons[i].url) { |
| 135 $Array.splice( |
| 136 options.buttons[i].icons, |
| 137 0, |
| 138 0, |
| 139 {scale: 1.0, data: options.buttons[i].url}); |
| 140 } |
| 141 } |
| 142 |
| 143 return [id, options, callback]; |
| 144 } |
| 145 |
122 var handleCreate = genHandle('notifications.create', | 146 var handleCreate = genHandle('notifications.create', |
123 function(callback, id) { callback(id); }); | 147 function(callback, id) { callback(id); }); |
124 var handleUpdate = genHandle('notifications.update', | 148 var handleUpdate = genHandle('notifications.update', |
125 function(callback, id) { callback(false); }); | 149 function(callback, id) { callback(false); }); |
126 | 150 |
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); |
130 apiFunctions.setHandleRequest('update', handleUpdate); | 155 apiFunctions.setHandleRequest('update', handleUpdate); |
131 }; | 156 }; |
132 | 157 |
133 binding.registerCustomHook(notificationsCustomHook); | 158 binding.registerCustomHook(notificationsCustomHook); |
134 | 159 |
135 exports.binding = binding.generate(); | 160 exports.binding = binding.generate(); |
OLD | NEW |