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_public.browser.test.util;
6 
7 import org.chromium.base.test.util.CallbackHelper;
8 import org.chromium.content_public.browser.JavaScriptCallback;
9 import org.chromium.content_public.browser.WebContents;
10 
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.concurrent.TimeUnit;
15 import java.util.concurrent.TimeoutException;
16 
17 /**
18  * This class is used to provide callback hooks for tests and related classes.
19  */
20 public class TestCallbackHelperContainer {
21     private TestWebContentsObserver mTestWebContentsObserver;
22 
TestCallbackHelperContainer(final WebContents webContents)23     public TestCallbackHelperContainer(final WebContents webContents) {
24         // TODO(yfriedman): Change callers to be executed on the UI thread. Unfortunately this is
25         // super convenient as the caller is nearly always on the test thread which is fine to block
26         // and it's cumbersome to keep bouncing to the UI thread.
27         TestThreadUtils.runOnUiThreadBlocking(
28                 () -> { mTestWebContentsObserver = new TestWebContentsObserver(webContents); });
29     }
30 
31     /**
32      * CallbackHelper for OnPageCommitVisible.
33      */
34     public static class OnPageCommitVisibleHelper extends CallbackHelper {
35         private String mUrl;
notifyCalled(String url)36         public void notifyCalled(String url) {
37             mUrl = url;
38             notifyCalled();
39         }
getUrl()40         public String getUrl() {
41             assert getCallCount() > 0;
42             return mUrl;
43         }
44     }
45 
46     /**
47      * CallbackHelper for OnPageFinished.
48      */
49     public static class OnPageFinishedHelper extends CallbackHelper {
50         private List<String> mUrlList = Collections.synchronizedList(new ArrayList<>());
51         private String mUrl;
notifyCalled(String url)52         public void notifyCalled(String url) {
53             mUrl = url;
54             mUrlList.add(url);
55             notifyCalled();
56         }
getUrl()57         public String getUrl() {
58             assert getCallCount() > 0;
59             return mUrl;
60         }
getUrlList()61         public List<String> getUrlList() {
62             return mUrlList;
63         }
64     }
65 
66     /**
67      * CallbackHelper for OnPageStarted.
68      */
69     public static class OnPageStartedHelper extends CallbackHelper {
70         private String mUrl;
notifyCalled(String url)71         public void notifyCalled(String url) {
72             mUrl = url;
73             notifyCalled();
74         }
getUrl()75         public String getUrl() {
76             assert getCallCount() > 0;
77             return mUrl;
78         }
79     }
80 
81     /**
82      * CallbackHelper for OnReceivedError.
83      */
84     public static class OnReceivedErrorHelper extends CallbackHelper {
85         private int mErrorCode;
86         private String mDescription;
87         private String mFailingUrl;
notifyCalled(int errorCode, String description, String failingUrl)88         public void notifyCalled(int errorCode, String description, String failingUrl) {
89             mErrorCode = errorCode;
90             mDescription = description;
91             mFailingUrl = failingUrl;
92             notifyCalled();
93         }
getErrorCode()94         public int getErrorCode() {
95             assert getCallCount() > 0;
96             return mErrorCode;
97         }
getDescription()98         public String getDescription() {
99             assert getCallCount() > 0;
100             return mDescription;
101         }
getFailingUrl()102         public String getFailingUrl() {
103             assert getCallCount() > 0;
104             return mFailingUrl;
105         }
106     }
107 
108     /**
109      * CallbackHelper for OnEvaluateJavaScriptResult.
110      * This class wraps the evaluation of JavaScript code allowing test code to
111      * synchronously evaluate JavaScript and then test the result.
112      */
113     public static class OnEvaluateJavaScriptResultHelper extends CallbackHelper {
114         private String mJsonResult;
115 
116         /**
117          * Starts evaluation of a given JavaScript code on a given webContents.
118          * @param webContents A WebContents instance to be used.
119          * @param code A JavaScript code to be evaluated.
120          */
evaluateJavaScriptForTests(WebContents webContents, String code)121         public void evaluateJavaScriptForTests(WebContents webContents, String code) {
122             JavaScriptCallback callback = new JavaScriptCallback() {
123                 @Override
124                 public void handleJavaScriptResult(String jsonResult) {
125                     notifyCalled(jsonResult);
126                 }
127             };
128             mJsonResult = null;
129             TestThreadUtils.runOnUiThreadBlocking(
130                     () -> webContents.evaluateJavaScriptForTests(code, callback));
131         }
132 
133         /**
134          * Returns true if the evaluation started by evaluateJavaScriptForTests() has completed.
135          */
hasValue()136         public boolean hasValue() {
137             return mJsonResult != null;
138         }
139 
140         /**
141          * Returns the JSON result of a previously completed JavaScript evaluation and
142          * resets the helper to accept new evaluations.
143          * @return String JSON result of a previously completed JavaScript evaluation.
144          */
getJsonResultAndClear()145         public String getJsonResultAndClear() {
146             assert hasValue();
147             String result = mJsonResult;
148             mJsonResult = null;
149             return result;
150         }
151 
152         /**
153          * Waits till the JavaScript evaluation finishes and returns true if a value was returned,
154          * false if it timed-out.
155          */
waitUntilHasValue(long timeout, TimeUnit unit)156         public boolean waitUntilHasValue(long timeout, TimeUnit unit) throws TimeoutException {
157             int count = getCallCount();
158             // Reads and writes are atomic for reference variables in java, this is thread safe
159             if (hasValue()) return true;
160             waitForCallback(count, 1, timeout, unit);
161             return hasValue();
162         }
163 
waitUntilHasValue()164         public boolean waitUntilHasValue() throws TimeoutException {
165             return waitUntilHasValue(CallbackHelper.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
166         }
167 
notifyCalled(String jsonResult)168         public void notifyCalled(String jsonResult) {
169             assert !hasValue();
170             mJsonResult = jsonResult;
171             notifyCalled();
172         }
173     }
174 
getOnPageStartedHelper()175     public OnPageStartedHelper getOnPageStartedHelper() {
176         return mTestWebContentsObserver.getOnPageStartedHelper();
177     }
178 
getOnPageFinishedHelper()179     public OnPageFinishedHelper getOnPageFinishedHelper() {
180         return mTestWebContentsObserver.getOnPageFinishedHelper();
181     }
182 
getOnReceivedErrorHelper()183     public OnReceivedErrorHelper getOnReceivedErrorHelper() {
184         return mTestWebContentsObserver.getOnReceivedErrorHelper();
185     }
186 
getOnFirstVisuallyNonEmptyPaintHelper()187     public CallbackHelper getOnFirstVisuallyNonEmptyPaintHelper() {
188         return mTestWebContentsObserver.getOnFirstVisuallyNonEmptyPaintHelper();
189     }
190 }
191