Bug 1502118 - Add threading annotations to remaining APIs. r=snorp
authorAgi Sferro <agi@mozilla.com>
Mon, 17 Dec 2018 22:31:46 +0000
changeset 511000 0d938252d0ed11c83387e1501aee8ebac8df894a
parent 510999 95951162d7754a91e19172596ff5cb635291adf7
child 511001 4cd3b9cf8159f9b73cfb625dd105eb5cd259395a
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1502118
milestone66.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 1502118 - Add threading annotations to remaining APIs. r=snorp Depends on D13880 Differential Revision: https://phabricator.services.mozilla.com/D13881
mobile/android/geckoview/CHANGELOG.md
mobile/android/geckoview/api.txt
mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/AllowOrDeny.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CompositorController.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/DynamicToolbarAnimator.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResponse.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResult.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/MediaElement.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/OverscrollEdgeEffect.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebMessage.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebResponse.java
--- a/mobile/android/geckoview/CHANGELOG.md
+++ b/mobile/android/geckoview/CHANGELOG.md
@@ -1,13 +1,13 @@
 # v65
 - Moved `CompositorController`, `DynamicToolbarAnimator`,
   `OverscrollEdgeEffect`, `PanZoomController` from `org.mozilla.gecko.gfx` to
   `org.mozilla.geckoview`
-- Added `@UiThread`, `@AnyThread` annotations to several APIs
+- Added `@UiThread`, `@AnyThread` annotations to all APIs
 - Changed `GeckoRuntime#getLocale` to `GeckoRuntime#getLocales` and related APIs.
 - Merged `org.mozilla.gecko.gfx.LayerSession` into `GeckoSession`
 - Added `GeckoSession.MediaDelegate` and `MediaElement`. This allow monitoring
   and control of web media elements (play, pause, seek, etc).
 - Removed unused `access` parameter from
   `GeckoSession.PermissionDelegate#onContentPermissionRequest`
 - Added `WebMessage`, `WebRequest`, `WebResponse`, and `GeckoWebExecutor`. This
   exposes Gecko networking to apps. It includes speculative connections, name
@@ -24,9 +24,9 @@
 - Added `ContentDelegate.ContextElement` to extend the information passed to
   `ContentDelegate#onContextMenu`. Extended information includes the element's
   title and alt attributes.
 - Changed `ContentDelegate.ContextElement` TYPE_ constants to public access.
   Changed `ContentDelegate.ContextElement` to non-final class.
 - Update `CrashReporter.sendCrashReport()` to return the crash ID as a
   GeckoResult<String>.
 
-[api-version]: 8dd1c9e76471e6a1ee520e6c607ed6d3f9156fc2
+[api-version]: c9e474cac6732fc645b03868ad1fcbea10be7b9f
--- a/mobile/android/geckoview/api.txt
+++ b/mobile/android/geckoview/api.txt
@@ -1,18 +1,18 @@
 package org.mozilla.geckoview {
 
-  public final enum AllowOrDeny {
+  @android.support.annotation.AnyThread public final enum AllowOrDeny {
     method public static org.mozilla.geckoview.AllowOrDeny valueOf(java.lang.String);
     method public static org.mozilla.geckoview.AllowOrDeny[] values();
     enum_constant public static final org.mozilla.geckoview.AllowOrDeny ALLOW;
     enum_constant public static final org.mozilla.geckoview.AllowOrDeny DENY;
   }
 
-  public class BasicSelectionActionDelegate implements android.view.ActionMode.Callback org.mozilla.geckoview.GeckoSession.SelectionActionDelegate {
+  @android.support.annotation.UiThread public class BasicSelectionActionDelegate implements android.view.ActionMode.Callback org.mozilla.geckoview.GeckoSession.SelectionActionDelegate {
     ctor public BasicSelectionActionDelegate(android.app.Activity);
     ctor public BasicSelectionActionDelegate(android.app.Activity, boolean);
     method public boolean areExternalActionsEnabled();
     method public void enableExternalActions(boolean);
     method public boolean onActionItemClicked(android.view.ActionMode, android.view.MenuItem);
     method public boolean onCreateActionMode(android.view.ActionMode, android.view.Menu);
     method public void onDestroyActionMode(android.view.ActionMode);
     method public void onGetContentRect(android.view.ActionMode, android.view.View, android.graphics.Rect);
@@ -32,82 +32,82 @@ package org.mozilla.geckoview {
     field protected org.mozilla.geckoview.GeckoResponse<java.lang.String> mResponse;
     field protected org.mozilla.geckoview.GeckoSession.SelectionActionDelegate.Selection mSelection;
     field protected org.mozilla.geckoview.GeckoSession mSession;
     field protected final android.graphics.Matrix mTempMatrix;
     field protected final android.graphics.RectF mTempRect;
     field protected final boolean mUseFloatingToolbar;
   }
 
-  public final class CompositorController {
+  @android.support.annotation.UiThread public final class CompositorController {
     method public void addDrawCallback(java.lang.Runnable);
     method public int getClearColor();
     method public java.lang.Runnable getFirstPaintCallback();
     method public void getPixels(org.mozilla.geckoview.CompositorController.GetPixelsCallback);
     method public void removeDrawCallback(java.lang.Runnable);
     method public void setClearColor(int);
     method public void setFirstPaintCallback(java.lang.Runnable);
   }
 
   public static interface CompositorController.GetPixelsCallback {
-    method public void onPixelsResult(int, int, java.nio.IntBuffer);
+    method @android.support.annotation.UiThread public void onPixelsResult(int, int, java.nio.IntBuffer);
   }
 
   public class CrashReporter {
     ctor public CrashReporter();
-    method public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, android.content.Intent, java.lang.String);
-    method public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, android.os.Bundle, java.lang.String);
-    method public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, java.io.File, java.io.File, boolean, java.lang.String);
-    method public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, java.io.File, java.util.Map<java.lang.String,java.lang.String>, boolean, java.lang.String);
+    method @android.support.annotation.AnyThread public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, android.content.Intent, java.lang.String);
+    method @android.support.annotation.AnyThread public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, android.os.Bundle, java.lang.String);
+    method @android.support.annotation.AnyThread public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, java.io.File, java.io.File, boolean, java.lang.String);
+    method @android.support.annotation.AnyThread public static org.mozilla.geckoview.GeckoResult<java.lang.String> sendCrashReport(android.content.Context, java.io.File, java.util.Map<java.lang.String,java.lang.String>, boolean, java.lang.String);
   }
 
