Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(999)

Side by Side Diff: chrome/renderer/resources/extensions/notifications_custom_bindings.js

Issue 354733002: Notifications API support for images with multiple scale factors. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Updates custom bindings tests. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698