1// Copyright 2014 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 5package org.chromium.content.browser; 6 7import android.test.suitebuilder.annotation.SmallTest; 8import android.text.TextUtils; 9import android.util.Pair; 10 11import org.chromium.base.test.util.UrlUtils; 12import org.chromium.content.browser.test.util.TestCallbackHelperContainer; 13import org.chromium.content_public.browser.LoadUrlParams; 14import org.chromium.content_public.browser.NavigationTransitionDelegate; 15import org.chromium.content_shell_apk.ContentShellActivity; 16import org.chromium.content_shell_apk.ContentShellTestBase; 17import org.chromium.net.test.util.TestWebServer; 18 19import java.util.ArrayList; 20import java.util.List; 21import java.util.concurrent.TimeUnit; 22 23/** 24 * Test suite for navigation transition listeners. 25 */ 26public class TransitionTest extends ContentShellTestBase { 27 28 private static final String URL_1 = UrlUtils.encodeHtmlDataUri("<html>1</html>"); 29 private static final String URL_2 = "/2.html"; 30 private static final String URL_2_DATA = "<html>2</html>"; 31 private static final String URL_3 = "/3.html"; 32 private static final String URL_3_DATA = "<html>3</html>"; 33 34 static class TestNavigationTransitionDelegate implements NavigationTransitionDelegate { 35 private boolean mDidCallDefer = false; 36 private boolean mDidCallWillHandleDefer = false; 37 private boolean mDidCallAddStylesheet = false; 38 private boolean mHandleDefer = false; 39 private ArrayList<String> mTransitionStylesheets; 40 private ContentViewCore mContentViewCore; 41 private String mTransitionEnteringColor; 42 43 TestNavigationTransitionDelegate(ContentViewCore contentViewCore, boolean handleDefer) { 44 mContentViewCore = contentViewCore; 45 mHandleDefer = handleDefer; 46 mTransitionStylesheets = new ArrayList<String>(); 47 } 48 49 @Override 50 public void didDeferAfterResponseStarted(String markup, String cssSelector, 51 String enteringColor) { 52 mDidCallDefer = true; 53 mContentViewCore.resumeResponseDeferredAtStart(); 54 mTransitionEnteringColor = enteringColor; 55 } 56 57 @Override 58 public boolean willHandleDeferAfterResponseStarted() { 59 return mHandleDefer; 60 } 61 62 @Override 63 public void addEnteringStylesheetToTransition(String stylesheet) { 64 mDidCallAddStylesheet = true; 65 mTransitionStylesheets.add(stylesheet); 66 } 67 68 @Override 69 public void didStartNavigationTransitionForFrame(long frameId) { 70 } 71 72 public boolean getDidCallDefer() { 73 return mDidCallDefer; 74 } 75 76 public boolean getDidCallWillHandlerDefer() { 77 return mDidCallWillHandleDefer; 78 } 79 80 public boolean getDidCallAddStylesheet() { 81 return mDidCallAddStylesheet; 82 } 83 84 public ArrayList<String> getTransitionStylesheets() { 85 return mTransitionStylesheets; 86 } 87 88 public String getTransitionEnteringColor() { 89 return mTransitionEnteringColor; 90 } 91 }; 92 93 private static List<Pair<String, String>> createHeadersList( 94 String[] namesAndValues) { 95 List<Pair<String, String>> result = 96 new ArrayList<Pair<String, String>>(); 97 for (int i = 0; i < namesAndValues.length; i += 2) 98 result.add(Pair.create(namesAndValues[i], namesAndValues[i + 1])); 99 return result; 100 } 101 102 /** 103 * Tests that the listener recieves DidDeferAfterResponseStarted if we specify that 104 * the transition is handled. 105 */ 106 @SmallTest 107 public void testDidDeferAfterResponseStartedCalled() throws Throwable { 108 ContentShellActivity activity = launchContentShellWithUrl(URL_1); 109 waitForActiveShellToBeDoneLoading(); 110 ContentViewCore contentViewCore = activity.getActiveContentViewCore(); 111 TestCallbackHelperContainer testCallbackHelperContainer = 112 new TestCallbackHelperContainer(contentViewCore); 113 114 contentViewCore.getWebContents().setHasPendingNavigationTransitionForTesting(); 115 TestNavigationTransitionDelegate delegate = new TestNavigationTransitionDelegate( 116 contentViewCore, 117 true); 118 contentViewCore.getWebContents().setNavigationTransitionDelegate(delegate); 119 120 loadUrl(contentViewCore, testCallbackHelperContainer, new LoadUrlParams(URL_1)); 121 122 assertTrue("didDeferAfterResponseStarted called.", delegate.getDidCallDefer()); 123 } 124 125 /** 126 * Tests that the listener does not receive DidDeferAfterResponseStarted if we specify that 127 * the transition is handled. 128 */ 129 @SmallTest 130 public void testDidDeferAfterResponseStartedNotCalled() throws Throwable { 131 ContentShellActivity activity = launchContentShellWithUrl(URL_1); 132 waitForActiveShellToBeDoneLoading(); 133 ContentViewCore contentViewCore = activity.getActiveContentViewCore(); 134 TestCallbackHelperContainer testCallbackHelperContainer = 135 new TestCallbackHelperContainer(contentViewCore); 136 137 contentViewCore.getWebContents().setHasPendingNavigationTransitionForTesting(); 138 TestNavigationTransitionDelegate delegate = new TestNavigationTransitionDelegate( 139 contentViewCore, 140 false); 141 contentViewCore.getWebContents().setNavigationTransitionDelegate(delegate); 142 143 loadUrl(contentViewCore, testCallbackHelperContainer, new LoadUrlParams(URL_1)); 144 145 assertFalse("didDeferAfterResponseStarted called.", delegate.getDidCallDefer()); 146 } 147 148 /** 149 * Tests that the resource handler doesn't query the listener if no transition is pending. 150 */ 151 @SmallTest 152 public void testWillHandleDeferAfterResponseStartedNotCalled() throws Throwable { 153 ContentShellActivity activity = launchContentShellWithUrl(URL_1); 154 waitForActiveShellToBeDoneLoading(); 155 ContentViewCore contentViewCore = activity.getActiveContentViewCore(); 156 TestCallbackHelperContainer testCallbackHelperContainer = 157 new TestCallbackHelperContainer(contentViewCore); 158 159 TestNavigationTransitionDelegate delegate = new TestNavigationTransitionDelegate( 160 contentViewCore, 161 false); 162 contentViewCore.getWebContents().setNavigationTransitionDelegate(delegate); 163 164 loadUrl(contentViewCore, testCallbackHelperContainer, new LoadUrlParams(URL_1)); 165 166 assertFalse("didDeferAfterResponseStarted called.", delegate.getDidCallDefer()); 167 assertFalse("willHandleDeferAfterResponseStarted called.", 168 delegate.getDidCallWillHandlerDefer()); 169 } 170 171 /** 172 * Tests that the listener receives addStylesheetToTransition if we specify 173 * that there are entering transition stylesheet. 174 */ 175 @SmallTest 176 public void testAddStylesheetToTransitionCalled() throws Throwable { 177 TestWebServer webServer = null; 178 try { 179 webServer = new TestWebServer(false); 180 181 final String url2 = webServer.setResponse(URL_2, URL_2_DATA, null); 182 ContentShellActivity activity = launchContentShellWithUrl(url2); 183 waitForActiveShellToBeDoneLoading(); 184 ContentViewCore contentViewCore = activity.getActiveContentViewCore(); 185 TestCallbackHelperContainer testCallbackHelperContainer = 186 new TestCallbackHelperContainer(contentViewCore); 187 contentViewCore.getWebContents().setHasPendingNavigationTransitionForTesting(); 188 TestNavigationTransitionDelegate delegate = 189 new TestNavigationTransitionDelegate(contentViewCore, true); 190 contentViewCore.getWebContents().setNavigationTransitionDelegate(delegate); 191 192 int currentCallCount = testCallbackHelperContainer 193 .getOnPageFinishedHelper().getCallCount(); 194 String[] headers = { 195 "link", 196 "<transition0.css>;rel=transition-entering-stylesheet;scope=*", 197 "link", 198 "<transition1.css>;rel=transition-entering-stylesheet;scope=*", 199 "link", 200 "<transition2.css>;rel=transition-entering-stylesheet;scope=*" 201 }; 202 final String url3 = webServer.setResponse(URL_3, 203 URL_3_DATA, 204 createHeadersList(headers)); 205 LoadUrlParams url3_params = new LoadUrlParams(url3); 206 loadUrl(contentViewCore, testCallbackHelperContainer, url3_params); 207 testCallbackHelperContainer.getOnPageFinishedHelper().waitForCallback( 208 currentCallCount, 209 1, 210 10000, 211 TimeUnit.MILLISECONDS); 212 213 assertTrue("addStylesheetToTransition called.", 214 delegate.getDidCallAddStylesheet()); 215 assertTrue("Three stylesheets are added", 216 delegate.getTransitionStylesheets().size() == 3); 217 } finally { 218 if (webServer != null) 219 webServer.shutdown(); 220 } 221 } 222 223 /** 224 * Tests that the listener receives addStylesheetToTransition if we specify 225 * that there are no entering transition stylesheet. 226 */ 227 @SmallTest 228 public void testAddStylesheetToTransitionNotCalled() throws Throwable { 229 TestWebServer webServer = null; 230 try { 231 webServer = new TestWebServer(false); 232 233 final String url2 = webServer.setResponse(URL_2, URL_2_DATA, null); 234 ContentShellActivity activity = launchContentShellWithUrl(url2); 235 waitForActiveShellToBeDoneLoading(); 236 ContentViewCore contentViewCore = activity.getActiveContentViewCore(); 237 TestCallbackHelperContainer testCallbackHelperContainer = 238 new TestCallbackHelperContainer(contentViewCore); 239 contentViewCore.getWebContents().setHasPendingNavigationTransitionForTesting(); 240 TestNavigationTransitionDelegate delegate = 241 new TestNavigationTransitionDelegate(contentViewCore, true); 242 contentViewCore.getWebContents().setNavigationTransitionDelegate(delegate); 243 244 int currentCallCount = testCallbackHelperContainer 245 .getOnPageFinishedHelper().getCallCount(); 246 final String url3 = webServer.setResponse(URL_3, URL_3_DATA, null); 247 LoadUrlParams url3_params = new LoadUrlParams(url3); 248 loadUrl(contentViewCore, testCallbackHelperContainer, url3_params); 249 testCallbackHelperContainer.getOnPageFinishedHelper().waitForCallback( 250 currentCallCount, 251 1, 252 10000, 253 TimeUnit.MILLISECONDS); 254 255 assertFalse("addStylesheetToTransition is not called.", 256 delegate.getDidCallAddStylesheet()); 257 assertTrue("No stylesheets are added", 258 delegate.getTransitionStylesheets().size() == 0); 259 } finally { 260 if (webServer != null) 261 webServer.shutdown(); 262 } 263 } 264 265 /** 266 * Tests that the listener receives the entering color if it's specified in the 267 * response headers. 268 */ 269 @SmallTest 270 public void testParseTransitionEnteringColor() throws Throwable { 271 TestWebServer webServer = null; 272 try { 273 webServer = new TestWebServer(false); 274 275 final String url2 = webServer.setResponse(URL_2, URL_2_DATA, null); 276 ContentShellActivity activity = launchContentShellWithUrl(url2); 277 waitForActiveShellToBeDoneLoading(); 278 ContentViewCore contentViewCore = activity.getActiveContentViewCore(); 279 TestCallbackHelperContainer testCallbackHelperContainer = 280 new TestCallbackHelperContainer(contentViewCore); 281 contentViewCore.getWebContents().setHasPendingNavigationTransitionForTesting(); 282 TestNavigationTransitionDelegate delegate = 283 new TestNavigationTransitionDelegate(contentViewCore, true); 284 contentViewCore.getWebContents().setNavigationTransitionDelegate(delegate); 285 286 String transitionEnteringColor = "#00FF00"; 287 288 int currentCallCount = testCallbackHelperContainer 289 .getOnPageFinishedHelper().getCallCount(); 290 String[] headers = { 291 "X-Transition-Entering-Color", 292 transitionEnteringColor, 293 }; 294 final String url3 = webServer.setResponse(URL_3, 295 URL_3_DATA, 296 createHeadersList(headers)); 297 LoadUrlParams url3Params = new LoadUrlParams(url3); 298 loadUrl(contentViewCore, testCallbackHelperContainer, url3Params); 299 testCallbackHelperContainer.getOnPageFinishedHelper().waitForCallback( 300 currentCallCount, 301 1, 302 10000, 303 TimeUnit.MILLISECONDS); 304 305 assertTrue("X-Transition-Entering-Color parsed correctly.", 306 TextUtils.equals( 307 delegate.getTransitionEnteringColor(), 308 transitionEnteringColor)); 309 } finally { 310 if (webServer != null) webServer.shutdown(); 311 } 312 } 313} 314