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 20namespace { 21 22// Margin from the edge of the work area 23const int kVerticalEdgeMargin = 5; 24const int kHorizontalEdgeMargin = 5; 25 26} // namespace 27 28namespace chromeos { 29 30BalloonCollectionImpl::BalloonCollectionImpl() 31 : notification_ui_(new NotificationPanel()) { 32 registrar_.Add(this, NotificationType::BROWSER_CLOSED, 33 NotificationService::AllSources()); 34} 35 36BalloonCollectionImpl::~BalloonCollectionImpl() { 37 Shutdown(); 38} 39 40void 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 52bool 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 66void 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 84bool 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 94bool 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 106bool BalloonCollectionImpl::RemoveById(const std::string& id) { 107 return base_.CloseById(id); 108} 109 110bool BalloonCollectionImpl::RemoveBySourceOrigin(const GURL& origin) { 111 return base_.CloseAllBySourceOrigin(origin); 112} 113 114void BalloonCollectionImpl::RemoveAll() { 115 base_.CloseAll(); 116} 117 118bool BalloonCollectionImpl::HasSpace() const { 119 return true; 120} 121 122void BalloonCollectionImpl::ResizeBalloon(Balloon* balloon, 123 const gfx::Size& size) { 124 notification_ui_->ResizeNotification(balloon, size); 125} 126 127void 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 136void 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 149void 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 157Balloon* 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 167BalloonCollection* BalloonCollection::Create() { 168 return new chromeos::BalloonCollectionImpl(); 169} 170