OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser; | 5 package org.chromium.chrome.browser; |
6 | 6 |
7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
8 import android.content.pm.ApplicationInfo; | 8 import android.content.pm.ApplicationInfo; |
9 import android.content.pm.PackageManager; | 9 import android.content.pm.PackageManager; |
10 import android.graphics.Rect; | 10 import android.graphics.Rect; |
11 import android.os.Build; | 11 import android.os.Build; |
12 import android.os.Bundle; | 12 import android.os.Bundle; |
13 import android.os.Handler; | 13 import android.os.Handler; |
14 import android.os.HandlerThread; | 14 import android.os.HandlerThread; |
15 import android.os.Message; | 15 import android.os.Message; |
16 import android.support.test.filters.MediumTest; | 16 import android.support.test.filters.MediumTest; |
17 import android.view.View; | 17 import android.view.View; |
18 import android.view.ViewGroup; | 18 import android.view.ViewGroup; |
19 | 19 |
| 20 import org.junit.After; |
| 21 import org.junit.Assert; |
| 22 import org.junit.Before; |
| 23 import org.junit.Rule; |
| 24 import org.junit.Test; |
| 25 import org.junit.runner.RunWith; |
| 26 |
20 import org.chromium.base.ThreadUtils; | 27 import org.chromium.base.ThreadUtils; |
21 import org.chromium.base.test.util.CallbackHelper; | 28 import org.chromium.base.test.util.CallbackHelper; |
| 29 import org.chromium.base.test.util.CommandLineFlags; |
22 import org.chromium.base.test.util.Feature; | 30 import org.chromium.base.test.util.Feature; |
23 import org.chromium.base.test.util.RetryOnFailure; | 31 import org.chromium.base.test.util.RetryOnFailure; |
24 import org.chromium.chrome.test.ChromeActivityTestCaseBase; | 32 import org.chromium.chrome.test.ChromeActivityTestRule; |
| 33 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; |
25 | 34 |
26 import java.lang.reflect.Method; | 35 import java.lang.reflect.Method; |
27 import java.util.concurrent.TimeoutException; | 36 import java.util.concurrent.TimeoutException; |
28 | 37 |
29 /** | 38 /** |
30 * Tests for the SmartClipProvider. | 39 * Tests for the SmartClipProvider. |
31 */ | 40 */ |
32 public class SmartClipProviderTest | 41 @RunWith(ChromeJUnit4ClassRunner.class) |
33 extends ChromeActivityTestCaseBase<ChromeActivity> implements Handler.Ca
llback { | 42 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, |
| 43 ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) |
| 44 public class SmartClipProviderTest implements Handler.Callback { |
34 // This is a key for meta-data in the package manifest. It should NOT | 45 // This is a key for meta-data in the package manifest. It should NOT |
35 // change, as OEMs will use it when they look for the SmartClipProvider | 46 // change, as OEMs will use it when they look for the SmartClipProvider |
36 // interface. | 47 // interface. |
| 48 |
| 49 @Rule |
| 50 public ChromeActivityTestRule<ChromeActivity> mActivityTestRule = |
| 51 new ChromeActivityTestRule<>(ChromeActivity.class); |
| 52 |
37 private static final String SMART_CLIP_PROVIDER_KEY = | 53 private static final String SMART_CLIP_PROVIDER_KEY = |
38 "org.chromium.content.browser.SMART_CLIP_PROVIDER"; | 54 "org.chromium.content.browser.SMART_CLIP_PROVIDER"; |
39 | 55 |
40 private static class MyCallbackHelper extends CallbackHelper { | 56 private static class MyCallbackHelper extends CallbackHelper { |
41 public String getTitle() { | 57 public String getTitle() { |
42 return mTitle; | 58 return mTitle; |
43 } | 59 } |
44 | 60 |
45 public String getUrl() { | 61 public String getUrl() { |
46 return mUrl; | 62 return mUrl; |
(...skipping 28 matching lines...) Expand all Loading... |
75 } | 91 } |
76 | 92 |
77 private ChromeActivity mActivity; | 93 private ChromeActivity mActivity; |
78 private MyCallbackHelper mCallbackHelper; | 94 private MyCallbackHelper mCallbackHelper; |
79 private HandlerThread mHandlerThread; | 95 private HandlerThread mHandlerThread; |
80 private Handler mHandler; | 96 private Handler mHandler; |
81 private Class<?> mSmartClipProviderClass; | 97 private Class<?> mSmartClipProviderClass; |
82 private Method mSetSmartClipResultHandlerMethod; | 98 private Method mSetSmartClipResultHandlerMethod; |
83 private Method mExtractSmartClipDataMethod; | 99 private Method mExtractSmartClipDataMethod; |
84 | 100 |
85 public SmartClipProviderTest() { | 101 @Before |
86 super(ChromeActivity.class); | |
87 } | |
88 | |
89 @Override | |
90 public void startMainActivity() throws InterruptedException { | |
91 startMainActivityOnBlankPage(); | |
92 } | |
93 | |
94 @Override | |
95 public void setUp() throws Exception { | 102 public void setUp() throws Exception { |
96 super.setUp(); | 103 mActivityTestRule.startMainActivityOnBlankPage(); |
97 mActivity = getActivity(); | 104 mActivity = mActivityTestRule.getActivity(); |
98 mCallbackHelper = new MyCallbackHelper(); | 105 mCallbackHelper = new MyCallbackHelper(); |
99 mHandlerThread = new HandlerThread("ContentViewTest thread"); | 106 mHandlerThread = new HandlerThread("ContentViewTest thread"); |
100 mHandlerThread.start(); | 107 mHandlerThread.start(); |
101 mHandler = new Handler(mHandlerThread.getLooper(), this); | 108 mHandler = new Handler(mHandlerThread.getLooper(), this); |
102 | 109 |
103 mSmartClipProviderClass = getSmartClipProviderClass(); | 110 mSmartClipProviderClass = getSmartClipProviderClass(); |
104 assertNotNull(mSmartClipProviderClass); | 111 Assert.assertNotNull(mSmartClipProviderClass); |
105 mSetSmartClipResultHandlerMethod = mSmartClipProviderClass.getDeclaredMe
thod( | 112 mSetSmartClipResultHandlerMethod = mSmartClipProviderClass.getDeclaredMe
thod( |
106 "setSmartClipResultHandler", new Class[] { Handler.class }); | 113 "setSmartClipResultHandler", new Class[] { Handler.class }); |
107 mExtractSmartClipDataMethod = mSmartClipProviderClass.getDeclaredMethod( | 114 mExtractSmartClipDataMethod = mSmartClipProviderClass.getDeclaredMethod( |
108 "extractSmartClipData", | 115 "extractSmartClipData", |
109 new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.
TYPE }); | 116 new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.
TYPE }); |
110 } | 117 } |
111 | 118 |
| 119 @After |
112 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) | 120 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) |
113 @Override | |
114 public void tearDown() throws Exception { | 121 public void tearDown() throws Exception { |
115 try { | 122 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { |
116 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { | 123 mHandlerThread.quitSafely(); |
117 mHandlerThread.quitSafely(); | 124 } else { |
118 } else { | 125 mHandlerThread.quit(); |
119 mHandlerThread.quit(); | |
120 } | |
121 } finally { | |
122 super.tearDown(); | |
123 } | 126 } |
124 } | 127 } |
125 | 128 |
126 // Implements Handler.Callback | 129 // Implements Handler.Callback |
127 @Override | 130 @Override |
128 public boolean handleMessage(Message msg) { | 131 public boolean handleMessage(Message msg) { |
129 Bundle bundle = msg.getData(); | 132 Bundle bundle = msg.getData(); |
130 assertNotNull(bundle); | 133 Assert.assertNotNull(bundle); |
131 String url = bundle.getString("url"); | 134 String url = bundle.getString("url"); |
132 String title = bundle.getString("title"); | 135 String title = bundle.getString("title"); |
133 String text = bundle.getString("text"); | 136 String text = bundle.getString("text"); |
134 String html = bundle.getString("html"); | 137 String html = bundle.getString("html"); |
135 Rect rect = bundle.getParcelable("rect"); | 138 Rect rect = bundle.getParcelable("rect"); |
136 // We don't care about other values for now. | 139 // We don't care about other values for now. |
137 mCallbackHelper.notifyCalled(title, url, text, html, rect); | 140 mCallbackHelper.notifyCalled(title, url, text, html, rect); |
138 return true; | 141 return true; |
139 } | 142 } |
140 | 143 |
141 // Create SmartClipProvider interface from package meta-data. | 144 // Create SmartClipProvider interface from package meta-data. |
142 private Class<?> getSmartClipProviderClass() throws Exception { | 145 private Class<?> getSmartClipProviderClass() throws Exception { |
143 ApplicationInfo ai = mActivity.getPackageManager().getApplicationInfo( | 146 ApplicationInfo ai = mActivity.getPackageManager().getApplicationInfo( |
144 mActivity.getPackageName(), PackageManager.GET_META_DATA); | 147 mActivity.getPackageName(), PackageManager.GET_META_DATA); |
145 Bundle bundle = ai.metaData; | 148 Bundle bundle = ai.metaData; |
146 String className = bundle.getString(SMART_CLIP_PROVIDER_KEY); | 149 String className = bundle.getString(SMART_CLIP_PROVIDER_KEY); |
147 assertNotNull(className); | 150 Assert.assertNotNull(className); |
148 return Class.forName(className); | 151 return Class.forName(className); |
149 } | 152 } |
150 | 153 |
151 // Returns the first smart clip provider under the root view using DFS. | 154 // Returns the first smart clip provider under the root view using DFS. |
152 private Object findSmartClipProvider(View v) { | 155 private Object findSmartClipProvider(View v) { |
153 if (mSmartClipProviderClass.isInstance(v)) { | 156 if (mSmartClipProviderClass.isInstance(v)) { |
154 return v; | 157 return v; |
155 } else if (v instanceof ViewGroup) { | 158 } else if (v instanceof ViewGroup) { |
156 ViewGroup viewGroup = (ViewGroup) v; | 159 ViewGroup viewGroup = (ViewGroup) v; |
157 int count = viewGroup.getChildCount(); | 160 int count = viewGroup.getChildCount(); |
158 for (int i = 0; i < count; ++i) { | 161 for (int i = 0; i < count; ++i) { |
159 View c = viewGroup.getChildAt(i); | 162 View c = viewGroup.getChildAt(i); |
160 Object found = findSmartClipProvider(c); | 163 Object found = findSmartClipProvider(c); |
161 if (found != null) return found; | 164 if (found != null) return found; |
162 } | 165 } |
163 } | 166 } |
164 return null; | 167 return null; |
165 } | 168 } |
166 | 169 |
| 170 @Test |
167 @MediumTest | 171 @MediumTest |
168 @Feature({"SmartClip"}) | 172 @Feature({"SmartClip"}) |
169 @RetryOnFailure | 173 @RetryOnFailure |
170 public void testSmartClipDataCallback() throws InterruptedException, Timeout
Exception { | 174 public void testSmartClipDataCallback() throws InterruptedException, Timeout
Exception { |
171 final Rect rect = new Rect(10, 20, 110, 190); | 175 final Rect rect = new Rect(10, 20, 110, 190); |
172 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 176 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
173 @Override | 177 @Override |
174 public void run() { | 178 public void run() { |
175 // This emulates what OEM will be doing when they want to call | 179 // This emulates what OEM will be doing when they want to call |
176 // functions on SmartClipProvider through view hierarchy. | 180 // functions on SmartClipProvider through view hierarchy. |
177 | 181 |
178 Object scp = | 182 Object scp = findSmartClipProvider( |
179 findSmartClipProvider(getActivity().findViewById(android
.R.id.content)); | 183 mActivityTestRule.getActivity().findViewById(android.R.i
d.content)); |
180 assertNotNull(scp); | 184 Assert.assertNotNull(scp); |
181 try { | 185 try { |
182 mSetSmartClipResultHandlerMethod.invoke(scp, mHandler); | 186 mSetSmartClipResultHandlerMethod.invoke(scp, mHandler); |
183 mExtractSmartClipDataMethod.invoke( | 187 mExtractSmartClipDataMethod.invoke( |
184 scp, rect.left, rect.top, rect.width(), rect.height(
)); | 188 scp, rect.left, rect.top, rect.width(), rect.height(
)); |
185 } catch (Exception e) { | 189 } catch (Exception e) { |
186 e.printStackTrace(); | 190 e.printStackTrace(); |
187 fail(); | 191 Assert.fail(); |
188 } | 192 } |
189 } | 193 } |
190 }); | 194 }); |
191 mCallbackHelper.waitForCallback(0, 1); // call count: 0 --> 1 | 195 mCallbackHelper.waitForCallback(0, 1); // call count: 0 --> 1 |
192 assertEquals("about:blank", mCallbackHelper.getTitle()); | 196 Assert.assertEquals("about:blank", mCallbackHelper.getTitle()); |
193 assertEquals("about:blank", mCallbackHelper.getUrl()); | 197 Assert.assertEquals("about:blank", mCallbackHelper.getUrl()); |
194 assertNotNull(mCallbackHelper.getText()); | 198 Assert.assertNotNull(mCallbackHelper.getText()); |
195 assertNotNull(mCallbackHelper.getHtml()); | 199 Assert.assertNotNull(mCallbackHelper.getHtml()); |
196 assertNotNull(mCallbackHelper.getRect()); | 200 Assert.assertNotNull(mCallbackHelper.getRect()); |
197 assertEquals(rect.left, mCallbackHelper.getRect().left); | 201 Assert.assertEquals(rect.left, mCallbackHelper.getRect().left); |
198 assertEquals(rect.top, mCallbackHelper.getRect().top); | 202 Assert.assertEquals(rect.top, mCallbackHelper.getRect().top); |
199 assertEquals(rect.width(), mCallbackHelper.getRect().width()); | 203 Assert.assertEquals(rect.width(), mCallbackHelper.getRect().width()); |
200 assertEquals(rect.height(), mCallbackHelper.getRect().height()); | 204 Assert.assertEquals(rect.height(), mCallbackHelper.getRect().height()); |
201 } | 205 } |
202 | 206 |
| 207 @Test |
203 @MediumTest | 208 @MediumTest |
204 @Feature({"SmartClip"}) | 209 @Feature({"SmartClip"}) |
205 @RetryOnFailure | 210 @RetryOnFailure |
206 public void testSmartClipNoHandlerDoesntCrash() throws InterruptedException,
TimeoutException { | 211 public void testSmartClipNoHandlerDoesntCrash() throws InterruptedException,
TimeoutException { |
207 ThreadUtils.runOnUiThreadBlocking(new Runnable() { | 212 ThreadUtils.runOnUiThreadBlocking(new Runnable() { |
208 @Override | 213 @Override |
209 public void run() { | 214 public void run() { |
210 Object scp = | 215 Object scp = findSmartClipProvider( |
211 findSmartClipProvider(getActivity().findViewById(android
.R.id.content)); | 216 mActivityTestRule.getActivity().findViewById(android.R.i
d.content)); |
212 assertNotNull(scp); | 217 Assert.assertNotNull(scp); |
213 try { | 218 try { |
214 // Galaxy Note 4 has a bug where it doesn't always set the h
andler first; in | 219 // Galaxy Note 4 has a bug where it doesn't always set the h
andler first; in |
215 // that case, we shouldn't crash: http://crbug.com/710147 | 220 // that case, we shouldn't crash: http://crbug.com/710147 |
216 mExtractSmartClipDataMethod.invoke(scp, 10, 20, 100, 70); | 221 mExtractSmartClipDataMethod.invoke(scp, 10, 20, 100, 70); |
217 | 222 |
218 // Add a wait for a valid callback to make sure we have time
to | 223 // Add a wait for a valid callback to make sure we have time
to |
219 // hit the crash from the above call if any. | 224 // hit the crash from the above call if any. |
220 mSetSmartClipResultHandlerMethod.invoke(scp, mHandler); | 225 mSetSmartClipResultHandlerMethod.invoke(scp, mHandler); |
221 mExtractSmartClipDataMethod.invoke(scp, 10, 20, 100, 70); | 226 mExtractSmartClipDataMethod.invoke(scp, 10, 20, 100, 70); |
222 } catch (Exception e) { | 227 } catch (Exception e) { |
223 e.printStackTrace(); | 228 e.printStackTrace(); |
224 fail(); | 229 Assert.fail(); |
225 } | 230 } |
226 } | 231 } |
227 }); | 232 }); |
228 mCallbackHelper.waitForCallback(0, 1); // call count: 0 --> 1 | 233 mCallbackHelper.waitForCallback(0, 1); // call count: 0 --> 1 |
229 } | 234 } |
230 } | 235 } |
OLD | NEW |