Chromium Code Reviews| Index: components/arc/notification/arc_notification_item.cc |
| diff --git a/components/arc/notification/arc_notification_item.cc b/components/arc/notification/arc_notification_item.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..08c648ffc86bd3b484108ac40679d711d318fb29 |
| --- /dev/null |
| +++ b/components/arc/notification/arc_notification_item.cc |
| @@ -0,0 +1,171 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "components/arc/notification/arc_notification_item.h" |
| + |
| +#include "base/strings/string16.h" |
| +#include "base/strings/utf_string_conversions.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/child/image_decoder_utils.h" |
| +#include "ui/gfx/geometry/size.h" |
| +#include "ui/gfx/image/image.h" |
| +#include "ui/message_center/notification.h" |
| +#include "ui/message_center/notification_types.h" |
| +#include "ui/message_center/notifier_settings.h" |
| + |
| +namespace { |
| + |
| +// static |
| +static const char* kNotificationIdPrefix = "ARC_NOTIFICATION_"; |
| + |
| +SkBitmap DecodeImage(const std::vector<uint8_t>& data) { |
| + DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| + DCHECK(!data.empty()); // empty string should be handled in caller. |
| + |
| + // We may decode an image in the browser process since it has been generated |
| + // in ARC and should be safe. |
| + return content::DecodeImage(&data[0], gfx::Size(), data.size()); |
| +} |
| + |
| +class ArcNotificationDelegate : public message_center::NotificationDelegate { |
| + public: |
| + explicit ArcNotificationDelegate( |
| + base::WeakPtr<arc::ArcNotificationItem> item) |
| + : item_(item) {} |
| + |
| + void Close(bool by_user) override { |
| + if (item_) |
| + item_->Close(by_user); |
| + } |
| + |
| + // Indicates all notifications have a click handler. This changes the mouse |
| + // cursor on hover. |
| + // TODO(yoshiki): Return the correct value according to the content intent |
| + // and the flags. |
| + bool HasClickedListener() override { return true; } |
| + |
| + void Click() override { |
| + if (item_) |
| + item_->Click(); |
| + } |
| + |
| + private: |
| + // The destractor is private since this class is ref-counted. |
| + ~ArcNotificationDelegate() override {} |
| + |
| + base::WeakPtr<arc::ArcNotificationItem> item_; |
|
hidehiko
2015/12/17 07:47:51
nit: Oops, I overlooked. DISALLOW_COPY_AND_ASSIGN.
yoshiki
2015/12/17 19:15:14
Done.
|
| +}; |
| + |
| +} // anonymous namespace |
| + |
| +namespace arc { |
| + |
| +ArcNotificationItem::ArcNotificationItem( |
| + ArcNotificationManager* manager, |
| + message_center::MessageCenter* message_center, |
| + const arc::ArcNotificationData& data, |
| + const AccountId& profile_id) |
| + : manager_(manager), |
| + message_center_(message_center), |
| + profile_id_(profile_id), |
| + notification_key_(data.key), |
| + notification_id_(kNotificationIdPrefix + notification_key_), |
| + weak_ptr_factory_(this) { |
| + // This must be initialized after ArcBridgeService. |
|
hidehiko
2015/12/17 07:47:51
This comment looks stale...?
Or, maybe taking ArcN
yoshiki
2015/12/17 19:15:14
It was slate. Removed.
|
| +} |
| + |
| +void ArcNotificationItem::UpdateWithArcNotificationData( |
| + const arc::ArcNotificationData& data) { |
| + DCHECK(notification_key_ == data.key); |
| + |
| + // Stores the latest data to the |newer_data_| property and returns, if the |
| + // previous decode is still in progress. |
| + if (notification_) { |
|
elijahtaylor1
2015/12/16 02:34:37
I'm glad there's a comment here, but you could be
yoshiki
2015/12/17 19:15:13
Done.
|
| + newer_data_ = data.Clone(); |
|
hidehiko
2015/12/17 07:47:51
This will keep only newest data here, and (intenti
yoshiki
2015/12/17 19:15:13
Done.
|
| + return; |
| + } |
| + |
| + message_center::RichNotificationData rich_data; |
| + message_center::NotificationType type; |
| + switch (data.type) { |
| + case arc::ARC_NOTIFICATION_TYPE_BASIC: |
| + type = message_center::NOTIFICATION_TYPE_SIMPLE; |
| + break; |
| + case arc::ARC_NOTIFICATION_TYPE_IMAGE: |
| + // TODO(yoshiki): Implement this types. |
| + type = message_center::NOTIFICATION_TYPE_SIMPLE; |
| + break; |
| + case arc::ARC_NOTIFICATION_TYPE_PROGRESS: |
| + type = message_center::NOTIFICATION_TYPE_PROGRESS; |
| + rich_data.timestamp = base::Time::UnixEpoch() + |
| + base::TimeDelta::FromMilliseconds(data.time); |
| + rich_data.progress = std::max( |
| + 0, std::min(100, static_cast<int>(std::round( |
| + static_cast<float>(data.progress_current) / |
| + data.progress_max * 100)))); |
| + break; |
| + } |
| + |
| + message_center::NotifierId notifier_id( |
|
elijahtaylor1
2015/12/16 02:34:37
I don't have any idea what this is/does, can you a
yoshiki
2015/12/17 19:15:13
Done.
|
| + message_center::NotifierId::SYSTEM_COMPONENT, notification_id_); |
| + notifier_id.profile_id = profile_id_.GetUserEmail(); |
| + |
| + DCHECK(!data.title.is_null()); |
| + DCHECK(!data.message.is_null()); |
| + notification_.reset(new message_center::Notification( |
| + type, notification_id_, base::UTF8ToUTF16(data.title.get()), |
| + base::UTF8ToUTF16(data.message.get()), |
| + gfx::Image(), // Will be overriden by decoded image. |
| + base::UTF8ToUTF16("arc"), // display source |
| + GURL(), // origin url |
|
elijahtaylor1
2015/12/16 02:34:37
can you state here why empty is ok?
yoshiki
2015/12/17 19:15:14
Done.
|
| + notifier_id, rich_data, |
| + new ArcNotificationDelegate(weak_ptr_factory_.GetWeakPtr()))); |
| + |
| + DCHECK(!data.icon_data.is_null()); |
| + if (data.icon_data.size() == 0) { |
| + OnImageDecoded(SkBitmap()); // Passes an empty bitmap. |
| + return; |
| + } |
| + |
| + std::string icon_data_str(data.icon_data.storage().begin(), |
| + data.icon_data.storage().end()); // copy |
| + // TODO(yoshiki): Remove decoding by passing a bitmap directly from Android. |
|
hidehiko
2015/12/17 07:47:51
Thank you for offline chat.
I thought, the simple
yoshiki
2015/12/17 19:15:13
Correct, we'll be able to omit the async task from
|
| + base::PostTaskAndReplyWithResult( |
| + content::BrowserThread::GetBlockingPool(), |
| + FROM_HERE, |
| + base::Bind(&DecodeImage, data.icon_data.storage()), |
| + base::Bind(&ArcNotificationItem::OnImageDecoded, |
| + weak_ptr_factory_.GetWeakPtr())); |
| +} |
| + |
| +ArcNotificationItem::~ArcNotificationItem() {} |
| + |
| +void ArcNotificationItem::OnClosedFromAndroid() { |
| + message_center_->RemoveNotification(notification_id_, true /* by_user */); |
| +} |
| + |
| +void ArcNotificationItem::Close(bool by_user) { |
| + manager_->SendNotificationRemovedFromChrome(notification_key_); |
| +} |
| + |
| +void ArcNotificationItem::Click() { |
| + manager_->SendNotificationClickedOnChrome(notification_key_); |
| +} |
| + |
| +void ArcNotificationItem::OnImageDecoded(const SkBitmap& bitmap) { |
| + gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap); |
| + notification_->set_icon(image); |
| + |
| + DCHECK(notification_); |
| + message_center_->AddNotification(notification_.Pass()); |
|
hidehiko
2015/12/17 07:47:51
Maybe: std::move(notification_) ?
yoshiki
2015/12/17 19:15:13
Done.
|
| + DCHECK(!notification_); // |notification_| becomes null. |
|
hidehiko
2015/12/17 07:47:51
nit: To be honest, this is redundant.
yoshiki
2015/12/17 19:15:13
Done.
|
| + |
| + if (newer_data_) { |
|
hidehiko
2015/12/17 07:47:51
Could you add brief comment what this is for?
yoshiki
2015/12/17 19:15:13
Done.
|
| + arc::ArcNotificationDataPtr data(std::move(newer_data_)); |
| + DCHECK(!newer_data_); // |newer_data_| becomes null. |
| + UpdateWithArcNotificationData(*data); |
| + } |
| +} |
| + |
| +} // namespace arc |