Bug 701996 - Merge widget/src/android from birch back into mozilla-central. r=dougt/blassey
authorDoug Turner <dougt@dougt.org>
Mon, 14 Nov 2011 19:12:14 -0800
changeset 80240 5384d8c6c527e771ca5e398caf195ea714b7e836
parent 80239 f694183357ec7d7a9c5406dc651e9805c77f33da
child 80241 09440352f371e49af29acb3532b460685e1a60dc
push id323
push userrcampbell@mozilla.com
push dateTue, 15 Nov 2011 21:58:36 +0000
treeherderfx-team@3ea216303184 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdougt, blassey
bugs701996
milestone11.0a1
Bug 701996 - Merge widget/src/android from birch back into mozilla-central. r=dougt/blassey
embedding/android/GeckoAppShell.java
embedding/android/GeckoEvent.java
widget/src/android/AndroidBridge.cpp
widget/src/android/AndroidBridge.h
widget/src/android/AndroidJNI.cpp
widget/src/android/AndroidJavaWrappers.cpp
widget/src/android/AndroidJavaWrappers.h
widget/src/android/Makefile.in
widget/src/android/nsAppShell.cpp
widget/src/android/nsIAndroidBridge.idl
widget/src/android/nsWidgetFactory.cpp
widget/src/android/nsWindow.cpp
widget/src/android/nsWindow.h
--- a/embedding/android/GeckoAppShell.java
+++ b/embedding/android/GeckoAppShell.java
@@ -57,16 +57,18 @@ import android.content.pm.*;
 import android.graphics.*;
 import android.widget.*;
 import android.hardware.*;
 import android.location.*;
 import android.webkit.MimeTypeMap;
 import android.media.MediaScannerConnection;
 import android.media.MediaScannerConnection.MediaScannerConnectionClient;
 import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.AccessibilityEvent;
 
 import android.util.*;
 import android.net.Uri;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 
 import android.graphics.drawable.*;
 import android.graphics.Bitmap;
@@ -1354,16 +1356,23 @@ public class GeckoAppShell
                 Settings.System.getInt(GeckoApp.mAppContext.getContentResolver(),
                                        Settings.System.TEXT_SHOW_PASSWORD, 1);
             return (showPassword > 0);
         }
         catch (Exception e) {
             return true;
         }
     }
+
+    public static boolean getAccessibilityEnabled() {
+        AccessibilityManager accessibilityManager =
+            (AccessibilityManager) GeckoApp.mAppContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+        return accessibilityManager.isEnabled();
+    }
+
     public static void addPluginView(final View view,
                                      final double x, final double y,
                                      final double w, final double h) {
 
         Log.i("GeckoAppShell", "addPluginView:" + view + " @ x:" + x + " y:" + y + " w:" + w + " h:" + h ) ;
 
         getMainHandler().post(new Runnable() { 
                 public void run() {
@@ -1615,16 +1624,26 @@ public class GeckoAppShell
         });
         try {
             sTracerQueue.take();
         } catch(InterruptedException ie) {
             Log.w("GeckoAppShell", "exception firing tracer", ie);
         }
     }
 
+    // unused
+    public static String handleGeckoMessage(String message) {
+        return "";
+    }
+    // unused
+    static void checkUriVisited(String uri) {}
+    // unused
+    static void markUriVisited(final String uri) {}
+
+
     public static void enableBatteryNotifications() {
         GeckoBatteryManager.enableNotifications();
     }
 
     public static void disableBatteryNotifications() {
         GeckoBatteryManager.disableNotifications();
     }
 
--- a/embedding/android/GeckoEvent.java
+++ b/embedding/android/GeckoEvent.java
@@ -68,16 +68,18 @@ public class GeckoEvent {
     public static final int ACTIVITY_STOPPING = 9;
     public static final int ACTIVITY_PAUSING = 10;
     public static final int ACTIVITY_SHUTDOWN = 11;
     public static final int LOAD_URI = 12;
     public static final int SURFACE_CREATED = 13;
     public static final int SURFACE_DESTROYED = 14;
     public static final int GECKO_EVENT_SYNC = 15;
     public static final int ACTIVITY_START = 17;
+    public static final int SAVE_STATE = 18;
+    public static final int BROADCAST = 19;
 
     public static final int IME_COMPOSITION_END = 0;
     public static final int IME_COMPOSITION_BEGIN = 1;
     public static final int IME_SET_TEXT = 2;
     public static final int IME_GET_TEXT = 3;
     public static final int IME_DELETE_TEXT = 4;
     public static final int IME_SET_SELECTION = 5;
     public static final int IME_GET_SELECTION = 6;
@@ -99,17 +101,17 @@ public class GeckoEvent {
     public Point mP0, mP1;
     public Rect mRect;
     public double mX, mY, mZ;
     public double mAlpha, mBeta, mGamma;
 
     public int mMetaState, mFlags;
     public int mKeyCode, mUnicodeChar;
     public int mOffset, mCount;
-    public String mCharacters;
+    public String mCharacters, mCharactersExtra;
     public int mRangeType, mRangeStyles;
     public int mRangeForeColor, mRangeBackColor;
     public Location mLocation;
     public Address  mAddress;
 
     public int mNativeWindow;
 
     public GeckoEvent() {
@@ -218,13 +220,19 @@ public class GeckoEvent {
         }
 
         mType = etype;
 
         mP0 = new Point(w, h);
         mP1 = new Point(screenw, screenh);
     }
 
+    public GeckoEvent(String subject, String data) {
+        mType = BROADCAST;
+        mCharacters = subject;
+        mCharactersExtra = data;
+    }
+
     public GeckoEvent(String uri) {
         mType = LOAD_URI;
         mCharacters = uri;
     }
 }
--- a/widget/src/android/AndroidBridge.cpp
+++ b/widget/src/android/AndroidBridge.cpp
@@ -156,16 +156,21 @@ AndroidBridge::Init(JNIEnv *jEnv,
     jGetShowPasswordSetting = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getShowPasswordSetting", "()Z");
     jPostToJavaThread = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "postToJavaThread", "(Z)V");
     jInitCamera = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "initCamera", "(Ljava/lang/String;III)[I");
     jCloseCamera = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "closeCamera", "()V");
     jEnableBatteryNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableBatteryNotifications", "()V");
     jDisableBatteryNotifications = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "disableBatteryNotifications", "()V");
     jGetCurrentBatteryInformation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getCurrentBatteryInformation", "()[D");
 
+    jGetAccessibilityEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getAccessibilityEnabled", "()Z");
+    jHandleGeckoMessage = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "handleGeckoMessage", "(Ljava/lang/String;)Ljava/lang/String;");
+    jCheckUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "checkUriVisited", "(Ljava/lang/String;)V");
+    jMarkUriVisited = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "markUriVisited", "(Ljava/lang/String;)V");
+
     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"));
 
     InitAndroidJavaWrappers(jEnv);
@@ -665,16 +670,23 @@ AndroidBridge::HideProgressDialogOnce()
     static bool once = false;
     if (!once) {
         ALOG_BRIDGE("AndroidBridge::HideProgressDialogOnce");
         mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jHideProgressDialog);
         once = true;
     }
 }
 
+bool
+AndroidBridge::GetAccessibilityEnabled()
+{
+    ALOG_BRIDGE("AndroidBridge::GetAccessibilityEnabled");
+    return mJNIEnv->CallStaticBooleanMethod(mGeckoAppShellClass, jGetAccessibilityEnabled);
+}
+
 void
 AndroidBridge::PerformHapticFeedback(bool aIsLongPress)
 {
     ALOG_BRIDGE("AndroidBridge::PerformHapticFeedback");
     mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass,
                                     jPerformHapticFeedback, aIsLongPress);
 }
 
@@ -835,16 +847,22 @@ AndroidBridge::GetShowPasswordSetting()
 
 void
 AndroidBridge::SetSurfaceView(jobject obj)
 {
     mSurfaceView.Init(obj);
 }
 
 void
