Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9293)

Unified Diff: content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java

Issue 2765443004: AndroidOverlay implementation using Dialog. (Closed)
Patch Set: fixed build errors for content_junit_tests Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..82b6f0984592e20593eba8c2bcf1a57d1712df90
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/androidoverlay/DialogOverlayImpl.java
@@ -0,0 +1,207 @@
+// 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.app.Dialog;
+import android.content.Context;
+import android.os.IBinder;
+import android.view.Surface;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.gfx.mojom.Rect;
+import org.chromium.media.mojom.AndroidOverlay;
+import org.chromium.media.mojom.AndroidOverlayClient;
+import org.chromium.media.mojom.AndroidOverlayConfig;
+import org.chromium.mojo.system.MojoException;
+
+/**
+ * Default AndroidOverlay impl. Uses a separate (shared) overlay-ui thread to own a Dialog
+ * instance, probably via a separate object that operates only on that thread. We will post
+ * messages to / from that thread from the main thread.
+ */
+public class DialogOverlayImpl implements AndroidOverlay, DialogOverlayCore.Host,
+ DialogOverlayOperations.WindowTokenListener {
+ private static final String TAG = "DialogOverlayImpl";
+
+ private AndroidOverlayClient mClient;
boliu 2017/03/30 22:42:02 any/all of this can be final?
liberato (no reviews please) 2017/04/04 17:49:29 client, dialogcore: no, cleared when they're clean
+ private DialogOverlayOperations mOps;
+ private DialogOverlayCore mDialogCore;
+ private ThreadHoppingHost mHoppingHost;
+
+ // If nonzero, then we have registered a surface with this ID.
+ private int mSurfaceId;
+
+ // Are we currently registered with |mOps| to receive token updates?
+ private boolean mRegisteredForToken;
+
+ /**
+ * @param client Mojo client interface.
+ * @param config initial overlay configuration.
+ * @param handler handler that posts to the overlay-ui thread. This is the android UI thread
+ * that the dialog uses, not the browser UI thread.
+ * @param provider the overlay provider that owns us.
+ */
+ public DialogOverlayImpl(AndroidOverlayClient client, final AndroidOverlayConfig config,
+ DialogOverlayOperations ops) {
+ mClient = client;
boliu 2017/03/30 22:42:03 probably worth asserting what thread each method r
liberato (no reviews please) 2017/04/04 17:49:29 Done.
+ mOps = ops;
+ mDialogCore = new DialogOverlayCore();
+ mHoppingHost = new ThreadHoppingHost(this);
+
+ // Post init to the proper (overlay-ui) thread.
+ final DialogOverlayCore dialogCore = mDialogCore;
+ final Context context = ContextUtils.getApplicationContext();
+ mOps.getOverlayUiHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ Dialog dialog = mOps.createDialog(context);
+ dialogCore.initialize(dialog, config, mHoppingHost);
+ }
+ });
+
+ // Register to get token updates.
+ mOps.registerWindowTokenListener(config.routingToken, this);
+ mRegisteredForToken = true;
+ }
+
+ @Override
+ public void onSurfaceReady(Surface surface) {
+ if (mDialogCore == null || mClient == null) return;
+
+ mSurfaceId = mOps.registerSurface(surface);
+ mClient.onSurfaceReady(mSurfaceId);
+ }
+
+ @Override
+ public void onOverlayDestroyed() {
+ if (mDialogCore == null) return;
+
+ // Notify the client that the overlay is gone.
+ if (mClient != null) mClient.onDestroyed();
+
+ // Also clear out |mDialogCore| to prevent us from sending useless messages to it. Note
+ // that we might have already sent useless messages to it, and it should be robust against
+ // that sort of thing.
+ cleanup();
+
+ // Note that we don't notify |mOps| yet, though we could. We wait for the client to close
+ // their connection first.
+ }
+
+ // Due to threading issues, |mHoppingHost| doesn't forward this.
+ @Override
+ public void waitForCleanup() {
+ assert false : "Not reached";
+ }
+
+ // Client is done with this overlay.
+ @Override
+ public void close() {
+ // TODO(liberato): verify that this actually works, else add an explicit shutdown and hope
+ // that the client calls it.
+
+ // Allow surfaceDestroyed to proceed, if it's waiting.
+ mHoppingHost.onCleanup();
+
+ // Notify |mDialogCore| that it has been released. This might not be called if it notifies
+ // us that it's been destroyed. We still might send it in that case if the client closes
+ // the connection before we find out that it's been destroyed on the overlay-ui thread.
+ if (mDialogCore != null) {
+ final DialogOverlayCore dialogCore = mDialogCore;
+ mOps.getOverlayUiHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ dialogCore.release();
+ }
+ });
+
+ // Note that we might get messagaes from |mDialogCore| after this, since they might be
+ // dispatched before |r| arrives. Clearing |mDialogCore| causes us to ignore them.
+ cleanup();
+ }
+
+ // Notify the provider that we've been released by the client. Note that the surface might
+ // not have been destroyed yet, but that's okay. We could wait for a callback from the
+ // dialog core before proceeding, but this makes it easier for the client to destroy and
+ // re-create an overlay without worrying about an intermittent failure due to having too
+ // many overlays open at once.
+ mOps.notifyReleased();
+ }
+
+ private void sendWindowTokenToCore(final IBinder token) {
+ final DialogOverlayCore dialogCore = mDialogCore;
+ mOps.getOverlayUiHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ dialogCore.onWindowToken(token);
+ }
+ });
+ }
+
+ @Override
+ public void onWindowToken(final IBinder token) {
+ if (mDialogCore == null) return;
+
+ // Forward this change.
+ // Note that if we don't have a window token, then we could wait until we do, simply by
+ // skipping sending null if we haven't sent any non-null token yet. If we're transitioning
+ // between windows, that might make the client's job easier. It wouldn't have to guess when
+ // a new token is available.
+ sendWindowTokenToCore(token);
+ }
+
+ @Override
+ public void onDismissed() {
+ // Notify the client that the overlay is going away.
+ if (mClient != null) mClient.onDestroyed();
+
+ // Notify |mDialogCore| that it lost the token, if it had one.
+ sendWindowTokenToCore(null);
+
+ cleanup();
+ }
+
+ @Override
+ public void onConnectionError(MojoException e) {
+ close();
+ }
+
+ @Override
+ public void scheduleLayout(final Rect rect) {
+ if (mDialogCore == null) return;
+
+ final DialogOverlayCore dialogCore = mDialogCore;
+ mOps.getOverlayUiHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ dialogCore.layoutSurface(rect);
+ }
+ });
+ }
+
+ /**
+ * Unregister for callbacks, unregister any surface that we have, and forget about
+ * |mDialogCore|. Multiple calls are okay.
+ */
+ private void cleanup() {
+ if (mSurfaceId != 0) {
+ mOps.unregisterSurface(mSurfaceId);
+ mSurfaceId = 0;
+ }
+
+ if (mRegisteredForToken) {
+ mOps.unregisterWindowTokenListener();
+ mRegisteredForToken = false;
+ }
+
+ // Also clear out |mDialogCore| to prevent us from sending useless messages to it. Note
+ // that we might have already sent useless messages to it, and it should be robust against
+ // that sort of thing.
+ if (mDialogCore != null) mDialogCore = null;
boliu 2017/03/30 22:42:03 redundant check
liberato (no reviews please) 2017/04/04 17:49:29 Done.
+
+ // If we wanted to send any message to |mClient|, we should have done so already.
+ mClient = null;
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698