1 // Copyright (c) 2012 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 var SetIconCommon = requireNative('setIcon').SetIconCommon; 6 var sendRequest = require('sendRequest').sendRequest; 7 8 function loadImagePath(path, iconSize, actionType, callback) { 9 var img = new Image(); 10 img.onerror = function() { 11 console.error('Could not load ' + actionType + ' icon \'' + 12 path + '\'.'); 13 }; 14 img.onload = function() { 15 var canvas = document.createElement('canvas'); 16 canvas.width = img.width > iconSize ? iconSize : img.width; 17 canvas.height = img.height > iconSize ? iconSize : img.height; 18 19 var canvas_context = canvas.getContext('2d'); 20 canvas_context.clearRect(0, 0, canvas.width, canvas.height); 21 canvas_context.drawImage(img, 0, 0, canvas.width, canvas.height); 22 var imageData = canvas_context.getImageData(0, 0, canvas.width, 23 canvas.height); 24 callback(imageData); 25 }; 26 img.src = path; 27 } 28 29 function verifyImageData(imageData, iconSize) { 30 // Verify that this at least looks like an ImageData element. 31 // Unfortunately, we cannot use instanceof because the ImageData 32 // constructor is not public. 33 // 34 // We do this manually instead of using JSONSchema to avoid having these 35 // properties show up in the doc. 36 if (!('width' in imageData) || 37 !('height' in imageData) || 38 !('data' in imageData)) { 39 throw new Error( 40 'The imageData property must contain an ImageData object or' + 41 ' dictionary of ImageData objects.'); 42 } 43 44 if (imageData.width > iconSize || 45 imageData.height > iconSize) { 46 throw new Error( 47 'The imageData property must contain an ImageData object that ' + 48 'is no larger than ' + iconSize + ' pixels square.'); 49 } 50 } 51 52 function setIcon(details, callback, name, parameters, actionType) { 53 var iconSizes = [19, 38]; 54 if ('iconIndex' in details) { 55 sendRequest(name, [details, callback], parameters); 56 } else if ('imageData' in details) { 57 if (typeof details.imageData == 'object') { 58 var isEmpty = true; 59 for (var i = 0; i < iconSizes.length; i++) { 60 var sizeKey = iconSizes[i].toString(); 61 if (sizeKey in details.imageData) { 62 verifyImageData(details.imageData[sizeKey], iconSizes[i]); 63 isEmpty =false; 64 } 65 } 66 67 if (!isEmpty) { 68 sendRequest(name, [details, callback], parameters, 69 {nativeFunction: SetIconCommon}); 70 } else { 71 // If details.imageData is not dictionary with keys in set {'19', '38'}, 72 // it must be an ImageData object. 73 var sizeKey = iconSizes[0].toString(); 74 var imageData = details.imageData; 75 details.imageData = {}; 76 details.imageData[sizeKey] = imageData; 77 verifyImageData(details.imageData[sizeKey], iconSizes[0]); 78 sendRequest(name, [details, callback], parameters, 79 {nativeFunction: SetIconCommon}); 80 } 81 } else { 82 throw new Error('imageData property has unexpected type.'); 83 } 84 } else if ('path' in details) { 85 if (typeof details.path == 'object') { 86 details.imageData = {}; 87 var isEmpty = true; 88 var processIconSize = function(index) { 89 if (index == iconSizes.length) { 90 delete details.path; 91 if (isEmpty) 92 throw new Error('The path property must not be empty.'); 93 sendRequest(name, [details, callback], parameters, 94 {nativeFunction: SetIconCommon}); 95 return; 96 } 97 var sizeKey = iconSizes[index].toString(); 98 if (!(sizeKey in details.path)) { 99 processIconSize(index + 1); 100 return; 101 } 102 isEmpty = false; 103 loadImagePath(details.path[sizeKey], iconSizes[index], actionType, 104 function(imageData) { 105 details.imageData[sizeKey] = imageData; 106 processIconSize(index + 1); 107 }); 108 } 109 110 processIconSize(0); 111 } else if (typeof details.path == 'string') { 112 var sizeKey = iconSizes[0].toString(); 113 details.imageData = {}; 114 loadImagePath(details.path, iconSizes[0], actionType, 115 function(imageData) { 116 details.imageData[sizeKey] = imageData; 117 delete details.path; 118 sendRequest(name, [details, callback], parameters, 119 {nativeFunction: SetIconCommon}); 120 }); 121 } else { 122 throw new Error('The path property should contain either string or ' + 123 'dictionary of strings.'); 124 } 125 } else { 126 throw new Error( 127 'Either the path or imageData property must be specified.'); 128 } 129 } 130 131 exports.setIcon = setIcon; 132