First draft of Query in Omnibox.

This CL provides a functional version of the query in omnibox
functionality, hidden behind a flag. Tests for the new functionality are
also included in LocationBarLayoutTest.

Further input from UX/security is required at this point.

Bug: 776988
Change-Id: I2f45df924ebf0caeacdccd1384bbf18d9facf791
Reviewed-on: https://chromium-review.googlesource.com/902929
Commit-Queue: Troy Hildebrandt <[email protected]>
Reviewed-by: Ted Choc <[email protected]>
Reviewed-by: Maria Khomenko <[email protected]>
Cr-Commit-Position: refs/heads/master@{#538902}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index e38aab5a..5cc944ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -248,6 +248,7 @@
     public static final String SOLE_INTEGRATION = "SoleIntegration";
     public static final String SOUND_CONTENT_SETTING = "SoundContentSetting";
     public static final String SPANNABLE_INLINE_AUTOCOMPLETE = "SpannableInlineAutocomplete";
+    public static final String QUERY_IN_OMNIBOX = "QueryInOmnibox";
     public static final String TAB_REPARENTING = "TabReparenting";
     public static final String TRUSTED_WEB_ACTIVITY = "TrustedWebActivity";
     public static final String VIDEO_PERSISTENCE = "VideoPersistence";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
index 5746f0c..a738d4c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -1349,9 +1349,11 @@
         } else {
             // For the default toolbar color, use a green or red icon.
             if (securityLevel == ConnectionSecurityLevel.DANGEROUS) {
+                assert !provider.isDisplayingQueryTerms();
                 list = ApiCompatibilityUtils.getColorStateList(resources, R.color.google_red_700);
-            } else if (securityLevel == ConnectionSecurityLevel.SECURE
-                    || securityLevel == ConnectionSecurityLevel.EV_SECURE) {
+            } else if (!provider.isDisplayingQueryTerms()
+                    && (securityLevel == ConnectionSecurityLevel.SECURE
+                               || securityLevel == ConnectionSecurityLevel.EV_SECURE)) {
                 list = ApiCompatibilityUtils.getColorStateList(resources, R.color.google_green_700);
             } else {
                 list = ApiCompatibilityUtils.getColorStateList(resources, R.color.dark_mode_tint);
@@ -2192,7 +2194,7 @@
     }
 
     /**
-     * Changes the text on the url bar
+     * Changes the text on the url bar.
      * @param originalText The original text (URL or search terms) for copy/cut.
      * @param displayText The text (URL or search terms) for user display.
      * @return Whether the URL was changed as a result of this call.
@@ -2303,7 +2305,7 @@
 
     /**
      * Update the location bar visuals based on a loading state change.
-     * @param updateUrl Whether to update the URL as a result of the this call.
+     * @param updateUrl Whether to update the URL as a result of this call.
      */
     @Override
     public void updateLoadingState(boolean updateUrl) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
index b778ffb..9a984fe6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -629,18 +629,16 @@
     /**
      * Sets the text content of the URL bar.
      *
-     * @param url The original URL (or generic text) that can be used for copy/cut/paste.
-     * @param formattedUrl Formatted URL for user display. Null if there isn't one.
+     * @param pageUrl The original URL (or generic text) that can be used for copy/cut/paste.
+     * @param displayText Formatted URL or alternate text for user display. Null if there isn't one.
      * @return Whether the visible text has changed.
      */
-    public boolean setUrl(String url, String formattedUrl) {
-        if (!TextUtils.isEmpty(formattedUrl)) {
+    public boolean setUrl(String pageUrl, String displayText) {
+        if (!TextUtils.isEmpty(displayText)) {
             try {
-                URL javaUrl = new URL(url);
-                mFormattedUrlLocation =
-                        getUrlContentsPrePath(formattedUrl, javaUrl.getHost());
-                mOriginalUrlLocation =
-                        getUrlContentsPrePath(url, javaUrl.getHost());
+                URL javaUrl = new URL(pageUrl);
+                mFormattedUrlLocation = getUrlContentsPrePath(displayText, javaUrl.getHost());
+                mOriginalUrlLocation = getUrlContentsPrePath(pageUrl, javaUrl.getHost());
             } catch (MalformedURLException mue) {
                 mOriginalUrlLocation = null;
                 mFormattedUrlLocation = null;
@@ -648,11 +646,11 @@
         } else {
             mOriginalUrlLocation = null;
             mFormattedUrlLocation = null;
-            formattedUrl = url;
+            displayText = pageUrl;
         }
 
         Editable previousText = getEditableText();
-        setText(formattedUrl);
+        setText(displayText);
 
         boolean textChanged = !TextUtils.equals(previousText, getEditableText());
         if (textChanged && !isFocused()) scrollToTLD();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
index 5ae473c..df1817ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/TemplateUrlService.java
@@ -435,6 +435,15 @@
         return nativeGetSearchEngineUrlFromTemplateUrl(mNativeTemplateUrlServiceAndroid, keyword);
     }
 
+    /**
+     * Extracts the search query terms from a SRP URL.
+     * @param url The SRP URL.
+     * @return A string containing just the search terms stripped from the SRP URL.
+     */
+    public String extractSearchTermsFromUrl(String url) {
+        return nativeExtractSearchTermsFromUrl(mNativeTemplateUrlServiceAndroid, url);
+    }
+
     @VisibleForTesting
     public String addSearchEngineForTesting(String keyword, int ageInDays) {
         return nativeAddSearchEngineForTesting(
@@ -477,4 +486,6 @@
             long nativeTemplateUrlServiceAndroid, String keyword, int offset);
     private native String nativeUpdateLastVisitedForTesting(
             long nativeTemplateUrlServiceAndroid, String keyword);
+    private native String nativeExtractSearchTermsFromUrl(
+            long nativeTemplateUrlServiceAndroid, String url);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
index fe3c43c..2ec619c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java
@@ -109,4 +109,9 @@
     public int getSecurityIconResource() {
         return 0;
     }
+
+    @Override
+    public boolean isDisplayingQueryTerms() {
+        return false;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
index c160fd91..1be231c5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarDataProvider.java
@@ -107,4 +107,9 @@
      */
     @DrawableRes
     int getSecurityIconResource();
+
+    /**
+     * @return Whether or not we're currently showing a search query instead of a URL.
+     */
+    boolean isDisplayingQueryTerms();
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
index a7e8f81..eeb12fe 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarLayout.java
@@ -232,6 +232,11 @@
             public int getSecurityIconResource() {
                 return 0;
             }
+
+            @Override
+            public boolean isDisplayingQueryTerms() {
+                return false;
+            }
         };
 
         // Set menu button background in case it was previously called before inflation
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index 4e22f33..75d83f8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -26,6 +26,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.NativePage;
 import org.chromium.chrome.browser.TabLoadStatus;
@@ -179,6 +180,8 @@
     private boolean mShouldUpdateToolbarPrimaryColor = true;
     private int mCurrentThemeColor;
 
+    private boolean mQueryInOmniboxEnabled;
+
     /**
      * Creates a ToolbarManager object.
      *
@@ -318,6 +321,16 @@
 
                 assert tab == mToolbarModel.getTab();
                 mLocationBar.updateSecurityIcon();
+
+                // If the SSL state was updated while the location bar is display a DSE URL and
+                // the query in omnibox feature is enabled, update the URL to be on the safe side,
+                // as we may be showing query terms when we should now be showing the full URL for
+                // security.
+                if (mQueryInOmniboxEnabled
+                        && TemplateUrlService.getInstance()
+                                   .isSearchResultsPageFromDefaultSearchProvider(tab.getUrl())) {
+                    mLocationBar.setUrlToPageUrl();
+                }
             }
 
             @Override
@@ -880,6 +893,8 @@
         refreshSelectedTab();
         if (mTabModelSelector.isTabStateInitialized()) mTabRestoreCompleted = true;
         handleTabRestoreCompleted();
+
+        mQueryInOmniboxEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_IN_OMNIBOX);
     }
 
     private void handleTabRestoreCompleted() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
index 6454ebf8..8c31707 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarModelImpl.java
@@ -35,13 +35,16 @@
 /**
  * Contains the data and state for the toolbar.
  */
-class ToolbarModelImpl extends ToolbarModel implements ToolbarDataProvider, ToolbarModelDelegate {
+@VisibleForTesting
+public class ToolbarModelImpl
+        extends ToolbarModel implements ToolbarDataProvider, ToolbarModelDelegate {
     private final BottomSheet mBottomSheet;
     private final boolean mUseModernDesign;
     private Tab mTab;
     private boolean mIsIncognito;
     private int mPrimaryColor;
     private boolean mIsUsingBrandColor;
+    private boolean mQueryInOmniboxEnabled;
 
     /**
      * Default constructor for this class.
@@ -62,6 +65,7 @@
      */
     public void initializeWithNative() {
         initialize(this);
+        mQueryInOmniboxEnabled = ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_IN_OMNIBOX);
     }
 
     @Override
@@ -144,6 +148,10 @@
             String originalUrl = mTab.getOriginalUrl();
             displayText = OfflinePageUtils.stripSchemeFromOnlineUrl(
                   DomDistillerTabUtils.getFormattedUrlFromOriginalDistillerUrl(originalUrl));
+        } else {
+            String searchTerms = extractSearchTermsFromUrl(url);
+            // Show the search terms in the omnibox instead of the URL if this is a DSE search URL.
+            if (searchTerms != null) displayText = searchTerms;
         }
 
         return displayText;
@@ -265,6 +273,11 @@
 
     @Override
     public int getSecurityIconResource() {
+        // If we're showing a query in the omnibox, and the security level is high enough to show
+        // the search icon, return that instead of the security icon.
+        if (isDisplayingQueryTerms()) {
+            return R.drawable.ic_search;
+        }
         return getSecurityIconResource(
                 getSecurityLevel(), !DeviceFormFactor.isTablet(), isOfflinePage());
     }
@@ -310,4 +323,34 @@
                 && ChromeFeatureList.isInitialized()
                 && ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_HOME_CLEAR_URL_ON_OPEN);
     }
+
+    @Override
+    public boolean isDisplayingQueryTerms() {
+        return extractSearchTermsFromUrl(getCurrentUrl()) != null;
+    }
+
+    private boolean securityLevelSafeForQueryInOmnibox() {
+        int securityLevel = getSecurityLevel();
+        return securityLevel == ConnectionSecurityLevel.SECURE
+                || securityLevel == ConnectionSecurityLevel.EV_SECURE;
+    }
+
+    /**
+     * Extracts query terms from a URL if it's a SRP URL from the default search engine.
+     *
+     * @param url The URL to extract search terms from.
+     * @return The search terms. Returns null if not a DSE SRP URL or there are no search terms to
+     *         extract, if query in omnibox is disabled, or if the security level is insufficient to
+     *         display search terms in place of SRP URL.
+     */
+    private String extractSearchTermsFromUrl(String url) {
+        boolean shouldShowSearchTerms =
+                mQueryInOmniboxEnabled && securityLevelSafeForQueryInOmnibox();
+        if (!shouldShowSearchTerms) return null;
+        String searchTerms = TemplateUrlService.getInstance().extractSearchTermsFromUrl(url);
+        if (!TextUtils.isEmpty(searchTerms)) {
+            return searchTerms;
+        }
+        return null;
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
index 36017f4..8cdb5bb2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/LocationBarLayoutTest.java
@@ -15,6 +15,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
@@ -22,16 +23,20 @@
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.ChromeFeatureList;
 import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.search_engines.TemplateUrlService;
+import org.chromium.chrome.browser.toolbar.ToolbarModelImpl;
 import org.chromium.chrome.browser.widget.TintedImageButton;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
+import org.chromium.components.security_state.ConnectionSecurityLevel;
 import org.chromium.ui.test.util.UiRestriction;
 
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
 
 /**
  * Unit tests for {@link LocationBarLayout}.
@@ -46,9 +51,82 @@
     @Rule
     public TestRule mProcessor = new Features.InstrumentationProcessor();
 
+    private static final int SEARCH_ICON_RESOURCE = R.drawable.ic_search;
+
+    private static final String SEARCH_TERMS = "machine learning";
+    private static final String GOOGLE_SRP_URL = "https://www.google.com/search?q=machine+learning";
+    private static final String BING_SRP_URL = "https://www.bing.com/search?q=machine+learning";
+
+    private TestToolbarModel mTestToolbarModel;
+
+    private class TestToolbarModel extends ToolbarModelImpl {
+        private String mCurrentUrl;
+        private Integer mSecurityLevel;
+
+        public TestToolbarModel() {
+            super(null /* bottomSheet */, false /* useModernDesign */);
+            initializeWithNative();
+        }
+
+        void setCurrentUrl(String url) {
+            mCurrentUrl = url;
+        }
+
+        void setSecurityLevel(@ConnectionSecurityLevel int securityLevel) {
+            mSecurityLevel = securityLevel;
+        }
+
+        @Override
+        public String getCurrentUrl() {
+            if (mCurrentUrl == null) return super.getCurrentUrl();
+            return mCurrentUrl;
+        }
+
+        @Override
+        @ConnectionSecurityLevel
+        public int getSecurityLevel() {
+            if (mSecurityLevel == null) return super.getSecurityLevel();
+            return mSecurityLevel;
+        }
+
+        @Override
+        public boolean shouldShowGoogleG(String urlBarText) {
+            return false;
+        }
+    }
+
     @Before
     public void setUp() throws InterruptedException {
         mActivityTestRule.startMainActivityOnBlankPage();
+        mTestToolbarModel = new TestToolbarModel();
+        mTestToolbarModel.setTab(mActivityTestRule.getActivity().getActivityTab(), false);
+        getLocationBar().setToolbarDataProvider(mTestToolbarModel);
+    }
+
+    private void setUrlToPageUrl(LocationBarLayout locationBar) {
+        ThreadUtils.runOnUiThreadBlocking(() -> { getLocationBar().updateLoadingState(true); });
+    }
+
+    // Partially lifted from TemplateUrlServiceTest.
+    private void setSearchEngine(String keyword)
+            throws ExecutionException, InterruptedException, TimeoutException {
+        CallbackHelper callback = new CallbackHelper();
+        Callable<Void> setSearchEngineCallable = new Callable<Void>() {
+            @Override
+            public Void call() {
+                TemplateUrlService.getInstance().runWhenLoaded(() -> {
+                    TemplateUrlService.getInstance().setSearchEngine(keyword);
+                    callback.notifyCalled();
+                });
+                return null;
+            }
+        };
+        ThreadUtils.runOnUiThreadBlocking(setSearchEngineCallable);
+        callback.waitForCallback("Failed to set search engine", 0);
+    }
+
+    private UrlBar getUrlBar() {
+        return (UrlBar) mActivityTestRule.getActivity().findViewById(R.id.url_bar);
     }
 
     private LocationBarLayout getLocationBar() {
@@ -63,6 +141,11 @@
         return (TintedImageButton) mActivityTestRule.getActivity().findViewById(R.id.mic_button);
     }
 
+    private TintedImageButton getSecurityButton() {
+        return (TintedImageButton) mActivityTestRule.getActivity().findViewById(
+                R.id.security_button);
+    }
+
     private void setUrlBarTextAndFocus(String text)
             throws ExecutionException, InterruptedException {
         ThreadUtils.runOnUiThreadBlocking(new Callable<Void>() {
@@ -126,4 +209,107 @@
         Assert.assertNotEquals(getDeleteButton().getVisibility(), View.VISIBLE);
         Assert.assertEquals(getMicButton().getVisibility(), View.VISIBLE);
     }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.QUERY_IN_OMNIBOX)
+    @Feature({"QueryInOmnibox"})
+    public void testIsOnlyShowingSearchTermsIfSrpIsGoogle() {
+        final UrlBar urlBar = getUrlBar();
+        final LocationBarLayout locationBar = getLocationBar();
+
+        mTestToolbarModel.setCurrentUrl(GOOGLE_SRP_URL);
+        mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
+        setUrlToPageUrl(locationBar);
+
+        Assert.assertEquals(SEARCH_TERMS, urlBar.getText().toString());
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.QUERY_IN_OMNIBOX)
+    @Feature({"QueryInOmnibox"})
+    public void testIsOnlyShowingSearchTermsIfSrpIsBing()
+            throws ExecutionException, InterruptedException, TimeoutException {
+        final UrlBar urlBar = getUrlBar();
+        final LocationBarLayout locationBar = getLocationBar();
+
+        setSearchEngine("bing.com");
+        mTestToolbarModel.setCurrentUrl(BING_SRP_URL);
+        mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
+        setUrlToPageUrl(locationBar);
+
+        Assert.assertEquals(SEARCH_TERMS, urlBar.getText().toString());
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.QUERY_IN_OMNIBOX)
+    @Feature({"QueryInOmnibox"})
+    public void testIsNotShowingSearchTermsIfSrpIsBingAndSrpUrlIsGoogle()
+            throws ExecutionException, InterruptedException, TimeoutException {
+        final UrlBar urlBar = getUrlBar();
+        final LocationBarLayout locationBar = getLocationBar();
+
+        setSearchEngine("bing.com");
+        mTestToolbarModel.setCurrentUrl(GOOGLE_SRP_URL);
+        mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
+        setUrlToPageUrl(locationBar);
+
+        Assert.assertNotEquals(SEARCH_TERMS, urlBar.getText().toString());
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.QUERY_IN_OMNIBOX)
+    @Feature({"QueryInOmnibox"})
+    public void testNotShowingSearchIconOnMixedContent() {
+        final UrlBar urlBar = getUrlBar();
+        final LocationBarLayout locationBar = getLocationBar();
+
+        mTestToolbarModel.setCurrentUrl(GOOGLE_SRP_URL);
+        mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.NONE);
+        setUrlToPageUrl(locationBar);
+
+        TintedImageButton securityButton = getSecurityButton();
+        Assert.assertNotEquals(SEARCH_TERMS, urlBar.getText().toString());
+        ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> Assert.assertNotEquals(
+                                mTestToolbarModel.getSecurityIconResource(), SEARCH_ICON_RESOURCE));
+    }
+
+    @Test
+    @SmallTest
+    @EnableFeatures(ChromeFeatureList.QUERY_IN_OMNIBOX)
+    @Feature({"QueryInOmnibox"})
+    public void testIsShowingSearchIconSecureContent() {
+        final LocationBarLayout locationBar = getLocationBar();
+
+        mTestToolbarModel.setCurrentUrl(GOOGLE_SRP_URL);
+        mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
+        setUrlToPageUrl(locationBar);
+
+        TintedImageButton securityButton = getSecurityButton();
+        Assert.assertEquals(securityButton.getVisibility(), View.VISIBLE);
+        ThreadUtils.runOnUiThreadBlocking(
+                ()
+                        -> Assert.assertEquals(
+                                mTestToolbarModel.getSecurityIconResource(), SEARCH_ICON_RESOURCE));
+    }
+
+    @Test
+    @SmallTest
+    @DisableFeatures(ChromeFeatureList.QUERY_IN_OMNIBOX)
+    @Feature({"QueryInOmnibox"})
+    public void testNotShowingSearchTermsIfSrpIsGoogleAndFlagIsDisabled() {
+        final UrlBar urlBar = getUrlBar();
+        final LocationBarLayout locationBar = getLocationBar();
+
+        mTestToolbarModel.setCurrentUrl(GOOGLE_SRP_URL);
+        mTestToolbarModel.setSecurityLevel(ConnectionSecurityLevel.SECURE);
+        setUrlToPageUrl(locationBar);
+
+        Assert.assertNotEquals(SEARCH_TERMS, urlBar.getText().toString());
+    }
 }
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
index 2482f11..b389ec9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -66,12 +66,12 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @CommandLineParameter({"", "disable-features=" + ChromeFeatureList.SPANNABLE_INLINE_AUTOCOMPLETE})
 public class UrlBarTest {
-    // 9000+ chars of goodness
 
     @Rule
     public ChromeActivityTestRule<ChromeActivity> mActivityTestRule =
             new ChromeActivityTestRule<>(ChromeActivity.class);
 
+    // 9000+ chars of goodness
     private static final String HUGE_URL =
             "data:text/plain,H"
             + new String(new char[9000]).replace('\0', 'u')
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index d628073..3c75370 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3770,6 +3770,12 @@
      SINGLE_VALUE_TYPE(chromeos::switches::kNewWallpaperPicker)},
 #endif  // OS_CHROMEOS
 
