Touch-to-Search is a feature that allows a Chrome user to quickly run Google searches by touching the text they wish to search for on a web page they are viewing. The search results are displayed in an overlay that can be “promoted” into a new tab if the user desires.
The original name for Touch-to-Search was “Contextual Search”, and usage of that name persists in many contexts, including all of the class names in this code.
Touch-to-Search was available in a limited Finch trial on iOS phone devices in M41-44, and will be available to all users (phone and tablet) in M49. It is also available via chrome://flags
.
Cr-UI-Browser-Mobile-TouchToSearch
Generally speaking, a touch-to-search interaction goes through some or all of the following phases, and the transitions between each phase are asynchronous.
There is a slightly different flow of states for when the user long-presses on a word on the web page, initiating an iOS text selection.
Additionally, during or between many of these phases, the user may be interacting with the touch-to-search panel, changing its position.
Touch detection is handled both by native code and injected javascript. Broadly speaking, detection happens as follows:
UITapGestureRecognizer
to the current tab's web view.handleTapAtPoint()
is called. This method determines if the tap was inside a plain text word.This takes the Touch-to-Search system from the Touch to Dispatch phases as described in Behavior, above.
(There are numerous complicating factors inside this sequence; they are detailed in sections below.)
In order to highlight text on the web page, Touch-to-Search inserts (via the JavaScript component) HTML and CSS. So that this DOM modification doesn't interfere with other DOM modifications performed by Chrome (for example, find-in-page highlighting), tap processing is performed after obtaining a DOM mutation lock on the page.
Some pages may dynamically adjust the page in response to a tap (for example, a non-native drop-down menu may be implemented this way). In order to give a page time to update in response to a tap, tap processing is delayed by (currently) 800ms.
Tapping on sections of a page that have recently been changed doesn't trigger touch-to-search, again on the assumption that a recently-updated part of the page is actually a control updating in response to the tap. To detect this, each DOM modification on the page is observed via a JavaScript MutationObserver. For each mutation, the time and the mutated DOM element are recorded. Taps that are in elements contained by or containing elements modified since the original native tap event are rejected. In conjunction with the tap processing delay (above), this is implemented by checking for DOM elements modified as long ago as the tap processing was delayed.
The list of modified DOM elements is cleared of records older than the 800ms tap delay every time a mutation occurs, but not more frequently than the tap delay.
The Touch-to-Search UI consists of the following views, which appear above the active tab:
ContextualSearchPanelView
), which contains the other views and moves up and down in response to user gestures.ContextualSearchHeaderView
), which displays the tapped word and its context, and other UI elements.The panel can be in several different positions relative to the current tab. The panel's horizontal position never varies; it is always the width of the tab. Vertically, the panel can be in any of four position. These are named differently on iOS and Android; Android names are in parenthesis. (At some point iOS will standardize on the Android names).
Position | Description |
---|---|
DISMISSED (CLOSED ) | Panel is offscreen, just below the current tab, |
PEEKING (PEEKED ) | Panel is showing only the header at the bottom of the tab. |
PREVIEWING (EXPANDED ) | Panel covers 2/3 of the tab, showing most of the search results. |
COVERING (MAXIMIZED ) | Panel covers the entire tab, so the header overlaps the toolbar. |
The header is the main piece of UI for touch-to-search. It shows the currently active search term, indicates the progress of the search term resolution, shows the “Google G” for brand identification, and shows a control that hints as to how to expand/dismiss the panel.
Animations use standard material animation durations:
Animation | Duration |
---|---|
Panel movement (non-dismissing) | 0.35s |
Panel dismissal | 0.25s |
Text and other transitions | 0.25s |
PEEKING
to PREVIEWING
As the panel moves from PEEKING
to PREVIEWING
(whether dragged or animated), the following animations occur:
PREVIEWING
to COVERING
When touch-to-search is initiated (assuming the panel is DISMISSED
):
PEEKING
(0.35s). The header is in the “initial” state.(Total animation time: 0.85s)
These animations aren't preempted even if resolution occurs after they complete.
The G-logo iris effect is implemented by adding a circular alpha channel layer as a mask to the G-logo image view; this mask layer is initially scaled to be very small, and has its transform animated to scale up and reveal the logo.
There is currently no animation during dispatch.
When resolution occurs: