chromeos: Show onscreen bubble when brightness changes.

This adds a BrightnessLibrary class that registers to receive
notification of brightness changes from the libcros code
that I added in http://codereview.chromium.org/5640003/,
a BrightnessBubble class to control an onscreen indicator of
the current brightness level, and a BrightnessObserver class
that wires up the two.

This change depends on
http://codereview.chromium.org/5603012/, which pulls the
updated version of libcros into Chrome.

BUG=chromium-os:8473,chromium-os:4816
TEST=built and tried it

Review URL: http://codereview.chromium.org/5620004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68879 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index df00c32..b3e7124 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -587,6 +587,7 @@
         <include name="IDR_VOLUME_BUBBLE_UP_ICON" file="volume_up_icon.png" type="BINDATA" />
         <include name="IDR_VOLUME_BUBBLE_DOWN_ICON" file="volume_down_icon.png" type="BINDATA" />
         <include name="IDR_VOLUME_BUBBLE_MUTE_ICON" file="volume_mute_icon.png" type="BINDATA" />
+        <include name="IDR_BRIGHTNESS_BUBBLE_ICON" file="brightness_icon.png" type="BINDATA" />
         <include name="IDR_SCROLL_BACKGROUND" file="chromeos_scroll_background.png" type="BINDATA" />
         <include name="IDR_SCROLL_BACKGROUND_BORDER_UP" file="chromeos_scroll_background_border_up.png" type="BINDATA" />
         <include name="IDR_SCROLL_BACKGROUND_BORDER_DOWN" file="chromeos_scroll_background_border_down.png" type="BINDATA" />
