| 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 "ui/arc/notification/arc_notification_item.h" | 5 #include "ui/arc/notification/arc_notification_item.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 11 #include "base/strings/string16.h" | 11 #include "base/strings/string16.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/task_runner.h" | 13 #include "base/task_runner.h" |
| 14 #include "base/task_runner_util.h" | 14 #include "base/task_runner_util.h" |
| 15 #include "base/threading/worker_pool.h" | 15 #include "base/threading/worker_pool.h" |
| 16 #include "components/arc/bitmap/bitmap_type_converters.h" | |
| 17 #include "third_party/skia/include/core/SkCanvas.h" | 16 #include "third_party/skia/include/core/SkCanvas.h" |
| 18 #include "third_party/skia/include/core/SkPaint.h" | 17 #include "third_party/skia/include/core/SkPaint.h" |
| 19 #include "ui/gfx/codec/png_codec.h" | 18 #include "ui/gfx/codec/png_codec.h" |
| 20 #include "ui/gfx/geometry/size.h" | 19 #include "ui/gfx/geometry/size.h" |
| 21 #include "ui/gfx/image/image.h" | 20 #include "ui/gfx/image/image.h" |
| 22 #include "ui/gfx/text_elider.h" | 21 #include "ui/gfx/text_elider.h" |
| 23 #include "ui/message_center/message_center_style.h" | 22 #include "ui/message_center/message_center_style.h" |
| 24 #include "ui/message_center/notification.h" | 23 #include "ui/message_center/notification.h" |
| 25 #include "ui/message_center/notification_types.h" | 24 #include "ui/message_center/notification_types.h" |
| 26 #include "ui/message_center/notifier_settings.h" | 25 #include "ui/message_center/notifier_settings.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 const std::string& notification_key, | 128 const std::string& notification_key, |
| 130 const AccountId& profile_id) | 129 const AccountId& profile_id) |
| 131 : manager_(manager), | 130 : manager_(manager), |
| 132 message_center_(message_center), | 131 message_center_(message_center), |
| 133 profile_id_(profile_id), | 132 profile_id_(profile_id), |
| 134 notification_key_(notification_key), | 133 notification_key_(notification_key), |
| 135 notification_id_(kNotificationIdPrefix + notification_key_), | 134 notification_id_(kNotificationIdPrefix + notification_key_), |
| 136 weak_ptr_factory_(this) {} | 135 weak_ptr_factory_(this) {} |
| 137 | 136 |
| 138 void ArcNotificationItem::UpdateWithArcNotificationData( | 137 void ArcNotificationItem::UpdateWithArcNotificationData( |
| 139 const mojom::ArcNotificationData& data) { | 138 mojom::ArcNotificationDataPtr data) { |
| 140 DCHECK(thread_checker_.CalledOnValidThread()); | 139 DCHECK(thread_checker_.CalledOnValidThread()); |
| 141 DCHECK(notification_key_ == data.key); | 140 DCHECK(notification_key_ == data->key); |
| 142 | 141 |
| 143 // Check if a decode task is on-going or not. If |notification_| is non-null, | 142 // Check if a decode task is on-going or not. If |notification_| is non-null, |
| 144 // a decode task is on-going asynchronously. Otherwise, there is no task. | 143 // a decode task is on-going asynchronously. Otherwise, there is no task and |
| 144 // cache the latest data to the |newer_data_| property. |
| 145 // TODO(yoshiki): Refactor and remove this check by omitting image decoding | 145 // TODO(yoshiki): Refactor and remove this check by omitting image decoding |
| 146 // from here. | 146 // from here. |
| 147 if (CacheArcNotificationData(data)) | 147 if (HasPendingNotification()) { |
| 148 CacheArcNotificationData(std::move(data)); |
| 148 return; | 149 return; |
| 150 } |
| 149 | 151 |
| 150 message_center::RichNotificationData rich_data; | 152 message_center::RichNotificationData rich_data; |
| 151 message_center::NotificationType type; | 153 message_center::NotificationType type; |
| 152 | 154 |
| 153 switch (data.type) { | 155 switch (data->type) { |
| 154 case mojom::ArcNotificationType::BASIC: | 156 case mojom::ArcNotificationType::BASIC: |
| 155 type = message_center::NOTIFICATION_TYPE_BASE_FORMAT; | 157 type = message_center::NOTIFICATION_TYPE_BASE_FORMAT; |
| 156 break; | 158 break; |
| 157 case mojom::ArcNotificationType::LIST: | 159 case mojom::ArcNotificationType::LIST: |
| 158 type = message_center::NOTIFICATION_TYPE_MULTIPLE; | 160 type = message_center::NOTIFICATION_TYPE_MULTIPLE; |
| 159 | 161 |
| 160 if (data.texts.is_null()) | 162 if (data->texts.is_null()) |
| 161 break; | 163 break; |
| 162 | 164 |
| 163 for (size_t i = 0; | 165 for (size_t i = 0; |
| 164 i < std::min(data.texts.size(), | 166 i < std::min(data->texts.size(), |
| 165 message_center::kNotificationMaximumItems - 1); | 167 message_center::kNotificationMaximumItems - 1); |
| 166 i++) { | 168 i++) { |
| 167 rich_data.items.emplace_back( | 169 rich_data.items.emplace_back( |
| 168 base::string16(), base::UTF8ToUTF16(data.texts.at(i).get())); | 170 base::string16(), base::UTF8ToUTF16(data->texts.at(i).get())); |
| 169 } | 171 } |
| 170 | 172 |
| 171 if (data.texts.size() > message_center::kNotificationMaximumItems) { | 173 if (data->texts.size() > message_center::kNotificationMaximumItems) { |
| 172 // Show an elipsis as the 5th item if there are more than 5 items. | 174 // Show an elipsis as the 5th item if there are more than 5 items. |
| 173 rich_data.items.emplace_back(base::string16(), gfx::kEllipsisUTF16); | 175 rich_data.items.emplace_back(base::string16(), gfx::kEllipsisUTF16); |
| 174 } else if (data.texts.size() == | 176 } else if (data->texts.size() == |
| 175 message_center::kNotificationMaximumItems) { | 177 message_center::kNotificationMaximumItems) { |
| 176 // Show the 5th item if there are exact 5 items. | 178 // Show the 5th item if there are exact 5 items. |
| 177 rich_data.items.emplace_back( | 179 rich_data.items.emplace_back( |
| 178 base::string16(), | 180 base::string16(), |
| 179 base::UTF8ToUTF16(data.texts.at(data.texts.size() - 1).get())); | 181 base::UTF8ToUTF16(data->texts.at(data->texts.size() - 1).get())); |
| 180 } | 182 } |
| 181 break; | 183 break; |
| 182 case mojom::ArcNotificationType::IMAGE: | 184 case mojom::ArcNotificationType::IMAGE: |
| 183 type = message_center::NOTIFICATION_TYPE_IMAGE; | 185 type = message_center::NOTIFICATION_TYPE_IMAGE; |
| 184 | 186 |
| 185 if (!data.big_picture.is_null()) { | 187 if (data->big_picture && !data->big_picture->isNull()) { |
| 186 rich_data.image = gfx::Image::CreateFrom1xBitmap( | 188 rich_data.image = gfx::Image::CreateFrom1xBitmap( |
| 187 CropImage(data.big_picture.To<SkBitmap>())); | 189 CropImage(*data->big_picture)); |
| 188 } | 190 } |
| 189 break; | 191 break; |
| 190 case mojom::ArcNotificationType::PROGRESS: | 192 case mojom::ArcNotificationType::PROGRESS: |
| 191 type = message_center::NOTIFICATION_TYPE_PROGRESS; | 193 type = message_center::NOTIFICATION_TYPE_PROGRESS; |
| 192 rich_data.timestamp = base::Time::UnixEpoch() + | 194 rich_data.timestamp = base::Time::UnixEpoch() + |
| 193 base::TimeDelta::FromMilliseconds(data.time); | 195 base::TimeDelta::FromMilliseconds(data->time); |
| 194 rich_data.progress = std::max( | 196 rich_data.progress = std::max( |
| 195 0, std::min(100, static_cast<int>(std::round( | 197 0, std::min(100, static_cast<int>(std::round( |
| 196 static_cast<float>(data.progress_current) / | 198 static_cast<float>(data->progress_current) / |
| 197 data.progress_max * 100)))); | 199 data->progress_max * 100)))); |
| 198 break; | 200 break; |
| 199 } | 201 } |
| 200 DCHECK(IsKnownEnumValue(data.type)) << "Unsupported notification type: " | 202 DCHECK(IsKnownEnumValue(data->type)) << "Unsupported notification type: " |
| 201 << data.type; | 203 << data->type; |
| 202 | 204 |
| 203 for (size_t i = 0; i < data.buttons.size(); i++) { | 205 for (size_t i = 0; i < data->buttons.size(); i++) { |
| 204 rich_data.buttons.emplace_back( | 206 rich_data.buttons.emplace_back( |
| 205 base::UTF8ToUTF16(data.buttons.at(i)->label.get())); | 207 base::UTF8ToUTF16(data->buttons.at(i)->label.get())); |
| 206 } | 208 } |
| 207 | 209 |
| 208 // If the client is old (version < 1), both |no_clear| and |ongoing_event| | 210 // If the client is old (version < 1), both |no_clear| and |ongoing_event| |
| 209 // are false. | 211 // are false. |
| 210 rich_data.pinned = (data.no_clear || data.ongoing_event); | 212 rich_data.pinned = (data->no_clear || data->ongoing_event); |
| 211 | 213 |
| 212 rich_data.priority = ConvertAndroidPriority(data.priority); | 214 rich_data.priority = ConvertAndroidPriority(data->priority); |
| 213 rich_data.small_image = ConvertAndroidSmallIcon(data.small_icon); | 215 if (data->small_icon) |
| 216 rich_data.small_image = gfx::Image::CreateFrom1xBitmap(*data->small_icon); |
| 214 | 217 |
| 215 // The identifier of the notifier, which is used to distinguish the notifiers | 218 // The identifier of the notifier, which is used to distinguish the notifiers |
| 216 // in the message center. | 219 // in the message center. |
| 217 message_center::NotifierId notifier_id( | 220 message_center::NotifierId notifier_id( |
| 218 message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId); | 221 message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId); |
| 219 notifier_id.profile_id = profile_id_.GetUserEmail(); | 222 notifier_id.profile_id = profile_id_.GetUserEmail(); |
| 220 | 223 |
| 221 DCHECK(!data.title.is_null()); | 224 DCHECK(!data->title.is_null()); |
| 222 DCHECK(!data.message.is_null()); | 225 DCHECK(!data->message.is_null()); |
| 223 SetNotification(base::MakeUnique<message_center::Notification>( | 226 SetNotification(base::MakeUnique<message_center::Notification>( |
| 224 type, notification_id_, base::UTF8ToUTF16(data.title.get()), | 227 type, notification_id_, base::UTF8ToUTF16(data->title.get()), |
| 225 base::UTF8ToUTF16(data.message.get()), | 228 base::UTF8ToUTF16(data->message.get()), |
| 226 gfx::Image(), // icon image: Will be overriden later. | 229 gfx::Image(), // icon image: Will be overriden later. |
| 227 base::UTF8ToUTF16("arc"), // display source | 230 base::UTF8ToUTF16("arc"), // display source |
| 228 GURL(), // empty origin url, for system component | 231 GURL(), // empty origin url, for system component |
| 229 notifier_id, rich_data, | 232 notifier_id, rich_data, |
| 230 new ArcNotificationDelegate(weak_ptr_factory_.GetWeakPtr()))); | 233 new ArcNotificationDelegate(weak_ptr_factory_.GetWeakPtr()))); |
| 231 | 234 |
| 232 DCHECK(!data.icon_data.is_null()); | 235 DCHECK(!data->icon_data.is_null()); |
| 233 if (data.icon_data.size() == 0) { | 236 if (data->icon_data.size() == 0) { |
| 234 OnImageDecoded(SkBitmap()); // Pass an empty bitmap. | 237 OnImageDecoded(SkBitmap()); // Pass an empty bitmap. |
| 235 return; | 238 return; |
| 236 } | 239 } |
| 237 | 240 |
| 238 // TODO(yoshiki): Remove decoding by passing a bitmap directly from Android. | 241 // TODO(yoshiki): Remove decoding by passing a bitmap directly from Android. |
| 239 base::PostTaskAndReplyWithResult( | 242 base::PostTaskAndReplyWithResult( |
| 240 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, | 243 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE, |
| 241 base::Bind(&DecodeImage, data.icon_data.storage()), | 244 base::Bind(&DecodeImage, data->icon_data.storage()), |
| 242 base::Bind(&ArcNotificationItem::OnImageDecoded, | 245 base::Bind(&ArcNotificationItem::OnImageDecoded, |
| 243 weak_ptr_factory_.GetWeakPtr())); | 246 weak_ptr_factory_.GetWeakPtr())); |
| 244 } | 247 } |
| 245 | 248 |
| 246 ArcNotificationItem::~ArcNotificationItem() {} | 249 ArcNotificationItem::~ArcNotificationItem() {} |
| 247 | 250 |
| 248 void ArcNotificationItem::OnClosedFromAndroid(bool by_user) { | 251 void ArcNotificationItem::OnClosedFromAndroid(bool by_user) { |
| 249 being_removed_by_manager_ = true; // Closing is initiated by the manager. | 252 being_removed_by_manager_ = true; // Closing is initiated by the manager. |
| 250 message_center_->RemoveNotification(notification_id_, by_user); | 253 message_center_->RemoveNotification(notification_id_, by_user); |
| 251 } | 254 } |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 case 1: // PRIORITY_HIGH | 290 case 1: // PRIORITY_HIGH |
| 288 return 0; | 291 return 0; |
| 289 case 2: // PRIORITY_MAX | 292 case 2: // PRIORITY_MAX |
| 290 return 2; | 293 return 2; |
| 291 default: | 294 default: |
| 292 NOTREACHED() << "Invalid Priority: " << android_priority; | 295 NOTREACHED() << "Invalid Priority: " << android_priority; |
| 293 return 0; | 296 return 0; |
| 294 } | 297 } |
| 295 } | 298 } |
| 296 | 299 |
| 297 // static | 300 bool ArcNotificationItem::HasPendingNotification() { |
| 298 gfx::Image ArcNotificationItem::ConvertAndroidSmallIcon( | 301 return (notification_ != nullptr); |
| 299 const mojom::ArcBitmapPtr& arc_bitmap) { | |
| 300 if (arc_bitmap.is_null()) | |
| 301 return gfx::Image(); | |
| 302 | |
| 303 return gfx::Image::CreateFrom1xBitmap(arc_bitmap.To<SkBitmap>()); | |
| 304 } | 302 } |
| 305 | 303 |
| 306 bool ArcNotificationItem::CacheArcNotificationData( | 304 void ArcNotificationItem::CacheArcNotificationData( |
| 307 const mojom::ArcNotificationData& data) { | 305 mojom::ArcNotificationDataPtr data) { |
| 308 if (!notification_) | |
| 309 return false; | |
| 310 | |
| 311 // Store the latest data to the |newer_data_| property if there is a pending | |
| 312 // |notification_|. | |
| 313 // If old |newer_data_| has been stored, discard the old one. | 306 // If old |newer_data_| has been stored, discard the old one. |
| 314 newer_data_ = data.Clone(); | 307 newer_data_ = std::move(data); |
| 315 return true; | |
| 316 } | 308 } |
| 317 | 309 |
| 318 void ArcNotificationItem::SetNotification( | 310 void ArcNotificationItem::SetNotification( |
| 319 std::unique_ptr<message_center::Notification> notification) { | 311 std::unique_ptr<message_center::Notification> notification) { |
| 320 notification_ = std::move(notification); | 312 notification_ = std::move(notification); |
| 321 } | 313 } |
| 322 | 314 |
| 323 void ArcNotificationItem::AddToMessageCenter() { | 315 void ArcNotificationItem::AddToMessageCenter() { |
| 324 DCHECK(notification_); | 316 DCHECK(notification_); |
| 325 message_center_->AddNotification(std::move(notification_)); | 317 message_center_->AddNotification(std::move(notification_)); |
| 326 | 318 |
| 327 if (newer_data_) { | 319 if (newer_data_) { |
| 328 // There is the newer data, so updates again. | 320 // There is the newer data, so updates again. |
| 329 mojom::ArcNotificationDataPtr data(std::move(newer_data_)); | 321 UpdateWithArcNotificationData(std::move(newer_data_)); |
| 330 UpdateWithArcNotificationData(*data); | |
| 331 } | 322 } |
| 332 } | 323 } |
| 333 | 324 |
| 334 bool ArcNotificationItem::CalledOnValidThread() const { | 325 bool ArcNotificationItem::CalledOnValidThread() const { |
| 335 return thread_checker_.CalledOnValidThread(); | 326 return thread_checker_.CalledOnValidThread(); |
| 336 } | 327 } |
| 337 | 328 |
| 338 void ArcNotificationItem::OnImageDecoded(const SkBitmap& bitmap) { | 329 void ArcNotificationItem::OnImageDecoded(const SkBitmap& bitmap) { |
| 339 DCHECK(thread_checker_.CalledOnValidThread()); | 330 DCHECK(thread_checker_.CalledOnValidThread()); |
| 340 | 331 |
| 341 gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap); | 332 gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap); |
| 342 notification_->set_icon(image); | 333 notification_->set_icon(image); |
| 343 AddToMessageCenter(); | 334 AddToMessageCenter(); |
| 344 } | 335 } |
| 345 | 336 |
| 346 } // namespace arc | 337 } // namespace arc |
| OLD | NEW |