Bug 913985 - Part 5: refactor the Bridge to use the generated code. r=kats
☠☠ backed out by 0201aa7eaf5c ☠ ☠
authorChris Kitching <chriskitching@linux.com>
Tue, 12 Nov 2013 10:41:01 -0800
changeset 171878 d23d1e678417529b5f485e23043a487b50dd28ae
parent 171877 a9c9187b4f4aa3bd151df81a3eedbde26a7f2db4
child 171879 53513a959cf0288dd256259e4e7170627bea328d
push idunknown
push userunknown
push dateunknown
reviewerskats
bugs913985
milestone28.0a1
Bug 913985 - Part 5: refactor the Bridge to use the generated code. r=kats
dom/ipc/ContentParent.cpp
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/system/android/AndroidLocationProvider.cpp
dom/system/android/nsHapticFeedback.cpp
gfx/gl/GLContext.h
gfx/thebes/nsSurfaceTexture.cpp
hal/android/AndroidHal.cpp
hal/android/AndroidSensor.cpp
ipc/glue/MessagePump.cpp
mobile/android/components/build/nsAndroidHistory.cpp
mobile/android/components/build/nsShellService.cpp
netwerk/base/src/Tickler.cpp
netwerk/protocol/device/CameraStreamImpl.cpp
netwerk/system/android/nsAndroidNetworkLinkService.cpp
toolkit/components/alerts/nsAlertsService.cpp
toolkit/components/downloads/nsDownloadManager.cpp
toolkit/components/jsdownloads/src/DownloadPlatform.cpp
toolkit/xre/nsAndroidStartup.cpp
toolkit/xre/nsAppRunner.cpp
tools/profiler/TableTicker.cpp
tools/profiler/platform.cpp
uriloader/exthandler/android/nsAndroidHandlerApp.cpp
uriloader/exthandler/android/nsExternalSharingAppService.cpp
uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
widget/android/AndroidBridge.cpp
widget/android/AndroidBridge.h
widget/android/AndroidBridgeUtilities.h
widget/android/AndroidJNI.cpp
widget/android/AndroidJNIWrapper.cpp
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
widget/android/nsAppShell.cpp
widget/android/nsClipboard.cpp
widget/android/nsIMEPicker.cpp
widget/android/nsLookAndFeel.cpp
widget/android/nsScreenManagerAndroid.cpp
widget/android/nsWindow.cpp
widget/android/nsWindow.h
xpcom/base/nsSystemInfo.cpp
xpcom/components/ManifestParser.cpp
xpcom/io/nsLocalFileUnix.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1786,17 +1786,17 @@ ContentParent::RecvGetIconForExtension(c
 bool
 ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
 {
     // default behavior is to show the last password character
     *showPassword = true;
 #ifdef MOZ_WIDGET_ANDROID
     NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available");
     if (AndroidBridge::Bridge() != nullptr)
-        *showPassword = AndroidBridge::Bridge()->GetShowPasswordSetting();
+        *showPassword = GeckoAppShell::GetShowPasswordSetting();
 #endif
     return true;
 }
 
 bool
 ContentParent::RecvFirstIdle()
 {
 #ifdef MOZ_NUWA_PROCESS
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -2257,21 +2257,17 @@ NPError NP_CALLBACK
     case kSupportedDrawingModel_ANPGetValue: {
       LOG("get supported drawing model");
       uint32_t* bits = reinterpret_cast<uint32_t*>(result);
       *bits = kBitmap_ANPDrawingModel && kSurface_ANPDrawingModel;
       return NPERR_NO_ERROR;
     }  
 
     case kJavaContext_ANPGetValue: {
-      AndroidBridge *bridge = AndroidBridge::Bridge();
-      if (!bridge)
-        return NPERR_GENERIC_ERROR;
-
-      jobject ret = bridge->GetContext();
+      jobject ret = GeckoAppShell::GetContext();
       if (!ret)
         return NPERR_GENERIC_ERROR;
 
       int32_t* i  = reinterpret_cast<int32_t*>(result);
       *i = reinterpret_cast<int32_t>(ret);
       return NPERR_NO_ERROR;
     }
 
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -863,17 +863,17 @@ void nsNPAPIPluginInstance::NotifyFullSc
 
   if (RUNNING != mRunning || mFullScreen == aFullScreen)
     return;
 
   mFullScreen = aFullScreen;
   SendLifecycleEvent(this, mFullScreen ? kEnterFullScreen_ANPLifecycleAction : kExitFullScreen_ANPLifecycleAction);
 
   if (mFullScreen && mFullScreenOrientation != dom::eScreenOrientation_None) {
-    AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation);
+    GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
   }
 }
 
 void nsNPAPIPluginInstance::NotifySize(nsIntSize size)
 {
   if (kOpenGL_ANPDrawingModel != GetANPDrawingModel() ||
       size == mCurrentSize)
     return;
@@ -920,21 +920,21 @@ void nsNPAPIPluginInstance::SetFullScree
 
   uint32_t oldOrientation = mFullScreenOrientation;
   mFullScreenOrientation = orientation;
 
   if (mFullScreen) {
     // We're already fullscreen so immediately apply the orientation change
 
     if (mFullScreenOrientation != dom::eScreenOrientation_None) {
-      AndroidBridge::Bridge()->LockScreenOrientation(mFullScreenOrientation);
+      GeckoAppShell::LockScreenOrientation(mFullScreenOrientation);
     } else if (oldOrientation != dom::eScreenOrientation_None) {
       // We applied an orientation when we entered fullscreen, but
       // we don't want it anymore
-      AndroidBridge::Bridge()->UnlockScreenOrientation();
+      GeckoAppShell::UnlockScreenOrientation();
     }
   }
 }
 
 void nsNPAPIPluginInstance::PopPostedEvent(PluginEventRunnable* r)
 {
   mPostedEvents.RemoveElement(r);
 }
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -1667,19 +1667,17 @@ bool nsPluginInstanceOwner::AddPluginVie
   return true;
 }
 
 void nsPluginInstanceOwner::RemovePluginView()
 {
   if (!mInstance || !mJavaView)
     return;
 
-  if (AndroidBridge::Bridge())
-    AndroidBridge::Bridge()->RemovePluginView((jobject)mJavaView, mFullScreen);
-
+  GeckoAppShell::RemovePluginView((jobject)mJavaView, mFullScreen);
   AndroidBridge::GetJNIEnv()->DeleteGlobalRef((jobject)mJavaView);
   mJavaView = nullptr;
 
   if (mFullScreen)
     sFullScreenInstance = nullptr;
 }
 
 void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos)
--- a/dom/system/android/AndroidLocationProvider.cpp
+++ b/dom/system/android/AndroidLocationProvider.cpp
@@ -23,17 +23,17 @@ AndroidLocationProvider::~AndroidLocatio
     NS_IF_RELEASE(gLocationCallback);
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::Startup()
 {
     if (!AndroidBridge::Bridge())
         return NS_ERROR_NOT_IMPLEMENTED;
-    AndroidBridge::Bridge()->EnableLocation(true);
+    GeckoAppShell::EnableLocation(true);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::Watch(nsIGeolocationUpdate* aCallback)
 {
     NS_IF_RELEASE(gLocationCallback);
     gLocationCallback = aCallback;
@@ -41,20 +41,20 @@ AndroidLocationProvider::Watch(nsIGeoloc
     return NS_OK;
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::Shutdown()
 {
     if (!AndroidBridge::Bridge())
         return NS_ERROR_NOT_IMPLEMENTED;
-    AndroidBridge::Bridge()->EnableLocation(false);
+    GeckoAppShell::EnableLocation(false);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 AndroidLocationProvider::SetHighAccuracy(bool enable)
 {
     if (!AndroidBridge::Bridge())
         return NS_ERROR_NOT_IMPLEMENTED;
-    AndroidBridge::Bridge()->EnableLocationHighAccuracy(enable);
+    GeckoAppShell::EnableLocationHighAccuracy(enable);
     return NS_OK;
 }
--- a/dom/system/android/nsHapticFeedback.cpp
+++ b/dom/system/android/nsHapticFeedback.cpp
@@ -11,13 +11,13 @@ using namespace mozilla;
 
 NS_IMPL_ISUPPORTS1(nsHapticFeedback, nsIHapticFeedback)
 
 NS_IMETHODIMP
 nsHapticFeedback::PerformSimpleAction(int32_t aType)
 {
     AndroidBridge* bridge = AndroidBridge::Bridge();
     if (bridge) {
-        bridge->PerformHapticFeedback(aType == LongPress);
+        GeckoAppShell::PerformHapticFeedback(aType == LongPress);
         return NS_OK;
     }
     return NS_ERROR_FAILURE;
 }
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -2510,17 +2510,17 @@ public:
     virtual bool UnbindExternalBuffer(GLuint texture) { return false; }
 
 #ifdef MOZ_WIDGET_GONK
     virtual EGLImage CreateEGLImageForNativeBuffer(void* buffer) = 0;
     virtual void DestroyEGLImage(EGLImage image) = 0;
 #endif
 
     virtual already_AddRefed<TextureImage>
-    CreateDirectTextureImage(android::GraphicBuffer* aBuffer, GLenum aWrapMode)
+    CreateDirectTextureImage(::android::GraphicBuffer* aBuffer, GLenum aWrapMode)
     { return nullptr; }
 
     // Before reads from offscreen texture
     void GuaranteeResolve();
 
 protected:
     GLuint mTexBlit_Buffer;
     GLuint mTexBlit_VertShader;
--- a/gfx/thebes/nsSurfaceTexture.cpp
+++ b/gfx/thebes/nsSurfaceTexture.cpp
@@ -205,17 +205,17 @@ nsSurfaceTexture::~nsSurfaceTexture()
     mNativeWindow = nullptr;
   }
 
   JNIEnv* env = GetJNIForThread();
   if (!env)
     return;
 
   if (mSurfaceTexture && env) {
-    AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
+    GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
 
     env->DeleteGlobalRef(mSurfaceTexture);
     mSurfaceTexture = nullptr;
   }
 }
 
 void*
 nsSurfaceTexture::GetNativeWindow()
@@ -234,19 +234,19 @@ nsSurfaceTexture::GetTransformMatrix(gfx
 {
   return sJNIFunctions.GetTransformMatrix(mSurfaceTexture, aMatrix);
 }
 
 void
 nsSurfaceTexture::SetFrameAvailableCallback(nsIRunnable* aRunnable)
 {
   if (aRunnable)
-    AndroidBridge::Bridge()->RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
+    GeckoAppShell::RegisterSurfaceTextureFrameListener(mSurfaceTexture, mID);
   else
-    AndroidBridge::Bridge()->UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
+    GeckoAppShell::UnregisterSurfaceTextureFrameListener(mSurfaceTexture);
 
   mFrameAvailableCallback = aRunnable;
 }
 
 void
 nsSurfaceTexture::NotifyFrameAvailable()
 {
   if (mFrameAvailableCallback) {
--- a/hal/android/AndroidHal.cpp
+++ b/hal/android/AndroidHal.cpp
@@ -9,16 +9,17 @@
 #include "AndroidBridge.h"
 #include "mozilla/dom/network/Constants.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "nsIScreenManager.h"
 #include "nsServiceManagerUtils.h"
 
 using namespace mozilla::dom;
 using namespace mozilla::hal;
+using namespace mozilla::widget::android;
 
 namespace mozilla {
 namespace hal_impl {
 
 void
 Vibrate(const nsTArray<uint32_t> &pattern, const WindowIdentifier &)
 {
   // Ignore the WindowIdentifier parameter; it's here only because hal::Vibrate,
@@ -49,107 +50,65 @@ Vibrate(const nsTArray<uint32_t> &patter
   b->Vibrate(pattern);
 }
 
 void
 CancelVibrate(const WindowIdentifier &)
 {
   // Ignore WindowIdentifier parameter.
 
-  AndroidBridge* b = AndroidBridge::Bridge();
-  if (b)
-    b->CancelVibrate();
+  GeckoAppShell::CancelVibrate();
 }
 
 void
 EnableBatteryNotifications()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->EnableBatteryNotifications();
+  GeckoAppShell::EnableBatteryNotifications();
 }
 
 void
 DisableBatteryNotifications()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->DisableBatteryNotifications();
+  GeckoAppShell::DisableBatteryNotifications();
 }
 
 void
 GetCurrentBatteryInformation(hal::BatteryInformation* aBatteryInfo)
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->GetCurrentBatteryInformation(aBatteryInfo);
+  AndroidBridge::Bridge()->GetCurrentBatteryInformation(aBatteryInfo);
 }
 
 void
 EnableNetworkNotifications()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->EnableNetworkNotifications();
+  GeckoAppShell::EnableNetworkNotifications();
 }
 
 void
 DisableNetworkNotifications()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->DisableNetworkNotifications();
+  GeckoAppShell::DisableNetworkNotifications();
 }
 
 void
 GetCurrentNetworkInformation(hal::NetworkInformation* aNetworkInfo)
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->GetCurrentNetworkInformation(aNetworkInfo);
+  AndroidBridge::Bridge()->GetCurrentNetworkInformation(aNetworkInfo);
 }
 
 void
 EnableScreenConfigurationNotifications()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->EnableScreenOrientationNotifications();
+  GeckoAppShell::EnableScreenOrientationNotifications();
 }
 
 void
 DisableScreenConfigurationNotifications()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->DisableScreenOrientationNotifications();
+  GeckoAppShell::DisableScreenOrientationNotifications();
 }
 
 void
 GetCurrentScreenConfiguration(ScreenConfiguration* aScreenConfiguration)
 {
   AndroidBridge* bridge = AndroidBridge::Bridge();
   if (!bridge) {
     return;
@@ -176,43 +135,37 @@ GetCurrentScreenConfiguration(ScreenConf
 
   *aScreenConfiguration =
     hal::ScreenConfiguration(rect, orientation, colorDepth, pixelDepth);
 }
 
 bool
 LockScreenOrientation(const ScreenOrientation& aOrientation)
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
+  if (!AndroidBridge::Bridge()) {
     return false;
   }
 
   switch (aOrientation) {
     // The Android backend only supports these orientations.
     case eScreenOrientation_PortraitPrimary:
     case eScreenOrientation_PortraitSecondary:
     case eScreenOrientation_PortraitPrimary | eScreenOrientation_PortraitSecondary:
     case eScreenOrientation_LandscapePrimary:
     case eScreenOrientation_LandscapeSecondary:
     case eScreenOrientation_LandscapePrimary | eScreenOrientation_LandscapeSecondary:
     case eScreenOrientation_Default:
-      bridge->LockScreenOrientation(aOrientation);
+      GeckoAppShell::LockScreenOrientation(aOrientation);
       return true;
     default:
       return false;
   }
 }
 
 void
 UnlockScreenOrientation()
 {
-  AndroidBridge* bridge = AndroidBridge::Bridge();
-  if (!bridge) {
-    return;
-  }
-
-  bridge->UnlockScreenOrientation();
+  GeckoAppShell::UnlockScreenOrientation();
 }
 
 } // hal_impl
 } // mozilla
 
--- a/hal/android/AndroidSensor.cpp
+++ b/hal/android/AndroidSensor.cpp
@@ -8,18 +8,18 @@
 
 using namespace mozilla::hal;
 
 namespace mozilla {
 namespace hal_impl {
 
 void
 EnableSensorNotifications(SensorType aSensor) {
-  AndroidBridge::Bridge()->EnableSensor(aSensor);
+  GeckoAppShell::EnableSensor(aSensor);
 }
 
 void
 DisableSensorNotifications(SensorType aSensor) {
-  AndroidBridge::Bridge()->DisableSensor(aSensor);
+  GeckoAppShell::DisableSensor(aSensor);
 }
 
 } // hal_impl
 } // mozilla
