OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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.androidoverlay; | |
6 | |
7 import android.os.Handler; | |
8 import android.os.HandlerThread; | |
9 import android.support.test.filters.SmallTest; | |
10 | |
11 import org.junit.Assert; | |
12 | |
13 import org.chromium.base.ThreadUtils; | |
14 import org.chromium.base.test.util.Feature; | |
15 import org.chromium.content.browser.framehost.RenderFrameHostImpl; | |
16 import org.chromium.content_shell_apk.ContentShellTestBase; | |
17 import org.chromium.media.mojom.AndroidOverlayClient; | |
18 import org.chromium.media.mojom.AndroidOverlayConfig; | |
19 import org.chromium.mojo.common.mojom.UnguessableToken; | |
20 import org.chromium.mojo.system.MojoException; | |
21 | |
22 import java.util.concurrent.ArrayBlockingQueue; | |
23 import java.util.concurrent.Callable; | |
24 import java.util.concurrent.TimeUnit; | |
25 | |
26 /** | |
27 * Tests for DialogOverlayImpl. | |
28 */ | |
29 public class DialogOverlayImplTest extends ContentShellTestBase { | |
30 private static final String BLANK_URL = "about://blank"; | |
31 | |
32 // The routing token that we'll use to create overlays. | |
33 UnguessableToken mRoutingToken; | |
34 | |
35 // overlay-ui thread. | |
36 HandlerThread mOverlayUiThread; | |
37 Handler mOverlayUiHandler; | |
38 | |
39 // Runnable that will be called on the browser UI thread when an overlay is released. | |
40 Runnable mReleasedRunnable; | |
41 | |
42 // True if we should create a secure overlay. | |
43 boolean mSecure; | |
44 | |
45 /** | |
46 * AndroidOverlay client that supports waiting operations for callbacks. On e may call | |
47 * nextEvent() to get the next callback, waiting if needed. | |
48 */ | |
49 public static class Client implements AndroidOverlayClient { | |
50 // AndroidOverlayClient | |
51 public static final int SURFACE_READY = 0; | |
52 public static final int DESTROYED = 1; | |
53 public static final int CLOSE = 2; | |
54 public static final int CONNECTION_ERROR = 2; | |
55 // AndroidOverlayProviderImpl.Callbacks | |
56 public static final int RELEASED = 100; | |
57 | |
58 /** | |
59 * Records one callback event. | |
60 */ | |
61 public static class Event { | |
62 public Event(int which) { | |
63 this.which = which; | |
64 } | |
65 | |
66 public Event(int which, long surfaceKey) { | |
67 this.which = which; | |
68 this.surfaceKey = surfaceKey; | |
69 } | |
70 | |
71 public Event(int which, MojoException exception) { | |
72 this.which = which; | |
73 } | |
74 | |
75 public int which; | |
76 public long surfaceKey; | |
77 } | |
78 | |
79 private ArrayBlockingQueue<Event> mPending; | |
80 | |
81 public Client() { | |
82 mPending = new ArrayBlockingQueue<Event>(10); | |
83 } | |
84 | |
85 @Override | |
86 public void onSurfaceReady(long surfaceKey) { | |
87 mPending.add(new Event(SURFACE_READY, surfaceKey)); | |
88 } | |
89 | |
90 @Override | |
91 public void onDestroyed() { | |
92 mPending.add(new Event(DESTROYED)); | |
93 } | |
94 | |
95 @Override | |
96 public void close() { | |
97 mPending.add(new Event(CLOSE)); | |
98 } | |
99 | |
100 @Override | |
101 public void onConnectionError(MojoException exception) { | |
102 mPending.add(new Event(CONNECTION_ERROR, exception)); | |
103 } | |
104 | |
105 // This isn't part of the overlay client. It's called by the overlay to indicate that it | |
106 // has been released by the client, but it's routed to us anyway. It's on the Browser UI | |
107 // thread, and it's convenient for us to keep track of it here. | |
108 public void notifyReleased() { | |
109 mPending.add(new Event(RELEASED)); | |
110 } | |
111 | |
112 // Wait for something to happen. We enforce a timeout, since the test h arness doesn't | |
113 // always seem to fail the test when it times out. Plus, it takes ~minu te for that, but | |
114 // none of our messages should take that long. | |
115 Event nextEvent() { | |
116 try { | |
117 return mPending.poll(500, TimeUnit.MILLISECONDS); | |
118 } catch (InterruptedException e) { | |
119 Assert.fail(e.toString()); | |
120 } | |
121 | |
122 // NOTREACHED | |
123 return null; | |
124 } | |
125 | |
126 boolean isEmpty() { | |
127 return mPending.size() == 0; | |
128 } | |
129 } | |
130 | |
131 private Client mClient = new Client(); | |
132 | |
133 @Override | |
134 public void setUp() throws Exception { | |
135 super.setUp(); | |
136 | |
137 startActivityWithTestUrl(BLANK_URL); | |
138 | |
139 // Fetch the routing token. | |
140 mRoutingToken = | |
141 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Ungues sableToken>() { | |
142 @Override | |
143 public UnguessableToken call() { | |
144 RenderFrameHostImpl host = | |
145 (RenderFrameHostImpl) getWebContents().getMainFr ame(); | |
146 org.chromium.base.UnguessableToken routingToken = | |
147 host.getAndroidOverlayRoutingToken(); | |
148 UnguessableToken mojoToken = new UnguessableToken(); | |
149 mojoToken.high = routingToken.getHighForSerialization(); | |
150 mojoToken.low = routingToken.getLowForSerialization(); | |
151 return mojoToken; | |
152 } | |
153 }); | |
154 | |
155 // Set up the overlay UI thread | |
156 mOverlayUiThread = new HandlerThread("TestOverlayUI"); | |
157 mOverlayUiThread.start(); | |
158 mOverlayUiHandler = new Handler(mOverlayUiThread.getLooper()); | |
159 | |
160 // Just delegate to |mClient| when an overlay is released. | |
161 mReleasedRunnable = new Runnable() { | |
162 @Override | |
163 public void run() { | |
164 mClient.notifyReleased(); | |
165 } | |
166 }; | |
167 } | |
168 | |
169 // Create an overlay with the given parameters and return it. | |
170 DialogOverlayImpl createOverlay(final int x, final int y, final int width, f inal int height) { | |
171 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable<DialogO verlayImpl>() { | |
172 @Override | |
173 public DialogOverlayImpl call() { | |
174 AndroidOverlayConfig config = new AndroidOverlayConfig(); | |
175 config.routingToken = mRoutingToken; | |
176 config.rect = new org.chromium.gfx.mojom.Rect(); | |
177 config.rect.x = x; | |
178 config.rect.y = y; | |
179 config.rect.width = width; | |
180 config.rect.height = height; | |
181 config.secure = mSecure; | |
182 HandlerThread overlayUiThread = new HandlerThread("TestOverlayUI "); | |
183 overlayUiThread.start(); | |
184 DialogOverlayImpl impl = new DialogOverlayImpl( | |
185 mClient, config, mOverlayUiHandler, mReleasedRunnable); | |
186 | |
187 return impl; | |
188 } | |
189 }); | |
190 } | |
191 | |
192 @SmallTest | |
193 @Feature({"AndroidOverlay"}) | |
194 public void testCreateDestroyOverlay() { | |
195 final DialogOverlayImpl overlay = createOverlay(0, 0, 10, 10); | |
196 | |
197 // We should get a new overlay with a valid surface key. | |
198 Client.Event event = mClient.nextEvent(); | |
199 Assert.assertEquals(Client.SURFACE_READY, event.which); | |
200 Assert.assertTrue(event.surfaceKey > 0); | |
201 | |
202 // Close the overlay, and make sure that the provider is notified. | |
203 // Note that we should not get a 'destroyed' message when we close it. | |
204 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Void>() { | |
boliu
2017/04/26 17:40:11
for void, there's runOnUiThreadBlocking which take
liberato (no reviews please)
2017/04/26 18:26:28
Done.
| |
205 @Override | |
206 public Void call() { | |
207 overlay.close(); | |
208 return null; | |
209 } | |
210 }); | |
211 Assert.assertEquals(Client.RELEASED, mClient.nextEvent().which); | |
212 } | |
213 | |
214 @SmallTest | |
215 @Feature({"AndroidOverlay"}) | |
216 public void testCreateOverlayFailsIfUnknownRoutingToken() { | |
217 // Try to create an overlay with a bad routing token. | |
218 mRoutingToken.high++; | |
219 DialogOverlayImpl overlay = createOverlay(0, 0, 10, 10); | |
220 Assert.assertNotNull(overlay); | |
221 | |
222 // We should be notified that the overlay is destroyed. | |
223 Client.Event event = mClient.nextEvent(); | |
224 Assert.assertEquals(Client.DESTROYED, event.which); | |
225 } | |
226 | |
227 @SmallTest | |
228 @Feature({"AndroidOverlay"}) | |
229 public void testScheduleLayoutDoesntCrash() { | |
230 // Make sure that we don't get any messages due to scheduleLayout, and w e don't crash. | |
231 final DialogOverlayImpl overlay = createOverlay(0, 0, 10, 10); | |
232 | |
233 // Wait for the surface. | |
234 Assert.assertEquals(Client.SURFACE_READY, mClient.nextEvent().which); | |
235 final org.chromium.gfx.mojom.Rect rect = new org.chromium.gfx.mojom.Rect (); | |
236 rect.x = 100; | |
237 rect.y = 200; | |
238 rect.width = 100; | |
239 rect.height = 100; | |
240 ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Void>() { | |
241 @Override | |
242 public Void call() { | |
243 overlay.scheduleLayout(rect); | |
244 return null; | |
245 } | |
246 }); | |
247 | |
248 // No additional messages should have arrived. | |
249 Assert.assertTrue(mClient.isEmpty()); | |
250 } | |
251 | |
252 @SmallTest | |
253 @Feature({"AndroidOverlay"}) | |
254 public void testCreateSecureSurface() { | |
255 // Test that creating a secure overlay creates an overlay. We can't rea lly tell if it's | |
256 // secure or not, until we can do a screen shot test. | |
257 mSecure = true; | |
258 final DialogOverlayImpl overlay = createOverlay(0, 0, 10, 10); | |
259 Assert.assertNotNull(overlay); | |
260 | |
261 // We should get a new overlay with a valid surface key. | |
262 Client.Event event = mClient.nextEvent(); | |
263 Assert.assertEquals(Client.SURFACE_READY, event.which); | |
264 Assert.assertTrue(event.surfaceKey > 0); | |
265 } | |
266 } | |
OLD | NEW |