Bug 1413698 - 5. Use GeckoSession where appropriate; r=snorp
authorJim Chen <nchen@mozilla.com>
Mon, 06 Nov 2017 14:54:09 -0500
changeset 443660 1bb6b4ff9df2ab90e3867131fdd836a67413b377
parent 443659 bff0682273b310d8604161cf551fa103ad7d1ba1
child 443661 56ee4e33d6ab146d7a4a300ff233b29bbf752d43
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1413698
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1413698 - 5. Use GeckoSession where appropriate; r=snorp Change places where we use GeckoView to use GeckoSession instead. MozReview-Commit-ID: InT4i1MaoBe
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewHandler.java
mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java
mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -3493,33 +3493,29 @@ public class BrowserApp extends GeckoApp
 
     @Override
     public void closeOptionsMenu() {
         if (!mBrowserToolbar.closeOptionsMenu())
             super.closeOptionsMenu();
     }
 
     @Override // GeckoView.ContentListener
-    public void onFullScreen(final GeckoView view, final boolean fullscreen) {
-        super.onFullScreen(view, fullscreen);
+    public void onFullScreen(final GeckoSession session, final boolean fullscreen) {
+        super.onFullScreen(session, fullscreen);
 
         if (fullscreen) {
             mDynamicToolbar.setVisible(false, VisibilityTransition.IMMEDIATE);
             mDynamicToolbar.setPinned(true, PinReason.FULL_SCREEN);
         } else {
             mDynamicToolbar.setPinned(false, PinReason.FULL_SCREEN);
             mDynamicToolbar.setVisible(true, VisibilityTransition.IMMEDIATE);
         }
     }
 
     @Override
-    public void onContextMenu(GeckoView view, int screenX, int screenY,
-                              String uri, String elementSrc) {}
-
-    @Override
     public boolean onPrepareOptionsMenu(Menu aMenu) {
         if (aMenu == null)
             return false;
 
         // Hide the tab history panel when hardware menu button is pressed.
         TabHistoryFragment frag = (TabHistoryFragment) getSupportFragmentManager().findFragmentByTag(TAB_HISTORY_FRAGMENT_TAG);
         if (frag != null) {
             frag.dismiss();
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -109,17 +109,17 @@ import static org.mozilla.gecko.Tabs.INV
 import static org.mozilla.gecko.mma.MmaDelegate.DOWNLOAD_MEDIA_SAVED_IMAGE;
 import static org.mozilla.gecko.mma.MmaDelegate.READER_AVAILABLE;
 
 public abstract class GeckoApp extends GeckoActivity
                                implements AnchoredPopup.OnVisibilityChangeListener,
                                           BundleEventListener,
                                           GeckoMenu.Callback,
                                           GeckoMenu.MenuPresenter,
-                                          GeckoView.ContentListener,
+                                          GeckoSession.ContentListener,
                                           ScreenOrientationDelegate,
                                           Tabs.OnTabsChangedListener,
                                           ViewTreeObserver.OnGlobalLayoutListener {
 
     private static final String LOGTAG = "GeckoApp";
     private static final long ONE_DAY_MS = TimeUnit.MILLISECONDS.convert(1, TimeUnit.DAYS);
 
     public static final String ACTION_ALERT_CALLBACK       = "org.mozilla.gecko.ALERT_CALLBACK";
@@ -853,36 +853,42 @@ public abstract class GeckoApp extends G
         }
         return inSampleSize;
     }
 
     public void requestRender() {
         mLayerView.requestRender();
     }
 
-    @Override // GeckoView.ContentListener
-    public void onTitleChange(final GeckoView view, final String title) {
+    @Override // GeckoSession.ContentListener
+    public void onTitleChange(final GeckoSession session, final String title) {
     }
 
-    @Override // GeckoView.ContentListener
-    public void onFullScreen(final GeckoView view, final boolean fullScreen) {
+    @Override // GeckoSession.ContentListener
+    public void onFullScreen(final GeckoSession session, final boolean fullScreen) {
         if (fullScreen) {
             SnackbarBuilder.builder(this)
                     .message(R.string.fullscreen_warning)
                     .duration(Snackbar.LENGTH_LONG).buildAndShow();
         }
         ThreadUtils.assertOnUiThread();
         ActivityUtils.setFullScreen(this, fullScreen);
     }
 
+    @Override
+    public void onContextMenu(final GeckoSession session, final int screenX,
+                              final int screenY, final String uri,
+                              final String elementSrc) {
+    }
+
     protected void setFullScreen(final boolean fullscreen) {
         ThreadUtils.postToUiThread(new Runnable() {
             @Override
             public void run() {
-                onFullScreen(mLayerView, fullscreen);
+                onFullScreen(mLayerView.getSession(), fullscreen);
             }
         });
     }
 
     /**
      * Check and start the Java profiler if MOZ_PROFILER_STARTUP env var is specified.
      **/
     protected static void earlyStartJavaSampler(SafeIntent intent) {
@@ -1035,20 +1041,24 @@ public abstract class GeckoApp extends G
         setContentView(getLayout());
 
         // Set up Gecko layout.
         mRootLayout = (RelativeLayout) findViewById(R.id.root_layout);
         mGeckoLayout = (RelativeLayout) findViewById(R.id.gecko_layout);
         mMainLayout = (RelativeLayout) findViewById(R.id.main_layout);
         mLayerView = (GeckoView) findViewById(R.id.layer_view);
 
-        mLayerView.setChromeUri("chrome://browser/content/browser.xul");
-        mLayerView.setContentListener(this);
+        final GeckoSession session = new GeckoSession();
+        mLayerView.setSession(session);
         mLayerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
 
+        session.getSettings().setString(GeckoViewSettings.CHROME_URI,
+                                        "chrome://browser/content/browser.xul");
+        session.setContentListener(this);
+
         GeckoAccessibility.setDelegate(mLayerView);
 
         getAppEventDispatcher().registerGeckoThreadListener(this,
             "Accessibility:Event",
             "Locale:Set",
             null);
 
         getAppEventDispatcher().registerUiThreadListener(this,
--- a/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
+++ b/mobile/android/base/java/org/mozilla/gecko/RemotePresentationService.java
@@ -1,25 +1,20 @@
 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * vim: ts=4 sw=4 expandtab:
  * 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/. */
 
 package org.mozilla.gecko;
 
-import org.mozilla.gecko.AppConstants.Versions;
-import org.mozilla.gecko.GeckoAppShell;
-import org.mozilla.gecko.PresentationView;
-import org.mozilla.gecko.R;
+import org.mozilla.gecko.GeckoSession;
+import org.mozilla.gecko.GeckoView;
+import org.mozilla.gecko.GeckoViewSettings;
 import org.mozilla.gecko.ScreenManagerHelper;
-import org.mozilla.gecko.annotation.JNITarget;
-import org.mozilla.gecko.annotation.ReflectionTarget;
-import org.mozilla.gecko.annotation.WrapForJNI;
-import org.mozilla.gecko.gfx.LayerView;
 
 import com.google.android.gms.cast.CastMediaControlIntent;
 import com.google.android.gms.cast.CastPresentation;
 import com.google.android.gms.cast.CastRemoteDisplayLocalService;
 import com.google.android.gms.common.ConnectionResult;
 import com.google.android.gms.common.GooglePlayServicesUtil;
 
 import android.app.Activity;
@@ -99,19 +94,21 @@ public class RemotePresentationService e
         } catch (WindowManager.InvalidDisplayException ex) {
             Log.e(LOGTAG, "Unable to show presentation, display was removed.", ex);
             dismissPresentation();
         }
     }
 }
 
 class VirtualPresentation extends CastPresentation {
-    private final String LOGTAG = "VirtualPresentation";
+    private static final String LOGTAG = "VirtualPresentation";
+    private static final String PRESENTATION_VIEW_URI = "chrome://browser/content/PresentationView.xul";
+
     private RelativeLayout layout;
-    private PresentationView view;
+    private GeckoView view;
     private String deviceId;
     private int screenId;
 
     public VirtualPresentation(Context context, Display display) {
         super(context, display);
     }
 
     public void setDeviceId(String deviceId) { this.deviceId = deviceId; }
@@ -122,18 +119,25 @@ class VirtualPresentation extends CastPr
         super.onCreate(savedInstanceState);
 
         /*
          * NOTICE: The context get from getContext() is different to the context
          * of the application. Presentaion has its own context to get correct
          * resources.
          */
 
-        // Create new PresentationView
-        view = new PresentationView(getContext(), deviceId, screenId);
+        // Create new GeckoView
+        view = new GeckoView(getContext());
+
+        final GeckoSession session = new GeckoSession();
+        session.getSettings().setString(GeckoViewSettings.CHROME_URI,
+                                        PRESENTATION_VIEW_URI + "#" + deviceId);
+        session.getSettings().setInt(GeckoViewSettings.SCREEN_ID, screenId);
+
+        view.setSession(session);
         view.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                                               LayoutParams.MATCH_PARENT));
 
         // Create new layout to put the GeckoView
         layout = new RelativeLayout(getContext());
         layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
                                                 LayoutParams.MATCH_PARENT));
         layout.addView(view);
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/ActionBarPresenter.java
@@ -24,17 +24,17 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.TextView;
 
 import org.mozilla.gecko.GeckoView;
