Commit a0badbb2 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Mfill Android] Ensure integration tests cover the native component

This change tries to use more of the Chrome stack for our integration
tests. This might catch errors in the bridge that previously let compile
failures slip.
This *might* increase robustness because the calls of the native bridge
are now correct and don't have to be replaced anymore. This caused some
weird cases where the bridge would say: display nothing and the test
quickly called *DO* display something.

The overhead shouldn't increase much, since we don't actually load the
test data from the render but instead fill the cache of the native part
of the component.
This allows the native side to behave naturally and even fill tapped
suggestions as it normally would.

A small clean-up that supported this change: the EmbeddedTestServer
allows loading html pages which provides an IP as origin instead of
a data url.

Bug: 913888, 894428, 922131, 920901
Change-Id: Ib2c09ed386354965ccdaf2f44ca1aafd218fd018
Reviewed-on: https://chromium-review.googlesource.com/c/1448233
Commit-Queue: Friedrich [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarFabio Tirelo <ftirelo@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Cr-Commit-Position: refs/heads/master@{#629964}
parent 7a2943f7
......@@ -739,6 +739,7 @@ android_library("chrome_test_java") {
"//chrome/test/data/navigation_interception/",
"//chrome/test/data/notifications/",
"//chrome/test/data/offline_pages/",
"//chrome/test/data/password/",
"//chrome/test/data/popup_blocker/",
"//chrome/test/data/push_messaging/",
"//chrome/test/data/translate/",
......
......@@ -8,6 +8,7 @@ import android.graphics.Bitmap;
import android.support.annotation.Px;
import org.chromium.base.Callback;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity;
......@@ -15,6 +16,7 @@ import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessory
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Action;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.content_public.browser.WebContents;
import org.chromium.ui.base.WindowAndroid;
class ManualFillingBridge {
......@@ -145,6 +147,12 @@ class ManualFillingBridge {
nativeOnFaviconRequested(mNativeView, desiredSize, faviconCallback);
}
@VisibleForTesting
public static void cachePasswordSheetData(
WebContents webContents, String[] userNames, String[] passwords) {
nativeCachePasswordSheetDataForTesting(webContents, userNames, passwords);
}
private native void nativeOnFaviconRequested(long nativeManualFillingViewAndroid,
int desiredSizeInPx, Callback<Bitmap> faviconCallback);
private native void nativeOnFillingTriggered(
......@@ -152,4 +160,7 @@ class ManualFillingBridge {
private native void nativeOnOptionSelected(
long nativeManualFillingViewAndroid, String selectedOption);
private native void nativeOnGenerationRequested(long nativeManualFillingViewAndroid);
private static native void nativeCachePasswordSheetDataForTesting(
WebContents webContents, String[] userNames, String[] passwords);
}
\ No newline at end of file
......@@ -129,7 +129,6 @@ public class AccessorySheetTabViewTest {
final AtomicReference<Boolean> clicked = new AtomicReference<>(false);
assertThat(mView.get().getChildCount(), is(0));
ManualFillingTestHelper.createTestCredentials();
ThreadUtils.runOnUiThreadBlocking(() -> {
mModel.add(new AccessorySheetDataPiece(
new KeyboardAccessoryData.FooterCommand(
......
......@@ -12,7 +12,6 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createTestCredentials;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.scrollToLastElement;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed;
......@@ -72,17 +71,16 @@ public class ManualFillingUiCaptureTest {
public void testCaptureKeyboardAccessoryWithPasswords()
throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false);
mHelper.cacheTestCredentials();
mHelper.addGenerationButton();
mHelper.clickPasswordField();
mHelper.sendCredentials(createTestCredentials());
mHelper.focusPasswordField();
mHelper.waitForKeyboardAccessoryToBeShown();
waitForActionsInAccessory();
waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBar");
mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
waitForSuggestionsInSheet();
waitForUnrelatedChromeUi();
......@@ -101,16 +99,15 @@ public class ManualFillingUiCaptureTest {
public void testCaptureKeyboardAccessoryWithPasswordsRTL()
throws InterruptedException, TimeoutException {
mHelper.loadTestPage(true);
mHelper.cacheTestCredentials();
mHelper.focusPasswordField();
mHelper.waitForKeyboardAccessoryToBeShown();
mHelper.addGenerationButton();
mHelper.clickPasswordField();
mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory();
waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBarRTL");
mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
waitForSuggestionsInSheet();
waitForUnrelatedChromeUi();
......@@ -129,16 +126,16 @@ public class ManualFillingUiCaptureTest {
public void testCaptureKeyboardAccessoryV2WithPasswords()
throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false);
mHelper.cacheTestCredentials();
mHelper.focusPasswordField();
mHelper.waitForKeyboardAccessoryToBeShown();
mHelper.addGenerationButton();
mHelper.clickPasswordField();
mHelper.addAutofillChips();
mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory();
waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBarV2");
mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.bar_items_view))
.perform(scrollTo(isAssignableFrom(KeyboardAccessoryTabLayoutView.class)),
actionOnItem(isAssignableFrom(KeyboardAccessoryTabLayoutView.class),
......@@ -161,17 +158,16 @@ public class ManualFillingUiCaptureTest {
public void testCaptureKeyboardAccessoryV2WithPasswordsRTL()
throws InterruptedException, TimeoutException {
mHelper.loadTestPage(true);
mHelper.cacheTestCredentials();
mHelper.focusPasswordField();
mHelper.waitForKeyboardAccessoryToBeShown();
mHelper.addGenerationButton();
mHelper.clickPasswordField();
mHelper.addAutofillChips();
mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory();
waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBarV2RTL");
mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.bar_items_view))
.perform(scrollTo(isAssignableFrom(KeyboardAccessoryTabLayoutView.class)),
actionOnItem(isAssignableFrom(KeyboardAccessoryTabLayoutView.class),
......
......@@ -6,7 +6,9 @@
#include <jni.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/android/callback_android.h"
......@@ -14,8 +16,12 @@
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autofill/manual_filling_controller.h"
#include "chrome/browser/autofill/manual_filling_controller_impl.h"
#include "chrome/browser/password_manager/password_accessory_controller.h"
#include "components/autofill/core/browser/accessory_sheet_data.h"
#include "components/autofill/core/common/password_form.h"
#include "jni/ManualFillingBridge_jni.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android.h"
......@@ -159,6 +165,44 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
return j_tab_data;
}
// static
void JNI_ManualFillingBridge_CachePasswordSheetDataForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& j_web_contents,
const base::android::JavaParamRef<jobjectArray>& j_usernames,
const base::android::JavaParamRef<jobjectArray>& j_passwords) {
content::WebContents* web_contents =
content::WebContents::FromJavaWebContents(j_web_contents);
PasswordAccessoryController* pwd_controller =
static_cast<ManualFillingControllerImpl*>(
ManualFillingControllerImpl::GetOrCreate(web_contents).get())
->password_controller_for_testing();
if (!pwd_controller) {
// If the controller isn't initialized (e.g. because the flags are not set),
// fail silently so tests can use shared setup methods for old and new UI.
LOG(ERROR) << "Tried to fill cache of non-existent accessory controller.";
return;
}
url::Origin origin = url::Origin::Create(web_contents->GetLastCommittedURL());
std::vector<std::string> usernames;
std::vector<std::string> passwords;
base::android::AppendJavaStringArrayToStringVector(env, j_usernames,
&usernames);
base::android::AppendJavaStringArrayToStringVector(env, j_passwords,
&passwords);
std::vector<autofill::PasswordForm> password_forms(usernames.size());
std::map<base::string16, const autofill::PasswordForm*> credentials;
for (unsigned int i = 0; i < usernames.size(); ++i) {
password_forms[i].origin = origin.GetURL();
password_forms[i].username_value = base::ASCIIToUTF16(usernames[i]);
password_forms[i].password_value = base::ASCIIToUTF16(passwords[i]);
credentials[password_forms[i].username_value] = &password_forms[i];
}
pwd_controller->SavePasswordsForOrigin(credentials, origin);
}
// static
std::unique_ptr<ManualFillingViewInterface> ManualFillingViewInterface::Create(
ManualFillingController* controller) {
......
......@@ -57,6 +57,10 @@ class ManualFillingControllerImpl
// Returns the held view for testing.
ManualFillingViewInterface* view() const { return view_.get(); }
#endif // defined(UNIT_TEST)
// Returns the connected password accessory controller for testing.
PasswordAccessoryController* password_controller_for_testing() const {
return pwd_controller_.get();
}
private:
friend class content::WebContentsUserData<ManualFillingControllerImpl>;
......
<html>
<head>
<meta name="viewport" "content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
</head>"
<body>
<form method="POST">
<input type="text" id="username_field" name="username_field" autocomplete="email">
<input type="password" id="password_field" name="password_field">
<input type="submit" id="input_submit_button" name="input_submit_button">
<input type="submit" />
</form>
</body>
</html>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment