Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / public / test / android / javatests / src / org / chromium / content / browser / test / util / DOMUtils.java
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.content.browser.test.util;
6
7 import android.graphics.Rect;
8 import android.test.ActivityInstrumentationTestCase2;
9 import android.util.JsonReader;
10
11 import junit.framework.Assert;
12
13 import org.chromium.content.browser.ContentViewCore;
14 import org.chromium.content_public.browser.WebContents;
15
16 import java.io.IOException;
17 import java.io.StringReader;
18 import java.util.concurrent.TimeoutException;
19
20 /**
21  * Collection of DOM-based utilities.
22  */
23 public class DOMUtils {
24     /**
25      * Pauses the video with given {@code nodeId}.
26      */
27     public static void pauseVideo(final WebContents webContents, final String nodeId)
28             throws InterruptedException, TimeoutException {
29         StringBuilder sb = new StringBuilder();
30         sb.append("(function() {");
31         sb.append("  var video = document.getElementById('" + nodeId + "');");
32         sb.append("  if (video) video.pause();");
33         sb.append("})();");
34         JavaScriptUtils.executeJavaScriptAndWaitForResult(
35                 webContents, sb.toString());
36     }
37
38     /**
39      * Returns whether the video with given {@code nodeId} is paused.
40      */
41     public static boolean isVideoPaused(final WebContents webContents, final String nodeId)
42             throws InterruptedException, TimeoutException {
43         return getNodeField("paused", webContents, nodeId, Boolean.class);
44     }
45
46     /**
47      * Waits until the playback of the video with given {@code nodeId} has started.
48      *
49      * @return Whether the playback has started.
50      */
51     public static boolean waitForVideoPlay(final WebContents webContents, final String nodeId)
52             throws InterruptedException {
53         return CriteriaHelper.pollForCriteria(new Criteria() {
54             @Override
55             public boolean isSatisfied() {
56                 try {
57                     return !DOMUtils.isVideoPaused(webContents, nodeId);
58                 } catch (InterruptedException e) {
59                     // Intentionally do nothing
60                     return false;
61                 } catch (TimeoutException e) {
62                     // Intentionally do nothing
63                     return false;
64                 }
65             }
66         });
67     }
68
69     /**
70      * Returns whether the document is in fullscreen.
71      */
72     public static boolean isFullscreen(final WebContents webContents)
73             throws InterruptedException, TimeoutException {
74         StringBuilder sb = new StringBuilder();
75         sb.append("(function() {");
76         sb.append("  return [document.webkitIsFullScreen];");
77         sb.append("})();");
78
79         String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
80                 webContents, sb.toString());
81         return readValue(jsonText, Boolean.class);
82     }
83
84     /**
85      * Makes the document exit fullscreen.
86      */
87     public static void exitFullscreen(final WebContents webContents) {
88         StringBuilder sb = new StringBuilder();
89         sb.append("(function() {");
90         sb.append("  if (document.webkitExitFullscreen) document.webkitExitFullscreen();");
91         sb.append("})();");
92
93         JavaScriptUtils.executeJavaScript(webContents, sb.toString());
94     }
95
96     /**
97      * Returns the rect boundaries for a node by its id.
98      */
99     public static Rect getNodeBounds(final WebContents webContents, String nodeId)
100             throws InterruptedException, TimeoutException {
101         StringBuilder sb = new StringBuilder();
102         sb.append("(function() {");
103         sb.append("  var node = document.getElementById('" + nodeId + "');");
104         sb.append("  if (!node) return null;");
105         sb.append("  var width = Math.round(node.offsetWidth);");
106         sb.append("  var height = Math.round(node.offsetHeight);");
107         sb.append("  var x = -window.scrollX;");
108         sb.append("  var y = -window.scrollY;");
109         sb.append("  do {");
110         sb.append("    x += node.offsetLeft;");
111         sb.append("    y += node.offsetTop;");
112         sb.append("  } while (node = node.offsetParent);");
113         sb.append("  return [ Math.round(x), Math.round(y), width, height ];");
114         sb.append("})();");
115
116         String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
117                 webContents, sb.toString());
118
119         Assert.assertFalse("Failed to retrieve bounds for " + nodeId,
120                 jsonText.trim().equalsIgnoreCase("null"));
121
122         JsonReader jsonReader = new JsonReader(new StringReader(jsonText));
123         int[] bounds = new int[4];
124         try {
125             jsonReader.beginArray();
126             int i = 0;
127             while (jsonReader.hasNext()) {
128                 bounds[i++] = jsonReader.nextInt();
129             }
130             jsonReader.endArray();
131             Assert.assertEquals("Invalid bounds returned.", 4, i);
132
133             jsonReader.close();
134         } catch (IOException exception) {
135             Assert.fail("Failed to evaluate JavaScript: " + jsonText + "\n" + exception);
136         }
137
138         return new Rect(bounds[0], bounds[1], bounds[0] + bounds[2], bounds[1] + bounds[3]);
139     }
140
141     /**
142      * Focus a DOM node by its id.
143      */
144     public static void focusNode(final WebContents webContents, String nodeId)
145             throws InterruptedException, TimeoutException {
146         StringBuilder sb = new StringBuilder();
147         sb.append("(function() {");
148         sb.append("  var node = document.getElementById('" + nodeId + "');");
149         sb.append("  if (node) node.focus();");
150         sb.append("})();");
151
152         JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, sb.toString());
153     }
154
155     /**
156      * Click a DOM node by its id.
157      */
158     public static void clickNode(ActivityInstrumentationTestCase2 activityTestCase,
159             final ContentViewCore viewCore, String nodeId)
160             throws InterruptedException, TimeoutException {
161         int[] clickTarget = getClickTargetForNode(viewCore, nodeId);
162         TouchCommon.singleClickView(viewCore.getContainerView(), clickTarget[0], clickTarget[1]);
163     }
164
165     /**
166      * Long-press a DOM node by its id.
167      */
168     public static void longPressNode(ActivityInstrumentationTestCase2 activityTestCase,
169             final ContentViewCore viewCore, String nodeId)
170             throws InterruptedException, TimeoutException {
171         int[] clickTarget = getClickTargetForNode(viewCore, nodeId);
172         TouchCommon.longPressView(viewCore.getContainerView(), clickTarget[0], clickTarget[1]);
173     }
174
175     /**
176      * Scrolls the view to ensure that the required DOM node is visible.
177      */
178     public static void scrollNodeIntoView(WebContents webContents, String nodeId)
179             throws InterruptedException, TimeoutException {
180         JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents,
181                 "document.getElementById('" + nodeId + "').scrollIntoView()");
182     }
183
184     /**
185      * Returns the contents of the node by its id.
186      */
187     public static String getNodeContents(WebContents webContents, String nodeId)
188             throws InterruptedException, TimeoutException {
189         return getNodeField("textContent", webContents, nodeId, String.class);
190     }
191
192     /**
193      * Returns the value of the node by its id.
194      */
195     public static String getNodeValue(final WebContents webContents, String nodeId)
196             throws InterruptedException, TimeoutException {
197         return getNodeField("value", webContents, nodeId, String.class);
198     }
199
200     /**
201      * Returns the string value of a field of the node by its id.
202      */
203     public static String getNodeField(String fieldName, final WebContents webContents,
204             String nodeId)
205             throws InterruptedException, TimeoutException {
206         return getNodeField(fieldName, webContents, nodeId, String.class);
207     }
208
209     private static <T> T getNodeField(String fieldName, final WebContents webContents,
210             String nodeId, Class<T> valueType)
211             throws InterruptedException, TimeoutException {
212         StringBuilder sb = new StringBuilder();
213         sb.append("(function() {");
214         sb.append("  var node = document.getElementById('" + nodeId + "');");
215         sb.append("  if (!node) return null;");
216         sb.append("  return [ node." + fieldName + " ];");
217         sb.append("})();");
218
219         String jsonText = JavaScriptUtils.executeJavaScriptAndWaitForResult(
220                 webContents, sb.toString());
221         Assert.assertFalse("Failed to retrieve contents for " + nodeId,
222                 jsonText.trim().equalsIgnoreCase("null"));
223         return readValue(jsonText, valueType);
224     }
225
226     private static <T> T readValue(String jsonText, Class<T> valueType) {
227         JsonReader jsonReader = new JsonReader(new StringReader(jsonText));
228         T value = null;
229         try {
230             jsonReader.beginArray();
231             if (jsonReader.hasNext()) value = readValue(jsonReader, valueType);
232             jsonReader.endArray();
233             Assert.assertNotNull("Invalid contents returned.", value);
234
235             jsonReader.close();
236         } catch (IOException exception) {
237             Assert.fail("Failed to evaluate JavaScript: " + jsonText + "\n" + exception);
238         }
239         return value;
240     }
241
242     @SuppressWarnings("unchecked")
243     private static <T> T readValue(JsonReader jsonReader, Class<T> valueType)
244             throws IOException {
245         if (valueType.equals(String.class)) return ((T) jsonReader.nextString());
246         if (valueType.equals(Boolean.class)) return ((T) ((Boolean) jsonReader.nextBoolean()));
247         if (valueType.equals(Integer.class)) return ((T) ((Integer) jsonReader.nextInt()));
248         if (valueType.equals(Long.class)) return ((T) ((Long) jsonReader.nextLong()));
249         if (valueType.equals(Double.class)) return ((T) ((Double) jsonReader.nextDouble()));
250
251         throw new IllegalArgumentException("Cannot read values of type " + valueType);
252     }
253
254     /**
255      * Wait until a given node has non-zero bounds.
256      * @return Whether the node started having non-zero bounds.
257      */
258     public static boolean waitForNonZeroNodeBounds(final WebContents webContents,
259             final String nodeName)
260             throws InterruptedException {
261         return CriteriaHelper.pollForCriteria(new Criteria() {
262             @Override
263             public boolean isSatisfied() {
264                 try {
265                     return !DOMUtils.getNodeBounds(webContents, nodeName).isEmpty();
266                 } catch (InterruptedException e) {
267                     // Intentionally do nothing
268                     return false;
269                 } catch (TimeoutException e) {
270                     // Intentionally do nothing
271                     return false;
272                 }
273             }
274         });
275     }
276
277     /**
278      * Returns click targets for a given DOM node.
279      */
280     private static int[] getClickTargetForNode(ContentViewCore viewCore, String nodeName)
281             throws InterruptedException, TimeoutException {
282         Rect bounds = getNodeBounds(viewCore.getWebContents(), nodeName);
283         Assert.assertNotNull("Failed to get DOM element bounds of '" + nodeName + "'.", bounds);
284
285         int clickX = (int) viewCore.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterX());
286         int clickY = (int) viewCore.getRenderCoordinates().fromLocalCssToPix(bounds.exactCenterY())
287                 + viewCore.getTopControlsLayoutHeightPix();
288         return new int[] { clickX, clickY };
289     }
290 }