chromium/components/autofill/android/touch_to_fill_keyboard_suppressor.h

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_AUTOFILL_ANDROID_TOUCH_TO_FILL_KEYBOARD_SUPPRESSOR_H_
#define COMPONENTS_AUTOFILL_ANDROID_TOUCH_TO_FILL_KEYBOARD_SUPPRESSOR_H_

#include "base/memory/weak_ptr.h"
#include "base/scoped_multi_source_observation.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "components/autofill/content/browser/content_autofill_driver_factory.h"
#include "components/autofill/core/browser/autofill_manager.h"

namespace autofill {

class ContentAutofillClient;

// Suppresses the Android IME.
//
// If a TTF surface intends to be displayed, it must suppress the keyboard
// preemptively before Autofill has parsed the form. Otherwise, the keyboard
// could be displayed while Autofill is parsing the form, which would lead to
// flickering.
//
// TouchToFillKeyboardSuppressor takes two callbacks from a TTF controller:
// - `is_showing()` returns true iff the TTF is currently shown;
// - `intends_to_show()` returns true iff the TTF is intended to be shown
//   once parsing is completed.
//
// With TouchToFillKeyboardSuppressor, the controller can implement the
// following behavior:
//
//                  +--------------------------------------------------------+
//                  |      After parsing: controller wants to show TTF?      |
//                  +--------------------------+-----------------------------+
//                  |            No            |            Yes              |
// +----------+-----+--------------------------+-----------------------------+
// | Before   | No  |                   Don't suppress.                      |
// | parsing: |     |                   Don't show TTF.                      |
// | con-     +-----+--------------------------+-----------------------------+
// | troller  | Yes | Suppress before parsing. | Suppress before parsing.    |
// | intends  |     | Unsuppress after parsing | Unsuppress after timeout if |
// | to show  |     | or after timeout.        | parsing is slow. Otherwise, |
// | TTF?     |     | Don't show TTF.          | show TTF, then unsuppress.  |
// +----------+-----+--------------------------+-----------------------------+
//
// The timeout mechanism is intended for cases where parsing takes extremely
// long.
//
// The TTF controller  must satisfy the following conditions:
// - The `is_showing()` callback must be true after parsing only if
//   `is_showing() || intends_to_show()` has been true before parsing.
// - The TTF controller must show the TTF only if `is_suppressing()` is true.
// - The TTF controller must call `Unsuppress()` after the TTF was shown.
//
// The lifecycle of a TouchToFillKeyboardSuppressor must be aligned to the
// lifecycle of a tab (represented here by a ContentAutofillClient).
// It must be created before any ContentAutofillDrivers of the tab have been
// created: it won't suppress the keyboard in frames that were created already.
//
// TouchToFillKeyboardSuppressor observes all AutofillManagers of a given tab
// (represented by the ContentAutofillClient). The event structure is this:
// 1. AutofillManager::Observer::OnBeforeAskForValuesToFill().
// 2. Asynchronous parsing.
// 3. Controller's shows TTF only if
//    - `intends_to_show()` had been true in Step 1, and
//    - `is_suppressing()` is true now.
// 4. AutofillManager::Observer::OnAfterAskForValuesToFill().
class TouchToFillKeyboardSuppressor
    : public ContentAutofillDriverFactory::Observer,
      public AutofillManager::Observer {};

}  // namespace autofill

#endif  // COMPONENTS_AUTOFILL_ANDROID_TOUCH_TO_FILL_KEYBOARD_SUPPRESSOR_H_