OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content_shell_apk; | 5 package org.chromium.content_shell_apk; |
6 | 6 |
7 import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; | 7 import android.app.Instrumentation; |
| 8 import android.content.Intent; |
8 | 9 |
9 import android.annotation.TargetApi; | |
10 import android.content.ComponentName; | |
11 import android.content.Context; | |
12 import android.content.Intent; | |
13 import android.net.Uri; | |
14 import android.os.Build; | |
15 import android.os.PowerManager; | |
16 import android.text.TextUtils; | |
17 import android.view.ViewGroup; | |
18 | |
19 import org.chromium.base.ThreadUtils; | |
20 import org.chromium.base.test.BaseActivityInstrumentationTestCase; | 10 import org.chromium.base.test.BaseActivityInstrumentationTestCase; |
21 import org.chromium.base.test.util.CallbackHelper; | 11 import org.chromium.base.test.util.CallbackHelper; |
22 import org.chromium.base.test.util.CommandLineFlags; | 12 import org.chromium.base.test.util.CommandLineFlags; |
23 import org.chromium.base.test.util.UrlUtils; | |
24 import org.chromium.content.browser.ContentView; | 13 import org.chromium.content.browser.ContentView; |
25 import org.chromium.content.browser.ContentViewCore; | 14 import org.chromium.content.browser.ContentViewCore; |
26 import org.chromium.content.browser.test.util.Criteria; | |
27 import org.chromium.content.browser.test.util.CriteriaHelper; | |
28 import org.chromium.content.browser.test.util.TestCallbackHelperContainer; | 15 import org.chromium.content.browser.test.util.TestCallbackHelperContainer; |
29 import org.chromium.content.common.ContentSwitches; | 16 import org.chromium.content.common.ContentSwitches; |
30 import org.chromium.content_public.browser.LoadUrlParams; | 17 import org.chromium.content_public.browser.LoadUrlParams; |
31 import org.chromium.content_public.browser.NavigationController; | 18 import org.chromium.content_public.browser.NavigationController; |
32 import org.chromium.content_public.browser.WebContents; | 19 import org.chromium.content_public.browser.WebContents; |
33 import org.chromium.content_shell.Shell; | 20 import org.chromium.content_shell.Shell; |
| 21 import org.chromium.content_shell_apk.ContentShellActivityTestRule.RerunWithUpda
tedContainerView; |
| 22 import org.chromium.content_shell_apk.ContentShellTestCommon.TestCommonCallback; |
34 | 23 |
35 import java.lang.annotation.ElementType; | |
36 import java.lang.annotation.Retention; | |
37 import java.lang.annotation.RetentionPolicy; | |
38 import java.lang.annotation.Target; | |
39 import java.lang.reflect.AnnotatedElement; | 24 import java.lang.reflect.AnnotatedElement; |
40 import java.util.concurrent.Callable; | |
41 import java.util.concurrent.ExecutionException; | 25 import java.util.concurrent.ExecutionException; |
42 import java.util.concurrent.TimeUnit; | |
43 | 26 |
44 /** | 27 /** |
45 * Base test class for all ContentShell based tests. | 28 * Base test class for all ContentShell based tests. |
46 */ | 29 */ |
47 @CommandLineFlags.Add(ContentSwitches.ENABLE_TEST_INTENTS) | 30 @CommandLineFlags.Add(ContentSwitches.ENABLE_TEST_INTENTS) |
48 public class ContentShellTestBase | 31 public class ContentShellTestBase extends BaseActivityInstrumentationTestCase<Co
ntentShellActivity> |
49 extends BaseActivityInstrumentationTestCase<ContentShellActivity> { | 32 implements TestCommonCallback<ContentShellActivity> { |
50 /** The maximum time the waitForActiveShellToBeDoneLoading method will wait.
*/ | 33 protected static final long WAIT_PAGE_LOADING_TIMEOUT_SECONDS = |
51 private static final long WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT = scaleTimeo
ut(10000); | 34 ContentShellTestCommon.WAIT_PAGE_LOADING_TIMEOUT_SECONDS; |
52 | 35 |
53 protected static final long WAIT_PAGE_LOADING_TIMEOUT_SECONDS = scaleTimeout
(15); | 36 private ContentShellTestCommon mDelegate; |
54 | 37 |
55 public ContentShellTestBase() { | 38 public ContentShellTestBase() { |
56 super(ContentShellActivity.class); | 39 super(ContentShellActivity.class); |
| 40 mDelegate = new ContentShellTestCommon(this); |
| 41 } |
| 42 |
| 43 @SuppressWarnings("deprecation") |
| 44 @Override |
| 45 public ContentShellActivity getActivityForTestCommon() { |
| 46 return getActivity(); |
57 } | 47 } |
58 | 48 |
59 @Override | 49 @Override |
| 50 @SuppressWarnings("deprecation") |
| 51 public Instrumentation getInstrumentationForTestCommon() { |
| 52 return getInstrumentation(); |
| 53 } |
| 54 |
| 55 @SuppressWarnings("deprecation") |
| 56 @Override |
| 57 public ContentShellActivity launchActivityWithIntentForTestCommon(Intent int
ent) { |
| 58 setActivityIntent(intent); |
| 59 return getActivity(); |
| 60 } |
| 61 |
| 62 @SuppressWarnings("deprecation") |
| 63 @Override |
| 64 public void runOnUiThreadForTestCommon(Runnable runnable) throws Throwable { |
| 65 runTestOnUiThread(runnable); |
| 66 } |
| 67 |
| 68 @Override |
| 69 @SuppressWarnings("deprecation") |
60 protected void setUp() throws Exception { | 70 protected void setUp() throws Exception { |
61 super.setUp(); | 71 super.setUp(); |
62 assertScreenIsOn(); | 72 mDelegate.assertScreenIsOn(); |
63 } | |
64 | |
65 @TargetApi(Build.VERSION_CODES.KITKAT_WATCH) | |
66 @SuppressWarnings("deprecation") | |
67 private void assertScreenIsOn() { | |
68 PowerManager pm = (PowerManager) getInstrumentation().getContext().getSy
stemService( | |
69 Context.POWER_SERVICE); | |
70 | |
71 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { | |
72 assertTrue("Many tests will fail if the screen is not on.", pm.isInt
eractive()); | |
73 } else { | |
74 assertTrue("Many tests will fail if the screen is not on.", pm.isScr
eenOn()); | |
75 } | |
76 } | 73 } |
77 | 74 |
78 /** | 75 /** |
79 * Starts the ContentShell activity and loads the given URL. | 76 * Starts the ContentShell activity and loads the given URL. |
80 * The URL can be null, in which case will default to ContentShellActivity.D
EFAULT_SHELL_URL. | 77 * The URL can be null, in which case will default to ContentShellActivity.D
EFAULT_SHELL_URL. |
81 */ | 78 */ |
82 protected ContentShellActivity launchContentShellWithUrl(String url) { | 79 public ContentShellActivity launchContentShellWithUrl(String url) { |
83 Intent intent = new Intent(Intent.ACTION_MAIN); | 80 return mDelegate.launchContentShellWithUrl(url); |
84 intent.addCategory(Intent.CATEGORY_LAUNCHER); | |
85 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); | |
86 if (url != null) intent.setData(Uri.parse(url)); | |
87 intent.setComponent(new ComponentName(getInstrumentation().getTargetCont
ext(), | |
88 ContentShellActivity.class)); | |
89 setActivityIntent(intent); | |
90 return getActivity(); | |
91 } | 81 } |
92 | 82 |
93 // TODO(cjhopman): These functions are inconsistent with launchContentShell*
**. Should be | 83 // TODO(cjhopman): These functions are inconsistent with launchContentShell*
**. Should be |
94 // startContentShell*** and should use the url exactly without the getTestFi
leUrl call. Possibly | 84 // startContentShell*** and should use the url exactly without the getTestFi
leUrl call. Possibly |
95 // these two ways of starting the activity (launch* and start*) should be me
rged into one. | 85 // these two ways of starting the activity (launch* and start*) should be me
rged into one. |
96 /** | 86 /** |
97 * Starts the content shell activity with the provided test url. | 87 * Starts the content shell activity with the provided test url. |
98 * The url is synchronously loaded. | 88 * The url is synchronously loaded. |
99 * @param url Test url to load. | 89 * @param url Test url to load. |
100 */ | 90 */ |
101 protected void startActivityWithTestUrl(String url) { | 91 public void startActivityWithTestUrl(String url) { |
102 launchContentShellWithUrl(UrlUtils.getIsolatedTestFileUrl(url)); | 92 mDelegate.launchContentShellWithUrlSync(url); |
103 assertNotNull(getActivity()); | |
104 waitForActiveShellToBeDoneLoading(); | |
105 assertEquals(UrlUtils.getIsolatedTestFileUrl(url), | |
106 getContentViewCore().getWebContents().getUrl()); | |
107 } | 93 } |
108 | 94 |
109 /** | 95 /** |
110 * Returns the current ContentViewCore or null if there is no ContentView. | 96 * Returns the current ContentViewCore or null if there is no ContentView. |
111 */ | 97 */ |
112 protected ContentViewCore getContentViewCore() { | 98 public ContentViewCore getContentViewCore() { |
113 return getActivity().getActiveShell().getContentViewCore(); | 99 return mDelegate.getContentViewCore(); |
114 } | 100 } |
115 | 101 |
116 /** | 102 /** |
117 * Returns the WebContents of this Shell. | 103 * Returns the WebContents of this Shell. |
118 */ | 104 */ |
119 protected WebContents getWebContents() { | 105 public WebContents getWebContents() { |
120 return getActivity().getActiveShell().getWebContents(); | 106 return mDelegate.getWebContents(); |
121 } | 107 } |
122 | 108 |
123 /** | 109 /** |
124 * Waits for the Active shell to finish loading. This times out after | 110 * Waits for the Active shell to finish loading. This times out after |
125 * WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT milliseconds and it shouldn't be us
ed for long | 111 * WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT milliseconds and it shouldn't be us
ed for long |
126 * loading pages. Instead it should be used more for test initialization. Th
e proper way | 112 * loading pages. Instead it should be used more for test initialization. Th
e proper way |
127 * to wait is to use a TestCallbackHelperContainer after the initial load is
completed. | 113 * to wait is to use a TestCallbackHelperContainer after the initial load is
completed. |
128 */ | 114 */ |
129 protected void waitForActiveShellToBeDoneLoading() { | 115 public void waitForActiveShellToBeDoneLoading() { |
130 final ContentShellActivity activity = getActivity(); | 116 mDelegate.waitForActiveShellToBeDoneLoading(); |
131 | |
132 // Wait for the Content Shell to be initialized. | |
133 CriteriaHelper.pollUiThread(new Criteria() { | |
134 @Override | |
135 public boolean isSatisfied() { | |
136 Shell shell = activity.getActiveShell(); | |
137 // There are two cases here that need to be accounted for. | |
138 // The first is that we've just created a Shell and it isn't | |
139 // loading because it has no URL set yet. The second is that | |
140 // we've set a URL and it actually is loading. | |
141 if (shell == null) { | |
142 updateFailureReason("Shell is null."); | |
143 return false; | |
144 } | |
145 if (shell.isLoading()) { | |
146 updateFailureReason("Shell is still loading."); | |
147 return false; | |
148 } | |
149 if (TextUtils.isEmpty(shell.getContentViewCore().getWebContents(
).getUrl())) { | |
150 updateFailureReason("Shell's URL is empty or null."); | |
151 return false; | |
152 } | |
153 return true; | |
154 } | |
155 }, WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT, CriteriaHelper.DEFAULT_POLLING
_INTERVAL); | |
156 } | 117 } |
157 | 118 |
158 /** | 119 /** |
159 * Creates a new {@link Shell} and waits for it to finish loading. | 120 * Creates a new {@link Shell} and waits for it to finish loading. |
160 * @param url The URL to create the new {@link Shell} with. | 121 * @param url The URL to create the new {@link Shell} with. |
161 * @return A new instance of a {@link Shell}. | 122 * @return A new instance of a {@link Shell}. |
162 * @throws ExecutionException | 123 * @throws ExecutionException |
163 */ | 124 */ |
164 protected Shell loadNewShell(final String url) throws ExecutionException { | 125 public Shell loadNewShell(String url) throws ExecutionException { |
165 Shell shell = ThreadUtils.runOnUiThreadBlocking(new Callable<Shell>() { | 126 return mDelegate.loadNewShell(url); |
166 @Override | 127 } |
167 public Shell call() { | |
168 getActivity().getShellManager().launchShell(url); | |
169 return getActivity().getActiveShell(); | |
170 } | |
171 }); | |
172 | 128 |
173 assertNotNull("Unable to create shell.", shell); | |
174 assertEquals("Active shell unexpected.", shell, getActivity().getActiveS
hell()); | |
175 | |
176 waitForActiveShellToBeDoneLoading(); | |
177 | |
178 return shell; | |
179 } | |
180 /** | 129 /** |
181 * Loads a URL in the specified content view. | 130 * Loads a URL in the specified content view. |
182 * | 131 * |
183 * @param navigationController The navigation controller to load the URL in. | 132 * @param navigationController The navigation controller to load the URL in. |
184 * @param callbackHelperContainer The callback helper container used to moni
tor progress. | 133 * @param callbackHelperContainer The callback helper container used to moni
tor progress. |
185 * @param params The URL params to use. | 134 * @param params The URL params to use. |
186 */ | 135 */ |
187 protected void loadUrl( | 136 public void loadUrl(NavigationController navigationController, |
188 final NavigationController navigationController, | 137 TestCallbackHelperContainer callbackHelperContainer, LoadUrlParams p
arams) |
189 TestCallbackHelperContainer callbackHelperContainer, | 138 throws Throwable { |
190 final LoadUrlParams params) throws Throwable { | 139 mDelegate.loadUrl(navigationController, callbackHelperContainer, params)
; |
191 handleBlockingCallbackAction( | |
192 callbackHelperContainer.getOnPageFinishedHelper(), | |
193 new Runnable() { | |
194 @Override | |
195 public void run() { | |
196 navigationController.loadUrl(params); | |
197 } | |
198 }); | |
199 } | 140 } |
200 | 141 |
201 /** | 142 /** |
202 * Handles performing an action on the UI thread that will return when the s
pecified callback | 143 * Handles performing an action on the UI thread that will return when the s
pecified callback |
203 * is incremented. | 144 * is incremented. |
204 * | 145 * |
205 * @param callbackHelper The callback helper that will be blocked on. | 146 * @param callbackHelper The callback helper that will be blocked on. |
206 * @param action The action to be performed on the UI thread. | 147 * @param action The action to be performed on the UI thread. |
207 */ | 148 */ |
208 protected void handleBlockingCallbackAction( | 149 public void handleBlockingCallbackAction(CallbackHelper callbackHelper, Runn
able action) |
209 CallbackHelper callbackHelper, Runnable action) throws Throwable { | 150 throws Throwable { |
210 int currentCallCount = callbackHelper.getCallCount(); | 151 mDelegate.handleBlockingCallbackAction(callbackHelper, action); |
211 runTestOnUiThread(action); | |
212 callbackHelper.waitForCallback( | |
213 currentCallCount, 1, WAIT_PAGE_LOADING_TIMEOUT_SECONDS, TimeUnit
.SECONDS); | |
214 } | 152 } |
215 | 153 |
216 // TODO(aelias): This method needs to be removed once http://crbug.com/17951
1 is fixed. | 154 // TODO(aelias): This method needs to be removed once http://crbug.com/17951
1 is fixed. |
217 // Meanwhile, we have to wait if the page has the <meta viewport> tag. | 155 // Meanwhile, we have to wait if the page has the <meta viewport> tag. |
218 /** | 156 /** |
219 * Waits till the ContentViewCore receives the expected page scale factor | 157 * Waits till the ContentViewCore receives the expected page scale factor |
220 * from the compositor and asserts that this happens. | 158 * from the compositor and asserts that this happens. |
221 */ | 159 */ |
222 protected void assertWaitForPageScaleFactorMatch(float expectedScale) { | 160 public void assertWaitForPageScaleFactorMatch(float expectedScale) { |
223 CriteriaHelper.pollInstrumentationThread( | 161 mDelegate.assertWaitForPageScaleFactorMatch(expectedScale); |
224 Criteria.equals(expectedScale, new Callable<Float>() { | |
225 @Override | |
226 public Float call() { | |
227 return getContentViewCore().getScale(); | |
228 } | |
229 })); | |
230 } | 162 } |
231 | 163 |
232 /** | 164 /** |
233 * Replaces the {@link ContentViewCore#mContainerView} with a newly created | 165 * Replaces the {@link ContentViewCore#mContainerView} with a newly created |
234 * {@link ContentView}. | 166 * {@link ContentView}. |
235 */ | 167 */ |
236 @SuppressWarnings("javadoc") | 168 @SuppressWarnings("javadoc") |
237 protected void replaceContainerView() throws Throwable { | 169 public void replaceContainerView() throws Throwable { |
238 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 170 mDelegate.replaceContainerView(); |
239 @Override | |
240 public void run() { | |
241 ContentView cv = ContentView.createContentView(getActivity(), ge
tContentViewCore()); | |
242 ((ViewGroup) getContentViewCore().getContainerView().getParent()
).addView(cv); | |
243 getContentViewCore().setContainerView(cv); | |
244 getContentViewCore().setContainerViewInternals(cv); | |
245 cv.requestFocus(); | |
246 } | |
247 }); | |
248 } | 171 } |
249 | 172 |
| 173 @SuppressWarnings("deprecation") |
250 @Override | 174 @Override |
251 protected void runTest() throws Throwable { | 175 protected void runTest() throws Throwable { |
252 super.runTest(); | 176 super.runTest(); |
253 try { | 177 try { |
254 AnnotatedElement method = getClass().getMethod(getName(), (Class[])
null); | 178 AnnotatedElement method = getClass().getMethod(getName(), (Class[])
null); |
255 if (method.isAnnotationPresent(RerunWithUpdatedContainerView.class))
{ | 179 if (method.isAnnotationPresent(RerunWithUpdatedContainerView.class))
{ |
256 replaceContainerView(); | 180 replaceContainerView(); |
257 super.runTest(); | 181 super.runTest(); |
258 } | 182 } |
259 } catch (Throwable e) { | 183 } catch (Throwable e) { |
260 throw new Throwable("@RerunWithUpdatedContainerView failed." | 184 throw new Throwable("@RerunWithUpdatedContainerView failed." |
261 + " See ContentShellTestBase#runTest.", e); | 185 + " See ContentShellTestBase#runTest.", e); |
262 } | 186 } |
263 } | 187 } |
264 | |
265 /** | |
266 * Annotation for tests that should be executed a second time after replacin
g | |
267 * the ContentViewCore's container view (see {@link #runTest()}). | |
268 * | |
269 * <p>Please note that {@link #setUp()} is only invoked once before both run
s, | |
270 * and that any state changes produced by the first run are visible to the s
econd run. | |
271 */ | |
272 @Target(ElementType.METHOD) | |
273 @Retention(RetentionPolicy.RUNTIME) | |
274 public @interface RerunWithUpdatedContainerView { | |
275 } | |
276 } | 188 } |
OLD | NEW |