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

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

Powered by Google App Engine
This is Rietveld 408576698