Chromium Code Reviews| 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 |