| 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 "content/child/notifications/pending_notification.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/barrier_closure.h" | |
| 10 #include "base/bind.h" | |
| 11 #include "base/callback.h" | |
| 12 #include "base/location.h" | |
| 13 #include "base/metrics/histogram_macros.h" | |
| 14 #include "base/thread_task_runner_handle.h" | |
| 15 #include "content/common/notification_constants.h" | |
| 16 #include "content/public/common/notification_resources.h" | |
| 17 #include "skia/ext/image_operations.h" | |
| 18 #include "url/gurl.h" | |
| 19 | |
| 20 namespace content { | |
| 21 | |
| 22 namespace { | |
| 23 | |
| 24 // Scales down |icon| to fit within |max_size_px| if its width or height is | |
| 25 // larger than |max_size_px| and returns the result. Otherwise does nothing and | |
| 26 // returns |icon| unchanged. | |
| 27 SkBitmap ScaleDownIfNeeded(const SkBitmap& icon, int max_size_px) { | |
| 28 if (icon.width() > max_size_px || icon.height() > max_size_px) { | |
| 29 SCOPED_UMA_HISTOGRAM_TIMER("Notifications.Icon.ScaleDownTime"); | |
| 30 return skia::ImageOperations::Resize(icon, | |
| 31 skia::ImageOperations::RESIZE_BEST, | |
| 32 std::min(icon.width(), max_size_px), | |
| 33 std::min(icon.height(), max_size_px)); | |
| 34 } | |
| 35 return icon; | |
| 36 } | |
| 37 | |
| 38 } // namespace | |
| 39 | |
| 40 PendingNotification::PendingNotification( | |
| 41 const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner) | |
| 42 : main_task_runner_(main_task_runner), weak_factory_(this) {} | |
| 43 | |
| 44 PendingNotification::~PendingNotification() {} | |
| 45 | |
| 46 void PendingNotification::FetchResources( | |
| 47 const blink::WebNotificationData& notification_data, | |
| 48 const base::Closure& fetches_finished_callback) { | |
| 49 // TODO(mvanouwerkerk): Add a timeout mechanism: crbug.com/579137 | |
| 50 | |
| 51 size_t num_actions = notification_data.actions.size(); | |
| 52 action_icons_.resize(num_actions); | |
| 53 | |
| 54 size_t num_closures = 2 /* notification icon and badge */ + num_actions; | |
| 55 fetches_finished_barrier_closure_ = | |
| 56 base::BarrierClosure(num_closures, fetches_finished_callback); | |
| 57 | |
| 58 FetchImageResource(notification_data.icon, | |
| 59 base::Bind(&PendingNotification::DidFetchNotificationIcon, | |
| 60 weak_factory_.GetWeakPtr())); | |
| 61 FetchImageResource(notification_data.badge, | |
| 62 base::Bind(&PendingNotification::DidFetchBadge, | |
| 63 weak_factory_.GetWeakPtr())); | |
| 64 for (size_t i = 0; i < num_actions; i++) { | |
| 65 FetchImageResource(notification_data.actions[i].icon, | |
| 66 base::Bind(&PendingNotification::DidFetchActionIcon, | |
| 67 weak_factory_.GetWeakPtr(), i)); | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 NotificationResources PendingNotification::GetResources() const { | |
| 72 NotificationResources resources; | |
| 73 resources.notification_icon = notification_icon_; | |
| 74 resources.badge = badge_; | |
| 75 resources.action_icons = action_icons_; | |
| 76 return resources; | |
| 77 } | |
| 78 | |
| 79 void PendingNotification::FetchImageResource( | |
| 80 const blink::WebURL& image_web_url, | |
| 81 const ImageLoadCompletedCallback& image_callback) { | |
| 82 if (image_web_url.isEmpty()) { | |
| 83 image_callback.Run(SkBitmap()); | |
| 84 return; | |
| 85 } | |
| 86 | |
| 87 // Explicitly convert the WebURL to a GURL before passing it to a different | |
| 88 // thread. This is important because WebURLs must not be passed between | |
| 89 // threads, and per base::Bind() semantics conversion would otherwise be done | |
| 90 // on the receiving thread. | |
| 91 GURL image_gurl(image_web_url); | |
| 92 | |
| 93 scoped_refptr<NotificationImageLoader> image_loader( | |
| 94 new NotificationImageLoader(image_callback, | |
| 95 base::ThreadTaskRunnerHandle::Get(), | |
| 96 main_task_runner_)); | |
| 97 image_loaders_.push_back(image_loader); | |
| 98 main_task_runner_->PostTask( | |
| 99 FROM_HERE, base::Bind(&NotificationImageLoader::StartOnMainThread, | |
| 100 image_loader, image_gurl)); | |
| 101 } | |
| 102 | |
| 103 void PendingNotification::DidFetchNotificationIcon(const SkBitmap& bitmap) { | |
| 104 notification_icon_ = | |
| 105 ScaleDownIfNeeded(bitmap, kPlatformNotificationMaxIconSizePx); | |
| 106 fetches_finished_barrier_closure_.Run(); | |
| 107 } | |
| 108 | |
| 109 void PendingNotification::DidFetchBadge(const SkBitmap& bitmap) { | |
| 110 badge_ = ScaleDownIfNeeded(bitmap, kPlatformNotificationMaxBadgeSizePx); | |
| 111 fetches_finished_barrier_closure_.Run(); | |
| 112 } | |
| 113 | |
| 114 void PendingNotification::DidFetchActionIcon(size_t action_index, | |
| 115 const SkBitmap& bitmap) { | |
| 116 DCHECK_LT(action_index, action_icons_.size()); | |
| 117 | |
| 118 action_icons_[action_index] = | |
| 119 ScaleDownIfNeeded(bitmap, kPlatformNotificationMaxActionIconSizePx); | |
| 120 fetches_finished_barrier_closure_.Run(); | |
| 121 } | |
| 122 | |
| 123 } // namespace content | |
| OLD | NEW |