--- a/ipc/glue/MessagePump.cpp
+++ b/ipc/glue/MessagePump.cpp
@@ -90,17 +90,17 @@ MessagePump::Run(MessagePump::Delegate* 
     // here.  To ensure that MessageLoop tasks and XPCOM events have
     // equal priority, we sensitively rely on processing exactly one
     // Task per DoWorkRunnable XPCOM event.
 
 #ifdef MOZ_WIDGET_ANDROID
     // This processes messages in the Android Looper. Note that we only
     // get here if the normal Gecko event loop has been awoken above.
     // Bug 750713
-    did_work |= AndroidBridge::Bridge()->PumpMessageLoop();
+    did_work |= GeckoAppShell::PumpMessageLoop();
 #endif
 
     did_work |= aDelegate->DoDelayedWork(&delayed_work_time_);
 
 if (did_work && delayed_work_time_.is_null()
 #ifdef MOZ_NUWA_PROCESS
     && (!IsNuwaReady() || !IsNuwaProcess())
 #endif
--- a/mobile/android/components/build/nsAndroidHistory.cpp
+++ b/mobile/android/components/build/nsAndroidHistory.cpp
@@ -45,20 +45,17 @@ nsAndroidHistory::RegisterVisitedCallbac
 
   nsTArray<Link*>* list = mListeners.Get(uriString);
   if (! list) {
     list = new nsTArray<Link*>();
     mListeners.Put(uriString, list);
   }
   list->AppendElement(aContent);
 
-  AndroidBridge *bridge = AndroidBridge::Bridge();
-  if (bridge) {
-    bridge->CheckURIVisited(uriString);
-  }
+ GeckoAppShell::CheckURIVisited(uriString);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::UnregisterVisitedCallback(nsIURI *aURI, Link *aContent)
 {
   if (!aContent || !aURI)
@@ -91,37 +88,35 @@ nsAndroidHistory::VisitURI(nsIURI *aURI,
     return NS_OK;
 
   if (aFlags & VisitFlags::REDIRECT_SOURCE)
     return NS_OK;
 
   if (aFlags & VisitFlags::UNRECOVERABLE_ERROR)
     return NS_OK;
 
-  AndroidBridge *bridge = AndroidBridge::Bridge();
-  if (bridge) {
+  if (AndroidBridge::Bridge()) {
     nsAutoCString uri;
     nsresult rv = aURI->GetSpec(uri);
     if (NS_FAILED(rv)) return rv;
     NS_ConvertUTF8toUTF16 uriString(uri);
-    bridge->MarkURIVisited(uriString);
+    GeckoAppShell::MarkURIVisited(uriString);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::SetURITitle(nsIURI *aURI, const nsAString& aTitle)
 {
-  AndroidBridge *bridge = AndroidBridge::Bridge();
-  if (bridge) {
+  if (AndroidBridge::Bridge()) {
     nsAutoCString uri;
     nsresult rv = aURI->GetSpec(uri);
     if (NS_FAILED(rv)) return rv;
     NS_ConvertUTF8toUTF16 uriString(uri);
-    bridge->SetURITitle(uriString, aTitle);
+    GeckoAppShell::SetURITitle(uriString, aTitle);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidHistory::NotifyVisited(nsIURI *aURI)
 {
   if (aURI && sHistory) {
--- a/mobile/android/components/build/nsShellService.cpp
+++ b/mobile/android/components/build/nsShellService.cpp
@@ -3,25 +3,27 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsShellService.h"
 #include "nsString.h"
 
 #include "AndroidBridge.h"
 
+using namespace mozilla::widget::android;
+
 NS_IMPL_ISUPPORTS1(nsShellService, nsIShellService)
 
 NS_IMETHODIMP
 nsShellService::SwitchTask()
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 nsShellService::CreateShortcut(const nsAString& aTitle, const nsAString& aURI, const nsAString& aIconData, const nsAString& aIntent)
 {
   if (!aTitle.Length() || !aURI.Length() || !aIconData.Length())
     return NS_ERROR_FAILURE;
 
-  mozilla::AndroidBridge::Bridge()->CreateShortcut(aTitle, aURI, aIconData, aIntent);
+  GeckoAppShell::CreateShortcut(aTitle, aURI, aIconData, aIntent);
   return NS_OK;
 }
--- a/netwerk/base/src/Tickler.cpp
+++ b/netwerk/base/src/Tickler.cpp
@@ -75,17 +75,17 @@ nsresult
 Tickler::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!mTimer);
   MOZ_ASSERT(!mActive);
   MOZ_ASSERT(!mThread);
   MOZ_ASSERT(!mFD);
 
-  AndroidBridge::Bridge()->EnableNetworkNotifications();
+  GeckoAppShell::EnableNetworkNotifications();
 
   mFD = PR_OpenUDPSocket(PR_AF_INET);
   if (!mFD)
     return NS_ERROR_FAILURE;
 
   // make sure new socket has a ttl of 1
   // failure is not fatal.
   PRSocketOptionData opt;
--- a/netwerk/protocol/device/CameraStreamImpl.cpp
+++ b/netwerk/protocol/device/CameraStreamImpl.cpp
@@ -85,14 +85,14 @@ bool CameraStreamImpl::Init(const nsCStr
 {
     mCallback = aCallback;
     mWidth = width;
     mHeight = height;
     return AndroidBridge::Bridge()->InitCamera(contentType, camera, &mWidth, &mHeight, &mFps);
 }
 
 void CameraStreamImpl::Close() {
-    AndroidBridge::Bridge()->CloseCamera();
+    GeckoAppShell::CloseCamera();
     mCallback = nullptr;
 }
 
 } // namespace net
 } // namespace mozilla
--- a/netwerk/system/android/nsAndroidNetworkLinkService.cpp
+++ b/netwerk/system/android/nsAndroidNetworkLinkService.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsAndroidNetworkLinkService.h"
 #include "nsServiceManagerUtils.h"
 #include "mozilla/Services.h"
 
 #include "AndroidBridge.h"
 
+using namespace mozilla::widget::android;
+
 NS_IMPL_ISUPPORTS1(nsAndroidNetworkLinkService,
                    nsINetworkLinkService)
 
 nsAndroidNetworkLinkService::nsAndroidNetworkLinkService()
 {
 }
 
 nsAndroidNetworkLinkService::~nsAndroidNetworkLinkService()
@@ -26,26 +28,26 @@ nsAndroidNetworkLinkService::GetIsLinkUp
 {
   if (!mozilla::AndroidBridge::Bridge()) {
     // Fail soft here and assume a connection exists
     NS_WARNING("GetIsLinkUp is not supported without a bridge connection");
     *aIsUp = true;
     return NS_OK;
   }
 
-  *aIsUp = mozilla::AndroidBridge::Bridge()->IsNetworkLinkUp();
+  *aIsUp = GeckoAppShell::IsNetworkLinkUp();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidNetworkLinkService::GetLinkStatusKnown(bool *aIsKnown)
 {
   NS_ENSURE_TRUE(mozilla::AndroidBridge::Bridge(), NS_ERROR_NOT_IMPLEMENTED);
 
-  *aIsKnown = mozilla::AndroidBridge::Bridge()->IsNetworkLinkKnown();
+  *aIsKnown = GeckoAppShell::IsNetworkLinkKnown();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsAndroidNetworkLinkService::GetLinkType(uint32_t *aLinkType)
 {
   NS_ENSURE_ARG_POINTER(aLinkType);
 
--- a/toolkit/components/alerts/nsAlertsService.cpp
+++ b/toolkit/components/alerts/nsAlertsService.cpp
@@ -6,16 +6,17 @@
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "nsXULAppAPI.h"
 
 #include "nsAlertsService.h"
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
+using namespace mozilla::widget::android;
 #else
 
 #include "nsXPCOM.h"
 #include "nsIServiceManager.h"
 #include "nsIDOMWindow.h"
 #include "nsPromiseFlatString.h"
 #include "nsToolkitCompsCID.h"
 
@@ -122,17 +123,17 @@ NS_IMETHODIMP nsAlertsService::CloseAler
 {
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
     ContentChild* cpc = ContentChild::GetSingleton();
     cpc->SendCloseAlert(nsAutoString(aAlertName), IPC::Principal(aPrincipal));
     return NS_OK;
   }
 
 #ifdef MOZ_WIDGET_ANDROID
-  mozilla::AndroidBridge::Bridge()->CloseNotification(aAlertName);
+  GeckoAppShell::CloseNotification(aAlertName);
   return NS_OK;
 #else
 
   // Try the system notification service.
   nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
   if (sysAlerts) {
     return sysAlerts->CloseAlert(aAlertName, nullptr);
   }
@@ -143,24 +144,24 @@ NS_IMETHODIMP nsAlertsService::CloseAler
 
 
 NS_IMETHODIMP nsAlertsService::OnProgress(const nsAString & aAlertName,
                                           int64_t aProgress,
                                           int64_t aProgressMax,
                                           const nsAString & aAlertText)
 {
 #ifdef MOZ_WIDGET_ANDROID
-  mozilla::AndroidBridge::Bridge()->AlertsProgressListener_OnProgress(aAlertName, aProgress, aProgressMax, aAlertText);
+  GeckoAppShell::AlertsProgressListener_OnProgress(aAlertName, aProgress, aProgressMax, aAlertText);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif // !MOZ_WIDGET_ANDROID
 }
 
 NS_IMETHODIMP nsAlertsService::OnCancel(const nsAString & aAlertName)
 {
 #ifdef MOZ_WIDGET_ANDROID
-  mozilla::AndroidBridge::Bridge()->CloseNotification(aAlertName);
+  GeckoAppShell::CloseNotification(aAlertName);
   return NS_OK;
 #else
   return NS_ERROR_NOT_IMPLEMENTED;
 #endif // !MOZ_WIDGET_ANDROID
 }
--- a/toolkit/components/downloads/nsDownloadManager.cpp
+++ b/toolkit/components/downloads/nsDownloadManager.cpp
@@ -47,16 +47,17 @@
 #endif
 
 #ifdef XP_MACOSX
 #include <CoreFoundation/CoreFoundation.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
+using namespace mozilla::widget::android;
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
 #endif
 
 using namespace mozilla;
 using mozilla::downloads::GenerateGUID;
@@ -2792,17 +2793,17 @@ nsDownload::SetState(DownloadState aStat
 #ifdef MOZ_WIDGET_ANDROID
         nsCOMPtr<nsIMIMEInfo> mimeInfo;
         nsAutoCString contentType;
         GetMIMEInfo(getter_AddRefs(mimeInfo));
 
         if (mimeInfo)
           mimeInfo->GetMIMEType(contentType);
 
-        mozilla::AndroidBridge::Bridge()->ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
+        GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(contentType));
 #endif
       }
 
 #ifdef XP_WIN
       // Adjust file attributes so that by default, new files are indexed
       // by desktop search services. Skip off those that land in the temp
       // folder.
       nsCOMPtr<nsIFile> tempDir, fileDir;
--- a/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
+++ b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp
@@ -113,17 +113,17 @@ nsresult DownloadPlatform::DownloadDone(
                                              kCFStringEncodingUTF8);
     CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
     ::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
                                            observedObject, nullptr, TRUE);
     ::CFRelease(observedObject);
 #endif
 #ifdef MOZ_WIDGET_ANDROID
     if (!aContentType.IsEmpty()) {
-      mozilla::AndroidBridge::Bridge()->ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
+      mozilla::widget::android::GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType));
     }
 #endif
   }
 
 #ifdef XP_WIN
   // Adjust file attributes so that by default, new files are indexed by
   // desktop search services. Skip off those that land in the temp folder.
   nsCOMPtr<nsIFile> tempDir, fileDir;
--- a/toolkit/xre/nsAndroidStartup.cpp
+++ b/toolkit/xre/nsAndroidStartup.cpp
@@ -70,14 +70,14 @@ GeckoStart(void *data, const nsXREAppDat
     }
     targs.AppendElement(static_cast<char *>(nullptr));
 
     int result = XRE_main(targs.Length() - 1, targs.Elements(), appData, 0);
 
     if (result)
         LOG("XRE_main returned %d", result);
 
-    mozilla::AndroidBridge::Bridge()->NotifyXreExit();
+    mozilla::widget::android::GeckoAppShell::NotifyXreExit();
 
     free(targs[0]);
     nsMemory::Free(data);
     return;
 }
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -1644,17 +1644,17 @@ static nsresult LaunchChild(nsINativeApp
     gRestartArgc = 1;
     gRestartArgv[gRestartArgc] = nullptr;
 #endif
   }
 
   SaveToEnv("MOZ_LAUNCHED_CHILD=1");
 
 #if defined(MOZ_WIDGET_ANDROID)
-  mozilla::AndroidBridge::Bridge()->ScheduleRestart();
+  mozilla::widget::android::GeckoAppShell::ScheduleRestart();
 #else
 #if defined(XP_MACOSX)
   CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
   uint32_t restartMode = 0;
   restartMode = gRestartMode;
   LaunchChildMac(gRestartArgc, gRestartArgv, restartMode);
 #else
   nsCOMPtr<nsIFile> lf;
@@ -1756,17 +1756,17 @@ ProfileLockedDialog(nsIFile* aProfileDir
 
     nsCOMPtr<nsIPromptService> ps
       (do_GetService(NS_PROMPTSERVICE_CONTRACTID));
     NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE);
 
     if (aUnlocker) {
       int32_t button;
 #ifdef MOZ_WIDGET_ANDROID
-      mozilla::AndroidBridge::Bridge()->KillAnyZombies();
+      mozilla::widget::android::GeckoAppShell::KillAnyZombies();
       button = 1;
 #else
       const uint32_t flags =
         (nsIPromptService::BUTTON_TITLE_CANCEL * 
          nsIPromptService::BUTTON_POS_0) +
         (nsIPromptService::BUTTON_TITLE_IS_STRING * 
          nsIPromptService::BUTTON_POS_1) +
         nsIPromptService::BUTTON_POS_1_DEFAULT;
@@ -1783,17 +1783,17 @@ ProfileLockedDialog(nsIFile* aProfileDir
         if (NS_FAILED(rv)) 
           return rv;
 
         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
                                   nullptr, aResult);
       }
     } else {
 #ifdef MOZ_WIDGET_ANDROID
-      if (mozilla::AndroidBridge::Bridge()->UnlockProfile()) {
+      if (mozilla::widget::android::GeckoAppShell::UnlockProfile()) {
         return NS_LockProfilePath(aProfileDir, aProfileLocalDir, 
                                   nullptr, aResult);
       }
 #else
       rv = ps->Alert(nullptr, killTitle, killMessage);
       NS_ENSURE_SUCCESS_LOG(rv, rv);
 #endif
     }
--- a/tools/profiler/TableTicker.cpp
+++ b/tools/profiler/TableTicker.cpp
@@ -225,17 +225,17 @@ typename Builder::Object BuildJavaThread
         break;
       }
       if (!sample) {
         sample = b.CreateObject();
         frames = b.CreateArray();
         b.DefineProperty(sample, "frames", frames);
         b.ArrayPush(samples, sample);
 
-        double sampleTime = AndroidBridge::Bridge()->GetSampleTimeJavaProfiling(0, sampleId);
+        double sampleTime = GeckoJavaSampler::GetSampleTimeJavaProfiling(0, sampleId);
         b.DefineProperty(sample, "time", sampleTime);
       }
       typename Builder::RootedObject frame(b.context(), b.CreateObject());
       b.DefineProperty(frame, "location", result.BeginReading());
       b.ArrayPush(frames, frame);
       frameId++;
     }
     if (frameId == 0) {
@@ -277,22 +277,22 @@ void TableTicker::BuildJSObject(Builder&
       typename Builder::RootedObject threadSamples(b.context(), b.CreateObject());
       sRegisteredThreads->at(i)->Profile()->BuildJSObject(b, threadSamples);
       b.ArrayPush(threads, threadSamples);
     }
   }
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   if (ProfileJava()) {
-    AndroidBridge::Bridge()->PauseJavaProfiling();
+    GeckoJavaSampler::PauseJavaProfiling();
 
     typename Builder::RootedObject javaThread(b.context(), BuildJavaThreadJSObject(b));
     b.ArrayPush(threads, javaThread);
 
-    AndroidBridge::Bridge()->UnpauseJavaProfiling();
+    GeckoJavaSampler::UnpauseJavaProfiling();
   }
 #endif
 
   SetPaused(false);
 
   // Send a event asking any subprocesses (plugins) to
   // give us their information
   SubprocessClosure<Builder> closure(&b, threads);
--- a/tools/profiler/platform.cpp
+++ b/tools/profiler/platform.cpp
@@ -23,16 +23,17 @@
 #include "nsDirectoryServiceDefs.h"
 #include "mozilla/Services.h"
 #include "nsThreadUtils.h"
 #include "ProfilerMarkers.h"
 #include "nsXULAppAPI.h"
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   #include "AndroidBridge.h"
+  using namespace mozilla::widget::android;
 #endif
 
 mozilla::ThreadLocal<PseudoStack *> tlsPseudoStack;
 mozilla::ThreadLocal<TableTicker *> tlsTicker;
 mozilla::ThreadLocal<void *> tlsStackTop;
 // We need to track whether we've been initialized otherwise
 // we end up using tlsStack without initializing it.
 // Because tlsStack is totally opaque to us we can't reuse
@@ -670,17 +671,17 @@ void mozilla_sampler_start(int aProfileE
 
 #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK)
   if (t->ProfileJava()) {
     int javaInterval = aInterval;
     // Java sampling doesn't accuratly keep up with 1ms sampling
     if (javaInterval < 10) {
       aInterval = 10;
     }
-    mozilla::AndroidBridge::Bridge()->StartJavaProfiling(javaInterval, 1000);
+    GeckoJavaSampler::StartJavaProfiling(javaInterval, 1000);
   }
 #endif
 
   if (t->AddMainThreadIO()) {
     if (!sInterposeObserver) {
       // Lazily create IO interposer observer
       sInterposeObserver = new mozilla::ProfilerIOInterposeObserver();
     }
--- a/uriloader/exthandler/android/nsAndroidHandlerApp.cpp
+++ b/uriloader/exthandler/android/nsAndroidHandlerApp.cpp
@@ -1,16 +1,18 @@
 /* -*- Mode: c++; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsAndroidHandlerApp.h"
 #include "AndroidBridge.h"
 
+using namespace mozilla::widget::android;
+
 
 NS_IMPL_ISUPPORTS2(nsAndroidHandlerApp, nsIHandlerApp, nsISharingHandlerApp)
 
 nsAndroidHandlerApp::nsAndroidHandlerApp(const nsAString& aName,
                                          const nsAString& aDescription,
                                          const nsAString& aPackageName,
                                          const nsAString& aClassName,
                                          const nsACString& aMimeType,
@@ -65,24 +67,22 @@ nsAndroidHandlerApp::Equals(nsIHandlerAp
 NS_IMETHODIMP
 nsAndroidHandlerApp::LaunchWithURI(nsIURI *aURI, nsIInterfaceRequestor *aWindowContext)
 {
   if (!mozilla::AndroidBridge::Bridge())
     return NS_ERROR_FAILURE;
 
   nsCString uriSpec;
   aURI->GetSpec(uriSpec);
-  return mozilla::AndroidBridge::Bridge()->
-    OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), NS_ConvertUTF8toUTF16(mMimeType), mPackageName, mClassName, mAction) ? 
+  return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), NS_ConvertUTF8toUTF16(mMimeType), mPackageName, mClassName, mAction) ? 
     NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsAndroidHandlerApp::Share(const nsAString & data, const nsAString & title)
 {
   if (!mozilla::AndroidBridge::Bridge())
     return NS_ERROR_FAILURE;
 
-  return mozilla::AndroidBridge::Bridge()->
-    OpenUriExternal(data, NS_ConvertUTF8toUTF16(mMimeType), mPackageName, 
+  return GeckoAppShell::OpenUriExternal(data, NS_ConvertUTF8toUTF16(mMimeType), mPackageName, 
                     mClassName, mAction) ? NS_OK : NS_ERROR_FAILURE;
 }
 
--- a/uriloader/exthandler/android/nsExternalSharingAppService.cpp
+++ b/uriloader/exthandler/android/nsExternalSharingAppService.cpp
@@ -27,19 +27,18 @@ nsExternalSharingAppService::~nsExternal
 NS_IMETHODIMP
 nsExternalSharingAppService::ShareWithDefault(const nsAString & data,
                                               const nsAString & mime,
                                               const nsAString & title)
 {
   NS_NAMED_LITERAL_STRING(sendAction, "android.intent.action.SEND");
   const nsString emptyString = EmptyString();
   if (AndroidBridge::Bridge())
-    return AndroidBridge::Bridge()->
-      OpenUriExternal(data, mime,
-                      emptyString,emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE;
+    return GeckoAppShell::OpenUriExternal(data, mime,
+                                          emptyString,emptyString, sendAction, title) ? NS_OK : NS_ERROR_FAILURE;
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsExternalSharingAppService::GetSharingApps(const nsAString & aMIMEType,
                                             uint32_t *aLen,
                                             nsISharingHandlerApp ***aHandlers)
--- a/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
+++ b/uriloader/exthandler/android/nsMIMEInfoAndroid.cpp
@@ -5,16 +5,18 @@
 #include "nsMIMEInfoAndroid.h"
 #include "AndroidBridge.h"
 #include "nsAndroidHandlerApp.h"
 #include "nsArrayUtils.h"
 #include "nsISupportsUtils.h"
 #include "nsStringEnumerator.h"
 #include "nsNetUtil.h"
 
+using namespace mozilla::widget::android;
+
 NS_IMPL_ISUPPORTS2(nsMIMEInfoAndroid, nsIMIMEInfo, nsIHandlerInfo)
 
 NS_IMETHODIMP
 nsMIMEInfoAndroid::LaunchDefaultWithFile(nsIFile* aFile)
 {
   LaunchWithFile(aFile);
   return NS_OK;
 }
@@ -24,18 +26,17 @@ nsMIMEInfoAndroid::LoadUriInternal(nsIUR
 {
   nsCString uriSpec;
   aURI->GetSpec(uriSpec);
 
   nsCString uriScheme;
   aURI->GetScheme(uriScheme);
 
   if (mozilla::AndroidBridge::Bridge())
-    return mozilla::AndroidBridge::Bridge()->
-      OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), (mType.Equals(uriScheme) || mType.Equals(uriSpec)) ? EmptyString() : NS_ConvertUTF8toUTF16(mType)) ? NS_OK : NS_ERROR_FAILURE;
+    return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(uriSpec), (mType.Equals(uriScheme) || mType.Equals(uriSpec)) ? EmptyString() : NS_ConvertUTF8toUTF16(mType)) ? NS_OK : NS_ERROR_FAILURE;
 
   return NS_ERROR_FAILURE;
 }
 
 
 bool
 nsMIMEInfoAndroid::GetMimeInfoForMimeType(const nsACString& aMimeType,
                                           nsMIMEInfoAndroid** aMimeInfo)
--- a/widget/android/AndroidBridge.cpp
+++ b/widget/android/AndroidBridge.cpp
@@ -34,23 +34,18 @@
 #include "nsPIDOMWindow.h"
 #include "mozilla/dom/ScreenOrientation.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIDOMClientRect.h"
 #include "StrongPointer.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "nsPrintfCString.h"
 
-#ifdef DEBUG
-#define ALOG_BRIDGE(args...) ALOG(args)
-#else
-#define ALOG_BRIDGE(args...) ((void)0)
-#endif
-
 using namespace mozilla;
+using namespace mozilla::widget::android;
 using namespace mozilla::gfx;
 
 NS_IMPL_ISUPPORTS0(nsFilePickerCallback)
 
 StaticRefPtr<AndroidBridge> AndroidBridge::sBridge;
 static unsigned sJavaEnvThreadIndex = 0;
 static jobject sGlobalContext = nullptr;
 static void JavaThreadDetachFunc(void *arg);
@@ -165,24 +160,23 @@ AndroidBridge::Init(JNIEnv *jEnv)
 {
     ALOG_BRIDGE("AndroidBridge::Init");
     jEnv->GetJavaVM(&mJavaVM);
 
     AutoLocalJNIFrame jniFrame(jEnv);
 
     mJNIEnv = nullptr;
     mThread = -1;
-    mGLControllerObj = nullptr;
+    mGLControllerObj = NULL;
     mOpenedGraphicsLibraries = false;
     mHasNativeBitmapAccess = false;
     mHasNativeWindowAccess = false;
     mHasNativeWindowFallback = false;
 
     initInit();
-    InitStubs(jEnv);
 
 #ifdef MOZ_WEBSMS_BACKEND
     mAndroidSmsMessageClass = getClassGlobalRef("android/telephony/SmsMessage");
     jCalculateLength = getStaticMethod("calculateLength", "(Ljava/lang/CharSequence;Z)[I");
 #endif
 
     jStringClass = getClassGlobalRef("java/lang/String");
 
@@ -267,16 +261,62 @@ jstring AndroidBridge::NewJavaString(Aut
 jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const char* string) {
     return NewJavaString(frame, NS_ConvertUTF8toUTF16(string));
 }
 
 jstring AndroidBridge::NewJavaString(AutoLocalJNIFrame* frame, const nsACString& string) {
     return NewJavaString(frame, NS_ConvertUTF8toUTF16(string));
 }
 
+extern "C" {
+    __attribute__ ((visibility("default")))
+    JNIEnv * GetJNIForThread()
+    {
+        JNIEnv *jEnv = NULL;
+        JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
+        if (!jVm) {
+            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM");
+            return NULL;
+        }
+        jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
+
+        if (jEnv)
+            return jEnv;
+
+        int status = jVm->GetEnv((void**) &jEnv, JNI_VERSION_1_2);
+        if (status) {
+
+            status = jVm->AttachCurrentThread(&jEnv, NULL);
+            if (status) {
+                __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread",  "Could not attach");
+                return NULL;
+            }
+
+            PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv);
+        }
+        if (!jEnv) {
+            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "returning NULL");
+        }
+        return jEnv;
+    }
+}
+
+void AutoGlobalWrappedJavaObject::Dispose() {
+    if (isNull()) {
+        return;
+    }
+
+    GetJNIForThread()->DeleteGlobalRef(wrapped_obj);
+    wrapped_obj = NULL;
+}
+
+AutoGlobalWrappedJavaObject::~AutoGlobalWrappedJavaObject() {
+    Dispose();
+}
+
 static void
 getHandlersFromStringArray(JNIEnv *aJNIEnv, jobjectArray jArr, jsize aLen,
                            nsIMutableArray *aHandlersArray,
                            nsIHandlerApp **aDefaultApp,
                            const nsAString& aAction = EmptyString(),
                            const nsACString& aMimeType = EmptyCString())
 {
     nsString empty = EmptyString();
@@ -306,17 +346,17 @@ AndroidBridge::GetHandlersForMimeType(co
                                       const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForMimeType");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    jobjectArray arr = GetHandlersForMimeTypeWrapper(aMimeType, aAction);
+    jobjectArray arr = GeckoAppShell::GetHandlersForMimeTypeWrapper(aMimeType, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
     if (!aHandlersArray)
         return len > 0;
 
@@ -335,17 +375,17 @@ AndroidBridge::GetHandlersForURL(const n
                                  const nsAString& aAction)
 {
     ALOG_BRIDGE("AndroidBridge::GetHandlersForURL");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    jobjectArray arr = GetHandlersForURLWrapper(aURL, aAction);
+    jobjectArray arr = GeckoAppShell::GetHandlersForURLWrapper(aURL, aAction);
     if (!arr)
         return false;
 
     jsize len = env->GetArrayLength(arr);
 
     if (!aHandlersArray)
         return len > 0;
 
@@ -360,17 +400,17 @@ void
 AndroidBridge::GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType)
 {
     ALOG_BRIDGE("AndroidBridge::GetMimeTypeFromExtensions");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstrType = GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt));
+    jstring jstrType = GeckoAppShell::GetMimeTypeFromExtensionsWrapper(NS_ConvertUTF8toUTF16(aFileExt));
     if (!jstrType) {
         return;
     }
     nsJNIString jniStr(jstrType, env);
     CopyUTF16toUTF8(jniStr.get(), aMimeType);
 
     env->DeleteLocalRef(jstrType);
 }
@@ -379,17 +419,17 @@ void
 AndroidBridge::GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt)
 {
     ALOG_BRIDGE("AndroidBridge::GetExtensionFromMimeType");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstrExt = GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType));
+    jstring jstrExt = GeckoAppShell::GetExtensionFromMimeTypeWrapper(NS_ConvertUTF8toUTF16(aMimeType));
     if (!jstrExt) {
         return;
     }
     nsJNIString jniStr(jstrExt, env);
     CopyUTF16toUTF8(jniStr.get(), aFileExt);
 
     env->DeleteLocalRef(jstrExt);
 }
@@ -398,83 +438,53 @@ bool
 AndroidBridge::GetClipboardText(nsAString& aText)
 {
     ALOG_BRIDGE("AndroidBridge::GetClipboardText");
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
-    jstring result = GetClipboardTextWrapper();
+    jstring result = Clipboard::GetClipboardTextWrapper();
     if (!result)
         return false;
 
     nsJNIString jniStr(result, env);
     aText.Assign(jniStr);
 
     env->DeleteLocalRef(result);
     return true;
 }
 
-bool
-AndroidBridge::ClipboardHasText()
-{
-    ALOG_BRIDGE("AndroidBridge::ClipboardHasText");
-
-    JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return false;
-
-    AutoLocalJNIFrame jniFrame(env);
-
-    jstring jStr = GetClipboardTextWrapper();
-    bool ret = jStr;
-
-    return ret;
-}
-
-void
-AndroidBridge::EmptyClipboard()
-{
-    ALOG_BRIDGE("AndroidBridge::EmptyClipboard");
-
-    JNIEnv *env = GetJNIEnv();
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env, 0);
-    env->CallStaticVoidMethod(mClipboardClass, jSetClipboardText, nullptr);
-}
-
 void
 AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl,
                                      const nsAString& aAlertTitle,
                                      const nsAString& aAlertText,
                                      const nsAString& aAlertCookie,
                                      nsIObserver *aAlertListener,
                                      const nsAString& aAlertName)
 {
     if (nsAppShell::gAppShell && aAlertListener) {
         // This will remove any observers already registered for this id
         nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeAddObserver(aAlertName, aAlertListener));
     }
 
-    ShowAlertNotificationWrapper(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName);
+    GeckoAppShell::ShowAlertNotificationWrapper(aImageUrl, aAlertTitle, aAlertText, aAlertCookie, aAlertName);
 }
 
 int
 AndroidBridge::GetDPI()
 {
     static int sDPI = 0;
     if (sDPI)
         return sDPI;
 
     const int DEFAULT_DPI = 160;
 
-    sDPI = GetDpiWrapper();
+    sDPI = GeckoAppShell::GetDpiWrapper();
     if (!sDPI) {
         return DEFAULT_DPI;
     }
 
     return sDPI;
 }
 
 int
@@ -483,72 +493,60 @@ AndroidBridge::GetScreenDepth()
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     static int sDepth = 0;
     if (sDepth)
         return sDepth;
 
     const int DEFAULT_DEPTH = 16;
 
-    sDepth = GetScreenDepthWrapper();
+    sDepth = GeckoAppShell::GetScreenDepthWrapper();
     if (!sDepth)
         return DEFAULT_DEPTH;
 
     return sDepth;
 }
 
 void
 AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstr = ShowFilePickerForExtensionsWrapper(aExtensions);
+    jstring jstr = GeckoAppShell::ShowFilePickerForExtensionsWrapper(aExtensions);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
     env->DeleteLocalRef(jstr);
 }
 
 void
 AndroidBridge::ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
-    jstring jstr = ShowFilePickerForMimeTypeWrapper(aMimeType);
+    jstring jstr = GeckoAppShell::ShowFilePickerForMimeTypeWrapper(aMimeType);
     if (jstr == nullptr) {
         return;
     }
 
     aFilePath.Assign(nsJNIString(jstr, env));
     env->DeleteLocalRef(jstr);
 }
 
 void
 AndroidBridge::ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback)
 {
     callback->AddRef();
-    ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback);
-}
-
-void
-AndroidBridge::HideProgressDialogOnce()
-{
-    static bool once = false;
-    if (once)
-        return;
-
-    HideProgressDialog();
-
-    once = true;
+    GeckoAppShell::ShowFilePickerAsyncWrapper(aMimeType, (int64_t) callback);
 }
 
 void
 AndroidBridge::Vibrate(const nsTArray<uint32_t>& aPattern)
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     uint32_t len = aPattern.Length();
@@ -566,17 +564,17 @@ AndroidBridge::Vibrate(const nsTArray<ui
     // It's clear if this worth special-casing, but it creates less
     // java junk, so dodges the GC.
     if (len == 1) {
         jlong d = aPattern[0];
         if (d < 0) {
             ALOG_BRIDGE("  invalid vibration duration < 0");
             return;
         }
-        Vibrate1(d);
+        GeckoAppShell::Vibrate1(d);
         return;
     }
 
     // First element of the array vibrate() expects is how long to wait
     // *before* vibrating.  For us, this is always 0.
 
     jlongArray array = env->NewLongArray(len + 1);
     if (!array) {
@@ -592,34 +590,34 @@ AndroidBridge::Vibrate(const nsTArray<ui
             ALOG_BRIDGE("  invalid vibration duration < 0");
             env->ReleaseLongArrayElements(array, elts, JNI_ABORT);
             return;
         }
         elts[i + 1] = d;
     }
     env->ReleaseLongArrayElements(array, elts, 0);
 
-    VibrateA(array, -1/*don't repeat*/);
+    GeckoAppShell::VibrateA(array, -1/*don't repeat*/);
 }
 
 void
 AndroidBridge::GetSystemColors(AndroidSystemColors *aColors)
 {
 
     NS_ASSERTION(aColors != nullptr, "AndroidBridge::GetSystemColors: aColors is null!");
     if (!aColors)
         return;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jintArray arr = GetSystemColoursWrapper();
+    jintArray arr = GeckoAppShell::GetSystemColoursWrapper();
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
     jint *elements = env->GetIntArrayElements(arr, 0);
 
     uint32_t colorsCount = sizeof(AndroidSystemColors) / sizeof(nscolor);
     if (len < colorsCount)
@@ -647,17 +645,17 @@ AndroidBridge::GetIconForExtension(const
         return;
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jbyteArray arr = GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
+    jbyteArray arr = GeckoAppShell::GetIconForExtensionWrapper(NS_ConvertUTF8toUTF16(aFileExt), aIconSize);
 
     NS_ASSERTION(arr != nullptr, "AndroidBridge::GetIconForExtension: Returned pixels array is null!");
     if (!arr)
         return;
 
     uint32_t len = static_cast<uint32_t>(env->GetArrayLength(arr));
     jbyte *elements = env->GetByteArrayElements(arr, 0);
 
@@ -675,72 +673,60 @@ AndroidBridge::SetLayerClient(JNIEnv* en
     // if resetting is true, that means Android destroyed our GeckoApp activity
     // and we had to recreate it, but all the Gecko-side things were not destroyed.
     // We therefore need to link up the new java objects to Gecko, and that's what
     // we do here.
     bool resetting = (mLayerClient != nullptr);
 
     if (resetting) {
         // clear out the old layer client
-        env->DeleteGlobalRef(mLayerClient->wrappedObject());
         delete mLayerClient;
         mLayerClient = nullptr;
     }
 
-    AndroidGeckoLayerClient *client = new AndroidGeckoLayerClient();
-    client->Init(env->NewGlobalRef(jobj));
-    mLayerClient = client;
+    mLayerClient = GeckoLayerClient::Wrap(jobj);
 
     if (resetting) {
         // since we are re-linking the new java objects to Gecko, we need to get
         // the viewport from the compositor (since the Java copy was thrown away)
         // and we do that by setting the first-paint flag.
         nsWindow::ForceIsFirstPaint();
     }
 }
 
 void
 AndroidBridge::RegisterCompositor(JNIEnv *env)
 {
-    ALOG_BRIDGE("AndroidBridge::RegisterCompositor");
-    if (mGLControllerObj) {
+    if (mGLControllerObj != NULL && !mGLControllerObj->isNull()) {
         // we already have this set up, no need to do it again
         return;
     }
 
-    if (!env) {
-        env = GetJNIForThread();    // called on the compositor thread
-    }
-    if (!env) {
-        return;
-    }
-
-    jobject glController = RegisterCompositorWrapper();
+    jobject glController = LayerView::RegisterCompositorWrapper();
     if (!glController) {
         return;
     }
 
-    mGLControllerObj = env->NewGlobalRef(glController);
-    env->DeleteLocalRef(glController);
+    mGLControllerObj = GLController::Wrap(glController);
 }
 
 EGLSurface
 AndroidBridge::CreateEGLSurfaceForCompositor()
 {
     if (!jEGLSurfacePointerField) {
         return nullptr;
     }
     MOZ_ASSERT(mGLControllerObj, "AndroidBridge::CreateEGLSurfaceForCompositor called with a null GL controller ref");
 
     JNIEnv* env = GetJNIForThread(); // called on the compositor thread
     if (!env) {
         return nullptr;
     }
 
-    jobject eglSurface = CreateEGLSurfaceForCompositorWrapper(mGLControllerObj);
+    jobject eglSurface = mGLControllerObj->CreateEGLSurfaceForCompositorWrapper();
     if (!eglSurface)
         return nullptr;
 
     EGLSurface ret = reinterpret_cast<EGLSurface>(env->GetIntField(eglSurface, jEGLSurfacePointerField));
     env->DeleteLocalRef(eglSurface);
     return ret;
 }
 
@@ -802,21 +788,16 @@ AndroidBridge::GetStaticStringField(cons
 
 // Available for places elsewhere in the code to link to.
 bool
 mozilla_AndroidBridge_SetMainThread(pthread_t thr)
 {
     return AndroidBridge::Bridge()->SetMainThread(thr);
 }
 
-jclass GetGeckoAppShellClass()
-{
-    return mozilla::AndroidBridge::GetGeckoAppShellClass();
-}
-
 void*
 AndroidBridge::GetNativeSurface(JNIEnv* env, jobject surface) {
     if (!env || !mHasNativeWindowFallback || !jSurfacePointerField)
         return nullptr;
 
     return (void*)env->GetIntField(surface, jSurfacePointerField);
 }
 
@@ -1003,17 +984,17 @@ AndroidBridge::ValidateBitmap(jobject bi
 bool
 AndroidBridge::InitCamera(const nsCString& contentType, uint32_t camera, uint32_t *width, uint32_t *height, uint32_t *fps)
 {
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return false;
 
     AutoLocalJNIFrame jniFrame(env);
-    jintArray arr = InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height);
+    jintArray arr = GeckoAppShell::InitCameraWrapper(NS_ConvertUTF8toUTF16(contentType), (int32_t) camera, (int32_t) width, (int32_t) height);
 
     if (!arr)
         return false;
 
     jint *elements = env->GetIntArrayElements(arr, 0);
 
     *width = elements[1];
     *height = elements[2];
@@ -1034,17 +1015,17 @@ AndroidBridge::GetCurrentBatteryInformat
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double and a boolean.
-    jdoubleArray arr = GetCurrentBatteryInformationWrapper();
+    jdoubleArray arr = GeckoAppShell::GetCurrentBatteryInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 3) {
         return;
     }
 
     jdouble* info = env->GetDoubleArrayElements(arr, 0);
 
     aBatteryInfo->level() = info[0];
     aBatteryInfo->charging() = info[1] == 1.0f;
@@ -1058,17 +1039,17 @@ AndroidBridge::HandleGeckoMessage(const 
 {
     ALOG_BRIDGE("%s", __PRETTY_FUNCTION__);
 
     JNIEnv *env = GetJNIEnv();
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
-    jstring returnMessage = HandleGeckoMessageWrapper(aMessage);
+    jstring returnMessage = GeckoAppShell::HandleGeckoMessageWrapper(aMessage);
 
     if (!returnMessage)
         return;
 
     nsJNIString jniStr(returnMessage, env);
     aRet.Assign(jniStr);
     ALOG_BRIDGE("leaving %s", __PRETTY_FUNCTION__);
 }
@@ -1125,41 +1106,41 @@ AndroidBridge::SendMessage(const nsAStri
                            nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::SendMessage");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    SendMessageWrapper(aNumber, aMessage, requestId);
+    GeckoAppShell::SendMessageWrapper(aNumber, aMessage, requestId);
 }
 
 void
 AndroidBridge::GetMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::GetMessage");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    GetMessageWrapper(aMessageId, requestId);
+    GeckoAppShell::GetMessageWrapper(aMessageId, requestId);
 }
 
 void
 AndroidBridge::DeleteMessage(int32_t aMessageId, nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::DeleteMessage");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    DeleteMessageWrapper(aMessageId, requestId);
+    GeckoAppShell::DeleteMessageWrapper(aMessageId, requestId);
 }
 
 void
 AndroidBridge::CreateMessageList(const dom::mobilemessage::SmsFilterData& aFilter, bool aReverse,
                                  nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::CreateMessageList");
 
@@ -1178,31 +1159,31 @@ AndroidBridge::CreateMessageList(const d
                                           jStringClass,
                                           NewJavaString(&jniFrame, EmptyString()));
 
     for (uint32_t i = 0; i < aFilter.numbers().Length(); ++i) {
         env->SetObjectArrayElement(numbers, i,
                                    NewJavaString(&jniFrame, aFilter.numbers()[i]));
     }
 
-    CreateMessageListWrapper(aFilter.startDate(), aFilter.endDate(),
+    GeckoAppShell::CreateMessageListWrapper(aFilter.startDate(), aFilter.endDate(),
                              numbers, aFilter.numbers().Length(),
                              aFilter.delivery(), aReverse, requestId);
 }
 
 void
 AndroidBridge::GetNextMessageInList(int32_t aListId, nsIMobileMessageCallback* aRequest)
 {
     ALOG_BRIDGE("AndroidBridge::GetNextMessageInList");
 
     uint32_t requestId;
     if (!QueueSmsRequest(aRequest, &requestId))
         return;
 
-    GetNextMessageInListWrapper(aListId, requestId);
+    GeckoAppShell::GetNextMessageInListWrapper(aListId, requestId);
 }
 
 bool
 AndroidBridge::QueueSmsRequest(nsIMobileMessageCallback* aRequest, uint32_t* aRequestIdOut)
 {
     MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
     MOZ_ASSERT(aRequest && aRequestIdOut);
 
@@ -1244,17 +1225,17 @@ AndroidBridge::GetCurrentNetworkInformat
     if (!env)
         return;
 
     AutoLocalJNIFrame jniFrame(env);
 
     // To prevent calling too many methods through JNI, the Java method returns
     // an array of double even if we actually want a double, two booleans, and an integer.
 
-    jdoubleArray arr = GetCurrentNetworkInformationWrapper();
+    jdoubleArray arr = GeckoAppShell::GetCurrentNetworkInformationWrapper();
     if (!arr || env->GetArrayLength(arr) != 4) {
         return;
     }
 
     jdouble* info = env->GetDoubleArrayElements(arr, 0);
 
     aNetworkInfo->bandwidth() = info[0];
     aNetworkInfo->canBeMetered() = info[1] == 1.0f;
@@ -1437,17 +1418,17 @@ jobject
 AndroidBridge::GetGlobalContextRef() {
     if (sGlobalContext == nullptr) {
         JNIEnv *env = GetJNIForThread();
         if (!env)
             return 0;
 
         AutoLocalJNIFrame jniFrame(env, 4);
 
-        jobject context = GetContext();
+        jobject context = GeckoAppShell::GetContext();
         if (!context) {
             ALOG_BRIDGE("%s: Could not GetContext()", __FUNCTION__);
             return 0;
         }
         jclass contextClass = env->FindClass("android/content/Context");
         if (!contextClass) {
             ALOG_BRIDGE("%s: Could not find Context class.", __FUNCTION__);
             return 0;
@@ -1488,58 +1469,101 @@ AndroidBridge::UnlockWindow(void* window
     }
 
     return true;
 }
 
 void
 AndroidBridge::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
 {
-    AndroidGeckoLayerClient *client = mLayerClient;
+    GeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
-    client->SetFirstPaintViewport(aOffset, aZoom, aCssPageRect);
+    client->SetFirstPaintViewport((float)aOffset.x, (float)aOffset.y, aZoom.scale,
+                                  aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
 }
 
 void
 AndroidBridge::SetPageRect(const CSSRect& aCssPageRect)
 {
-    AndroidGeckoLayerClient *client = mLayerClient;
+    GeckoLayerClient *client = mLayerClient;
     if (!client)
         return;
 
-    client->SetPageRect(aCssPageRect);
+    client->SetPageRect(aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
 }
 
 void
 AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                                 bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
                                 LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
-    AndroidGeckoLayerClient *client = mLayerClient;
-    if (!client)
+    GeckoLayerClient *client = mLayerClient;
+    if (!client) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
+    }
+
+    jobject viewTransformJObj = client->SyncViewportInfo(aDisplayPort.x, aDisplayPort.y,
+                                aDisplayPort.width, aDisplayPort.height,
+                                aDisplayResolution.scale, aLayersUpdated);
+    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
 
-    client->SyncViewportInfo(aDisplayPort, aDisplayResolution, aLayersUpdated,
-                             aScrollOffset, aScale, aFixedLayerMargins,
-                             aOffset);
+    if (!viewTransformJObj) {
+        return;
+    }
+
+    ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
+    aScrollOffset = ScreenPoint(viewTransform->getx(), viewTransform->gety());
+    aScale.scale = viewTransform->getscale();
+    aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
+    aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
+    aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
+    aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
+    aOffset.x = viewTransform->getoffsetX();
+    aOffset.y = viewTransform->getoffsetY();
+    delete viewTransform;
 }
 
 void AndroidBridge::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
                                      bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
                                      bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
 {
-    AndroidGeckoLayerClient *client = mLayerClient;
-    if (!client)
+    GeckoLayerClient *client = mLayerClient;
+    if (!client) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
+    }
+
+    // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
+    LayerRect dpUnrounded = aDisplayPort * aDisplayResolution;
+    dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
+    LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
+
+    jobject viewTransformJObj = client->SyncFrameMetrics(aScrollOffset.x, aScrollOffset.y, aZoom,
+                                                         aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
+                                                         aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
+                                                         aIsFirstPaint);
 
-    client->SyncFrameMetrics(aScrollOffset, aZoom, aCssPageRect,
-                             aLayersUpdated, aDisplayPort, aDisplayResolution,
-                             aIsFirstPaint, aFixedLayerMargins, aOffset);
+    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
+    if (!viewTransformJObj) {
+        return;
+    }
+    ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj);
+
+    aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop();
+    aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight();
+    aFixedLayerMargins.bottom = viewTransform->getfixedLayerMarginBottom();
+    aFixedLayerMargins.left = viewTransform->getfixedLayerMarginLeft();
+
+    aOffset.x = viewTransform->getoffsetX();
+    aOffset.y = viewTransform->getoffsetY();
+
+    delete viewTransform;
 }
 
 AndroidBridge::AndroidBridge()
   : mLayerClient(nullptr),
     mNativePanZoomController(nullptr)
 {
 }
 
@@ -1594,55 +1618,22 @@ static void
 JavaThreadDetachFunc(void *arg)
 {
     JNIEnv *env = (JNIEnv*) arg;
     JavaVM *vm = nullptr;
     env->GetJavaVM(&vm);
     vm->DetachCurrentThread();
 }
 
-extern "C" {
-    __attribute__ ((visibility("default")))
-    JNIEnv * GetJNIForThread()
-    {
-        JNIEnv *jEnv = nullptr;
-        JavaVM *jVm  = mozilla::AndroidBridge::GetVM();
-        if (!jVm) {
-            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "Returned a null VM");
-            return nullptr;
-        }
-        jEnv = static_cast<JNIEnv*>(PR_GetThreadPrivate(sJavaEnvThreadIndex));
-
-        if (jEnv)
-            return jEnv;
-
-        int status = jVm->GetEnv((void**) &jEnv, JNI_VERSION_1_2);
-        if (status) {
-
-            status = jVm->AttachCurrentThread(&jEnv, nullptr);
-            if (status) {
-                __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread",  "Could not attach");
-                return nullptr;
-            }
-            
-            PR_SetThreadPrivate(sJavaEnvThreadIndex, jEnv);
-        }
-        if (!jEnv) {
-            __android_log_print(ANDROID_LOG_INFO, "GetJNIForThread", "returning NULL");
-        }
-        return jEnv;
-    }
-}
-
 uint32_t
 AndroidBridge::GetScreenOrientation()
 {
     ALOG_BRIDGE("AndroidBridge::GetScreenOrientation");
 
-    int16_t orientation = GetScreenOrientationWrapper();
+    int16_t orientation = GeckoAppShell::GetScreenOrientationWrapper();
 
     if (!orientation)
         return dom::eScreenOrientation_None;
 
     return static_cast<dom::ScreenOrientation>(orientation);
 }
 
 void
@@ -1658,17 +1649,17 @@ AndroidBridge::GetProxyForURI(const nsAC
                               const int32_t      aPort,
                               nsACString & aResult)
 {
     JNIEnv* env = GetJNIEnv();
     if (!env)
         return NS_ERROR_FAILURE;
 
     AutoLocalJNIFrame jniFrame(env);
-    jstring jstrRet = GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
+    jstring jstrRet = GeckoAppShell::GetProxyForURIWrapper(NS_ConvertUTF8toUTF16(aSpec),
                                             NS_ConvertUTF8toUTF16(aScheme),
                                             NS_ConvertUTF8toUTF16(aHost),
                                             aPort);
 
     if (!jstrRet)
         return NS_ERROR_FAILURE;
 
     nsJNIString jniStr(jstrRet, env);
@@ -1694,34 +1685,34 @@ NS_IMETHODIMP nsAndroidBridge::SetBrowse
 
 void
 AndroidBridge::AddPluginView(jobject view, const LayoutDeviceRect& rect, bool isFullScreen) {
     nsWindow* win = nsWindow::TopWindow();
     if (!win)
         return;
 
     CSSRect cssRect = rect / win->GetDefaultScale();
-    AddPluginViewWrapper(view, cssRect.x, cssRect.y, cssRect.width, cssRect.height, isFullScreen);
+    GeckoAppShell::AddPluginViewWrapper(view, cssRect.x, cssRect.y, cssRect.width, cssRect.height, isFullScreen);
 }
 
 extern "C"
 __attribute__ ((visibility("default")))
 jobject JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
 
 bool
 AndroidBridge::GetThreadNameJavaProfiling(uint32_t aThreadId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
     if (!env)
         return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jstring jstrThreadName = GetThreadNameJavaProfilingWrapper(aThreadId);
+    jstring jstrThreadName = GeckoJavaSampler::GetThreadNameJavaProfilingWrapper(aThreadId);
 
     if (!jstrThreadName)
         return false;
 
     nsJNIString jniStr(jstrThreadName, env);
     CopyUTF16toUTF8(jniStr.get(), aResult);
     return true;
 }
@@ -1731,17 +1722,17 @@ AndroidBridge::GetFrameNameJavaProfiling
                                           uint32_t aFrameId, nsCString & aResult)
 {
     JNIEnv* env = GetJNIForThread();
     if (!env)
         return false;
 
     AutoLocalJNIFrame jniFrame(env);
 
-    jstring jstrSampleName = GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId);
+    jstring jstrSampleName = GeckoJavaSampler::GetFrameNameJavaProfilingWrapper(aThreadId, aSampleId, aFrameId);
 
     if (!jstrSampleName)
         return false;
 
     nsJNIString jniStr(jstrSampleName, env);
     CopyUTF16toUTF8(jniStr.get(), aResult);
     env->DeleteLocalRef(jstrSampleName);
     return true;
@@ -1852,71 +1843,144 @@ nsresult AndroidBridge::CaptureThumbnail
     }
     NS_ENSURE_SUCCESS(rv, rv);
     return NS_OK;
 }
 
 void
 AndroidBridge::GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort)
 {
+
+    ALOG_BRIDGE("Enter: %s", __PRETTY_FUNCTION__);
     JNIEnv* env = GetJNIEnv();
-    if (!env || !mLayerClient)
+    if (!env || !mLayerClient || mLayerClient->isNull()) {
+
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
+    }
     AutoLocalJNIFrame jniFrame(env, 0);
-    mLayerClient->GetDisplayPort(&jniFrame, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, metrics, displayPort);
+
+    float x, y, width, height,
+        pageLeft, pageTop, pageRight, pageBottom,
+        cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
+        zoom;
+    metrics->GetX(&x);
+    metrics->GetY(&y);
+    metrics->GetWidth(&width);
+    metrics->GetHeight(&height);
+    metrics->GetPageLeft(&pageLeft);
+    metrics->GetPageTop(&pageTop);
+    metrics->GetPageRight(&pageRight);
+    metrics->GetPageBottom(&pageBottom);
+    metrics->GetCssPageLeft(&cssPageLeft);
+    metrics->GetCssPageTop(&cssPageTop);
+    metrics->GetCssPageRight(&cssPageRight);
+    metrics->GetCssPageBottom(&cssPageBottom);
+    metrics->GetZoom(&zoom);
+
+    ImmutableViewportMetrics jmetrics = ImmutableViewportMetrics(pageLeft, pageTop, pageRight, pageBottom,
+                                                                 cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
+                                                                 x, y, x + width, y + height,
+                                                                 zoom);
+
+    jobject jobj = mLayerClient->GetDisplayPort(aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics.wrappedObject());
+    if (!jobj) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+        return;
+    }
+    DisplayPortMetrics* displayPortMetrics = DisplayPortMetrics::Wrap(jobj);
+
+    AndroidRectF rect(env, displayPortMetrics->getMPosition());
+    if (jniFrame.CheckForException()) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    float resolution = displayPortMetrics->getResolution();
+    if (jniFrame.CheckForException()) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    *displayPort = new nsAndroidDisplayport(rect, resolution);
+    (*displayPort)->AddRef();
+
+    delete displayPortMetrics;
+    ALOG_BRIDGE("Exit: %s", __PRETTY_FUNCTION__);
 }
 
 void
 AndroidBridge::ContentDocumentChanged()
 {
-    JNIEnv* env = GetJNIEnv();
-    if (!env || !mLayerClient)
+    if (!mLayerClient) {
         return;
-    AutoLocalJNIFrame jniFrame(env, 0);
-    mLayerClient->ContentDocumentChanged(&jniFrame);
+    }
+    mLayerClient->ContentDocumentChanged();
 }
 
 bool
 AndroidBridge::IsContentDocumentDisplayed()
 {
     JNIEnv* env = GetJNIEnv();
     if (!env || !mLayerClient)
         return false;
-    AutoLocalJNIFrame jniFrame(env, 0);
-    return mLayerClient->IsContentDocumentDisplayed(&jniFrame);
+
+    return mLayerClient->IsContentDocumentDisplayed();
 }
 
 bool
 AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY)
 {
-    AndroidGeckoLayerClient *client = mLayerClient;
-    if (!client)
+    GeckoLayerClient *client = mLayerClient;
+    if (!client) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return false;
+    }
 
-    return client->ProgressiveUpdateCallback(aHasPendingNewThebesContent, aDisplayPort, aDisplayResolution, aDrawingCritical, aViewport, aScaleX, aScaleY);
+    jobject progressiveUpdateDataJObj = client->ProgressiveUpdateCallback(aHasPendingNewThebesContent,
+                                                                   (float)aDisplayPort.x,
+                                                                   (float)aDisplayPort.y,
+                                                                   (float)aDisplayPort.width,
+                                                                   (float)aDisplayPort.height,
+                                                                          aDisplayResolution,
+                                                                         !aDrawingCritical);
+
+    NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
+
+    ProgressiveUpdateData* progressiveUpdateData = ProgressiveUpdateData::Wrap(progressiveUpdateDataJObj);
+
+    aViewport.x = progressiveUpdateData->getx();
+    aViewport.y = progressiveUpdateData->gety();
+    aViewport.width = progressiveUpdateData->getwidth();
+    aViewport.height = progressiveUpdateData->getheight();
+    aScaleX = aScaleY = progressiveUpdateData->getscale();
+
+    bool ret = progressiveUpdateData->getabort();
+    delete progressiveUpdateData;
+
+    return ret;
 }
 
-jobject
+NativePanZoomController*
 AndroidBridge::SetNativePanZoomController(jobject obj)
 {
-    jobject old = mNativePanZoomController;
-    mNativePanZoomController = obj;
+    NativePanZoomController* old = mNativePanZoomController;
+    mNativePanZoomController = NativePanZoomController::Wrap(obj);
     return old;
 }
 
 void
 AndroidBridge::RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics)
 {
     ALOG_BRIDGE("AndroidBridge::RequestContentRepaint");
 
     CSSToScreenScale resolution = aFrameMetrics.mZoom;
     ScreenRect dp = (aFrameMetrics.mDisplayPort + aFrameMetrics.mScrollOffset) * resolution;
 
-    RequestContentRepaintWrapper(mNativePanZoomController,
-        dp.x, dp.y, dp.width, dp.height, resolution.scale);
+    mNativePanZoomController->RequestContentRepaintWrapper(dp.x, dp.y, dp.width, dp.height, resolution.scale);
 }
 
 void
 AndroidBridge::HandleDoubleTap(const CSSIntPoint& aPoint)
 {
     nsCString data = nsPrintfCString("{ \"x\": %d, \"y\": %d }", aPoint.x, aPoint.y);
     nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeBroadcastEvent(
             NS_LITERAL_CSTRING("Gesture:DoubleTap"), data));
@@ -1963,17 +2027,17 @@ AndroidBridge::PostDelayedTask(Task* aTa
     if (i == mDelayedTaskQueue.Length()) {
         // this new task will run after all the existing tasks in the queue
         mDelayedTaskQueue.AppendElement(newTask);
     }
     if (i == 0) {
         // if we're inserting it at the head of the queue, notify Java because
         // we need to get a callback at an earlier time than the last scheduled
         // callback
-        PostDelayedCallbackWrapper(mNativePanZoomController, (int64_t)aDelayMs);
+        mNativePanZoomController->PostDelayedCallbackWrapper((int64_t)aDelayMs);
     }
 }
 
 int64_t
 AndroidBridge::RunDelayedTasks()
 {
     while (mDelayedTaskQueue.Length() > 0) {
         DelayedTask* nextTask = mDelayedTaskQueue[0];
--- a/widget/android/AndroidBridge.h
+++ b/widget/android/AndroidBridge.h
@@ -9,17 +9,17 @@
 #include <jni.h>
 #include <android/log.h>
 #include <cstdlib>
 #include <pthread.h>
 
 #include "nsCOMPtr.h"
 #include "nsCOMArray.h"
 
-#include "AndroidJavaWrappers.h"
+#include "GeneratedJNIWrappers.h"
 
 #include "nsIMutableArray.h"
 #include "nsIMIMEInfo.h"
 #include "nsColor.h"
 #include "gfxRect.h"
 
 #include "nsIAndroidBridge.h"
 #include "nsIMobileMessageCallback.h"
@@ -36,24 +36,25 @@
 class nsWindow;
 class nsIDOMMozSmsMessage;
 class nsIObserver;
 
 /* See the comment in AndroidBridge about this function before using it */
 extern "C" JNIEnv * GetJNIForThread();
 
 extern bool mozilla_AndroidBridge_SetMainThread(pthread_t);
-extern jclass GetGeckoAppShellClass();
 
 namespace base {
 class Thread;
 } // end namespace base
 
 typedef void* EGLSurface;
 
+using namespace mozilla::widget::android;
+
 namespace mozilla {
 
 namespace hal {
 class BatteryInformation;
 class NetworkInformation;
 } // namespace hal
 
 namespace dom {
@@ -155,20 +156,16 @@ public:
                 return nullptr;
             }
             return sBridge->mJNIEnv;
 
         }
         return nullptr;
     }
 
-    static jclass GetGeckoAppShellClass() {
-        return sBridge->mGeckoAppShellClass;
-    }
-
     // The bridge needs to be constructed via ConstructBridge first,
     // and then once the Gecko main thread is spun up (Gecko side),
     // SetMainThread should be called which will create the JNIEnv for
     // us to use.  toolkit/xre/nsAndroidStartup.cpp calls
     // SetMainThread.
     bool SetMainThread(pthread_t thr);
 
     /* These are all implemented in Java */
@@ -178,36 +175,32 @@ public:
     nsresult CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int32_t bufH, int32_t tabId, jobject buffer);
     void GetDisplayPort(bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
     void ContentDocumentChanged();
     bool IsContentDocumentDisplayed();
 
     bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
 
     void SetLayerClient(JNIEnv* env, jobject jobj);
-    AndroidGeckoLayerClient &GetLayerClient() { return *mLayerClient; }
+    GeckoLayerClient* GetLayerClient() { return mLayerClient; }
 
     bool GetHandlersForURL(const nsAString& aURL,
                            nsIMutableArray* handlersArray = nullptr,
                            nsIHandlerApp **aDefaultApp = nullptr,
                            const nsAString& aAction = EmptyString());
 
     bool GetHandlersForMimeType(const nsAString& aMimeType,
                                 nsIMutableArray* handlersArray = nullptr,
                                 nsIHandlerApp **aDefaultApp = nullptr,
                                 const nsAString& aAction = EmptyString());
 
     void GetMimeTypeFromExtensions(const nsACString& aFileExt, nsCString& aMimeType);
     void GetExtensionFromMimeType(const nsACString& aMimeType, nsACString& aFileExt);
 
     bool GetClipboardText(nsAString& aText);
-    
-    void EmptyClipboard();
-
-    bool ClipboardHasText();
 
     void ShowAlertNotification(const nsAString& aImageUrl,
                                const nsAString& aAlertTitle,
                                const nsAString& aAlertText,
                                const nsAString& aAlertData,
                                nsIObserver *aAlertListener,
                                const nsAString& aAlertName);
 
@@ -215,18 +208,16 @@ public:
     int GetScreenDepth();
 
     void ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions);
     void ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType);
     void ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback);
 
     void Vibrate(const nsTArray<uint32_t>& aPattern);
 
-    void HideProgressDialogOnce();
-
     void GetSystemColors(AndroidSystemColors *aColors);
 
     void GetIconForExtension(const nsACString& aFileExt, uint32_t aIconSize, uint8_t * const aBuf);
 
     // Switch Java to composite with the Gecko Compositor thread
     void RegisterCompositor(JNIEnv* env = nullptr);
     EGLSurface CreateEGLSurfaceForCompositor();
 
@@ -335,17 +326,17 @@ protected:
 
     // the global JavaVM
     JavaVM *mJavaVM;
 
     // the JNIEnv for the main thread
     JNIEnv *mJNIEnv;
     pthread_t mThread;
 
-    AndroidGeckoLayerClient *mLayerClient;
+    GeckoLayerClient *mLayerClient = NULL;
 
     // the android.telephony.SmsMessage class
     jclass mAndroidSmsMessageClass;
 
     AndroidBridge();
     ~AndroidBridge();
 
     void InitStubs(JNIEnv *jEnv);
@@ -376,17 +367,17 @@ protected:
 
     // For native surface stuff
     jclass jSurfaceClass;
     jfieldID jSurfacePointerField;
 
     jclass jLayerView;
 
     jfieldID jEGLSurfacePointerField;
-    jobject mGLControllerObj;
+    GLController *mGLControllerObj;
 
     // some convinient types to have around
     jclass jStringClass;
 
     // calls we've dlopened from libjnigraphics.so
     int (* AndroidBitmap_getInfo)(JNIEnv *env, jobject bitmap, void *info);
     int (* AndroidBitmap_lockPixels)(JNIEnv *env, jobject bitmap, void **buffer);
     int (* AndroidBitmap_unlockPixels)(JNIEnv *env, jobject bitmap);
