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