OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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.browser; |
| 6 |
| 7 import android.app.Dialog; |
| 8 import android.support.v7.app.AlertDialog; |
| 9 import android.test.FlakyTest; |
| 10 import android.util.JsonReader; |
| 11 import android.widget.Button; |
| 12 |
| 13 import org.chromium.base.ThreadUtils; |
| 14 import org.chromium.base.test.util.DisabledTest; |
| 15 import org.chromium.chrome.browser.preferences.Preferences; |
| 16 import org.chromium.chrome.browser.preferences.PreferencesStaging; |
| 17 import org.chromium.chrome.browser.preferences.privacy.ClearBrowsingDataDialogFr
agment; |
| 18 import org.chromium.chrome.test.ChromeActivityTestCaseBase; |
| 19 import org.chromium.chrome.test.util.ActivityUtils; |
| 20 import org.chromium.chrome.test.util.TestHttpServerClient; |
| 21 import org.chromium.content.browser.ContentViewCore; |
| 22 import org.chromium.content.browser.test.util.CallbackHelper; |
| 23 import org.chromium.content.browser.test.util.Criteria; |
| 24 import org.chromium.content.browser.test.util.CriteriaHelper; |
| 25 import org.chromium.content.browser.test.util.JavaScriptUtils; |
| 26 import org.chromium.content.browser.test.util.TestTouchUtils; |
| 27 import org.chromium.content.browser.test.util.UiUtils; |
| 28 |
| 29 import java.io.IOException; |
| 30 import java.io.StringReader; |
| 31 import java.util.Vector; |
| 32 import java.util.concurrent.Callable; |
| 33 import java.util.concurrent.TimeoutException; |
| 34 |
| 35 public class HistoryUITest extends ChromeActivityTestCaseBase<ChromeActivity> { |
| 36 |
| 37 private static final String HISTORY_URL = "chrome://history-frame/"; |
| 38 |
| 39 public HistoryUITest() { |
| 40 super(ChromeActivity.class); |
| 41 } |
| 42 |
| 43 @Override |
| 44 public void startMainActivity() throws InterruptedException { |
| 45 startMainActivityOnBlankPage(); |
| 46 } |
| 47 |
| 48 private static class HistoryItem { |
| 49 public final String url; |
| 50 public final String title; |
| 51 |
| 52 HistoryItem(String url, String title) { |
| 53 this.url = url; |
| 54 this.title = title; |
| 55 } |
| 56 } |
| 57 |
| 58 private HistoryItem[] getHistoryContents() throws InterruptedException, Time
outException { |
| 59 getInstrumentation().waitForIdleSync(); |
| 60 String jsResults = runJavaScriptCodeInCurrentTab(new StringBuilder() |
| 61 .append("var rawResults = document.querySelectorAll('.title');\n
") |
| 62 .append("var results = [];\n") |
| 63 .append("for (i = 0; i < rawResults.length; ++i) {\n") |
| 64 .append(" results.push([rawResults[i].childNodes[0].href,\n") |
| 65 .append(" rawResults[i].childNodes[0].childNodes[0].textConte
nt]);\n") |
| 66 .append("}\n") |
| 67 .append("results").toString()); |
| 68 |
| 69 JsonReader jsonReader = new JsonReader(new StringReader(jsResults)); |
| 70 Vector<HistoryItem> results = new Vector<HistoryItem>(); |
| 71 try { |
| 72 jsonReader.beginArray(); |
| 73 while (jsonReader.hasNext()) { |
| 74 jsonReader.beginArray(); |
| 75 assertTrue(jsonReader.hasNext()); |
| 76 String url = jsonReader.nextString(); |
| 77 assertTrue(jsonReader.hasNext()); |
| 78 String title = jsonReader.nextString(); |
| 79 assertFalse(jsonReader.hasNext()); |
| 80 jsonReader.endArray(); |
| 81 results.add(new HistoryItem(url, title)); |
| 82 } |
| 83 jsonReader.endArray(); |
| 84 } catch (IOException ioe) { |
| 85 fail("Failed to evaluate JavaScript: " + jsResults + "\n" + ioe); |
| 86 } |
| 87 |
| 88 HistoryItem[] history = new HistoryItem[results.size()]; |
| 89 results.toArray(history); |
| 90 return history; |
| 91 } |
| 92 |
| 93 private void removeSelectedEntries(int[] indices) |
| 94 throws InterruptedException, TimeoutException { |
| 95 // Build the query with the indices of the history elements to delete. |
| 96 StringBuilder jsQuery = new StringBuilder("var toCheck = ["); |
| 97 for (int i = 0; i < indices.length; ++i) { |
| 98 if (i != 0) { |
| 99 jsQuery.append(", "); |
| 100 } |
| 101 jsQuery.append(Integer.toString(indices[i])); |
| 102 } |
| 103 |
| 104 // Remove the specified indices from history. |
| 105 runJavaScriptCodeInCurrentTab(jsQuery.append("];\n") |
| 106 .append("var checkboxes = Array.prototype.slice.call(") |
| 107 .append(" document.getElementsByTagName('input')).") |
| 108 .append(" filter(function(elem, index, array) {") |
| 109 .append(" return elem.type == 'checkbox'; })\n") |
| 110 .append("for (i = 0; i < checkboxes.length; ++i) {\n") |
| 111 .append(" checkboxes[i].checked = false;\n") |
| 112 .append("}\n") |
| 113 .append("for (i = 0; i < toCheck.length; ++i) {\n") |
| 114 .append(" checkboxes[toCheck[i]].checked = true;\n") |
| 115 .append("}\n") |
| 116 .append("window.confirm = function() { return true; };\n") |
| 117 .append("removeItems();\n").toString()); |
| 118 |
| 119 // The deleteComplete() JavaScript method is called when the operation f
inishes. |
| 120 // Since we cannot synchronously wait for a JS callback, keep checking u
ntil the delete |
| 121 // queue becomes empty. |
| 122 Boolean pending; |
| 123 do { |
| 124 pending = Boolean.parseBoolean(runJavaScriptCodeInCurrentTab("delete
Queue.length > 0")); |
| 125 } while (pending); |
| 126 } |
| 127 |
| 128 private int getHistoryLength(ContentViewCore cvc) |
| 129 throws InterruptedException, TimeoutException { |
| 130 getInstrumentation().waitForIdleSync(); |
| 131 |
| 132 String numResultsString = JavaScriptUtils.executeJavaScriptAndWaitForRes
ult( |
| 133 cvc.getWebContents(), "document.querySelectorAll('.entry').lengt
h"); |
| 134 int numResults = Integer.parseInt(numResultsString); |
| 135 return numResults; |
| 136 } |
| 137 |
| 138 /** |
| 139 * Wait for the UI to show the expected number of results. |
| 140 * @param expected The number of results that should be loaded. |
| 141 * @throws InterruptedException |
| 142 */ |
| 143 private void assertResultCountReaches(final ContentViewCore cvc, final int e
xpected) |
| 144 throws InterruptedException { |
| 145 assertTrue(CriteriaHelper.pollForCriteria( |
| 146 new Criteria() { |
| 147 @Override |
| 148 public boolean isSatisfied() { |
| 149 try { |
| 150 return expected == getHistoryLength(cvc); |
| 151 } catch (InterruptedException e) { |
| 152 e.printStackTrace(); |
| 153 return false; |
| 154 } catch (TimeoutException e) { |
| 155 e.printStackTrace(); |
| 156 return false; |
| 157 } |
| 158 } |
| 159 })); |
| 160 } |
| 161 |
| 162 /* |
| 163 * @MediumTest |
| 164 * @Feature({"History"}) |
| 165 * Bug 5969084 |
| 166 */ |
| 167 @DisabledTest |
| 168 public void testSearchHistory() throws InterruptedException, TimeoutExceptio
n { |
| 169 // Introduce some entries in the history page. |
| 170 loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/about.html
")); |
| 171 loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/get_title_
test.html")); |
| 172 loadUrl(HISTORY_URL); |
| 173 UiUtils.settleDownUI(getInstrumentation()); |
| 174 assertResultCountReaches(getActivity().getCurrentContentViewCore(), 2); |
| 175 |
| 176 // Search for one of them. |
| 177 Tab tab = getActivity().getActivityTab(); |
| 178 final CallbackHelper loadCallback = new CallbackHelper(); |
| 179 TabObserver observer = new EmptyTabObserver() { |
| 180 @Override |
| 181 public void onLoadStopped(Tab tab) { |
| 182 if (tab.getUrl().startsWith(HISTORY_URL)) { |
| 183 loadCallback.notifyCalled(); |
| 184 } |
| 185 } |
| 186 }; |
| 187 tab.addObserver(observer); |
| 188 runJavaScriptCodeInCurrentTab("historyView.setSearch('about')"); |
| 189 loadCallback.waitForCallback(0); |
| 190 assertResultCountReaches(getActivity().getCurrentContentViewCore(), 1); |
| 191 |
| 192 // Delete the search term. |
| 193 runJavaScriptCodeInCurrentTab("historyView.setSearch('')"); |
| 194 loadCallback.waitForCallback(1); |
| 195 assertResultCountReaches(getActivity().getCurrentContentViewCore(), 2); |
| 196 tab.removeObserver(observer); |
| 197 } |
| 198 |
| 199 /* |
| 200 * @LargeTest |
| 201 * @Feature({"History"}) |
| 202 * Bug 6164471 |
| 203 */ |
| 204 @FlakyTest |
| 205 public void testRemovingEntries() throws InterruptedException, TimeoutExcept
ion { |
| 206 // Urls will be visited in reverse order to preserve the array ordering |
| 207 // in the history results. |
| 208 String[] testUrls = new String[] { |
| 209 TestHttpServerClient.getUrl("chrome/test/data/android/google.htm
l"), |
| 210 TestHttpServerClient.getUrl("chrome/test/data/android/about.html
"), |
| 211 }; |
| 212 |
| 213 String[] testTitles = new String[testUrls.length]; |
| 214 for (int i = testUrls.length - 1; i >= 0; --i) { |
| 215 loadUrl(testUrls[i]); |
| 216 testTitles[i] = getActivity().getActivityTab().getTitle(); |
| 217 } |
| 218 |
| 219 // Check that the history page contains the visited pages. |
| 220 loadUrl(HISTORY_URL); |
| 221 UiUtils.settleDownUI(getInstrumentation()); |
| 222 HistoryItem[] history = getHistoryContents(); |
| 223 assertEquals(testUrls.length, history.length); |
| 224 for (int i = 0; i < testUrls.length; ++i) { |
| 225 assertEquals(testUrls[i], history[i].url); |
| 226 assertEquals(testTitles[i], history[i].title); |
| 227 } |
| 228 |
| 229 // Remove the first entry from history. |
| 230 assertTrue(history.length >= 1); |
| 231 removeSelectedEntries(new int[]{ 0 }); |
| 232 |
| 233 // Check that now the first result is the second visited page. |
| 234 history = getHistoryContents(); |
| 235 assertEquals(testUrls.length - 1, history.length); |
| 236 assertEquals(testUrls[1], history[0].url); |
| 237 assertEquals(testTitles[1], history[0].title); |
| 238 } |
| 239 |
| 240 /* |
| 241 * @LargeTest |
| 242 * @Feature({"History"}) |
| 243 * Bug 5971989 |
| 244 */ |
| 245 @FlakyTest |
| 246 public void testClearBrowsingData() throws InterruptedException, TimeoutExce
ption { |
| 247 // Introduce some entries in the history page. |
| 248 loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/google.htm
l")); |
| 249 loadUrl(TestHttpServerClient.getUrl("chrome/test/data/android/about.html
")); |
| 250 loadUrl(HISTORY_URL); |
| 251 UiUtils.settleDownUI(getInstrumentation()); |
| 252 assertResultCountReaches(getActivity().getCurrentContentViewCore(), 2); |
| 253 |
| 254 // Trigger cleaning up all the browsing data. JS finishing events will m
ake it synchronous |
| 255 // to us. |
| 256 final Preferences prefActivity = ActivityUtils.waitForActivity( |
| 257 getInstrumentation(), PreferencesStaging.class, new Runnable() { |
| 258 @Override |
| 259 public void run() { |
| 260 try { |
| 261 runJavaScriptCodeInCurrentTab("openClearBrowsingData
()"); |
| 262 } catch (InterruptedException e) { |
| 263 fail("Exception occurred while attempting to open cl
ear browing data"); |
| 264 } catch (TimeoutException e) { |
| 265 fail("Exception occurred while attempting to open cl
ear browing data"); |
| 266 } |
| 267 } |
| 268 }); |
| 269 assertNotNull("Could not find the preferences activity", prefActivity); |
| 270 |
| 271 final ClearBrowsingDataDialogFragment clearBrowsingFragment = |
| 272 ActivityUtils.waitForFragment( |
| 273 prefActivity, ClearBrowsingDataDialogFragment.FRAGMENT_T
AG); |
| 274 assertNotNull("Could not find clear browsing data fragment", clearBrowsi
ngFragment); |
| 275 |
| 276 Dialog dialog = clearBrowsingFragment.getDialog(); |
| 277 final Button clearButton = ((AlertDialog) dialog).getButton( |
| 278 AlertDialog.BUTTON_POSITIVE); |
| 279 assertNotNull("Could not find Clear button.", clearButton); |
| 280 |
| 281 TestTouchUtils.performClickOnMainSync(getInstrumentation(), clearButton)
; |
| 282 assertTrue("Clear browsing dialog never hidden", |
| 283 CriteriaHelper.pollForUIThreadCriteria(new Criteria() { |
| 284 @Override |
| 285 public boolean isSatisfied() { |
| 286 return !clearBrowsingFragment.isVisible(); |
| 287 } |
| 288 })); |
| 289 |
| 290 final ChromeActivity mainActivity = ActivityUtils.waitForActivity( |
| 291 getInstrumentation(), getActivity().getClass(), new Runnable() { |
| 292 @Override |
| 293 public void run() { |
| 294 ThreadUtils.runOnUiThread(new Runnable() { |
| 295 @Override |
| 296 public void run() { |
| 297 prefActivity.finish(); |
| 298 } |
| 299 }); |
| 300 } |
| 301 }); |
| 302 assertNotNull("Main never resumed", mainActivity); |
| 303 assertTrue("Main tab never restored", CriteriaHelper.pollForCriteria(new
Criteria() { |
| 304 @Override |
| 305 public boolean isSatisfied() { |
| 306 return ThreadUtils.runOnUiThreadBlockingNoException(new Callable
<Boolean>() { |
| 307 @Override |
| 308 public Boolean call() throws Exception { |
| 309 return mainActivity.getActivityTab() != null |
| 310 && !mainActivity.getActivityTab().isFrozen(); |
| 311 } |
| 312 }); |
| 313 } |
| 314 })); |
| 315 JavaScriptUtils.executeJavaScriptAndWaitForResult( |
| 316 mainActivity.getCurrentContentViewCore().getWebContents(), "relo
adHistory()"); |
| 317 assertResultCountReaches(getActivity().getCurrentContentViewCore(), 0); |
| 318 } |
| 319 } |
OLD | NEW |