+AndroidBridge::SetSoftwareLayerClient(jobject obj)
+{
+    mSoftwareLayerClient.Init(obj);
+}
+
+void
 AndroidBridge::ShowInputMethodPicker()
 {
     ALOG_BRIDGE("AndroidBridge::ShowInputMethodPicker");
     mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jShowInputMethodPicker);
 }
 
 void *
 AndroidBridge::CallEglCreateWindowSurface(void *dpy, void *config, AndroidGeckoSurfaceView &sview)
@@ -997,51 +1015,43 @@ AndroidBridge::CreateShortcut(const nsAS
     return;
     
   mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jCreateShortcut, jstrTitle, jstrURI, jstrIconData, jstrIntent);
 }
 
 void
 AndroidBridge::PostToJavaThread(nsIRunnable* aRunnable, bool aMainThread)
 {
-    __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "%s", __PRETTY_FUNCTION__);
     JNIEnv* env = AndroidBridge::AttachThread(false);
     if (!env) {
-        __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "no jni env in %s!!", __PRETTY_FUNCTION__);
         return;
     }
     mRunnableQueue.AppendObject(aRunnable);
     env->CallStaticVoidMethod(mGeckoAppShellClass, jPostToJavaThread, (jboolean)aMainThread);
 
     jthrowable ex = env->ExceptionOccurred();
     if (ex) {
         env->ExceptionDescribe();
         env->ExceptionClear();
     }
-    __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "leaving %s", __PRETTY_FUNCTION__);
 }
 
 void
 AndroidBridge::ExecuteNextRunnable()
 {
-    __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "%s", __PRETTY_FUNCTION__);
-
     JNIEnv* env = AndroidBridge::AttachThread(false);
     if (!env) {
-        __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "no jni env in %s!!", __PRETTY_FUNCTION__);
         return;
     }
 
     if (mRunnableQueue.Count() > 0) {
         nsIRunnable* r = mRunnableQueue[0];
-        __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "going to run %p", r);
         r->Run();
         mRunnableQueue.RemoveObjectAt(0);
     }
-    __android_log_print(ANDROID_LOG_INFO, "GeckoBridge", "leaving %s", __PRETTY_FUNCTION__);
 }
 
 void
 AndroidBridge::OpenGraphicsLibraries()
 {
     if (!mOpenedGraphicsLibraries) {
         // Try to dlopen libjnigraphics.so for direct bitmap access on
         // Android 2.2+ (API level 8)
@@ -1264,16 +1274,64 @@ AndroidBridge::GetCurrentBatteryInformat
 
     aBatteryInfo->level() = info[0];
     aBatteryInfo->charging() = info[1] == 1.0f;
     aBatteryInfo->remainingTime() = info[2];
 
     mJNIEnv->ReleaseDoubleArrayElements(arr, info, 0);
 }
 
+void
+AndroidBridge::HandleGeckoMessage(const nsAString &aMessage, nsAString &aRet)
+{
+    ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
+    JNIEnv* env = AndroidBridge::AttachThread(false);
+    if (!env) {
+        ALOG_BRIDGE("no jni env in %s!!", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    AutoLocalJNIFrame jniFrame(1);
+    jstring jMessage = mJNIEnv->NewString(nsPromiseFlatString(aMessage).get(), aMessage.Length());
+    jstring returnMessage =  static_cast<jstring>(env->CallStaticObjectMethod(mGeckoAppShellClass, jHandleGeckoMessage, jMessage));
+
+    jthrowable ex = env->ExceptionOccurred();
+    if (ex) {
+        env->ExceptionDescribe();
+        env->ExceptionClear();
+    }
+    nsJNIString jniStr(returnMessage);
+    aRet.Assign(jniStr);
+    ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__);
+}
+
+void
+AndroidBridge::CheckURIVisited(const nsAString& aURI)
+{
+  AutoLocalJNIFrame jniFrame(1);
+  jstring jstrURI = mJNIEnv->NewString(nsPromiseFlatString(aURI).get(), aURI.Length());
+  mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jCheckUriVisited, jstrURI);
+}
+
+void
+AndroidBridge::MarkURIVisited(const nsAString& aURI)
+{
+  AutoLocalJNIFrame jniFrame(1);
+  jstring jstrURI = mJNIEnv->NewString(nsPromiseFlatString(aURI).get(), aURI.Length());
+  mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jMarkUriVisited, jstrURI);
+}
+
+void AndroidBridge::EmitGeckoAccessibilityEvent (PRInt32 eventType, const nsAString& role, const nsAString& text, const nsAString& description, bool enabled, bool checked, bool password) {
+    AutoLocalJNIFrame jniFrame;
+    jstring jstrRole = mJNIEnv->NewString(nsPromiseFlatString(role).get(), role.Length());
+    jstring jstrText = mJNIEnv->NewString(nsPromiseFlatString(text).get(), text.Length());
+    jstring jstrDescription = mJNIEnv->NewString(nsPromiseFlatString(description).get(), description.Length());
+    mJNIEnv->CallStaticVoidMethod(mGeckoAppShellClass, jEmitGeckoAccessibilityEvent, eventType, jstrRole, jstrText, jstrDescription, enabled, checked, password);
+}
+
 void *
 AndroidBridge::LockBitmap(jobject bitmap)
 {
     int err;
     void *buf;
 
     if ((err = AndroidBitmap_lockPixels(JNI(), bitmap, &buf)) != 0) {
         ALOG_BRIDGE("AndroidBitmap_lockPixels failed! (error %d)", err);
@@ -1374,8 +1432,26 @@ AndroidBridge::UnlockWindow(void* window
     int err;
     if ((err = ANativeWindow_unlockAndPost(window)) != 0) {
         ALOG_BRIDGE("ANativeWindow_unlockAndPost failed! (error %d)", err);
         return false;
     }
 
     return true;
 }
+
+/* Implementation file */
+NS_IMPL_ISUPPORTS1(nsAndroidBridge, nsIAndroidBridge)
+
+nsAndroidBridge::nsAndroidBridge()
+{
+}
+
+nsAndroidBridge::~nsAndroidBridge()
+{
+}
+
+/* void handleGeckoEvent (in AString message); */
+NS_IMETHODIMP nsAndroidBridge::HandleGeckoMessage(const nsAString & message, nsAString &aRet NS_OUTPARAM)
+{
+    AndroidBridge::Bridge()->HandleGeckoMessage(message, aRet);
+    return NS_OK;
+}
--- a/widget/src/android/AndroidBridge.h
+++ b/widget/src/android/AndroidBridge.h
@@ -35,28 +35,31 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef AndroidBridge_h__
 #define AndroidBridge_h__
 
 #include <jni.h>
 #include <android/log.h>
+#include <cstdlib>
 
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 #include "nsIRunnable.h"
 #include "nsIObserver.h"
 
 #include "AndroidJavaWrappers.h"
 
 #include "nsIMutableArray.h"
 #include "nsIMIMEInfo.h"
 #include "nsColor.h"
 
+#include "nsIAndroidBridge.h"
+
 // Some debug #defines
 // #define DEBUG_ANDROID_EVENTS
 // #define DEBUG_ANDROID_WIDGET
 
 class nsWindow;
 
 namespace mozilla {
 
@@ -142,16 +145,19 @@ public:
     void ReturnIMEQueryResult(const PRUnichar *aResult, PRUint32 aLen, int aSelStart, int aSelLen);
 
     void NotifyAppShellReady();
 
     void NotifyXreExit();
 
     void ScheduleRestart();
 
+    void SetSoftwareLayerClient(jobject jobj);
+    AndroidGeckoSoftwareLayerClient &GetSoftwareLayerClient() { return mSoftwareLayerClient; }
+
     void SetSurfaceView(jobject jobj);
     AndroidGeckoSurfaceView& SurfaceView() { return mSurfaceView; }
 
     bool GetHandlersForURL(const char *aURL, 
                              nsIMutableArray* handlersArray = nsnull,
                              nsIHandlerApp **aDefaultApp = nsnull,
                              const nsAString& aAction = EmptyString());
 
@@ -217,16 +223,18 @@ public:
     void GetSystemColors(AndroidSystemColors *aColors);
 
     void GetIconForExtension(const nsACString& aFileExt, PRUint32 aIconSize, PRUint8 * const aBuf);
 
     bool GetShowPasswordSetting();
 
     void FireAndWaitForTracerEvent();
 
+    bool GetAccessibilityEnabled();
+
     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
@@ -284,16 +292,23 @@ public:
     bool HasNativeWindowAccess();
 
     void *AcquireNativeWindow(jobject surface);
     void ReleaseNativeWindow(void *window);
     bool SetNativeWindowFormat(void *window, int format);
 
     bool LockWindow(void *window, unsigned char **bits, int *width, int *height, int *format, int *stride);
     bool UnlockWindow(void *window);
+    
+    void HandleGeckoMessage(const nsAString& message, nsAString &aRet);
+
+    void EmitGeckoAccessibilityEvent (PRInt32 eventType, const nsAString& role, const nsAString& text, const nsAString& description, bool enabled, bool checked, bool password);
+
+    void CheckURIVisited(const nsAString& uri);
+    void MarkURIVisited(const nsAString& uri);
 
     bool InitCamera(const nsCString& contentType, PRUint32 camera, PRUint32 *width, PRUint32 *height, PRUint32 *fps);
 
     void CloseCamera();
 
     void EnableBatteryNotifications();
     void DisableBatteryNotifications();
     void GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo);
@@ -305,16 +320,17 @@ protected:
     JavaVM *mJavaVM;
 
     // the JNIEnv for the main thread
     JNIEnv *mJNIEnv;
     void *mThread;
 
     // the GeckoSurfaceView
     AndroidGeckoSurfaceView mSurfaceView;
+    AndroidGeckoSoftwareLayerClient mSoftwareLayerClient;
 
     // the GeckoAppShell java class
     jclass mGeckoAppShellClass;
 
     AndroidBridge() { }
     bool Init(JNIEnv *jEnv, jclass jGeckoApp);
 
     void EnsureJNIThread();
@@ -370,16 +386,21 @@ protected:
     jmethodID jCreateShortcut;
     jmethodID jGetShowPasswordSetting;
     jmethodID jPostToJavaThread;
     jmethodID jInitCamera;
     jmethodID jCloseCamera;
     jmethodID jEnableBatteryNotifications;
     jmethodID jDisableBatteryNotifications;
     jmethodID jGetCurrentBatteryInformation;
+    jmethodID jGetAccessibilityEnabled;
+    jmethodID jHandleGeckoMessage;
+    jmethodID jCheckUriVisited;
+    jmethodID jMarkUriVisited;
+    jmethodID jEmitGeckoAccessibilityEvent;
 
     // stuff we need for CallEglCreateWindowSurface
     jclass jEGLSurfaceImplClass;
     jclass jEGLContextImplClass;
     jclass jEGLConfigImplClass;
     jclass jEGLDisplayImplClass;
     jclass jEGLContextClass;
     jclass jEGL10Class;
@@ -394,13 +415,31 @@ protected:
     int (*ANativeWindow_setBuffersGeometry)(void *window, int width, int height, int format);
 
     int (* ANativeWindow_lock)(void *window, void *outBuffer, void *inOutDirtyBounds);
     int (* ANativeWindow_unlockAndPost)(void *window);
 };
 
 }
 
