Home | History | Annotate | Download | only in status_icons
      1 // Copyright (c) 2012 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/status_icons/desktop_notification_balloon.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/strings/string_number_conversions.h"
      9 #include "base/threading/thread_restrictions.h"
     10 #include "chrome/browser/browser_process.h"
     11 #include "chrome/browser/notifications/desktop_notification_service.h"
     12 #include "chrome/browser/notifications/notification.h"
     13 #include "chrome/browser/notifications/notification_delegate.h"
     14 #include "chrome/browser/notifications/notification_ui_manager.h"
     15 #include "chrome/browser/profiles/profile_manager.h"
     16 #include "third_party/skia/include/core/SkBitmap.h"
     17 #include "ui/gfx/image/image_skia.h"
     18 
     19 namespace {
     20 
     21 void CloseBalloon(const std::string& id) {
     22   // The browser process may have gone away during shutting down, in this case
     23   // notification_ui_manager() will close the balloon in its destructor.
     24   if (!g_browser_process)
     25     return;
     26 
     27   g_browser_process->notification_ui_manager()->CancelById(id);
     28 }
     29 
     30 // Prefix added to the notification ids.
     31 const char kNotificationPrefix[] = "desktop_notification_balloon.";
     32 
     33 // Timeout for automatically dismissing the notification balloon.
     34 const size_t kTimeoutSeconds = 6;
     35 
     36 class DummyNotificationDelegate : public NotificationDelegate {
     37  public:
     38   explicit DummyNotificationDelegate(const std::string& id)
     39       : id_(kNotificationPrefix + id) {}
     40 
     41   virtual void Display() OVERRIDE {
     42     base::MessageLoop::current()->PostDelayedTask(
     43         FROM_HERE,
     44         base::Bind(&CloseBalloon, id()),
     45         base::TimeDelta::FromSeconds(kTimeoutSeconds));
     46   }
     47   virtual void Error() OVERRIDE {}
     48   virtual void Close(bool by_user) OVERRIDE {}
     49   virtual void Click() OVERRIDE {}
     50   virtual std::string id() const OVERRIDE { return id_; }
     51   virtual content::WebContents* GetWebContents() const OVERRIDE {
     52     return NULL;
     53   }
     54 
     55  private:
     56   virtual ~DummyNotificationDelegate() {}
     57 
     58   std::string id_;
     59 };
     60 
     61 }  // anonymous namespace
     62 
     63 int DesktopNotificationBalloon::id_count_ = 1;
     64 
     65 DesktopNotificationBalloon::DesktopNotificationBalloon() {
     66 }
     67 
     68 DesktopNotificationBalloon::~DesktopNotificationBalloon() {
     69   if (!notification_id_.empty())
     70     CloseBalloon(notification_id_);
     71 }
     72 
     73 void DesktopNotificationBalloon::DisplayBalloon(
     74     const gfx::ImageSkia& icon,
     75     const base::string16& title,
     76     const base::string16& contents) {
     77   // Allowing IO access is required here to cover the corner case where
     78   // there is no last used profile and the default one is loaded.
     79   // IO access won't be required for normal uses.
     80   Profile* profile;
     81   {
     82     base::ThreadRestrictions::ScopedAllowIO allow_io;
     83     profile = ProfileManager::GetLastUsedProfile();
     84   }
     85   notification_id_ = DesktopNotificationService::AddIconNotification(
     86       GURL(), title, contents, gfx::Image(icon), base::string16(),
     87       new DummyNotificationDelegate(base::IntToString(id_count_++)), profile);
     88 }
     89