| Index: ui/arc/notification/arc_notification_item.cc
|
| diff --git a/ui/arc/notification/arc_notification_item.cc b/ui/arc/notification/arc_notification_item.cc
|
| deleted file mode 100644
|
| index 2c4cac44b5317b355a1796d20a505bae1f2a5dd9..0000000000000000000000000000000000000000
|
| --- a/ui/arc/notification/arc_notification_item.cc
|
| +++ /dev/null
|
| @@ -1,349 +0,0 @@
|
| -// Copyright 2016 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 "ui/arc/notification/arc_notification_item.h"
|
| -
|
| -#include <algorithm>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/memory/ptr_util.h"
|
| -#include "base/strings/string16.h"
|
| -#include "base/strings/utf_string_conversions.h"
|
| -#include "base/task_runner.h"
|
| -#include "base/task_scheduler/post_task.h"
|
| -#include "third_party/skia/include/core/SkCanvas.h"
|
| -#include "third_party/skia/include/core/SkPaint.h"
|
| -#include "ui/gfx/codec/png_codec.h"
|
| -#include "ui/gfx/geometry/size.h"
|
| -#include "ui/gfx/image/image.h"
|
| -#include "ui/gfx/text_elider.h"
|
| -#include "ui/message_center/message_center_style.h"
|
| -#include "ui/message_center/notification.h"
|
| -#include "ui/message_center/notification_types.h"
|
| -#include "ui/message_center/notifier_settings.h"
|
| -
|
| -namespace arc {
|
| -
|
| -namespace {
|
| -
|
| -constexpr char kNotifierId[] = "ARC_NOTIFICATION";
|
| -constexpr char kNotificationIdPrefix[] = "ARC_NOTIFICATION_";
|
| -
|
| -SkBitmap DecodeImage(const std::vector<uint8_t>& data) {
|
| - 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 NotificationListerService in Android and should be safe.
|
| - SkBitmap bitmap;
|
| - gfx::PNGCodec::Decode(&data[0], data.size(), &bitmap);
|
| - return bitmap;
|
| -}
|
| -
|
| -// Crops the image to proper size for Chrome Notification. It accepts only
|
| -// specified aspect ratio. Otherwise, it might be letterboxed.
|
| -SkBitmap CropImage(const SkBitmap& original_bitmap) {
|
| - DCHECK_NE(0, original_bitmap.width());
|
| - DCHECK_NE(0, original_bitmap.height());
|
| -
|
| - const SkSize container_size = SkSize::Make(
|
| - message_center::kNotificationPreferredImageWidth,
|
| - message_center::kNotificationPreferredImageHeight);
|
| - const float container_aspect_ratio =
|
| - static_cast<float>(message_center::kNotificationPreferredImageWidth) /
|
| - message_center::kNotificationPreferredImageHeight;
|
| - const float image_aspect_ratio =
|
| - static_cast<float>(original_bitmap.width()) / original_bitmap.height();
|
| -
|
| - SkRect source_rect;
|
| - if (image_aspect_ratio > container_aspect_ratio) {
|
| - float width = original_bitmap.height() * container_aspect_ratio;
|
| - source_rect = SkRect::MakeXYWH((original_bitmap.width() - width) / 2,
|
| - 0,
|
| - width,
|
| - original_bitmap.height());
|
| - } else {
|
| - float height = original_bitmap.width() / container_aspect_ratio;
|
| - source_rect = SkRect::MakeXYWH(0,
|
| - (original_bitmap.height() - height) / 2,
|
| - original_bitmap.width(),
|
| - height);
|
| - }
|
| -
|
| - SkBitmap container_bitmap;
|
| - container_bitmap.allocN32Pixels(container_size.width(),
|
| - container_size.height());
|
| - SkPaint paint;
|
| - paint.setFilterQuality(kHigh_SkFilterQuality);
|
| - SkCanvas container_image(container_bitmap);
|
| - container_image.drawColor(message_center::kImageBackgroundColor);
|
| - container_image.drawBitmapRect(
|
| - original_bitmap, source_rect, SkRect::MakeSize(container_size), &paint);
|
| -
|
| - return container_bitmap;
|
| -}
|
| -
|
| -class ArcNotificationDelegate : public message_center::NotificationDelegate {
|
| - public:
|
| - explicit ArcNotificationDelegate(base::WeakPtr<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();
|
| - }
|
| -
|
| - void ButtonClick(int button_index) override {
|
| - if (item_)
|
| - item_->ButtonClick(button_index);
|
| - }
|
| -
|
| - private:
|
| - // The destructor is private since this class is ref-counted.
|
| - ~ArcNotificationDelegate() override {}
|
| -
|
| - base::WeakPtr<ArcNotificationItem> item_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(ArcNotificationDelegate);
|
| -};
|
| -
|
| -} // anonymous namespace
|
| -
|
| -ArcNotificationItem::ArcNotificationItem(
|
| - ArcNotificationManager* manager,
|
| - message_center::MessageCenter* message_center,
|
| - const std::string& notification_key,
|
| - const AccountId& profile_id)
|
| - : manager_(manager),
|
| - message_center_(message_center),
|
| - profile_id_(profile_id),
|
| - notification_key_(notification_key),
|
| - notification_id_(kNotificationIdPrefix + notification_key_),
|
| - weak_ptr_factory_(this) {}
|
| -
|
| -void ArcNotificationItem::UpdateWithArcNotificationData(
|
| - mojom::ArcNotificationDataPtr data) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - DCHECK(notification_key_ == data->key);
|
| -
|
| - // Check if a decode task is on-going or not. If |notification_| is non-null,
|
| - // a decode task is on-going asynchronously. Otherwise, there is no task and
|
| - // cache the latest data to the |newer_data_| property.
|
| - // TODO(yoshiki): Refactor and remove this check by omitting image decoding
|
| - // from here.
|
| - if (HasPendingNotification()) {
|
| - CacheArcNotificationData(std::move(data));
|
| - return;
|
| - }
|
| -
|
| - message_center::RichNotificationData rich_data;
|
| - message_center::NotificationType type;
|
| -
|
| - switch (data->type) {
|
| - case mojom::ArcNotificationType::BASIC:
|
| - type = message_center::NOTIFICATION_TYPE_BASE_FORMAT;
|
| - break;
|
| - case mojom::ArcNotificationType::LIST:
|
| - type = message_center::NOTIFICATION_TYPE_MULTIPLE;
|
| -
|
| - if (!data->texts.has_value())
|
| - break;
|
| -
|
| - for (size_t i = 0;
|
| - i < std::min(data->texts->size(),
|
| - message_center::kNotificationMaximumItems - 1);
|
| - i++) {
|
| - rich_data.items.emplace_back(base::string16(),
|
| - base::UTF8ToUTF16(data->texts->at(i)));
|
| - }
|
| -
|
| - if (data->texts->size() > message_center::kNotificationMaximumItems) {
|
| - // Show an elipsis as the 5th item if there are more than 5 items.
|
| - rich_data.items.emplace_back(base::string16(), gfx::kEllipsisUTF16);
|
| - } else if (data->texts->size() ==
|
| - message_center::kNotificationMaximumItems) {
|
| - // Show the 5th item if there are exact 5 items.
|
| - rich_data.items.emplace_back(
|
| - base::string16(),
|
| - base::UTF8ToUTF16(data->texts->at(data->texts->size() - 1)));
|
| - }
|
| - break;
|
| - case mojom::ArcNotificationType::IMAGE:
|
| - type = message_center::NOTIFICATION_TYPE_IMAGE;
|
| -
|
| - if (data->big_picture && !data->big_picture->isNull()) {
|
| - rich_data.image = gfx::Image::CreateFrom1xBitmap(
|
| - CropImage(*data->big_picture));
|
| - }
|
| - break;
|
| - case mojom::ArcNotificationType::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;
|
| - }
|
| - DCHECK(IsKnownEnumValue(data->type)) << "Unsupported notification type: "
|
| - << data->type;
|
| -
|
| - for (size_t i = 0; i < data->buttons.size(); i++) {
|
| - rich_data.buttons.emplace_back(
|
| - base::UTF8ToUTF16(data->buttons.at(i)->label));
|
| - }
|
| -
|
| - // If the client is old (version < 1), both |no_clear| and |ongoing_event|
|
| - // are false.
|
| - rich_data.pinned = (data->no_clear || data->ongoing_event);
|
| -
|
| - rich_data.priority = ConvertAndroidPriority(data->priority);
|
| - if (data->small_icon)
|
| - rich_data.small_image = gfx::Image::CreateFrom1xBitmap(*data->small_icon);
|
| -
|
| - // The identifier of the notifier, which is used to distinguish the notifiers
|
| - // in the message center.
|
| - message_center::NotifierId notifier_id(
|
| - message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId);
|
| - notifier_id.profile_id = profile_id_.GetUserEmail();
|
| -
|
| - SetNotification(base::MakeUnique<message_center::Notification>(
|
| - type, notification_id_, base::UTF8ToUTF16(data->title),
|
| - base::UTF8ToUTF16(data->message),
|
| - gfx::Image(), // icon image: Will be overriden later.
|
| - base::UTF8ToUTF16("arc"), // display source
|
| - GURL(), // empty origin url, for system component
|
| - notifier_id, rich_data,
|
| - new ArcNotificationDelegate(weak_ptr_factory_.GetWeakPtr())));
|
| -
|
| - if (data->icon_data.size() == 0) {
|
| - OnImageDecoded(SkBitmap()); // Pass an empty bitmap.
|
| - return;
|
| - }
|
| -
|
| - // TODO(yoshiki): Remove decoding by passing a bitmap directly from Android.
|
| - base::PostTaskWithTraitsAndReplyWithResult(
|
| - FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
| - base::Bind(&DecodeImage, data->icon_data),
|
| - base::Bind(&ArcNotificationItem::OnImageDecoded,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| -}
|
| -
|
| -ArcNotificationItem::~ArcNotificationItem() {}
|
| -
|
| -void ArcNotificationItem::OnClosedFromAndroid() {
|
| - being_removed_by_manager_ = true; // Closing is initiated by the manager.
|
| - message_center_->RemoveNotification(notification_id_, false /* by_user */);
|
| -}
|
| -
|
| -void ArcNotificationItem::Close(bool by_user) {
|
| - if (being_removed_by_manager_) {
|
| - // Closing is caused by the manager, so we don't need to nofify a close
|
| - // event to the manager.
|
| - return;
|
| - }
|
| -
|
| - // Do not touch its any members afterwards, because this instance will be
|
| - // destroyed in the following call
|
| - manager_->SendNotificationRemovedFromChrome(notification_key_);
|
| -}
|
| -
|
| -void ArcNotificationItem::Click() {
|
| - manager_->SendNotificationClickedOnChrome(notification_key_);
|
| -}
|
| -
|
| -void ArcNotificationItem::ButtonClick(int button_index) {
|
| - manager_->SendNotificationButtonClickedOnChrome(
|
| - notification_key_, button_index);
|
| -}
|
| -
|
| -void ArcNotificationItem::OpenSettings() {
|
| - manager_->OpenNotificationSettings(notification_key_);
|
| -}
|
| -
|
| -bool ArcNotificationItem::IsOpeningSettingsSupported() const {
|
| - return manager_->IsOpeningSettingsSupported();
|
| -}
|
| -
|
| -void ArcNotificationItem::ToggleExpansion() {
|
| - manager_->SendNotificationToggleExpansionOnChrome(notification_key_);
|
| -}
|
| -
|
| -// Converts from Android notification priority to Chrome notification priority.
|
| -// On Android, PRIORITY_DEFAULT does not pop up, so this maps PRIORITY_DEFAULT
|
| -// to Chrome's -1 to adapt that behavior. Also, this maps PRIORITY_LOW and _HIGH
|
| -// to -2 and 0 respectively to adjust the value with keeping the order among
|
| -// _LOW, _DEFAULT and _HIGH.
|
| -// static
|
| -// TODO(yoshiki): rewrite this conversion as typemap
|
| -int ArcNotificationItem::ConvertAndroidPriority(
|
| - mojom::ArcNotificationPriority android_priority) {
|
| - switch (android_priority) {
|
| - case mojom::ArcNotificationPriority::MIN:
|
| - case mojom::ArcNotificationPriority::LOW:
|
| - return message_center::MIN_PRIORITY;
|
| - case mojom::ArcNotificationPriority::DEFAULT:
|
| - return message_center::LOW_PRIORITY;
|
| - case mojom::ArcNotificationPriority::HIGH:
|
| - return message_center::DEFAULT_PRIORITY;
|
| - case mojom::ArcNotificationPriority::MAX:
|
| - return message_center::MAX_PRIORITY;
|
| -
|
| - // fall-through
|
| - default:
|
| - NOTREACHED() << "Invalid Priority: " << android_priority;
|
| - return message_center::DEFAULT_PRIORITY;
|
| - }
|
| -}
|
| -
|
| -bool ArcNotificationItem::HasPendingNotification() {
|
| - return (notification_ != nullptr);
|
| -}
|
| -
|
| -void ArcNotificationItem::CacheArcNotificationData(
|
| - mojom::ArcNotificationDataPtr data) {
|
| - // If old |newer_data_| has been stored, discard the old one.
|
| - newer_data_ = std::move(data);
|
| -}
|
| -
|
| -void ArcNotificationItem::SetNotification(
|
| - std::unique_ptr<message_center::Notification> notification) {
|
| - notification_ = std::move(notification);
|
| -}
|
| -
|
| -void ArcNotificationItem::AddToMessageCenter() {
|
| - DCHECK(notification_);
|
| - message_center_->AddNotification(std::move(notification_));
|
| -
|
| - if (newer_data_) {
|
| - // There is the newer data, so updates again.
|
| - UpdateWithArcNotificationData(std::move(newer_data_));
|
| - }
|
| -}
|
| -
|
| -bool ArcNotificationItem::CalledOnValidThread() const {
|
| - return thread_checker_.CalledOnValidThread();
|
| -}
|
| -
|
| -void ArcNotificationItem::OnImageDecoded(const SkBitmap& bitmap) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| -
|
| - gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap);
|
| - notification_->set_icon(image);
|
| - AddToMessageCenter();
|
| -}
|
| -
|
| -} // namespace arc
|
|
|