| 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 |