Commit 9c6f62dc authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

Wait until native is loaded before issuing voice search queries

Bug: 1060382
Change-Id: If8022bfe71c9a8c8f70a4de37153e1c7ad028d64
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2106742Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#751803}
parent 40c90b9e
...@@ -1256,4 +1256,9 @@ public class LocationBarLayout extends FrameLayout ...@@ -1256,4 +1256,9 @@ public class LocationBarLayout extends FrameLayout
mWindowDelegate.setWindowSoftInputMode(softInputMode); mWindowDelegate.setWindowSoftInputMode(softInputMode);
} }
} }
public void setVoiceRecognitionHandlerForTesting(
VoiceRecognitionHandler voiceRecognitionHandler) {
mVoiceRecognitionHandler = voiceRecognitionHandler;
}
} }
...@@ -11,6 +11,7 @@ import android.util.AttributeSet; ...@@ -11,6 +11,7 @@ import android.util.AttributeSet;
import android.view.View; import android.view.View;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.locale.LocaleManager; import org.chromium.chrome.browser.locale.LocaleManager;
...@@ -36,6 +37,7 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout { ...@@ -36,6 +37,7 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout {
private Delegate mDelegate; private Delegate mDelegate;
private boolean mPendingSearchPromoDecision; private boolean mPendingSearchPromoDecision;
private boolean mPendingBeginQuery; private boolean mPendingBeginQuery;
private boolean mNativeLibraryReady;
public SearchActivityLocationBarLayout(Context context, AttributeSet attrs) { public SearchActivityLocationBarLayout(Context context, AttributeSet attrs) {
super(context, attrs, R.layout.location_bar_base); super(context, attrs, R.layout.location_bar_base);
...@@ -72,6 +74,8 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout { ...@@ -72,6 +74,8 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout {
@Override @Override
public void onNativeLibraryReady() { public void onNativeLibraryReady() {
super.onNativeLibraryReady(); super.onNativeLibraryReady();
mNativeLibraryReady = true;
setAutocompleteProfile(Profile.getLastUsedRegularProfile()); setAutocompleteProfile(Profile.getLastUsedRegularProfile());
mPendingSearchPromoDecision = LocaleManager.getInstance().needToCheckForSearchEnginePromo(); mPendingSearchPromoDecision = LocaleManager.getInstance().needToCheckForSearchEnginePromo();
...@@ -107,8 +111,9 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout { ...@@ -107,8 +111,9 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout {
* Begins a new query. * Begins a new query.
* @param isVoiceSearchIntent Whether this is a voice search. * @param isVoiceSearchIntent Whether this is a voice search.
* @param optionalText Prepopulate with a query, this may be null. * @param optionalText Prepopulate with a query, this may be null.
* */ */
void beginQuery(boolean isVoiceSearchIntent, @Nullable String optionalText) { @VisibleForTesting
public void beginQuery(boolean isVoiceSearchIntent, @Nullable String optionalText) {
// Clear the text regardless of the promo decision. This allows the user to enter text // Clear the text regardless of the promo decision. This allows the user to enter text
// before native has been initialized and have it not be cleared one the delayed beginQuery // before native has been initialized and have it not be cleared one the delayed beginQuery
// logic is performed. // logic is performed.
...@@ -116,7 +121,7 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout { ...@@ -116,7 +121,7 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout {
UrlBarData.forNonUrlText(optionalText == null ? "" : optionalText), UrlBarData.forNonUrlText(optionalText == null ? "" : optionalText),
UrlBar.ScrollType.NO_SCROLL, SelectionState.SELECT_ALL); UrlBar.ScrollType.NO_SCROLL, SelectionState.SELECT_ALL);
if (mPendingSearchPromoDecision) { if (mPendingSearchPromoDecision || (isVoiceSearchIntent && !mNativeLibraryReady)) {
mPendingBeginQuery = true; mPendingBeginQuery = true;
return; return;
} }
...@@ -126,6 +131,7 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout { ...@@ -126,6 +131,7 @@ public class SearchActivityLocationBarLayout extends LocationBarLayout {
private void beginQueryInternal(boolean isVoiceSearchIntent) { private void beginQueryInternal(boolean isVoiceSearchIntent) {
assert !mPendingSearchPromoDecision; assert !mPendingSearchPromoDecision;
assert !isVoiceSearchIntent || mNativeLibraryReady;
if (getVoiceRecognitionHandler().isVoiceSearchEnabled() && isVoiceSearchIntent) { if (getVoiceRecognitionHandler().isVoiceSearchEnabled() && isVoiceSearchIntent) {
getVoiceRecognitionHandler().startVoiceRecognition( getVoiceRecognitionHandler().startVoiceRecognition(
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
package org.chromium.chrome.browser.searchwidget; package org.chromium.chrome.browser.searchwidget;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.Instrumentation; import android.app.Instrumentation;
...@@ -20,6 +24,8 @@ import org.junit.Before; ...@@ -20,6 +24,8 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus;
import org.chromium.base.Callback; import org.chromium.base.Callback;
...@@ -37,6 +43,7 @@ import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; ...@@ -37,6 +43,7 @@ import org.chromium.chrome.browser.omnibox.MatchClassificationStyle;
import org.chromium.chrome.browser.omnibox.UrlBar; import org.chromium.chrome.browser.omnibox.UrlBar;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion.MatchClassification; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion.MatchClassification;
import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler;
import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
import org.chromium.chrome.browser.searchwidget.SearchActivity.SearchActivityDelegate; import org.chromium.chrome.browser.searchwidget.SearchActivity.SearchActivityDelegate;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
...@@ -137,10 +144,16 @@ public class SearchActivityTest { ...@@ -137,10 +144,16 @@ public class SearchActivityTest {
@Rule @Rule
public MultiActivityTestRule mTestRule = new MultiActivityTestRule(); public MultiActivityTestRule mTestRule = new MultiActivityTestRule();
@Mock
VoiceRecognitionHandler mHandler;
private TestDelegate mTestDelegate; private TestDelegate mTestDelegate;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this);
doReturn(true).when(mHandler).isVoiceSearchEnabled();
mTestDelegate = new TestDelegate(); mTestDelegate = new TestDelegate();
SearchActivity.setDelegateForTests(mTestDelegate); SearchActivity.setDelegateForTests(mTestDelegate);
DefaultSearchEnginePromoDialog.setObserverForTests(mTestDelegate); DefaultSearchEnginePromoDialog.setObserverForTests(mTestDelegate);
...@@ -204,6 +217,38 @@ public class SearchActivityTest { ...@@ -204,6 +217,38 @@ public class SearchActivityTest {
}, url); }, url);
} }
@Test
@SmallTest
public void testVoiceSearchBeforeNativeIsLoaded() throws Exception {
// Wait for the activity to load, but don't let it load the native library.
mTestDelegate.shouldDelayLoadingNative = true;
final SearchActivity searchActivity = startSearchActivity(0, /*isVoiceSearch=*/true);
final SearchActivityLocationBarLayout locationBar =
(SearchActivityLocationBarLayout) searchActivity.findViewById(
R.id.search_location_bar);
locationBar.setVoiceRecognitionHandlerForTesting(mHandler);
locationBar.beginQuery(/* isVoiceSearchIntent= */ true, /* optionalText= */ null);
verify(mHandler, times(0))
.startVoiceRecognition(
VoiceRecognitionHandler.VoiceInteractionSource.SEARCH_WIDGET);
mTestDelegate.shouldDelayNativeInitializationCallback.waitForCallback(0);
Assert.assertEquals(0, mTestDelegate.showSearchEngineDialogIfNeededCallback.getCallCount());
Assert.assertEquals(0, mTestDelegate.onFinishDeferredInitializationCallback.getCallCount());
// Start loading native, then let the activity finish initialization.
TestThreadUtils.runOnUiThreadBlocking(
() -> searchActivity.startDelayedNativeInitialization());
Assert.assertEquals(
1, mTestDelegate.shouldDelayNativeInitializationCallback.getCallCount());
mTestDelegate.showSearchEngineDialogIfNeededCallback.waitForCallback(0);
mTestDelegate.onFinishDeferredInitializationCallback.waitForCallback(0);
verify(mHandler).startVoiceRecognition(
VoiceRecognitionHandler.VoiceInteractionSource.SEARCH_WIDGET);
}
@Test @Test
@SmallTest @SmallTest
public void testTypeBeforeNativeIsLoaded() throws Exception { public void testTypeBeforeNativeIsLoaded() throws Exception {
...@@ -436,7 +481,7 @@ public class SearchActivityTest { ...@@ -436,7 +481,7 @@ public class SearchActivityTest {
OmniboxTestUtils.waitForOmniboxSuggestions(locationBar, OMNIBOX_SHOW_TIMEOUT_MS); OmniboxTestUtils.waitForOmniboxSuggestions(locationBar, OMNIBOX_SHOW_TIMEOUT_MS);
// Start the Activity again by firing another copy of the same Intent. // Start the Activity again by firing another copy of the same Intent.
SearchActivity restartedActivity = startSearchActivity(1); SearchActivity restartedActivity = startSearchActivity(1, /*isVoiceSearch=*/false);
Assert.assertEquals(searchActivity, restartedActivity); Assert.assertEquals(searchActivity, restartedActivity);
// The query should be wiped. // The query should be wiped.
...@@ -450,10 +495,10 @@ public class SearchActivityTest { ...@@ -450,10 +495,10 @@ public class SearchActivityTest {
} }
private SearchActivity startSearchActivity() { private SearchActivity startSearchActivity() {
return startSearchActivity(0); return startSearchActivity(0, /*isVoiceSearch=*/false);
} }
private SearchActivity startSearchActivity(int expectedCallCount) { private SearchActivity startSearchActivity(int expectedCallCount, boolean isVoiceSearch) {
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
ActivityMonitor searchMonitor = ActivityMonitor searchMonitor =
new ActivityMonitor(SearchActivity.class.getName(), null, false); new ActivityMonitor(SearchActivity.class.getName(), null, false);
...@@ -469,7 +514,7 @@ public class SearchActivityTest { ...@@ -469,7 +514,7 @@ public class SearchActivityTest {
// Fire the Intent to start up the SearchActivity. // Fire the Intent to start up the SearchActivity.
Intent intent = new Intent(); Intent intent = new Intent();
SearchWidgetProvider.startSearchActivity(intent, false); SearchWidgetProvider.startSearchActivity(intent, isVoiceSearch);
Activity searchActivity = instrumentation.waitForMonitorWithTimeout( Activity searchActivity = instrumentation.waitForMonitorWithTimeout(
searchMonitor, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL); searchMonitor, CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL);
Assert.assertNotNull("Activity didn't start", searchActivity); Assert.assertNotNull("Activity didn't start", searchActivity);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment