Home | History | Annotate | Download | only in notifications
      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