OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "modules/notifications/NotificationResourcesLoader.h" | |
6 | |
7 #include "core/dom/ExecutionContext.h" | |
8 #include "public/platform/modules/notifications/WebNotificationData.h" | |
9 #include "public/platform/modules/notifications/WebNotificationResources.h" | |
10 #include "skia/ext/image_operations.h" | |
11 #include "third_party/skia/include/core/SkBitmap.h" | |
12 | |
13 namespace blink { | |
14 | |
15 namespace { | |
16 | |
17 // TODO(mvanouwerkerk): Get icon dimensions from the embedder. | |
18 | |
19 // The maximum reasonable notification icon size, scaled from dip units to | |
20 // pixels using the largest supported scaling factor. | |
21 static const int kMaxIconSizePx = 320; // 80 dip * 4 | |
22 | |
23 // The maximum reasonable badge size, scaled from dip units to pixels using the | |
24 // largest supported scaling factor. | |
25 static const int kMaxBadgeSizePx = 96; // 24 dip * 4 | |
26 | |
27 // The maximum reasonable action icon size, scaled from dip units to pixels | |
28 // using the largest supported scaling factor. | |
29 static const int kMaxActionIconSizePx = 128; // 32 dip * 4 | |
30 | |
31 // Scales down |image| to fit within |maxSizePx| if its width or height is | |
32 // larger than |maxSizePx| and returns the result. Otherwise does nothing and | |
33 // returns |image| unchanged. | |
34 SkBitmap scaleDownIfNeeded(const SkBitmap& image, int maxSizePx) | |
35 { | |
36 if (image.width() > maxSizePx || image.height() > maxSizePx) { | |
37 return skia::ImageOperations::Resize(image, | |
38 skia::ImageOperations::RESIZE_BEST, | |
39 std::min(image.width(), maxSizePx), | |
40 std::min(image.height(), maxSizePx)); | |
41 } | |
42 return image; | |
43 } | |
44 | |
45 } // namespace | |
46 | |
47 NotificationResourcesLoader::NotificationResourcesLoader( | |
48 ExecutionContext* executionContext, | |
49 PassOwnPtr<CompletionCallback> completionCallback) | |
50 : ContextLifecycleObserver(executionContext) | |
51 , m_completionCallback(completionCallback) | |
52 , m_pendingRequestCount(0) | |
53 { | |
54 ThreadState::current()->registerPreFinalizer(this); | |
Peter Beverloo
2016/04/13 18:32:27
DCHECK(m_completionCallback)
Michael van Ouwerkerk
2016/04/14 13:42:11
Done.
| |
55 } | |
56 | |
57 NotificationResourcesLoader::~NotificationResourcesLoader() | |
58 { | |
59 } | |
60 | |
61 void NotificationResourcesLoader::start( | |
Peter Beverloo
2016/04/13 18:32:27
micro nit: nowrap
Michael van Ouwerkerk
2016/04/14 13:42:11
Done.
| |
62 const WebNotificationData& notificationData) | |
63 { | |
64 size_t numActions = notificationData.actions.size(); | |
65 m_pendingRequestCount = 2 /* icon and badge */ + numActions; | |
66 | |
67 loadImage(notificationData.icon, | |
68 bind<const SkBitmap&>(&NotificationResourcesLoader::didLoadIcon, | |
69 WeakPersistentThisPointer<NotificationResourcesLoader>(this))); | |
70 loadImage(notificationData.badge, | |
71 bind<const SkBitmap&>(&NotificationResourcesLoader::didLoadBadge, | |
72 WeakPersistentThisPointer<NotificationResourcesLoader>(this))); | |
73 | |
74 m_actionIcons.resize(numActions); | |
75 for (size_t i = 0; i < numActions; i++) { | |
76 loadImage(notificationData.actions[i].icon, | |
77 bind<const SkBitmap&>( | |
78 &NotificationResourcesLoader::didLoadActionIcon, | |
79 WeakPersistentThisPointer<NotificationResourcesLoader>(this), | |
80 i)); | |
81 } | |
82 } | |
83 | |
84 std::unique_ptr<WebNotificationResources> | |
85 NotificationResourcesLoader::getResources() const | |
86 { | |
87 std::unique_ptr<WebNotificationResources> | |
Peter Beverloo
2016/04/13 18:32:27
micro nit: nowrap
Michael van Ouwerkerk
2016/04/14 13:42:11
Done.
| |
88 resources(new WebNotificationResources()); | |
89 resources->icon = m_icon; | |
90 resources->badge = m_badge; | |
91 resources->actionIcons = m_actionIcons; | |
92 return resources; | |
93 } | |
94 | |
95 void NotificationResourcesLoader::contextDestroyed() | |
96 { | |
97 stop(); | |
98 } | |
99 | |
100 void NotificationResourcesLoader::stop() | |
101 { | |
102 for (auto imageLoader : m_imageLoaders) | |
103 imageLoader->stop(); | |
104 } | |
105 | |
106 DEFINE_TRACE(NotificationResourcesLoader) | |
107 { | |
108 visitor->trace(m_imageLoaders); | |
109 ContextLifecycleObserver::trace(visitor); | |
110 } | |
111 | |
112 void NotificationResourcesLoader::loadImage( | |
113 const KURL& url, | |
114 PassOwnPtr<NotificationImageLoader::ImageCallback> imageCallback) | |
115 { | |
116 if (url.isNull() || url.isEmpty() || !url.isValid()) { | |
117 didFinishRequest(); | |
118 return; | |
119 } | |
120 | |
121 NotificationImageLoader* imageLoader = new NotificationImageLoader(); | |
122 m_imageLoaders.append(imageLoader); | |
123 imageLoader->start(getExecutionContext(), url, imageCallback); | |
124 } | |
125 | |
126 void NotificationResourcesLoader::didLoadIcon(const SkBitmap& image) | |
127 { | |
128 m_icon = scaleDownIfNeeded(image, kMaxIconSizePx); | |
129 didFinishRequest(); | |
130 } | |
131 | |
132 void NotificationResourcesLoader::didLoadBadge(const SkBitmap& image) | |
133 { | |
134 m_badge = scaleDownIfNeeded(image, kMaxBadgeSizePx); | |
Peter Beverloo
2016/04/13 18:32:28
As a.. refactoring opportunity, have you considere
Michael van Ouwerkerk
2016/04/14 13:42:11
I've added a TODO at scaleDownIfNeeded. In the cur
Peter Beverloo
2016/04/15 11:07:29
I.e. unpredictable performance from the developer'
| |
135 didFinishRequest(); | |
136 } | |
137 | |
138 void NotificationResourcesLoader::didLoadActionIcon(size_t actionIndex, | |
Peter Beverloo
2016/04/13 18:32:27
micro nit: nowrap
Michael van Ouwerkerk
2016/04/14 13:42:11
Done.
| |
139 const SkBitmap& image) | |
140 { | |
141 DCHECK_LT(actionIndex, m_actionIcons.size()); | |
142 | |
143 m_actionIcons[actionIndex] = scaleDownIfNeeded(image, kMaxActionIconSizePx); | |
144 didFinishRequest(); | |
145 } | |
146 | |
147 void NotificationResourcesLoader::didFinishRequest() | |
148 { | |
149 DCHECK_GT(m_pendingRequestCount, 0); | |
150 m_pendingRequestCount--; | |
151 if (!m_pendingRequestCount) { | |
152 m_imageLoaders.clear(); | |
153 (*m_completionCallback)(this); | |
154 // The |this| pointer may have been deleted now. | |
155 } | |
156 } | |
157 | |
158 } // namespace blink | |
OLD | NEW |