-import org.mozilla.gecko.GeckoView.ProgressListener.SecurityInformation;
+import org.mozilla.gecko.GeckoSession.ProgressListener.SecurityInformation;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.SiteIdentity;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.toolbar.SecurityModeUtil;
 import org.mozilla.gecko.toolbar.CustomTabsSecurityPopup;
 import org.mozilla.gecko.util.ColorUtil;
 
 /**
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsActivity.java
@@ -36,16 +36,17 @@ import android.widget.ProgressBar;
 import org.mozilla.gecko.ActivityHandlerHelper;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.Clipboard;
 import org.mozilla.gecko.DoorHangerPopup;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.FormAssistPopup;
 import org.mozilla.gecko.GeckoAccessibility;
 import org.mozilla.gecko.GeckoSharedPrefs;
+import org.mozilla.gecko.GeckoSession;
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoViewSettings;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.SnackbarBuilder;
 import org.mozilla.gecko.Telemetry;
 import org.mozilla.gecko.TelemetryContract;
 import org.mozilla.gecko.menu.GeckoMenu;
@@ -66,32 +67,33 @@ import org.mozilla.gecko.webapps.WebApps
 import org.mozilla.gecko.widget.ActionModePresenter;
 import org.mozilla.gecko.widget.GeckoPopupMenu;
 
 import java.util.List;
 
 public class CustomTabsActivity extends AppCompatActivity
                                 implements ActionModePresenter,
                                            GeckoMenu.Callback,
-                                           GeckoView.ContentListener,
-                                           GeckoView.NavigationListener,
-                                           GeckoView.ProgressListener {
+                                           GeckoSession.ContentListener,
+                                           GeckoSession.NavigationListener,
+                                           GeckoSession.ProgressListener {
 
     private static final String LOGTAG = "CustomTabsActivity";
 
     private final SparseArrayCompat<PendingIntent> menuItemsIntent = new SparseArrayCompat<>();
     private GeckoPopupMenu popupMenu;
     private View doorhangerOverlay;
     private ActionBarPresenter actionBarPresenter;
     private ProgressBar mProgressView;
     // A state to indicate whether this activity is finishing with customize animation
     private boolean usingCustomAnimation = false;
 
     private MenuItem menuItemControl;
 
+    private GeckoSession mGeckoSession;
     private GeckoView mGeckoView;
     private PromptService mPromptService;
     private DoorHangerPopup mDoorHangerPopup;
     private FormAssistPopup mFormAssistPopup;
 
     private ActionMode mActionMode;
     private TextSelection mTextSelection;
 
@@ -121,21 +123,24 @@ public class CustomTabsActivity extends 
 
         actionBarPresenter = new ActionBarPresenter(actionBar, getActionBarTextColor());
         actionBarPresenter.displayUrlOnly(intent.getDataString());
         actionBarPresenter.setBackgroundColor(IntentUtil.getToolbarColor(intent), getWindow());
         actionBarPresenter.setTextLongClickListener(new UrlCopyListener());
 
         mGeckoView = (GeckoView) findViewById(R.id.gecko_view);
 
-        mGeckoView.setNavigationListener(this);
-        mGeckoView.setProgressListener(this);
-        mGeckoView.setContentListener(this);
+        GeckoAccessibility.setDelegate(mGeckoView);
 
-        GeckoAccessibility.setDelegate(mGeckoView);
+        mGeckoSession = new GeckoSession();
+        mGeckoView.setSession(mGeckoSession);
+
+        mGeckoSession.setNavigationListener(this);
+        mGeckoSession.setProgressListener(this);
+        mGeckoSession.setContentListener(this);
 
         mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
         mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
 
         mFormAssistPopup = (FormAssistPopup) findViewById(R.id.form_assist_popup);
         mFormAssistPopup.create(mGeckoView);
 
         mTextSelection = TextSelection.Factory.create(mGeckoView, this);
@@ -144,35 +149,35 @@ public class CustomTabsActivity extends 
         final GeckoViewSettings settings = mGeckoView.getSettings();
         settings.setBoolean(GeckoViewSettings.USE_MULTIPROCESS, false);
         settings.setBoolean(
             GeckoViewSettings.USE_REMOTE_DEBUGGER,
             GeckoSharedPrefs.forApp(this).getBoolean(
                 GeckoPreferences.PREFS_DEVTOOLS_REMOTE_USB_ENABLED, false));
 
         if (intent != null && !TextUtils.isEmpty(intent.getDataString())) {
-            mGeckoView.loadUri(intent.getDataString());
+            mGeckoSession.loadUri(intent.getDataString());
         } else {
             Log.w(LOGTAG, "No intend found for custom tab");
             finish();
         }
 
         sendTelemetry();
         recordCustomTabUsage(getReferrerHost());
     }
 
     @Override
     public void onResume() {
-        mGeckoView.setActive(true);
+        mGeckoSession.setActive(true);
         super.onResume();
     }
 
     @Override
     public void onPause() {
-        mGeckoView.setActive(false);
+        mGeckoSession.setActive(false);
         super.onPause();
     }
 
     @Override
     public void onDestroy() {
         mTextSelection.destroy();
         mFormAssistPopup.destroy();
         mDoorHangerPopup.destroy();
@@ -238,18 +243,18 @@ public class CustomTabsActivity extends 
             return IntentUtil.getAnimationPackageName(new SafeIntent(getIntent()));
         } else {
             return super.getPackageName();
         }
     }
 
     @Override
     public void finish() {
-        if (mGeckoView != null) {
-            mGeckoView.loadUri("about:blank");
+        if (mGeckoSession != null) {
+            mGeckoSession.loadUri("about:blank");
         }
 
         super.finish();
 
         final SafeIntent intent = new SafeIntent(getIntent());
         // When 3rd party app launch this Activity, it could also specify custom exit-animation.
         if (IntentUtil.hasExitAnimation(intent)) {
             usingCustomAnimation = true;
@@ -257,17 +262,17 @@ public class CustomTabsActivity extends 
                     IntentUtil.getExitAnimationRes(intent));
             usingCustomAnimation = false;
         }
     }
 
     @Override
     public void onBackPressed() {
         if (mCanGoBack) {
-            mGeckoView.goBack();
+            mGeckoSession.goBack();
         } else {
             finish();
         }
     }
 
     // Usually should use onCreateOptionsMenu() to initialize menu items. But GeckoApp overwrite
     // it to support custom menu(Bug 739412). Then the parameter *menu* in this.onCreateOptionsMenu()
     // and this.onPrepareOptionsMenu() are different instances - GeckoApp.onCreatePanelMenu() changed it.
@@ -492,25 +497,25 @@ public class CustomTabsActivity extends 
         actionBarPresenter.update(mCurrentTitle, mCurrentUrl, mSecurityInformation);
     }
 
     /**
      * Call this method to reload page, or stop page loading if progress not complete yet.
      */
     private void onLoadingControlClicked() {
         if (mCanStop) {
-            mGeckoView.stop();
+            mGeckoSession.stop();
         } else {
-            mGeckoView.reload();
+            mGeckoSession.reload();
         }
     }
 
     private void onForwardClicked() {
         if (mCanGoForward) {
-            mGeckoView.goForward();
+            mGeckoSession.goForward();
         }
     }
 
     /**
      * Callback for Open-in menu item.
      */
     private void onOpenInClicked() {
         if (TextUtils.isEmpty(mCurrentUrl)) {
@@ -574,37 +579,37 @@ public class CustomTabsActivity extends 
         }
         String referrerName = intent.getStringExtra("android.intent.extra.REFERRER_NAME");
         if (referrerName != null) {
             return Uri.parse(referrerName).getHost();
         }
         return null;
     }
 
