Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.content.browser; | |
| 6 | |
| 7 import android.app.Activity; | |
| 8 import android.os.IBinder; | |
| 9 | |
| 10 import org.chromium.base.annotations.CalledByNative; | |
| 11 import org.chromium.base.annotations.JNINamespace; | |
| 12 import org.chromium.media.DialogSurfaceWindowTokenProvider; | |
| 13 import org.chromium.ui.base.WindowAndroid; | |
| 14 | |
| 15 import java.util.HashMap; | |
| 16 import java.util.HashSet; | |
| 17 | |
| 18 /** | |
| 19 * Implementation of DialogSurfaceWindowTokenProvider. Asks ContentViewCore to | |
| 20 * provide updates on token changes. | |
| 21 */ | |
| 22 @JNINamespace("content") | |
| 23 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
| |
| 24 implements DialogSurfaceWindowTokenProvider, ContentViewCore.Observer { | |
| 25 private static final String TAG = "cr_DialogSurfaceWTP"; | |
| 26 | |
| 27 private class ClientSet extends HashSet<DialogSurfaceWindowTokenProvider.Cli ent> {} | |
|
boliu
2017/01/04 01:48:43
these classes should be static
liberato (no reviews please)
2017/01/11 22:17:56
Done.
| |
| 28 private class ClientMap extends HashMap<ContentViewCore, ClientSet> {} | |
| 29 private class ReverseClientMap | |
| 30 extends HashMap<DialogSurfaceWindowTokenProvider.Client, ContentView Core> {} | |
| 31 | |
| 32 // Access |mClients| and |mReverseClients| with |mClientLock| held. These | |
| 33 // let us associate clients with the ContentViewCore that they're interested | |
| 34 // in listening to. | |
| 35 private final Object mClientLock = new Object(); | |
| 36 private final ClientMap mClients = new ClientMap(); | |
| 37 private final ReverseClientMap mReverseClients = new ReverseClientMap(); | |
| 38 | |
| 39 // This may be called on any thread. | |
| 40 @Override | |
| 41 public void registerClient( | |
| 42 int rendererPid, int renderFrameId, DialogSurfaceWindowTokenProvider .Client client) { | |
| 43 nativeCallBackWithContentViewCore(rendererPid, renderFrameId, this, clie nt); | |
| 44 } | |
| 45 | |
| 46 // This may be called on any thread. | |
| 47 @Override | |
| 48 public void unregisterClient(DialogSurfaceWindowTokenProvider.Client client) { | |
| 49 synchronized (mClientLock) { | |
| 50 unregisterClientLocked(client); | |
| 51 } | |
| 52 } | |
| 53 | |
| 54 // Unregister |client| for updates, with |mClientLock| held. This may be | |
| 55 // called on any thread. | |
| 56 private void unregisterClientLocked(DialogSurfaceWindowTokenProvider.Client client) { | |
| 57 // If we switched threads here, then we could remove mClientLock and | |
| 58 // also unregister for callbacks with CVC. | |
| 59 // Remove client from both the forward and reverse tables. | |
| 60 ContentViewCore cvc = mReverseClients.get(client); | |
| 61 if (cvc == null) return; | |
| 62 | |
| 63 mReverseClients.remove(client); | |
| 64 | |
| 65 ClientSet clients = mClients.get(cvc); | |
| 66 if (clients != null) { | |
| 67 clients.remove(client); | |
| 68 if (clients.size() == 0) { | |
| 69 // We can't cvc.removeObserver(this) here, since we can be on | |
| 70 // the wrong thread. Instead, simply ignore it and skip the | |
| 71 // callbacks if needed. We could probably remove it on the | |
| 72 // next callback, which will be on the correct thread. | |
| 73 // Do not post a remove, though, since we might re-attach in | |
| 74 // the interim. | |
| 75 mClients.remove(cvc); | |
| 76 } | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 /** | |
| 81 * Receive a callback from native with a previously requested ContentViewCor e. | |
| 82 * This is called on the UI thread. | |
| 83 */ | |
| 84 @CalledByNative | |
| 85 private void onContentViewCore( | |
| 86 DialogSurfaceWindowTokenProvider.Client client, ContentViewCore cvc) { | |
| 87 IBinder token = null; | |
| 88 | |
| 89 if (cvc != null) { | |
| 90 WindowAndroid windowAndroid = cvc.getWindowAndroid(); | |
| 91 if (windowAndroid != null) { | |
| 92 token = windowAndroid.getWindowToken(); | |
| 93 } | |
| 94 | |
| 95 // Register to get updates about window changes, so that we know | |
| 96 // when the token changes. | |
| 97 // Note that we might actually already be a client of this, if we | |
| 98 // unregistered the last client for |cvc| and then a new one came | |
| 99 // along before we got around to unregistering. That's okay. We | |
| 100 // could prevent it, but it's not worth the book-keeping right now. | |
| 101 // We're the only observer anyway. | |
| 102 cvc.addObserver(this); | |
| 103 } | |
| 104 | |
| 105 client.onWindowToken(token); | |
| 106 addClient(cvc, client); | |
| 107 } | |
| 108 | |
| 109 // This will be called on the UI thread. | |
| 110 @Override | |
| 111 public void onContentViewCoreDestroyed(ContentViewCore cvc) { | |
| 112 synchronized (mClientLock) { | |
| 113 onContentViewCoreDestroyedLocked(cvc); | |
| 114 } | |
| 115 } | |
| 116 | |
| 117 private void onContentViewCoreDestroyedLocked(ContentViewCore cvc) { | |
| 118 ClientSet clients = mClients.get(cvc); | |
| 119 if (clients == null) return; | |
| 120 | |
| 121 // Why not just send back the CVC, and have the client manager setting | |
| 122 // up callbacks? It's only a little weird, because (a) media/ can't | |
| 123 // access ContentViewCore. So, we do it here. Plus, if we ever want | |
| 124 // to move the DialogSurface implementation into the gpu process, we'll | |
| 125 // be still running in the browser anyway. So, we do it here. | |
| 126 for (DialogSurfaceWindowTokenProvider.Client client : clients) { | |
| 127 mReverseClients.remove(client); | |
| 128 // We might want to notify them that the CVC was destroyed, | |
| 129 // rather than telling them that there's simply no token. | |
| 130 client.onWindowToken(null); | |
| 131 } | |
| 132 | |
| 133 mClients.remove(cvc); | |
| 134 } | |
| 135 | |
| 136 // This will be called on the UI thread. | |
| 137 @Override | |
| 138 public void onAttachedToWindowAndroid(ContentViewCore cvc) { | |
| 139 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.
| |
| 140 IBinder token = null; | |
| 141 if (activity != null) { | |
| 142 token = activity.getWindow().getDecorView().getRootView().getWindowT oken(); | |
| 143 } | |
| 144 | |
| 145 // Don't bother to call back if there's no token anyway. | |
| 146 if (token == null) return; | |
| 147 | |
| 148 synchronized (mClientLock) { | |
| 149 ClientSet clients = mClients.get(cvc); | |
| 150 if (clients == null) { | |
| 151 // We no longer have any clients, so remove this observer. | |
| 152 cvc.removeObserver(this); | |
| 153 return; | |
| 154 } | |
| 155 | |
| 156 for (DialogSurfaceWindowTokenProvider.Client client : clients) { | |
| 157 client.onWindowToken(token); | |
| 158 } | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 // This will be called on the UI thread. | |
| 163 @Override | |
| 164 public void onDetachedFromWindowAndroid(ContentViewCore cvc) { | |
| 165 synchronized (mClientLock) { | |
| 166 ClientSet clients = mClients.get(cvc); | |
| 167 if (clients == null) { | |
| 168 // We no longer have any clients, so remove this observer. | |
| 169 cvc.removeObserver(this); | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 for (DialogSurfaceWindowTokenProvider.Client client : clients) { | |
| 174 client.onWindowToken(null); | |
| 175 } | |
| 176 } | |
| 177 } | |
| 178 | |
| 179 // |client| is now a client of |cvc|, so that it receives future updates | |
| 180 // about the window token for |cvc|'s activity. | |
| 181 // This will be called on the UI thread. | |
| 182 private void addClient(ContentViewCore cvc, DialogSurfaceWindowTokenProvider .Client client) { | |
| 183 synchronized (mClientLock) { | |
| 184 ClientSet clients = mClients.get(cvc); | |
| 185 if (clients == null) { | |
| 186 clients = new ClientSet(); | |
| 187 mClients.put(cvc, clients); | |
| 188 } | |
| 189 clients.add(client); | |
| 190 mReverseClients.put(client, cvc); | |
| 191 } | |
| 192 } | |
| 193 | |
| 194 // Look up the ContentViewCore for (rendererPid, renderFrameId), and call | |
| 195 // back onContentViewCore with it and |client|. The callback will happen | |
| 196 // on the browser UI thread. | |
| 197 private static native void nativeCallBackWithContentViewCore(int rendererPid , int renderFrameId, | |
| 198 DialogSurfaceWindowTokenProvider provider, | |
| 199 DialogSurfaceWindowTokenProvider.Client client); | |
| 200 } | |
| OLD | NEW |