+#define NS_ANDROIDBRIDGE_CID \
+{ 0x0FE2321D, 0xEBD9, 0x467D, \
+    { 0xA7, 0x43, 0x03, 0xA6, 0x8D, 0x40, 0x59, 0x9E } }
+
+class nsAndroidBridge : public nsIAndroidBridge
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIANDROIDBRIDGE
+
+  nsAndroidBridge();
+
+private:
+  ~nsAndroidBridge();
+
+protected:
+};
+
 extern "C" JNIEnv * GetJNIForThread();
 extern bool mozilla_AndroidBridge_SetMainThread(void *);
 extern jclass GetGeckoAppShellClass();
 
 #endif /* AndroidBridge_h__ */
--- a/widget/src/android/AndroidJNI.cpp
+++ b/widget/src/android/AndroidJNI.cpp
@@ -39,46 +39,53 @@
 #include "nsILocalFile.h"
 #include "nsString.h"
 
 #include "AndroidBridge.h"
 
 #include <jni.h>
 #include <pthread.h>
 #include <dlfcn.h>
+#include <stdio.h>
 
 #include "nsAppShell.h"
 #include "nsWindow.h"
 #include <android/log.h>
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "nsINetworkLinkService.h"
 
+#ifdef MOZ_ANDROID_HISTORY
+#include "nsAndroidHistory.h"
+#endif
+
 #ifdef MOZ_CRASHREPORTER
 #include "nsICrashReporter.h"
 #include "nsExceptionHandler.h"
 #endif
 
 
 using namespace mozilla;
 
 /* Forward declare all the JNI methods as extern "C" */
 
 extern "C" {
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_nativeInit(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *, jclass, jobject event);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv *, jclass);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSoftwareLayerClient(JNIEnv *jenv, jclass, jobject sv);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject sv);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *, jclass);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv *, jclass, jstring observerKey, jstring topic, jstring data);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onChangeNetworkLinkStatus(JNIEnv *, jclass, jstring status);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_reportJavaCrash(JNIEnv *, jclass, jstring stack);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_executeNextRunnable(JNIEnv *, jclass);
+    NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri);
     NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble);
 }
 
 
 /*
  * Incoming JNI methods
  */
 
@@ -106,16 +113,22 @@ Java_org_mozilla_gecko_GeckoAppShell_pro
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject obj)
 {
     AndroidBridge::Bridge()->SetSurfaceView(jenv->NewGlobalRef(obj));
 }
 
 NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_setSoftwareLayerClient(JNIEnv *jenv, jclass, jobject obj)
+{
+    AndroidBridge::Bridge()->SetSoftwareLayerClient(jenv->NewGlobalRef(obj));
+}
+
+NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_onLowMemory(JNIEnv *jenv, jclass jc)
 {
     if (nsAppShell::gAppShell) {
         nsAppShell::gAppShell->NotifyObservers(nsnull,
                                                "memory-pressure",
                                                NS_LITERAL_STRING("low-memory").get());
     }
 }
@@ -185,16 +198,24 @@ Java_org_mozilla_gecko_GeckoAppShell_exe
         __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", "no bridge in %s!!!!", __PRETTY_FUNCTION__);
         return;
     }
     AndroidBridge::Bridge()->ExecuteNextRunnable();
     __android_log_print(ANDROID_LOG_INFO, "GeckoJNI", "leaving %s", __PRETTY_FUNCTION__);
 }
 
 NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *jenv, jclass, jstring uri)