+#if defined(OS_ANDROID)
+    {"enable-query-in-omnibox", flag_descriptions::kQueryInOmniboxName,
+     flag_descriptions::kQueryInOmniboxDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kQueryInOmnibox)},
+#endif  // OS_ANDROID
+
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 9567c3b0..c93606d9 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -110,6 +110,7 @@
     &kProgressBarThrottleFeature,
     &kPwaImprovedSplashScreen,
     &kPwaPersistentNotification,
+    &kQueryInOmnibox,
     &kReaderModeInCCT,
     &kSearchEnginePromoExistingDevice,
     &kSearchEnginePromoNewDevice,
@@ -343,6 +344,9 @@
 const base::Feature kPwaPersistentNotification{
     "PwaPersistentNotification", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kQueryInOmnibox{"QueryInOmnibox",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kReaderModeInCCT{"ReaderModeInCCT",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index 0fdd63c..0d5b7e31 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -5,10 +5,9 @@
 #ifndef CHROME_BROWSER_ANDROID_CHROME_FEATURE_LIST_H_
 #define CHROME_BROWSER_ANDROID_CHROME_FEATURE_LIST_H_
 
+#include <base/feature_list.h>
 #include <jni.h>
 
-#include "base/feature_list.h"
-
 namespace chrome {
 namespace android {
 
@@ -72,6 +71,7 @@
 extern const base::Feature kProgressBarThrottleFeature;
 extern const base::Feature kPwaImprovedSplashScreen;
 extern const base::Feature kPwaPersistentNotification;
+extern const base::Feature kQueryInOmnibox;
 extern const base::Feature kReaderModeInCCT;
 extern const base::Feature kSoleIntegration;
 extern const base::Feature kSpannableInlineAutocomplete;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index ba354c1..8e66ee3 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1220,6 +1220,11 @@
     "running after the last window is closed, and to launch at OS startup, if "
     "the Push API needs it.";
 
+const char kQueryInOmniboxName[] = "Query in Omnibox";
+const char kQueryInOmniboxDescription[] =
+    "Only display query terms in the omnibox when viewing a search results "
+    "page.";
+
 const char kQuicName[] = "Experimental QUIC protocol";
 const char kQuicDescription[] = "Enable experimental QUIC protocol support.";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 2a752b5..b915dc9 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -758,6 +758,9 @@
 extern const char kPushApiBackgroundModeName[];
 extern const char kPushApiBackgroundModeDescription[];
 
+extern const char kQueryInOmniboxName[];
+extern const char kQueryInOmniboxDescription[];
+
 extern const char kQuicName[];
 extern const char kQuicDescription[];
 
diff --git a/chrome/browser/search_engines/template_url_service_android.cc b/chrome/browser/search_engines/template_url_service_android.cc
index 2e5abc0..927aa93 100644
--- a/chrome/browser/search_engines/template_url_service_android.cc
+++ b/chrome/browser/search_engines/template_url_service_android.cc
@@ -407,6 +407,21 @@
   return base::android::ConvertUTF16ToJavaString(env, t_url->data().keyword());
 }
 
+base::android::ScopedJavaLocalRef<jstring>
+TemplateUrlServiceAndroid::ExtractSearchTermsFromUrl(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    const base::android::JavaParamRef<jstring>& jurl) {
+  base::string16 search_terms;
+  const TemplateURL* default_search_provider =
+      template_url_service_->GetDefaultSearchProvider();
+  bool has_search_terms = default_search_provider->ExtractSearchTermsFromURL(
+      GURL(base::android::ConvertJavaStringToUTF8(jurl)),
+      template_url_service_->search_terms_data(), &search_terms);
+  return base::android::ConvertUTF16ToJavaString(
+      env, (has_search_terms ? search_terms : base::string16()));
+}
+
 static jlong JNI_TemplateUrlService_Init(JNIEnv* env,
                                          const JavaParamRef<jobject>& obj) {
   TemplateUrlServiceAndroid* template_url_service_android =
diff --git a/chrome/browser/search_engines/template_url_service_android.h b/chrome/browser/search_engines/template_url_service_android.h
index 85c29e4..7cd432fa 100644
--- a/chrome/browser/search_engines/template_url_service_android.h
+++ b/chrome/browser/search_engines/template_url_service_android.h
@@ -86,6 +86,10 @@
   void SetFilteringEnabled(JNIEnv* env,
                            const base::android::JavaParamRef<jobject>& obj,
                            jboolean filtering_enabled);
+  base::android::ScopedJavaLocalRef<jstring> ExtractSearchTermsFromUrl(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      const base::android::JavaParamRef<jstring>& jurl);
 
   // Adds a custom search engine, sets |jkeyword| as its short_name and keyword,
   // and sets its date_created as |age_in_days| days before the current time.
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 1c997db..e48b107 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -25803,6 +25803,7 @@
       label="OmniboxUIExperimentHideSteadyStateUrlSchemeAndSubdomains:disabled"/>
   <int value="-1285021473" label="save-page-as-mhtml"/>
   <int value="-1284637134" label="pull-to-refresh"/>
+  <int value="-1278796760" label="QueryInOmnibox:enabled"/>
   <int value="-1276912933" label="enable-quick-unlock-pin"/>
   <int value="-1271563519" label="enable-appcontainer"/>
   <int value="-1269084216" label="ash-md"/>
@@ -26817,6 +26818,7 @@
   <int value="1272699563" label="enable-hosted-mode"/>
   <int value="1275507565" label="OfflinePagesRenovations:enabled"/>
   <int value="1276209777" label="ntp-switch-to-existing-tab"/>
+  <int value="1277386636" label="QueryInOmnibox:disabled"/>
   <int value="1279584261" label="enable-carrier-switching"/>
   <int value="1280614081" label="show-overdraw-feedback"/>
   <int value="1283908088" label="ImprovedLanguageSettings:disabled"/>