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 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.testshell; 6 7 import android.content.ComponentName; 8 import android.content.Context; 9 import android.content.Intent; 10 import android.net.Uri; 11 import android.test.ActivityInstrumentationTestCase2; 12 import android.text.TextUtils; 13 import android.util.Log; 14 15 import static org.chromium.base.test.util.ScalableTimeout.ScaleTimeout; 16 17 import org.chromium.base.CommandLine; 18 import org.chromium.base.ThreadUtils; 19 import org.chromium.chrome.test.util.ApplicationData; 20 import org.chromium.content.browser.BrowserStartupController; 21 import org.chromium.content.browser.test.util.Criteria; 22 import org.chromium.content.browser.test.util.CriteriaHelper; 23 import org.chromium.content.common.ProcessInitException; 24 25 import java.util.concurrent.atomic.AtomicBoolean; 26 27 /** 28 * Base test class for all ChromiumTestShell based tests. 29 */ 30 public class ChromiumTestShellTestBase extends 31 ActivityInstrumentationTestCase2<ChromiumTestShellActivity> { 32 /** The maximum time the waitForActiveShellToBeDoneLoading method will wait. */ 33 private static final long WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT = ScaleTimeout(10000); 34 private static final String TAG = "ChromiumTestShellTestBase"; 35 ChromiumTestShellTestBase()36 public ChromiumTestShellTestBase() { 37 super(ChromiumTestShellActivity.class); 38 } 39 startChromeBrowserProcessSync(final Context targetContext)40 protected static void startChromeBrowserProcessSync(final Context targetContext) { 41 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 42 @Override 43 public void run() { 44 CommandLine.initFromFile("/data/local/tmp/chromium-testshell-command-line"); 45 try { 46 BrowserStartupController.get(targetContext).startBrowserProcessesSync( 47 BrowserStartupController.MAX_RENDERERS_LIMIT); 48 } catch (ProcessInitException e) { 49 Log.e(TAG, "Unable to load native library.", e); 50 fail("Unable to load native library"); 51 } 52 } 53 }); 54 } 55 56 /** 57 * Starts the ChromiumTestShell activity and loads the given URL. 58 */ launchChromiumTestShellWithUrl(String url)59 protected ChromiumTestShellActivity launchChromiumTestShellWithUrl(String url) { 60 Intent intent = new Intent(Intent.ACTION_MAIN); 61 intent.addCategory(Intent.CATEGORY_LAUNCHER); 62 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 63 if (url != null) intent.setData(Uri.parse(url)); 64 intent.setComponent(new ComponentName(getInstrumentation().getTargetContext(), 65 ChromiumTestShellActivity.class)); 66 setActivityIntent(intent); 67 return getActivity(); 68 } 69 70 /** 71 * Starts the ChromiumTestShell activity and loads a blank page. 72 */ launchChromiumTestShellWithBlankPage()73 protected ChromiumTestShellActivity launchChromiumTestShellWithBlankPage() { 74 return launchChromiumTestShellWithUrl("about:blank"); 75 } 76 77 /** 78 * Waits for the Active shell to finish loading. This times out after 79 * WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT milliseconds and it shouldn't be used for long 80 * loading pages. Instead it should be used more for test initialization. The proper way 81 * to wait is to use a TestCallbackHelperContainer after the initial load is completed. 82 * @return Whether or not the Shell was actually finished loading. 83 * @throws InterruptedException 84 */ waitForActiveShellToBeDoneLoading()85 protected boolean waitForActiveShellToBeDoneLoading() throws InterruptedException { 86 final ChromiumTestShellActivity activity = getActivity(); 87 88 // Wait for the Content Shell to be initialized. 89 return CriteriaHelper.pollForCriteria(new Criteria() { 90 @Override 91 public boolean isSatisfied() { 92 try { 93 final AtomicBoolean isLoaded = new AtomicBoolean(false); 94 runTestOnUiThread(new Runnable() { 95 @Override 96 public void run() { 97 TestShellTab tab = activity.getActiveTab(); 98 if (tab != null) { 99 isLoaded.set(!tab.isLoading() 100 && !TextUtils.isEmpty(tab.getContentView().getUrl())); 101 } else { 102 isLoaded.set(false); 103 } 104 } 105 }); 106 107 return isLoaded.get(); 108 } catch (Throwable e) { 109 return false; 110 } 111 } 112 }, WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL); 113 } 114 115 /** 116 * Clear all files and folders in the Chromium testshell's application directory except 'lib'. 117 * 118 * The 'cache' directory is recreated as an empty directory. 119 * 120 * @return Whether clearing the application data was successful. 121 */ 122 protected boolean clearAppData() throws InterruptedException { 123 return ApplicationData.clearAppData(getInstrumentation().getTargetContext()); 124 } 125 126 /** 127 * Navigates the currently active tab to a sanitized version of {@code url}. 128 * @param url The potentially unsanitized URL to navigate to. 129 */ 130 public void loadUrlWithSanitization(final String url) throws InterruptedException { 131 getInstrumentation().runOnMainSync(new Runnable() { 132 @Override 133 public void run() { 134 getActivity().getActiveTab().loadUrlWithSanitization(url); 135 } 136 }); 137 waitForActiveShellToBeDoneLoading(); 138 } 139 140 // TODO(aelias): This method needs to be removed once http://crbug.com/179511 is fixed. 141 // Meanwhile, we have to wait if the page has the <meta viewport> tag. 142 /** 143 * Waits till the ContentViewCore receives the expected page scale factor 144 * from the compositor and asserts that this happens. 145 */ 146 protected void assertWaitForPageScaleFactorMatch(final float expectedScale) 147 throws InterruptedException { 148 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 149 @Override 150 public boolean isSatisfied() { 151 return getActivity().getActiveTab().getContentViewCore().getScale() == 152 expectedScale; 153 } 154 })); 155 } 156 } 157