Index: content/public/android/java/src/org/chromium/content/browser/androidoverlay/ThreadHoppingHost.java |
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/ThreadHoppingHost.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/ThreadHoppingHost.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2af612f5d00adf1c0fb357b72a3831d9340df6be |
--- /dev/null |
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/ThreadHoppingHost.java |
@@ -0,0 +1,70 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+package org.chromium.content.browser.androidoverlay; |
+ |
+import android.os.Handler; |
+import android.view.Surface; |
+ |
+import java.util.concurrent.Semaphore; |
+ |
+/** |
+ * DialogOverlayCore::Host implementation that transfers messages to the thread on which it was |
+ * constructed. Due to threading concerns, waitForCleanup is not forwarded. |
+ */ |
+class ThreadHoppingHost implements DialogOverlayCore.Host { |
+ // Handler for the host we're proxying to. Typically Browser::UI. |
+ private Handler mHandler; |
+ |
+ // Host impl that we're proxying to. |
+ private final DialogOverlayCore.Host mHost; |
+ |
+ // Semaphore to keep track of whether cleanup has started yet. |
+ private final Semaphore mSemaphore = new Semaphore(0); |
+ |
+ // We will forward to |host| on whatever thread we're constructed on. |
+ public ThreadHoppingHost(DialogOverlayCore.Host host) { |
+ mHandler = new Handler(); |
+ mHost = host; |
+ } |
+ |
+ @Override |
+ public void onSurfaceReady(final Surface surface) { |
+ mHandler.post(new Runnable() { |
+ @Override |
+ public void run() { |
+ mHost.onSurfaceReady(surface); |
+ } |
+ }); |
+ } |
+ |
+ @Override |
+ public void onOverlayDestroyed() { |
+ mHandler.post(new Runnable() { |
+ @Override |
+ public void run() { |
+ mHost.onOverlayDestroyed(); |
+ } |
+ }); |
+ } |
+ |
+ // We don't forward via to |mHandler|, since it should be asynchronous. Else, the |mHandler| |
+ // thread would block. Instead, we wait here and somebody must call onCleanup() to let us know |
+ // that cleanup has started, and that we may return. |
+ @Override |
+ public void waitForCleanup() { |
+ while (true) { |
+ try { |
+ mSemaphore.acquire(); |
+ break; |
+ } catch (InterruptedException e) { |
+ } |
+ } |
+ } |
+ |
+ // Notify us that cleanup has started. This is called on |mHandler|'s thread. |
+ public void onCleanup() { |
+ mSemaphore.release(1); |
+ } |
+} |