-  public final class DynamicToolbarAnimator {
+  @android.support.annotation.UiThread public final class DynamicToolbarAnimator {
     method public org.mozilla.geckoview.DynamicToolbarAnimator.ToolbarChromeProxy getToolbarChromeProxy();
     method public void hideToolbar(boolean);
     method public boolean isPinned();
     method public boolean isPinnedBy(org.mozilla.geckoview.DynamicToolbarAnimator.PinReason);
     method public void setMaxToolbarHeight(int);
     method public void setPinned(boolean, org.mozilla.geckoview.DynamicToolbarAnimator.PinReason);
     method public void setToolbarChromeProxy(org.mozilla.geckoview.DynamicToolbarAnimator.ToolbarChromeProxy);
     method public void showToolbar(boolean);
   }
 
-  public static final enum DynamicToolbarAnimator.PinReason {
+  @android.support.annotation.AnyThread public static final enum DynamicToolbarAnimator.PinReason {
     method public static org.mozilla.geckoview.DynamicToolbarAnimator.PinReason valueOf(java.lang.String);
     method public static org.mozilla.geckoview.DynamicToolbarAnimator.PinReason[] values();
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason ACTION_MODE;
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason CARET_DRAG;
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason CUSTOM_TAB;
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason DISABLED;
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason FULL_SCREEN;
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason PAGE_LOADING;
     enum_constant public static final org.mozilla.geckoview.DynamicToolbarAnimator.PinReason RELAYOUT;
     field public final int value;
   }
 
   public static interface DynamicToolbarAnimator.ToolbarChromeProxy {
-    method public android.graphics.Bitmap getBitmapOfToolbarChrome();
-    method public boolean isToolbarChromeVisible();
-    method public void toggleToolbarChrome(boolean);
+    method @android.support.annotation.UiThread public android.graphics.Bitmap getBitmapOfToolbarChrome();
+    method @android.support.annotation.UiThread public boolean isToolbarChromeVisible();
+    method @android.support.annotation.UiThread public void toggleToolbarChrome(boolean);
   }
 
   public class GeckoDisplay {
     ctor protected GeckoDisplay(org.mozilla.geckoview.GeckoSession);
     method @android.support.annotation.UiThread public void screenOriginChanged(int, int);
     method @android.support.annotation.UiThread public boolean shouldPinOnScreen();
     method @android.support.annotation.UiThread public void surfaceChanged(android.view.Surface, int, int);
     method @android.support.annotation.UiThread public void surfaceChanged(android.view.Surface, int, int, int, int);
     method @android.support.annotation.UiThread public void surfaceDestroyed();
   }
 
   public interface GeckoResponse<T> {
-    method public void respond(T);
+    method @android.support.annotation.AnyThread public void respond(T);
   }
 
-  public class GeckoResult<T> {
+  @android.support.annotation.AnyThread public class GeckoResult<T> {
     ctor public GeckoResult();
     ctor public GeckoResult(android.os.Handler);
     ctor public GeckoResult(org.mozilla.geckoview.GeckoResult<T>);
     method public synchronized void complete(T);
     method public synchronized void completeExceptionally(java.lang.Throwable);
     method public synchronized boolean equals(java.lang.Object);
     method public <U> org.mozilla.geckoview.GeckoResult<U> exceptionally(org.mozilla.geckoview.GeckoResult.OnExceptionListener<U>);
     method public static <T> org.mozilla.geckoview.GeckoResult<T> fromException(java.lang.Throwable);
@@ -119,57 +119,57 @@ package org.mozilla.geckoview {
     method public <U> org.mozilla.geckoview.GeckoResult<U> then(org.mozilla.geckoview.GeckoResult.OnValueListener<T,U>);
     method public <U> org.mozilla.geckoview.GeckoResult<U> then(org.mozilla.geckoview.GeckoResult.OnValueListener<T,U>, org.mozilla.geckoview.GeckoResult.OnExceptionListener<U>);
     method public org.mozilla.geckoview.GeckoResult<T> withHandler(android.os.Handler);
     field public static final org.mozilla.geckoview.GeckoResult<org.mozilla.geckoview.AllowOrDeny> ALLOW;
     field public static final org.mozilla.geckoview.GeckoResult<org.mozilla.geckoview.AllowOrDeny> DENY;
   }
 
   public static interface GeckoResult.OnExceptionListener<V> {
-    method public org.mozilla.geckoview.GeckoResult<V> onException(java.lang.Throwable);
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoResult<V> onException(java.lang.Throwable);
   }
 
   public static interface GeckoResult.OnValueListener<T,U> {
-    method public org.mozilla.geckoview.GeckoResult<U> onValue(T);
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoResult<U> onValue(T);
   }
 
   public static final class GeckoResult.UncaughtException extends java.lang.RuntimeException {
     ctor public UncaughtException(java.lang.Throwable);
   }
 
   public final class GeckoRuntime implements android.os.Parcelable {
     ctor public GeckoRuntime();
-    method public void attachTo(android.content.Context);
+    method @android.support.annotation.UiThread public void attachTo(android.content.Context);
     method @android.support.annotation.UiThread public static org.mozilla.geckoview.GeckoRuntime create(android.content.Context);
     method @android.support.annotation.UiThread public static org.mozilla.geckoview.GeckoRuntime create(android.content.Context, org.mozilla.geckoview.GeckoRuntimeSettings);
-    method public int describeContents();
+    method @android.support.annotation.AnyThread public int describeContents();
     method @android.support.annotation.UiThread public static synchronized org.mozilla.geckoview.GeckoRuntime getDefault(android.content.Context);
-    method public org.mozilla.geckoview.GeckoRuntime.Delegate getDelegate();
-    method public java.io.File getProfileDir();
-    method public org.mozilla.geckoview.GeckoRuntimeSettings getSettings();
+    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoRuntime.Delegate getDelegate();
+    method @android.support.annotation.UiThread public java.io.File getProfileDir();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoRuntimeSettings getSettings();
     method @android.support.annotation.UiThread public org.mozilla.geckoview.RuntimeTelemetry getTelemetry();
-    method public void orientationChanged();
-    method public void orientationChanged(int);
-    method public void readFromParcel(android.os.Parcel);
-    method public void setDelegate(org.mozilla.geckoview.GeckoRuntime.Delegate);
-    method public void shutdown();
-    method public void writeToParcel(android.os.Parcel, int);
+    method @android.support.annotation.UiThread public void orientationChanged();
+    method @android.support.annotation.UiThread public void orientationChanged(int);
+    method @android.support.annotation.AnyThread public void readFromParcel(android.os.Parcel);
+    method @android.support.annotation.UiThread public void setDelegate(org.mozilla.geckoview.GeckoRuntime.Delegate);
+    method @android.support.annotation.AnyThread public void shutdown();
+    method @android.support.annotation.AnyThread public void writeToParcel(android.os.Parcel, int);
     field public static final java.lang.String ACTION_CRASHED = "org.mozilla.gecko.ACTION_CRASHED";
     field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoRuntime> CREATOR;
     field public static final java.lang.String EXTRA_CRASH_FATAL = "fatal";
     field public static final java.lang.String EXTRA_EXTRAS_PATH = "extrasPath";
     field public static final java.lang.String EXTRA_MINIDUMP_PATH = "minidumpPath";
     field public static final java.lang.String EXTRA_MINIDUMP_SUCCESS = "minidumpSuccess";
   }
 
   public static interface GeckoRuntime.Delegate {
     method @android.support.annotation.UiThread public void onShutdown();
   }
 
-  public final class GeckoRuntimeSettings implements android.os.Parcelable {
+  @android.support.annotation.AnyThread public final class GeckoRuntimeSettings implements android.os.Parcelable {
     method public int describeContents();
     method public java.lang.String[] getArguments();
     method public boolean getBlockMalware();
     method public boolean getBlockPhishing();
     method public boolean getConsoleOutputEnabled();
     method public int getCookieBehavior();
     method public int getCookieLifetime();
     method public java.lang.Class<?> getCrashHandler();
@@ -203,17 +203,17 @@ package org.mozilla.geckoview {
     field public static final int COOKIE_ACCEPT_NON_TRACKERS = 4;
     field public static final int COOKIE_ACCEPT_VISITED = 3;
     field public static final int COOKIE_LIFETIME_DAYS = 3;
     field public static final int COOKIE_LIFETIME_NORMAL = 0;
     field public static final int COOKIE_LIFETIME_RUNTIME = 2;
     field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoRuntimeSettings> CREATOR;
   }
 
-  public static final class GeckoRuntimeSettings.Builder {
+  @android.support.annotation.AnyThread public static final class GeckoRuntimeSettings.Builder {
     ctor public Builder();
     ctor public Builder(org.mozilla.geckoview.GeckoRuntimeSettings);
     method public org.mozilla.geckoview.GeckoRuntimeSettings.Builder arguments(java.lang.String[]);
     method public org.mozilla.geckoview.GeckoRuntimeSettings.Builder blockMalware(boolean);
     method public org.mozilla.geckoview.GeckoRuntimeSettings.Builder blockPhishing(boolean);
     method public org.mozilla.geckoview.GeckoRuntimeSettings build();
     method public org.mozilla.geckoview.GeckoRuntimeSettings.Builder consoleOutput(boolean);
     method public org.mozilla.geckoview.GeckoRuntimeSettings.Builder cookieBehavior(int);
@@ -233,95 +233,94 @@ package org.mozilla.geckoview {
     method public org.mozilla.geckoview.GeckoRuntimeSettings.Builder webFontsEnabled(boolean);
   }
 
   public class GeckoSession implements android.os.Parcelable {
     ctor public GeckoSession();
     ctor public GeckoSession(org.mozilla.geckoview.GeckoSessionSettings);
     method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoDisplay acquireDisplay();
     method @android.support.annotation.UiThread public void close();
-    method public static java.lang.String createDataUri(byte[], java.lang.String);
-    method public static java.lang.String createDataUri(java.lang.String, java.lang.String);
-    method public int describeContents();
-    method public boolean equals(java.lang.Object);
-    method public void exitFullScreen();
+    method @android.support.annotation.AnyThread public static java.lang.String createDataUri(byte[], java.lang.String);
+    method @android.support.annotation.AnyThread public static java.lang.String createDataUri(java.lang.String, java.lang.String);
+    method @android.support.annotation.AnyThread public int describeContents();
+    method @android.support.annotation.AnyThread public boolean equals(java.lang.Object);
+    method @android.support.annotation.AnyThread public void exitFullScreen();
     method @android.support.annotation.UiThread public org.mozilla.geckoview.SessionAccessibility getAccessibility();
     method @android.support.annotation.UiThread public void getClientBounds(android.graphics.RectF);
     method @android.support.annotation.UiThread public void getClientToScreenMatrix(android.graphics.Matrix);
     method @android.support.annotation.UiThread public void getClientToSurfaceMatrix(android.graphics.Matrix);
     method @android.support.annotation.UiThread public org.mozilla.geckoview.CompositorController getCompositorController();
-    method public org.mozilla.geckoview.GeckoSession.ContentDelegate getContentDelegate();
+    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession.ContentDelegate getContentDelegate();
     method @android.support.annotation.UiThread public org.mozilla.geckoview.DynamicToolbarAnimator getDynamicToolbarAnimator();
-    method public org.mozilla.gecko.EventDispatcher getEventDispatcher();
-    method public org.mozilla.geckoview.SessionFinder getFinder();
-    method public org.mozilla.geckoview.GeckoSession.HistoryDelegate getHistoryDelegate();
-    method public org.mozilla.geckoview.GeckoSession.MediaDelegate getMediaDelegate();
-    method public org.mozilla.geckoview.GeckoSession.NavigationDelegate getNavigationDelegate();
+    method @android.support.annotation.AnyThread public org.mozilla.gecko.EventDispatcher getEventDispatcher();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.SessionFinder getFinder();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSession.HistoryDelegate getHistoryDelegate();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSession.MediaDelegate getMediaDelegate();
+    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession.NavigationDelegate getNavigationDelegate();
     method @android.support.annotation.UiThread public org.mozilla.geckoview.OverscrollEdgeEffect getOverscrollEdgeEffect();
     method @android.support.annotation.UiThread public void getPageToScreenMatrix(android.graphics.Matrix);
     method @android.support.annotation.UiThread public void getPageToSurfaceMatrix(android.graphics.Matrix);
     method @android.support.annotation.UiThread public org.mozilla.geckoview.PanZoomController getPanZoomController();
-    method public org.mozilla.geckoview.GeckoSession.PermissionDelegate getPermissionDelegate();
-    method public org.mozilla.geckoview.GeckoSession.ProgressDelegate getProgressDelegate();
-    method public org.mozilla.geckoview.GeckoSession.PromptDelegate getPromptDelegate();
-    method public org.mozilla.geckoview.GeckoSession.ScrollDelegate getScrollDelegate();
-    method public org.mozilla.geckoview.GeckoSession.SelectionActionDelegate getSelectionActionDelegate();
-    method public org.mozilla.geckoview.GeckoSessionSettings getSettings();
+    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession.PermissionDelegate getPermissionDelegate();
+    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession.ProgressDelegate getProgressDelegate();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSession.PromptDelegate getPromptDelegate();
+    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession.ScrollDelegate getScrollDelegate();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSession.SelectionActionDelegate getSelectionActionDelegate();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSessionSettings getSettings();
     method @android.support.annotation.UiThread public void getSurfaceBounds(android.graphics.Rect);
     method @android.support.annotation.AnyThread public org.mozilla.geckoview.SessionTextInput getTextInput();
-    method public org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate getTrackingProtectionDelegate();
-    method public org.mozilla.geckoview.GeckoResult<java.lang.String> getUserAgent();
-    method public void goBack();
-    method public void goForward();
-    method public int hashCode();
-    method public boolean isOpen();
-    method public void loadData(byte[], java.lang.String);
-    method public void loadString(java.lang.String, java.lang.String);
-    method public void loadUri(java.lang.String);
-    method public void loadUri(java.lang.String, int);
-    method public void loadUri(java.lang.String, java.lang.String, int);
-    method public void loadUri(android.net.Uri);
-    method public void loadUri(android.net.Uri, int);
-    method public void loadUri(android.net.Uri, android.net.Uri, int);
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate getTrackingProtectionDelegate();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoResult<java.lang.String> getUserAgent();
+    method @android.support.annotation.AnyThread public void goBack();
+    method @android.support.annotation.AnyThread public void goForward();
+    method @android.support.annotation.AnyThread public int hashCode();
+    method @android.support.annotation.AnyThread public boolean isOpen();
+    method @android.support.annotation.AnyThread public void loadData(byte[], java.lang.String);
+    method @android.support.annotation.AnyThread public void loadString(java.lang.String, java.lang.String);
+    method @android.support.annotation.AnyThread public void loadUri(java.lang.String);
+    method @android.support.annotation.AnyThread public void loadUri(java.lang.String, int);
+    method @android.support.annotation.AnyThread public void loadUri(java.lang.String, java.lang.String, int);
+    method @android.support.annotation.AnyThread public void loadUri(android.net.Uri);
+    method @android.support.annotation.AnyThread public void loadUri(android.net.Uri, int);
+    method @android.support.annotation.AnyThread public void loadUri(android.net.Uri, android.net.Uri, int);
     method @android.support.annotation.UiThread public void open(org.mozilla.geckoview.GeckoRuntime);
-    method public void readFromParcel(android.os.Parcel);
+    method @android.support.annotation.AnyThread public void readFromParcel(android.os.Parcel);
     method @android.support.annotation.UiThread public void releaseDisplay(org.mozilla.geckoview.GeckoDisplay);
-    method public void reload();
-    method public void restoreState(org.mozilla.geckoview.GeckoSession.SessionState);
-    method public org.mozilla.geckoview.GeckoResult<org.mozilla.geckoview.GeckoSession.SessionState> saveState();
-    method public void setActive(boolean);
-    method public void setContentDelegate(org.mozilla.geckoview.GeckoSession.ContentDelegate);
-    method public void setFocused(boolean);
-    method public void setHistoryDelegate(org.mozilla.geckoview.GeckoSession.HistoryDelegate);
-    method public void setMediaDelegate(org.mozilla.geckoview.GeckoSession.MediaDelegate);
-    method public void setNavigationDelegate(org.mozilla.geckoview.GeckoSession.NavigationDelegate);
-    method public void setPermissionDelegate(org.mozilla.geckoview.GeckoSession.PermissionDelegate);
-    method public void setProgressDelegate(org.mozilla.geckoview.GeckoSession.ProgressDelegate);
-    method public void setPromptDelegate(org.mozilla.geckoview.GeckoSession.PromptDelegate);
-    method public void setScrollDelegate(org.mozilla.geckoview.GeckoSession.ScrollDelegate);
-    method public void setSelectionActionDelegate(org.mozilla.geckoview.GeckoSession.SelectionActionDelegate);
-    method public void setTrackingProtectionDelegate(org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate);
-    method public void stop();
-    method public void writeToParcel(android.os.Parcel, int);
-    method protected void setShouldPinOnScreen(boolean);
+    method @android.support.annotation.AnyThread public void reload();
+    method @android.support.annotation.AnyThread public void restoreState(org.mozilla.geckoview.GeckoSession.SessionState);
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoResult<org.mozilla.geckoview.GeckoSession.SessionState> saveState();
+    method @android.support.annotation.AnyThread public void setActive(boolean);
+    method @android.support.annotation.UiThread public void setContentDelegate(org.mozilla.geckoview.GeckoSession.ContentDelegate);
+    method @android.support.annotation.AnyThread public void setFocused(boolean);
+    method @android.support.annotation.AnyThread public void setHistoryDelegate(org.mozilla.geckoview.GeckoSession.HistoryDelegate);
+    method @android.support.annotation.AnyThread public void setMediaDelegate(org.mozilla.geckoview.GeckoSession.MediaDelegate);
+    method @android.support.annotation.UiThread public void setNavigationDelegate(org.mozilla.geckoview.GeckoSession.NavigationDelegate);
+    method @android.support.annotation.UiThread public void setPermissionDelegate(org.mozilla.geckoview.GeckoSession.PermissionDelegate);
+    method @android.support.annotation.UiThread public void setProgressDelegate(org.mozilla.geckoview.GeckoSession.ProgressDelegate);
+    method @android.support.annotation.AnyThread public void setPromptDelegate(org.mozilla.geckoview.GeckoSession.PromptDelegate);
+    method @android.support.annotation.UiThread public void setScrollDelegate(org.mozilla.geckoview.GeckoSession.ScrollDelegate);
+    method @android.support.annotation.UiThread public void setSelectionActionDelegate(org.mozilla.geckoview.GeckoSession.SelectionActionDelegate);
+    method @android.support.annotation.AnyThread public void setTrackingProtectionDelegate(org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate);
+    method @android.support.annotation.AnyThread public void stop();
+    method @android.support.annotation.AnyThread public void writeToParcel(android.os.Parcel, int);
+    method @android.support.annotation.UiThread protected void setShouldPinOnScreen(boolean);
     field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoSession> CREATOR;
     field public static final int FINDER_DISPLAY_DIM_PAGE = 2;
     field public static final int FINDER_DISPLAY_DRAW_LINK_OUTLINE = 4;
     field public static final int FINDER_DISPLAY_HIGHLIGHT_ALL = 1;
     field public static final int FINDER_FIND_BACKWARDS = 1;
     field public static final int FINDER_FIND_LINKS_ONLY = 8;
     field public static final int FINDER_FIND_MATCH_CASE = 2;
     field public static final int FINDER_FIND_WHOLE_WORD = 4;
     field public static final int LOAD_FLAGS_ALLOW_POPUPS = 8;
     field public static final int LOAD_FLAGS_BYPASS_CACHE = 1;
     field public static final int LOAD_FLAGS_BYPASS_CLASSIFIER = 16;
     field public static final int LOAD_FLAGS_BYPASS_PROXY = 2;
     field public static final int LOAD_FLAGS_EXTERNAL = 4;
     field public static final int LOAD_FLAGS_NONE = 0;
-    field protected final org.mozilla.geckoview.GeckoSession.Compositor mCompositor;
     field protected org.mozilla.geckoview.GeckoSession.Window mWindow;
   }
 
   public static interface GeckoSession.ContentDelegate {
     method @android.support.annotation.UiThread public void onCloseRequest(org.mozilla.geckoview.GeckoSession);
     method @android.support.annotation.UiThread public void onContextMenu(org.mozilla.geckoview.GeckoSession, int, int, org.mozilla.geckoview.GeckoSession.ContentDelegate.ContextElement);
     method @android.support.annotation.UiThread public void onCrash(org.mozilla.geckoview.GeckoSession);
     method @android.support.annotation.UiThread public void onExternalResponse(org.mozilla.geckoview.GeckoSession, org.mozilla.geckoview.GeckoSession.WebResponseInfo);
@@ -339,17 +338,17 @@ package org.mozilla.geckoview {
     field public static final int TYPE_VIDEO = 2;
     field public final java.lang.String altText;
     field public final java.lang.String linkUri;
     field public final java.lang.String srcUri;
     field public final java.lang.String title;
     field public final int type;
   }
 
-  public static final class GeckoSession.FinderResult {
+  @android.support.annotation.AnyThread public static final class GeckoSession.FinderResult {
     ctor protected FinderResult();
     field public final android.graphics.RectF clientRect;
     field public final int current;
     field public final int flags;
     field public final boolean found;
     field public final java.lang.String linkUri;
     field public final java.lang.String searchString;
     field public final int total;
@@ -598,17 +597,17 @@ package org.mozilla.geckoview {
 
   public static class GeckoSession.SelectionActionDelegate.Selection {
     ctor protected Selection();
     field public final android.graphics.RectF clientRect;
     field public final int flags;
     field public final java.lang.String text;
   }
 
-  public static class GeckoSession.SessionState implements android.os.Parcelable {
+  @android.support.annotation.AnyThread public static class GeckoSession.SessionState implements android.os.Parcelable {
     ctor public SessionState(java.lang.String);
     method public int describeContents();
     method public void readFromParcel(android.os.Parcel);
     method public java.lang.String toString();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoSession.SessionState> CREATOR;
   }
 
@@ -648,25 +647,25 @@ package org.mozilla.geckoview {
     field public static final int CATEGORY_NONE = 0;
     field public static final int CATEGORY_SOCIAL = 4;
     field public static final int CATEGORY_TEST = 16;
   }
 
   public static interface GeckoSession.TrackingProtectionDelegate.Category implements java.lang.annotation.Annotation {
   }
 
-  public static class GeckoSession.WebResponseInfo {
+  @android.support.annotation.AnyThread public static class GeckoSession.WebResponseInfo {
     ctor protected WebResponseInfo();
     field public final long contentLength;
     field public final java.lang.String contentType;
     field public final java.lang.String filename;
     field public final java.lang.String uri;
   }
 
-  public final class GeckoSessionSettings implements android.os.Parcelable {
+  @android.support.annotation.AnyThread public final class GeckoSessionSettings implements android.os.Parcelable {
     ctor public GeckoSessionSettings();
     ctor public GeckoSessionSettings(org.mozilla.geckoview.GeckoSessionSettings);
     method public int describeContents();
     method public boolean equals(java.lang.Object);
     method public boolean getBoolean(org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean>);
     method public int getInt(org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Integer>);
     method public java.lang.String getString(org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.String>);
     method public int hashCode();
@@ -695,44 +694,44 @@ package org.mozilla.geckoview {
     field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> USE_MULTIPROCESS;
     field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> USE_PRIVATE_MODE;
     field public static final org.mozilla.geckoview.GeckoSessionSettings.Key<java.lang.Boolean> USE_TRACKING_PROTECTION;
   }
 
   public static class GeckoSessionSettings.Key<T> {
   }
 
-  public class GeckoView extends android.widget.FrameLayout {
+  @android.support.annotation.UiThread public class GeckoView extends android.widget.FrameLayout {
     ctor public GeckoView(android.content.Context);
     ctor public GeckoView(android.content.Context, android.util.AttributeSet);
     method public void autofill(android.util.SparseArray<android.view.autofill.AutofillValue>);
-    method @android.support.annotation.UiThread public void coverUntilFirstPaint(int);
+    method public void coverUntilFirstPaint(int);
     method public void dispatchDraw(android.graphics.Canvas);
     method public boolean gatherTransparentRegion(android.graphics.Region);
-    method @android.support.annotation.UiThread public org.mozilla.geckoview.DynamicToolbarAnimator getDynamicToolbarAnimator();
-    method public org.mozilla.gecko.EventDispatcher getEventDispatcher();
+    method public org.mozilla.geckoview.DynamicToolbarAnimator getDynamicToolbarAnimator();
+    method @android.support.annotation.AnyThread public org.mozilla.gecko.EventDispatcher getEventDispatcher();
     method public android.os.Handler getHandler();
-    method @android.support.annotation.UiThread public org.mozilla.geckoview.PanZoomController getPanZoomController();
-    method public org.mozilla.geckoview.GeckoSession getSession();
+    method public org.mozilla.geckoview.PanZoomController getPanZoomController();
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoSession getSession();
     method public void onAttachedToWindow();
     method public android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
     method public void onDetachedFromWindow();
     method public boolean onGenericMotionEvent(android.view.MotionEvent);
     method public boolean onKeyDown(int, android.view.KeyEvent);
     method public boolean onKeyLongPress(int, android.view.KeyEvent);
     method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
     method public boolean onKeyPreIme(int, android.view.KeyEvent);
     method public boolean onKeyUp(int, android.view.KeyEvent);
     method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public void onWindowFocusChanged(boolean);
-    method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession releaseSession();
-    method @android.support.annotation.UiThread public void setSession(org.mozilla.geckoview.GeckoSession);
-    method @android.support.annotation.UiThread public void setSession(org.mozilla.geckoview.GeckoSession, org.mozilla.geckoview.GeckoRuntime);
-    method @android.support.annotation.UiThread public boolean shouldPinOnScreen();
+    method public org.mozilla.geckoview.GeckoSession releaseSession();
+    method public void setSession(org.mozilla.geckoview.GeckoSession);
+    method public void setSession(org.mozilla.geckoview.GeckoSession, org.mozilla.geckoview.GeckoRuntime);
+    method public boolean shouldPinOnScreen();
     method protected void onConfigurationChanged(android.content.res.Configuration);
     method protected void onFocusChanged(boolean, int, android.graphics.Rect);
     method protected void onRestoreInstanceState(android.os.Parcelable);
     method protected android.os.Parcelable onSaveInstanceState();
     method protected void onWindowVisibilityChanged(int);
     field protected final org.mozilla.geckoview.GeckoView.Display mDisplay;
     field protected org.mozilla.geckoview.GeckoRuntime mRuntime;
     field protected org.mozilla.geckoview.GeckoSession mSession;
@@ -747,17 +746,17 @@ package org.mozilla.geckoview {
     method public void speculativeConnect(java.lang.String);
     field public static final int FETCH_FLAGS_ANONYMOUS = 1;
     field public static final int FETCH_FLAGS_NONE = 0;
   }
 
   public static interface GeckoWebExecutor.FetchFlags implements java.lang.annotation.Annotation {
   }
 
-  public class MediaElement {
+  @android.support.annotation.AnyThread public class MediaElement {
     method public org.mozilla.geckoview.MediaElement.Delegate getDelegate();
     method public void pause();
     method public void play();
     method public void seek(double);
     method public void setDelegate(org.mozilla.geckoview.MediaElement.Delegate);
     method public void setMuted(boolean);
     method public void setPlaybackRate(double);
     method public void setVolume(double);
@@ -818,111 +817,111 @@ package org.mozilla.geckoview {
     field public final java.lang.String currentSource;
     field public final double duration;
     field public final long height;
     field public final boolean isSeekable;
     field public final int videoTrackCount;
     field public final long width;
   }
 
-  public final class OverscrollEdgeEffect {
+  @android.support.annotation.UiThread public final class OverscrollEdgeEffect {
     method public void draw(android.graphics.Canvas);
     method public java.lang.Runnable getInvalidationCallback();
     method public void setInvalidationCallback(java.lang.Runnable);
     method public void setTheme(android.content.Context);
   }
 
-  public class PanZoomController extends org.mozilla.gecko.mozglue.JNIObject {
+  @android.support.annotation.UiThread public class PanZoomController extends org.mozilla.gecko.mozglue.JNIObject {
     ctor protected PanZoomController(org.mozilla.geckoview.GeckoSession);
     method public float getScrollFactor();
     method public boolean onMotionEvent(android.view.MotionEvent);
     method public boolean onMouseEvent(android.view.MotionEvent);
     method public boolean onTouchEvent(android.view.MotionEvent);
     method public void setIsLongpressEnabled(boolean);
     method public void setScrollFactor(float);
     method protected void disposeNative();
     method protected void finalize();
   }
 
   public final class RuntimeTelemetry {
-    method public org.mozilla.geckoview.GeckoResult<org.mozilla.gecko.util.GeckoBundle> getSnapshots(boolean);
+    method @android.support.annotation.AnyThread public org.mozilla.geckoview.GeckoResult<org.mozilla.gecko.util.GeckoBundle> getSnapshots(boolean);
   }
 
-  public class SessionAccessibility {
+  @android.support.annotation.UiThread public class SessionAccessibility {
     method public android.view.View getView();
     method public boolean onMotionEvent(android.view.MotionEvent);
     method @android.support.annotation.UiThread public void setView(android.view.View);
   }
 
-  public final class SessionFinder {
+  @android.support.annotation.AnyThread public final class SessionFinder {
     method public void clear();
     method public org.mozilla.geckoview.GeckoResult<org.mozilla.geckoview.GeckoSession.FinderResult> find(java.lang.String, int);
     method public int getDisplayFlags();
     method public void setDisplayFlags(int);
   }
 
   public final class SessionTextInput {
-    method public void autofill(android.util.SparseArray<java.lang.CharSequence>);
+    method @android.support.annotation.UiThread public void autofill(android.util.SparseArray<java.lang.CharSequence>);
     method @android.support.annotation.UiThread public org.mozilla.geckoview.GeckoSession.TextInputDelegate getDelegate();
     method @android.support.annotation.AnyThread public synchronized android.os.Handler getHandler(android.os.Handler);
     method @android.support.annotation.UiThread public android.view.View getView();
     method @android.support.annotation.AnyThread public synchronized android.view.inputmethod.InputConnection onCreateInputConnection(android.view.inputmethod.EditorInfo);
     method @android.support.annotation.UiThread public boolean onKeyDown(int, android.view.KeyEvent);
     method @android.support.annotation.UiThread public boolean onKeyLongPress(int, android.view.KeyEvent);
     method @android.support.annotation.UiThread public boolean onKeyMultiple(int, int, android.view.KeyEvent);
     method @android.support.annotation.UiThread public boolean onKeyPreIme(int, android.view.KeyEvent);
     method @android.support.annotation.UiThread public boolean onKeyUp(int, android.view.KeyEvent);
-    method public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
+    method @android.support.annotation.UiThread public void onProvideAutofillVirtualStructure(android.view.ViewStructure, int);
     method @android.support.annotation.UiThread public void setDelegate(org.mozilla.geckoview.GeckoSession.TextInputDelegate);
     method @android.support.annotation.UiThread public synchronized void setView(android.view.View);
   }
 
-  public abstract class WebMessage {
+  @android.support.annotation.AnyThread public abstract class WebMessage {
     ctor protected WebMessage(org.mozilla.geckoview.WebMessage.Builder);
     field public final java.nio.ByteBuffer body;
     field public final java.util.Map<java.lang.String, java.lang.String> headers;
     field public final java.lang.String uri;
   }
 
-  public abstract static class WebMessage.Builder {
+  @android.support.annotation.AnyThread public abstract static class WebMessage.Builder {
     method public org.mozilla.geckoview.WebMessage.Builder addHeader(java.lang.String, java.lang.String);
     method public org.mozilla.geckoview.WebMessage.Builder body(java.nio.ByteBuffer);
     method public org.mozilla.geckoview.WebMessage.Builder header(java.lang.String, java.lang.String);
     method public org.mozilla.geckoview.WebMessage.Builder uri(java.lang.String);
   }
 
-  public class WebRequest extends org.mozilla.geckoview.WebMessage {
+  @android.support.annotation.AnyThread public class WebRequest extends org.mozilla.geckoview.WebMessage {
     ctor public WebRequest(java.lang.String);
     field public static final int CACHE_MODE_DEFAULT = 1;
     field public static final int CACHE_MODE_FORCE_CACHE = 5;
     field public static final int CACHE_MODE_NO_CACHE = 4;
     field public static final int CACHE_MODE_NO_STORE = 2;
     field public static final int CACHE_MODE_ONLY_IF_CACHED = 6;
     field public static final int CACHE_MODE_RELOAD = 3;
     field public final int cacheMode;
     field public final java.lang.String method;
     field public final java.lang.String referrer;
   }
 
-  public static class WebRequest.Builder extends org.mozilla.geckoview.WebMessage.Builder {
+  @android.support.annotation.AnyThread public static class WebRequest.Builder extends org.mozilla.geckoview.WebMessage.Builder {
     ctor public Builder(java.lang.String);
     method public org.mozilla.geckoview.WebRequest.Builder addHeader(java.lang.String, java.lang.String);
     method public org.mozilla.geckoview.WebRequest.Builder body(java.nio.ByteBuffer);
     method public org.mozilla.geckoview.WebRequest build();
     method public org.mozilla.geckoview.WebRequest.Builder cacheMode(int);
     method public org.mozilla.geckoview.WebRequest.Builder header(java.lang.String, java.lang.String);
     method public org.mozilla.geckoview.WebRequest.Builder method(java.lang.String);
     method public org.mozilla.geckoview.WebRequest.Builder referrer(java.lang.String);
     method public org.mozilla.geckoview.WebRequest.Builder uri(java.lang.String);
   }
 
   public static interface WebRequest.CacheMode implements java.lang.annotation.Annotation {
   }
 
-  public class WebRequestError extends java.lang.Exception {
+  @android.support.annotation.AnyThread public class WebRequestError extends java.lang.Exception {
     ctor public WebRequestError(int, int);
     method public boolean equals(java.lang.Object);
     method public int hashCode();
     field public static final int ERROR_CATEGORY_CONTENT = 4;
     field public static final int ERROR_CATEGORY_NETWORK = 3;
     field public static final int ERROR_CATEGORY_PROXY = 6;
     field public static final int ERROR_CATEGORY_SAFEBROWSING = 7;
     field public static final int ERROR_CATEGORY_SECURITY = 2;
@@ -959,45 +958,27 @@ package org.mozilla.geckoview {
   }
 
   public static interface WebRequestError.Error implements java.lang.annotation.Annotation {
   }
 
   public static interface WebRequestError.ErrorCategory implements java.lang.annotation.Annotation {
   }
 
-  public class WebResponse extends org.mozilla.geckoview.WebMessage {
+  @android.support.annotation.AnyThread public class WebResponse extends org.mozilla.geckoview.WebMessage {
     ctor protected WebResponse(org.mozilla.geckoview.WebResponse.Builder);
     field public final boolean redirected;
     field public final int statusCode;
   }
 
-  public static class WebResponse.Builder extends org.mozilla.geckoview.WebMessage.Builder {
+  @android.support.annotation.AnyThread public static class WebResponse.Builder extends org.mozilla.geckoview.WebMessage.Builder {
     ctor public Builder(java.lang.String);
     method public org.mozilla.geckoview.WebResponse.Builder addHeader(java.lang.String, java.lang.String);
     method public org.mozilla.geckoview.WebResponse.Builder body(java.nio.ByteBuffer);
     method public org.mozilla.geckoview.WebResponse build();
     method public org.mozilla.geckoview.WebResponse.Builder header(java.lang.String, java.lang.String);
     method public org.mozilla.geckoview.WebResponse.Builder redirected(boolean);
     method public org.mozilla.geckoview.WebResponse.Builder statusCode(int);
     method public org.mozilla.geckoview.WebResponse.Builder uri(java.lang.String);
   }
 
-  protected class GeckoSession.Compositor extends org.mozilla.gecko.mozglue.JNIObject {
-    ctor protected Compositor();
-    method public native void attachNPZC(org.mozilla.geckoview.PanZoomController);
-    method public native void enableLayerUpdateNotifications(boolean);
-    method public boolean isReady();
-    method public native void onBoundsChanged(int, int, int, int);
-    method public native void requestScreenPixels();
-    method public native void sendToolbarAnimatorMessage(int);
-    method public native void sendToolbarPixelsToCompositor(int, int, int[]);
-    method public native void setDefaultClearColor(int);
-    method public native void setMaxToolbarHeight(int);
-    method public native void setPinned(boolean, int);
-    method public native void syncPauseCompositor();
-    method public native void syncResumeResizeCompositor(int, int, int, int, java.lang.Object);
-    method protected native void disposeNative();
-    method protected void finalize();
-  }
-
 }
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/EventDispatcher.java
@@ -16,16 +16,17 @@ import org.mozilla.gecko.util.GeckoBundl
 import org.mozilla.gecko.util.ThreadUtils;
 import org.mozilla.geckoview.BuildConfig;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.os.Bundle;
 import android.os.Handler;
+import android.support.annotation.AnyThread;
 import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -241,16 +242,17 @@ public final class EventDispatcher exten
 
     /**
      * Dispatch event to any registered Bundle listeners (non-Gecko thread listeners).
      *
      * @param type Event type
      * @param message Bundle message
      * @param callback Optional object for callbacks from events.
      */
+    @AnyThread
     public void dispatch(final String type, final GeckoBundle message,
                          final EventCallback callback) {
         final boolean isGeckoReady;
         synchronized (this) {
             isGeckoReady = isReadyForDispatchingToGecko();
             if (isGeckoReady && mAttachedToGecko && hasGeckoListener(type)) {
                 dispatchToGecko(type, message, JavaCallbackDelegate.wrap(callback));
                 return;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/AllowOrDeny.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/AllowOrDeny.java
@@ -1,14 +1,17 @@
 /* -*- 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.geckoview;
 
+import android.support.annotation.AnyThread;
+
 /**
  * This represents a decision to allow or deny a request.
  */
+@AnyThread
 public enum AllowOrDeny {
     ALLOW, DENY;
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/BasicSelectionActionDelegate.java
@@ -11,22 +11,25 @@ import android.app.Activity;
 import android.content.ActivityNotFoundException;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.os.Build;
 import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 
+import org.mozilla.gecko.util.ThreadUtils;
+
 import java.util.Arrays;
 import java.util.List;
 
 /**
  * Class that implements a basic SelectionActionDelegate. This class is used by GeckoView by
  * default if the consumer does not explicitly set a SelectionActionDelegate.
  *
  * To provide custom actions, extend this class and override the following methods,
@@ -35,16 +38,17 @@ import java.util.List;
  * array must include all actions, available or not, and must not change over the class lifetime.
  *
  * 2) Override {@link #isActionAvailable} to return whether a custom action is currently available.
  *
  * 3) Override {@link #prepareAction} to set custom title and/or icon for a custom action.
  *
  * 4) Override {@link #performAction} to perform a custom action when used.
  */
+@UiThread
 public class BasicSelectionActionDelegate implements ActionMode.Callback,
                                                      GeckoSession.SelectionActionDelegate {
     private static final String LOGTAG = "GeckoBasicSelectionAction";
 
     protected static final String ACTION_PROCESS_TEXT = Intent.ACTION_PROCESS_TEXT;
 
     private static final String[] FLOATING_TOOLBAR_ACTIONS = new String[] {
         ACTION_CUT, ACTION_COPY, ACTION_PASTE, ACTION_SELECT_ALL, ACTION_PROCESS_TEXT
@@ -108,16 +112,17 @@ public class BasicSelectionActionDelegat
     }
 
     /**
      * Set whether to include text actions from other apps in the floating toolbar.
      *
      * @param enable True if external actions should be enabled.
      */
     public void enableExternalActions(final boolean enable) {
+        ThreadUtils.assertOnUiThread();
         mExternalActionsEnabled = enable;
 
         if (mActionMode != null) {
             mActionMode.invalidate();
         }
     }
 
     /**
@@ -239,32 +244,34 @@ public class BasicSelectionActionDelegat
         intent.putExtra(Intent.EXTRA_PROCESS_TEXT, mSelection.text);
         // TODO: implement ability to replace text in Gecko for editable selection (bug 1453137).
         intent.putExtra(Intent.EXTRA_PROCESS_TEXT_READONLY, true);
         return intent;
     }
 
     @Override
     public boolean onCreateActionMode(final ActionMode actionMode, final Menu menu) {
+        ThreadUtils.assertOnUiThread();
         final String[] allActions = getAllActions();
         for (final String actionId : allActions) {
             if (isActionAvailable(actionId)) {
                 if (!mUseFloatingToolbar && (
                         Build.VERSION.SDK_INT == 22 || Build.VERSION.SDK_INT == 23)) {
                     // Android bug where onPrepareActionMode is not called initially.
                     onPrepareActionMode(actionMode, menu);
                 }
                 return true;
             }
         }
         return false;
     }
 
     @Override
     public boolean onPrepareActionMode(final ActionMode actionMode, final Menu menu) {
+        ThreadUtils.assertOnUiThread();
         final String[] allActions = getAllActions();
         boolean changed = false;
 
         // Whether we are repopulating an existing menu.
         mRepopulatedMenu = menu.size() != 0;
 
         // For each action, see if it's available at present, and if necessary,
         // add to or remove from menu.
@@ -297,16 +304,17 @@ public class BasicSelectionActionDelegat
                 changed = true;
             }
         }
         return changed;
     }
 
     @Override
     public boolean onActionItemClicked(final ActionMode actionMode, final MenuItem menuItem) {
+        ThreadUtils.assertOnUiThread();
         MenuItem realMenuItem = null;
         if (mRepopulatedMenu) {
             // When we repopulate an existing menu, Android can sometimes give us an old,
             // deleted MenuItem. Find the current MenuItem that corresponds to the old one.
             final Menu menu = actionMode.getMenu();
             final int size = menu.size();
             for (int i = 0; i < size; i++) {
                 final MenuItem item = menu.getItem(i);
@@ -324,40 +332,43 @@ public class BasicSelectionActionDelegat
             return false;
         }
         final String[] allActions = getAllActions();
         return performAction(allActions[realMenuItem.getItemId() - Menu.FIRST], realMenuItem);
     }
 
     @Override
     public void onDestroyActionMode(final ActionMode actionMode) {
+        ThreadUtils.assertOnUiThread();
         if (!mUseFloatingToolbar) {
             clearSelection();
         }
         mSession = null;
         mSelection = null;
         mActions = null;
         mResponse = null;
         mActionMode = null;
     }
 
     public void onGetContentRect(final ActionMode mode, final View view, final Rect outRect) {
+        ThreadUtils.assertOnUiThread();
         if (mSelection.clientRect == null) {
             return;
         }
         mSession.getClientToScreenMatrix(mTempMatrix);
         mTempMatrix.mapRect(mTempRect, mSelection.clientRect);
         mTempRect.roundOut(outRect);
     }
 
     @TargetApi(Build.VERSION_CODES.M)
     @Override
     public void onShowActionRequest(final GeckoSession session, final Selection selection,
                                     final String[] actions,
                                     final GeckoResponse<String> response) {
+        ThreadUtils.assertOnUiThread();
         mSession = session;
         mSelection = selection;
         mActions = Arrays.asList(actions);
         mResponse = response;
 
         if (mActionMode != null) {
             if (actions.length > 0) {
                 mActionMode.invalidate();
@@ -372,16 +383,17 @@ public class BasicSelectionActionDelegat
                                                     ActionMode.TYPE_FLOATING);
         } else {
             mActionMode = mActivity.startActionMode(this);
         }
     }
 
     @Override
     public void onHideAction(GeckoSession session, int reason) {
+        ThreadUtils.assertOnUiThread();
         if (mActionMode == null) {
             return;
         }
 
         switch (reason) {
             case HIDE_REASON_ACTIVE_SCROLL:
             case HIDE_REASON_ACTIVE_SELECTION:
             case HIDE_REASON_INVISIBLE_SELECTION:
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CompositorController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CompositorController.java
@@ -5,25 +5,28 @@
 
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.annotation.RobocopTarget;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.graphics.Color;
 import android.support.annotation.NonNull;
+import android.support.annotation.UiThread;
 
 import java.nio.IntBuffer;
 import java.util.ArrayList;
 import java.util.List;
 
+@UiThread
 public final class CompositorController {
     private final GeckoSession.Compositor mCompositor;
 
     public interface GetPixelsCallback {
+        @UiThread
         void onPixelsResult(int width, int height, IntBuffer pixels);
     }
 
     private List<Runnable> mDrawCallbacks;
     private GetPixelsCallback mGetPixelsCallback;
     private int mDefaultClearColor = Color.WHITE;
     private Runnable mFirstPaintCallback;
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/CrashReporter.java
@@ -1,16 +1,17 @@
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.util.ProxySelector;
 
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
 import android.os.Bundle;
+import android.support.annotation.AnyThread;
 import android.util.Log;
 
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
@@ -64,16 +65,17 @@ public class CrashReporter {
      * @param intent The Intent sent to the {@link GeckoRuntime} crash handler
      * @param appName A human-readable app name.
      * @throws IOException This can be thrown if there was a networking error while sending the report.
      * @throws URISyntaxException This can be thrown if the crash server URI from the extra data was invalid.
      * @return A GeckoResult containing the crash ID as a String.
      * @see GeckoRuntimeSettings.Builder#crashHandler(Class)
      * @see GeckoRuntime#ACTION_CRASHED
      */
+    @AnyThread
     public static GeckoResult<String> sendCrashReport(Context context, Intent intent, String appName)
             throws IOException, URISyntaxException {
         return sendCrashReport(context, intent.getExtras(), appName);
     }
 
     /**
      * Sends a crash report to the Mozilla  <a href="https://wiki.mozilla.org/Socorro">Socorro</a>
      * crash report server.
@@ -86,16 +88,17 @@ public class CrashReporter {
      * @param intentExtras The Bundle of extras attached to the Intent received by a crash handler.
      * @param appName A human-readable app name.
      * @throws IOException This can be thrown if there was a networking error while sending the report.
      * @throws URISyntaxException This can be thrown if the crash server URI from the extra data was invalid.
      * @return A GeckoResult containing the crash ID as a String.
      * @see GeckoRuntimeSettings.Builder#crashHandler(Class)
      * @see GeckoRuntime#ACTION_CRASHED
      */
+    @AnyThread
     public static GeckoResult<String> sendCrashReport(Context context, Bundle intentExtras, String appName)
             throws IOException, URISyntaxException {
         final File dumpFile = new File(intentExtras.getString(GeckoRuntime.EXTRA_MINIDUMP_PATH));
         final File extrasFile = new File(intentExtras.getString(GeckoRuntime.EXTRA_EXTRAS_PATH));
         final boolean success = intentExtras.getBoolean(GeckoRuntime.EXTRA_MINIDUMP_SUCCESS, false);
 
         return sendCrashReport(context, dumpFile, extrasFile, success, appName);
     }
@@ -114,16 +117,17 @@ public class CrashReporter {
      * @param success A boolean indicating whether the dump was successfully generated.
      * @param appName A human-readable app name.
      * @throws IOException This can be thrown if there was a networking error while sending the report.
      * @throws URISyntaxException This can be thrown if the crash server URI from the extra data was invalid.
      * @return A GeckoResult containing the crash ID as a String.
      * @see GeckoRuntimeSettings.Builder#crashHandler(Class)
      * @see GeckoRuntime#ACTION_CRASHED
      */
+    @AnyThread
     public static GeckoResult<String> sendCrashReport(Context context, File minidumpFile, File extrasFile,
                                        boolean success, String appName) throws IOException, URISyntaxException {
         // Compute the minidump hash and generate the stack traces
         computeMinidumpHash(extrasFile, minidumpFile);
 
         // Extract the annotations from the .extra file
         HashMap<String, String> extrasMap = readStringsFromFile(extrasFile.getPath());
 
@@ -140,16 +144,17 @@ public class CrashReporter {
      * @param success A boolean indicating whether the dump was successfully generated.
      * @param appName A human-readable app name.
      * @throws IOException This can be thrown if there was a networking error while sending the report.
      * @throws URISyntaxException This can be thrown if the crash server URI from the extra data was invalid.
      * @return A GeckoResult containing the crash ID as a String.
      * @see GeckoRuntimeSettings.Builder#crashHandler(Class)
      * @see GeckoRuntime#ACTION_CRASHED
      */
+    @AnyThread
     public static GeckoResult<String> sendCrashReport(Context context, File minidumpFile,
                                        Map<String, String> extras, boolean success,
                                        String appName) throws IOException, URISyntaxException {
         Log.d(LOGTAG, "Sending crash report: " + minidumpFile.getPath());
 
         String spec = extras.get(SERVER_URL_KEY);
         if (spec == null) {
             return GeckoResult.fromException(new Exception("No server url present"));
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/DynamicToolbarAnimator.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/DynamicToolbarAnimator.java
@@ -3,24 +3,28 @@
  * 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.geckoview;
 
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.graphics.Bitmap;
+import android.support.annotation.AnyThread;
+import android.support.annotation.UiThread;
 import android.util.Log;
 
 import java.util.EnumSet;
 import java.util.Set;
 
+@UiThread
 public final class DynamicToolbarAnimator {
     private static final String LOGTAG = "GeckoDynamicToolbarAnimator";
 
+    @AnyThread
     public static enum PinReason {
         DISABLED(0),
         RELAYOUT(1),
         ACTION_MODE(2),
         FULL_SCREEN(3),
         CARET_DRAG(4),
         PAGE_LOADING(5),
         CUSTOM_TAB(6);
@@ -28,18 +32,21 @@ public final class DynamicToolbarAnimato
         public final int value;
 
         PinReason(final int aValue) {
             value = aValue;
         }
     }
 
     public interface ToolbarChromeProxy {
+        @UiThread
         public Bitmap getBitmapOfToolbarChrome();
+        @UiThread
         public boolean isToolbarChromeVisible();
+        @UiThread
         public void toggleToolbarChrome(boolean aShow);
     }
 
     private final Set<PinReason> mPinFlags = EnumSet.noneOf(PinReason.class);
 
     private final GeckoSession mTarget;
     private final GeckoSession.Compositor mCompositor;
     private ToolbarChromeProxy mToolbarChromeProxy;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResponse.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResponse.java
@@ -1,19 +1,22 @@
 /* -*- 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.geckoview;
 
+import android.support.annotation.AnyThread;
+
 /**
  * This is used to receive async responses from delegate methods.
  */
 public interface GeckoResponse<T> {
     /**
      * Called when async processing has finished.
      *
      * @param value The value contained in the response.
      */
+    @AnyThread
     void respond(T value);
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResult.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoResult.java
@@ -1,16 +1,17 @@
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.os.Handler;
 import android.os.Looper;
 import android.os.SystemClock;
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import java.util.ArrayList;
 import java.util.concurrent.TimeoutException;
 
 /**
  * GeckoResult is a class that represents an asynchronous result. The result is initially pending,
@@ -146,16 +147,17 @@ import java.util.concurrent.TimeoutExcep
  *     public GeckoResult&lt;Void&gt; onException(final Throwable exception) throws Throwable {
  *         // exception instanceof BarException
  *         return new BazException();
  *     }
  * });</pre>
  *
  * @param <T> The type of the value delivered via the GeckoResult.
  */
+@AnyThread
 public class GeckoResult<T> {
     private static final String LOGTAG = "GeckoResult";
 
     public static final class UncaughtException extends RuntimeException {
         public UncaughtException(final Throwable cause) {
             super(cause);
         }
     }
@@ -552,16 +554,17 @@ public class GeckoResult<T> {
          * Called when a {@link GeckoResult} is completed with a value. Will be
          * called on the same thread where the GeckoResult was created or on
          * the {@link Handler} provided via {@link #withHandler(Handler)}.
          *
          * @param value The value of the {@link GeckoResult}
          * @return Result used to complete the next result in the chain. May be null.
          * @throws Throwable Exception used to complete next result in the chain.
          */
+        @AnyThread
         @Nullable GeckoResult<U> onValue(@Nullable T value) throws Throwable;
     }
 
     /**
      * An interface used to deliver exceptions to listeners of a {@link GeckoResult}
      *
      * @param <V> Type of the vale for the result returned from {@link #onException(Throwable)}
      */
@@ -570,16 +573,17 @@ public class GeckoResult<T> {
          * Called when a {@link GeckoResult} is completed with an exception.
          * Will be called on the same thread where the GeckoResult was created
          * or on the {@link Handler} provided via {@link #withHandler(Handler)}.
          *
          * @param exception Exception that completed the result.
          * @return Result used to complete the next result in the chain. May be null.
          * @throws Throwable Exception used to complete next result in the chain.
          */
+        @AnyThread
         @Nullable GeckoResult<V> onException(@NonNull Throwable exception) throws Throwable;
     }
 
     private boolean haveValue() {
         return mComplete && mError == null;
     }
 
     private boolean haveError() {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntime.java
@@ -11,16 +11,17 @@ import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.content.Context;
 import android.os.Process;
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.text.TextUtils;
 import android.util.Log;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.GeckoAppShell;
@@ -118,17 +119,19 @@ public final class GeckoRuntime implemen
     private Delegate mDelegate;
     private RuntimeTelemetry mTelemetry;
 
     /**
      * Attach the runtime to the given context.
      *
      * @param context The new context to attach to.
      */
+    @UiThread
     public void attachTo(final @NonNull Context context) {
+        ThreadUtils.assertOnUiThread();
         if (DEBUG) {
             Log.d(LOGTAG, "attachTo " + context.getApplicationContext());
         }
         final Context appContext = context.getApplicationContext();
         if (!appContext.equals(GeckoAppShell.getApplicationContext())) {
             GeckoAppShell.setApplicationContext(appContext);
         }
     }
@@ -247,16 +250,17 @@ public final class GeckoRuntime implemen
      * to prevent that, bind the runtime to the process lifetime instead of the
      * activity lifetime.
      *
      * @param context The context of the runtime.
      * @return An initialized runtime.
      */
     @UiThread
     public static @NonNull GeckoRuntime create(final @NonNull Context context) {
+        ThreadUtils.assertOnUiThread();
         return create(context, new GeckoRuntimeSettings());
     }
 
     /**
      * Create a new runtime with the given settings and attach it to the given
      * context.
      *
      * Create will throw if there is already an active Gecko instance running,
@@ -283,16 +287,17 @@ public final class GeckoRuntime implemen
         }
 
         return runtime;
     }
 
     /**
      * Shutdown the runtime. This will invalidate all attached sessions.
      */
+    @AnyThread
     public void shutdown() {
         if (DEBUG) {
             Log.d(LOGTAG, "shutdown");
         }
 
         GeckoSystemStateListener.getInstance().shutdown();
         GeckoThread.forceQuit();
     }
@@ -306,29 +311,33 @@ public final class GeckoRuntime implemen
         void onShutdown();
     }
 
     /**
      * Set a delegate for receiving callbacks relevant to to this GeckoRuntime.
      *
      * @param delegate an implementation of {@link GeckoRuntime.Delegate}.
      */
+    @UiThread
     public void setDelegate(final Delegate delegate) {
+        ThreadUtils.assertOnUiThread();
         mDelegate = delegate;
     }
 
     /**
      * Returns the current delegate, if any.
      *
      * @return an instance of {@link GeckoRuntime.Delegate} or null if no delegate has been set.
      */
+    @UiThread
     public @Nullable Delegate getDelegate() {
         return mDelegate;
     }
 
+    @AnyThread
     public GeckoRuntimeSettings getSettings() {
         return mSettings;
     }
 
     /* package */ void setPref(final String name, final Object value,
                                boolean override) {
         if (override || !GeckoAppShell.isFennec()) {
             // Override pref on Fennec only when requested to prevent
@@ -354,58 +363,69 @@ public final class GeckoRuntime implemen
     }
 
     /**
      * Get the profile directory for this runtime. This is where Gecko stores
      * internal data.
      *
      * @return Profile directory
      */
-    @NonNull public File getProfileDir() {
+    @UiThread
+    public File getProfileDir() {
+        ThreadUtils.assertOnUiThread();
         return GeckoThread.getActiveProfile().getDir();
     }
 
     /**
      * Notify Gecko that the screen orientation has changed.
      */
+    @UiThread
     public void orientationChanged() {
+        ThreadUtils.assertOnUiThread();
         GeckoScreenOrientation.getInstance().update();
     }
 
     /**
      * Notify Gecko that the screen orientation has changed.
      * @param newOrientation The new screen orientation, as retrieved e.g. from the current
      *                       {@link android.content.res.Configuration}.
      */
+    @UiThread
     public void orientationChanged(int newOrientation) {
+        ThreadUtils.assertOnUiThread();
         GeckoScreenOrientation.getInstance().update(newOrientation);
     }
 
     @Override // Parcelable
+    @AnyThread
     public int describeContents() {
         return 0;
     }
 
     @Override // Parcelable
+    @AnyThread
     public void writeToParcel(Parcel out, int flags) {
         out.writeParcelable(mSettings, flags);
     }
 
     // AIDL code may call readFromParcel even though it's not part of Parcelable.
+    @AnyThread
     public void readFromParcel(final Parcel source) {
         mSettings = source.readParcelable(getClass().getClassLoader());
     }
 
     public static final Parcelable.Creator<GeckoRuntime> CREATOR
         = new Parcelable.Creator<GeckoRuntime>() {
         @Override
+        @AnyThread
         public GeckoRuntime createFromParcel(final Parcel in) {
             final GeckoRuntime runtime = new GeckoRuntime();
             runtime.readFromParcel(in);
             return runtime;
         }
 
         @Override
+        @AnyThread
         public GeckoRuntime[] newArray(final int size) {
             return new GeckoRuntime[size];
         }
     };
 }
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -11,30 +11,33 @@ import java.lang.annotation.RetentionPol
 import java.util.Collections;
 import java.util.Map;
 
 import android.app.Service;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.AnyThread;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.support.v4.util.ArrayMap;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.geckoview.GeckoSession.TrackingProtectionDelegate;
 
+@AnyThread
 public final class GeckoRuntimeSettings implements Parcelable {
 
     /**
      * Settings builder used to construct the settings object.
      */
+    @AnyThread
     public static final class Builder {
         private final GeckoRuntimeSettings mSettings;
 
         public Builder() {
             mSettings = new GeckoRuntimeSettings();
         }
 
         public Builder(final GeckoRuntimeSettings settings) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -162,17 +162,17 @@ public class GeckoSession implements Par
     /* package */ final static int LAYERS_UPDATED                   = 10;
     // Sent to compositor when the toolbar snapshot fails.
     /* package */ final static int TOOLBAR_SNAPSHOT_FAILED          = 11;
     // Special message sent from UiCompositorControllerChild once it is open
     /* package */ final static int COMPOSITOR_CONTROLLER_OPEN       = 20;
     // Special message sent from controller to query if the compositor controller is open.
     /* package */ final static int IS_COMPOSITOR_CONTROLLER_OPEN    = 21;
 
-    protected class Compositor extends JNIObject {
+    /* protected */ class Compositor extends JNIObject {
         public boolean isReady() {
             return GeckoSession.this.isCompositorReady();
         }
 
         @WrapForJNI(calledFrom = "ui")
         private void onCompositorAttached() {
             GeckoSession.this.onCompositorAttached();
         }
@@ -252,17 +252,17 @@ public class GeckoSession implements Par
         }
 
         @Override
         protected void finalize() throws Throwable {
             disposeNative();
         }
     }
 
-    protected final Compositor mCompositor = new Compositor();
+    /* package */ final Compositor mCompositor = new Compositor();
 
     @WrapForJNI(stubName = "GetCompositor", calledFrom = "ui")
     private Object getCompositorFromNative() {
         // Only used by native code.
         return mCompositorReady ? mCompositor : null;
     }
 
     /* package */ static abstract class CallbackResult<T> extends GeckoResult<T>
@@ -874,40 +874,45 @@ public class GeckoSession implements Par
         }
     }
 
     /**
      * Get the current user agent string for this GeckoSession.
      *
      * @return a {@link GeckoResult} containing the UserAgent string
      */
+    @AnyThread
     public @NonNull GeckoResult<String> getUserAgent() {
         final CallbackResult<String> result = new CallbackResult<String>() {
             @Override
             public void sendSuccess(final Object value) {
                 complete((String) value);
             }
         };
         mEventDispatcher.dispatch("GeckoView:GetUserAgent", null, result);
         return result;
     }
 
     /**
      * Get the current prompt delegate for this GeckoSession.
      * @return PromptDelegate instance or null if using default delegate.
      */
+    @UiThread
     public PermissionDelegate getPermissionDelegate() {
+        ThreadUtils.assertOnUiThread();
         return mPermissionHandler.getDelegate();
     }
 
     /**
      * Set the current permission delegate for this GeckoSession.
      * @param delegate PermissionDelegate instance or null to use the default delegate.
      */
+    @UiThread
     public void setPermissionDelegate(final PermissionDelegate delegate) {
+        ThreadUtils.assertOnUiThread();
         mPermissionHandler.setDelegate(delegate, this);
     }
 
     private PromptDelegate mPromptDelegate;
 
     private final Listener mListener = new Listener();
 
     /* package */ static final class Window extends JNIObject implements IInterface {
@@ -1144,70 +1149,78 @@ public class GeckoSession implements Par
     }
 
     /* package */ void transferFrom(final GeckoSession session) {
         transferFrom(session.mWindow, session.mSettings, session.mId);
         session.mWindow = null;
     }
 
     @Override // Parcelable
+    @AnyThread
     public int describeContents() {
         return 0;
     }
 
     @Override // Parcelable
+    @AnyThread
     public void writeToParcel(Parcel out, int flags) {
         out.writeStrongInterface(mWindow);
         out.writeParcelable(mSettings, flags);
         out.writeString(mId);
     }
 
     // AIDL code may call readFromParcel even though it's not part of Parcelable.
+    @AnyThread
     public void readFromParcel(final Parcel source) {
         final IBinder binder = source.readStrongBinder();
         final IInterface ifce = (binder != null) ?
                 binder.queryLocalInterface(Window.class.getName()) : null;
         final Window window = (ifce instanceof Window) ? (Window) ifce : null;
         final GeckoSessionSettings settings =
                 source.readParcelable(getClass().getClassLoader());
         final String id = source.readString();
         transferFrom(window, settings, id);
     }
 
     public static final Creator<GeckoSession> CREATOR = new Creator<GeckoSession>() {
         @Override
+        @AnyThread
         public GeckoSession createFromParcel(final Parcel in) {
             final GeckoSession session = new GeckoSession();
             session.readFromParcel(in);
             return session;
         }
 
         @Override
+        @AnyThread
         public GeckoSession[] newArray(final int size) {
             return new GeckoSession[size];
         }
     };
 
     @Override
+    @AnyThread
     public int hashCode() {
         return mId.hashCode();
     }
 
     @Override
+    @AnyThread
     public boolean equals(Object obj) {
         return obj instanceof GeckoSession && mId.equals(((GeckoSession) obj).mId);
     }
 
     /**
      * Return whether this session is open.
      *
      * @return True if session is open.
      * @see #open
      * @see #close
      */
+    @AnyThread
     public boolean isOpen() {
         return mWindow != null;
     }
 
     /* package */ boolean isReady() {
         return mNativeQueue.isReady();
     }
 
@@ -1389,153 +1402,167 @@ public class GeckoSession implements Par
      * Bypass the URI classifier (content blocking and Safe Browsing).
      */
     public static final int LOAD_FLAGS_BYPASS_CLASSIFIER = 1 << 4;
 
     /**
      * Load the given URI.
      * @param uri The URI of the resource to load.
      */
+    @AnyThread
     public void loadUri(@NonNull String uri) {
         loadUri(uri, null, LOAD_FLAGS_NONE);
     }
 
     /**
      * Load the given URI with the specified referrer and load type.
      *
      * @param uri the URI to load
      * @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
      */
+    @AnyThread
     public void loadUri(@NonNull String uri, @LoadFlags int flags) {
         loadUri(uri, null, flags);
     }
 
     /**
      * Load the given URI with the specified referrer and load type.
      *
      * @param uri the URI to load
      * @param referrer the referrer, may be null
      * @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
      */
+    @AnyThread
     public void loadUri(@NonNull String uri, @Nullable String referrer,
                         @LoadFlags int flags) {
         final GeckoBundle msg = new GeckoBundle();
         msg.putString("uri", uri);
         msg.putInt("flags", flags);
 
         if (referrer != null) {
             msg.putString("referrer", referrer);
         }
         mEventDispatcher.dispatch("GeckoView:LoadUri", msg);
     }
 
     /**
      * Load the given URI.
      * @param uri The URI of the resource to load.
      */
+    @AnyThread
     public void loadUri(@NonNull Uri uri) {
         loadUri(uri, null, LOAD_FLAGS_NONE);
     }
 
     /**
      * Load the given URI with the specified referrer and load type.
      * @param uri the URI to load
      * @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
      */
+    @AnyThread
     public void loadUri(@NonNull Uri uri, @LoadFlags int flags) {
         loadUri(uri.toString(), null, flags);
     }
 
     /**
      * Load the given URI with the specified referrer and load type.
      * @param uri the URI to load
      * @param referrer the Uri to use as the referrer
      * @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
      */
+    @AnyThread
     public void loadUri(@NonNull Uri uri, @Nullable Uri referrer,
                         @LoadFlags int flags) {
         loadUri(uri.toString(), referrer != null ? referrer.toString() : null, flags);
     }
 
     /**
      * Load the specified String data. Internally this is converted to a data URI.
      *
      * @param data a String representing the data
      * @param mimeType the mime type of the data, e.g. "text/plain". Maybe be null, in
      *                 which case the type is guessed.
      *
      */
+    @AnyThread
     public void loadString(@NonNull final String data, @Nullable final String mimeType) {
         if (data == null) {
             throw new IllegalArgumentException("data cannot be null");
         }
 
         loadUri(createDataUri(data, mimeType), null, LOAD_FLAGS_NONE);
     }
 
     /**
      * Load the specified bytes. Internally this is converted to a data URI.
      *
      * @param bytes    the data to load
      * @param mimeType the mime type of the data, e.g. video/mp4. May be null, in which
      *                 case the type is guessed.
      */
+    @AnyThread
     public void loadData(@NonNull final byte[] bytes, @Nullable final String mimeType) {
         if (bytes == null) {
             throw new IllegalArgumentException("data cannot be null");
         }
 
         loadUri(createDataUri(bytes, mimeType), null, LOAD_FLAGS_NONE);
     }
 
     /**
      * Creates a data URI of of the form "data:&lt;mime type&gt;,&lt;base64-encoded data&gt;"
      * @param bytes the bytes that should be contained in the URL
      * @param mimeType optional mime type, e.g. text/plain
      * @return a URI String
      */
+    @AnyThread
     public static String createDataUri(@NonNull final byte[] bytes, @Nullable final String mimeType) {
         return String.format("data:%s;base64,%s", mimeType != null ? mimeType : "",
                              Base64.encodeToString(bytes, Base64.NO_WRAP));
     }
 
     /**
      * Creates a data URI of of the form "data:&lt;mime type&gt;,&lt;base64-encoded data&gt;"
      * @param data the String data that should be contained in the URL
      * @param mimeType optional mime type, e.g. text/plain
      * @return a URI String
      */
+    @AnyThread
     public static String createDataUri(@NonNull final String data, @Nullable final String mimeType) {
         return String.format("data:%s,%s", mimeType != null ? mimeType : "", data);
     }
 
     /**
     * Reload the current URI.
     */
+    @AnyThread
     public void reload() {
         mEventDispatcher.dispatch("GeckoView:Reload", null);
     }
 
     /**
     * Stop loading.
     */
+    @AnyThread
     public void stop() {
         mEventDispatcher.dispatch("GeckoView:Stop", null);
     }
 
     /**
     * Go back in history.
     */
+    @AnyThread
     public void goBack() {
         mEventDispatcher.dispatch("GeckoView:GoBack", null);
     }
 
     /**
     * Go forward in history.
     */
+    @AnyThread
     public void goForward() {
         mEventDispatcher.dispatch("GeckoView:GoForward", null);
     }
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true,
             value = {FINDER_FIND_BACKWARDS, FINDER_FIND_LINKS_ONLY,
                     FINDER_FIND_MATCH_CASE, FINDER_FIND_WHOLE_WORD})
@@ -1561,16 +1588,17 @@ public class GeckoSession implements Par
     /** Dim the rest of the page when showing a find-in-page match. */
     public static final int FINDER_DISPLAY_DIM_PAGE = 1 << 1;
     /** Draw outlines around matching links. */
     public static final int FINDER_DISPLAY_DRAW_LINK_OUTLINE = 1 << 2;
 
     /**
      * Represent the result of a find-in-page operation.
      */
+    @AnyThread
     public static final class FinderResult {
         /** Whether a match was found. */
         public final boolean found;
         /** Whether the search wrapped around the top or bottom of the page. */
         public final boolean wrapped;
         /** Ordinal number of the current match starting from 1, or 0 if no match. */
         public final int current;
         /** Total number of matches found so far, or -1 if unknown. */
@@ -1620,16 +1648,17 @@ public class GeckoSession implements Par
         }
     }
 
     /**
      * Get the SessionFinder instance for this session, to perform find-in-page operations.
      *
      * @return SessionFinder instance.
      */
+    @AnyThread
     public SessionFinder getFinder() {
         if (mFinder == null) {
             mFinder = new SessionFinder(getEventDispatcher());
         }
         return mFinder;
     }
 
     /**
@@ -1637,40 +1666,43 @@ public class GeckoSession implements Par
      * visible or not. Setting a GeckoSession to inactive will significantly reduce its memory
      * footprint, but should only be done if the GeckoSession is not currently visible. Note that
      * a session can be active (i.e. visible) but not focused.
      *
      * @param active A boolean determining whether the GeckoSession is active.
      *
      * @see #setFocused
      */
+    @AnyThread
     public void setActive(boolean active) {
         final GeckoBundle msg = new GeckoBundle(1);
         msg.putBoolean("active", active);
         mEventDispatcher.dispatch("GeckoView:SetActive", msg);
     }
 
     /**
      * Move focus to this session or away from this session. Only one session has focus at
      * a given time. Note that a session can be unfocused but still active (i.e. visible).
      *
      * @param focused True if the session should gain focus or
      *                false if the session should lose focus.
      *
      * @see #setActive
      */
+    @AnyThread
     public void setFocused(boolean focused) {
         final GeckoBundle msg = new GeckoBundle(1);
         msg.putBoolean("focused", focused);
         mEventDispatcher.dispatch("GeckoView:SetFocused", msg);
     }
 
     /**
      * Class representing a saved session state.
      */
+    @AnyThread
     public static class SessionState implements Parcelable {
         private String mState;
 
         /**
          * Construct a SessionState from a String.
          *
          * @param state A String representing a SessionState; should originate as output
          *              of SessionState.toString().
@@ -1716,16 +1748,17 @@ public class GeckoSession implements Par
     /**
      * Save the current browsing session state of this GeckoSession. This session state
      * includes the history, scroll position, zoom, and any form data that has been entered,
      * but does not include information pertaining to the GeckoSession itself (for example,
      * this does not include settings on the GeckoSession).
      *
      * @return A {@link GeckoResult} containing the {@link SessionState}
      */
+    @AnyThread
     public @NonNull GeckoResult<SessionState> saveState() {
         CallbackResult<SessionState> result = new CallbackResult<SessionState>() {
             @Override
             public void sendSuccess(final Object value) {
                 complete(new SessionState((String)value));
             }
         };
         mEventDispatcher.dispatch("GeckoView:SaveState", null, result);
@@ -1734,16 +1767,17 @@ public class GeckoSession implements Par
 
     /**
      * Restore a saved state to this GeckoSession; only data that is saved (history, scroll
      * position, zoom, and form data) will be restored. These will overwrite the corresponding
      * state of this GeckoSession.
      *
      * @param state A saved session state; this should originate from GeckoSession.saveState().
      */
+    @AnyThread
     public void restoreState(final SessionState state) {
         final GeckoBundle msg = new GeckoBundle(1);
         msg.putString("state", state.toString());
         mEventDispatcher.dispatch("GeckoView:RestoreState", msg);
     }
 
     // This is the GeckoDisplay acquired via acquireDisplay(), if any.
     private GeckoDisplay mDisplay;
@@ -1785,178 +1819,208 @@ public class GeckoSession implements Par
 
         if (display != mDisplay) {
             throw new IllegalArgumentException("Display not attached");
         }
 
         mDisplay = null;
     }
 
+    @AnyThread
     public GeckoSessionSettings getSettings() {
         return mSettings;
     }
 
     /**
     * Exits fullscreen mode
     */
+    @AnyThread
     public void exitFullScreen() {
         mEventDispatcher.dispatch("GeckoViewContent:ExitFullScreen", null);
     }
 
     /**
     * Set the content callback handler.
     * This will replace the current handler.
     * @param delegate An implementation of ContentDelegate.
     */
+    @UiThread
     public void setContentDelegate(ContentDelegate delegate) {
+        ThreadUtils.assertOnUiThread();
         mContentHandler.setDelegate(delegate, this);
     }
 
     /**
     * Get the content callback handler.
     * @return The current content callback handler.
     */
+    @UiThread
     public ContentDelegate getContentDelegate() {
+        ThreadUtils.assertOnUiThread();
         return mContentHandler.getDelegate();
     }
 
     /**
     * Set the progress callback handler.
     * This will replace the current handler.
     * @param delegate An implementation of ProgressDelegate.
     */
+    @UiThread
     public void setProgressDelegate(ProgressDelegate delegate) {
+        ThreadUtils.assertOnUiThread();
         mProgressHandler.setDelegate(delegate, this);
     }
 
     /**
     * Get the progress callback handler.
     * @return The current progress callback handler.
     */
+    @UiThread
     public ProgressDelegate getProgressDelegate() {
+        ThreadUtils.assertOnUiThread();
         return mProgressHandler.getDelegate();
     }
 
     /**
     * Set the navigation callback handler.
     * This will replace the current handler.
     * @param delegate An implementation of NavigationDelegate.
     */
+    @UiThread
     public void setNavigationDelegate(NavigationDelegate delegate) {
+        ThreadUtils.assertOnUiThread();
         mNavigationHandler.setDelegate(delegate, this);
     }
 
     /**
     * Get the navigation callback handler.
     * @return The current navigation callback handler.
     */
+    @UiThread
     public NavigationDelegate getNavigationDelegate() {
+        ThreadUtils.assertOnUiThread();
         return mNavigationHandler.getDelegate();
     }
 
     /**
     * Set the content scroll callback handler.
     * This will replace the current handler.
     * @param delegate An implementation of ScrollDelegate.
     */
+    @UiThread
     public void setScrollDelegate(ScrollDelegate delegate) {
+        ThreadUtils.assertOnUiThread();
         mScrollHandler.setDelegate(delegate, this);
     }
 
+    @UiThread
     public ScrollDelegate getScrollDelegate() {
+        ThreadUtils.assertOnUiThread();
         return mScrollHandler.getDelegate();
     }
 
     /**
      * Set the history tracking delegate for this session, replacing the
      * current delegate if one is set.
      *
      * @param delegate The history tracking delegate, or {@code null} to unset.
      */
+    @AnyThread
     public void setHistoryDelegate(@Nullable HistoryDelegate delegate) {
         mHistoryHandler.setDelegate(delegate, this);
     }
 
     /** @return The history tracking delegate for this session. */
+    @AnyThread
     public @Nullable HistoryDelegate getHistoryDelegate() {
         return mHistoryHandler.getDelegate();
     }
 
     /**
     * Set the tracking protection callback handler.
     * This will replace the current handler.
     * @param delegate An implementation of TrackingProtectionDelegate.
     */
+    @AnyThread
     public void setTrackingProtectionDelegate(TrackingProtectionDelegate delegate) {
         mTrackingProtectionHandler.setDelegate(delegate, this);
     }
 
     /**
     * Get the tracking protection callback handler.
     * @return The current tracking protection callback handler.
     */
+    @AnyThread
     public TrackingProtectionDelegate getTrackingProtectionDelegate() {
         return mTrackingProtectionHandler.getDelegate();
     }
 
     /**
      * Set the current prompt delegate for this GeckoSession.
      * @param delegate PromptDelegate instance or null to use the built-in delegate.
      */
+    @AnyThread
     public void setPromptDelegate(PromptDelegate delegate) {
         mPromptDelegate = delegate;
     }
 
     /**
      * Get the current prompt delegate for this GeckoSession.
      * @return PromptDelegate instance or null if using built-in delegate.
      */
+    @AnyThread
     public PromptDelegate getPromptDelegate() {
         return mPromptDelegate;
     }
 
     /**
      * Set the current selection action delegate for this GeckoSession.
      *
      * @param delegate SelectionActionDelegate instance or null to unset.
      */
+    @UiThread
     public void setSelectionActionDelegate(@Nullable SelectionActionDelegate delegate) {
+        ThreadUtils.assertOnUiThread();
+
         if (getSelectionActionDelegate() != null) {
             // When the delegate is changed or cleared, make sure onHideAction is called
             // one last time to hide any existing selection action UI. Gecko doesn't keep
             // track of the old delegate, so we can't rely on Gecko to do that for us.
             getSelectionActionDelegate().onHideAction(
                     this, GeckoSession.SelectionActionDelegate.HIDE_REASON_NO_SELECTION);
         }
         mSelectionActionDelegate.setDelegate(delegate, this);
     }
 
     /**
      * Set the media callback handler.
      * This will replace the current handler.
      * @param delegate An implementation of MediaDelegate.
      */
+    @AnyThread
     public void setMediaDelegate(final @Nullable MediaDelegate delegate) {
         mMediaHandler.setDelegate(delegate, this);
     }
 
     /**
      * Get the Media callback handler.
      * @return The current Media callback handler.
      */
+    @AnyThread
     public @Nullable MediaDelegate getMediaDelegate() {
         return mMediaHandler.getDelegate();
     }
 
 
     /**
      * Get the current selection action delegate for this GeckoSession.
      *
      * @return SelectionActionDelegate instance or null if not set.
      */
+    @AnyThread
     public @Nullable SelectionActionDelegate getSelectionActionDelegate() {
         return mSelectionActionDelegate.getDelegate();
     }
 
     private static class PromptCallback implements
         PromptDelegate.AlertCallback, PromptDelegate.ButtonCallback,
         PromptDelegate.TextCallback, PromptDelegate.AuthCallback,
         PromptDelegate.ChoiceCallback, PromptDelegate.FileCallback {
@@ -2339,16 +2403,17 @@ public class GeckoSession implements Par
             }
             default: {
                 callback.sendError("Invalid type");
                 break;
             }
         }
     }
 
+    @UiThread
     protected void setShouldPinOnScreen(final boolean pinned) {
         if (DEBUG) {
             ThreadUtils.assertOnUiThread();
         }
 
         if (mToolbar != null) {
             mToolbar.setPinned(pinned, DynamicToolbarAnimator.PinReason.CARET_DRAG);
         }
@@ -2356,16 +2421,17 @@ public class GeckoSession implements Par
         mShouldPinOnScreen = pinned;
     }
 
     /* package */ boolean shouldPinOnScreen() {
         ThreadUtils.assertOnUiThread();
         return mShouldPinOnScreen;
     }
 
+    @AnyThread
     public EventDispatcher getEventDispatcher() {
         return mEventDispatcher;
     }
 
     public interface ProgressDelegate {
         /**
          * Class representing security information for a site.
          */
@@ -2507,16 +2573,17 @@ public class GeckoSession implements Par
         */
         @UiThread
         void onSecurityChange(GeckoSession session, SecurityInformation securityInfo);
     }
 
     /**
      * WebResponseInfo contains information about a single web response.
      */
+    @AnyThread
     static public class WebResponseInfo {
         /**
          * The URI of the response. Cannot be null.
          */
         @NonNull public final String uri;
 
         /**
          * The content type (mime type) of the response. May be null.
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
@@ -5,23 +5,25 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.util.GeckoBundle;
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Log;
 
 import java.util.Arrays;
 import java.util.Collection;
 
+@AnyThread
 public final class GeckoSessionSettings implements Parcelable {
     private static final String LOGTAG = "GeckoSessionSettings";
     private static final boolean DEBUG = false;
 
     // This needs to match nsIDocShell.idl
     public static final int DISPLAY_MODE_BROWSER = 0;
     public static final int DISPLAY_MODE_MINIMAL_UI = 1;
     public static final int DISPLAY_MODE_STANDALONE = 2;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
@@ -20,18 +20,19 @@ import android.content.res.Configuration
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Build;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.support.annotation.AnyThread;
+import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.support.annotation.NonNull;
 import android.support.annotation.UiThread;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
@@ -40,16 +41,17 @@ import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStructure;
 import android.view.autofill.AutofillValue;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.FrameLayout;
 
+@UiThread
 public class GeckoView extends FrameLayout {
     private static final String LOGTAG = "GeckoView";
     private static final boolean DEBUG = false;
 
     protected final Display mDisplay = new Display();
     protected GeckoSession mSession;
     protected GeckoRuntime mRuntime;
     private boolean mStateSaved;
@@ -206,17 +208,16 @@ public class GeckoView extends FrameLayo
 
     /**
      * Set a color to cover the display surface while a document is being shown. The color
      * is automatically cleared once the new document starts painting. Set to
      * Color.TRANSPARENT to undo the cover.
      *
      * @param color Cover color.
      */
-    @UiThread
     public void coverUntilFirstPaint(final int color) {
         ThreadUtils.assertOnUiThread();
 
         if (mSurfaceView != null) {
             mSurfaceView.setBackgroundColor(color);
         }
     }
 
@@ -224,30 +225,28 @@ public class GeckoView extends FrameLayo
      * Return whether the view should be pinned on the screen. When pinned, the view
      * should not be moved on the screen due to animation, scrolling, etc. A common reason
      * for the view being pinned is when the user is dragging a selection caret inside
      * the view; normal user interaction would be disrupted in that case if the view
      * was moved on screen.
      *
      * @return True if view should be pinned on the screen.
      */
-    @UiThread
     public boolean shouldPinOnScreen() {
         ThreadUtils.assertOnUiThread();
 
         return mDisplay.shouldPinOnScreen();
     }
 
     /* package */ void setActive(final boolean active) {
         if (mSession != null) {
             mSession.setActive(active);
         }
     }
 
-    @UiThread
     public GeckoSession releaseSession() {
         ThreadUtils.assertOnUiThread();
 
         if (mSession == null) {
             return null;
         }
 
         // Cover the view while we are not drawing to the surface.
@@ -279,33 +278,33 @@ public class GeckoView extends FrameLayo
     }
 
     /**
      * Attach a session to this view. The session should be opened before
      * attaching.
      *
      * @param session The session to be attached.
      */
-    @UiThread
     public void setSession(@NonNull final GeckoSession session) {
+        ThreadUtils.assertOnUiThread();
+
         if (!session.isOpen()) {
             throw new IllegalArgumentException("Session must be open before attaching");
         }
 
         setSession(session, session.getRuntime());
     }
 
     /**
      * Attach a session to this view. The session should be opened before
      * attaching or a runtime needs to be provided for automatic opening.
      *
      * @param session The session to be attached.
      * @param runtime The runtime to be used for opening the session.
      */
-    @UiThread
     public void setSession(@NonNull final GeckoSession session,
                            @Nullable final GeckoRuntime runtime) {
         ThreadUtils.assertOnUiThread();
 
         if (mSession != null && mSession.isOpen()) {
             throw new IllegalStateException("Current session is open");
         }
 
@@ -366,31 +365,31 @@ public class GeckoView extends FrameLayo
             session.setSelectionActionDelegate(mSelectionActionDelegate);
         }
 
         if (isFocused()) {
             session.setFocused(true);
         }
     }
 
+    @AnyThread
     public GeckoSession getSession() {
         return mSession;
     }
 
+    @AnyThread
     public EventDispatcher getEventDispatcher() {
         return mSession.getEventDispatcher();
     }
 
-    @UiThread
     public PanZoomController getPanZoomController() {
         ThreadUtils.assertOnUiThread();
         return mSession.getPanZoomController();
     }
 
-    @UiThread
     public DynamicToolbarAnimator getDynamicToolbarAnimator() {
         ThreadUtils.assertOnUiThread();
         return mSession.getDynamicToolbarAnimator();
     }
 
     @Override
     public void onAttachedToWindow() {
         if (mSession == null) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/MediaElement.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/MediaElement.java
@@ -1,30 +1,32 @@
 /* -*- 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.geckoview;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.IntDef;
 import android.support.annotation.Nullable;
 import android.support.annotation.UiThread;
 import android.util.Log;
 
 import org.mozilla.gecko.util.GeckoBundle;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
  * GeckoSession applications can use this class to handle media events
  * and control the HTMLMediaElement externally.
  **/
+@AnyThread
 public class MediaElement {
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({MEDIA_STATE_PLAY, MEDIA_STATE_PLAYING, MEDIA_STATE_PAUSE,
              MEDIA_STATE_ENDED, MEDIA_STATE_SEEKING, MEDIA_STATE_SEEKED,
              MEDIA_STATE_STALLED, MEDIA_STATE_SUSPEND, MEDIA_STATE_WAITING,
              MEDIA_STATE_ABORT, MEDIA_STATE_EMPTIED})
     /* package */ @interface MediaStateFlags {}
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/OverscrollEdgeEffect.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/OverscrollEdgeEffect.java
@@ -9,21 +9,23 @@ import org.mozilla.gecko.util.ThreadUtil
 
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.os.Build;
+import android.support.annotation.UiThread;
 import android.view.View;
 import android.widget.EdgeEffect;
 
 import java.lang.reflect.Field;
 
+@UiThread
 public final class OverscrollEdgeEffect {
     // Used to index particular edges in the edges array
     private static final int TOP = 0;
     private static final int BOTTOM = 1;
     private static final int LEFT = 2;
     private static final int RIGHT = 3;
 
     /* package */ static final int AXIS_X = 0;
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
@@ -6,23 +6,25 @@
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 import org.mozilla.gecko.mozglue.JNIObject;
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.graphics.Rect;
 import android.os.SystemClock;
+import android.support.annotation.UiThread;
 import android.util.Log;
 import android.util.Pair;
 import android.view.MotionEvent;
 import android.view.InputDevice;
 
 import java.util.ArrayList;
 
+@UiThread
 public class PanZoomController extends JNIObject {
     private static final String LOGTAG = "GeckoNPZC";
     private static final int EVENT_SOURCE_SCROLL = 0;
     private static final int EVENT_SOURCE_MOTION = 1;
     private static final int EVENT_SOURCE_MOUSE = 2;
 
     private final GeckoSession mSession;
     private final Rect mTempRect = new Rect();
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/RuntimeTelemetry.java
@@ -1,16 +1,17 @@
 /* -*- 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.geckoview;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.util.Log;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.util.GeckoBundle;
 
 /**
  * The telemetry API gives access to telemetry data of the Gecko runtime.
@@ -35,16 +36,17 @@ public final class RuntimeTelemetry {
      * <li>keyedHistograms</li>
      * <li>scalars</li>
      * <li>keyedScalars</li>
      * </ul>
      *
      * @param clear Whether the retrieved snapshots should be cleared.
      * @return A {@link GeckoResult} with the GeckoBundle snapshot results.
      */
+    @AnyThread
     public @NonNull GeckoResult<GeckoBundle> getSnapshots(final boolean clear) {
         final GeckoBundle msg = new GeckoBundle(1);
         msg.putBoolean("clear", clear);
 
         final GeckoSession.CallbackResult<GeckoBundle> result =
             new GeckoSession.CallbackResult<GeckoBundle>() {
                 @Override
                 public void sendSuccess(final Object value) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionAccessibility.java
@@ -32,16 +32,17 @@ import android.view.accessibility.Access
 import android.view.accessibility.AccessibilityNodeInfo.RangeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo;
 import android.view.accessibility.AccessibilityNodeInfo.CollectionInfo;
 import android.view.accessibility.AccessibilityNodeProvider;
 
 import java.util.Iterator;
 import java.util.LinkedList;
 
+@UiThread
 public class SessionAccessibility {
     private static final String LOGTAG = "GeckoAccessibility";
 
     // This is the number BrailleBack uses to start indexing routing keys.
     private static final int BRAILLE_CLICK_BASE_INDEX = -275000000;
     private static final String ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE =
             "ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE";
 
@@ -489,16 +490,18 @@ public class SessionAccessibility {
     }
 
     /**
       * Get the View instance that delegates accessibility to this session.
       *
       * @return View instance.
       */
     public View getView() {
+        ThreadUtils.assertOnUiThread();
+
         return mView;
     }
 
     /**
       * Set the View instance that should delegate accessibility to this session.
       *
       * @param view View instance.
       */
@@ -612,16 +615,18 @@ public class SessionAccessibility {
             }
         }
 
         @WrapForJNI(dispatchTo = "gecko")
         private static native void toggleNativeAccessibility(boolean enable);
     }
 
     public boolean onMotionEvent(final MotionEvent event) {
+        ThreadUtils.assertOnUiThread();
+
         if (!Settings.isTouchExplorationEnabled()) {
             return false;
         }
 
         if (event.getSource() != InputDevice.SOURCE_TOUCHSCREEN) {
             return false;
         }
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionFinder.java
@@ -6,27 +6,29 @@
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.EventDispatcher;
 import org.mozilla.gecko.util.GeckoBundle;
 import org.mozilla.geckoview.GeckoSession.FinderFindFlags;
 import org.mozilla.geckoview.GeckoSession.FinderDisplayFlags;
 import org.mozilla.geckoview.GeckoSession.FinderResult;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 import android.util.Pair;
 
 import java.util.Arrays;
 import java.util.List;
 
 /**
  * {@code SessionFinder} instances returned by {@link GeckoSession#getFinder()} performs
  * find-in-page operations.
  */
+@AnyThread
 public final class SessionFinder {
     private static final String LOGTAG = "GeckoSessionFinder";
 
     private static final List<Pair<Integer, String>> sFlagNames = Arrays.asList(
             new Pair<>(GeckoSession.FINDER_FIND_BACKWARDS, "backwards"),
             new Pair<>(GeckoSession.FINDER_FIND_LINKS_ONLY, "linksOnly"),
             new Pair<>(GeckoSession.FINDER_FIND_MATCH_CASE, "matchCase"),
             new Pair<>(GeckoSession.FINDER_FIND_WHOLE_WORD, "wholeWord")
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/SessionTextInput.java
@@ -494,16 +494,17 @@ public final class SessionTextInput {
     /**
      * Fill the specified {@link ViewStructure} with auto-fill fields from the current page.
      *
      * @param structure Structure to be filled.
      * @param flags Zero or a combination of {@link View#AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
      *              AUTOFILL_FLAG_*} constants.
      */
     @TargetApi(23)
+    @UiThread
     public void onProvideAutofillVirtualStructure(@NonNull final ViewStructure structure,
                                                   final int flags) {
         final View view = getView();
         if (view != null) {
             structure.setClassName(view.getClass().getName());
         }
         structure.setEnabled(true);
         structure.setVisibility(View.VISIBLE);
@@ -527,16 +528,17 @@ public final class SessionTextInput {
         }
     }
 
     /**
      * Perform auto-fill using the specified values.
      *
      * @param values Map of auto-fill IDs to values.
      */
+    @UiThread
     public void autofill(final SparseArray<CharSequence> values) {
         if (mAutoFillRoots == null) {
             return;
         }
 
         GeckoBundle response = null;
         EventCallback callback = null;
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebMessage.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebMessage.java
@@ -3,30 +3,32 @@
  * 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.geckoview;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import android.support.v4.util.ArrayMap;
 
 import java.nio.ByteBuffer;
 
 import java.util.Collections;
 import java.util.Map;
 
 /**
  * This is an abstract base class for HTTP request and response types.
  */
 @WrapForJNI
+@AnyThread
 public abstract class WebMessage {
 
     /**
      * The URI for the request or response.
      */
     public final @NonNull String uri;
 
     /**
@@ -63,16 +65,17 @@ public abstract class WebMessage {
         String[] values = new String[headers.size()];
         headers.values().toArray(values);
         return values;
     }
 
     /**
      * This is a Builder used by subclasses of {@link WebMessage}.
      */
+    @AnyThread
     public static abstract class Builder {
         /* package */ String mUri;
         /* package */ Map<String, String> mHeaders = new ArrayMap<>();
         /* package */ ByteBuffer mBody;
 
         /**
          * Construct a Builder instance with the specified URI.
          *
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequest.java
@@ -3,30 +3,32 @@
  * 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.geckoview;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.IntDef;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 import java.nio.ByteBuffer;
 
 /**
  * WebRequest represents an HTTP[S] request. The typical pattern is to create instances of this
  * class via {@link WebRequest.Builder}, and fetch responses via {@link GeckoWebExecutor#fetch(WebRequest)}.
  */
 @WrapForJNI
+@AnyThread
 public class WebRequest extends WebMessage {
     /**
      * The HTTP method for the request. Defaults to "GET".
      */
     public final @NonNull String method;
 
     /**
      * The cache mode for the request. See {@link #CACHE_MODE_DEFAULT}.
@@ -102,16 +104,17 @@ public class WebRequest extends WebMessa
         method = builder.mMethod;
         cacheMode = builder.mCacheMode;
         referrer = builder.mReferrer;
     }
 
     /**
      * Builder offers a convenient way for constructing {@link WebRequest} instances.
      */
+    @AnyThread
     public static class Builder extends WebMessage.Builder {
         /* package */ String mMethod = "GET";
         /* package */ int mCacheMode = CACHE_MODE_DEFAULT;
         /* package */ String mReferrer;
 
         /**
          * Construct a Builder instance with the specified URI.
          *
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebRequestError.java
@@ -4,25 +4,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/. */
 
 package org.mozilla.geckoview;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 
 import android.annotation.SuppressLint;
+import android.support.annotation.AnyThread;
 import android.support.annotation.IntDef;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
 /**
  * WebRequestError is simply a container for error codes and categories used by
  * {@link GeckoSession.NavigationDelegate#onLoadError(GeckoSession, String, WebRequestError)}.
  */
+@AnyThread
 public class WebRequestError extends Exception {
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({ERROR_CATEGORY_UNKNOWN, ERROR_CATEGORY_SECURITY,
             ERROR_CATEGORY_NETWORK, ERROR_CATEGORY_CONTENT,
             ERROR_CATEGORY_URI, ERROR_CATEGORY_PROXY,
             ERROR_CATEGORY_SAFEBROWSING})
     public @interface ErrorCategory {}
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebResponse.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebResponse.java
@@ -3,25 +3,27 @@
  * 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.geckoview;
 
 import org.mozilla.gecko.annotation.WrapForJNI;
 
+import android.support.annotation.AnyThread;
 import android.support.annotation.NonNull;
 
 import java.nio.ByteBuffer;
 
 /**
  * WebResponse represents an HTTP[S] response. It is normally created
  * by {@link GeckoWebExecutor#fetch(WebRequest)}.
  */
 @WrapForJNI
+@AnyThread
 public class WebResponse extends WebMessage {
     /**
      * The HTTP status code for the response, e.g. 200.
      */
     public final int statusCode;
 
     /**
      * A boolean indicating whether or not this response is
@@ -34,16 +36,17 @@ public class WebResponse extends WebMess
         this.statusCode = builder.mStatusCode;
         this.redirected = builder.mRedirected;
     }
 
     /**
      * Builder offers a convenient way to create WebResponse instances.
      */
     @WrapForJNI
+    @AnyThread
     public static class Builder extends WebMessage.Builder {
         /* package */ int mStatusCode;
         /* package */ boolean mRedirected;
 
         /**
          * Constructs a new Builder instance with the specified URI.
          *
          * @param uri A URI String.