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 30 BalloonCollectionImpl::BalloonCollectionImpl() 31 : notification_ui_(new NotificationPanel()) { 32 registrar_.Add(this, NotificationType::BROWSER_CLOSED, 33 NotificationService::AllSources()); 34 } 35 36 BalloonCollectionImpl::~BalloonCollectionImpl() { 37 Shutdown(); 38 } 39 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 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 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 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 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 106 bool BalloonCollectionImpl::RemoveById(const std::string& id) { 107 return base_.CloseById(id); 108 } 109 110 bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) { 111 return base_.CloseAllBySourceOrigin(origin); 112 } 113 114 void BalloonCollectionImpl::RemoveAll() { 115 base_.CloseAll(); 116 } 117 118 bool BalloonCollectionImpl::HasSpace() const { 119 return true; 120 } 121 122 void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon, 123 const gfx::Size& size) { 124 notification_ui_->ResizeNotification(balloon, size); 125 } 126 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 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 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 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 167 BalloonCollection* BalloonCollection::Create() { 168 return new chromeos::BalloonCollectionImpl(); 169 } 170