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 5 package org.chromium.chrome.browser.input; 6 7 import android.app.Activity; 8 import android.content.Intent; 9 import android.provider.MediaStore; 10 import android.test.suitebuilder.annotation.MediumTest; 11 12 import org.chromium.base.test.util.Feature; 13 import org.chromium.base.test.util.UrlUtils; 14 import org.chromium.chrome.shell.ChromeShellActivity; 15 import org.chromium.chrome.shell.ChromeShellActivity.ActivityWindowAndroidFactory; 16 import org.chromium.chrome.shell.ChromeShellTestBase; 17 import org.chromium.content.browser.ContentViewCore; 18 import org.chromium.content.browser.test.util.Criteria; 19 import org.chromium.content.browser.test.util.CriteriaHelper; 20 import org.chromium.content.browser.test.util.DOMUtils; 21 import org.chromium.content.browser.test.util.UiUtils; 22 import org.chromium.ui.base.ActivityWindowAndroid; 23 24 /** 25 * Integration test for select file dialog used for <input type="file" /> 26 */ 27 public class SelectFileDialogTest extends ChromeShellTestBase { 28 private static final String DATA_URL = UrlUtils.encodeHtmlDataUri( 29 "<html><head><meta name=\"viewport\"" + 30 "content=\"width=device-width, initial-scale=2.0, maximum-scale=2.0\" /></head>" + 31 "<body><form action=\"about:blank\">" + 32 "<input id=\"input_file\" type=\"file\" /><br/>" + 33 "<input id=\"input_image\" type=\"file\" accept=\"image/*\" capture /><br/>" + 34 "<input id=\"input_audio\" type=\"file\" accept=\"audio/*\" capture />" + 35 "</form>" + 36 "</body></html>"); 37 38 private ContentViewCore mContentViewCore; 39 private ActivityWindowAndroidForTest mActivityWindowAndroidForTest; 40 41 private static class ActivityWindowAndroidForTest extends ActivityWindowAndroid { 42 public Intent lastIntent; 43 public IntentCallback lastCallback; 44 /** 45 * @param activity 46 */ 47 public ActivityWindowAndroidForTest(Activity activity) { 48 super(activity); 49 } 50 51 @Override 52 public int showCancelableIntent(Intent intent, IntentCallback callback, int errorId) { 53 lastIntent = intent; 54 lastCallback = callback; 55 return 1; 56 } 57 } 58 59 private class IntentSentCriteria implements Criteria { 60 @Override 61 public boolean isSatisfied() { 62 return mActivityWindowAndroidForTest.lastIntent != null; 63 } 64 } 65 66 @Override 67 public void setUp() throws Exception { 68 super.setUp(); 69 70 ChromeShellActivity.setActivityWindowAndroidFactory(new ActivityWindowAndroidFactory() { 71 @Override 72 public ActivityWindowAndroid getActivityWindowAndroid(Activity activity) { 73 mActivityWindowAndroidForTest = new ActivityWindowAndroidForTest(activity); 74 return mActivityWindowAndroidForTest; 75 } 76 }); 77 launchChromeShellWithUrl(DATA_URL); 78 assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); 79 80 mContentViewCore = getActivity().getActiveContentViewCore(); 81 // TODO(aurimas) remove this wait once crbug.com/179511 is fixed. 82 assertWaitForPageScaleFactorMatch(2); 83 assertTrue( 84 DOMUtils.waitForNonZeroNodeBounds(mContentViewCore, "input_file")); 85 } 86 87 /** 88 * Tests that clicks on <input type="file" /> trigger intent calls to ActivityWindowAndroid. 89 */ 90 @MediumTest 91 @Feature({"TextInput", "Main"}) 92 public void testSelectFileAndCancelRequest() throws Throwable { 93 DOMUtils.clickNode(this, mContentViewCore, "input_file"); 94 assertTrue("SelectFileDialog never sent an intent.", 95 CriteriaHelper.pollForCriteria(new IntentSentCriteria())); 96 assertEquals(Intent.ACTION_CHOOSER, mActivityWindowAndroidForTest.lastIntent.getAction()); 97 resetActivityWindowAndroidForTest(); 98 99 DOMUtils.clickNode(this, mContentViewCore, "input_image"); 100 assertTrue("SelectFileDialog never sent an intent.", 101 CriteriaHelper.pollForCriteria(new IntentSentCriteria())); 102 assertEquals(MediaStore.ACTION_IMAGE_CAPTURE, 103 mActivityWindowAndroidForTest.lastIntent.getAction()); 104 resetActivityWindowAndroidForTest(); 105 106 DOMUtils.clickNode(this, mContentViewCore, "input_audio"); 107 assertTrue("SelectFileDialog never sent an intent.", 108 CriteriaHelper.pollForCriteria(new IntentSentCriteria())); 109 assertEquals(MediaStore.Audio.Media.RECORD_SOUND_ACTION, 110 mActivityWindowAndroidForTest.lastIntent.getAction()); 111 resetActivityWindowAndroidForTest(); 112 } 113 114 private void resetActivityWindowAndroidForTest() { 115 UiUtils.runOnUiThread(getActivity(), new Runnable() { 116 @Override 117 public void run() { 118 mActivityWindowAndroidForTest.lastCallback.onIntentCompleted( 119 mActivityWindowAndroidForTest, Activity.RESULT_CANCELED, null, null); 120 } 121 }); 122 mActivityWindowAndroidForTest.lastCallback = null; 123 mActivityWindowAndroidForTest.lastIntent = null; 124 } 125 } 126