-    /* GeckoView.NavigationListener */
+    /* GeckoSession.NavigationListener */
     @Override
-    public void onLocationChange(GeckoView view, String url) {
+    public void onLocationChange(GeckoSession session, String url) {
         mCurrentUrl = url;
         updateActionBar();
         updateProgress(60);
     }
 
     @Override
-    public void onCanGoBack(GeckoView view, boolean canGoBack) {
+    public void onCanGoBack(GeckoSession session, boolean canGoBack) {
         mCanGoBack = canGoBack;
     }
 
     @Override
-    public void onCanGoForward(GeckoView view, boolean canGoForward) {
+    public void onCanGoForward(GeckoSession session, boolean canGoForward) {
         mCanGoForward = canGoForward;
         updateMenuItemForward();
     }
 
     @Override
-    public boolean onLoadUri(final GeckoView view, final String urlStr,
+    public boolean onLoadUri(final GeckoSession session, final String urlStr,
                              final TargetWindow where) {
         if (where != TargetWindow.NEW) {
             return false;
         }
 
         final Uri url = Uri.parse(urlStr);
         if (url == null) {
             // We can't handle this, so deny it.
@@ -613,58 +618,58 @@ public class CustomTabsActivity extends 
         }
 
         final Intent intent = new Intent(Intent.ACTION_VIEW);
         intent.setData(url);
         startActivity(intent);
         return true;
     }
 
-    /* GeckoView.ProgressListener */
+    /* GeckoSession.ProgressListener */
     @Override
-    public void onPageStart(GeckoView view, String url) {
+    public void onPageStart(GeckoSession session, String url) {
         mCurrentUrl = url;
         mCanStop = true;
         updateActionBar();
         updateCanStop();
         updateProgress(20);
     }
 
     @Override
-    public void onPageStop(GeckoView view, boolean success) {
+    public void onPageStop(GeckoSession session, boolean success) {
         mCanStop = false;
         updateCanStop();
         updateProgress(100);
     }
 
     @Override
-    public void onSecurityChange(GeckoView view, SecurityInformation securityInfo) {
+    public void onSecurityChange(GeckoSession session, SecurityInformation securityInfo) {
         mSecurityInformation = securityInfo;
         updateActionBar();
     }
 
-    /* GeckoView.ContentListener */
+    /* GeckoSession.ContentListener */
     @Override
-    public void onTitleChange(GeckoView view, String title) {
+    public void onTitleChange(GeckoSession session, String title) {
         mCurrentTitle = title;
         updateActionBar();
     }
 
     @Override
-    public void onFullScreen(GeckoView view, boolean fullScreen) {
+    public void onFullScreen(GeckoSession session, boolean fullScreen) {
         ActivityUtils.setFullScreen(this, fullScreen);
         if (fullScreen) {
             getSupportActionBar().hide();
         } else {
             getSupportActionBar().show();
         }
     }
 
     @Override
-    public void onContextMenu(GeckoView view, int screenX, int screenY,
+    public void onContextMenu(GeckoSession session, int screenX, int screenY,
                               final String uri, final String elementSrc) {
 
         final String content = uri != null ? uri : elementSrc != null ? elementSrc : "";
         final Uri validUri = WebApps.getValidURL(content);
         if (validUri == null) {
             return;
         }
 
--- a/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
+++ b/mobile/android/base/java/org/mozilla/gecko/customtabs/CustomTabsSecurityPopup.java
@@ -14,17 +14,17 @@ import android.support.design.widget.Sna
 import android.support.v4.content.ContextCompat;
 import android.support.v4.widget.TextViewCompat;
 import android.widget.ImageView;
 import android.widget.Toast;
 import org.mozilla.gecko.AboutPages;
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoView;
-import org.mozilla.gecko.GeckoView.ProgressListener.SecurityInformation;
+import org.mozilla.gecko.GeckoSession.ProgressListener.SecurityInformation;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.SiteIdentity;
 import org.mozilla.gecko.SiteIdentity.SecurityMode;
 import org.mozilla.gecko.SiteIdentity.MixedMode;
 import org.mozilla.gecko.SiteIdentity.TrackingMode;
 import org.mozilla.gecko.SnackbarBuilder;
 import org.mozilla.gecko.Tab;
 import org.mozilla.gecko.Tabs;
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
@@ -29,38 +29,41 @@ import android.view.WindowManager;
 import android.widget.TextView;
 
 import org.mozilla.gecko.ActivityHandlerHelper;
 import org.mozilla.gecko.AppConstants;
 import org.mozilla.gecko.BrowserApp;
 import org.mozilla.gecko.DoorHangerPopup;
 import org.mozilla.gecko.GeckoAccessibility;
 import org.mozilla.gecko.GeckoScreenOrientation;
+import org.mozilla.gecko.GeckoSession;
 import org.mozilla.gecko.GeckoSharedPrefs;
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoViewSettings;
 import org.mozilla.gecko.preferences.GeckoPreferences;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.customtabs.CustomTabsActivity;
 import org.mozilla.gecko.permissions.Permissions;
 import org.mozilla.gecko.prompts.PromptService;
 import org.mozilla.gecko.text.TextSelection;
 import org.mozilla.gecko.util.ActivityUtils;
 import org.mozilla.gecko.util.ColorUtil;
 import org.mozilla.gecko.widget.ActionModePresenter;
 
 public class WebAppActivity extends AppCompatActivity
                             implements ActionModePresenter,
-                                       GeckoView.NavigationListener {
+                                       GeckoSession.ContentListener,
+                                       GeckoSession.NavigationListener {
     private static final String LOGTAG = "WebAppActivity";
 
     public static final String MANIFEST_PATH = "MANIFEST_PATH";
     public static final String MANIFEST_URL = "MANIFEST_URL";
     private static final String SAVED_INTENT = "savedIntent";
 
+    private GeckoSession mGeckoSession;
     private GeckoView mGeckoView;
     private PromptService mPromptService;
     private DoorHangerPopup mDoorHangerPopup;
 
     private ActionMode mActionMode;
     private TextSelection mTextSelection;
 
     private boolean mIsFullScreenMode;
@@ -86,38 +89,21 @@ public class WebAppActivity extends AppC
 
             Intent lastLaunchIntent = savedInstanceState.getParcelable(SAVED_INTENT);
             setIntent(lastLaunchIntent);
         }
 
         super.onCreate(savedInstanceState);
 
         mGeckoView = new GeckoView(this);
-        mGeckoView.setNavigationListener(this);
-        mGeckoView.setContentListener(new GeckoView.ContentListener() {
-            public void onTitleChange(GeckoView view, String title) {}
-            public void onContextMenu(GeckoView view, int screenX, int screenY,
-                               String uri, String elementSrc) {
-                final String content = uri != null ? uri : elementSrc != null ? elementSrc : "";
-                final Uri validUri = WebApps.getValidURL(content);
-                if (validUri == null) {
-                    return;
-                }
+        mGeckoSession = new GeckoSession();
+        mGeckoView.setSession(mGeckoSession);
 
-                runOnUiThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        WebApps.openInFennec(validUri, WebAppActivity.this);
-                    }
-                });
-            }
-            public void onFullScreen(GeckoView view, boolean fullScreen) {
-                updateFullScreenContent(fullScreen);
-            }
-        });
+        mGeckoSession.setNavigationListener(this);
+        mGeckoSession.setContentListener(this);
 
         GeckoAccessibility.setDelegate(mGeckoView);
 
         mPromptService = new PromptService(this, mGeckoView.getEventDispatcher());
         mDoorHangerPopup = new DoorHangerPopup(this, mGeckoView.getEventDispatcher());
 
         mTextSelection = TextSelection.Factory.create(mGeckoView, this);
         mTextSelection.create();
@@ -144,30 +130,30 @@ public class WebAppActivity extends AppC
                 Log.e(LOGTAG, "Failed to fall back to launching in Firefox");
             }
             finish();
             return;
         }
 
         updateFromManifest();
 
-        mGeckoView.loadUri(mManifest.getStartUri().toString());
+        mGeckoSession.loadUri(mManifest.getStartUri().toString());
 
         setContentView(mGeckoView);
     }
 
     @Override
     public void onResume() {
-        mGeckoView.setActive(true);
+        mGeckoSession.setActive(true);
         super.onResume();
     }
 
     @Override
     public void onPause() {
-        mGeckoView.setActive(false);
+        mGeckoSession.setActive(false);
         super.onPause();
     }
 
     @Override
     public void onDestroy() {
         mTextSelection.destroy();
         mDoorHangerPopup.destroy();
         mPromptService.destroy();
@@ -200,19 +186,19 @@ public class WebAppActivity extends AppC
         if (hasFocus) {
             updateFullScreen();
         }
     }
 
     @Override
     public void onBackPressed() {
         if (mIsFullScreenContent) {
-            mGeckoView.exitFullScreen();
+            mGeckoSession.exitFullScreen();
         } else if (mCanGoBack) {
-            mGeckoView.goBack();
+            mGeckoSession.goBack();
         } else {
             super.onBackPressed();
         }
     }
 
     private void updateFromManifest() {
         if (AppConstants.Versions.feature21Plus) {
             updateTaskAndStatusBar();
@@ -260,52 +246,72 @@ public class WebAppActivity extends AppC
         setRequestedOrientation(activityOrientation);
     }
 
     private void updateDisplayMode() {
         final String displayMode = mManifest.getDisplayMode();
 
         updateFullScreenMode(displayMode.equals("fullscreen"));
 
-        GeckoViewSettings.DisplayMode mode;
+        int mode;
         switch (displayMode) {
             case "standalone":
-                mode = GeckoViewSettings.DisplayMode.STANDALONE;
+                mode = GeckoViewSettings.DISPLAY_MODE_STANDALONE;
                 break;
             case "fullscreen":
-                mode = GeckoViewSettings.DisplayMode.FULLSCREEN;
+                mode = GeckoViewSettings.DISPLAY_MODE_FULLSCREEN;
                 break;
             case "minimal-ui":
-                mode = GeckoViewSettings.DisplayMode.MINIMAL_UI;
+                mode = GeckoViewSettings.DISPLAY_MODE_MINIMAL_UI;
                 break;
             case "browser":
             default:
-                mode = GeckoViewSettings.DisplayMode.BROWSER;
+                mode = GeckoViewSettings.DISPLAY_MODE_BROWSER;
                 break;
         }
 
-        mGeckoView.getSettings().setInt(GeckoViewSettings.DISPLAY_MODE, mode.value());
+        mGeckoView.getSettings().setInt(GeckoViewSettings.DISPLAY_MODE, mode);
+    }
+
+    @Override // GeckoSession.NavigationListener
+    public void onLocationChange(GeckoSession session, String url) {
+    }
+
+    @Override // GeckoSession.NavigationListener
+    public void onCanGoBack(GeckoSession session, boolean canGoBack) {
+        mCanGoBack = canGoBack;
+    }
+
+    @Override // GeckoSession.NavigationListener
+    public void onCanGoForward(GeckoSession session, boolean canGoForward) {
     }
 
-    /* GeckoView.NavigationListener */
-    @Override
-    public void onLocationChange(GeckoView view, String url) {
+    @Override // GeckoSession.ContentListener
+    public void onTitleChange(GeckoSession session, String title) {
+    }
+
+    @Override // GeckoSession.ContentListener
+    public void onContextMenu(GeckoSession session, int screenX, int screenY,
+                              String uri, String elementSrc) {
+        final String content = uri != null ? uri : elementSrc != null ? elementSrc : "";
+        final Uri validUri = WebApps.getValidURL(content);
+        if (validUri == null) {
+            return;
+        }
+
+        WebApps.openInFennec(validUri, WebAppActivity.this);
+    }
+
+    @Override // GeckoSession.ContentListener
+    public void onFullScreen(GeckoSession session, boolean fullScreen) {
+        updateFullScreenContent(fullScreen);
     }
 
     @Override
-    public void onCanGoBack(GeckoView view, boolean canGoBack) {
-        mCanGoBack = canGoBack;
-    }
-
-    @Override
-    public void onCanGoForward(GeckoView view, boolean canGoForward) {
-    }
-
-    @Override
-    public boolean onLoadUri(final GeckoView view, final String urlStr,
+    public boolean onLoadUri(final GeckoSession session, final String urlStr,
                              final TargetWindow where) {
         final Uri uri = Uri.parse(urlStr);
         if (uri == null) {
             // We can't really handle this, so deny it?
             Log.w(LOGTAG, "Failed to parse URL for navigation: " + urlStr);
             return true;
         }
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewHandler.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoViewHandler.java
@@ -7,51 +7,50 @@
 package org.mozilla.gecko;
 
 import org.mozilla.gecko.util.BundleEventListener;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoBundle;
 
 import android.util.Log;
 
-
 /* package */ abstract class GeckoViewHandler<Listener>
     implements BundleEventListener {
 
     private static final String LOGTAG = "GeckoViewHandler";
     private static final boolean DEBUG = false;
 
     private Listener mListener;
     private final boolean mAlwaysListen;
     private final String mModuleName;
     private final String[] mEvents;
 
 
-    GeckoViewHandler(final String module, final GeckoView view,
+    GeckoViewHandler(final String module, final GeckoSession session,
                      final String[] events) {
-        this(module, view, events, /* alwaysListen */ false);
+        this(module, session, events, /* alwaysListen */ false);
     }
 
-    GeckoViewHandler(final String module, final GeckoView view,
+    GeckoViewHandler(final String module, final GeckoSession session,
                      final String[] events, final boolean alwaysListen) {
         mAlwaysListen = alwaysListen;
         mModuleName = module;
         mEvents = events;
 
         if (alwaysListen) {
-            register(view.getEventDispatcher());
+            register(session.getEventDispatcher());
         }
     }
 
     public Listener getListener() {
         return mListener;
     }
 
-    public void setListener(final Listener listener, final GeckoView view) {
-        final EventDispatcher eventDispatcher = view.getEventDispatcher();
+    public void setListener(final Listener listener, final GeckoSession session) {
+        final EventDispatcher eventDispatcher = session.getEventDispatcher();
         if (mListener == listener) {
             return;
         }
 
         if (!mAlwaysListen && mListener != null) {
             unregister(eventDispatcher);
         }
 
--- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java
+++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java
@@ -43,34 +43,29 @@ import android.widget.TimePicker;
 
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
 
-import org.mozilla.gecko.GeckoView;
+import org.mozilla.gecko.GeckoSession;
 import org.mozilla.gecko.util.GeckoBundle;
 
-final class BasicGeckoViewPrompt implements GeckoView.PromptDelegate {
+final class BasicGeckoViewPrompt implements GeckoSession.PromptDelegate {
     protected static final String LOGTAG = "BasicGeckoViewPrompt";
 
+    private final Activity mActivity;
     public int filePickerRequestCode = 1;
     private int mFileType;
     private FileCallback mFileCallback;
 
-    private static Activity getActivity(final GeckoView view) {
-        if (view != null) {
-            final Context context = view.getContext();
-            if (context instanceof Activity) {
-                return (Activity) context;
-            }
-        }
-        return null;
+    public BasicGeckoViewPrompt(final Activity activity) {
+        mActivity = activity;
     }
 
     private AlertDialog.Builder addCheckbox(final AlertDialog.Builder builder,
                                             ViewGroup parent,
                                             final AlertCallback callback) {
         if (!callback.hasCheckbox()) {
             return builder;
         }
@@ -92,35 +87,35 @@ final class BasicGeckoViewPrompt impleme
             parent.setPadding(/* left */ padding, /* top */ 0,
                               /* right */ padding, /* bottom */ 0);
             builder.setView(parent);
         }
         parent.addView(checkbox);
         return builder;
     }
 
-    public void alert(final GeckoView view, final String title, final String msg,
+    public void alert(final GeckoSession session, final String title, final String msg,
                       final AlertCallback callback) {
-        final Activity activity = getActivity(view);
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
                 .setTitle(title)
                 .setMessage(msg)
                 .setPositiveButton(android.R.string.ok, /* onClickListener */ null);
         createStandardDialog(addCheckbox(builder, /* parent */ null, callback),
                              callback).show();
     }
 
-    public void promptForButton(final GeckoView view, final String title, final String msg,
-                                final String[] btnMsg, final ButtonCallback callback)
-    {
-        final Activity activity = getActivity(view);
+    public void promptForButton(final GeckoSession session, final String title,
+                                final String msg, final String[] btnMsg,
+                                final ButtonCallback callback) {
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity)
                 .setTitle(title)
                 .setMessage(msg);
         final DialogInterface.OnClickListener listener =
@@ -182,20 +177,20 @@ final class BasicGeckoViewPrompt impleme
                     @Override
                     public void onDismiss(final DialogInterface dialog) {
                         callback.dismiss();
                     }
                 });
         return dialog;
     }
 
-    public void promptForText(final GeckoView view, final String title, final String msg,
-                              final String value, final TextCallback callback)
-    {
-        final Activity activity = getActivity(view);
+    public void promptForText(final GeckoSession session, final String title,
+                              final String msg, final String value,
+                              final TextCallback callback) {
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
         final LinearLayout container = addStandardLayout(builder, title, msg);
         final EditText editText = new EditText(builder.getContext());
         editText.setText(value);
@@ -208,20 +203,20 @@ final class BasicGeckoViewPrompt impleme
                     public void onClick(final DialogInterface dialog, final int which) {
                         callback.confirm(editText.getText().toString());
                     }
                 });
 
         createStandardDialog(addCheckbox(builder, container, callback), callback).show();
     }
 
-    public void promptForAuth(final GeckoView view, final String title, final String msg,
-                              final GeckoBundle options, final AuthCallback callback)
-    {
-        final Activity activity = getActivity(view);
+    public void promptForAuth(final GeckoSession session, final String title,
+                              final String msg, final GeckoBundle options,
+                              final AuthCallback callback) {
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
         final LinearLayout container = addStandardLayout(builder, title, msg);
 
         final int flags = options.getInt("flags");
@@ -286,21 +281,20 @@ final class BasicGeckoViewPrompt impleme
                 } else {
                     newIndent = null;
                 }
                 addChoiceItems(type, list, children, newIndent);
             }
         }
     }
 
-    public void promptForChoice(final GeckoView view, final String title, final String msg,
-                                final int type, final GeckoBundle[] choices,
-                                final ChoiceCallback callback)
-    {
-        final Activity activity = getActivity(view);
+    public void promptForChoice(final GeckoSession session, final String title,
+                                final String msg, final int type,
+                                final GeckoBundle[] choices, final ChoiceCallback callback) {
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
         addStandardLayout(builder, title, msg);
 
         final ListView list = new ListView(builder.getContext());
@@ -418,17 +412,17 @@ final class BasicGeckoViewPrompt impleme
                                         final int position, final long id) {
                     final GeckoBundle item = adapter.getItem(position);
                     if (type == CHOICE_TYPE_MENU) {
                         final GeckoBundle[] children = item.getBundleArray("items");
                         if (children != null) {
                             // Show sub-menu.
                             dialog.setOnDismissListener(null);
                             dialog.dismiss();
-                            promptForChoice(view, item.getString("label"), /* msg */ null,
+                            promptForChoice(session, item.getString("label"), /* msg */ null,
                                             type, children, callback);
                             return;
                         }
                     }
                     callback.confirm(item);
                     dialog.dismiss();
                 }
             });
@@ -468,20 +462,20 @@ final class BasicGeckoViewPrompt impleme
     private static int parseColor(final String value, final int def) {
         try {
             return Color.parseColor(value);
         } catch (final IllegalArgumentException e) {
             return def;
         }
     }
 
-    public void promptForColor(final GeckoView view, final String title,
+    public void promptForColor(final GeckoSession session, final String title,
                                final String value, final TextCallback callback)
     {
-        final Activity activity = getActivity(view);
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
         addStandardLayout(builder, title, /* msg */ null);
 
         final int initial = parseColor(value, /* def */ 0);
@@ -576,21 +570,20 @@ final class BasicGeckoViewPrompt impleme
             cal.set(Calendar.HOUR_OF_DAY, picker.getHour());
             cal.set(Calendar.MINUTE, picker.getMinute());
         } else {
             cal.set(Calendar.HOUR_OF_DAY, picker.getCurrentHour());
             cal.set(Calendar.MINUTE, picker.getCurrentMinute());
         }
     }
 
-    public void promptForDateTime(final GeckoView view, final String title, final int type,
-                                  final String value, final String min, final String max,
-                                  final TextCallback callback)
-    {
-        final Activity activity = getActivity(view);
+    public void promptForDateTime(final GeckoSession session, final String title,
+                                  final int type, final String value, final String min,
+                                  final String max, final TextCallback callback) {
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
         final String format;
         if (type == DATETIME_TYPE_DATE) {
             format = "yyyy-MM-dd";
         } else if (type == DATETIME_TYPE_MONTH) {
@@ -693,20 +686,20 @@ final class BasicGeckoViewPrompt impleme
         };
         builder.setNegativeButton(android.R.string.cancel, /* listener */ null)
                .setNeutralButton(R.string.clear_field, listener)
                .setPositiveButton(android.R.string.ok, listener);
         createStandardDialog(builder, callback).show();
     }
 
     @TargetApi(19)
-    public void promptForFile(GeckoView view, String title, int type,
+    public void promptForFile(GeckoSession session, String title, int type,
                               String[] mimeTypes, FileCallback callback)
     {
-        final Activity activity = getActivity(view);
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.dismiss();
             return;
         }
 
         // Merge all given MIME types into one, using wildcard if needed.
         String mimeType = null;
         String mimeSubtype = null;
@@ -748,18 +741,17 @@ final class BasicGeckoViewPrompt impleme
             mFileCallback = callback;
             activity.startActivityForResult(intent, filePickerRequestCode);
         } catch (final ActivityNotFoundException e) {
             Log.e(LOGTAG, "Cannot launch activity", e);
             callback.dismiss();
         }
     }
 
-    public void onFileCallbackResult(final Context context, final int resultCode,
-                                     final Intent data) {
+    public void onFileCallbackResult(final int resultCode, final Intent data) {
         if (mFileCallback == null) {
             return;
         }
 
         final FileCallback callback = mFileCallback;
         mFileCallback = null;
 
         if (resultCode != Activity.RESULT_OK || data == null) {
@@ -767,36 +759,36 @@ final class BasicGeckoViewPrompt impleme
             return;
         }
 
         final Uri uri = data.getData();
         final ClipData clip = data.getClipData();
 
         if (mFileType == FILE_TYPE_SINGLE ||
             (mFileType == FILE_TYPE_MULTIPLE && clip == null)) {
-            callback.confirm(context, uri);
+            callback.confirm(mActivity, uri);
 
         } else if (mFileType == FILE_TYPE_MULTIPLE) {
             if (clip == null) {
                 Log.w(LOGTAG, "No selected file");
                 callback.dismiss();
                 return;
             }
             final int count = clip.getItemCount();
             final ArrayList<Uri> uris = new ArrayList<>(count);
             for (int i = 0; i < count; i++) {
                 uris.add(clip.getItemAt(i).getUri());
             }
-            callback.confirm(context, uris.toArray(new Uri[uris.size()]));
+            callback.confirm(mActivity, uris.toArray(new Uri[uris.size()]));
         }
     }
 
-    public void promptForPermission(final GeckoView view, final String title,
-                                    final GeckoView.PermissionDelegate.Callback callback) {
-        final Activity activity = getActivity(view);
+    public void promptForPermission(final GeckoSession session, final String title,
+                                    final GeckoSession.PermissionDelegate.Callback callback) {
+        final Activity activity = mActivity;
         if (activity == null) {
             callback.reject();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
         builder.setTitle(title)
                .setNegativeButton(android.R.string.cancel, /* onClickListener */ null)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@@ -845,20 +837,20 @@ final class BasicGeckoViewPrompt impleme
 
         final Spinner spinner = new Spinner(context);
         spinner.setAdapter(adapter);
         spinner.setSelection(0);
         container.addView(spinner);
         return spinner;
     }
 
-    public void promptForMedia(final GeckoView view, final String title,
+    public void promptForMedia(final GeckoSession session, final String title,
                                final GeckoBundle[] video, final GeckoBundle[] audio,
-                               final GeckoView.PermissionDelegate.MediaCallback callback) {
-        final Activity activity = getActivity(view);
+                               final GeckoSession.PermissionDelegate.MediaCallback callback) {
+        final Activity activity = mActivity;
         if (activity == null || (video == null && audio == null)) {
             callback.reject();
             return;
         }
         final AlertDialog.Builder builder = new AlertDialog.Builder(activity);
         final LinearLayout container = addStandardLayout(builder, title, /* msg */ null);
 
         final Spinner videoSpinner;
--- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
+++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java
@@ -13,29 +13,31 @@ import android.os.Build;
 import android.os.Bundle;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.WindowManager;
 
 import java.util.Locale;
 
+import org.mozilla.gecko.GeckoSession;
 import org.mozilla.gecko.GeckoView;
 import org.mozilla.gecko.GeckoViewSettings;
 import org.mozilla.gecko.util.GeckoBundle;
 
 public class GeckoViewActivity extends Activity {
     private static final String LOGTAG = "GeckoViewActivity";
     private static final String DEFAULT_URL = "https://mozilla.org";
     private static final String USE_MULTIPROCESS_EXTRA = "use_multiprocess";
     private static final String USE_REMOTE_DEBUGGER_EXTRA = "use_remote_debugger";
 
     /* package */ static final int REQUEST_FILE_PICKER = 1;
     private static final int REQUEST_PERMISSIONS = 2;
 
+    private GeckoSession mGeckoSession;
     private GeckoView mGeckoView;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         Log.i(LOGTAG, "zerdatime " + SystemClock.elapsedRealtime() +
               " - application start");
 
@@ -52,32 +54,35 @@ public class GeckoViewActivity extends A
                 geckoArgs = intentArgs;
             } else {
                 geckoArgs += " " + intentArgs;
             }
         }
 
         final boolean useMultiprocess = getIntent().getBooleanExtra(USE_MULTIPROCESS_EXTRA,
                                                                     true);
-        GeckoView.preload(this, geckoArgs, useMultiprocess);
+        GeckoSession.preload(this, geckoArgs, useMultiprocess);
 
         setContentView(R.layout.geckoview_activity);
 
         mGeckoView = (GeckoView) findViewById(R.id.gecko_view);
-        mGeckoView.setContentListener(new MyGeckoViewContent());
-        mGeckoView.setProgressListener(new MyGeckoViewProgress());
-        mGeckoView.setNavigationListener(new Navigation());
+        mGeckoSession = new GeckoSession();
+        mGeckoView.setSession(mGeckoSession);
 
-        final BasicGeckoViewPrompt prompt = new BasicGeckoViewPrompt();
+        mGeckoSession.setContentListener(new MyGeckoViewContent());
+        mGeckoSession.setProgressListener(new MyGeckoViewProgress());
+        mGeckoSession.setNavigationListener(new Navigation());
+
+        final BasicGeckoViewPrompt prompt = new BasicGeckoViewPrompt(this);
         prompt.filePickerRequestCode = REQUEST_FILE_PICKER;
-        mGeckoView.setPromptDelegate(prompt);
+        mGeckoSession.setPromptDelegate(prompt);
 
         final MyGeckoViewPermission permission = new MyGeckoViewPermission();
         permission.androidPermissionRequestCode = REQUEST_PERMISSIONS;
-        mGeckoView.setPermissionDelegate(permission);
+        mGeckoSession.setPermissionDelegate(permission);
 
         mGeckoView.getSettings().setBoolean(GeckoViewSettings.USE_MULTIPROCESS,
                                             useMultiprocess);
         loadSettings(getIntent());
         loadFromIntent(getIntent());
     }
 
     @Override
@@ -88,98 +93,98 @@ public class GeckoViewActivity extends A
         loadSettings(intent);
         if (intent.getData() != null) {
             loadFromIntent(intent);
         }
     }
 
     private void loadFromIntent(final Intent intent) {
         final Uri uri = intent.getData();
-        mGeckoView.loadUri(uri != null ? uri.toString() : DEFAULT_URL);
+        mGeckoSession.loadUri(uri != null ? uri.toString() : DEFAULT_URL);
     }
 
     private void loadSettings(final Intent intent) {
         mGeckoView.getSettings().setBoolean(
             GeckoViewSettings.USE_REMOTE_DEBUGGER,
             intent.getBooleanExtra(USE_REMOTE_DEBUGGER_EXTRA, false));
     }
 
     @Override
     protected void onActivityResult(final int requestCode, final int resultCode,
                                     final Intent data) {
         if (requestCode == REQUEST_FILE_PICKER) {
             final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt)
-                    mGeckoView.getPromptDelegate();
-            prompt.onFileCallbackResult(this, resultCode, data);
+                    mGeckoSession.getPromptDelegate();
+            prompt.onFileCallbackResult(resultCode, data);
         } else {
             super.onActivityResult(requestCode, resultCode, data);
         }
     }
 
     @Override
     public void onRequestPermissionsResult(final int requestCode,
                                            final String[] permissions,
                                            final int[] grantResults) {
         if (requestCode == REQUEST_PERMISSIONS) {
             final MyGeckoViewPermission permission = (MyGeckoViewPermission)
-                    mGeckoView.getPermissionDelegate();
+                    mGeckoSession.getPermissionDelegate();
             permission.onRequestPermissionsResult(permissions, grantResults);
         } else {
             super.onRequestPermissionsResult(requestCode, permissions, grantResults);
         }
     }
 
-    private class MyGeckoViewContent implements GeckoView.ContentListener {
+    private class MyGeckoViewContent implements GeckoSession.ContentListener {
         @Override
-        public void onTitleChange(GeckoView view, String title) {
+        public void onTitleChange(GeckoSession session, String title) {
             Log.i(LOGTAG, "Content title changed to " + title);
         }
 
         @Override
-        public void onFullScreen(final GeckoView view, final boolean fullScreen) {
+        public void onFullScreen(final GeckoSession session, final boolean fullScreen) {
             getWindow().setFlags(fullScreen ? WindowManager.LayoutParams.FLAG_FULLSCREEN : 0,
                                  WindowManager.LayoutParams.FLAG_FULLSCREEN);
             if (fullScreen) {
                 getActionBar().hide();
             } else {
                 getActionBar().show();
             }
         }
 
         @Override
-        public void onContextMenu(GeckoView view, int screenX, int screenY,
+        public void onContextMenu(GeckoSession session, int screenX, int screenY,
                                   String uri, String elementSrc) {
             Log.d(LOGTAG, "onContextMenu screenX=" + screenX +
                           " screenY=" + screenY + " uri=" + uri +
                           " elementSrc=" + elementSrc);
         }
     }
 
-    private class MyGeckoViewProgress implements GeckoView.ProgressListener {
+    private class MyGeckoViewProgress implements GeckoSession.ProgressListener {
         @Override
-        public void onPageStart(GeckoView view, String url) {
+        public void onPageStart(GeckoSession session, String url) {
             Log.i(LOGTAG, "Starting to load page at " + url);
             Log.i(LOGTAG, "zerdatime " + SystemClock.elapsedRealtime() +
                   " - page load start");
         }
 
         @Override
-        public void onPageStop(GeckoView view, boolean success) {
+        public void onPageStop(GeckoSession session, boolean success) {
             Log.i(LOGTAG, "Stopping page load " + (success ? "successfully" : "unsuccessfully"));
             Log.i(LOGTAG, "zerdatime " + SystemClock.elapsedRealtime() +
                   " - page load stop");
         }
 
         @Override
-        public void onSecurityChange(GeckoView view, SecurityInformation securityInfo) {
+        public void onSecurityChange(GeckoSession session, SecurityInformation securityInfo) {
             Log.i(LOGTAG, "Security status changed to " + securityInfo.securityMode);
         }
     }
 
-    private class MyGeckoViewPermission implements GeckoView.PermissionDelegate {
+    private class MyGeckoViewPermission implements GeckoSession.PermissionDelegate {
 
         public int androidPermissionRequestCode = 1;
         private Callback mCallback;
 
         public void onRequestPermissionsResult(final String[] permissions,
                                                final int[] grantResults) {
             if (mCallback == null) {
                 return;
@@ -193,46 +198,46 @@ public class GeckoViewActivity extends A
                     cb.reject();
                     return;
                 }
             }
             cb.grant();
         }
 
         @Override
-        public void requestAndroidPermissions(final GeckoView view, final String[] permissions,
+        public void requestAndroidPermissions(final GeckoSession session, final String[] permissions,
                                               final Callback callback) {
             if (Build.VERSION.SDK_INT < 23) {
                 // requestPermissions was introduced in API 23.
                 callback.grant();
                 return;
             }
             mCallback = callback;
             requestPermissions(permissions, androidPermissionRequestCode);
         }
 
         @Override
-        public void requestContentPermission(final GeckoView view, final String uri,
+        public void requestContentPermission(final GeckoSession session, final String uri,
                                              final String type, final String access,
                                              final Callback callback) {
             final int resId;
             if ("geolocation".equals(type)) {
                 resId = R.string.request_geolocation;
             } else if ("desktop-notification".equals(type)) {
                 resId = R.string.request_notification;
             } else {
                 Log.w(LOGTAG, "Unknown permission: " + type);
                 callback.reject();
                 return;
             }
 
             final String title = getString(resId, Uri.parse(uri).getAuthority());
             final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt)
-                    mGeckoView.getPromptDelegate();
-            prompt.promptForPermission(view, title, callback);
+                    mGeckoSession.getPromptDelegate();
+            prompt.promptForPermission(session, title, callback);
         }
 
         private void normalizeMediaName(final GeckoBundle[] sources) {
             if (sources == null) {
                 return;
             }
             for (final GeckoBundle source : sources) {
                 final String mediaSource = source.getString("mediaSource");
@@ -250,17 +255,17 @@ public class GeckoViewActivity extends A
                 } else {
                     name = getString(R.string.media_other);
                 }
                 source.putString("name", name);
             }
         }
 
         @Override
-        public void requestMediaPermission(final GeckoView view, final String uri,
+        public void requestMediaPermission(final GeckoSession session, final String uri,
                                            final GeckoBundle[] video,
                                            final GeckoBundle[] audio,
                                            final MediaCallback callback) {
             final String host = Uri.parse(uri).getAuthority();
             final String title;
             if (audio == null) {
                 title = getString(R.string.request_video, host);
             } else if (video == null) {
@@ -268,39 +273,39 @@ public class GeckoViewActivity extends A
             } else {
                 title = getString(R.string.request_media, host);
             }
 
             normalizeMediaName(video);
             normalizeMediaName(audio);
 
             final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt)
-                    mGeckoView.getPromptDelegate();
-            prompt.promptForMedia(view, title, video, audio, callback);
+                    mGeckoSession.getPromptDelegate();
+            prompt.promptForMedia(session, title, video, audio, callback);
         }
     }
 
-    private class Navigation implements GeckoView.NavigationListener {
+    private class Navigation implements GeckoSession.NavigationListener {
         @Override
-        public void onLocationChange(GeckoView view, final String url) {
+        public void onLocationChange(GeckoSession session, final String url) {
         }
 
         @Override
-        public void onCanGoBack(GeckoView view, boolean canGoBack) {
+        public void onCanGoBack(GeckoSession session, boolean canGoBack) {
         }
 
         @Override
-        public void onCanGoForward(GeckoView view, boolean value) {
+        public void onCanGoForward(GeckoSession session, boolean value) {
         }
 
         @Override
-        public boolean onLoadUri(final GeckoView view, final String uri,
+        public boolean onLoadUri(final GeckoSession session, final String uri,
                                  final TargetWindow where) {
             Log.d(LOGTAG, "onLoadUri=" + uri +
                           " where=" + where);
             if (where != TargetWindow.NEW) {
                 return false;
             }
-            view.loadUri(uri);
+            session.loadUri(uri);
             return true;
         }
     }
 }