blob: 6c15c5b5c3b310a68d4102d6b1a97c8150318c78 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.autofill_assistant;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.content_public.browser.WebContents;
/**
* Bridge to native side autofill_assistant::UiControllerAndroid. It allows native side to control
* Autofill Assistant related UIs and forward UI events to native side.
* This controller is purely a translation and forwarding layer between Native side and the
* different Java coordinators.
*/
@JNINamespace("autofill_assistant")
// TODO(crbug.com/806868): This class should be removed once all logic is in native side and the
// model is directly modified by the native AssistantMediator.
class AutofillAssistantUiController implements AssistantCoordinator.Delegate {
private long mNativeUiController;
private final AssistantCoordinator mCoordinator;
@CalledByNative
private static AutofillAssistantUiController createAndStartUi(
WebContents webContents, long nativeUiController) {
return new AutofillAssistantUiController(
ChromeActivity.fromWebContents(webContents), webContents, nativeUiController);
}
private AutofillAssistantUiController(
ChromeActivity activity, WebContents webContents, long nativeUiController) {
mNativeUiController = nativeUiController;
mCoordinator = new AssistantCoordinator(activity, webContents, this);
initForCustomTab(activity);
}
private void initForCustomTab(ChromeActivity activity) {
if (!(activity instanceof CustomTabActivity)) {
return;
}
Tab activityTab = activity.getActivityTab();
activityTab.addObserver(new EmptyTabObserver() {
@Override
public void onActivityAttachmentChanged(Tab tab, boolean isAttached) {
if (!isAttached) {
activityTab.removeObserver(this);
mCoordinator.shutdownImmediately(DropOutReason.TAB_DETACHED);
}
}
});
// Shut down Autofill Assistant when the selected tab (foreground tab) is changed.
TabModel currentTabModel = activity.getTabModelSelector().getCurrentModel();
currentTabModel.addObserver(new EmptyTabModelObserver() {
@Override
public void didSelectTab(Tab tab, int type, int lastId) {
// Shutdown the Autofill Assistant if the user switches to another tab.
if (!activityTab.equals(tab)) {
currentTabModel.removeObserver(this);
mCoordinator.gracefulShutdown(
/* showGiveUpMessage= */ true, DropOutReason.TAB_CHANGED);
}
}
});
}
/**
* Java => native methods.
*/
@Override
public void stop() {
safeNativeStop();
}
/**
* Native => Java methods.
*/
// TODO(crbug.com/806868): Some of these functions still have a little bit of logic (e.g. make
// the progress bar pulse when hiding overlay). Maybe it would be better to forward all calls to
// AssistantCoordinator (that way this bridge would only have a reference to that one) which in
// turn will forward calls to the other sub coordinators. The main reason this is not done yet
// is to avoid boilerplate.
@CalledByNative
private AssistantModel getModel() {
return mCoordinator.getModel();
}
@CalledByNative
private void clearNativePtr() {
mNativeUiController = 0;
}
@CalledByNative
private void onShutdown(@DropOutReason int reason) {
mCoordinator.shutdownImmediately(reason);
}
@CalledByNative
private void onShutdownGracefully(@DropOutReason int reason) {
mCoordinator.gracefulShutdown(/* showGiveUpMessage= */ false, reason);
}
@CalledByNative
private void onClose() {
mCoordinator.close();
}
@CalledByNative
private void onShowOnboarding(Runnable onAccept) {
mCoordinator.showOnboarding(onAccept);
}
@CalledByNative
private void expandBottomSheet() {
mCoordinator.getBottomBarCoordinator().expand();
}
@CalledByNative
private void showFeedback(String debugContext) {
mCoordinator.showFeedback(debugContext);
}
@CalledByNative
private void dismissAndShowSnackbar(String message, @DropOutReason int reason) {
mCoordinator.dismissAndShowSnackbar(message, reason);
}
// Native methods.
void safeNativeStop() {
if (mNativeUiController != 0) nativeStop(mNativeUiController);
}
private native void nativeStop(long nativeUiControllerAndroid);
}