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/NotificationResourcesLoader.h" | 5 #include "modules/notifications/NotificationResourcesLoader.h" |
6 | 6 |
7 #include "platform/Histogram.h" | 7 #include "platform/Histogram.h" |
8 #include "platform/weborigin/KURL.h" | 8 #include "platform/weborigin/KURL.h" |
9 #include "public/platform/modules/notifications/WebNotificationConstants.h" | 9 #include "public/platform/modules/notifications/WebNotificationConstants.h" |
10 #include "public/platform/modules/notifications/WebNotificationData.h" | 10 #include "public/platform/modules/notifications/WebNotificationData.h" |
11 #include "public/platform/modules/notifications/WebNotificationResources.h" | 11 #include "public/platform/modules/notifications/WebNotificationResources.h" |
12 #include "skia/ext/image_operations.h" | 12 #include "skia/ext/image_operations.h" |
13 #include "third_party/skia/include/core/SkBitmap.h" | 13 #include "third_party/skia/include/core/SkBitmap.h" |
14 #include "wtf/CurrentTime.h" | 14 #include "wtf/CurrentTime.h" |
15 #include "wtf/Threading.h" | 15 #include "wtf/Threading.h" |
16 #include <cmath> | |
16 | 17 |
17 namespace blink { | 18 namespace blink { |
18 | 19 |
19 namespace { | 20 namespace { |
20 | 21 |
21 // Scales down |image| to fit within |maxSizePx| if its width or height is | 22 // Scales down |image| to fit within |maxWidthPx|x|maxHeightPx| if it is larger |
22 // larger than |maxSizePx| and returns the result. Otherwise does nothing and | 23 // and returns the result. Otherwise does nothing and returns |image| unchanged. |
23 // returns |image| unchanged. | |
24 // TODO(mvanouwerkerk): Explore doing the scaling on a background thread. | 24 // TODO(mvanouwerkerk): Explore doing the scaling on a background thread. |
25 SkBitmap scaleDownIfNeeded(const SkBitmap& image, int maxSizePx) | 25 SkBitmap scaleDownIfNeeded(const SkBitmap& image, int maxWidthPx, int maxHeightP x) |
26 { | 26 { |
27 if (image.width() > maxSizePx || image.height() > maxSizePx) { | 27 if (image.width() > maxWidthPx || image.height() > maxHeightPx) { |
28 double scale = std::min( | |
29 maxWidthPx / (float) image.width(), | |
30 maxHeightPx / (float) image.height()); | |
Peter Beverloo
2016/08/22 20:11:07
nit: we don't do C-style casts in Chromium
johnme
2016/08/23 14:59:49
Done.
| |
28 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scaleTimeHistogram , new CustomCountHistogram("Notifications.Icon.ScaleDownTime", 1, 1000 * 10 /* 1 0 seconds max */, 50 /* buckets */)); | 31 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, scaleTimeHistogram , new CustomCountHistogram("Notifications.Icon.ScaleDownTime", 1, 1000 * 10 /* 1 0 seconds max */, 50 /* buckets */)); |
29 double startTime = monotonicallyIncreasingTimeMS(); | 32 double startTime = monotonicallyIncreasingTimeMS(); |
30 SkBitmap scaledImage = skia::ImageOperations::Resize(image, skia::ImageO perations::RESIZE_BEST, std::min(image.width(), maxSizePx), std::min(image.heigh t(), maxSizePx)); | 33 skia::ImageOperations::ResizeMethod quality = std::max(image.width(), ma xWidthPx) > 640 ? skia::ImageOperations::RESIZE_GOOD : skia::ImageOperations::RE SIZE_BEST; |
Peter Beverloo
2016/08/22 20:11:07
I have two concerns about this:
(1) It's unclea
johnme
2016/08/23 14:59:49
It seems we should use RESIZE_BETTER in this case
| |
34 SkBitmap scaledImage = skia::ImageOperations::Resize(image, quality, std ::lround(scale * image.width()), std::lround(scale * image.height())); | |
31 scaleTimeHistogram.count(monotonicallyIncreasingTimeMS() - startTime); | 35 scaleTimeHistogram.count(monotonicallyIncreasingTimeMS() - startTime); |
32 return scaledImage; | 36 return scaledImage; |
33 } | 37 } |
34 return image; | 38 return image; |
35 } | 39 } |
36 | 40 |
37 } // namespace | 41 } // namespace |
38 | 42 |
39 NotificationResourcesLoader::NotificationResourcesLoader(std::unique_ptr<Complet ionCallback> completionCallback) | 43 NotificationResourcesLoader::NotificationResourcesLoader(std::unique_ptr<Complet ionCallback> completionCallback) |
40 : m_started(false), m_completionCallback(std::move(completionCallback)), m_p endingRequestCount(0) | 44 : m_started(false), m_completionCallback(std::move(completionCallback)), m_p endingRequestCount(0) |
41 { | 45 { |
42 ThreadState::current()->registerPreFinalizer(this); | 46 ThreadState::current()->registerPreFinalizer(this); |
43 DCHECK(m_completionCallback); | 47 DCHECK(m_completionCallback); |
44 } | 48 } |
45 | 49 |
46 NotificationResourcesLoader::~NotificationResourcesLoader() | 50 NotificationResourcesLoader::~NotificationResourcesLoader() |
47 { | 51 { |
48 } | 52 } |
49 | 53 |
50 void NotificationResourcesLoader::start(ExecutionContext* executionContext, cons t WebNotificationData& notificationData) | 54 void NotificationResourcesLoader::start(ExecutionContext* executionContext, cons t WebNotificationData& notificationData) |
51 { | 55 { |
52 DCHECK(!m_started); | 56 DCHECK(!m_started); |
53 m_started = true; | 57 m_started = true; |
54 | 58 |
55 size_t numActions = notificationData.actions.size(); | 59 size_t numActions = notificationData.actions.size(); |
56 m_pendingRequestCount = 2 /* icon and badge */ + numActions; | 60 m_pendingRequestCount = 3 /* image, icon, badge */ + numActions; |
57 | 61 |
62 loadImage(executionContext, notificationData.image, WTF::bind(&NotificationR esourcesLoader::didLoadImage, wrapWeakPersistent(this))); | |
58 loadImage(executionContext, notificationData.icon, WTF::bind(&NotificationRe sourcesLoader::didLoadIcon, wrapWeakPersistent(this))); | 63 loadImage(executionContext, notificationData.icon, WTF::bind(&NotificationRe sourcesLoader::didLoadIcon, wrapWeakPersistent(this))); |
59 loadImage(executionContext, notificationData.badge, WTF::bind(&NotificationR esourcesLoader::didLoadBadge, wrapWeakPersistent(this))); | 64 loadImage(executionContext, notificationData.badge, WTF::bind(&NotificationR esourcesLoader::didLoadBadge, wrapWeakPersistent(this))); |
60 | 65 |
61 m_actionIcons.resize(numActions); | 66 m_actionIcons.resize(numActions); |
62 for (size_t i = 0; i < numActions; i++) | 67 for (size_t i = 0; i < numActions; i++) |
63 loadImage(executionContext, notificationData.actions[i].icon, WTF::bind( &NotificationResourcesLoader::didLoadActionIcon, wrapWeakPersistent(this), i)); | 68 loadImage(executionContext, notificationData.actions[i].icon, WTF::bind( &NotificationResourcesLoader::didLoadActionIcon, wrapWeakPersistent(this), i)); |
64 } | 69 } |
65 | 70 |
66 std::unique_ptr<WebNotificationResources> NotificationResourcesLoader::getResour ces() const | 71 std::unique_ptr<WebNotificationResources> NotificationResourcesLoader::getResour ces() const |
67 { | 72 { |
68 std::unique_ptr<WebNotificationResources> resources(new WebNotificationResou rces()); | 73 std::unique_ptr<WebNotificationResources> resources(new WebNotificationResou rces()); |
74 resources->image = m_image; | |
69 resources->icon = m_icon; | 75 resources->icon = m_icon; |
70 resources->badge = m_badge; | 76 resources->badge = m_badge; |
71 resources->actionIcons = m_actionIcons; | 77 resources->actionIcons = m_actionIcons; |
72 return resources; | 78 return resources; |
73 } | 79 } |
74 | 80 |
75 void NotificationResourcesLoader::stop() | 81 void NotificationResourcesLoader::stop() |
76 { | 82 { |
77 for (auto imageLoader : m_imageLoaders) | 83 for (auto imageLoader : m_imageLoaders) |
78 imageLoader->stop(); | 84 imageLoader->stop(); |
79 } | 85 } |
80 | 86 |
81 DEFINE_TRACE(NotificationResourcesLoader) | 87 DEFINE_TRACE(NotificationResourcesLoader) |
82 { | 88 { |
83 visitor->trace(m_imageLoaders); | 89 visitor->trace(m_imageLoaders); |
84 } | 90 } |
85 | 91 |
86 void NotificationResourcesLoader::loadImage(ExecutionContext* executionContext, const KURL& url, std::unique_ptr<NotificationImageLoader::ImageCallback> imageCa llback) | 92 void NotificationResourcesLoader::loadImage(ExecutionContext* executionContext, const KURL& url, std::unique_ptr<NotificationImageLoader::ImageCallback> imageCa llback) |
87 { | 93 { |
88 if (url.isNull() || url.isEmpty() || !url.isValid()) { | 94 if (url.isNull() || url.isEmpty() || !url.isValid()) { |
89 didFinishRequest(); | 95 didFinishRequest(); |
90 return; | 96 return; |
91 } | 97 } |
92 | 98 |
93 NotificationImageLoader* imageLoader = new NotificationImageLoader(); | 99 NotificationImageLoader* imageLoader = new NotificationImageLoader(); |
94 m_imageLoaders.append(imageLoader); | 100 m_imageLoaders.append(imageLoader); |
95 imageLoader->start(executionContext, url, std::move(imageCallback)); | 101 imageLoader->start(executionContext, url, std::move(imageCallback)); |
96 } | 102 } |
97 | 103 |
104 void NotificationResourcesLoader::didLoadImage(const SkBitmap& image) | |
105 { | |
106 m_image = scaleDownIfNeeded(image, kWebNotificationMaxImageWidthPx, kWebNoti ficationMaxImageHeightPx); | |
107 didFinishRequest(); | |
108 } | |
109 | |
98 void NotificationResourcesLoader::didLoadIcon(const SkBitmap& image) | 110 void NotificationResourcesLoader::didLoadIcon(const SkBitmap& image) |
99 { | 111 { |
100 m_icon = scaleDownIfNeeded(image, kWebNotificationMaxIconSizePx); | 112 m_icon = scaleDownIfNeeded(image, kWebNotificationMaxIconSizePx, kWebNotific ationMaxIconSizePx); |
101 didFinishRequest(); | 113 didFinishRequest(); |
102 } | 114 } |
103 | 115 |
104 void NotificationResourcesLoader::didLoadBadge(const SkBitmap& image) | 116 void NotificationResourcesLoader::didLoadBadge(const SkBitmap& image) |
105 { | 117 { |
106 m_badge = scaleDownIfNeeded(image, kWebNotificationMaxBadgeSizePx); | 118 m_badge = scaleDownIfNeeded(image, kWebNotificationMaxBadgeSizePx, kWebNotif icationMaxBadgeSizePx); |
107 didFinishRequest(); | 119 didFinishRequest(); |
108 } | 120 } |
109 | 121 |
110 void NotificationResourcesLoader::didLoadActionIcon(size_t actionIndex, const Sk Bitmap& image) | 122 void NotificationResourcesLoader::didLoadActionIcon(size_t actionIndex, const Sk Bitmap& image) |
111 { | 123 { |
112 DCHECK_LT(actionIndex, m_actionIcons.size()); | 124 DCHECK_LT(actionIndex, m_actionIcons.size()); |
113 | 125 |
114 m_actionIcons[actionIndex] = scaleDownIfNeeded(image, kWebNotificationMaxAct ionIconSizePx); | 126 m_actionIcons[actionIndex] = scaleDownIfNeeded(image, kWebNotificationMaxAct ionIconSizePx, kWebNotificationMaxActionIconSizePx); |
115 didFinishRequest(); | 127 didFinishRequest(); |
116 } | 128 } |
117 | 129 |
118 void NotificationResourcesLoader::didFinishRequest() | 130 void NotificationResourcesLoader::didFinishRequest() |
119 { | 131 { |
120 DCHECK_GT(m_pendingRequestCount, 0); | 132 DCHECK_GT(m_pendingRequestCount, 0); |
121 m_pendingRequestCount--; | 133 m_pendingRequestCount--; |
122 if (!m_pendingRequestCount) { | 134 if (!m_pendingRequestCount) { |
123 stop(); | 135 stop(); |
124 (*m_completionCallback)(this); | 136 (*m_completionCallback)(this); |
125 // The |this| pointer may have been deleted now. | 137 // The |this| pointer may have been deleted now. |
126 } | 138 } |
127 } | 139 } |
128 | 140 |
129 } // namespace blink | 141 } // namespace blink |
OLD | NEW |