+{
+#ifdef MOZ_ANDROID_HISTORY
+    nsAndroidHistory::NotifyURIVisited(nsJNIString(uri, jenv));
+#endif
+}
+
+NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass,
                                                          jdouble aLevel,
                                                          jboolean aCharging,
                                                          jdouble aRemainingTime)
 {
     class NotifyBatteryChangeRunnable : public nsRunnable {
     public:
       NotifyBatteryChangeRunnable(double aLevel, bool aCharging, double aRemainingTime)
--- a/widget/src/android/AndroidJavaWrappers.cpp
+++ b/widget/src/android/AndroidJavaWrappers.cpp
@@ -51,16 +51,17 @@ jfieldID AndroidGeckoEvent::jBetaField =
 jfieldID AndroidGeckoEvent::jGammaField = 0;
 jfieldID AndroidGeckoEvent::jXField = 0;
 jfieldID AndroidGeckoEvent::jYField = 0;
 jfieldID AndroidGeckoEvent::jZField = 0;
 jfieldID AndroidGeckoEvent::jRectField = 0;
 jfieldID AndroidGeckoEvent::jNativeWindowField = 0;
 
 jfieldID AndroidGeckoEvent::jCharactersField = 0;
+jfieldID AndroidGeckoEvent::jCharactersExtraField = 0;
 jfieldID AndroidGeckoEvent::jKeyCodeField = 0;
 jfieldID AndroidGeckoEvent::jMetaStateField = 0;
 jfieldID AndroidGeckoEvent::jFlagsField = 0;
 jfieldID AndroidGeckoEvent::jUnicodeCharField = 0;
 jfieldID AndroidGeckoEvent::jOffsetField = 0;
 jfieldID AndroidGeckoEvent::jCountField = 0;
 jfieldID AndroidGeckoEvent::jRangeTypeField = 0;
 jfieldID AndroidGeckoEvent::jRangeStylesField = 0;
@@ -97,16 +98,21 @@ jmethodID AndroidAddress::jGetFeatureNam
 jmethodID AndroidAddress::jGetLocalityMethod;
 jmethodID AndroidAddress::jGetPostalCodeMethod;
 jmethodID AndroidAddress::jGetPremisesMethod;
 jmethodID AndroidAddress::jGetSubAdminAreaMethod;
 jmethodID AndroidAddress::jGetSubLocalityMethod;
 jmethodID AndroidAddress::jGetSubThoroughfareMethod;
 jmethodID AndroidAddress::jGetThoroughfareMethod;
 
+jclass AndroidGeckoSoftwareLayerClient::jGeckoSoftwareLayerClientClass = 0;
+jmethodID AndroidGeckoSoftwareLayerClient::jLockBufferMethod = 0;
+jmethodID AndroidGeckoSoftwareLayerClient::jUnlockBufferMethod = 0;
+jmethodID AndroidGeckoSoftwareLayerClient::jBeginDrawingMethod = 0;
+jmethodID AndroidGeckoSoftwareLayerClient::jEndDrawingMethod = 0;
 jclass AndroidGeckoSurfaceView::jGeckoSurfaceViewClass = 0;
 jmethodID AndroidGeckoSurfaceView::jBeginDrawingMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jEndDrawingMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jDraw2DBitmapMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jDraw2DBufferMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBitmapMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBufferMethod = 0;
 jmethodID AndroidGeckoSurfaceView::jGetSurfaceMethod = 0;
@@ -129,16 +135,19 @@ jmethodID AndroidGeckoSurfaceView::jGetH
 void
 mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
 {
     AndroidGeckoEvent::InitGeckoEventClass(jEnv);
     AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(jEnv);
     AndroidPoint::InitPointClass(jEnv);
     AndroidLocation::InitLocationClass(jEnv);
     AndroidAddress::InitAddressClass(jEnv);
+    AndroidRect::InitRectClass(jEnv);
+
+    AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(jEnv);
 }
 
 void
 AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
 {
     initInit();
 
     jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent");
@@ -152,16 +161,17 @@ AndroidGeckoEvent::InitGeckoEventClass(J
     jBetaField = getField("mBeta", "D");
     jGammaField = getField("mGamma", "D");
     jXField = getField("mX", "D");
     jYField = getField("mY", "D");
     jZField = getField("mZ", "D");
     jRectField = getField("mRect", "Landroid/graphics/Rect;");
 
     jCharactersField = getField("mCharacters", "Ljava/lang/String;");
+    jCharactersExtraField = getField("mCharactersExtra", "Ljava/lang/String;");
     jKeyCodeField = getField("mKeyCode", "I");
     jMetaStateField = getField("mMetaState", "I");
     jFlagsField = getField("mFlags", "I");
     jUnicodeCharField = getField("mUnicodeChar", "I");
     jOffsetField = getField("mOffset", "I");
     jCountField = getField("mCount", "I");
     jRangeTypeField = getField("mRangeType", "I");
     jRangeStylesField = getField("mRangeStyles", "I");
@@ -297,16 +307,32 @@ AndroidRect::InitRectClass(JNIEnv *jEnv)
     jRectClass = getClassGlobalRef("android/graphics/Rect");
 
     jBottomField = getField("bottom", "I");
     jLeftField = getField("left", "I");
     jTopField = getField("top", "I");
     jRightField = getField("right", "I");
 }
 
+void
+AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(JNIEnv *jEnv)
+{
+#ifdef MOZ_JAVA_COMPOSITOR
+    initInit();
+
+    jGeckoSoftwareLayerClientClass =
+        getClassGlobalRef("org/mozilla/gecko/gfx/GeckoSoftwareLayerClient");
+
+    jLockBufferMethod = getMethod("lockBuffer", "()Ljava/nio/ByteBuffer;");
+    jUnlockBufferMethod = getMethod("unlockBuffer", "()V");
+    jBeginDrawingMethod = getMethod("beginDrawing", "()V");
+    jEndDrawingMethod = getMethod("endDrawing", "(IIII)V");
+#endif
+}
+
 #undef initInit
 #undef initClassGlobalRef
 #undef getField
 #undef getMethod
 
 void
 AndroidGeckoEvent::ReadP0Field(JNIEnv *jenv)
 {
@@ -347,16 +373,37 @@ AndroidGeckoEvent::ReadCharactersField(J
     }
 
     int len = jenv->GetStringLength(s);
     mCharacters.SetLength(len);
     jenv->GetStringRegion(s, 0, len, mCharacters.BeginWriting());
 }
 
 void
+AndroidGeckoEvent::ReadCharactersExtraField(JNIEnv *jenv)
+{
+    jstring s = (jstring) jenv->GetObjectField(wrapped_obj, jCharactersExtraField);
+    if (!s) {
+        mCharactersExtra.SetIsVoid(PR_TRUE);
+        return;
+    }
+
+    int len = jenv->GetStringLength(s);
+    mCharactersExtra.SetLength(len);
+    jenv->GetStringRegion(s, 0, len, mCharactersExtra.BeginWriting());
+}
+
+void
+AndroidGeckoEvent::Init(int aType, nsIntRect const& aRect)
+{
+    mType = aType;
+    mRect = aRect;
+}
+
+void
 AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
 {
     NS_ASSERTION(!wrapped_obj, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 
     if (!jobj)
         return;
@@ -432,16 +479,27 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
             break;
         }
 
         case LOAD_URI: {
             ReadCharactersField(jenv);
             break;
         }
 
+        case BROADCAST: {
+            ReadCharactersField(jenv);
+            ReadCharactersExtraField(jenv);
+            break;
+        }
+
+        case SAVE_STATE: {
+            ReadCharactersField(jenv);
+            break;
+        }
+
         default:
             break;
     }
 
 #ifndef DEBUG_ANDROID_EVENTS
     ALOG("AndroidGeckoEvent: %p : %d", (void*)jobj, mType);
 #endif
 }
@@ -468,16 +526,35 @@ AndroidGeckoEvent::Init(AndroidGeckoEven
     mTime = aResizeEvent->mTime;
     mP0.x = aResizeEvent->mP0.x;
     mP0.y = aResizeEvent->mP0.y;
     mP1.x = aResizeEvent->mP1.x;
     mP1.y = aResizeEvent->mP1.y;
 }
 
 void
+AndroidPoint::Init(JNIEnv *jenv, jobject jobj)
+{
+    if (jobj) {
+        mX = jenv->GetIntField(jobj, jXField);
+        mY = jenv->GetIntField(jobj, jYField);
+    } else {
+        mX = 0;
+        mY = 0;
+    }
+}
+
+void
+AndroidGeckoSoftwareLayerClient::Init(jobject jobj)
+{
+    NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
+    wrapped_obj = jobj;
+}
+
+void
 AndroidGeckoSurfaceView::Init(jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 }
 
 int
@@ -502,16 +579,49 @@ AndroidGeckoSurfaceView::Draw2D(jobject 
 
 void
 AndroidGeckoSurfaceView::Draw2D(jobject buffer, int stride)
 {
     JNI()->CallVoidMethod(wrapped_obj, jDraw2DBufferMethod, buffer, stride);
 }
 
 jobject
+AndroidGeckoSoftwareLayerClient::LockBuffer()
+{
+    NS_ASSERTION(!isNull(), "LockBuffer() called on null software layer client!");
+    AndroidBridge::AutoLocalJNIFrame(1);
+    return JNI()->CallObjectMethod(wrapped_obj, jLockBufferMethod);
+}
+
+void
+AndroidGeckoSoftwareLayerClient::UnlockBuffer()
+{
+    NS_ASSERTION(!isNull(), "UnlockBuffer() called on null software layer client!");
+    AndroidBridge::AutoLocalJNIFrame(1);
+    JNI()->CallVoidMethod(wrapped_obj, jUnlockBufferMethod);
+}
+
+void
+AndroidGeckoSoftwareLayerClient::BeginDrawing()
+{
+    NS_ASSERTION(!isNull(), "BeginDrawing() called on null software layer client!");
+    AndroidBridge::AutoLocalJNIFrame(1);
+    return JNI()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod);
+}
+
+void
+AndroidGeckoSoftwareLayerClient::EndDrawing(const nsIntRect &aRect)
+{
+    NS_ASSERTION(!isNull(), "EndDrawing() called on null software layer client!");
+    AndroidBridge::AutoLocalJNIFrame(1);
+    return JNI()->CallVoidMethod(wrapped_obj, jEndDrawingMethod, aRect.x, aRect.y, aRect.width,
+                                 aRect.height);
+}
+
+jobject
 AndroidGeckoSurfaceView::GetSoftwareDrawBitmap()
 {
     return JNI()->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBitmapMethod);
 }
 
 jobject
 AndroidGeckoSurfaceView::GetSoftwareDrawBuffer()
 {
@@ -526,32 +636,16 @@ AndroidGeckoSurfaceView::GetSurface()
 
 jobject
 AndroidGeckoSurfaceView::GetSurfaceHolder()
 {
     return JNI()->CallObjectMethod(wrapped_obj, jGetHolderMethod);
 }
 
 void
-AndroidPoint::Init(JNIEnv *jenv, jobject jobj)
-{
-    NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
-
-    wrapped_obj = jobj;
-
-    if (jobj) {
-        mX = jenv->GetIntField(jobj, jXField);
-        mY = jenv->GetIntField(jobj, jYField);
-    } else {
-        mX = 0;
-        mY = 0;
-    }
-}
-
-void
 AndroidRect::Init(JNIEnv *jenv, jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nsnull, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 
     if (jobj) {
         mTop = jenv->GetIntField(jobj, jTopField);
--- a/widget/src/android/AndroidJavaWrappers.h
+++ b/widget/src/android/AndroidJavaWrappers.h
@@ -144,16 +144,42 @@ protected:
 
     static jclass jRectClass;
     static jfieldID jBottomField;
     static jfieldID jLeftField;
     static jfieldID jRightField;
     static jfieldID jTopField;
 };
 
+class AndroidGeckoSoftwareLayerClient : public WrappedJavaObject {
+public:
+    static void InitGeckoSoftwareLayerClientClass(JNIEnv *jEnv);
+ 
+     void Init(jobject jobj);
+ 
+    AndroidGeckoSoftwareLayerClient() {}
+    AndroidGeckoSoftwareLayerClient(jobject jobj) { Init(jobj); }
+
+    jobject LockBuffer();
+    unsigned char *LockBufferBits();
+    void UnlockBuffer();
+    void BeginDrawing();
+    void EndDrawing(const nsIntRect &aRect);
+
+private:
+    static jclass jGeckoSoftwareLayerClientClass;
+    static jmethodID jLockBufferMethod;
+    static jmethodID jUnlockBufferMethod;
+
+protected:
+     static jmethodID jBeginDrawingMethod;
+     static jmethodID jEndDrawingMethod;
+};
+
+
 class AndroidGeckoSurfaceView : public WrappedJavaObject
 {
 public:
     static void InitGeckoSurfaceViewClass(JNIEnv *jEnv);
 
     AndroidGeckoSurfaceView() { }
     AndroidGeckoSurfaceView(jobject jobj) {
         Init(jobj);
@@ -383,41 +409,46 @@ public:
 
     AndroidGeckoEvent() { }
     AndroidGeckoEvent(int aType) {
         Init(aType);
     }
     AndroidGeckoEvent(int x1, int y1, int x2, int y2) {
         Init(x1, y1, x2, y2);
     }
+    AndroidGeckoEvent(int aType, const nsIntRect &aRect) {
+        Init(aType, aRect);
+    }
     AndroidGeckoEvent(JNIEnv *jenv, jobject jobj) {
         Init(jenv, jobj);
     }
     AndroidGeckoEvent(AndroidGeckoEvent *aResizeEvent) {
         Init(aResizeEvent);
     }
 
     void Init(JNIEnv *jenv, jobject jobj);
     void Init(int aType);
     void Init(int x1, int y1, int x2, int y2);
+    void Init(int aType, const nsIntRect &aRect);
     void Init(AndroidGeckoEvent *aResizeEvent);
 
     int Action() { return mAction; }
     int Type() { return mType; }
     int64_t Time() { return mTime; }
     const nsIntPoint& P0() { return mP0; }
     const nsIntPoint& P1() { return mP1; }
     double Alpha() { return mAlpha; }
     double Beta() { return mBeta; }
     double Gamma() { return mGamma; }
     double X() { return mX; }
     double Y() { return mY; }
     double Z() { return mZ; }
     const nsIntRect& Rect() { return mRect; }
     nsAString& Characters() { return mCharacters; }
+    nsAString& CharactersExtra() { return mCharactersExtra; }
     int KeyCode() { return mKeyCode; }
     int MetaState() { return mMetaState; }
     int Flags() { return mFlags; }
     int UnicodeChar() { return mUnicodeChar; }
     int Offset() { return mOffset; }
     int Count() { return mCount; }
     int RangeType() { return mRangeType; }
     int RangeStyles() { return mRangeStyles; }
@@ -435,24 +466,25 @@ protected:
     nsIntRect mRect;
     int mFlags, mMetaState;
     int mKeyCode, mUnicodeChar;
     int mOffset, mCount;
     int mRangeType, mRangeStyles;
     int mRangeForeColor, mRangeBackColor;
     double mAlpha, mBeta, mGamma;
     double mX, mY, mZ;
-    nsString mCharacters;
+    nsString mCharacters, mCharactersExtra;
     nsRefPtr<nsGeoPosition> mGeoPosition;
     nsRefPtr<nsGeoPositionAddress> mGeoAddress;
 
     void ReadP0Field(JNIEnv *jenv);
     void ReadP1Field(JNIEnv *jenv);
     void ReadRectField(JNIEnv *jenv);
     void ReadCharactersField(JNIEnv *jenv);
+    void ReadCharactersExtraField(JNIEnv *jenv);
 
     static jclass jGeckoEventClass;
     static jfieldID jActionField;
     static jfieldID jTypeField;
     static jfieldID jTimeField;
     static jfieldID jP0Field;
     static jfieldID jP1Field;
     static jfieldID jAlphaField;
@@ -460,16 +492,17 @@ protected:
     static jfieldID jGammaField;
     static jfieldID jXField;
     static jfieldID jYField;
     static jfieldID jZField;
     static jfieldID jRectField;
     static jfieldID jNativeWindowField;
 
     static jfieldID jCharactersField;
+    static jfieldID jCharactersExtraField;
     static jfieldID jKeyCodeField;
     static jfieldID jMetaStateField;
     static jfieldID jFlagsField;
     static jfieldID jOffsetField;
     static jfieldID jCountField;
     static jfieldID jUnicodeCharField;
     static jfieldID jRangeTypeField;
     static jfieldID jRangeStylesField;
@@ -493,16 +526,18 @@ public:
         ACTIVITY_PAUSING = 10,
         ACTIVITY_SHUTDOWN = 11,
         LOAD_URI = 12,
         SURFACE_CREATED = 13,
         SURFACE_DESTROYED = 14,
         GECKO_EVENT_SYNC = 15,
         FORCED_RESIZE = 16,
         ACTIVITY_START = 17,
+        SAVE_STATE = 18,
+        BROADCAST = 19,
         dummy_java_enum_list_end
     };
 
     enum {
         IME_COMPOSITION_END = 0,
         IME_COMPOSITION_BEGIN = 1,
         IME_SET_TEXT = 2,
         IME_GET_TEXT = 3,
--- a/widget/src/android/Makefile.in
+++ b/widget/src/android/Makefile.in
@@ -39,16 +39,17 @@ DEPTH           = ../../..
 topsrcdir       = @top_srcdir@
 srcdir          = @srcdir@
 VPATH           = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE          = widget
 LIBRARY_NAME    = widget_android
+XPIDL_MODULE	= widget_android
 EXPORT_LIBRARY  = 1
 IS_COMPONENT    = 1
 MODULE_NAME     = nsWidgetAndroidModule
 GRE_MODULE      = 1
 LIBXUL_LIBRARY  = 1
 
 
 CPPSRCS	= \
@@ -73,25 +74,31 @@ NOT_THERE_YET_CPPSRCS = \
 	nsQtKeyUtils.cpp \
 	nsBidiKeyboard.cpp \
 	nsDragService.cpp \
 	nsNativeThemeQt.cpp \
 	mozqwidget.cpp \
 	nsSound.cpp \
 	$(NULL)
 
+XPIDLSRCS	= \
+	nsIAndroidBridge.idl \
+	$(NULL)
+
 SHARED_LIBRARY_LIBS = ../xpwidgets/libxpwidgets_s.a
 
 EXPORTS = AndroidBridge.h AndroidJavaWrappers.h
 
 include $(topsrcdir)/config/rules.mk
 
 DEFINES += -D_IMPL_NS_WIDGET
 #DEFINES += -DDEBUG_WIDGETS
 
 LOCAL_INCLUDES += \
 	-I$(topsrcdir)/widget/src/xpwidgets \
 	-I$(topsrcdir)/widget/src/shared \
 	-I$(topsrcdir)/dom/system/android \
+	-I$(topsrcdir)/toolkit/components/places \
+	-I$(topsrcdir)/docshell/base \
 	-I$(srcdir) \
 	$(NULL)
 
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
--- a/widget/src/android/nsAppShell.cpp
+++ b/widget/src/android/nsAppShell.cpp
@@ -363,22 +363,40 @@ nsAppShell::ProcessNextNativeEvent(bool 
     case AndroidGeckoEvent::ACTIVITY_START: {
         nsCOMPtr<nsIObserverService> obsServ =
             mozilla::services::GetObserverService();
         obsServ->NotifyObservers(nsnull, "application-foreground", nsnull);
 
         break;
     }
 
+    case AndroidGeckoEvent::BROADCAST: {
+
+        if (curEvent->Characters().Length() == 0)
+            break;
+
+        nsCOMPtr<nsIObserverService> obsServ =
+            mozilla::services::GetObserverService();
+
+        const NS_ConvertUTF16toUTF8 topic(curEvent->Characters());
+        const nsPromiseFlatString& data = PromiseFlatString(curEvent->CharactersExtra());
+
+        obsServ->NotifyObservers(nsnull, topic.get(), data.get());
+        break;
+    }
+
     case AndroidGeckoEvent::LOAD_URI: {
         nsCOMPtr<nsICommandLineRunner> cmdline
             (do_CreateInstance("@mozilla.org/toolkit/command-line;1"));
         if (!cmdline)
             break;
 
+        if (curEvent->Characters().Length() == 0)
+            break;
+
         char *uri = ToNewUTF8String(curEvent->Characters());
         if (!uri)
             break;
 
         const char *argv[3] = {
             "dummyappname",
             "-remote",
             uri
new file mode 100644
--- /dev/null
+++ b/widget/src/android/nsIAndroidBridge.idl
@@ -0,0 +1,7 @@
+#include "nsISupports.idl"
+
+[scriptable, uuid(32c345d4-9f45-446a-8a93-8939f3453e87)]
+interface nsIAndroidBridge : nsISupports
+{
+  AString handleGeckoMessage(in AString message);
+};
--- a/widget/src/android/nsWidgetFactory.cpp
+++ b/widget/src/android/nsWidgetFactory.cpp
@@ -36,16 +36,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "mozilla/ModuleUtils.h"
 
 #include "nsCOMPtr.h"
 #include "nsWidgetsCID.h"
 #include "nsAppShell.h"
+#include "AndroidBridge.h"
 
 #include "nsWindow.h"
 #include "nsLookAndFeel.h"
 #include "nsAppShellSingleton.h"
 #include "nsScreenManagerAndroid.h"
 
 #include "nsIdleServiceAndroid.h"
 #include "nsClipboard.h"
@@ -66,16 +67,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleSer
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintOptionsAndroid, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintSession, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecAndroid)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsIMEPicker)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsAndroidBridge)
 
 #include "GfxInfo.h"
 namespace mozilla {
 namespace widget {
 // This constructor should really be shared with all platforms.
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init)
 }
 }
@@ -108,16 +110,17 @@ NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
 NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID);
 NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID);
 NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
 NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
 NS_DEFINE_NAMED_CID(NS_IMEPICKER_CID);
 NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
+NS_DEFINE_NAMED_CID(NS_ANDROIDBRIDGE_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
   { &kNS_WINDOW_CID, false, NULL, nsWindowConstructor },
   { &kNS_CHILD_CID, false, NULL, nsWindowConstructor },
   { &kNS_APPSHELL_CID, false, NULL, nsAppShellConstructor },
   { &kNS_SCREENMANAGER_CID, false, NULL, nsScreenManagerAndroidConstructor },
   { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceAndroidConstructor },
   { &kNS_TRANSFERABLE_CID, false, NULL, nsTransferableConstructor },
@@ -125,16 +128,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor },
   { &kNS_PRINTSETTINGSSERVICE_CID, false, NULL, nsPrintOptionsAndroidConstructor },
   { &kNS_PRINTSESSION_CID, false, NULL, nsPrintSessionConstructor },
   { &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecAndroidConstructor },
   { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor },
   { &kNS_HTMLFORMATCONVERTER_CID, false, NULL, nsHTMLFormatConverterConstructor },
   { &kNS_IMEPICKER_CID, false, NULL, nsIMEPickerConstructor },
   { &kNS_GFXINFO_CID, false, NULL, mozilla::widget::GfxInfoConstructor },
+  { &kNS_ANDROIDBRIDGE_CID, false, NULL, nsAndroidBridgeConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
   { "@mozilla.org/widgets/window/android;1", &kNS_WINDOW_CID },
   { "@mozilla.org/widgets/child_window/android;1", &kNS_CHILD_CID },
   { "@mozilla.org/widget/appshell/android;1", &kNS_APPSHELL_CID },
   { "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID },
@@ -144,16 +148,17 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
   { "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
   { "@mozilla.org/gfx/printsession;1", &kNS_PRINTSESSION_CID },
   { "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
   { "@mozilla.org/filepicker;1", &kNS_FILEPICKER_CID },
   { "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
   { "@mozilla.org/imepicker;1", &kNS_IMEPICKER_CID },
   { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
+  { "@mozilla.org/android/bridge;1", &kNS_ANDROIDBRIDGE_CID },
   { NULL }
 };
 
 static void
 nsWidgetAndroidModuleDtor()
 {
     nsLookAndFeel::Shutdown();
     nsAppShellShutdown();
--- a/widget/src/android/nsWindow.cpp
+++ b/widget/src/android/nsWindow.cpp
@@ -70,24 +70,36 @@ using mozilla::unused;
 #include "LayerManagerOGL.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 
 #include "nsTArray.h"
 
 #include "AndroidBridge.h"
 
+#include "imgIEncoder.h"
+
+#include "nsStringGlue.h"
+
+// NB: Keep these in sync with LayerController.java in embedding/android/.
+#define TILE_WIDTH      1024
+#define TILE_HEIGHT     2048
+
 using namespace mozilla;
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
 
 // The dimensions of the current android view
 static gfxIntSize gAndroidBounds;
 static gfxIntSize gAndroidScreenBounds;
 
+#ifdef ACCESSIBILITY
+bool nsWindow::sAccessibilityEnabled = false;
+#endif
+
 class ContentCreationNotifier;
 static nsCOMPtr<ContentCreationNotifier> gContentCreationNotifier;
 // A helper class to send updates when content processes
 // are created. Currently an update for the screen size is sent.
 class ContentCreationNotifier : public nsIObserver
 {
     NS_DECL_ISUPPORTS
 
@@ -171,26 +183,33 @@ nsWindow::DumpWindows(const nsTArray<nsW
         DumpWindows(w->mChildren, indent+1);
     }
 }
 
 nsWindow::nsWindow() :
     mIsVisible(false),
     mParent(nsnull),
     mFocus(nsnull),
+#ifdef ACCESSIBILITY
+    mRootAccessible(nsnull),
+#endif
     mIMEComposing(false)
 {
 }
 
 nsWindow::~nsWindow()
 {
     gTopLevelWindows.RemoveElement(this);
     nsWindow *top = FindTopLevel();
     if (top->mFocus == this)
         top->mFocus = nsnull;
+#ifdef ACCESSIBILITY
+    if (mRootAccessible)
+        mRootAccessible = nsnull;
+#endif
     ALOG("nsWindow %p destructor", (void*)this);
 }
 
 bool
 nsWindow::IsTopLevel()
 {
     return mWindowType == eWindowType_toplevel ||
         mWindowType == eWindowType_dialog ||
@@ -278,16 +297,25 @@ nsWindow::ConfigureChildren(const nsTArr
                          config[i].mBounds.width,
                          config[i].mBounds.height,
                          false);
     }
 
     return NS_OK;
 }
 
+void
+nsWindow::RedrawAll()
+{
+    nsIntRect entireRect(0, 0, TILE_WIDTH, TILE_HEIGHT);
+    AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW,
+                                                     entireRect);
+    nsAppShell::gAppShell->PostEvent(event);
+}
+
 NS_IMETHODIMP
 nsWindow::SetParent(nsIWidget *aNewParent)
 {
     if ((nsIWidget*)mParent == aNewParent)
         return NS_OK;
 
     // If we had a parent before, remove ourselves from its list of
     // children.  If we didn't have a parent, then remove ourselves
@@ -298,17 +326,17 @@ nsWindow::SetParent(nsIWidget *aNewParen
 
     mParent = (nsWindow*)aNewParent;
 
     if (mParent)
         mParent->mChildren.AppendElement(this);
 
     // if we are now in the toplevel window's hierarchy, schedule a redraw
     if (FindTopLevel() == TopWindow())
-        nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
+        RedrawAll();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::ReparentNativeWidget(nsIWidget *aNewParent)
 {
     NS_PRECONDITION(aNewParent, "");
@@ -366,26 +394,63 @@ nsWindow::Show(bool aState)
                 if (!win->mIsVisible)
                     continue;
 
                 win->BringToFront();
                 break;
             }
         }
     } else if (FindTopLevel() == TopWindow()) {
-        nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
+        RedrawAll();
     }
 
+#ifdef ACCESSIBILITY
+    static bool sAccessibilityChecked = false;
+    if (!sAccessibilityChecked) {
+        sAccessibilityChecked = true;
+        sAccessibilityEnabled =
+            AndroidBridge::Bridge()->GetAccessibilityEnabled();
+     } 
+    if (aState && sAccessibilityEnabled)
+        CreateRootAccessible();
+#endif
+
 #ifdef DEBUG_ANDROID_WIDGET
     DumpWindows();
 #endif
 
     return NS_OK;
 }
 
+#ifdef ACCESSIBILITY
+void
+nsWindow::CreateRootAccessible()
+{
+    if (IsTopLevel() && !mRootAccessible) {
+        ALOG(("nsWindow:: Create Toplevel Accessibility\n"));
+        nsAccessible *acc = DispatchAccessibleEvent();
+
+        if (acc) {
+            mRootAccessible = acc;
+        }
+    }
+}
+
+nsAccessible*
+nsWindow::DispatchAccessibleEvent()
+{
+    nsAccessibleEvent event(true, NS_GETACCESSIBLE, this);
+
+    nsEventStatus status;
+    DispatchEvent(&event, status);
+
+    return event.mAccessible;
+}
+#endif
+
 NS_IMETHODIMP
 nsWindow::SetModal(bool aState)
 {
     ALOG("nsWindow[%p]::SetModal %d ignored", (void*)this, aState);
 
     return NS_OK;
 }
 
@@ -454,17 +519,17 @@ nsWindow::Resize(PRInt32 aX,
     mBounds.width = aWidth;
     mBounds.height = aHeight;
 
     if (needSizeDispatch)
         OnSizeChanged(gfxIntSize(aWidth, aHeight));
 
     // Should we skip honoring aRepaint here?
     if (aRepaint && FindTopLevel() == TopWindow())
-        nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
+        RedrawAll();
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::SetZIndex(PRInt32 aZIndex)
 {
     ALOG("nsWindow[%p]::SetZIndex %d ignored", (void*)this, aZIndex);
@@ -507,17 +572,18 @@ nsWindow::IsEnabled(bool *aState)
     *aState = true;
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::Invalidate(const nsIntRect &aRect,
                      bool aIsSynchronous)
 {
-    nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
+    AndroidGeckoEvent *event = new AndroidGeckoEvent(AndroidGeckoEvent::DRAW, aRect);
+    nsAppShell::gAppShell->PostEvent(event);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::Update()
 {
     return NS_OK;
 }
@@ -583,17 +649,17 @@ nsWindow::BringToFront()
         DispatchEvent(&event);
     }
 
     nsGUIEvent event(true, NS_ACTIVATE, this);
     DispatchEvent(&event);
 
     // force a window resize
     nsAppShell::gAppShell->ResendLastResizeEvent(this);
-    nsAppShell::gAppShell->PostEvent(new AndroidGeckoEvent(-1, -1, -1, -1));
+    RedrawAll();
 }
 
 NS_IMETHODIMP
 nsWindow::GetScreenBounds(nsIntRect &aRect)
 {
     nsIntPoint p = WidgetToScreenOffset();
 
     aRect.x = p.x;
@@ -725,16 +791,76 @@ nsWindow::GetThebesSurface()
      * we need a RenderingContext to measure text against.
      */
 
     // XXX this really wants to return already_AddRefed, but this only really gets used
     // on direct assignment to a gfxASurface
     return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24);
 }
 
+bool
+nsWindow::DrawToFile(const nsAString &path)
+{
+    if (!IsTopLevel() || !mIsVisible) {
+        ALOG("### DrawToFile works only for a visible toplevel window!");
+        return PR_FALSE;
+    }
+
+    if (GetLayerManager(nsnull)->GetBackendType() != LayerManager::LAYERS_BASIC) {
+        ALOG("### DrawToFile works only for a basic layers!");
+        return PR_FALSE;
+    }
+
+    nsRefPtr<gfxImageSurface> imgSurface =
+        new gfxImageSurface(gfxIntSize(mBounds.width, mBounds.height),
+                            gfxImageSurface::ImageFormatARGB32);
+    
+    if (imgSurface->CairoStatus()) {
+        ALOG("### Failed to create a valid surface");
+        return PR_FALSE;
+    }
+
+    nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height);
+    bool result = DrawTo(imgSurface, boundsRect);
+    NS_ENSURE_TRUE(result, PR_FALSE);
+
+    nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/png");
+    NS_ENSURE_TRUE(encoder, PR_FALSE);
+
+    encoder->InitFromData(imgSurface->Data(),
+                          imgSurface->Stride() * mBounds.height,
+                          mBounds.width,
+                          mBounds.height,
+                          imgSurface->Stride(),
+                          imgIEncoder::INPUT_FORMAT_HOSTARGB,
+                          EmptyString());
+
+    nsCOMPtr<nsILocalFile> file;
+    NS_NewLocalFile(path, true, getter_AddRefs(file));
+    NS_ENSURE_TRUE(file, PR_FALSE);
+
+    PRUint32 length;
+    encoder->Available(&length);
+
+    nsCOMPtr<nsIOutputStream> outputStream;
+    NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file);
+    NS_ENSURE_TRUE(outputStream, PR_FALSE);
+
+    nsCOMPtr<nsIOutputStream> bufferedOutputStream;
+    NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
+                               outputStream, length);
+    NS_ENSURE_TRUE(bufferedOutputStream, PR_FALSE);
+
+    PRUint32 numWritten;
+    bufferedOutputStream->WriteFrom(encoder, length, &numWritten);
+    NS_ENSURE_SUCCESS(length == numWritten, PR_FALSE);
+
+    return PR_TRUE;
+}
+
 void
 nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
 {
     if (!AndroidBridge::Bridge())
         return;
 
     nsWindow *win = TopWindow();
     if (!win)
@@ -877,16 +1003,20 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe
             sSurfaceExists = false;
             sValidSurface = false;
             break;
 
         case AndroidGeckoEvent::GECKO_EVENT_SYNC:
             AndroidBridge::Bridge()->AcknowledgeEventSync();
             break;
 
+        case AndroidGeckoEvent::SAVE_STATE:
+            win->DrawToFile(ae->Characters());
+            break;
+
         default:
             break;
     }
 }
 
 void
 nsWindow::OnAndroidEvent(AndroidGeckoEvent *ae)
 {
@@ -902,16 +1032,23 @@ nsWindow::OnAndroidEvent(AndroidGeckoEve
             ALOG("Window got targetted android event type %d, but didn't handle!", ae->Type());
             break;
     }
 }
 
 bool
 nsWindow::DrawTo(gfxASurface *targetSurface)
 {
+    nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height);
+    return DrawTo(targetSurface, boundsRect);
+}
+
+bool
+nsWindow::DrawTo(gfxASurface *targetSurface, const nsIntRect &invalidRect)
+{
     if (!mIsVisible)
         return false;
 
     nsEventStatus status;
     nsIntRect boundsRect(0, 0, mBounds.width, mBounds.height);
 
     // Figure out if any of our children cover this widget completely
     PRInt32 coveringChildIndex = -1;
@@ -922,17 +1059,17 @@ nsWindow::DrawTo(gfxASurface *targetSurf
         if (mChildren[i]->mBounds.Contains(boundsRect)) {
             coveringChildIndex = PRInt32(i);
         }
     }
 
     // If we have no covering child, then we need to render this.
     if (coveringChildIndex == -1) {
         nsPaintEvent event(true, NS_PAINT, this);
-        event.region = boundsRect;
+        event.region = boundsRect.Intersect(invalidRect);
         switch (GetLayerManager(nsnull)->GetBackendType()) {
             case LayerManager::LAYERS_BASIC: {
                 nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
 
                 {
                     AutoLayerManagerSetup
                       setupLayerManager(this, ctx, BasicLayerManager::BUFFER_NONE);
                     status = DispatchEvent(&event);
@@ -977,33 +1114,32 @@ nsWindow::DrawTo(gfxASurface *targetSurf
             !mChildren[i]->mBounds.Intersects(boundsRect)) {
             continue;
         }
 
         if (targetSurface)
             targetSurface->SetDeviceOffset(offset + gfxPoint(mChildren[i]->mBounds.x,
                                                              mChildren[i]->mBounds.y));
 
-        bool ok = mChildren[i]->DrawTo(targetSurface);
+        bool ok = mChildren[i]->DrawTo(targetSurface, invalidRect);
 
         if (!ok) {
             ALOG("nsWindow[%p]::DrawTo child %d[%p] returned FALSE!", (void*) this, i, (void*)mChildren[i]);
         }
     }
 
     if (targetSurface)
         targetSurface->SetDeviceOffset(offset);
 
     return true;
 }
 
 void
 nsWindow::OnDraw(AndroidGeckoEvent *ae)
 {
-  
     if (!sSurfaceExists) {
         return;
     }
 
     if (!IsTopLevel()) {
         ALOG("##### redraw for window %p, which is not a toplevel window -- sending to toplevel!", (void*) this);
         DumpWindows();
         return;
@@ -1011,16 +1147,33 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
 
     if (!mIsVisible) {
         ALOG("##### redraw for window %p, which is not visible -- ignoring!", (void*) this);
         DumpWindows();
         return;
     }
 
     AndroidBridge::AutoLocalJNIFrame jniFrame;
+#ifdef MOZ_JAVA_COMPOSITOR
+    AndroidGeckoSoftwareLayerClient &client =
+        AndroidBridge::Bridge()->GetSoftwareLayerClient();
+    client.BeginDrawing();
+    unsigned char *bits = client.LockBufferBits();
+    nsRefPtr<gfxImageSurface> targetSurface =
+        new gfxImageSurface(bits, gfxIntSize(TILE_WIDTH, TILE_HEIGHT), TILE_WIDTH * 2,
+                            gfxASurface::ImageFormatRGB16_565);
+    if (targetSurface->CairoStatus()) {
+        ALOG("### Failed to create a valid surface from the bitmap");
+    } else {
+        DrawTo(targetSurface, ae->Rect());
+        client.UnlockBuffer();
+        client.EndDrawing(ae->Rect());
+    }
+        return;
+#endif
 
     AndroidGeckoSurfaceView& sview(AndroidBridge::Bridge()->SurfaceView());
 
     NS_ASSERTION(!sview.isNull(), "SurfaceView is null!");
 
     AndroidBridge::Bridge()->HideProgressDialogOnce();
 
     if (GetLayerManager(nsnull)->GetBackendType() == LayerManager::LAYERS_BASIC) {
--- a/widget/src/android/nsWindow.h
+++ b/widget/src/android/nsWindow.h
@@ -38,16 +38,20 @@
 #ifndef NSWINDOW_H_
 #define NSWINDOW_H_
 
 #include "nsBaseWidget.h"
 #include "gfxPoint.h"
 
 #include "nsTArray.h"
 
+#ifdef ACCESSIBILITY
+#include "nsAccessible.h"
+#endif
+
 class gfxASurface;
 class nsIdleService;
 
 namespace mozilla {
     class AndroidGeckoEvent;
     class AndroidKeyEvent;
 }
 
@@ -162,20 +166,27 @@ public:
 
     LayerManager* GetLayerManager (PLayersChild* aShadowManager = nsnull, 
                                    LayersBackend aBackendHint = LayerManager::LAYERS_NONE, 
                                    LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT, 
                                    bool* aAllowRetaining = nsnull);
     gfxASurface* GetThebesSurface();
 
     NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
+
+#ifdef ACCESSIBILITY
+    static bool sAccessibilityEnabled;
+#endif
+
 protected:
     void BringToFront();
     nsWindow *FindTopLevel();
     bool DrawTo(gfxASurface *targetSurface);
+    bool DrawTo(gfxASurface *targetSurface, const nsIntRect &aRect);
+    bool DrawToFile(const nsAString &path);
     bool IsTopLevel();
     void OnIMEAddRange(mozilla::AndroidGeckoEvent *ae);
 
     // Call this function when the users activity is the direct cause of an
     // event (like a keypress or mouse click).
     void UserActivity();
 
     bool mIsVisible;
@@ -206,11 +217,27 @@ protected:
     static void LogWindow(nsWindow *win, int index, int indent);
 
 private:
     void InitKeyEvent(nsKeyEvent& event, mozilla::AndroidGeckoEvent& key);
     void DispatchGestureEvent(mozilla::AndroidGeckoEvent *ae);
     void DispatchGestureEvent(PRUint32 msg, PRUint32 direction, double delta,
                                const nsIntPoint &refPoint, PRUint64 time);
     void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae);
+    void RedrawAll();
+
+#ifdef ACCESSIBILITY
+    nsRefPtr<nsAccessible> mRootAccessible;
+
+    /**
+     * Request to create the accessible for this window if it is top level.
+     */
+    void CreateRootAccessible();
+
+    /**
+     * Generate the NS_GETACCESSIBLE event to get accessible for this window
+     * and return it.
+     */
+    nsAccessible *DispatchAccessibleEvent();
+#endif // ACCESSIBILITY
 };
 
 #endif /* NSWINDOW_H_ */