blob: 7cf52d01190e8f0e0a37e0bfe08649e06473c2e1 [file] [log] [blame]
// Copyright 2019 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 androidx.annotation.Nullable;
import org.chromium.base.BundleUtils;
import org.chromium.base.Callback;
import org.chromium.base.Log;
import org.chromium.base.SysUtils;
import org.chromium.chrome.browser.autofill_assistant.metrics.FeatureModuleInstallation;
/**
* Manages the loading of autofill assistant DFM, and provides implementation of
* AutofillAssistantModuleEntry.
*/
public class AutofillAssistantModuleEntryProvider {
private static final String TAG = "AutofillAssistant";
/**
* The real singleton instances. Using an instance instead of static methods allows modifying
* method implementation during tests. Outside of tests, this is the only instance that should
* exist.
*/
static final AutofillAssistantModuleEntryProvider INSTANCE =
new AutofillAssistantModuleEntryProvider();
boolean isInstalled() {
return AutofillAssistantModule.isInstalled();
}
/* Returns the AA module entry, if it is already installed. */
@Nullable
/* package */
AutofillAssistantModuleEntry getModuleEntryIfInstalled() {
if (AutofillAssistantModule.isInstalled()) {
return AutofillAssistantModule.getImpl();
}
return null;
}
/** Gets the AA module entry, installing it if necessary. */
/* package */
void getModuleEntry(Callback<AutofillAssistantModuleEntry> callback,
AssistantModuleInstallUi.Provider moduleInstallUiProvider, boolean showUi) {
AutofillAssistantModuleEntry entry = getModuleEntryIfInstalled();
if (entry != null) {
callback.onResult(entry);
return;
}
loadDynamicModule(callback, moduleInstallUiProvider, showUi);
}
/**
* Maybe trigger a deferred install of the module.
*
* <p>This is public so that it can be used in the Chrome upgrade package. The conditions for
* eligibility are:
*
* <ul>
* <li>This is a Bundle build.
* <li>The autofill_assistant DFM is not installed yet.
* <li>The Android version is L+.
* <li>The device has high disk capacity.
* </ul>
*/
public static void maybeInstallDeferred() {
boolean isNotBundle = !BundleUtils.isBundle();
boolean isInstalled = AutofillAssistantModule.isInstalled();
boolean isNotHighEndDiskDevice = !SysUtils.isHighEndDiskDevice();
if (isNotBundle || isInstalled || isNotHighEndDiskDevice) {
Log.v(TAG,
"Deferred install not triggered: not_bundle=" + isNotBundle
+ ", already_installed=" + isInstalled
+ ", not_high_end_device=" + isNotHighEndDiskDevice);
return;
}
Log.v(TAG, "Deferred install triggered.");
AutofillAssistantMetrics.recordFeatureModuleInstallation(
FeatureModuleInstallation.DFM_BACKGROUND_INSTALLATION_REQUESTED);
AutofillAssistantModule.installDeferred();
}
private static void loadDynamicModule(Callback<AutofillAssistantModuleEntry> callback,
AssistantModuleInstallUi.Provider moduleInstallUiProvider, boolean showUi) {
AssistantModuleInstallUi ui = moduleInstallUiProvider.create((Boolean retry) -> {
if (retry) {
loadDynamicModule(callback, moduleInstallUiProvider, showUi);
} else {
callback.onResult(null);
}
});
if (showUi) {
// Shows toast informing user about install start.
ui.showInstallStartUi();
}
AutofillAssistantModule.install((success) -> {
if (success) {
// Don't show success UI from DFM, transition to Autofill Assistant UI directly.
callback.onResult(AutofillAssistantModule.getImpl());
return;
} else if (showUi) {
// Show inforbar to ask user if they want to retry or cancel.
ui.showInstallFailureUi();
} else {
callback.onResult(null);
}
});
}
}