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

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

Issue 2178973004: DialogSurfaceManager implementation. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: removed IDialogSurfaceActivityMapper from common.aidl Created 4 years 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/DialogSurfaceWindowTokenProviderImpl.java
diff --git a/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceWindowTokenProviderImpl.java b/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceWindowTokenProviderImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..eceb851da19e3dde3cc956fd1de8ef500d2a1651
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/DialogSurfaceWindowTokenProviderImpl.java
@@ -0,0 +1,200 @@
+// Copyright 2016 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;
+
+import android.app.Activity;
+import android.os.IBinder;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.media.DialogSurfaceWindowTokenProvider;
+import org.chromium.ui.base.WindowAndroid;
+
+import java.util.HashMap;
+import java.util.HashSet;
+
+/**
+ * Implementation of DialogSurfaceWindowTokenProvider. Asks ContentViewCore to
+ * provide updates on token changes.
+ */
+@JNINamespace("content")
+public class DialogSurfaceWindowTokenProviderImpl
boliu 2017/01/04 23:14:39 I can see why the Manager is singleton, but I don'
liberato (no reviews please) 2017/01/11 22:17:56 most of the code is to look up WebContents given (
boliu 2017/01/12 20:24:18 You can put it in a static method or something.
liberato (no reviews please) 2017/02/03 21:28:32 per our offline discussion, this class is not in P
+ implements DialogSurfaceWindowTokenProvider, ContentViewCore.Observer {
+ private static final String TAG = "cr_DialogSurfaceWTP";
+
+ private class ClientSet extends HashSet<DialogSurfaceWindowTokenProvider.Client> {}
boliu 2017/01/04 01:48:43 these classes should be static
liberato (no reviews please) 2017/01/11 22:17:56 Done.
+ private class ClientMap extends HashMap<ContentViewCore, ClientSet> {}
+ private class ReverseClientMap
+ extends HashMap<DialogSurfaceWindowTokenProvider.Client, ContentViewCore> {}
+
+ // Access |mClients| and |mReverseClients| with |mClientLock| held. These
+ // let us associate clients with the ContentViewCore that they're interested
+ // in listening to.
+ 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 registerClient(
+ int rendererPid, int renderFrameId, DialogSurfaceWindowTokenProvider.Client client) {
+ nativeCallBackWithContentViewCore(rendererPid, renderFrameId, this, client);
+ }
+
+ // This may be called on any thread.
+ @Override
+ public void unregisterClient(DialogSurfaceWindowTokenProvider.Client client) {
+ synchronized (mClientLock) {
+ unregisterClientLocked(client);
+ }
+ }
+
+ // Unregister |client| for updates, with |mClientLock| held. This may be
+ // called on any thread.
+ private void unregisterClientLocked(DialogSurfaceWindowTokenProvider.Client client) {
+ // If we switched threads here, then we could remove mClientLock and
+ // also unregister for callbacks with CVC.
+ // Remove client from both the forward and reverse tables.
+ ContentViewCore cvc = mReverseClients.get(client);
+ if (cvc == null) return;
+
+ mReverseClients.remove(client);
+
+ ClientSet clients = mClients.get(cvc);
+ if (clients != null) {
+ clients.remove(client);
+ if (clients.size() == 0) {
+ // We can't cvc.removeObserver(this) here, since we can be 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.
+ // Do not post a remove, though, since we might re-attach in
+ // the interim.
+ mClients.remove(cvc);
+ }
+ }
+ }
+
+ /**
+ * Receive a callback from native with a previously requested ContentViewCore.
+ * This is called on the UI thread.
+ */
+ @CalledByNative
+ private void onContentViewCore(
+ DialogSurfaceWindowTokenProvider.Client client, ContentViewCore cvc) {
+ IBinder token = null;
+
+ if (cvc != null) {
+ WindowAndroid windowAndroid = cvc.getWindowAndroid();
+ if (windowAndroid != null) {
+ token = windowAndroid.getWindowToken();
+ }
+
+ // Register to get updates about window changes, so that we know
+ // when the token changes.
+ // Note that we might actually already be a client of this, if we
+ // unregistered the last client for |cvc| and then a new one came
+ // along before we got around to unregistering. That's okay. We
+ // could prevent it, but it's not worth the book-keeping right now.
+ // We're the only observer anyway.
+ cvc.addObserver(this);
+ }
+
+ client.onWindowToken(token);
+ addClient(cvc, client);
+ }
+
+ // This will be called on the UI thread.
+ @Override
+ public void onContentViewCoreDestroyed(ContentViewCore cvc) {
+ synchronized (mClientLock) {
+ onContentViewCoreDestroyedLocked(cvc);
+ }
+ }
+
+ private void onContentViewCoreDestroyedLocked(ContentViewCore cvc) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) return;
+
+ // Why not just send back the CVC, and have the client manager setting
+ // up callbacks? It's only a little weird, because (a) media/ can't
+ // access ContentViewCore. So, we do it here. Plus, if we ever want
+ // to move the DialogSurface implementation into the gpu process, we'll
+ // be still running in the browser anyway. So, we do it here.
+ for (DialogSurfaceWindowTokenProvider.Client client : clients) {
+ mReverseClients.remove(client);
+ // We might want to notify them that the CVC was destroyed,
+ // rather than telling them that there's simply no token.
+ client.onWindowToken(null);
+ }
+
+ mClients.remove(cvc);
+ }
+
+ // This will be called on the UI thread.
+ @Override
+ public void onAttachedToWindowAndroid(ContentViewCore cvc) {
+ Activity activity = cvc.getWindowAndroid().getActivity().get();
boliu 2017/01/04 23:14:39 call getWindowToken?
liberato (no reviews please) 2017/01/11 22:17:56 erm, good point.
+ 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) {
+ // We no longer have any clients, so remove this observer.
+ cvc.removeObserver(this);
+ return;
+ }
+
+ for (DialogSurfaceWindowTokenProvider.Client client : clients) {
+ client.onWindowToken(token);
+ }
+ }
+ }
+
+ // This will be called on the UI thread.
+ @Override
+ public void onDetachedFromWindowAndroid(ContentViewCore cvc) {
+ synchronized (mClientLock) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) {
+ // We no longer have any clients, so remove this observer.
+ cvc.removeObserver(this);
+ return;
+ }
+
+ for (DialogSurfaceWindowTokenProvider.Client client : clients) {
+ client.onWindowToken(null);
+ }
+ }
+ }
+
+ // |client| is now a client of |cvc|, so that it receives future updates
+ // about the window token for |cvc|'s activity.
+ // This will be called on the UI thread.
+ private void addClient(ContentViewCore cvc, DialogSurfaceWindowTokenProvider.Client client) {
+ synchronized (mClientLock) {
+ ClientSet clients = mClients.get(cvc);
+ if (clients == null) {
+ clients = new ClientSet();
+ mClients.put(cvc, clients);
+ }
+ clients.add(client);
+ mReverseClients.put(client, cvc);
+ }
+ }
+
+ // Look up the ContentViewCore for (rendererPid, renderFrameId), and call
+ // back onContentViewCore with it and |client|. The callback will happen
+ // on the browser UI thread.
+ private static native void nativeCallBackWithContentViewCore(int rendererPid, int renderFrameId,
+ DialogSurfaceWindowTokenProvider provider,
+ DialogSurfaceWindowTokenProvider.Client client);
+}

Powered by Google App Engine
This is Rietveld 408576698