diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h
index ff1361bb2103ebfccf6036909d7d47068e20b461..328331820f31a9b800691a11f14951d0e80ac614 100644
--- a/chrome/browser/browser_process.h
+++ b/chrome/browser/browser_process.h
@@ -23,6 +23,7 @@ class DownloadRequestManager;
 class GoogleURLTracker;
 class IconManager;
 class MetricsService;
+class NotificationUIManager;
 class PrefService;
 class ProfileManager;
 class DebuggerWrapper;
@@ -69,6 +70,9 @@ class BrowserProcess {
   virtual DevToolsManager* devtools_manager() = 0;
   virtual Clipboard* clipboard() = 0;
 
+  // Returns the manager for desktop notifications.
+  virtual NotificationUIManager* notification_ui_manager() = 0;
+
   // Returns the thread that we perform I/O coordination on (network requests,
   // communication with renderers, etc.
   // NOTE: You should ONLY use this to pass to IPC or other objects which must
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index ebfb0bf911407d774eae6b3175c91075845ed57e..2195f423a92270fc263d41e64c62f958fb7187fd 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/net/dns_global.h"
 #include "chrome/browser/net/sdch_dictionary_fetcher.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/plugin_service.h"
 #include "chrome/browser/profile_manager.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
@@ -147,6 +148,7 @@ BrowserProcessImpl::BrowserProcessImpl(const CommandLine& command_line)
       created_icon_manager_(false),
       created_debugger_wrapper_(false),
       created_devtools_manager_(false),
+      created_notification_ui_manager_(false),
       module_ref_count_(0),
       checked_for_new_frames_(false),
       using_new_frames_(false),
@@ -433,6 +435,12 @@ void BrowserProcessImpl::CreateGoogleURLTracker() {
   google_url_tracker_.swap(google_url_tracker);
 }
 
+void BrowserProcessImpl::CreateNotificationUIManager() {
+  DCHECK(notification_ui_manager_.get() == NULL);
+  notification_ui_manager_.reset(NotificationUIManager::Create());
+  created_notification_ui_manager_ = true;
+}
+
 // The BrowserProcess object must outlive the file thread so we use traits
 // which don't do any management.
 template <>
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h
index a949ae446565e56623e61b4654df694d58bb973d..ea9efb4187c8e99e91e160c8ea9aa289ac3b686e 100644
--- a/chrome/browser/browser_process_impl.h
+++ b/chrome/browser/browser_process_impl.h
@@ -126,6 +126,13 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
     return clipboard_.get();
   }
 