@@ -400,25 +391,24 @@ protected:
     int (* ANativeWindow_unlockAndPost)(void *window);
 
     int (* Surface_lock)(void* surface, void* surfaceInfo, void* region, bool block);
     int (* Surface_unlockAndPost)(void* surface);
     void (* Region_constructor)(void* region);
     void (* Region_set)(void* region, void* rect);
 
 private:
-    jobject mNativePanZoomController;
+    NativePanZoomController* mNativePanZoomController;
     // This will always be accessed from one thread (the APZC "controller"
     // thread, which is the Java UI thread), so we don't need to do locking
     // to touch it
     nsTArray<DelayedTask*> mDelayedTaskQueue;
 
 public:
-    #include "GeneratedJNIWrappers.h"
-    jobject SetNativePanZoomController(jobject obj);
+    NativePanZoomController* SetNativePanZoomController(jobject obj);
     // GeckoContentController methods
     void RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE;
     void HandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
     void HandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
     void HandleLongTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
     void SendAsyncScrollDOMEvent(mozilla::layers::FrameMetrics::ViewID aScrollId,
                                  const CSSRect& aContentRect,
                                  const CSSSize& aScrollableSize) MOZ_OVERRIDE;
--- a/widget/android/AndroidBridgeUtilities.h
+++ b/widget/android/AndroidBridgeUtilities.h
@@ -12,8 +12,22 @@
 #define getMethod(fname, ftype) \
     AndroidBridge::GetMethodID(jEnv, jClass, fname, ftype)
 
 #define getStaticField(fname, ftype) \
     AndroidBridge::GetStaticFieldID(jEnv, jClass, fname, ftype)
 
 #define getStaticMethod(fname, ftype) \
     AndroidBridge::GetStaticMethodID(jEnv, jClass, fname, ftype)
