| OLD | NEW | 
|    1 // Copyright 2016 The Chromium Authors. All rights reserved. |    1 // Copyright 2016 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 #include "modules/notifications/NotificationImageLoader.h" |    5 #include "modules/notifications/NotificationImageLoader.h" | 
|    6  |    6  | 
|    7 #include "core/dom/ExecutionContext.h" |    7 #include "core/dom/ExecutionContext.h" | 
|    8 #include "core/fetch/ResourceLoaderOptions.h" |    8 #include "core/fetch/ResourceLoaderOptions.h" | 
|    9 #include "platform/Histogram.h" |    9 #include "platform/Histogram.h" | 
|   10 #include "platform/image-decoders/ImageDecoder.h" |   10 #include "platform/image-decoders/ImageDecoder.h" | 
|   11 #include "platform/image-decoders/ImageFrame.h" |   11 #include "platform/image-decoders/ImageFrame.h" | 
|   12 #include "platform/network/ResourceError.h" |   12 #include "platform/network/ResourceError.h" | 
|   13 #include "platform/network/ResourceLoadPriority.h" |   13 #include "platform/network/ResourceLoadPriority.h" | 
|   14 #include "platform/network/ResourceRequest.h" |   14 #include "platform/network/ResourceRequest.h" | 
|   15 #include "platform/weborigin/KURL.h" |   15 #include "platform/weborigin/KURL.h" | 
|   16 #include "public/platform/WebURLRequest.h" |   16 #include "public/platform/WebURLRequest.h" | 
|   17 #include "public/platform/modules/notifications/WebNotificationConstants.h" |   17 #include "third_party/skia/include/core/SkBitmap.h" | 
|   18 #include "skia/ext/image_operations.h" |  | 
|   19 #include "wtf/CurrentTime.h" |   18 #include "wtf/CurrentTime.h" | 
|   20 #include "wtf/Threading.h" |   19 #include "wtf/Threading.h" | 
|   21 #include <memory> |   20 #include <memory> | 
|   22  |   21  | 
|   23 #define NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, type_name, value, max) \ |  | 
|   24   case NotificationImageLoader::Type::type_name: {                            \ |  | 
|   25     DEFINE_THREAD_SAFE_STATIC_LOCAL(                                          \ |  | 
|   26         CustomCountHistogram, metric##type_name##Histogram,                   \ |  | 
|   27         new CustomCountHistogram("Notifications." #metric "." #type_name,     \ |  | 
|   28                                  1 /* min */, max, 50 /* buckets */));        \ |  | 
|   29     metric##type_name##Histogram.count(value);                                \ |  | 
|   30     break;                                                                    \ |  | 
|   31   } |  | 
|   32  |  | 
|   33 #define NOTIFICATION_HISTOGRAM_COUNTS(metric, type, value, max)            \ |  | 
|   34   switch (type) {                                                          \ |  | 
|   35     NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Image, value, max)      \ |  | 
|   36     NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Icon, value, max)       \ |  | 
|   37     NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Badge, value, max)      \ |  | 
|   38     NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, ActionIcon, value, max) \ |  | 
|   39   } |  | 
|   40  |  | 
|   41 namespace { |   22 namespace { | 
|   42  |   23  | 
|   43 // 99.9% of all images were fetched successfully in 90 seconds. |   24 // 99.9% of all images were fetched successfully in 90 seconds. | 
|   44 const unsigned long kImageFetchTimeoutInMs = 90000; |   25 const unsigned long kImageFetchTimeoutInMs = 90000; | 
|   45  |   26  | 
|   46 }  // namespace |   27 }  // namespace | 
|   47  |   28  | 
|   48 namespace blink { |   29 namespace blink { | 
|   49  |   30  | 
|   50 NotificationImageLoader::NotificationImageLoader(Type type) |   31 NotificationImageLoader::NotificationImageLoader() | 
|   51     : m_type(type), m_stopped(false), m_startTime(0.0) {} |   32     : m_stopped(false), m_startTime(0.0) {} | 
|   52  |   33  | 
|   53 NotificationImageLoader::~NotificationImageLoader() {} |   34 NotificationImageLoader::~NotificationImageLoader() {} | 
|   54  |   35  | 
|   55 // static |  | 
|   56 SkBitmap NotificationImageLoader::scaleDownIfNeeded(const SkBitmap& image, |  | 
|   57                                                     Type type) { |  | 
|   58   int maxWidthPx = 0, maxHeightPx = 0; |  | 
|   59   switch (type) { |  | 
|   60     case Type::Image: |  | 
|   61       maxWidthPx = kWebNotificationMaxImageWidthPx; |  | 
|   62       maxHeightPx = kWebNotificationMaxImageHeightPx; |  | 
|   63       break; |  | 
|   64     case Type::Icon: |  | 
|   65       maxWidthPx = kWebNotificationMaxIconSizePx; |  | 
|   66       maxHeightPx = kWebNotificationMaxIconSizePx; |  | 
|   67       break; |  | 
|   68     case Type::Badge: |  | 
|   69       maxWidthPx = kWebNotificationMaxBadgeSizePx; |  | 
|   70       maxHeightPx = kWebNotificationMaxBadgeSizePx; |  | 
|   71       break; |  | 
|   72     case Type::ActionIcon: |  | 
|   73       maxWidthPx = kWebNotificationMaxActionIconSizePx; |  | 
|   74       maxHeightPx = kWebNotificationMaxActionIconSizePx; |  | 
|   75       break; |  | 
|   76   } |  | 
|   77   DCHECK_GT(maxWidthPx, 0); |  | 
|   78   DCHECK_GT(maxHeightPx, 0); |  | 
|   79   // TODO(peter): Explore doing the scaling on a background thread. |  | 
|   80   if (image.width() > maxWidthPx || image.height() > maxHeightPx) { |  | 
|   81     double scale = std::min(static_cast<double>(maxWidthPx) / image.width(), |  | 
|   82                             static_cast<double>(maxHeightPx) / image.height()); |  | 
|   83     double startTime = monotonicallyIncreasingTimeMS(); |  | 
|   84     // TODO(peter): Try using RESIZE_BETTER for large images. |  | 
|   85     SkBitmap scaledImage = |  | 
|   86         skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST, |  | 
|   87                                       std::lround(scale * image.width()), |  | 
|   88                                       std::lround(scale * image.height())); |  | 
|   89     NOTIFICATION_HISTOGRAM_COUNTS(LoadScaleDownTime, type, |  | 
|   90                                   monotonicallyIncreasingTimeMS() - startTime, |  | 
|   91                                   1000 * 10 /* 10 seconds max */); |  | 
|   92     return scaledImage; |  | 
|   93   } |  | 
|   94   return image; |  | 
|   95 } |  | 
|   96  |  | 
|   97 void NotificationImageLoader::start( |   36 void NotificationImageLoader::start( | 
|   98     ExecutionContext* executionContext, |   37     ExecutionContext* executionContext, | 
|   99     const KURL& url, |   38     const KURL& url, | 
|  100     std::unique_ptr<ImageCallback> imageCallback) { |   39     std::unique_ptr<ImageCallback> imageCallback) { | 
|  101   DCHECK(!m_stopped); |   40   DCHECK(!m_stopped); | 
|  102  |   41  | 
|  103   m_startTime = monotonicallyIncreasingTimeMS(); |   42   m_startTime = monotonicallyIncreasingTimeMS(); | 
|  104   m_imageCallback = std::move(imageCallback); |   43   m_imageCallback = std::move(imageCallback); | 
|  105  |   44  | 
|  106   ThreadableLoaderOptions threadableLoaderOptions; |   45   ThreadableLoaderOptions threadableLoaderOptions; | 
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  143   m_data->append(data, length); |   82   m_data->append(data, length); | 
|  144 } |   83 } | 
|  145  |   84  | 
|  146 void NotificationImageLoader::didFinishLoading(unsigned long resourceIdentifier, |   85 void NotificationImageLoader::didFinishLoading(unsigned long resourceIdentifier, | 
|  147                                                double finishTime) { |   86                                                double finishTime) { | 
|  148   // If this has been stopped it is not desirable to trigger further work, |   87   // If this has been stopped it is not desirable to trigger further work, | 
|  149   // there is a shutdown of some sort in progress. |   88   // there is a shutdown of some sort in progress. | 
|  150   if (m_stopped) |   89   if (m_stopped) | 
|  151     return; |   90     return; | 
|  152  |   91  | 
|  153   NOTIFICATION_HISTOGRAM_COUNTS(LoadFinishTime, m_type, |   92   DEFINE_THREAD_SAFE_STATIC_LOCAL( | 
|  154                                 monotonicallyIncreasingTimeMS() - m_startTime, |   93       CustomCountHistogram, finishedTimeHistogram, | 
|  155                                 1000 * 60 * 60 /* 1 hour max */); |   94       new CustomCountHistogram("Notifications.Icon.LoadFinishTime", 1, | 
 |   95                                1000 * 60 * 60 /* 1 hour max */, | 
 |   96                                50 /* buckets */)); | 
 |   97   finishedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime); | 
|  156  |   98  | 
|  157   if (m_data) { |   99   if (m_data) { | 
|  158     NOTIFICATION_HISTOGRAM_COUNTS(LoadFileSize, m_type, m_data->size(), |  100     DEFINE_THREAD_SAFE_STATIC_LOCAL( | 
|  159                                   10000000 /* ~10mb max */); |  101         CustomCountHistogram, fileSizeHistogram, | 
 |  102         new CustomCountHistogram("Notifications.Icon.FileSize", 1, | 
 |  103                                  10000000 /* ~10mb max */, 50 /* buckets */)); | 
 |  104     fileSizeHistogram.count(m_data->size()); | 
|  160  |  105  | 
|  161     std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create( |  106     std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create( | 
|  162         m_data, true /* dataComplete */, ImageDecoder::AlphaPremultiplied, |  107         m_data, true /* dataComplete */, ImageDecoder::AlphaPremultiplied, | 
|  163         ImageDecoder::ColorSpaceTransformed, |  108         ImageDecoder::ColorSpaceTransformed, | 
|  164         ImageDecoder::globalTargetColorSpace()); |  109         ImageDecoder::globalTargetColorSpace()); | 
|  165     if (decoder) { |  110     if (decoder) { | 
|  166       // The |ImageFrame*| is owned by the decoder. |  111       // The |ImageFrame*| is owned by the decoder. | 
|  167       ImageFrame* imageFrame = decoder->frameBufferAtIndex(0); |  112       ImageFrame* imageFrame = decoder->frameBufferAtIndex(0); | 
|  168       if (imageFrame) { |  113       if (imageFrame) { | 
|  169         (*m_imageCallback)(imageFrame->bitmap()); |  114         (*m_imageCallback)(imageFrame->bitmap()); | 
|  170         return; |  115         return; | 
|  171       } |  116       } | 
|  172     } |  117     } | 
|  173   } |  118   } | 
|  174   runCallbackWithEmptyBitmap(); |  119   runCallbackWithEmptyBitmap(); | 
|  175 } |  120 } | 
|  176  |  121  | 
|  177 void NotificationImageLoader::didFail(const ResourceError& error) { |  122 void NotificationImageLoader::didFail(const ResourceError& error) { | 
|  178   NOTIFICATION_HISTOGRAM_COUNTS(LoadFailTime, m_type, |  123   DEFINE_THREAD_SAFE_STATIC_LOCAL( | 
|  179                                 monotonicallyIncreasingTimeMS() - m_startTime, |  124       CustomCountHistogram, failedTimeHistogram, | 
|  180                                 1000 * 60 * 60 /* 1 hour max */); |  125       new CustomCountHistogram("Notifications.Icon.LoadFailTime", 1, | 
 |  126                                1000 * 60 * 60 /* 1 hour max */, | 
 |  127                                50 /* buckets */)); | 
 |  128   failedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime); | 
|  181  |  129  | 
|  182   runCallbackWithEmptyBitmap(); |  130   runCallbackWithEmptyBitmap(); | 
|  183 } |  131 } | 
|  184  |  132  | 
|  185 void NotificationImageLoader::didFailRedirectCheck() { |  133 void NotificationImageLoader::didFailRedirectCheck() { | 
|  186   runCallbackWithEmptyBitmap(); |  134   runCallbackWithEmptyBitmap(); | 
|  187 } |  135 } | 
|  188  |  136  | 
|  189 void NotificationImageLoader::runCallbackWithEmptyBitmap() { |  137 void NotificationImageLoader::runCallbackWithEmptyBitmap() { | 
|  190   // If this has been stopped it is not desirable to trigger further work, |  138   // If this has been stopped it is not desirable to trigger further work, | 
|  191   // there is a shutdown of some sort in progress. |  139   // there is a shutdown of some sort in progress. | 
|  192   if (m_stopped) |  140   if (m_stopped) | 
|  193     return; |  141     return; | 
|  194  |  142  | 
|  195   (*m_imageCallback)(SkBitmap()); |  143   (*m_imageCallback)(SkBitmap()); | 
|  196 } |  144 } | 
|  197  |  145  | 
|  198 }  // namespace blink |  146 }  // namespace blink | 
| OLD | NEW |