Bug 641906 - Use system theme colors in nsLookAndFeel on Android. r=blassey
authorAlex Pakhotin <alexp@mozilla.com>
Wed, 30 Mar 2011 11:04:41 -0700
changeset 69077 d6d104661d3045b3ffa8557d96c46932e85bcd5f
parent 69076 2348924d64101470f497e5e36a2f784a28c8cdba
child 69078 d6a5096b586137b0314f3d709f0f8b05b8aa13c1
push id19852
push userbzbarsky@mozilla.com
push dateSat, 07 May 2011 02:06:27 +0000
treeherdermozilla-central@62941612320d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs641906
milestone6.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 641906 - Use system theme colors in nsLookAndFeel on Android. r=blassey
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
embedding/android/GeckoAppShell.java
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
widget/src/android/nsLookAndFeel.cpp
widget/src/android/nsLookAndFeel.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -95,16 +95,17 @@
 #include "nsAccelerometer.h"
 
 #include "nsIMemoryReporter.h"
 #include "nsMemoryReporterManager.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 
 #ifdef ANDROID
 #include "gfxAndroidPlatform.h"
+#include "AndroidBridge.h"
 #endif
 
 #include "nsIClipboard.h"
 #include "nsWidgetsCID.h"
 #include "nsISupportsPrimitives.h"
 static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
 static const char* sClipboardTextFlavors[] = { kUnicodeMime };
 
@@ -530,16 +531,32 @@ ContentParent::RecvClipboardHasText(PRBo
     nsCOMPtr<nsIClipboard> clipboard(do_GetService(kCClipboardCID, &rv));
     NS_ENSURE_SUCCESS(rv, true);
 
     clipboard->HasDataMatchingFlavors(sClipboardTextFlavors, 1, 
                                       nsIClipboard::kGlobalClipboard, hasText);
     return true;
 }
 
+bool
+ContentParent::RecvGetSystemColors(const PRUint32& colorsCount, InfallibleTArray<PRUint32>* colors)
+{
+#ifdef ANDROID
+    if (!AndroidBridge::Bridge())
+        return false;
+
+    colors->AppendElements(colorsCount);
+
+    // The array elements correspond to the members of AndroidSystemColors structure,
+    // so just pass the pointer to the elements buffer
+    AndroidBridge::Bridge()->GetSystemColors((AndroidSystemColors*)colors->Elements());
+#endif
+    return true;
+}
+
 NS_IMPL_THREADSAFE_ISUPPORTS3(ContentParent,
                               nsIObserver,
                               nsIThreadObserver,
                               nsIDOMGeoPositionCallback)
 
 NS_IMETHODIMP
 ContentParent::Observe(nsISupports* aSubject,
                        const char* aTopic,
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -160,16 +160,18 @@ private:
 
     virtual bool RecvGetIndexedDBDirectory(nsString* aDirectory);
 
     virtual bool RecvSetClipboardText(const nsString& text, const PRInt32& whichClipboard);
     virtual bool RecvGetClipboardText(const PRInt32& whichClipboard, nsString* text);
     virtual bool RecvEmptyClipboard();
     virtual bool RecvClipboardHasText(PRBool* hasText);
 
+    virtual bool RecvGetSystemColors(const PRUint32& colorsCount, InfallibleTArray<PRUint32>* colors);
+
     virtual bool RecvStartVisitedQuery(const IPC::URI& uri);
 
     virtual bool RecvVisitURI(const IPC::URI& uri,
                               const IPC::URI& referrer,
                               const PRUint32& flags);
 
     virtual bool RecvSetURITitle(const IPC::URI& uri,
                                  const nsString& title);
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -189,15 +189,18 @@ parent:
     // the clipboard is not available in the content process.
     SetClipboardText(nsString text, PRInt32 whichClipboard);
     sync GetClipboardText(PRInt32 whichClipboard)
         returns (nsString text);
     EmptyClipboard();
     sync ClipboardHasText()
         returns (PRBool hasText);
 
+    sync GetSystemColors(PRUint32 colorsCount)
+        returns (PRUint32[] colors);
+
 both:
      AsyncMessage(nsString aMessage, nsString aJSON);
 
 };
 
 }
 }
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -1002,16 +1002,52 @@ public class GeckoAppShell
         Locale.setDefault(locale);
 
         Resources res = GeckoApp.mAppContext.getBaseContext().getResources();
         Configuration config = res.getConfiguration();
         config.locale = locale;
         res.updateConfiguration(config, res.getDisplayMetrics());
     }
 
