12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Custom bindings for the notifications API.
646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var binding = require('binding').Binding.create('notifications');
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var sendRequest = require('sendRequest').sendRequest;
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var imageUtil = require('imageUtil');
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var lastError = require('lastError');
1246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)var notificationsPrivate = requireNative('notifications_private');
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)function imageDataSetter(context, key) {
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var f = function(val) {
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    this[key] = val;
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return $Function.bind(f, context);
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// A URL Spec is an object with the following keys:
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//  path: The resource to be downloaded.
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//  width: (optional) The maximum width of the image to be downloaded in device
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//         pixels.
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//  height: (optional) The maximum height of the image to be downloaded in
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//          device pixels.
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//  callback: A function to be called when the URL is complete. It
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//    should accept an ImageData object and set the appropriate
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//    field in |notificationDetails|.
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)function getUrlSpecs(imageSizes, notificationDetails) {
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var urlSpecs = [];
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
33558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // |iconUrl| might be optional for notification updates.
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (notificationDetails.iconUrl) {
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    $Array.push(urlSpecs, {
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      path: notificationDetails.iconUrl,
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      width: imageSizes.icon.width * imageSizes.scaleFactor,
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      height: imageSizes.icon.height * imageSizes.scaleFactor,
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      callback: imageDataSetter(notificationDetails, 'iconBitmap')
40558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    });
41558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // |appIconMaskUrl| is optional.
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (notificationDetails.appIconMaskUrl) {
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    $Array.push(urlSpecs, {
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      path: notificationDetails.appIconMaskUrl,
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      width: imageSizes.appIconMask.width * imageSizes.scaleFactor,
485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      height: imageSizes.appIconMask.height * imageSizes.scaleFactor,
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      callback: imageDataSetter(notificationDetails, 'appIconMaskBitmap')
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    });
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |imageUrl| is optional.
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (notificationDetails.imageUrl) {
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    $Array.push(urlSpecs, {
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      path: notificationDetails.imageUrl,
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      width: imageSizes.image.width * imageSizes.scaleFactor,
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      height: imageSizes.image.height * imageSizes.scaleFactor,
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      callback: imageDataSetter(notificationDetails, 'imageBitmap')
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    });
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Each button has an optional icon.
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var buttonList = notificationDetails.buttons;
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (buttonList && typeof buttonList.length === 'number') {
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    var numButtons = buttonList.length;
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    for (var i = 0; i < numButtons; i++) {
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      if (buttonList[i].iconUrl) {
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        $Array.push(urlSpecs, {
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          path: buttonList[i].iconUrl,
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          width: imageSizes.buttonIcon.width * imageSizes.scaleFactor,
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          height: imageSizes.buttonIcon.height * imageSizes.scaleFactor,
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          callback: imageDataSetter(buttonList[i], 'iconBitmap')
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        });
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  return urlSpecs;
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)function replaceNotificationOptionURLs(notification_details, callback) {
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var imageSizes = notificationsPrivate.GetNotificationImageSizes();
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  var url_specs = getUrlSpecs(imageSizes, notification_details);
85558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  if (!url_specs.length) {
86558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    callback(true);
87558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch    return;
88558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  }
89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var errors = 0;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  imageUtil.loadAllImages(url_specs, {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    onerror: function(index) {
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      errors++;
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    },
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    oncomplete: function(imageData) {
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (errors > 0) {
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        callback(false);
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (var index = 0; index < url_specs.length; index++) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        var url_spec = url_specs[index];
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        url_spec.callback(imageData[index]);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback(true);
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  });
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)function genHandle(name, failure_function) {
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return function(id, input_notification_details, callback) {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(dewittj): Remove this hack. This is used as a way to deep
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // copy a complex JSON object.
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var notification_details = JSON.parse(
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        JSON.stringify(input_notification_details));
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    var that = this;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    replaceNotificationOptionURLs(notification_details, function(success) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (success) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        sendRequest(that.name,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            [id, notification_details, callback],
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            that.definition.parameters);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        return;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      lastError.run(name,
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    'Unable to download all specified images.',
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                    null,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    failure_function, [callback, id])
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    });
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var handleCreate = genHandle('notifications.create',
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             function(callback, id) { callback(id); });
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)var handleUpdate = genHandle('notifications.update',
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                             function(callback, id) { callback(false); });
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)var notificationsCustomHook = function(bindingsAPI, extensionId) {
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  var apiFunctions = bindingsAPI.apiFunctions;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  apiFunctions.setHandleRequest('create', handleCreate);
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  apiFunctions.setHandleRequest('update', handleUpdate);
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)binding.registerCustomHook(notificationsCustomHook);
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)exports.binding = binding.generate();
146