1 // Copyright (c) 2011 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 "chrome/browser/chromeos/notifications/balloon_collection_impl.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "chrome/browser/chromeos/notifications/balloon_view.h"
11 #include "chrome/browser/chromeos/notifications/notification_panel.h"
12 #include "chrome/browser/notifications/balloon.h"
13 #include "chrome/browser/notifications/notification.h"
14 #include "chrome/browser/ui/browser_list.h"
15 #include "chrome/browser/ui/window_sizer.h"
16 #include "content/common/notification_service.h"
17 #include "ui/gfx/rect.h"
18 #include "ui/gfx/size.h"
19
20 namespace {
21
22 // Margin from the edge of the work area
23 const int kVerticalEdgeMargin = 5;
24 const int kHorizontalEdgeMargin = 5;
25
26 } // namespace
27
28 namespace chromeos {
29
BalloonCollectionImpl()30 BalloonCollectionImpl::BalloonCollectionImpl()
31 : notification_ui_(new NotificationPanel()) {
32 registrar_.Add(this, NotificationType::BROWSER_CLOSED,
33 NotificationService::AllSources());
34 }
35
~BalloonCollectionImpl()36 BalloonCollectionImpl::~BalloonCollectionImpl() {
37 Shutdown();
38 }
39
Add(const Notification & notification,Profile * profile)40 void BalloonCollectionImpl::Add(const Notification& notification,
41 Profile* profile) {
42 Balloon* new_balloon = MakeBalloon(notification, profile);
43 base_.Add(new_balloon);
44 new_balloon->Show();
45 notification_ui_->Add(new_balloon);
46
47 // There may be no listener in a unit test.
48 if (space_change_listener_)
49 space_change_listener_->OnBalloonSpaceChanged();
50 }
51
AddWebUIMessageCallback(const Notification & notification,const std::string & message,MessageCallback * callback)52 bool BalloonCollectionImpl::AddWebUIMessageCallback(
53 const Notification& notification,
54 const std::string& message,
55 MessageCallback* callback) {
56 Balloon* balloon = FindBalloon(notification);
57 if (!balloon) {
58 delete callback;
59 return false;
60 }
61 BalloonViewHost* host =
62 static_cast<BalloonViewHost*>(balloon->view()->GetHost());
63 return host->AddWebUIMessageCallback(message, callback);
64 }
65
AddSystemNotification(const Notification & notification,Profile * profile,bool sticky,bool control)66 void BalloonCollectionImpl::AddSystemNotification(
67 const Notification& notification,
68 Profile* profile,
69 bool sticky,
70 bool control) {
71
72 Balloon* new_balloon = new Balloon(notification, profile, this);
73 new_balloon->set_view(
74 new chromeos::BalloonViewImpl(sticky, control, true));
75 base_.Add(new_balloon);
76 new_balloon->Show();
77 notification_ui_->Add(new_balloon);
78
79 // There may be no listener in a unit test.
80 if (space_change_listener_)
81 space_change_listener_->OnBalloonSpaceChanged();
82 }
83
UpdateNotification(const Notification & notification)84 bool BalloonCollectionImpl::UpdateNotification(
85 const Notification& notification) {
86 Balloon* balloon = FindBalloon(notification);
87 if (!balloon)
88 return false;
89 balloon->Update(notification);
90 notification_ui_->Update(balloon);
91 return true;
92 }
93
UpdateAndShowNotification(const Notification & notification)94 bool BalloonCollectionImpl::UpdateAndShowNotification(
95 const Notification& notification) {
96 Balloon* balloon = FindBalloon(notification);
97 if (!balloon)
98 return false;
99 balloon->Update(notification);
100 bool updated = notification_ui_->Update(balloon);
101 DCHECK(updated);
102 notification_ui_->Show(balloon);
103 return true;
104 }
105
RemoveById(const std::string & id)106 bool BalloonCollectionImpl::RemoveById(const std::string& id) {
107 return base_.CloseById(id);
108 }
109
RemoveBySourceOrigin(const GURL & origin)110 bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) {
111 return base_.CloseAllBySourceOrigin(origin);
112 }
113
RemoveAll()114 void BalloonCollectionImpl::RemoveAll() {
115 base_.CloseAll();
116 }
117
HasSpace() const118 bool BalloonCollectionImpl::HasSpace() const {
119 return true;
120 }
121
ResizeBalloon(Balloon * balloon,const gfx::Size & size)122 void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon,
123 const gfx::Size& size) {
124 notification_ui_->ResizeNotification(balloon, size);
125 }
126
OnBalloonClosed(Balloon * source)127 void BalloonCollectionImpl::OnBalloonClosed(Balloon* source) {
128 notification_ui_->Remove(source);
129 base_.Remove(source);
130
131 // There may be no listener in a unit test.
132 if (space_change_listener_)
133 space_change_listener_->OnBalloonSpaceChanged();
134 }
135
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)136 void BalloonCollectionImpl::Observe(NotificationType type,
137 const NotificationSource& source,
138 const NotificationDetails& details) {
139 DCHECK(type == NotificationType::BROWSER_CLOSED);
140 bool app_closing = *Details<bool>(details).ptr();
141 // When exiting, we need to shutdown all renderers in
142 // BalloonViewImpl before IO thread gets deleted in the
143 // BrowserProcessImpl's destructor. See http://crbug.com/40810
144 // for details.
145 if (app_closing)
146 RemoveAll();
147 }
148
Shutdown()149 void BalloonCollectionImpl::Shutdown() {
150 // We need to remove the panel first because deleting
151 // views that are not owned by parent will not remove
152 // themselves from the parent.
153 DVLOG(1) << "Shutting down notification UI";
154 notification_ui_.reset();
155 }
156
MakeBalloon(const Notification & notification,Profile * profile)157 Balloon* BalloonCollectionImpl::MakeBalloon(const Notification& notification,
158 Profile* profile) {
159 Balloon* new_balloon = new Balloon(notification, profile, this);
160 new_balloon->set_view(new chromeos::BalloonViewImpl(false, true, false));
161 return new_balloon;
162 }
163
164 } // namespace chromeos
165
166 // static
Create()167 BalloonCollection* BalloonCollection::Create() {
168 return new chromeos::BalloonCollectionImpl();
169 }
170