Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(960)

Side by Side Diff: ui/arc/notification/arc_notification_item.cc

Issue 1477733002: Add ArcNotificationManager for new ARC notification (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Sync dependencies Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "ui/arc/notification/arc_notification_item.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/strings/string16.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/task_runner.h"
13 #include "base/task_runner_util.h"
14 #include "base/threading/worker_pool.h"
15 #include "ui/gfx/codec/png_codec.h"
16 #include "ui/gfx/geometry/size.h"
17 #include "ui/gfx/image/image.h"
18 #include "ui/message_center/message_center_style.h"
19 #include "ui/message_center/notification.h"
20 #include "ui/message_center/notification_types.h"
21 #include "ui/message_center/notifier_settings.h"
22
23 namespace arc {
24
25 namespace {
26
27 static const char kNotifierId[] = "ARC_NOTIFICATION";
28
29 static const char kNotificationIdPrefix[] = "ARC_NOTIFICATION_";
30
31 SkBitmap DecodeImage(const std::vector<uint8_t>& data) {
32 DCHECK(base::WorkerPool::RunsTasksOnCurrentThread());
33 DCHECK(!data.empty()); // empty string should be handled in caller.
34
35 // We may decode an image in the browser process since it has been generated
36 // in NotificationListerService in Android and should be safe.
37 SkBitmap bitmap;
38 gfx::PNGCodec::Decode(&data[0], data.size(), &bitmap);
39 return bitmap;
40 }
41
42 class ArcNotificationDelegate : public message_center::NotificationDelegate {
43 public:
44 explicit ArcNotificationDelegate(base::WeakPtr<ArcNotificationItem> item)
45 : item_(item) {}
46
47 void Close(bool by_user) override {
48 if (item_)
49 item_->Close(by_user);
50 }
51
52 // Indicates all notifications have a click handler. This changes the mouse
53 // cursor on hover.
54 // TODO(yoshiki): Return the correct value according to the content intent
55 // and the flags.
56 bool HasClickedListener() override { return true; }
57
58 void Click() override {
59 if (item_)
60 item_->Click();
61 }
62
63 private:
64 // The destructor is private since this class is ref-counted.
65 ~ArcNotificationDelegate() override {}
66
67 base::WeakPtr<ArcNotificationItem> item_;
68
69 DISALLOW_COPY_AND_ASSIGN(ArcNotificationDelegate);
70 };
71
72 } // anonymous namespace
73
74 ArcNotificationItem::ArcNotificationItem(
75 ArcNotificationManager* manager,
76 message_center::MessageCenter* message_center,
77 const std::string& notification_key,
78 const AccountId& profile_id)
79 : manager_(manager),
80 message_center_(message_center),
81 profile_id_(profile_id),
82 notification_key_(notification_key),
83 notification_id_(kNotificationIdPrefix + notification_key_),
84 weak_ptr_factory_(this) {}
85
86 void ArcNotificationItem::UpdateWithArcNotificationData(
87 const ArcNotificationData& data) {
88 DCHECK(thread_checker_.CalledOnValidThread());
89 DCHECK(notification_key_ == data.key);
90
91 // Check if a decode task is on-going or not. If |notification_| is non-null,
92 // a decode task is on-going asynchronously. Otherwise, there is no task.
93 // TODO(yoshiki): Refactor and remove this check by omitting image decoding
94 // from here.
95 if (notification_) {
96 // Store the latest data to the |newer_data_| property and returns, if the
97 // previous decode is still in progress.
98 // If old |newer_data_| has been stored, discard the old one.
99 newer_data_ = data.Clone();
100 return;
101 }
102
103 message_center::RichNotificationData rich_data;
104 message_center::NotificationType type;
105
106 switch (data.type) {
107 case ARC_NOTIFICATION_TYPE_BASIC:
108 type = message_center::NOTIFICATION_TYPE_SIMPLE;
109 break;
110 case ARC_NOTIFICATION_TYPE_IMAGE:
111 // TODO(yoshiki): Implement this types.
112 type = message_center::NOTIFICATION_TYPE_SIMPLE;
113 LOG(ERROR) << "Unsupported notification type: image";
114 break;
115 case ARC_NOTIFICATION_TYPE_PROGRESS:
116 type = message_center::NOTIFICATION_TYPE_PROGRESS;
117 rich_data.timestamp = base::Time::UnixEpoch() +
118 base::TimeDelta::FromMilliseconds(data.time);
119 rich_data.progress = std::max(
120 0, std::min(100, static_cast<int>(std::round(
121 static_cast<float>(data.progress_current) /
122 data.progress_max * 100))));
123 break;
124 }
125 DCHECK(0 <= data.type && data.type <= ARC_NOTIFICATION_TYPE_MAX)
126 << "Unsupported notification type: " << data.type;
127
128 // The identifier of the notifier, which is used to distinguish the notifiers
129 // in the message center.
130 message_center::NotifierId notifier_id(
131 message_center::NotifierId::SYSTEM_COMPONENT, kNotifierId);
132 notifier_id.profile_id = profile_id_.GetUserEmail();
133
134 DCHECK(!data.title.is_null());
135 DCHECK(!data.message.is_null());
136 notification_.reset(new message_center::Notification(
137 type, notification_id_, base::UTF8ToUTF16(data.title.get()),
138 base::UTF8ToUTF16(data.message.get()),
139 gfx::Image(), // icon image: Will be overriden later.
140 base::UTF8ToUTF16("arc"), // display source
141 GURL(), // empty origin url, for system component
142 notifier_id, rich_data,
143 new ArcNotificationDelegate(weak_ptr_factory_.GetWeakPtr())));
144
145 DCHECK(!data.icon_data.is_null());
146 if (data.icon_data.size() == 0) {
147 OnImageDecoded(SkBitmap()); // Pass an empty bitmap.
148 return;
149 }
150
151 // TODO(yoshiki): Remove decoding by passing a bitmap directly from Android.
152 base::PostTaskAndReplyWithResult(
153 base::WorkerPool::GetTaskRunner(true).get(), FROM_HERE,
154 base::Bind(&DecodeImage, data.icon_data.storage()),
155 base::Bind(&ArcNotificationItem::OnImageDecoded,
156 weak_ptr_factory_.GetWeakPtr()));
157 }
158
159 ArcNotificationItem::~ArcNotificationItem() {}
160
161 void ArcNotificationItem::OnClosedFromAndroid() {
162 being_removed_by_manager_ = true; // Closing is initiated by the manager.
163 message_center_->RemoveNotification(notification_id_, true /* by_user */);
164 }
165
166 void ArcNotificationItem::Close(bool by_user) {
167 if (being_removed_by_manager_) {
168 // Closing is caused by the manager, so we don't need to nofify a close
169 // event to the manager.
170 return;
171 }
172
173 // Do not touch its any members afterwards, because this instance will be
174 // destroyed in the following call
175 manager_->SendNotificationRemovedFromChrome(notification_key_);
176 }
177
178 void ArcNotificationItem::Click() {
179 manager_->SendNotificationClickedOnChrome(notification_key_);
180 }
181
182 void ArcNotificationItem::OnImageDecoded(const SkBitmap& bitmap) {
183 DCHECK(thread_checker_.CalledOnValidThread());
184
185 gfx::Image image = gfx::Image::CreateFrom1xBitmap(bitmap);
186 notification_->set_icon(image);
187
188 DCHECK(notification_);
189 message_center_->AddNotification(std::move(notification_));
190
191 if (newer_data_) {
192 // There is the newer data, so updates again.
193 ArcNotificationDataPtr data(std::move(newer_data_));
194 UpdateWithArcNotificationData(*data);
195 }
196 }
197
198 } // namespace arc
OLDNEW
« no previous file with comments | « ui/arc/notification/arc_notification_item.h ('k') | ui/arc/notification/arc_notification_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698