+  virtual NotificationUIManager* notification_ui_manager() {
+    DCHECK(CalledOnValidThread());
+    if (!created_notification_ui_manager_)
+      CreateNotificationUIManager();
+    return notification_ui_manager_.get();
+  }
+
   virtual IconManager* icon_manager() {
     DCHECK(CalledOnValidThread());
     if (!created_icon_manager_)
@@ -217,6 +224,7 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
   void CreateDebuggerWrapper(int port);
   void CreateDevToolsManager();
   void CreateGoogleURLTracker();
+  void CreateNotificationUIManager();
 
 #if defined(OS_WIN)
   void InitBrokerServices(sandbox::BrokerServices* broker_services);
@@ -267,6 +275,10 @@ class BrowserProcessImpl : public BrowserProcess, public NonThreadSafe {
 
   scoped_ptr<Clipboard> clipboard_;
 
+  // Manager for desktop notification UI.
+  bool created_notification_ui_manager_;
+  scoped_ptr<NotificationUIManager> notification_ui_manager_;
+
   scoped_ptr<AutomationProviderList> automation_provider_list_;
 
   scoped_ptr<GoogleURLTracker> google_url_tracker_;
diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h
index 38e0b27b299cfb6fd5bbede65e379bd1b1f63f51..d7fbfda29a4a1011cc4b2818a9476b1213b739e1 100644
--- a/chrome/browser/notifications/desktop_notification_service.h
+++ b/chrome/browser/notifications/desktop_notification_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H
-#define CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H
+#ifndef CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H_
+#define CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H_
 
 #include <set>
 
@@ -75,4 +75,4 @@ class DesktopNotificationService {
   DISALLOW_COPY_AND_ASSIGN(DesktopNotificationService);
 };
 
-#endif  // #ifndef CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H
+#endif  // CHROME_BROWSER_NOTIFICATIONS_DESKTOP_NOTIFICATION_SERVICE_H_
diff --git a/chrome/browser/notifications/desktop_notification_service_win.cc b/chrome/browser/notifications/desktop_notification_service_win.cc
index 41e3e298170e0abd21a2925b0ca14211c12e81f1..f6494cd68b111755f4b00aa9bc2ac12be741d647 100644
--- a/chrome/browser/notifications/desktop_notification_service_win.cc
+++ b/chrome/browser/notifications/desktop_notification_service_win.cc
@@ -12,9 +12,9 @@
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/chrome_thread.h"
 #include "chrome/browser/notifications/notification_object_proxy.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/renderer_host/render_process_host.h"
 #include "chrome/browser/renderer_host/site_instance.h"
-#include "chrome/browser/worker_host/worker_process_host.h"
 #include "chrome/common/child_process_host.h"
 #include "grit/browser_resources.h"
 #include "grit/generated_resources.h"
@@ -59,9 +59,7 @@ static string16 CreateDataUrl(const GURL& icon_url, const string16& title,
 // put the notification with the requested parameters on the desktop.
 void DesktopNotificationService::ShowNotification(
     const Notification& notification) {
-  SiteInstance* site_instance = SiteInstance::CreateSiteInstance(profile_);
-  // TODO(johnnyg): When UI Manager is available, add from here.
-  //  ui_manager_->Add(notification, profile_, site_instance);
+  ui_manager_->Add(notification, profile_);
 }
 
 // Shows a notification bubble which contains the contents of url.
@@ -94,4 +92,3 @@ bool DesktopNotificationService::ShowDesktopNotificationText(
   ShowNotification(notif);
   return true;
 }
-
diff --git a/chrome/browser/notifications/notification_ui_manager.cc b/chrome/browser/notifications/notification_ui_manager.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6818a42081f7b70181f386aacf220d2ad5244bc1
--- /dev/null
+++ b/chrome/browser/notifications/notification_ui_manager.cc
@@ -0,0 +1,77 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/notifications/notification_ui_manager.h"
+
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/notifications/balloon_collection.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/renderer_host/site_instance.h"
+
+// A class which represents a notification waiting to be shown.
+class QueuedNotification {
+ public:
+  QueuedNotification(const Notification& notification, Profile* profile)
+      : notification_(notification),
+        profile_(profile) {
+  }
+
+  const Notification& notification() const { return notification_; }
+  Profile* profile() const { return profile_; }
+
+ private:
+  // The notification to be shown.
+  Notification notification_;
+
+  // Non owned pointer to the user's profile.
+  Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(QueuedNotification);
+};
+
+NotificationUIManager::NotificationUIManager()
+    : balloon_collection_(NULL) {
+}
+
+NotificationUIManager::~NotificationUIManager() {
+  STLDeleteElements(&show_queue_);
+}
+
+// static
+NotificationUIManager* NotificationUIManager::Create() {
+  BalloonCollectionImpl* balloons = new BalloonCollectionImpl();
+  NotificationUIManager* instance = new NotificationUIManager();
+  instance->Initialize(balloons);
+  balloons->set_space_change_listener(instance);
+  return instance;
+}
+
+void NotificationUIManager::Add(const Notification& notification,
+                                Profile* profile) {
+  LOG(INFO) << "Added notification. URL: "
+            << notification.content_url().spec().c_str();
+  show_queue_.push_back(
+      new QueuedNotification(notification, profile));
+  CheckAndShowNotifications();
+}
+
+void NotificationUIManager::CheckAndShowNotifications() {
+  // TODO(johnnyg): http://crbug.com/25061 - Check for user idle/presentation.
+  ShowNotifications();
+}
+
+void NotificationUIManager::ShowNotifications() {
+  while (!show_queue_.empty() && balloon_collection_->HasSpace()) {
+    scoped_ptr<QueuedNotification> queued_notification(show_queue_.front());
+    show_queue_.pop_front();
+    balloon_collection_->Add(queued_notification->notification(),
+                             queued_notification->profile());
+  }
+}
+
+void NotificationUIManager::OnBalloonSpaceChanged() {
+  CheckAndShowNotifications();
+}
diff --git a/chrome/browser/notifications/notification_ui_manager.h b/chrome/browser/notifications/notification_ui_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..192058f9e5b3296e729a7647900e6c7716cb3cb3
--- /dev/null
+++ b/chrome/browser/notifications/notification_ui_manager.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_UI_MANAGER_H_
+#define CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_UI_MANAGER_H_
+
+#include <deque>
+
+#include "base/id_map.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/notifications/balloon.h"
+#include "chrome/browser/notifications/balloon_collection.h"
+
+class Notification;
+class Profile;
+class QueuedNotification;
+class SiteInstance;
+
+// The notification manager manages use of the desktop for notifications.
+// It maintains a queue of pending notifications when space becomes constrained.
+class NotificationUIManager :
+    public BalloonCollectionImpl::BalloonSpaceChangeListener {
+ public:
+  NotificationUIManager();
+  virtual ~NotificationUIManager();
+
+  // Creates an initialized UI manager with a new balloon collection
+  // and the listener relationship setup.
+  // Except for unit tests, this is the way to construct the object.
+  static NotificationUIManager* Create();
+
+  // Initializes the UI manager with a balloon collection; this object
+  // takes ownership of the balloon collection.
+  void Initialize(BalloonCollection* balloon_collection) {
+    DCHECK(!balloon_collection_.get());
+    DCHECK(balloon_collection);
+    balloon_collection_.reset(balloon_collection);
+  }
+
+  // Adds a notification to be displayed. Virtual for unit test override.
+  virtual void Add(const Notification& notification,
+                   Profile* profile);
+
+ private:
+  // Attempts to display notifications from the show_queue if the user
+  // is active.
+  void CheckAndShowNotifications();
+
+  // Attempts to display notifications from the show_queue.
+  void ShowNotifications();
+
+  // BalloonCollectionObserver implementation.
+  virtual void OnBalloonSpaceChanged();
+
+  // An owned pointer to the collection of active balloons.
+  scoped_ptr<BalloonCollection> balloon_collection_;
+
+  // A queue of notifications which are waiting to be shown.
+  typedef std::deque<QueuedNotification*> NotificationDeque;
+  NotificationDeque show_queue_;
+
+  DISALLOW_COPY_AND_ASSIGN(NotificationUIManager);
+};
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_NOTIFICATION_UI_MANAGER_H_
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 7d715f0e6790dcd0212cab4f16b5f0366d919ca3..cafba63768340328bc0b2f8de240b491e0a03421 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -1318,11 +1318,9 @@ WebKitContext* ProfileImpl::GetWebKitContext() {
 DesktopNotificationService* ProfileImpl::GetDesktopNotificationService() {
   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
   if (!desktop_notification_service_.get()) {
-     // TODO(johnnyg): hook this up with notification UI manager.
      desktop_notification_service_.reset(new DesktopNotificationService(
-         this, NULL));
+         this, g_browser_process->notification_ui_manager()));
   }
-
   return desktop_notification_service_.get();
 }
 
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 0bfaf484867d4ee81cec77e835696cded528471b..accb720785b4425952bdbb2f65d94ff9581d1276 100755
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -1813,6 +1813,8 @@
         'browser/notifications/notification.h',
         'browser/notifications/notification_object_proxy.cc',
         'browser/notifications/notification_object_proxy.h',
+        'browser/notifications/notification_ui_manager.cc',
+        'browser/notifications/notification_ui_manager.h',
         'browser/notifications/notifications_prefs_cache.cc',
         'browser/notifications/notifications_prefs_cache.h',
         'browser/ntp_background_util.cc',
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index fc59c19c83c19a84592fff134dafb7901ccd1272..2aa316710c249625c6e02b5661d9837dba830f6a 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -188,7 +188,7 @@ class RenderView : public RenderWidget,
       const WebKit::WebString& source_name, unsigned source_line);
   virtual void printPage(WebKit::WebFrame* frame);
   virtual WebKit::WebNotificationPresenter* notificationPresenter() {
-    return NULL;
+    return notification_provider_.get();
   }
   virtual void didStartLoading();
   virtual void didStopLoading();
diff --git a/chrome/test/testing_browser_process.h b/chrome/test/testing_browser_process.h
index 93444ad06183e7b837cf76e3ae8948b1488b4a92..070c865f78137512999a0c055e8bd90ba6f90a7a 100644
--- a/chrome/test/testing_browser_process.h
+++ b/chrome/test/testing_browser_process.h
@@ -103,6 +103,10 @@ class TestingBrowserProcess : public BrowserProcess {
     return clipboard_.get();
   }
 
+  virtual NotificationUIManager* notification_ui_manager() {
+    return NULL;
+  }
+
   virtual GoogleURLTracker* google_url_tracker() {
     return NULL;
   }