+
+#ifndef ALOG
+#if defined(DEBUG) || defined(FORCE_ALOG)
+#define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
+#else
+#define ALOG(args...) ((void)0)
+#endif
+#endif
+
+#ifdef DEBUG
+#define ALOG_BRIDGE(args...) ALOG(args)
+#else
+#define ALOG_BRIDGE(args...) ((void)0)
+#endif
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -856,20 +856,20 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject instance)
 {
     if (!AndroidBridge::Bridge()) {
         return;
     }
 
-    jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(env->NewGlobalRef(instance));
-    if (oldRef) {
+    NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(instance);
+    if (oldRef && !oldRef->isNull()) {
         MOZ_ASSERT(false, "Registering a new NPZC when we already have one");
-        env->DeleteGlobalRef(oldRef);
+        delete oldRef;
     }
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
 {
     APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
     if (controller) {
@@ -900,21 +900,21 @@ Java_org_mozilla_gecko_gfx_NativePanZoom
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject instance)
 {
     if (!AndroidBridge::Bridge()) {
         return;
     }
 
-    jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(nullptr);
-    if (!oldRef) {
+    NativePanZoomController* oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL);
+    if (!oldRef || oldRef->isNull()) {
         MOZ_ASSERT(false, "Clearing a non-existent NPZC");
     } else {
-        env->DeleteGlobalRef(oldRef);
+        delete oldRef;
     }
 }
 
 NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented)
 {
     APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
     if (controller) {
--- a/widget/android/AndroidJNIWrapper.cpp
+++ b/widget/android/AndroidJNIWrapper.cpp
@@ -9,22 +9,16 @@
 #include <dlfcn.h>
 #include <prthread.h>
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Assertions.h"
 #include "nsThreadUtils.h"
 #include "AndroidBridge.h"
 
-#ifdef DEBUG
-#define ALOG_BRIDGE(args...) ALOG(args)
-#else
-#define ALOG_BRIDGE(args...)
-#endif
-
 extern "C" {
   jclass __jsjni_GetGlobalClassRef(const char *className);
 }
 
 class GetGlobalClassRefRunnable : public nsRunnable {
   public:
     GetGlobalClassRefRunnable(const char *className, jclass *foundClass) :
         mClassName(className), mResult(foundClass) {}
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -1,23 +1,23 @@
 /* -*- Mode: c++; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AndroidJavaWrappers.h"
 #include "AndroidBridge.h"
 #include "AndroidBridgeUtilities.h"
-#include "nsIAndroidBridge.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIWidget.h"
 #include "mozilla/TouchEvents.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
+using namespace mozilla::widget::android;
 
 jclass AndroidGeckoEvent::jGeckoEventClass = 0;
 jfieldID AndroidGeckoEvent::jActionField = 0;
 jfieldID AndroidGeckoEvent::jTypeField = 0;
 jfieldID AndroidGeckoEvent::jAckNeededField = 0;
 jfieldID AndroidGeckoEvent::jTimeField = 0;
 jfieldID AndroidGeckoEvent::jPoints = 0;
 jfieldID AndroidGeckoEvent::jPointIndicies = 0;
@@ -86,77 +86,31 @@ jclass AndroidLocation::jLocationClass =
 jmethodID AndroidLocation::jGetLatitudeMethod = 0;
 jmethodID AndroidLocation::jGetLongitudeMethod = 0;
 jmethodID AndroidLocation::jGetAltitudeMethod = 0;
 jmethodID AndroidLocation::jGetAccuracyMethod = 0;
 jmethodID AndroidLocation::jGetBearingMethod = 0;
 jmethodID AndroidLocation::jGetSpeedMethod = 0;
 jmethodID AndroidLocation::jGetTimeMethod = 0;
 
-jclass AndroidGeckoLayerClient::jGeckoLayerClientClass = 0;
-jclass AndroidGeckoLayerClient::jViewportClass = 0;
-jclass AndroidGeckoLayerClient::jDisplayportClass = 0;
-jmethodID AndroidGeckoLayerClient::jSetFirstPaintViewport = 0;
-jmethodID AndroidGeckoLayerClient::jSetPageRect = 0;
-jmethodID AndroidGeckoLayerClient::jSyncViewportInfoMethod = 0;
-jmethodID AndroidGeckoLayerClient::jSyncFrameMetricsMethod = 0;
-jmethodID AndroidGeckoLayerClient::jCreateFrameMethod = 0;
-jmethodID AndroidGeckoLayerClient::jActivateProgramMethod = 0;
-jmethodID AndroidGeckoLayerClient::jDeactivateProgramMethod = 0;
-jmethodID AndroidGeckoLayerClient::jGetDisplayPort = 0;
-jmethodID AndroidGeckoLayerClient::jContentDocumentChanged = 0;
-jmethodID AndroidGeckoLayerClient::jIsContentDocumentDisplayed = 0;
-jmethodID AndroidGeckoLayerClient::jViewportCtor = 0;
-jfieldID AndroidGeckoLayerClient::jDisplayportPosition = 0;
-jfieldID AndroidGeckoLayerClient::jDisplayportResolution = 0;
-jmethodID AndroidGeckoLayerClient::jProgressiveUpdateCallbackMethod = 0;
-
-jclass AndroidLayerRendererFrame::jLayerRendererFrameClass = 0;
-jmethodID AndroidLayerRendererFrame::jBeginDrawingMethod = 0;
-jmethodID AndroidLayerRendererFrame::jDrawBackgroundMethod = 0;
-jmethodID AndroidLayerRendererFrame::jDrawForegroundMethod = 0;
-jmethodID AndroidLayerRendererFrame::jEndDrawingMethod = 0;
-
-jclass AndroidViewTransform::jViewTransformClass = 0;
-jfieldID AndroidViewTransform::jXField = 0;
-jfieldID AndroidViewTransform::jYField = 0;
-jfieldID AndroidViewTransform::jScaleField = 0;
-jfieldID AndroidViewTransform::jFixedLayerMarginLeft = 0;
-jfieldID AndroidViewTransform::jFixedLayerMarginTop = 0;
-jfieldID AndroidViewTransform::jFixedLayerMarginRight = 0;
-jfieldID AndroidViewTransform::jFixedLayerMarginBottom = 0;
-jfieldID AndroidViewTransform::jOffsetXField = 0;
-jfieldID AndroidViewTransform::jOffsetYField = 0;
-
-jclass AndroidProgressiveUpdateData::jProgressiveUpdateDataClass = 0;
-jfieldID AndroidProgressiveUpdateData::jXField = 0;
-jfieldID AndroidProgressiveUpdateData::jYField = 0;
-jfieldID AndroidProgressiveUpdateData::jWidthField = 0;
-jfieldID AndroidProgressiveUpdateData::jHeightField = 0;
-jfieldID AndroidProgressiveUpdateData::jScaleField = 0;
-jfieldID AndroidProgressiveUpdateData::jShouldAbortField = 0;
-
 RefCountedJavaObject::~RefCountedJavaObject() {
     if (mObject)
         GetJNIForThread()->DeleteGlobalRef(mObject);
     mObject = nullptr;
 }
 
 void
 mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
 {
     AndroidGeckoEvent::InitGeckoEventClass(jEnv);
     AndroidPoint::InitPointClass(jEnv);
     AndroidLocation::InitLocationClass(jEnv);
     AndroidRect::InitRectClass(jEnv);
     AndroidRectF::InitRectFClass(jEnv);
-    AndroidGeckoLayerClient::InitGeckoLayerClientClass(jEnv);
-    AndroidLayerRendererFrame::InitLayerRendererFrameClass(jEnv);
-    AndroidViewTransform::InitViewTransformClass(jEnv);
-    AndroidProgressiveUpdateData::InitProgressiveUpdateDataClass(jEnv);
+    InitStubs(jEnv);
 }
 
 void
 AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
 {
     initInit();
 
     jGeckoEventClass = getClassGlobalRef("org/mozilla/gecko/GeckoEvent");
@@ -285,92 +239,16 @@ AndroidRectF::InitRectFClass(JNIEnv *jEn
     jRectClass = getClassGlobalRef("android/graphics/RectF");
 
     jBottomField = getField("bottom", "F");
     jLeftField = getField("left", "F");
     jTopField = getField("top", "F");
     jRightField = getField("right", "F");
 }
 
-void
-AndroidGeckoLayerClient::InitGeckoLayerClientClass(JNIEnv *jEnv)
-{
-    initInit();
-
-    jGeckoLayerClientClass = getClassGlobalRef("org/mozilla/gecko/gfx/GeckoLayerClient");
-
-    jProgressiveUpdateCallbackMethod = getMethod("progressiveUpdateCallback",
-                                                 "(ZFFFFFZ)Lorg/mozilla/gecko/gfx/ProgressiveUpdateData;");
-    jSetFirstPaintViewport = getMethod("setFirstPaintViewport", "(FFFFFFF)V");
-    jSetPageRect = getMethod("setPageRect", "(FFFF)V");
-    jSyncViewportInfoMethod = getMethod("syncViewportInfo",
-                                        "(IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
-    jSyncFrameMetricsMethod = getMethod("syncFrameMetrics",
-                                        "(FFFFFFFZIIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;");
-    jCreateFrameMethod = getMethod("createFrame", "()Lorg/mozilla/gecko/gfx/LayerRenderer$Frame;");
-    jActivateProgramMethod = getMethod("activateProgram", "()V");
-    jDeactivateProgramMethod = getMethod("deactivateProgram", "()V");
-    jGetDisplayPort = getMethod("getDisplayPort", "(ZZILorg/mozilla/gecko/gfx/ImmutableViewportMetrics;)Lorg/mozilla/gecko/gfx/DisplayPortMetrics;");
-    jContentDocumentChanged = getMethod("contentDocumentChanged", "()V");
-    jIsContentDocumentDisplayed = getMethod("isContentDocumentDisplayed", "()Z");
-
-    jViewportClass = getClassGlobalRef("org/mozilla/gecko/gfx/ImmutableViewportMetrics");
-    jViewportCtor = getMethod("<init>", "(FFFFFFFFFFFFF)V");
-
-    jDisplayportClass = getClassGlobalRef("org/mozilla/gecko/gfx/DisplayPortMetrics");
-    jDisplayportPosition = getField("mPosition", "Landroid/graphics/RectF;");
-    jDisplayportResolution = getField("resolution", "F");
-}
-
-void
-AndroidLayerRendererFrame::InitLayerRendererFrameClass(JNIEnv *jEnv)
-{
-    initInit();
-
-    jLayerRendererFrameClass = getClassGlobalRef("org/mozilla/gecko/gfx/LayerRenderer$Frame");
-
-    jBeginDrawingMethod = getMethod("beginDrawing", "()V");
-    jDrawBackgroundMethod = getMethod("drawBackground", "()V");
-    jDrawForegroundMethod = getMethod("drawForeground", "()V");
-    jEndDrawingMethod = getMethod("endDrawing", "()V");
-}
-
-void
-AndroidViewTransform::InitViewTransformClass(JNIEnv *jEnv)
-{
-    initInit();
-
-    jViewTransformClass = getClassGlobalRef("org/mozilla/gecko/gfx/ViewTransform");
-
-    jXField = getField("x", "F");
-    jYField = getField("y", "F");
-    jScaleField = getField("scale", "F");
-    jFixedLayerMarginLeft = getField("fixedLayerMarginLeft", "F");
-    jFixedLayerMarginTop = getField("fixedLayerMarginTop", "F");
-    jFixedLayerMarginRight = getField("fixedLayerMarginRight", "F");
-    jFixedLayerMarginBottom = getField("fixedLayerMarginBottom", "F");
-    jOffsetXField = getField("offsetX", "F");
-    jOffsetYField = getField("offsetY", "F");
-}
-
-void
-AndroidProgressiveUpdateData::InitProgressiveUpdateDataClass(JNIEnv *jEnv)
-{
-    initInit();
-
-    jProgressiveUpdateDataClass = getClassGlobalRef("org/mozilla/gecko/gfx/ProgressiveUpdateData");
-
-    jXField = getField("x", "F");
-    jYField = getField("y", "F");
-    jWidthField = getField("width", "F");
-    jHeightField = getField("height", "F");
-    jScaleField = getField("scale", "F");
-    jShouldAbortField = getField("abort", "Z");
-}
-
 #undef initInit
 #undef initClassGlobalRef
 #undef getField
 #undef getMethod
 
 void
 AndroidGeckoEvent::ReadPointArray(nsTArray<nsIntPoint> &points,
                                   JNIEnv *jenv,
@@ -887,471 +765,18 @@ AndroidPoint::Init(JNIEnv *jenv, jobject
         mX = jenv->GetIntField(jobj, jXField);
         mY = jenv->GetIntField(jobj, jYField);
     } else {
         mX = 0;
         mY = 0;
     }
 }
 
-void
-AndroidGeckoLayerClient::Init(jobject jobj)
-{
-    NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
-    wrapped_obj = jobj;
-}
-
-void
-AndroidLayerRendererFrame::Init(JNIEnv *env, jobject jobj)
-{
-    if (!isNull()) {
-        Dispose(env);
-    }
-
-    wrapped_obj = env->NewGlobalRef(jobj);
-}
-
-void
-AndroidLayerRendererFrame::Dispose(JNIEnv *env)
-{
-    if (isNull()) {
-        return;
-    }
-
-    env->DeleteGlobalRef(wrapped_obj);
-    wrapped_obj = 0;
-}
-
-void
-AndroidViewTransform::Init(jobject jobj)
-{
-    NS_ABORT_IF_FALSE(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
-    wrapped_obj = jobj;
-}
-
-void
-AndroidProgressiveUpdateData::Init(jobject jobj)
-{
-    NS_ABORT_IF_FALSE(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
-    wrapped_obj = jobj;
-}
-
-void
-AndroidGeckoLayerClient::SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect)
-{
-    NS_ASSERTION(!isNull(), "SetFirstPaintViewport called on null layer client!");
-    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env, 0);
-    return env->CallVoidMethod(wrapped_obj, jSetFirstPaintViewport, (float)aOffset.x, (float)aOffset.y, aZoom.scale,
-                               aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
-}
-
-void
-AndroidGeckoLayerClient::SetPageRect(const CSSRect& aCssPageRect)
-{
-    NS_ASSERTION(!isNull(), "SetPageRect called on null layer client!");
-    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env, 0);
-    return env->CallVoidMethod(wrapped_obj, jSetPageRect,
-                               aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost());
-}
-
-void
-AndroidGeckoLayerClient::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
-                                          bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
-                                          LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
-{
-    NS_ASSERTION(!isNull(), "SyncViewportInfo called on null layer client!");
-    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env);
-
-    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncViewportInfoMethod,
-                                                      aDisplayPort.x, aDisplayPort.y,
-                                                      aDisplayPort.width, aDisplayPort.height,
-                                                      aDisplayResolution.scale, aLayersUpdated);
-    if (jniFrame.CheckForException())
-        return;
-
-    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
-
-    AndroidViewTransform viewTransform;
-    viewTransform.Init(viewTransformJObj);
-
-    aScrollOffset = ScreenPoint(viewTransform.GetX(env), viewTransform.GetY(env));
-    aScale.scale = viewTransform.GetScale(env);
-    viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
-
-    aOffset.x = viewTransform.GetOffsetX(env);
-    aOffset.y = viewTransform.GetOffsetY(env);
-}
-
-void
-AndroidGeckoLayerClient::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
-                                          bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
-                                          bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset)
-{
-    NS_ASSERTION(!isNull(), "SyncFrameMetrics called on null layer client!");
-    JNIEnv *env = GetJNIForThread();    // this is called on the compositor thread
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env);
-
-    // convert the displayport rect from scroll-relative CSS pixels to document-relative device pixels
-    LayerRect dpUnrounded = aDisplayPort * aDisplayResolution;
-    dpUnrounded += LayerPoint::FromUnknownPoint(aScrollOffset.ToUnknownPoint());
-    LayerIntRect dp = gfx::RoundedToInt(dpUnrounded);
-
-    jobject viewTransformJObj = env->CallObjectMethod(wrapped_obj, jSyncFrameMetricsMethod,
-            aScrollOffset.x, aScrollOffset.y, aZoom,
-            aCssPageRect.x, aCssPageRect.y, aCssPageRect.XMost(), aCssPageRect.YMost(),
-            aLayersUpdated, dp.x, dp.y, dp.width, dp.height, aDisplayResolution.scale,
-            aIsFirstPaint);
-
-    if (jniFrame.CheckForException())
-        return;
-
-    NS_ABORT_IF_FALSE(viewTransformJObj, "No view transform object!");
-
-    AndroidViewTransform viewTransform;
-    viewTransform.Init(viewTransformJObj);
-    viewTransform.GetFixedLayerMargins(env, aFixedLayerMargins);
-    aOffset.x = viewTransform.GetOffsetX(env);
-    aOffset.y = viewTransform.GetOffsetY(env);
-}
-
-bool
-AndroidGeckoLayerClient::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent,
-                                                   const LayerRect& aDisplayPort,
-                                                   float aDisplayResolution,
-                                                   bool aDrawingCritical,
-                                                   gfx::Rect& aViewport,
-                                                   float& aScaleX,
-                                                   float& aScaleY)
-{
-    JNIEnv *env = AndroidBridge::GetJNIEnv();
-    if (!env)
-        return false;
-
-    AutoJObject progressiveUpdateDataJObj(env, env->CallObjectMethod(wrapped_obj,
-                                                                     jProgressiveUpdateCallbackMethod,
-                                                                     aHasPendingNewThebesContent,
-                                                                     (float)aDisplayPort.x,
-                                                                     (float)aDisplayPort.y,
-                                                                     (float)aDisplayPort.width,
-                                                                     (float)aDisplayPort.height,
-                                                                     aDisplayResolution,
-                                                                     !aDrawingCritical));
-    if (env->ExceptionCheck()) {
-        env->ExceptionDescribe();
-        env->ExceptionClear();
-        return false;
-    }
-
-    NS_ABORT_IF_FALSE(progressiveUpdateDataJObj, "No progressive update data!");
-
-    AndroidProgressiveUpdateData progressiveUpdateData(progressiveUpdateDataJObj);
-
-    aViewport.x = progressiveUpdateData.GetX(env);
-    aViewport.y = progressiveUpdateData.GetY(env);
-    aViewport.width = progressiveUpdateData.GetWidth(env);
-    aViewport.height = progressiveUpdateData.GetHeight(env);
-    aScaleX = aScaleY = progressiveUpdateData.GetScale(env);
-
-    return progressiveUpdateData.GetShouldAbort(env);
-}
-
-jobject ConvertToJavaViewportMetrics(JNIEnv* env, nsIAndroidViewport* metrics) {
-    float x, y, width, height,
-        pageLeft, pageTop, pageRight, pageBottom,
-        cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
-        zoom;
-    metrics->GetX(&x);
-    metrics->GetY(&y);
-    metrics->GetWidth(&width);
-    metrics->GetHeight(&height);
-    metrics->GetPageLeft(&pageLeft);
-    metrics->GetPageTop(&pageTop);
-    metrics->GetPageRight(&pageRight);
-    metrics->GetPageBottom(&pageBottom);
-    metrics->GetCssPageLeft(&cssPageLeft);
-    metrics->GetCssPageTop(&cssPageTop);
-    metrics->GetCssPageRight(&cssPageRight);
-    metrics->GetCssPageBottom(&cssPageBottom);
-    metrics->GetZoom(&zoom);
-
-    jobject jobj = env->NewObject(AndroidGeckoLayerClient::jViewportClass, AndroidGeckoLayerClient::jViewportCtor,
-                                  pageLeft, pageTop, pageRight, pageBottom,
-                                  cssPageLeft, cssPageTop, cssPageRight, cssPageBottom,
-                                  x, y, x + width, y + height,
-                                  zoom);
-    return jobj;
-}
-
-class nsAndroidDisplayport MOZ_FINAL : public nsIAndroidDisplayport
-{
-public:
-    NS_DECL_ISUPPORTS
-    virtual nsresult GetLeft(float *aLeft) { *aLeft = mLeft; return NS_OK; }
-    virtual nsresult GetTop(float *aTop) { *aTop = mTop; return NS_OK; }
-    virtual nsresult GetRight(float *aRight) { *aRight = mRight; return NS_OK; }
-    virtual nsresult GetBottom(float *aBottom) { *aBottom = mBottom; return NS_OK; }
-    virtual nsresult GetResolution(float *aResolution) { *aResolution = mResolution; return NS_OK; }
-    virtual nsresult SetLeft(float aLeft) { mLeft = aLeft; return NS_OK; }
-    virtual nsresult SetTop(float aTop) { mTop = aTop; return NS_OK; }
-    virtual nsresult SetRight(float aRight) { mRight = aRight; return NS_OK; }
-    virtual nsresult SetBottom(float aBottom) { mBottom = aBottom; return NS_OK; }
-    virtual nsresult SetResolution(float aResolution) { mResolution = aResolution; return NS_OK; }
-
-    nsAndroidDisplayport(AndroidRectF aRect, float aResolution):
-        mLeft(aRect.Left()), mTop(aRect.Top()), mRight(aRect.Right()), mBottom(aRect.Bottom()), mResolution(aResolution) {}
-
-private:
-    ~nsAndroidDisplayport() {}
-    float mLeft, mTop, mRight, mBottom, mResolution;
-};
-
 NS_IMPL_ISUPPORTS1(nsAndroidDisplayport, nsIAndroidDisplayport)
 
-void createDisplayPort(AutoLocalJNIFrame *jniFrame, jobject jobj, nsIAndroidDisplayport** displayPort) {
-    JNIEnv* env = jniFrame->GetEnv();
-    AndroidRectF rect(env, env->GetObjectField(jobj, AndroidGeckoLayerClient::jDisplayportPosition));
-    if (jniFrame->CheckForException()) return;
-    float resolution = env->GetFloatField(jobj, AndroidGeckoLayerClient::jDisplayportResolution);
-    if (jniFrame->CheckForException()) return;
-    *displayPort = new nsAndroidDisplayport(rect, resolution);
-}
-
-void
-AndroidGeckoLayerClient::GetDisplayPort(AutoLocalJNIFrame *jniFrame, bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort)
-{
-    jobject jmetrics = ConvertToJavaViewportMetrics(jniFrame->GetEnv(), metrics);
-    if (jniFrame->CheckForException()) return;
-    if (!jmetrics)
-        return;
-    jobject jobj = jniFrame->GetEnv()->CallObjectMethod(wrapped_obj, jGetDisplayPort, aPageSizeUpdate, aIsBrowserContentDisplayed, tabId, jmetrics);
-    if (jniFrame->CheckForException()) return;
-    createDisplayPort(jniFrame, jobj, displayPort);
-    (*displayPort)->AddRef();
-}
-
-void
-AndroidGeckoLayerClient::ContentDocumentChanged(AutoLocalJNIFrame *jniFrame)
-{
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jContentDocumentChanged);
-}
-
-bool
-AndroidGeckoLayerClient::IsContentDocumentDisplayed(AutoLocalJNIFrame *jniFrame)
-{
-    return jniFrame->GetEnv()->CallBooleanMethod(wrapped_obj, jIsContentDocumentDisplayed);
-}
-
-bool
-AndroidGeckoLayerClient::CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jobject frameJObj = jniFrame->GetEnv()->CallObjectMethod(wrapped_obj, jCreateFrameMethod);
-    if (jniFrame->CheckForException())
-        return false;
-    NS_ABORT_IF_FALSE(frameJObj, "No frame object!");
-
-    aFrame.Init(jniFrame->GetEnv(), frameJObj);
-    return true;
-}
-
-bool
-AndroidGeckoLayerClient::ActivateProgram(AutoLocalJNIFrame *jniFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jActivateProgramMethod);
-    if (jniFrame->CheckForException())
-        return false;
-
-    return true;
-}
-
-bool
-AndroidGeckoLayerClient::DeactivateProgram(AutoLocalJNIFrame *jniFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDeactivateProgramMethod);
-    if (jniFrame->CheckForException())
-        return false;
-
-    return true;
-}
-
-bool
-AndroidLayerRendererFrame::BeginDrawing(AutoLocalJNIFrame *jniFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jBeginDrawingMethod);
-    if (jniFrame->CheckForException())
-        return false;
-
-    return true;
-}
-
-bool
-AndroidLayerRendererFrame::DrawBackground(AutoLocalJNIFrame *jniFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawBackgroundMethod);
-    if (jniFrame->CheckForException())
-        return false;
-
-    return true;
-}
-
-bool
-AndroidLayerRendererFrame::DrawForeground(AutoLocalJNIFrame *jniFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jDrawForegroundMethod);
-    if (jniFrame->CheckForException())
-        return false;
-
-    return true;
-}
-
-bool
-AndroidLayerRendererFrame::EndDrawing(AutoLocalJNIFrame *jniFrame)
-{
-    if (!jniFrame || !jniFrame->GetEnv())
-        return false;
-
-    jniFrame->GetEnv()->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
-    if (jniFrame->CheckForException())
-        return false;
-
-    return true;
-}
-
-float
-AndroidViewTransform::GetX(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jXField);
-}
-
-float
-AndroidViewTransform::GetY(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jYField);
-}
-
-float
-AndroidViewTransform::GetScale(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jScaleField);
-}
-
-void
-AndroidViewTransform::GetFixedLayerMargins(JNIEnv *env, LayerMargin &aFixedLayerMargins)
-{
-    if (!env)
-        return;
-
-    aFixedLayerMargins.top = env->GetFloatField(wrapped_obj, jFixedLayerMarginTop);
-    aFixedLayerMargins.right = env->GetFloatField(wrapped_obj, jFixedLayerMarginRight);
-    aFixedLayerMargins.bottom = env->GetFloatField(wrapped_obj, jFixedLayerMarginBottom);
-    aFixedLayerMargins.left = env->GetFloatField(wrapped_obj, jFixedLayerMarginLeft);
-}
-
-float
-AndroidViewTransform::GetOffsetX(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jOffsetXField);
-}
-
-float
-AndroidViewTransform::GetOffsetY(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jOffsetYField);
-}
-
-float
-AndroidProgressiveUpdateData::GetX(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jXField);
-}
-
-float
-AndroidProgressiveUpdateData::GetY(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jYField);
-}
-
-float
-AndroidProgressiveUpdateData::GetWidth(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jWidthField);
-}
-
-float
-AndroidProgressiveUpdateData::GetHeight(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jHeightField);
-}
-
-float
-AndroidProgressiveUpdateData::GetScale(JNIEnv *env)
-{
-    if (!env)
-        return 0.0f;
-    return env->GetFloatField(wrapped_obj, jScaleField);
-}
-
-bool
-AndroidProgressiveUpdateData::GetShouldAbort(JNIEnv *env)
-{
-    if (!env)
-        return false;
-    return env->GetBooleanField(wrapped_obj, jShouldAbortField);
-}
-
 void
 AndroidRect::Init(JNIEnv *jenv, jobject jobj)
 {
     NS_ASSERTION(wrapped_obj == nullptr, "Init called on non-null wrapped_obj!");
 
     wrapped_obj = jobj;
 
     if (jobj) {
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -10,39 +10,31 @@
 #include <android/input.h>
 #include <android/log.h>
 
 #include "nsGeoPosition.h"
 #include "nsRect.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsIObserver.h"
+#include "nsIAndroidBridge.h"
 #include "mozilla/gfx/Rect.h"
 #include "mozilla/dom/Touch.h"
 #include "mozilla/EventForwards.h"
 #include "InputData.h"
 #include "Units.h"
 
 //#define FORCE_ALOG 1
 
-#ifndef ALOG
-#if defined(DEBUG) || defined(FORCE_ALOG)
-#define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
-#else
-#define ALOG(args...) ((void)0)
-#endif
-#endif
-
 class nsIAndroidDisplayport;
 class nsIAndroidViewport;
 class nsIWidget;
 
 namespace mozilla {
 
-class AndroidGeckoLayerClient;
 class AutoLocalJNIFrame;
 
 void InitAndroidJavaWrappers(JNIEnv *jEnv);
 
 /*
  * Note: do not store global refs to any WrappedJavaObject;
  * these are live only during a particular JNI method, as
  * NewGlobalRef is -not- called on the jobject.
@@ -70,29 +62,61 @@ public:
 private:
     int32_t mRefCnt;
     jobject mObject;
 };
 
 class WrappedJavaObject {
 public:
     WrappedJavaObject() :
-        wrapped_obj(0)
+        wrapped_obj(NULL)
     { }
 
-    WrappedJavaObject(jobject jobj) {
+    WrappedJavaObject(jobject jobj) : wrapped_obj(NULL) {
         Init(jobj);
     }
 
     void Init(jobject jobj) {
         wrapped_obj = jobj;
     }
 
     bool isNull() const {
-        return wrapped_obj == 0;
+        return wrapped_obj == NULL;
+    }
+
+    jobject wrappedObject() const {
+        return wrapped_obj;
+    }
+
+protected:
+    jobject wrapped_obj;
+};
+
+class AutoGlobalWrappedJavaObject : protected WrappedJavaObject{
+public:
+    AutoGlobalWrappedJavaObject() :
+        wrapped_obj(NULL)
+    { }
+
+    AutoGlobalWrappedJavaObject(jobject jobj, JNIEnv* env) : wrapped_obj(NULL) {
+        Init(jobj, env);
+    }
+
+    virtual ~AutoGlobalWrappedJavaObject();
+    void Dispose();
+
+    void Init(jobject jobj, JNIEnv* env) {
+        if (!isNull()) {
+            env->DeleteGlobalRef(wrapped_obj);
+        }
+        wrapped_obj = env->NewGlobalRef(jobj);
+    }
+
+    bool isNull() const {
+        return wrapped_obj == NULL;
     }
 
     jobject wrappedObject() const {
         return wrapped_obj;
     }
 
 protected:
     jobject wrapped_obj;
@@ -181,138 +205,16 @@ protected:
 
     static jclass jRectClass;
     static jfieldID jBottomField;
     static jfieldID jLeftField;
     static jfieldID jRightField;
     static jfieldID jTopField;
 };
 
-class AndroidViewTransform : public WrappedJavaObject {
-public:
-    static void InitViewTransformClass(JNIEnv *jEnv);
-
-    void Init(jobject jobj);
-
-    AndroidViewTransform() {}
-    AndroidViewTransform(jobject jobj) { Init(jobj); }
-
-    float GetX(JNIEnv *env);
-    float GetY(JNIEnv *env);
-    float GetScale(JNIEnv *env);
-    void GetFixedLayerMargins(JNIEnv *env, LayerMargin &aFixedLayerMargins);
-    float GetOffsetX(JNIEnv *env);
-    float GetOffsetY(JNIEnv *env);
-
-private:
-    static jclass jViewTransformClass;
-    static jfieldID jXField;
-    static jfieldID jYField;
-    static jfieldID jScaleField;
-    static jfieldID jFixedLayerMarginLeft;
-    static jfieldID jFixedLayerMarginTop;
-    static jfieldID jFixedLayerMarginRight;
-    static jfieldID jFixedLayerMarginBottom;
-    static jfieldID jOffsetXField;
-    static jfieldID jOffsetYField;
-};
-
-class AndroidProgressiveUpdateData : public WrappedJavaObject {
-public:
-    static void InitProgressiveUpdateDataClass(JNIEnv *jEnv);
-
-    void Init(jobject jobj);
-
-    AndroidProgressiveUpdateData() {}
-    AndroidProgressiveUpdateData(jobject jobj) { Init(jobj); }
-
-    float GetX(JNIEnv *env);
-    float GetY(JNIEnv *env);
-    float GetWidth(JNIEnv *env);
-    float GetHeight(JNIEnv *env);
-    float GetScale(JNIEnv *env);
-    bool GetShouldAbort(JNIEnv *env);
-
-private:
-    static jclass jProgressiveUpdateDataClass;
-    static jfieldID jXField;
-    static jfieldID jYField;
-    static jfieldID jWidthField;
-    static jfieldID jHeightField;
-    static jfieldID jScaleField;
-    static jfieldID jShouldAbortField;
-};
-
-class AndroidLayerRendererFrame : public WrappedJavaObject {
-public:
-    static void InitLayerRendererFrameClass(JNIEnv *jEnv);
-
-    void Init(JNIEnv *env, jobject jobj);
-    void Dispose(JNIEnv *env);
-
-    bool BeginDrawing(AutoLocalJNIFrame *jniFrame);
-    bool DrawBackground(AutoLocalJNIFrame *jniFrame);
-    bool DrawForeground(AutoLocalJNIFrame *jniFrame);
-    bool EndDrawing(AutoLocalJNIFrame *jniFrame);
-
-private:
-    static jclass jLayerRendererFrameClass;
-    static jmethodID jBeginDrawingMethod;
-    static jmethodID jDrawBackgroundMethod;
-    static jmethodID jDrawForegroundMethod;
-    static jmethodID jEndDrawingMethod;
-};
-
-class AndroidGeckoLayerClient : public WrappedJavaObject {
-public:
-    static void InitGeckoLayerClientClass(JNIEnv *jEnv);
-
-    void Init(jobject jobj);
-
-    AndroidGeckoLayerClient() {}
-    AndroidGeckoLayerClient(jobject jobj) { Init(jobj); }
-
-    void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect);
-    void SetPageRect(const CSSRect& aCssPageRect);
-    void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
-                          bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale,
-                          LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset);
-    void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect,
-                          bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution,
-                          bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset);
-    bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, gfx::Rect& aViewport, float& aScaleX, float& aScaleY);
-    bool CreateFrame(AutoLocalJNIFrame *jniFrame, AndroidLayerRendererFrame& aFrame);
-    bool ActivateProgram(AutoLocalJNIFrame *jniFrame);
-    bool DeactivateProgram(AutoLocalJNIFrame *jniFrame);
-    void GetDisplayPort(AutoLocalJNIFrame *jniFrame, bool aPageSizeUpdate, bool aIsBrowserContentDisplayed, int32_t tabId, nsIAndroidViewport* metrics, nsIAndroidDisplayport** displayPort);
-    void ContentDocumentChanged(AutoLocalJNIFrame *jniFrame);
-    bool IsContentDocumentDisplayed(AutoLocalJNIFrame *jniFrame);
-
-protected:
-    static jclass jGeckoLayerClientClass;
-    static jmethodID jSetFirstPaintViewport;
-    static jmethodID jSetPageRect;
-    static jmethodID jSyncViewportInfoMethod;
-    static jmethodID jSyncFrameMetricsMethod;
-    static jmethodID jCreateFrameMethod;
-    static jmethodID jActivateProgramMethod;
-    static jmethodID jDeactivateProgramMethod;
-    static jmethodID jGetDisplayPort;
-    static jmethodID jContentDocumentChanged;
-    static jmethodID jIsContentDocumentDisplayed;
-    static jmethodID jProgressiveUpdateCallbackMethod;
-
-public:
-    static jclass jViewportClass;
-    static jclass jDisplayportClass;
-    static jmethodID jViewportCtor;
-    static jfieldID jDisplayportPosition;
-    static jfieldID jDisplayportResolution;
-};
-
 enum {
     // These keycode masks are not defined in android/keycodes.h:
     AKEYCODE_ESCAPE             = 111,
     AKEYCODE_FORWARD_DEL        = 112,
     AKEYCODE_CTRL_LEFT          = 113,
     AKEYCODE_CTRL_RIGHT         = 114,
     AKEYCODE_CAPS_LOCK          = 115,
     AKEYCODE_SCROLL_LOCK        = 116,
@@ -428,16 +330,39 @@ enum {
     AMETA_META_RIGHT_ON         = 0x00040000,
 
     AMETA_ALT_MASK              = AMETA_ALT_LEFT_ON   | AMETA_ALT_RIGHT_ON   | AMETA_ALT_ON,
     AMETA_CTRL_MASK             = AMETA_CTRL_LEFT_ON  | AMETA_CTRL_RIGHT_ON  | AMETA_CTRL_ON,
     AMETA_META_MASK             = AMETA_META_LEFT_ON  | AMETA_META_RIGHT_ON  | AMETA_META_ON,
     AMETA_SHIFT_MASK            = AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON | AMETA_SHIFT_ON,
 };
 
+class nsAndroidDisplayport MOZ_FINAL : public nsIAndroidDisplayport
+{
+public:
+    NS_DECL_ISUPPORTS
+    virtual nsresult GetLeft(float *aLeft) { *aLeft = mLeft; return NS_OK; }
+    virtual nsresult GetTop(float *aTop) { *aTop = mTop; return NS_OK; }
+    virtual nsresult GetRight(float *aRight) { *aRight = mRight; return NS_OK; }
+    virtual nsresult GetBottom(float *aBottom) { *aBottom = mBottom; return NS_OK; }
+    virtual nsresult GetResolution(float *aResolution) { *aResolution = mResolution; return NS_OK; }
+    virtual nsresult SetLeft(float aLeft) { mLeft = aLeft; return NS_OK; }
+    virtual nsresult SetTop(float aTop) { mTop = aTop; return NS_OK; }
+    virtual nsresult SetRight(float aRight) { mRight = aRight; return NS_OK; }
+    virtual nsresult SetBottom(float aBottom) { mBottom = aBottom; return NS_OK; }
+    virtual nsresult SetResolution(float aResolution) { mResolution = aResolution; return NS_OK; }
+
+    nsAndroidDisplayport(AndroidRectF aRect, float aResolution):
+        mLeft(aRect.Left()), mTop(aRect.Top()), mRight(aRect.Right()), mBottom(aRect.Bottom()), mResolution(aResolution) {}
+
+private:
+    ~nsAndroidDisplayport() {}
+    float mLeft, mTop, mRight, mBottom, mResolution;
+};
+
 class AndroidMotionEvent
 {
 public:
     enum {
         ACTION_DOWN = 0,
         ACTION_UP = 1,
         ACTION_MOVE = 2,
         ACTION_CANCEL = 3,
--- a/widget/android/nsAppShell.cpp
+++ b/widget/android/nsAppShell.cpp
@@ -29,16 +29,17 @@
 
 #include "mozilla/Services.h"
 #include "mozilla/unused.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Hal.h"
 #include "prenv.h"
 
 #include "AndroidBridge.h"
+#include "AndroidBridgeUtilities.h"
 #include <android/log.h>
 #include <pthread.h>
 #include <wchar.h>
 
 #include "mozilla/dom/ScreenOrientation.h"
 
 #include "GeckoProfiler.h"
 #ifdef MOZ_ANDROID_HISTORY
@@ -77,45 +78,45 @@ public:
         mBrowserApp(aBrowserApp), mPoints(aPoints), mTabId(aTabId), mBuffer(aBuffer) {}
 
     virtual nsresult Run() {
         jobject buffer = mBuffer->GetObject();
         nsCOMPtr<nsIDOMWindow> domWindow;
         nsCOMPtr<nsIBrowserTab> tab;
         mBrowserApp->GetBrowserTab(mTabId, getter_AddRefs(tab));
         if (!tab) {
-            AndroidBridge::Bridge()->SendThumbnail(buffer, mTabId, false);
+            ThumbnailHelper::SendThumbnail(buffer, mTabId, false);
             return NS_ERROR_FAILURE;
         }
 
         tab->GetWindow(getter_AddRefs(domWindow));
         if (!domWindow) {
-            AndroidBridge::Bridge()->SendThumbnail(buffer, mTabId, false);
+            ThumbnailHelper::SendThumbnail(buffer, mTabId, false);
             return NS_ERROR_FAILURE;
         }
 
         NS_ASSERTION(mPoints.Length() == 1, "Thumbnail event does not have enough coordinates");
 
         nsresult rv = AndroidBridge::Bridge()->CaptureThumbnail(domWindow, mPoints[0].x, mPoints[0].y, mTabId, buffer);
-        AndroidBridge::Bridge()->SendThumbnail(buffer, mTabId, NS_SUCCEEDED(rv));
+        ThumbnailHelper::SendThumbnail(buffer, mTabId, NS_SUCCEEDED(rv));
         return rv;
     }
 private:
     nsCOMPtr<nsIAndroidBrowserApp> mBrowserApp;
     nsTArray<nsIntPoint> mPoints;
     int mTabId;
     nsRefPtr<RefCountedJavaObject> mBuffer;
 };
 
 class WakeLockListener MOZ_FINAL : public nsIDOMMozWakeLockListener {
  public:
   NS_DECL_ISUPPORTS;
 
   nsresult Callback(const nsAString& topic, const nsAString& state) {
-    AndroidBridge::Bridge()->NotifyWakeLockChanged(topic, state);
+    GeckoAppShell::NotifyWakeLockChanged(topic, state);
     return NS_OK;
   }
 };
 
 NS_IMPL_ISUPPORTS1(WakeLockListener, nsIDOMMozWakeLockListener)
 nsCOMPtr<nsIPowerManagerService> sPowerManagerService = nullptr;
 StaticRefPtr<WakeLockListener> sWakeLockListener;
 
@@ -197,27 +198,27 @@ nsAppShell::Init()
 
     Preferences::AddStrongObservers(this, kObservedPrefs);
 
     bool match;
     rv = Preferences::GetBool(PREFNAME_MATCH_OS, &match);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (match) {
-        bridge->SetSelectedLocale(EmptyString());
+        GeckoAppShell::SetSelectedLocale(EmptyString());
         return NS_OK;
     }
 
     nsAutoString locale;
     rv = Preferences::GetLocalizedString(PREFNAME_UA_LOCALE, &locale);
     if (NS_FAILED(rv)) {
         rv = Preferences::GetString(PREFNAME_UA_LOCALE, &locale);
     }
 
-    bridge->SetSelectedLocale(locale);
+    GeckoAppShell::SetSelectedLocale(locale);
     mAllowCoalescingTouches = Preferences::GetBool(PREFNAME_COALESCE_TOUCHES, true);
     return rv;
 }
 
 NS_IMETHODIMP
 nsAppShell::Observe(nsISupports* aSubject,
                     const char* aTopic,
                     const PRUnichar* aData)
@@ -239,27 +240,27 @@ nsAppShell::Observe(nsISupports* aSubjec
             return NS_OK;
         }
 
         bool match;
         nsresult rv = Preferences::GetBool(PREFNAME_MATCH_OS, &match);
         NS_ENSURE_SUCCESS(rv, rv);
 
         if (match) {
-            bridge->SetSelectedLocale(EmptyString());
+            GeckoAppShell::SetSelectedLocale(EmptyString());
             return NS_OK;
         }
 
         nsAutoString locale;
         if (NS_FAILED(Preferences::GetLocalizedString(PREFNAME_UA_LOCALE,
                                                       &locale))) {
             locale = Preferences::GetString(PREFNAME_UA_LOCALE);
         }
 
-        bridge->SetSelectedLocale(locale);
+        GeckoAppShell::SetSelectedLocale(locale);
 
         mAllowCoalescingTouches = Preferences::GetBool(PREFNAME_COALESCE_TOUCHES, true);
         return NS_OK;
     }
     return NS_OK;
 }
 
 void
@@ -595,17 +596,17 @@ nsAppShell::ProcessNextNativeEvent(bool 
         break;
 
     default:
         nsWindow::OnGlobalAndroidEvent(curEvent);
         break;
     }
 
     if (curEvent->AckNeeded()) {
-        AndroidBridge::Bridge()->AcknowledgeEvent();
+        GeckoAppShell::AcknowledgeEvent();
     }
 
     EVLOG("nsAppShell: -- done event %p %d", (void*)curEvent.get(), curEvent->Type());
 
     return true;
 }
 
 void
--- a/widget/android/nsClipboard.cpp
+++ b/widget/android/nsClipboard.cpp
@@ -40,17 +40,17 @@ nsClipboard::SetData(nsITransferable *aT
   nsCOMPtr<nsISupportsString> supportsString = do_QueryInterface(tmp);
   // No support for non-text data
   NS_ENSURE_TRUE(supportsString, NS_ERROR_NOT_IMPLEMENTED);
   nsAutoString buffer;
   supportsString->GetData(buffer);
 
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     if (AndroidBridge::Bridge())
-      AndroidBridge::Bridge()->SetClipboardText(buffer);
+      Clipboard::SetClipboardText(buffer);
     else
       return NS_ERROR_NOT_IMPLEMENTED;
 
   } else {
     bool isPrivateData = false;
     aTransferable->GetIsPrivateData(&isPrivateData);
     ContentChild::GetSingleton()->SendSetClipboardText(buffer, isPrivateData,
                                                        aWhichClipboard);
@@ -97,17 +97,17 @@ nsClipboard::GetData(nsITransferable *aT
 
 NS_IMETHODIMP
 nsClipboard::EmptyClipboard(int32_t aWhichClipboard)
 {
   if (aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_NOT_IMPLEMENTED;
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     if (AndroidBridge::Bridge())
-      AndroidBridge::Bridge()->EmptyClipboard();
+      Clipboard::ClearText();
   } else {
     ContentChild::GetSingleton()->SendEmptyClipboard();
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -115,17 +115,17 @@ nsClipboard::HasDataMatchingFlavors(cons
                                     uint32_t aLength, int32_t aWhichClipboard,
                                     bool *aHasText)
 {
   *aHasText = false;
   if (aWhichClipboard != kGlobalClipboard)
     return NS_ERROR_NOT_IMPLEMENTED;
   if (XRE_GetProcessType() == GeckoProcessType_Default) {
     if (AndroidBridge::Bridge())
-      *aHasText = AndroidBridge::Bridge()->ClipboardHasText();
+      *aHasText = Clipboard::HasText();
   } else {
     ContentChild::GetSingleton()->SendClipboardHasText(aHasText);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsClipboard::SupportsSelectionClipboard(bool *aIsSupported)
--- a/widget/android/nsIMEPicker.cpp
+++ b/widget/android/nsIMEPicker.cpp
@@ -17,11 +17,11 @@ nsIMEPicker::nsIMEPicker()
 nsIMEPicker::~nsIMEPicker()
 {
   /* destructor code */
 }
 
 /* void show (); */
 NS_IMETHODIMP nsIMEPicker::Show()
 {
-    AndroidBridge::Bridge()->ShowInputMethodPicker();
+    GeckoAppShell::ShowInputMethodPicker();
     return NS_OK;
 }
--- a/widget/android/nsLookAndFeel.cpp
+++ b/widget/android/nsLookAndFeel.cpp
@@ -462,17 +462,17 @@ nsLookAndFeel::GetFontImpl(FontID aID, n
 
 /*virtual*/
 bool
 nsLookAndFeel::GetEchoPasswordImpl()
 {
     if (!mInitializedShowPassword) {
         if (XRE_GetProcessType() == GeckoProcessType_Default) {
             if (AndroidBridge::Bridge())
-                mShowPassword = AndroidBridge::Bridge()->GetShowPasswordSetting();
+                mShowPassword = GeckoAppShell::GetShowPasswordSetting();
             else
                 NS_ASSERTION(AndroidBridge::Bridge() != nullptr, "AndroidBridge is not available!");
         } else {
             ContentChild::GetSingleton()->SendGetShowPasswordSetting(&mShowPassword);
         }
         mInitializedShowPassword = true;
     }
     return mShowPassword;
--- a/widget/android/nsScreenManagerAndroid.cpp
+++ b/widget/android/nsScreenManagerAndroid.cpp
@@ -54,17 +54,17 @@ NS_IMETHODIMP
 nsScreenAndroid::GetColorDepth(int32_t *aColorDepth)
 {
     return GetPixelDepth(aColorDepth);
 }
 
 void
 nsScreenAndroid::ApplyMinimumBrightness(uint32_t aBrightness)
 {
-  AndroidBridge::Bridge()->SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
+  GeckoAppShell::SetKeepScreenOn(aBrightness == BRIGHTNESS_FULL);
 }
 
 NS_IMPL_ISUPPORTS1(nsScreenManagerAndroid, nsIScreenManager)
 
 nsScreenManagerAndroid::nsScreenManagerAndroid()
 {
     mOneScreen = new nsScreenAndroid(nullptr);
 }
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -47,16 +47,17 @@ using mozilla::unused;
 #include "mozilla/layers/AsyncCompositionManager.h"
 #include "mozilla/layers/APZCTreeManager.h"
 #include "GLContext.h"
 #include "GLContextProvider.h"
 
 #include "nsTArray.h"
 
 #include "AndroidBridge.h"
+#include "AndroidBridgeUtilities.h"
 #include "android_npapi.h"
 
 #include "imgIEncoder.h"
 
 #include "nsString.h"
 #include "GeckoProfiler.h" // For PROFILER_LABEL
 
 using namespace mozilla;
@@ -349,17 +350,17 @@ nsWindow::GetDefaultScaleInternal()
 {
     static double density = 0.0;
 
     if (density != 0.0) {
         return density;
     }
 
     if (AndroidBridge::Bridge()) {
-        density = AndroidBridge::Bridge()->GetDensity();
+        density = GeckoAppShell::GetDensity();
     }
 
     if (!density) {
         density = 1.0;
     }
 
     return density;
 }
@@ -514,17 +515,17 @@ nsWindow::PlaceBehind(nsTopLevelWidgetZP
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::SetSizeMode(int32_t aMode)
 {
     switch (aMode) {
         case nsSizeMode_Minimized:
-            AndroidBridge::Bridge()->MoveTaskToBack();
+            GeckoAppShell::MoveTaskToBack();
             break;
         case nsSizeMode_Fullscreen:
             MakeFullScreen(true);
             break;
     }
     return NS_OK;
 }
 
@@ -695,17 +696,17 @@ nsWindow::DispatchEvent(WidgetGUIEvent* 
         return status;
     }
     return nsEventStatus_eIgnore;
 }
 
 NS_IMETHODIMP
 nsWindow::MakeFullScreen(bool aFullScreen)
 {
-    AndroidBridge::Bridge()->SetFullScreen(aFullScreen);
+    GeckoAppShell::SetFullScreen(aFullScreen);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::SetWindowClass(const nsAString& xulWinType)
 {
     return NS_OK;
 }
@@ -1212,26 +1213,26 @@ bool nsWindow::OnMultitouchEvent(Android
 
     // if the last event we got was a down event, then by now we know for sure whether
     // this block has been default-prevented or not. if we haven't already sent the
     // notification for this block, do so now.
     if (sLastWasDownEvent && !sDefaultPreventedNotified) {
         // if this event is a down event, that means it's the start of a new block, and the
         // previous block should not be default-prevented
         bool defaultPrevented = isDownEvent ? false : preventDefaultActions;
-        AndroidBridge::Bridge()->NotifyDefaultPrevented(defaultPrevented);
+        GeckoAppShell::NotifyDefaultPrevented(defaultPrevented);
         sDefaultPreventedNotified = true;
     }
 
     // now, if this event is a down event, then we might already know that it has been
     // default-prevented. if so, we send the notification right away; otherwise we wait
     // for the next event.
     if (isDownEvent) {
         if (preventDefaultActions) {
-            AndroidBridge::Bridge()->NotifyDefaultPrevented(true);
+            GeckoAppShell::NotifyDefaultPrevented(true);
             sDefaultPreventedNotified = true;
         } else {
             sDefaultPreventedNotified = false;
         }
     }
     sLastWasDownEvent = isDownEvent;
 
     return preventDefaultActions;
@@ -1830,44 +1831,44 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *
             mIMESelectionChanged = false;
             // NotifyIMEOfTextChange also notifies selection
             // Use 'INT32_MAX / 2' here because subsequent text changes might
             // combine with this text change, and overflow might occur if
             // we just use INT32_MAX
             NotifyIMEOfTextChange(0, INT32_MAX / 2, INT32_MAX / 2);
             FlushIMEChanges();
         }
-        AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
+        GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
         return;
     } else if (ae->Action() == AndroidGeckoEvent::IME_UPDATE_CONTEXT) {
-        AndroidBridge::NotifyIMEContext(mInputContext.mIMEState.mEnabled,
+        GeckoAppShell::NotifyIMEContext(mInputContext.mIMEState.mEnabled,
                                         mInputContext.mHTMLInputType,
                                         mInputContext.mHTMLInputInputmode,
                                         mInputContext.mActionHint);
         mIMEUpdatingContext = false;
         return;
     }
     if (mIMEMaskEventsCount > 0) {
         // Still reply to events, but don't do anything else
         if (ae->Action() == AndroidGeckoEvent::IME_SYNCHRONIZE ||
             ae->Action() == AndroidGeckoEvent::IME_REPLACE_TEXT) {
-            AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
+            GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
         }
         return;
     }
     switch (ae->Action()) {
     case AndroidGeckoEvent::IME_FLUSH_CHANGES:
         {
             FlushIMEChanges();
         }
         break;
     case AndroidGeckoEvent::IME_SYNCHRONIZE:
         {
             FlushIMEChanges();
-            AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
+            GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
         }
         break;
     case AndroidGeckoEvent::IME_REPLACE_TEXT:
         {
             /*
                 Replace text in Gecko thread from ae->Start() to ae->End()
                   with the string ae->Characters()
 
@@ -1889,17 +1890,17 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *
             }
 
             if (!mIMEKeyEvents.IsEmpty()) {
                 for (uint32_t i = 0; i < mIMEKeyEvents.Length(); i++) {
                     OnKeyEvent(&mIMEKeyEvents[i]);
                 }
                 mIMEKeyEvents.Clear();
                 FlushIMEChanges();
-                AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
+                GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
                 break;
             }
 
             {
                 WidgetCompositionEvent event(true, NS_COMPOSITION_START, this);
                 InitEvent(event, nullptr);
                 DispatchEvent(&event);
             }
@@ -1911,17 +1912,17 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *
             }
             {
                 WidgetCompositionEvent event(true, NS_COMPOSITION_END, this);
                 InitEvent(event, nullptr);
                 event.data = ae->Characters();
                 DispatchEvent(&event);
             }
             FlushIMEChanges();
-            AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
+            GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
         }
         break;
     case AndroidGeckoEvent::IME_SET_SELECTION:
         {
             /*
                 Set Gecko selection to ae->Start() to ae->End()
 
                 Selection updates are masked to prevent Java from being
@@ -2091,17 +2092,17 @@ nsWindow::UserActivity()
 
 NS_IMETHODIMP
 nsWindow::NotifyIME(NotificationToIME aNotification)
 {
     switch (aNotification) {
         case REQUEST_TO_COMMIT_COMPOSITION:
             //ALOGIME("IME: REQUEST_TO_COMMIT_COMPOSITION: s=%d", aState);
             RemoveIMEComposition();
-            AndroidBridge::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
+            GeckoAppShell::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
             return NS_OK;
         case REQUEST_TO_CANCEL_COMPOSITION:
             ALOGIME("IME: REQUEST_TO_CANCEL_COMPOSITION");
 
             // Cancel composition on Gecko side
             if (mIMEComposing) {
                 nsRefPtr<nsWindow> kungFuDeathGrip(this);
 
@@ -2110,33 +2111,33 @@ nsWindow::NotifyIME(NotificationToIME aN
                 DispatchEvent(&textEvent);
 
                 WidgetCompositionEvent compEvent(true, NS_COMPOSITION_END,
                                                  this);
                 InitEvent(compEvent, nullptr);
                 DispatchEvent(&compEvent);
             }
 
-            AndroidBridge::NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
+            GeckoAppShell::NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
             return NS_OK;
         case NOTIFY_IME_OF_FOCUS:
             ALOGIME("IME: NOTIFY_IME_OF_FOCUS");
-            AndroidBridge::NotifyIME(NOTIFY_IME_OF_FOCUS);
+            GeckoAppShell::NotifyIME(NOTIFY_IME_OF_FOCUS);
             return NS_OK;
         case NOTIFY_IME_OF_BLUR:
             ALOGIME("IME: NOTIFY_IME_OF_BLUR");
 
             // Mask events because we lost focus. On the next focus event,
             // Gecko will notify Java, and Java will send an acknowledge focus
             // event back to Gecko. That is where we unmask event handling
             mIMEMaskEventsCount++;
             mIMEComposing = false;
             mIMEComposingText.Truncate();
 
-            AndroidBridge::NotifyIME(NOTIFY_IME_OF_BLUR);
+            GeckoAppShell::NotifyIME(NOTIFY_IME_OF_BLUR);
             return NS_OK;
         case NOTIFY_IME_OF_SELECTION_CHANGE:
             if (mIMEMaskSelectionUpdate) {
                 return NS_OK;
             }
 
             ALOGIME("IME: NOTIFY_IME_OF_SELECTION_CHANGE");
 
@@ -2186,17 +2187,17 @@ nsWindow::SetInputContext(const InputCon
         aContext.mIMEState.mOpen != IMEState::OPEN) {
         enabled = IMEState::DISABLED;
     }
 
     mInputContext.mIMEState.mEnabled = enabled;
 
     if (enabled == IMEState::ENABLED && aAction.UserMightRequestOpenVKB()) {
         // Don't reset keyboard when we should simply open the vkb
-        AndroidBridge::NotifyIME(AndroidBridge::NOTIFY_IME_OPEN_VKB);
+        GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_OPEN_VKB);
         return;
     }
 
     if (mIMEUpdatingContext) {
         return;
     }
     AndroidGeckoEvent *event = AndroidGeckoEvent::MakeIMEEvent(
             AndroidGeckoEvent::IME_UPDATE_CONTEXT);
@@ -2242,32 +2243,32 @@ nsWindow::FlushIMEChanges()
         WidgetQueryContentEvent event(true, NS_QUERY_TEXT_CONTENT, this);
         InitEvent(event, nullptr);
         event.InitForQueryTextContent(change.mStart,
                                       change.mNewEnd - change.mStart);
         DispatchEvent(&event);
         if (!event.mSucceeded)
             return;
 
-        AndroidBridge::NotifyIMEChange(event.mReply.mString,
+        GeckoAppShell::NotifyIMEChange(event.mReply.mString,
                                        change.mStart,
                                        change.mOldEnd,
                                        change.mNewEnd);
     }
     mIMETextChanges.Clear();
 
     if (mIMESelectionChanged) {
         WidgetQueryContentEvent event(true, NS_QUERY_SELECTED_TEXT, this);
         InitEvent(event, nullptr);
 
         DispatchEvent(&event);
         if (!event.mSucceeded)
             return;
 
-        AndroidBridge::NotifyIMEChange(EmptyString(),
+        GeckoAppShell::NotifyIMEChange(EmptyString(),
                              (int32_t) event.GetSelectionStart(),
                              (int32_t) event.GetSelectionEnd(), -1);
         mIMESelectionChanged = false;
     }
 }
 
 NS_IMETHODIMP
 nsWindow::NotifyIMEOfTextChange(uint32_t aStart,
@@ -2352,54 +2353,61 @@ nsWindow::GetIMEUpdatePreference()
     return nsIMEUpdatePreference(notifications, true);
 }
 
 void
 nsWindow::DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect)
 {
     JNIEnv *env = GetJNIForThread();
     NS_ABORT_IF_FALSE(env, "No JNI environment at DrawWindowUnderlay()!");
-    if (!env)
+    if (!env) {
         return;
+    }
 
     AutoLocalJNIFrame jniFrame(env);
 
-    AndroidGeckoLayerClient& client = AndroidBridge::Bridge()->GetLayerClient();
-    if (!client.CreateFrame(&jniFrame, mLayerRendererFrame)) return;
-    
-    if (!WidgetPaintsBackground())
+    GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
+    if (!client || client->isNull()) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
+        return;
+    }
+
+    jobject frameObj = client->CreateFrame();
+    NS_ABORT_IF_FALSE(frameObj, "No frame object!");
+    if (!frameObj) {
+        ALOG_BRIDGE("Exceptional Exit: %s", __PRETTY_FUNCTION__);
         return;
+    }
 
-    if (!client.ActivateProgram(&jniFrame)) return;
-    if (!mLayerRendererFrame.BeginDrawing(&jniFrame)) return;
-    if (!mLayerRendererFrame.DrawBackground(&jniFrame)) return;
-    if (!client.DeactivateProgram(&jniFrame)) return; // redundant, but in case somebody adds code after this...
+    mLayerRendererFrame.Init(frameObj, env);
+    if (!WidgetPaintsBackground()) {
+        return;
+    }
+
+    client->ActivateProgram();
+    mLayerRendererFrame.BeginDrawing();
+    mLayerRendererFrame.DrawBackground();
+    client->DeactivateProgram(); // redundant, but in case somebody adds code after this...
 }
 
 void
 nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
 {
     PROFILER_LABEL("nsWindow", "DrawWindowOverlay");
-    JNIEnv *env = GetJNIForThread();
-    NS_ABORT_IF_FALSE(env, "No JNI environment at DrawWindowOverlay()!");
-    if (!env)
-        return;
-
-    AutoLocalJNIFrame jniFrame(env);
 
     NS_ABORT_IF_FALSE(!mLayerRendererFrame.isNull(),
                       "Frame should have been created in DrawWindowUnderlay()!");
 
-    AndroidGeckoLayerClient& client = AndroidBridge::Bridge()->GetLayerClient();
+    GeckoLayerClient* client = AndroidBridge::Bridge()->GetLayerClient();
 
-    if (!client.ActivateProgram(&jniFrame)) return;
-    if (!mLayerRendererFrame.DrawForeground(&jniFrame)) return;
-    if (!mLayerRendererFrame.EndDrawing(&jniFrame)) return;
-    if (!client.DeactivateProgram(&jniFrame)) return;
-    mLayerRendererFrame.Dispose(env);
+    client->ActivateProgram();
+    mLayerRendererFrame.DrawForeground();
+    mLayerRendererFrame.EndDrawing();
+    client->DeactivateProgram();
+    mLayerRendererFrame.Dispose();
 }
 
 // off-main-thread compositor fields and functions
 
 StaticRefPtr<mozilla::layers::APZCTreeManager> nsWindow::sApzcTreeManager;
 StaticRefPtr<mozilla::layers::LayerManager> nsWindow::sLayerManager;
 StaticRefPtr<mozilla::layers::CompositorParent> nsWindow::sCompositorParent;
 StaticRefPtr<mozilla::layers::CompositorChild> nsWindow::sCompositorChild;
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -6,16 +6,17 @@
 #ifndef NSWINDOW_H_
 #define NSWINDOW_H_
 
 #include "nsBaseWidget.h"
 #include "gfxPoint.h"
 #include "nsIIdleServiceInternal.h"
 #include "nsTArray.h"
 #include "AndroidJavaWrappers.h"
+#include "GeneratedJNIWrappers.h"
 #include "mozilla/EventForwards.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/TextRange.h"
 
 class gfxASurface;
 
 struct ANPEvent;
 
@@ -235,17 +236,17 @@ private:
                              mozilla::AndroidGeckoEvent *ae,
                              const nsIntPoint &refPoint);
     void DispatchGestureEvent(uint32_t msg, uint32_t direction, double delta,
                               const nsIntPoint &refPoint, uint64_t time);
     void HandleSpecialKey(mozilla::AndroidGeckoEvent *ae);
     void CreateLayerManager(int aCompositorWidth, int aCompositorHeight);
     void RedrawAll();
 
-    mozilla::AndroidLayerRendererFrame mLayerRendererFrame;
+    mozilla::widget::android::LayerRendererFrame mLayerRendererFrame;
 
     static mozilla::StaticRefPtr<mozilla::layers::APZCTreeManager> sApzcTreeManager;
     static mozilla::StaticRefPtr<mozilla::layers::LayerManager> sLayerManager;
     static mozilla::StaticRefPtr<mozilla::layers::CompositorParent> sCompositorParent;
     static mozilla::StaticRefPtr<mozilla::layers::CompositorChild> sCompositorChild;
     static bool sCompositorPaused;
 };
 
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -21,16 +21,17 @@
 #endif
 
 #ifdef MOZ_WIDGET_GTK
 #include <gtk/gtk.h>
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidBridge.h"
+using namespace mozilla::widget::android;
 #endif
 
 #ifdef MOZ_WIDGET_GONK
 #include <sys/system_properties.h>
 #endif
 
 #ifdef ANDROID
 extern "C" {
@@ -224,17 +225,17 @@ nsSystemInfo::Init()
         if (mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", str))
             SetPropertyAsAString(NS_LITERAL_STRING("release_version"), str);
         int32_t version;
         if (!mozilla::AndroidBridge::Bridge()->GetStaticIntField("android/os/Build$VERSION", "SDK_INT", &version))
             version = 0;
         android_sdk_version = version;
         if (version >= 8 && mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build", "HARDWARE", str))
             SetPropertyAsAString(NS_LITERAL_STRING("hardware"), str);
-        bool isTablet = mozilla::AndroidBridge::Bridge()->IsTablet();
+        bool isTablet = GeckoAppShell::IsTablet();
         SetPropertyAsBool(NS_LITERAL_STRING("tablet"), isTablet);
         // NSPR "version" is the kernel version. For Android we want the Android version.
         // Rename SDK version to version and put the kernel version into kernel_version.
         rv = GetPropertyAsAString(NS_LITERAL_STRING("version"), str);
         if (NS_SUCCEEDED(rv)) {
             SetPropertyAsAString(NS_LITERAL_STRING("kernel_version"), str);
         }
         SetPropertyAsInt32(NS_LITERAL_STRING("version"), android_sdk_version);
--- a/xpcom/components/ManifestParser.cpp
+++ b/xpcom/components/ManifestParser.cpp
@@ -467,17 +467,17 @@ ParseManifest(NSLocationType type, FileL
 #elif defined(MOZ_WIDGET_GTK)
   nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(),
                                        gtk_major_version,
                                        gtk_minor_version);
 #elif defined(MOZ_WIDGET_ANDROID)
   bool isTablet = false;
   if (mozilla::AndroidBridge::Bridge()) {
     mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion);
-    isTablet = mozilla::AndroidBridge::Bridge()->IsTablet();
+    isTablet = mozilla::widget::android::GeckoAppShell::IsTablet();
   }
 #endif
 
   // Because contracts must be registered after CIDs, we save and process them
   // at the end.
   nsTArray<CachedDirective> contracts;
 
   char *token;
--- a/xpcom/io/nsLocalFileUnix.cpp
+++ b/xpcom/io/nsLocalFileUnix.cpp
@@ -1840,18 +1840,17 @@ nsLocalFile::Launch()
     nsresult rv;
     nsAutoCString type;
     nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1", &rv));
     if (NS_SUCCEEDED(rv))
         rv = mimeService->GetTypeFromFile(this, type);
 
     nsDependentCString fileUri = NS_LITERAL_CSTRING("file://");
     fileUri.Append(mPath);
-    mozilla::AndroidBridge* bridge = mozilla::AndroidBridge::Bridge();
-    return bridge->OpenUriExternal(NS_ConvertUTF8toUTF16(fileUri), NS_ConvertUTF8toUTF16(type)) ? NS_OK : NS_ERROR_FAILURE;
+    return GeckoAppShell::OpenUriExternal(NS_ConvertUTF8toUTF16(fileUri), NS_ConvertUTF8toUTF16(type)) ? NS_OK : NS_ERROR_FAILURE;
 #elif defined(MOZ_WIDGET_COCOA)
     CFURLRef url;
     if (NS_SUCCEEDED(GetCFURL(&url))) {
         nsresult rv = CocoaFileUtils::OpenURL(url);
         ::CFRelease(url);
         return rv;
     }
     return NS_ERROR_FAILURE;