| Index: third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
 | 
| diff --git a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
 | 
| index fb717c28a5aff7641993582243550df44841333c..7c4a01cd6f7b08eb448fa6ea52ae9aed1b886cc8 100644
 | 
| --- a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
 | 
| +++ b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
 | 
| @@ -6,14 +6,47 @@
 | 
|  
 | 
|  #include "platform/Histogram.h"
 | 
|  #include "platform/weborigin/KURL.h"
 | 
| +#include "public/platform/modules/notifications/WebNotificationConstants.h"
 | 
|  #include "public/platform/modules/notifications/WebNotificationData.h"
 | 
|  #include "public/platform/modules/notifications/WebNotificationResources.h"
 | 
| +#include "skia/ext/image_operations.h"
 | 
| +#include "third_party/skia/include/core/SkBitmap.h"
 | 
|  #include "wtf/CurrentTime.h"
 | 
|  #include "wtf/Threading.h"
 | 
|  #include <cmath>
 | 
|  
 | 
|  namespace blink {
 | 
|  
 | 
| +namespace {
 | 
| +
 | 
| +// Scales down |image| to fit within |maxWidthPx|x|maxHeightPx| if it is larger
 | 
| +// and returns the result. Otherwise does nothing and returns |image| unchanged.
 | 
| +// TODO(mvanouwerkerk): Explore doing the scaling on a background thread.
 | 
| +SkBitmap scaleDownIfNeeded(const SkBitmap& image,
 | 
| +                           int maxWidthPx,
 | 
| +                           int maxHeightPx) {
 | 
| +  if (image.width() > maxWidthPx || image.height() > maxHeightPx) {
 | 
| +    double scale = std::min(static_cast<double>(maxWidthPx) / image.width(),
 | 
| +                            static_cast<double>(maxHeightPx) / image.height());
 | 
| +    DEFINE_THREAD_SAFE_STATIC_LOCAL(
 | 
| +        CustomCountHistogram, scaleTimeHistogram,
 | 
| +        new CustomCountHistogram("Notifications.Icon.ScaleDownTime", 1,
 | 
| +                                 1000 * 10 /* 10 seconds max */,
 | 
| +                                 50 /* buckets */));
 | 
| +    double startTime = monotonicallyIncreasingTimeMS();
 | 
| +    // TODO(peter): Try using RESIZE_BETTER for large images.
 | 
| +    SkBitmap scaledImage =
 | 
| +        skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST,
 | 
| +                                      std::lround(scale * image.width()),
 | 
| +                                      std::lround(scale * image.height()));
 | 
| +    scaleTimeHistogram.count(monotonicallyIncreasingTimeMS() - startTime);
 | 
| +    return scaledImage;
 | 
| +  }
 | 
| +  return image;
 | 
| +}
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
|  NotificationResourcesLoader::NotificationResourcesLoader(
 | 
|      std::unique_ptr<CompletionCallback> completionCallback)
 | 
|      : m_started(false),
 | 
| @@ -36,23 +69,19 @@ void NotificationResourcesLoader::start(
 | 
|  
 | 
|    // TODO(johnme): ensure image is not loaded when it will not be used.
 | 
|    // TODO(mvanouwerkerk): ensure no badge is loaded when it will not be used.
 | 
| -  loadImage(executionContext, NotificationImageLoader::Type::Image,
 | 
| -            notificationData.image,
 | 
| +  loadImage(executionContext, notificationData.image,
 | 
|              WTF::bind(&NotificationResourcesLoader::didLoadImage,
 | 
|                        wrapWeakPersistent(this)));
 | 
| -  loadImage(executionContext, NotificationImageLoader::Type::Icon,
 | 
| -            notificationData.icon,
 | 
| +  loadImage(executionContext, notificationData.icon,
 | 
|              WTF::bind(&NotificationResourcesLoader::didLoadIcon,
 | 
|                        wrapWeakPersistent(this)));
 | 
| -  loadImage(executionContext, NotificationImageLoader::Type::Badge,
 | 
| -            notificationData.badge,
 | 
| +  loadImage(executionContext, notificationData.badge,
 | 
|              WTF::bind(&NotificationResourcesLoader::didLoadBadge,
 | 
|                        wrapWeakPersistent(this)));
 | 
|  
 | 
|    m_actionIcons.resize(numActions);
 | 
|    for (size_t i = 0; i < numActions; i++)
 | 
| -    loadImage(executionContext, NotificationImageLoader::Type::ActionIcon,
 | 
| -              notificationData.actions[i].icon,
 | 
| +    loadImage(executionContext, notificationData.actions[i].icon,
 | 
|                WTF::bind(&NotificationResourcesLoader::didLoadActionIcon,
 | 
|                          wrapWeakPersistent(this), i));
 | 
|  }
 | 
| @@ -79,7 +108,6 @@ DEFINE_TRACE(NotificationResourcesLoader) {
 | 
|  
 | 
|  void NotificationResourcesLoader::loadImage(
 | 
|      ExecutionContext* executionContext,
 | 
| -    NotificationImageLoader::Type type,
 | 
|      const KURL& url,
 | 
|      std::unique_ptr<NotificationImageLoader::ImageCallback> imageCallback) {
 | 
|    if (url.isNull() || url.isEmpty() || !url.isValid()) {
 | 
| @@ -87,26 +115,26 @@ void NotificationResourcesLoader::loadImage(
 | 
|      return;
 | 
|    }
 | 
|  
 | 
| -  NotificationImageLoader* imageLoader = new NotificationImageLoader(type);
 | 
| +  NotificationImageLoader* imageLoader = new NotificationImageLoader();
 | 
|    m_imageLoaders.append(imageLoader);
 | 
|    imageLoader->start(executionContext, url, std::move(imageCallback));
 | 
|  }
 | 
|  
 | 
|  void NotificationResourcesLoader::didLoadImage(const SkBitmap& image) {
 | 
| -  m_image = NotificationImageLoader::scaleDownIfNeeded(
 | 
| -      image, NotificationImageLoader::Type::Image);
 | 
| +  m_image = scaleDownIfNeeded(image, kWebNotificationMaxImageWidthPx,
 | 
| +                              kWebNotificationMaxImageHeightPx);
 | 
|    didFinishRequest();
 | 
|  }
 | 
|  
 | 
|  void NotificationResourcesLoader::didLoadIcon(const SkBitmap& image) {
 | 
| -  m_icon = NotificationImageLoader::scaleDownIfNeeded(
 | 
| -      image, NotificationImageLoader::Type::Icon);
 | 
| +  m_icon = scaleDownIfNeeded(image, kWebNotificationMaxIconSizePx,
 | 
| +                             kWebNotificationMaxIconSizePx);
 | 
|    didFinishRequest();
 | 
|  }
 | 
|  
 | 
|  void NotificationResourcesLoader::didLoadBadge(const SkBitmap& image) {
 | 
| -  m_badge = NotificationImageLoader::scaleDownIfNeeded(
 | 
| -      image, NotificationImageLoader::Type::Badge);
 | 
| +  m_badge = scaleDownIfNeeded(image, kWebNotificationMaxBadgeSizePx,
 | 
| +                              kWebNotificationMaxBadgeSizePx);
 | 
|    didFinishRequest();
 | 
|  }
 | 
|  
 | 
| @@ -114,8 +142,9 @@ void NotificationResourcesLoader::didLoadActionIcon(size_t actionIndex,
 | 
|                                                      const SkBitmap& image) {
 | 
|    DCHECK_LT(actionIndex, m_actionIcons.size());
 | 
|  
 | 
| -  m_actionIcons[actionIndex] = NotificationImageLoader::scaleDownIfNeeded(
 | 
| -      image, NotificationImageLoader::Type::ActionIcon);
 | 
| +  m_actionIcons[actionIndex] =
 | 
| +      scaleDownIfNeeded(image, kWebNotificationMaxActionIconSizePx,
 | 
| +                        kWebNotificationMaxActionIconSizePx);
 | 
|    didFinishRequest();
 | 
|  }
 | 
|  
 | 
| 
 |