diff --git a/chrome/browser/chromeos/brightness_bubble.cc b/chrome/browser/chromeos/brightness_bubble.cc
new file mode 100644
index 0000000..34f4bbd3
--- /dev/null
+++ b/chrome/browser/chromeos/brightness_bubble.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2010 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/chromeos/brightness_bubble.h"
+
+#include "app/resource_bundle.h"
+#include "base/singleton.h"
+#include "grit/theme_resources.h"
+
+namespace chromeos {
+
+BrightnessBubble::BrightnessBubble()
+    : SettingLevelBubble(
+          ResourceBundle::GetSharedInstance().GetBitmapNamed(
+              IDR_BRIGHTNESS_BUBBLE_ICON),
+          ResourceBundle::GetSharedInstance().GetBitmapNamed(
+              IDR_BRIGHTNESS_BUBBLE_ICON),
+          ResourceBundle::GetSharedInstance().GetBitmapNamed(
+              IDR_BRIGHTNESS_BUBBLE_ICON)) {
+}
+
+// static
+BrightnessBubble* BrightnessBubble::instance() {
+  return Singleton<BrightnessBubble>::get();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/brightness_bubble.h b/chrome/browser/chromeos/brightness_bubble.h
new file mode 100644
index 0000000..89553fc
--- /dev/null
+++ b/chrome/browser/chromeos/brightness_bubble.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 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_CHROMEOS_BRIGHTNESS_BUBBLE_H_
+#define CHROME_BROWSER_CHROMEOS_BRIGHTNESS_BUBBLE_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "chrome/browser/chromeos/setting_level_bubble.h"
+
+template <typename T> struct DefaultSingletonTraits;
+
+namespace chromeos {
+
+// Singleton class controlling brightness bubble.
+class BrightnessBubble : public SettingLevelBubble {
+ public:
+  static BrightnessBubble* instance();
+
+ private:
+  friend struct DefaultSingletonTraits<BrightnessBubble>;
+
+  BrightnessBubble();
+  virtual ~BrightnessBubble() {}
+
+  DISALLOW_COPY_AND_ASSIGN(BrightnessBubble);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_BRIGHTNESS_BUBBLE_H_
diff --git a/chrome/browser/chromeos/brightness_observer.cc b/chrome/browser/chromeos/brightness_observer.cc
new file mode 100644
index 0000000..f501b2a4
--- /dev/null
+++ b/chrome/browser/chromeos/brightness_observer.cc
@@ -0,0 +1,17 @@
+// Copyright (c) 2010 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/chromeos/brightness_observer.h"
+
+#include "chrome/browser/chromeos/brightness_bubble.h"
+#include "chrome/browser/chromeos/volume_bubble.h"
+
+namespace chromeos {
+
+void BrightnessObserver::BrightnessChanged(int level) {
+  BrightnessBubble::instance()->ShowBubble(level);
+  VolumeBubble::instance()->HideBubble();
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/brightness_observer.h b/chrome/browser/chromeos/brightness_observer.h
new file mode 100644
index 0000000..ce7bc956
--- /dev/null
+++ b/chrome/browser/chromeos/brightness_observer.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2010 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_CHROMEOS_BRIGHTNESS_OBSERVER_H_
+#define CHROME_BROWSER_CHROMEOS_BRIGHTNESS_OBSERVER_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "chrome/browser/chromeos/cros/brightness_library.h"
+
+namespace chromeos {
+
+// This observer displays a bubble at the bottom of the screen showing the
+// current brightness level whenever the user changes it.
+class BrightnessObserver : public BrightnessLibrary::Observer {
+ public:
+  BrightnessObserver() {}
+  virtual ~BrightnessObserver() {}
+
+ private:
+  // BrightnessLibrary::Observer implementation.
+  virtual void BrightnessChanged(int level);
+
+  DISALLOW_COPY_AND_ASSIGN(BrightnessObserver);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_BRIGHTNESS_OBSERVER_H_
diff --git a/chrome/browser/chromeos/cros/brightness_library.cc b/chrome/browser/chromeos/cros/brightness_library.cc
new file mode 100644
index 0000000..64bd1bf
--- /dev/null
+++ b/chrome/browser/chromeos/cros/brightness_library.cc
@@ -0,0 +1,93 @@
+// Copyright (c) 2010 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/chromeos/cros/brightness_library.h"
+
+#include "base/message_loop.h"
+#include "base/observer_list.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/chromeos/brightness_bubble.h"
+#include "chrome/browser/chromeos/volume_bubble.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+
+namespace chromeos {
+
+class BrightnessLibraryImpl : public BrightnessLibrary {
+ public:
+  BrightnessLibraryImpl() : brightness_connection_(NULL) {
+    if (CrosLibrary::Get()->EnsureLoaded())
+      Init();
+  }
+
+  ~BrightnessLibraryImpl() {
+    if (brightness_connection_) {
+      chromeos::DisconnectBrightness(brightness_connection_);
+      brightness_connection_ = NULL;
+    }
+  }
+
+  void AddObserver(Observer* observer) {
+    observers_.AddObserver(observer);
+  }
+
+  void RemoveObserver(Observer* observer) {
+    observers_.RemoveObserver(observer);
+  }
+
+ private:
+  static void BrightnessChangedHandler(void* object,
+                                       int brightness_level) {
+    BrightnessLibraryImpl* self = static_cast<BrightnessLibraryImpl*>(object);
+    self->OnBrightnessChanged(brightness_level);
+  }
+
+  void Init() {
+    DCHECK(!brightness_connection_) << "Already intialized";
+    brightness_connection_ =
+        chromeos::MonitorBrightness(&BrightnessChangedHandler, this);
+  }
+
+  void OnBrightnessChanged(int brightness_level) {
+    // Make sure we run on the UI thread.
+    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+      BrowserThread::PostTask(
+          BrowserThread::UI, FROM_HERE,
+          NewRunnableMethod(this,
+                            &BrightnessLibraryImpl::OnBrightnessChanged,
+                            brightness_level));
+      return;
+    }
+
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      BrightnessChanged(brightness_level));
+  }
+
+  chromeos::BrightnessConnection brightness_connection_;
+
+  ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrightnessLibraryImpl);
+};
+
+class BrightnessLibraryStubImpl : public BrightnessLibrary {
+ public:
+  BrightnessLibraryStubImpl() {}
+  ~BrightnessLibraryStubImpl() {}
+  void AddObserver(Observer* observer) {}
+  void RemoveObserver(Observer* observer) {}
+};
+
+// static
+BrightnessLibrary* BrightnessLibrary::GetImpl(bool stub) {
+  if (stub)
+    return new BrightnessLibraryStubImpl();
+  else
+    return new BrightnessLibraryImpl();
+}
+
+}  // namespace chromeos
+
+// Needed for NewRunnableMethod() call above.
+DISABLE_RUNNABLE_METHOD_REFCOUNT(chromeos::BrightnessLibraryImpl);
diff --git a/chrome/browser/chromeos/cros/brightness_library.h b/chrome/browser/chromeos/cros/brightness_library.h
new file mode 100644
index 0000000..442b049
--- /dev/null
+++ b/chrome/browser/chromeos/cros/brightness_library.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2010 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_CHROMEOS_CROS_BRIGHTNESS_LIBRARY_H_
+#define CHROME_BROWSER_CHROMEOS_CROS_BRIGHTNESS_LIBRARY_H_
+#pragma once
+
+#include "cros/chromeos_brightness.h"
+
+namespace chromeos {
+
+class BrightnessLibrary {
+ public:
+  class Observer {
+   public:
+    virtual void BrightnessChanged(int level) = 0;
+  };
+
+  virtual ~BrightnessLibrary() {}
+
+  virtual void AddObserver(Observer* observer) = 0;
+  virtual void RemoveObserver(Observer* observer) = 0;
+
+  // Factory function, creates a new instance and returns ownership.
+  // For normal usage, access the singleton via CrosLibrary::Get().
+  static BrightnessLibrary* GetImpl(bool stub);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CROS_BRIGHTNESS_LIBRARY_H_
diff --git a/chrome/browser/chromeos/cros/cros_library.cc b/chrome/browser/chromeos/cros/cros_library.cc
index 9065304..a294329 100644
--- a/chrome/browser/chromeos/cros/cros_library.cc
+++ b/chrome/browser/chromeos/cros/cros_library.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/cros/cros_library.h"
 
+#include "chrome/browser/chromeos/cros/brightness_library.h"
 #include "chrome/browser/chromeos/cros/burn_library.h"
 #include "chrome/browser/chromeos/cros/cros_library_loader.h"
 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
@@ -40,6 +41,10 @@
   return Singleton<CrosLibrary>::get();
 }
 
+BrightnessLibrary* CrosLibrary::GetBrightnessLibrary() {
+  return brightness_lib_.GetDefaultImpl(use_stub_impl_);
+}
+
 BurnLibrary* CrosLibrary::GetBurnLibrary() {
   return burn_lib_.GetDefaultImpl(use_stub_impl_);
 }
@@ -138,6 +143,11 @@
   library_->load_error_ = false;
 }
 
+void CrosLibrary::TestApi::SetBrightnessLibrary(
+    BrightnessLibrary* library, bool own) {
+  library_->brightness_lib_.SetImpl(library, own);
+}
+
 void CrosLibrary::TestApi::SetBurnLibrary(
     BurnLibrary* library, bool own) {
   library_->burn_lib_.SetImpl(library, own);
diff --git a/chrome/browser/chromeos/cros/cros_library.h b/chrome/browser/chromeos/cros/cros_library.h
index 06048ba4..ae16fa7 100644
--- a/chrome/browser/chromeos/cros/cros_library.h
+++ b/chrome/browser/chromeos/cros/cros_library.h
@@ -14,6 +14,7 @@
 #include "chrome/common/chrome_switches.h"
 namespace chromeos {
 
+class BrightnessLibrary;
 class BurnLibrary;
 class CryptohomeLibrary;
 class KeyboardLibrary;
@@ -50,6 +51,8 @@
     // when the CrosLibrary is deleted (or other mocks are set).
     // Setter for LibraryLoader.
     void SetLibraryLoader(LibraryLoader* loader, bool own);
+    // Setter for BrightnessLibrary.
+    void SetBrightnessLibrary(BrightnessLibrary* library, bool own);
     // Setter for BurnLibrary.
     void SetBurnLibrary(BurnLibrary* library, bool own);
     // Setter for CryptohomeLibrary.
@@ -88,6 +91,9 @@
   // This gets the CrosLibrary.
   static CrosLibrary* Get();
 
+  // Getter for BrightnessLibrary.
+  BrightnessLibrary* GetBrightnessLibrary();
+
   // Getter for BurnLibrary.
   BurnLibrary* GetBurnLibrary();
 
@@ -190,6 +196,7 @@
     bool own_;
   };
 
+  Library<BrightnessLibrary> brightness_lib_;
   Library<BurnLibrary> burn_lib_;
   Library<CryptohomeLibrary> crypto_lib_;
   Library<KeyboardLibrary> keyboard_lib_;
diff --git a/chrome/browser/chromeos/setting_level_bubble.cc b/chrome/browser/chromeos/setting_level_bubble.cc
index eb918e9..8648237 100644
--- a/chrome/browser/chromeos/setting_level_bubble.cc
+++ b/chrome/browser/chromeos/setting_level_bubble.cc
@@ -115,11 +115,15 @@
                        this, &SettingLevelBubble::OnTimeout);
 }
 
-void SettingLevelBubble::OnTimeout() {
+void SettingLevelBubble::HideBubble() {
   if (bubble_)
     bubble_->Close();
 }
 
+void SettingLevelBubble::OnTimeout() {
+  HideBubble();
+}
+
 void SettingLevelBubble::InfoBubbleClosing(InfoBubble* info_bubble, bool) {
   DCHECK(info_bubble == bubble_);
   timeout_timer_.Stop();
diff --git a/chrome/browser/chromeos/setting_level_bubble.h b/chrome/browser/chromeos/setting_level_bubble.h
index 4619127..262bbdc 100644
--- a/chrome/browser/chromeos/setting_level_bubble.h
+++ b/chrome/browser/chromeos/setting_level_bubble.h
@@ -8,6 +8,7 @@
 
 #include "app/animation_delegate.h"
 #include "app/slide_animation.h"
+#include "base/basictypes.h"
 #include "base/timer.h"
 #include "chrome/browser/views/info_bubble.h"
 
@@ -23,6 +24,7 @@
                            public AnimationDelegate {
  public:
   void ShowBubble(int percent);
+  void HideBubble();
 
  protected:
   explicit SettingLevelBubble(SkBitmap* increase_icon,
diff --git a/chrome/browser/chromeos/system_key_event_listener.cc b/chrome/browser/chromeos/system_key_event_listener.cc
index 0ac003a..748152c 100644
--- a/chrome/browser/chromeos/system_key_event_listener.cc
+++ b/chrome/browser/chromeos/system_key_event_listener.cc
@@ -8,6 +8,7 @@
 #include <X11/XF86keysym.h>
 
 #include "chrome/browser/chromeos/audio_handler.h"
+#include "chrome/browser/chromeos/brightness_bubble.h"
 #include "chrome/browser/chromeos/volume_bubble.h"
 #include "cros/chromeos_wm_ipc_enums.h"
 
@@ -131,6 +132,7 @@
   // http://crosbug.com/3751
   audio_handler_->SetMute(true);
   VolumeBubble::instance()->ShowBubble(0);
+  BrightnessBubble::instance()->HideBubble();
 }
 
 void SystemKeyEventListener::OnVolumeDown() {
@@ -141,6 +143,7 @@
     VolumeBubble::instance()->ShowBubble(
         audio_handler_->GetVolumePercent());
   }
+  BrightnessBubble::instance()->HideBubble();
 }
 
 void SystemKeyEventListener::OnVolumeUp() {
@@ -150,6 +153,7 @@
     audio_handler_->AdjustVolumeByPercent(kStepPercentage);
   VolumeBubble::instance()->ShowBubble(
       audio_handler_->GetVolumePercent());
+  BrightnessBubble::instance()->HideBubble();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/volume_bubble.h b/chrome/browser/chromeos/volume_bubble.h
index a99ae2ce..efbdc5f9 100644
--- a/chrome/browser/chromeos/volume_bubble.h
+++ b/chrome/browser/chromeos/volume_bubble.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_VOLUME_BUBBLE_H_
 #pragma once
 
+#include "base/basictypes.h"
 #include "chrome/browser/chromeos/setting_level_bubble.h"
 
 template <typename T> struct DefaultSingletonTraits;
diff --git a/chrome/browser/ui/browser_init.cc b/chrome/browser/ui/browser_init.cc
index 60fd1b3..936b6dd 100644
--- a/chrome/browser/ui/browser_init.cc
+++ b/chrome/browser/ui/browser_init.cc
@@ -81,6 +81,7 @@
 #endif
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/brightness_observer.h"
 #include "chrome/browser/chromeos/cros/cros_library.h"
 #include "chrome/browser/chromeos/cros/mount_library.h"
 #include "chrome/browser/chromeos/cros/network_library.h"
@@ -444,7 +445,7 @@
     // Connect the chromeos notifications
 
     // This observer is a singleton. It is never deleted but the pointer is kept
-    // in a global so that it isn't reported as a leak.
+    // in a static so that it isn't reported as a leak.
     static chromeos::LowBatteryObserver* low_battery_observer =
         new chromeos::LowBatteryObserver(profile);
     chromeos::CrosLibrary::Get()->GetPowerLibrary()->AddObserver(
@@ -462,6 +463,11 @@
     chromeos::CrosLibrary::Get()->GetNetworkLibrary()
         ->AddCellularDataPlanObserver(network_message_observer);
 
+    static chromeos::BrightnessObserver* brightness_observer =
+        new chromeos::BrightnessObserver();
+    chromeos::CrosLibrary::Get()->GetBrightnessLibrary()
+        ->AddObserver(brightness_observer);
+
     profile->SetupChromeOSEnterpriseExtensionObserver();
   }
 #endif
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 10989f6..cbf726c 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -396,6 +396,10 @@
         'browser/chromeos/audio_handler.h',
         'browser/chromeos/boot_times_loader.cc',
         'browser/chromeos/boot_times_loader.h',
+        'browser/chromeos/brightness_bubble.cc',
+        'browser/chromeos/brightness_bubble.h',
+        'browser/chromeos/brightness_observer.cc',
+        'browser/chromeos/brightness_observer.h',
         'browser/chromeos/browser_main_chromeos.cc',
         'browser/chromeos/browser_main_chromeos.h',
         'browser/chromeos/cros_settings.cc',
@@ -404,6 +408,8 @@
         'browser/chromeos/cros_settings_names.h',
         'browser/chromeos/cros_settings_provider.h',
         'browser/chromeos/cros_settings_provider.cc',
+        'browser/chromeos/cros/brightness_library.cc',
+        'browser/chromeos/cros/brightness_library.h',
         'browser/chromeos/cros/burn_library.cc',
         'browser/chromeos/cros/burn_library.h',
         'browser/chromeos/cros/cros_library.cc',