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

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

Issue 2247383002: Add support for tab migration to DialogSurface Base URL: https://chromium.googlesource.com/chromium/src.git@remaining_surface_manager
Patch Set: cleaned up logs Created 4 years, 4 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/DialogSurfaceActivityMapper.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceActivityMapper.java b/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceActivityMapper.java
index 915b20c04e486a3128cbeacd2ea8bd60b69bd3ca..61e76cf623d1538403742a5056d4798965e2c3f4 100644
--- a/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceActivityMapper.java
+++ b/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceActivityMapper.java
@@ -10,10 +10,12 @@ import android.os.RemoteException;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.Log;
import org.chromium.media.IDialogSurfaceActivityMapper;
import org.chromium.media.IDialogSurfaceHolder;
+import java.util.HashMap;
+import java.util.HashSet;
+
/**
* Implementation of IDialogSurfaceActivityMapper.
* Note that this doesn't have to be exposed via binder if the surfaces are
@@ -21,16 +23,53 @@ import org.chromium.media.IDialogSurfaceHolder;
* process, since that's where the information about the activity is.
* Provided by ChildProcessLauncher to DialogSurfaceManager.
*/
-public class DialogSurfaceActivityMapper extends IDialogSurfaceActivityMapper.Stub {
+public class DialogSurfaceActivityMapper
+ extends IDialogSurfaceActivityMapper.Stub implements ContentViewCore.Observer {
private static final String TAG = "cr_DialogSurfaceAM";
+ private class ClientSet extends HashSet<IDialogSurfaceHolder> {}
+ private class ClientMap extends HashMap<ContentViewCore, ClientSet> {}
+ private class ReverseClientMap extends HashMap<IDialogSurfaceHolder, ContentViewCore> {}
+ // Access mClients with mClientLock held.
+ private final Object mClientLock = new Object();
+ private final ClientMap mClients = new ClientMap();
+ private final ReverseClientMap mReverseClients = new ReverseClientMap();
+
+ // This may be called on any thread.
@Override
- public void postWindowToken(int rendererPid, int renderFrameId, IDialogSurfaceHolder holder) {
+ public void registerHolder(int rendererPid, int renderFrameId, IDialogSurfaceHolder holder) {
nativeCallBackWithContentViewCore(rendererPid, renderFrameId, this, holder);
}
+ // This may be called on any thread.
+ @Override
+ public void unregisterHolder(IDialogSurfaceHolder holder) {
+ // If we switched threads here, then we could remove mClientLock and
+ // also unregister for callbacks with CVC.
+ synchronized (mClientLock) {
+ // Remove holder from both the forward and reverse tables.
+ ContentViewCore cvc = mReverseClients.get(holder);
+ if (cvc == null) return;
+
+ mReverseClients.remove(holder);
+
+ ClientSet clients = mClients.get(cvc);
+ if (clients != null) {
+ clients.remove(holder);
+ if (clients.size() == 0) {
+ // We could cvc.removeObserver(this) here, but we're on the
+ // wrong thread. Instead, simply ignore it and skip the
+ // callbacks if needed. We could probably remove it on the
+ // next callback, which will be on the correct thread.
+ mClients.remove(cvc);
+ }
+ }
+ }
+ }
+
/**
* Receive a callback from native with a previously requested ContentViewCore.
+ * This is called on the UI thread.
*/
@CalledByNative
private void onContentViewCore(IDialogSurfaceHolder holder, ContentViewCore cvc) {
@@ -41,15 +80,94 @@ public class DialogSurfaceActivityMapper extends IDialogSurfaceActivityMapper.St
if (activity != null) {
token = activity.getWindow().getDecorView().getRootView().getWindowToken();
}
+
+ // Register to get updates about window changes, so that we know
+ // when the token changes.
+ cvc.addObserver(this);
}
try {
holder.onWindowToken(token);
+ addClient(cvc, holder);
+ // TODO(liberato): clean up if holder exits.
} catch (RemoteException e) {
Log.e(TAG, "Unable to post token " + token + " to DialogSurfaceHolder", e);
}
}
+ // This will be called on the UI thread.
+ @Override
+ public void onContentViewCoreDestroyed(ContentViewCore cvc) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) return;
+
+ // Why not just send back the CVC, and have the holder manager setting
+ // up callbacks? It's only a little weird, because (a) media/ can't
+ // access ContentViewCore, and (b) we're guaranteed to run in the
+ // browser, while DialogSurface might not.
+ for (IDialogSurfaceHolder holder : clients) {
+ try {
+ holder.onWindowToken(null);
+ } catch (RemoteException e) {
+ }
+ }
+
+ mClients.remove(cvc);
+ }
+
+ // This will be called on the UI thread.
+ @Override
+ public void onAttachedToWindowAndroid(ContentViewCore cvc) {
+ Activity activity = cvc.getWindowAndroid().getActivity().get();
+ IBinder token = null;
+ if (activity != null) {
+ token = activity.getWindow().getDecorView().getRootView().getWindowToken();
+ }
+
+ // Don't bother to call back if there's no token anyway.
+ if (token == null) return;
+
+ synchronized (mClientLock) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) return;
+
+ for (IDialogSurfaceHolder holder : clients) {
+ try {
+ holder.onWindowToken(token);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+
+ // This will be called on the UI thread.
+ @Override
+ public void onDetachedFromWindowAndroid(ContentViewCore cvc) {
+ synchronized (mClientLock) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) return;
+
+ for (IDialogSurfaceHolder holder : clients) {
+ try {
+ holder.onWindowToken(null);
+ } catch (RemoteException e) {
+ }
+ }
+ }
+ }
+
+ private void addClient(ContentViewCore cvc, IDialogSurfaceHolder holder) {
+ synchronized (mClientLock) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) {
+ clients = new ClientSet();
+ mClients.put(cvc, clients);
+ }
+ clients.add(holder);
+ mReverseClients.put(holder, cvc);
+ }
+ }
+
// Look up the ContentViewCore for (rendererPid, renderFrameId), and call
// back onContentViewCore with it and |holder|. The callback will happen
// on the browser UI thread.

Powered by Google App Engine
This is Rietveld 408576698