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::RenderViewHost* GetRenderViewHost() 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(const gfx::ImageSkia& icon, 74 const string16& title, 75 const string16& contents) { 76 // Allowing IO access is required here to cover the corner case where 77 // there is no last used profile and the default one is loaded. 78 // IO access won't be required for normal uses. 79 Profile* profile; 80 { 81 base::ThreadRestrictions::ScopedAllowIO allow_io; 82 profile = ProfileManager::GetLastUsedProfile(); 83 } 84 notification_id_ = DesktopNotificationService::AddIconNotification( 85 GURL(), title, contents, gfx::Image(icon), string16(), 86 new DummyNotificationDelegate(base::IntToString(id_count_++)), profile); 87 } 88