OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/download/notification/download_notification_item.h" | 5 #include "chrome/browser/download/notification/download_notification_item.h" |
6 | 6 |
7 #include "base/strings/string_number_conversions.h" | 7 #include "base/strings/string_number_conversions.h" |
8 #include "chrome/browser/browser_process.h" | |
8 #include "chrome/browser/download/download_crx_util.h" | 9 #include "chrome/browser/download/download_crx_util.h" |
9 #include "chrome/browser/download/download_item_model.h" | 10 #include "chrome/browser/download/download_item_model.h" |
11 #include "chrome/browser/notifications/notification.h" | |
12 #include "chrome/browser/notifications/notification_ui_manager.h" | |
10 #include "chrome/grit/chromium_strings.h" | 13 #include "chrome/grit/chromium_strings.h" |
11 #include "chrome/grit/generated_resources.h" | 14 #include "chrome/grit/generated_resources.h" |
12 #include "content/public/browser/browser_context.h" | 15 #include "content/public/browser/browser_context.h" |
13 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
14 #include "content/public/browser/download_item.h" | 17 #include "content/public/browser/download_item.h" |
15 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
16 #include "grit/theme_resources.h" | 19 #include "grit/theme_resources.h" |
17 #include "ui/base/l10n/l10n_util.h" | 20 #include "ui/base/l10n/l10n_util.h" |
18 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
19 #include "ui/message_center/message_center.h" | 22 #include "ui/message_center/message_center.h" |
20 #include "ui/message_center/notification.h" | |
21 #include "ui/message_center/notification_delegate.h" | |
22 | |
23 using message_center::Notification; | |
24 | 23 |
25 namespace { | 24 namespace { |
26 | 25 |
27 const char kDownloadNotificationNotifierId[] = | 26 const char kDownloadNotificationNotifierId[] = |
28 "chrome://settings/display/notification/id-notifier"; | 27 "chrome://downloads/notification/id-notifier"; |
29 const char kDownloadNotificationIdBase[] = | |
30 "chrome://settings/display/notification/id-"; | |
31 | 28 |
32 } // anonymous namespace | 29 } // anonymous namespace |
33 | 30 |
31 // static | |
32 const char DownloadNotificationItem::kDownloadNotificationOrigin[] = | |
33 "chrome://downloads"; | |
34 | |
35 // static | |
36 StubNotificationUIManager* | |
37 DownloadNotificationItem::stub_notification_ui_manager_for_testing_ = | |
38 nullptr; | |
39 | |
34 DownloadNotificationItem::NotificationWatcher::NotificationWatcher( | 40 DownloadNotificationItem::NotificationWatcher::NotificationWatcher( |
35 DownloadNotificationItem* item) | 41 DownloadNotificationItem* item) |
36 : item_(item) { | 42 : item_(item) { |
37 } | 43 } |
38 | 44 |
39 DownloadNotificationItem::NotificationWatcher::~NotificationWatcher() { | 45 DownloadNotificationItem::NotificationWatcher::~NotificationWatcher() { |
40 } | 46 } |
41 | 47 |
42 void DownloadNotificationItem::NotificationWatcher::Close(bool by_user) { | 48 void DownloadNotificationItem::NotificationWatcher::Close(bool by_user) { |
43 item_->OnNotificationClose(by_user); | 49 item_->OnNotificationClose(by_user); |
44 } | 50 } |
45 | 51 |
46 void DownloadNotificationItem::NotificationWatcher::Click() { | 52 void DownloadNotificationItem::NotificationWatcher::Click() { |
47 item_->OnNotificationClick(); | 53 item_->OnNotificationClick(); |
48 } | 54 } |
49 | 55 |
50 bool DownloadNotificationItem::NotificationWatcher::HasClickedListener() { | 56 bool DownloadNotificationItem::NotificationWatcher::HasClickedListener() { |
51 return true; | 57 return true; |
52 } | 58 } |
53 | 59 |
54 void DownloadNotificationItem::NotificationWatcher::ButtonClick( | 60 void DownloadNotificationItem::NotificationWatcher::ButtonClick( |
55 int button_index) { | 61 int button_index) { |
56 item_->OnNotificationButtonClick(button_index); | 62 item_->OnNotificationButtonClick(button_index); |
57 } | 63 } |
58 | 64 |
59 void DownloadNotificationItem::NotificationWatcher::OnNotificationRemoved( | 65 std::string DownloadNotificationItem::NotificationWatcher::id() const { |
60 const std::string& id, | 66 return base::UintToString(item_->item_->GetId()); |
61 bool by_user) { | |
62 if (id != item_->notification_->id()) | |
63 return; | |
64 item_->OnNotificationRemoved(by_user); | |
65 } | 67 } |
66 | 68 |
67 DownloadNotificationItem::DownloadNotificationItem(content::DownloadItem* item, | 69 DownloadNotificationItem::DownloadNotificationItem(content::DownloadItem* item, |
70 Profile* profile, | |
68 Delegate* delegate) | 71 Delegate* delegate) |
69 : openable_(false), | 72 : openable_(false), |
70 downloading_(false), | 73 downloading_(false), |
71 reshow_after_remove_(false), | |
72 image_resource_id_(0), | 74 image_resource_id_(0), |
75 profile_(profile), | |
73 watcher_(new NotificationWatcher(this)), | 76 watcher_(new NotificationWatcher(this)), |
74 item_(item), | 77 item_(item), |
75 delegate_(delegate) { | 78 delegate_(delegate) { |
76 item->AddObserver(this); | 79 item->AddObserver(this); |
77 | 80 |
78 message_center_ = message_center::MessageCenter::Get(); | |
79 message_center_->AddObserver(watcher_.get()); | |
80 | |
81 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 81 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
82 | 82 |
83 const base::string16 timeout_message = | |
84 l10n_util::GetStringUTF16(IDS_DOWNLOAD_STATUS_CRX_INSTALL_RUNNING); | |
85 const base::string16 message = | |
86 l10n_util::GetStringUTF16(IDS_PROMPT_MALICIOUS_DOWNLOAD_URL); | |
87 | |
88 std::string id(kDownloadNotificationIdBase); | |
89 id += base::UintToString(item_->GetId()); | |
90 | |
91 message_center::RichNotificationData data; | 83 message_center::RichNotificationData data; |
84 // Creates the notification instance. |title| and |body| will be overridden | |
85 // by UpdateNotificationData() below. | |
92 notification_.reset(new Notification( | 86 notification_.reset(new Notification( |
93 message_center::NOTIFICATION_TYPE_PROGRESS, id, message, timeout_message, | 87 message_center::NOTIFICATION_TYPE_PROGRESS, |
88 GURL(kDownloadNotificationOrigin), // origin_url | |
89 base::string16(), // title | |
90 base::string16(), // body | |
94 bundle.GetImageNamed(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING), | 91 bundle.GetImageNamed(IDR_DOWNLOAD_NOTIFICATION_DOWNLOADING), |
95 base::string16() /* display_source */, | |
96 message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, | 92 message_center::NotifierId(message_center::NotifierId::SYSTEM_COMPONENT, |
97 kDownloadNotificationNotifierId), | 93 kDownloadNotificationNotifierId), |
94 base::string16(), // display_source | |
95 base::UintToString(item_->GetId()), // tag | |
98 data, watcher_.get())); | 96 data, watcher_.get())); |
99 | 97 |
100 notification_->set_progress(0); | 98 notification_->set_progress(0); |
101 notification_->set_never_timeout(false); | 99 notification_->set_never_timeout(false); |
102 | 100 |
103 UpdateNotificationData(); | 101 UpdateNotificationData(); |
104 | 102 |
105 scoped_ptr<Notification> notification(new Notification(*notification_)); | 103 notification_ui_manager()->Add(*notification_, profile); |
106 message_center_->AddNotification(notification.Pass()); | |
107 } | 104 } |
108 | 105 |
109 DownloadNotificationItem::~DownloadNotificationItem() { | 106 DownloadNotificationItem::~DownloadNotificationItem() { |
110 if (item_) | 107 if (item_) |
111 item_->RemoveObserver(this); | 108 item_->RemoveObserver(this); |
112 message_center_->RemoveObserver(watcher_.get()); | |
113 } | 109 } |
114 | 110 |
115 void DownloadNotificationItem::OnNotificationClose(bool by_user) { | 111 void DownloadNotificationItem::OnNotificationClose(bool by_user) { |
116 if (item_->GetState() != content::DownloadItem::IN_PROGRESS) { | 112 bool reshow_after_remove = false; |
117 reshow_after_remove_ = false; | 113 if (item_->GetState() == content::DownloadItem::IN_PROGRESS) { |
118 } else { | 114 const Notification* current_notification = |
119 bool popup = false; | 115 notification_ui_manager()->FindById( |
116 watcher_->id(), NotificationUIManager::GetProfileID(profile_)); | |
120 | 117 |
121 const std::string id = notification_->id(); | 118 if (!current_notification) { |
122 message_center::NotificationList::PopupNotifications popups = | 119 NOTREACHED(); |
123 message_center_->GetPopupNotifications(); | 120 return; |
124 for (auto it = popups.begin(); it != popups.end(); it++) { | |
125 if ((*it)->id() == id) { | |
126 popup = true; | |
127 break; | |
128 } | |
129 } | 121 } |
130 | 122 |
131 // Reshows the notification in the notification center, if the download is | 123 // Reshows the notification in the notification center, if the download is |
132 // in progress and the notifitation being closed is a popup. | 124 // in progress and the notifitation being closed is a popup. |
133 reshow_after_remove_ = popup; | 125 reshow_after_remove = !current_notification->shown_as_popup(); |
Jun Mukai
2015/04/01 18:02:11
You don't have to check through this. Notificatio
yoshiki
2015/04/06 02:22:18
Actually, I'd like to check if the notification is
Jun Mukai
2015/04/06 08:20:06
What will happen if the user explicitly toggles th
| |
134 } | 126 } |
135 | 127 |
136 // OnNotificationRemoved() will be called soon, just after the notification | 128 if (!reshow_after_remove) { |
137 // is removed. | |
138 } | |
139 | |
140 void DownloadNotificationItem::OnNotificationRemoved(bool by_user) { | |
141 if (reshow_after_remove_) { | |
142 // Sets the notification as read. | |
143 notification_->set_is_read(true); | |
144 | |
145 // Reshows the notification. | |
146 scoped_ptr<Notification> notification(new Notification(*notification_)); | |
147 message_center_->AddNotification(notification.Pass()); | |
148 // Show the reshown notification as a non-popup. | |
149 message_center_->MarkSinglePopupAsShown(notification_->id(), true); | |
150 | |
151 reshow_after_remove_ = false; | |
152 } else { | |
153 // Cancels the download. | 129 // Cancels the download. |
154 item_->Cancel(by_user); | 130 item_->Cancel(by_user); |
155 delegate_->OnDownloadRemoved(this); | 131 delegate_->OnDownloadRemoved(this); |
132 } else { | |
133 notification_->set_shown_as_popup(true); | |
134 content::BrowserThread::PostTask( | |
135 content::BrowserThread::UI, FROM_HERE, | |
136 base::Bind(&DownloadNotificationItem::ShowNotificationAgain, | |
137 AsWeakPtr())); | |
156 } | 138 } |
157 } | 139 } |
158 | 140 |
141 void DownloadNotificationItem::ShowNotificationAgain() { | |
142 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
143 | |
144 // Do nothing if the notification already exists. | |
145 const Notification* current_notification = | |
146 notification_ui_manager()->FindById( | |
147 watcher_->id(), NotificationUIManager::GetProfileID(profile_)); | |
148 if (current_notification) | |
149 return; | |
150 | |
151 notification_ui_manager()->Add(*notification_, profile_); | |
152 } | |
153 | |
159 void DownloadNotificationItem::OnNotificationClick() { | 154 void DownloadNotificationItem::OnNotificationClick() { |
160 if (openable_) { | 155 if (openable_) { |
161 if (item_->IsDone()) | 156 if (item_->IsDone()) |
162 item_->OpenDownload(); | 157 item_->OpenDownload(); |
163 else | 158 else |
164 item_->SetOpenWhenComplete(!item_->GetOpenWhenComplete()); // Toggle | 159 item_->SetOpenWhenComplete(!item_->GetOpenWhenComplete()); // Toggle |
165 } | 160 } |
166 | 161 |
167 if (item_->IsDone()) | 162 if (item_->IsDone()) { |
168 message_center_->RemoveNotification(notification_->id(), true); | 163 notification_ui_manager()->CancelById( |
164 watcher_->id(), NotificationUIManager::GetProfileID(profile_)); | |
165 } | |
169 } | 166 } |
170 | 167 |
171 void DownloadNotificationItem::OnNotificationButtonClick(int button_index) { | 168 void DownloadNotificationItem::OnNotificationButtonClick(int button_index) { |
172 if (button_index < 0 || | 169 if (button_index < 0 || |
173 static_cast<size_t>(button_index) >= button_actions_->size()) { | 170 static_cast<size_t>(button_index) >= button_actions_->size()) { |
174 // Out of boundary. | 171 // Out of boundary. |
175 NOTREACHED(); | 172 NOTREACHED(); |
176 return; | 173 return; |
177 } | 174 } |
178 | 175 |
179 DownloadCommands::Command command = button_actions_->at(button_index); | 176 DownloadCommands::Command command = button_actions_->at(button_index); |
180 DownloadCommands(item_).ExecuteCommand(command); | 177 DownloadCommands(item_).ExecuteCommand(command); |
181 } | 178 } |
182 | 179 |
183 // DownloadItem::Observer methods | 180 // DownloadItem::Observer methods |
184 void DownloadNotificationItem::OnDownloadUpdated(content::DownloadItem* item) { | 181 void DownloadNotificationItem::OnDownloadUpdated(content::DownloadItem* item) { |
185 DCHECK_EQ(item, item_); | 182 DCHECK_EQ(item, item_); |
186 | 183 |
187 UpdateNotificationData(); | 184 UpdateNotificationData(); |
188 | 185 |
189 // Updates notification. | 186 // Updates notification. |
190 scoped_ptr<Notification> notification(new Notification(*notification_)); | 187 notification_ui_manager()->Update(*notification_, profile_); |
191 std::string id = notification->id(); | |
192 message_center_->UpdateNotification(id, notification.Pass()); | |
193 } | 188 } |
194 | 189 |
195 void DownloadNotificationItem::UpdateNotificationData() { | 190 void DownloadNotificationItem::UpdateNotificationData() { |
196 DownloadItemModel model(item_); | 191 DownloadItemModel model(item_); |
197 DownloadCommands command(item_); | 192 DownloadCommands command(item_); |
198 | 193 |
199 if (!downloading_) { | 194 if (!downloading_) { |
200 if (item_->GetState() == content::DownloadItem::IN_PROGRESS) { | 195 if (item_->GetState() == content::DownloadItem::IN_PROGRESS) { |
201 delegate_->OnDownloadStarted(this); | 196 delegate_->OnDownloadStarted(this); |
202 downloading_ = true; | 197 downloading_ = true; |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 } | 279 } |
285 | 280 |
286 void DownloadNotificationItem::OnDownloadOpened(content::DownloadItem* item) { | 281 void DownloadNotificationItem::OnDownloadOpened(content::DownloadItem* item) { |
287 DCHECK_EQ(item, item_); | 282 DCHECK_EQ(item, item_); |
288 // Do nothing. | 283 // Do nothing. |
289 } | 284 } |
290 | 285 |
291 void DownloadNotificationItem::OnDownloadRemoved(content::DownloadItem* item) { | 286 void DownloadNotificationItem::OnDownloadRemoved(content::DownloadItem* item) { |
292 DCHECK_EQ(item, item_); | 287 DCHECK_EQ(item, item_); |
293 | 288 |
294 // Removing the notification causes calling both |OnNotificationClose()| and | 289 // Removing the notification causes calling |OnNotificationClose()|. |
295 // |OnNotificationRemoved()|. | 290 notification_ui_manager()->CancelById( |
296 message_center_->RemoveNotification(notification_->id(), false); | 291 watcher_->id(), NotificationUIManager::GetProfileID(profile_)); |
297 } | 292 } |
298 | 293 |
299 void DownloadNotificationItem::OnDownloadDestroyed( | 294 void DownloadNotificationItem::OnDownloadDestroyed( |
300 content::DownloadItem* item) { | 295 content::DownloadItem* item) { |
301 DCHECK_EQ(item, item_); | 296 DCHECK_EQ(item, item_); |
302 | 297 |
303 item_ = nullptr; | 298 item_ = nullptr; |
304 } | 299 } |
305 | 300 |
306 void DownloadNotificationItem::SetNotificationImage(int resource_id) { | 301 void DownloadNotificationItem::SetNotificationImage(int resource_id) { |
307 if (image_resource_id_ == resource_id) | 302 if (image_resource_id_ == resource_id) |
308 return; | 303 return; |
309 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); | 304 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); |
310 image_resource_id_ = resource_id; | 305 image_resource_id_ = resource_id; |
311 notification_->set_icon(bundle.GetImageNamed(image_resource_id_)); | 306 notification_->set_icon(bundle.GetImageNamed(image_resource_id_)); |
312 } | 307 } |
313 | 308 |
309 NotificationUIManager* DownloadNotificationItem::notification_ui_manager() | |
310 const { | |
311 if (stub_notification_ui_manager_for_testing_) { | |
312 return stub_notification_ui_manager_for_testing_; | |
313 } | |
314 return g_browser_process->notification_ui_manager(); | |
315 } | |
316 | |
314 scoped_ptr<std::vector<DownloadCommands::Command>> | 317 scoped_ptr<std::vector<DownloadCommands::Command>> |
315 DownloadNotificationItem::GetPossibleActions() const { | 318 DownloadNotificationItem::GetPossibleActions() const { |
316 scoped_ptr<std::vector<DownloadCommands::Command>> actions( | 319 scoped_ptr<std::vector<DownloadCommands::Command>> actions( |
317 new std::vector<DownloadCommands::Command>()); | 320 new std::vector<DownloadCommands::Command>()); |
318 | 321 |
319 if (item_->IsDangerous()) { | 322 if (item_->IsDangerous()) { |
320 actions->push_back(DownloadCommands::DISCARD); | 323 actions->push_back(DownloadCommands::DISCARD); |
321 actions->push_back(DownloadCommands::KEEP); | 324 actions->push_back(DownloadCommands::KEEP); |
322 return actions.Pass(); | 325 return actions.Pass(); |
323 } | 326 } |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
448 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: | 451 case content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS: |
449 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: | 452 case content::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT: |
450 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: | 453 case content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED: |
451 case content::DOWNLOAD_DANGER_TYPE_MAX: { | 454 case content::DOWNLOAD_DANGER_TYPE_MAX: { |
452 break; | 455 break; |
453 } | 456 } |
454 } | 457 } |
455 NOTREACHED(); | 458 NOTREACHED(); |
456 return base::string16(); | 459 return base::string16(); |
457 } | 460 } |
OLD | NEW |