+    public static int[] getSystemColors() {
+        // attrsAppearance[] must correspond to AndroidSystemColors structure in android/AndroidBridge.h
+        final int[] attrsAppearance = {
+            android.R.attr.textColor,
+            android.R.attr.textColorPrimary,
+            android.R.attr.textColorPrimaryInverse,
+            android.R.attr.textColorSecondary,
+            android.R.attr.textColorSecondaryInverse,
+            android.R.attr.textColorTertiary,
+            android.R.attr.textColorTertiaryInverse,
+            android.R.attr.textColorHighlight,
+            android.R.attr.colorForeground,
+            android.R.attr.colorBackground,
+            android.R.attr.panelColorForeground,
+            android.R.attr.panelColorBackground
+        };
+
+        int[] result = new int[attrsAppearance.length];
+
+        final ContextThemeWrapper contextThemeWrapper =
+            new ContextThemeWrapper(GeckoApp.mAppContext, android.R.style.TextAppearance);
+
+        final TypedArray appearance = contextThemeWrapper.getTheme().obtainStyledAttributes(attrsAppearance);
+
+        if (appearance != null) {
+            for (int i = 0; i < appearance.getIndexCount(); i++) {
+                int idx = appearance.getIndex(i);
+                int color = appearance.getColor(idx, 0);
+                result[idx] = color;
+            }
+            appearance.recycle();
+        }
+
+        return result;
+    }
+
     public static void killAnyZombies() {
         GeckoProcessesVisitor visitor = new GeckoProcessesVisitor() {
             public boolean callback(int pid) {
                 if (pid != android.os.Process.myPid())
                     android.os.Process.killProcess(pid);
                 return true;
             }
         };
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -135,16 +135,17 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V");
     jHideProgressDialog = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideProgressDialog", "()V");
     jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V");
     jSetKeepScreenOn = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setKeepScreenOn", "(Z)V");
     jIsNetworkLinkUp = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkUp", "()Z");
     jIsNetworkLinkKnown = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "isNetworkLinkKnown", "()Z");
     jSetSelectedLocale = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setSelectedLocale", "(Ljava/lang/String;)V");
     jScanMedia = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "scanMedia", "(Ljava/lang/String;Ljava/lang/String;)V");
+    jGetSystemColors = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getSystemColors", "()[I");
 
     jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
     jEGL10Class = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGL10"));
     jEGLSurfaceImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLSurfaceImpl"));
     jEGLContextImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLContextImpl"));
     jEGLConfigImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLConfigImpl"));
     jEGLDisplayImplClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("com/google/android/gles_jni/EGLDisplayImpl"));
 
@@ -676,16 +677,52 @@ void
 AndroidBridge::SetSelectedLocale(const nsAString& aLocale)
 {
     ALOG_BRIDGE("AndroidBridge::SetSelectedLocale");
     jstring jLocale = GetJNIForThread()->NewString(PromiseFlatString(aLocale).get(), aLocale.Length());
     GetJNIForThread()->CallStaticVoidMethod(mGeckoAppShellClass, jSetSelectedLocale, jLocale);
 }
 
 void
+AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
+{
+    ALOG_BRIDGE("AndroidBridge::GetSystemColors");
+
+    NS_ASSERTION(aColors != nsnull, "AndroidBridge::GetSystemColors: aColors is null!");
+    if (!aColors)
+        return;
+
+    AutoLocalJNIFrame jniFrame;
+
+    jobject obj = mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass, jGetSystemColors);
+    jintArray arr = static_cast<jintArray>(obj);
+    if (!arr)
+        return;
+
+    jsize len = mJNIEnv->GetArrayLength(arr);
+    jint *elements = mJNIEnv->GetIntArrayElements(arr, 0);
+
+    PRUint32 colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
+    if (len < colorsCount)
+        colorsCount = len;
+
+    // Convert Android colors to nscolor by switching R and B in the ARGB 32 bit value
+    nscolor *colors = (nscolor*)aColors;
+
+    for (PRUint32 i = 0; i < colorsCount; i++) {
+        PRUint32 androidColor = static_cast<PRUint32>(elements[i]);
+        PRUint8 r = (androidColor & 0x00ff0000) >> 16;
+        PRUint8 b = (androidColor & 0x000000ff);
+        colors[i] = androidColor & 0xff00ff00 | b << 16 | r;
+    }
+
+    mJNIEnv->ReleaseIntArrayElements(arr, elements, 0);
+}
+
+void
 AndroidBridge::SetSurfaceView(jobject obj)
 {
     mSurfaceView.Init(obj);
 }
 
 void
 AndroidBridge::ShowInputMethodPicker()
 {
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -44,25 +44,42 @@
 #include "nsCOMPtr.h"
 #include "nsIRunnable.h"
 #include "nsIObserver.h"
 
 #include "AndroidJavaWrappers.h"
 
 #include "nsIMutableArray.h"
 #include "nsIMIMEInfo.h"
+#include "nsColor.h"
 
 // Some debug #defines
 // #define ANDROID_DEBUG_EVENTS
 // #define ANDROID_DEBUG_WIDGET
 
 class nsWindow;
 
 namespace mozilla {
 
+// The order and number of the members in this structure must correspond
+// to the attrsAppearance array in GeckoAppShell.getSystemColors()
+typedef struct AndroidSystemColors {
+    nscolor textColorPrimary;
+    nscolor textColorPrimaryInverse;
+    nscolor textColorSecondary;
+    nscolor textColorSecondaryInverse;
+    nscolor textColorTertiary;
+    nscolor textColorTertiaryInverse;
+    nscolor textColorHighlight;
+    nscolor colorForeground;
+    nscolor colorBackground;
+    nscolor panelColorForeground;
+    nscolor panelColorBackground;
+} AndroidSystemColors;
+
 class AndroidBridge
 {
 public:
     enum {
         NOTIFY_IME_RESETINPUTSTATE = 0,
         NOTIFY_IME_SETOPENSTATE = 1,
         NOTIFY_IME_CANCELCOMPOSITION = 2,
         NOTIFY_IME_FOCUSCHANGE = 3
@@ -184,16 +201,18 @@ public:
     void HideProgressDialogOnce();
 
     bool IsNetworkLinkUp();
 
     bool IsNetworkLinkKnown();
 
     void SetSelectedLocale(const nsAString&);
 
+    void GetSystemColors(AndroidSystemColors *aColors);
+
     struct AutoLocalJNIFrame {
         AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) {
             // Make sure there is enough space to store a local ref to the
             // exception.  I am not completely sure this is needed, but does
             // not hurt.
             AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries + 1);
         }
         // Note! Calling Purge makes all previous local refs created in
@@ -276,16 +295,17 @@ protected:
     jmethodID jShowInputMethodPicker;
     jmethodID jHideProgressDialog;
     jmethodID jPerformHapticFeedback;
     jmethodID jSetKeepScreenOn;
     jmethodID jIsNetworkLinkUp;
     jmethodID jIsNetworkLinkKnown;
     jmethodID jSetSelectedLocale;
     jmethodID jScanMedia;
+    jmethodID jGetSystemColors;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;
     jclass jEGLContextImplClass;
     jclass jEGLConfigImplClass;
     jclass jEGLDisplayImplClass;
     jclass jEGLContextClass;
     jclass jEGL10Class;
--- a/widget/src/android/nsLookAndFeel.cpp
+++ b/widget/src/android/nsLookAndFeel.cpp
@@ -16,116 +16,165 @@
  *
  * The Initial Developer of the Original Code is
  *   Mozilla Foundation
  * Portions created by the Initial Developer are Copyright (C) 2010
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Vladimir Vukicevic <vladimir@pobox.com>
+ *   Alex Pakhotin <alexp@mozilla.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+#include "mozilla/dom/ContentChild.h"
+#include "nsStyleConsts.h"
+#include "nsXULAppAPI.h"
 #include "nsLookAndFeel.h"
-#include "nsStyleConsts.h"
+
+using namespace mozilla;
+using mozilla::dom::ContentChild;
+
+PRBool nsLookAndFeel::mInitialized = PR_FALSE;
+AndroidSystemColors nsLookAndFeel::mSystemColors;
 
 nsLookAndFeel::nsLookAndFeel()
     : nsXPLookAndFeel()
 {
 }
 
 nsLookAndFeel::~nsLookAndFeel()
 {
 }
 
+#define BG_PRELIGHT_COLOR      NS_RGB(0xee,0xee,0xee)
+#define FG_PRELIGHT_COLOR      NS_RGB(0x77,0x77,0x77)
+#define BLACK_COLOR            NS_RGB(0x00,0x00,0x00)
+#define DARK_GRAY_COLOR        NS_RGB(0x40,0x40,0x40)
+#define GRAY_COLOR             NS_RGB(0x80,0x80,0x80)
+#define LIGHT_GRAY_COLOR       NS_RGB(0xa0,0xa0,0xa0)
+#define RED_COLOR              NS_RGB(0xff,0x00,0x00)
+
+nsresult
+nsLookAndFeel::GetSystemColors()
+{
+    if (mInitialized)
+        return NS_OK;
+
+    if (!AndroidBridge::Bridge())
+        return NS_ERROR_FAILURE;
+
+    AndroidBridge::Bridge()->GetSystemColors(&mSystemColors);
+
+    mInitialized = PR_TRUE;
+
+    return NS_OK;
+}
+
+nsresult
+nsLookAndFeel::CallRemoteGetSystemColors()
+{
+    // An array has to be used to get data from remote process
+    InfallibleTArray<PRUint32> colors;
+    PRUint32 colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
+
+    if (!ContentChild::GetSingleton()->SendGetSystemColors(colorsCount, &colors))
+        return NS_ERROR_FAILURE;
+
+    NS_ASSERTION(colors.Length() == colorsCount, "System colors array is incomplete");
+    if (colors.Length() == 0)
+        return NS_ERROR_FAILURE;
+
+    if (colors.Length() < colorsCount)
+        colorsCount = colors.Length();
+
+    // Array elements correspond to the members of mSystemColors structure,
+    // so just copy the memory block
+    memcpy(&mSystemColors, colors.Elements(), sizeof(nscolor) * colorsCount);
+
+    mInitialized = PR_TRUE;
+
+    return NS_OK;
+}
+
 nsresult
 nsLookAndFeel::NativeGetColor(const nsColorID aID, nscolor &aColor)
 {
     nsresult rv = NS_OK;
 
-#define BASE_ACTIVE_COLOR     NS_RGB(0xaa,0xaa,0xaa)
-#define BASE_NORMAL_COLOR     NS_RGB(0xff,0xff,0xff)
-#define BASE_SELECTED_COLOR   NS_RGB(0xaa,0xaa,0xaa)
-#define BG_ACTIVE_COLOR       NS_RGB(0xff,0xff,0xff)
-#define BG_INSENSITIVE_COLOR  NS_RGB(0xaa,0xaa,0xaa)
-#define BG_NORMAL_COLOR       NS_RGB(0xff,0xff,0xff)
-#define BG_PRELIGHT_COLOR     NS_RGB(0xee,0xee,0xee)
-#define BG_SELECTED_COLOR     NS_RGB(0x99,0x99,0x99)
-#define DARK_NORMAL_COLOR     NS_RGB(0x88,0x88,0x88)
-#define FG_INSENSITIVE_COLOR  NS_RGB(0x44,0x44,0x44)
-#define FG_NORMAL_COLOR       NS_RGB(0x00,0x00,0x00)
-#define FG_PRELIGHT_COLOR     NS_RGB(0x77,0x77,0x77)
-#define FG_SELECTED_COLOR     NS_RGB(0xaa,0xaa,0xaa)
-#define LIGHT_NORMAL_COLOR    NS_RGB(0xaa,0xaa,0xaa)
-#define TEXT_ACTIVE_COLOR     NS_RGB(0x99,0x99,0x99)
-#define TEXT_NORMAL_COLOR     NS_RGB(0x00,0x00,0x00)
-#define TEXT_SELECTED_COLOR   NS_RGB(0x00,0x00,0x00)
+    if (!mInitialized) {
+        if (XRE_GetProcessType() == GeckoProcessType_Default)
+            rv = GetSystemColors();
+        else
+            rv = CallRemoteGetSystemColors();
+        NS_ENSURE_SUCCESS(rv, rv);
+    }
 
     // XXX we'll want to use context.obtainStyledAttributes on the java side to
     // get all of these; see TextView.java for a good exmaple.
 
     switch (aID) {
         // These colors don't seem to be used for anything anymore in Mozilla
         // (except here at least TextSelectBackground and TextSelectForeground)
         // The CSS2 colors below are used.
     case eColor_WindowBackground:
-        aColor = BASE_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_WindowForeground:
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.textColorPrimary;
         break;
     case eColor_WidgetBackground:
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_WidgetForeground:
-        aColor = FG_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor_WidgetSelectBackground:
-        aColor = BG_SELECTED_COLOR;
+        aColor = mSystemColors.textColorHighlight;
         break;
     case eColor_WidgetSelectForeground:
-        aColor = FG_SELECTED_COLOR;
+        aColor = mSystemColors.textColorPrimaryInverse;
         break;
     case eColor_Widget3DHighlight:
-        aColor = NS_RGB(0xa0,0xa0,0xa0);
+        aColor = LIGHT_GRAY_COLOR;
         break;
     case eColor_Widget3DShadow:
-        aColor = NS_RGB(0x40,0x40,0x40);
+        aColor = DARK_GRAY_COLOR;
         break;
     case eColor_TextBackground:
         // not used?
-        aColor = BASE_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_TextForeground:
         // not used?
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.textColorPrimary;
         break;
     case eColor_TextSelectBackground:
     case eColor_IMESelectedRawTextBackground:
     case eColor_IMESelectedConvertedTextBackground:
         // still used
-        aColor = BASE_SELECTED_COLOR;
+        aColor = mSystemColors.textColorHighlight;
         break;
     case eColor_TextSelectForeground:
     case eColor_IMESelectedRawTextForeground:
     case eColor_IMESelectedConvertedTextForeground:
         // still used
-        aColor = TEXT_SELECTED_COLOR;
+        aColor = mSystemColors.textColorPrimaryInverse;
         break;
     case eColor_IMERawInputBackground:
     case eColor_IMEConvertedTextBackground:
         aColor = NS_TRANSPARENT;
         break;
     case eColor_IMERawInputForeground:
     case eColor_IMEConvertedTextForeground:
         aColor = NS_SAME_AS_FOREGROUND_COLOR;
@@ -134,183 +183,183 @@ nsLookAndFeel::NativeGetColor(const nsCo
     case eColor_IMEConvertedTextUnderline:
         aColor = NS_SAME_AS_FOREGROUND_COLOR;
         break;
     case eColor_IMESelectedRawTextUnderline:
     case eColor_IMESelectedConvertedTextUnderline:
         aColor = NS_TRANSPARENT;
         break;
     case eColor_SpellCheckerUnderline:
-      aColor = NS_RGB(0xff, 0, 0);
+      aColor = RED_COLOR;
       break;
 
         // css2  http://www.w3.org/TR/REC-CSS2/ui.html#system-colors
     case eColor_activeborder:
         // active window border
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_activecaption:
         // active window caption background
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_appworkspace:
         // MDI background color
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_background:
         // desktop background
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_captiontext:
         // text in active window caption, size box, and scrollbar arrow box (!)
-        aColor = FG_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor_graytext:
         // disabled text in windows, menus, etc.
-        aColor = FG_INSENSITIVE_COLOR;
+        aColor = mSystemColors.textColorTertiary;
         break;
     case eColor_highlight:
         // background of selected item
-        aColor = BASE_SELECTED_COLOR;
+        aColor = mSystemColors.textColorHighlight;
         break;
     case eColor_highlighttext:
         // text of selected item
-        aColor = TEXT_SELECTED_COLOR;
+        aColor = mSystemColors.textColorPrimaryInverse;
         break;
     case eColor_inactiveborder:
         // inactive window border
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_inactivecaption:
         // inactive window caption
-        aColor = BG_INSENSITIVE_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_inactivecaptiontext:
         // text in inactive window caption
-        aColor = FG_INSENSITIVE_COLOR;
+        aColor = mSystemColors.textColorTertiary;
         break;
     case eColor_infobackground:
         // tooltip background color
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_infotext:
         // tooltip text color
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor_menu:
         // menu background
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor_menutext:
         // menu text
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor_scrollbar:
         // scrollbar gray area
-        aColor = BG_ACTIVE_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
 
     case eColor_threedface:
     case eColor_buttonface:
         // 3-D face color
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
 
     case eColor_buttontext:
         // text on push buttons
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
 
     case eColor_buttonhighlight:
         // 3-D highlighted edge color
     case eColor_threedhighlight:
         // 3-D highlighted outer edge color
-        aColor = LIGHT_NORMAL_COLOR;
+        aColor = LIGHT_GRAY_COLOR;
         break;
 
     case eColor_threedlightshadow:
         // 3-D highlighted inner edge color
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
 
     case eColor_buttonshadow:
         // 3-D shadow edge color
     case eColor_threedshadow:
         // 3-D shadow inner edge color
-        aColor = DARK_NORMAL_COLOR;
+        aColor = GRAY_COLOR;
         break;
 
     case eColor_threeddarkshadow:
         // 3-D shadow outer edge color
-        aColor = NS_RGB(0,0,0);
+        aColor = BLACK_COLOR;
         break;
 
     case eColor_window:
     case eColor_windowframe:
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
 
     case eColor_windowtext:
-        aColor = FG_NORMAL_COLOR;
+        aColor = mSystemColors.textColorPrimary;
         break;
 
     case eColor__moz_eventreerow:
     case eColor__moz_field:
-        aColor = BASE_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor__moz_fieldtext:
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.textColorPrimary;
         break;
     case eColor__moz_dialog:
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor__moz_dialogtext:
-        aColor = FG_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor__moz_dragtargetzone:
-        aColor = BG_SELECTED_COLOR;
+        aColor = mSystemColors.textColorHighlight;
         break;
     case eColor__moz_buttondefault:
         // default button border color
-        aColor = NS_RGB(0,0,0);
+        aColor = BLACK_COLOR;
         break;
     case eColor__moz_buttonhoverface:
         aColor = BG_PRELIGHT_COLOR;
         break;
     case eColor__moz_buttonhovertext:
         aColor = FG_PRELIGHT_COLOR;
         break;
     case eColor__moz_cellhighlight:
     case eColor__moz_html_cellhighlight:
-        aColor = BASE_ACTIVE_COLOR;
+        aColor = mSystemColors.textColorHighlight;
         break;
     case eColor__moz_cellhighlighttext:
     case eColor__moz_html_cellhighlighttext:
-        aColor = TEXT_ACTIVE_COLOR;
+        aColor = mSystemColors.textColorPrimaryInverse;
         break;
     case eColor__moz_menuhover:
         aColor = BG_PRELIGHT_COLOR;
         break;
     case eColor__moz_menuhovertext:
         aColor = FG_PRELIGHT_COLOR;
         break;
     case eColor__moz_oddtreerow:
         aColor = NS_TRANSPARENT;
         break;
     case eColor__moz_nativehyperlinktext:
         aColor = NS_SAME_AS_FOREGROUND_COLOR;
         break;
     case eColor__moz_comboboxtext:
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor__moz_combobox:
-        aColor = BG_NORMAL_COLOR;
+        aColor = mSystemColors.colorBackground;
         break;
     case eColor__moz_menubartext:
-        aColor = TEXT_NORMAL_COLOR;
+        aColor = mSystemColors.colorForeground;
         break;
     case eColor__moz_menubarhovertext:
         aColor = FG_PRELIGHT_COLOR;
         break;
     default:
         /* default color is BLACK */
         aColor = 0;
         rv = NS_ERROR_FAILURE;
--- a/widget/src/android/nsLookAndFeel.h
+++ b/widget/src/android/nsLookAndFeel.h
@@ -35,21 +35,29 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 #ifndef __nsLookAndFeel
 #define __nsLookAndFeel
 
 #include "nsXPLookAndFeel.h"
+#include "AndroidBridge.h"
 
 class nsLookAndFeel: public nsXPLookAndFeel
 {
 public:
     nsLookAndFeel();
     virtual ~nsLookAndFeel();
 
     nsresult NativeGetColor(const nsColorID aID, nscolor &aColor);
     NS_IMETHOD GetMetric(const nsMetricID aID, PRInt32 & aMetric);
     NS_IMETHOD GetMetric(const nsMetricFloatID aID, float & aMetric);
+
+protected:
+    static PRBool mInitialized;
+    static mozilla::AndroidSystemColors mSystemColors;
+
+    nsresult GetSystemColors();
+    nsresult CallRemoteGetSystemColors();
 };
 
 #endif