Loading core/java/android/view/View.java +3 −2 Original line number Diff line number Diff line Loading @@ -1189,7 +1189,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public @interface AutofillFlags {} /** * Flag requesting you to add views not-important for autofill to the assist data. * Flag requesting you to add views that are marked as not important for autofill * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}. */ public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1; Loading Loading @@ -7484,7 +7485,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <li>Call {@link AutofillManager#commit()} when the autofill context * of the view structure changed and you want the current autofill interaction if such * to be commited. * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context * <li>Call {@link AutofillManager#cancel()} when the autofill context * of the view structure changed and you want the current autofill interaction if such * to be cancelled. * <li> The {@code left} and {@code top} values set in Loading core/java/android/view/autofill/AutofillManager.java +59 −32 Original line number Diff line number Diff line Loading @@ -388,9 +388,10 @@ public final class AutofillManager { /** * Explicitly requests a new autofill context. * * <p>Normally, the autofill context is automatically started when autofillable views are * focused, but this method should be used in the cases where it must be explicitly requested, * like a view that provides a contextual menu allowing users to autofill the activity. * <p>Normally, the autofill context is automatically started if necessary when * {@link #notifyViewEntered(View)} is called, but this method should be used in the * cases where it must be explicitly started. For example, when the view offers an AUTOFILL * option on its contextual overflow menu, and the user selects it. * * @param view view requesting the new autofill context. */ Loading @@ -401,16 +402,29 @@ public final class AutofillManager { /** * Explicitly requests a new autofill context for virtual views. * * <p>Normally, the autofill context is automatically started when autofillable views are * focused, but this method should be used in the cases where it must be explicitly requested, * like a virtual view that provides a contextual menu allowing users to autofill the activity. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the view. * @param bounds child boundaries, relative to the top window. * <p>Normally, the autofill context is automatically started if necessary when * {@link #notifyViewEntered(View, int, Rect)} is called, but this method should be used in the * cases where it must be explicitly started. For example, when the virtual view offers an * AUTOFILL option on its contextual overflow menu, and the user selects it. * * <p>The virtual view boundaries must be absolute screen coordinates. For example, if the * parent view uses {@code bounds} to draw the virtual view inside its Canvas, * the absolute bounds could be calculated by: * * <pre class="prettyprint"> * int offset[] = new int[2]; * getLocationOnScreen(offset); * Rect absBounds = new Rect(bounds.left + offset[0], * bounds.top + offset[1], * bounds.right + offset[0], bounds.bottom + offset[1]); * </pre> * * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. * @param absBounds absolute boundaries of the virtual view in the screen. */ public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) { notifyViewEntered(view, childId, bounds, FLAG_MANUAL_REQUEST); public void requestAutofill(@NonNull View view, int virtualId, @NonNull Rect absBounds) { notifyViewEntered(view, virtualId, absBounds, FLAG_MANUAL_REQUEST); } /** Loading Loading @@ -502,15 +516,27 @@ public final class AutofillManager { /** * Called when a virtual view that supports autofill is entered. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the view. * @param bounds child boundaries, relative to the top window. * <p>The virtual view boundaries must be absolute screen coordinates. For example, if the * parent, non-virtual view uses {@code bounds} to draw the virtual view inside its Canvas, * the absolute bounds could be calculated by: * * <pre class="prettyprint"> * int offset[] = new int[2]; * getLocationOnScreen(offset); * Rect absBounds = new Rect(bounds.left + offset[0], * bounds.top + offset[1], * bounds.right + offset[0], bounds.bottom + offset[1]); * </pre> * * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. * @param absBounds absolute boundaries of the virtual view in the screen. */ public void notifyViewEntered(@NonNull View view, int childId, @NonNull Rect bounds) { notifyViewEntered(view, childId, bounds, 0); public void notifyViewEntered(@NonNull View view, int virtualId, @NonNull Rect absBounds) { notifyViewEntered(view, virtualId, absBounds, 0); } private void notifyViewEntered(View view, int childId, Rect bounds, int flags) { private void notifyViewEntered(View view, int virtualId, Rect bounds, int flags) { if (!hasAutofillFeature()) { return; } Loading @@ -523,7 +549,7 @@ public final class AutofillManager { callback = mCallback; } } else { final AutofillId id = getAutofillId(view, childId); final AutofillId id = getAutofillId(view, virtualId); if (mSessionId == NO_SESSION) { // Starts new session. Loading @@ -536,7 +562,7 @@ public final class AutofillManager { } if (callback != null) { callback.onAutofillEvent(view, childId, callback.onAutofillEvent(view, virtualId, AutofillCallback.EVENT_INPUT_UNAVAILABLE); } } Loading @@ -544,10 +570,10 @@ public final class AutofillManager { /** * Called when a virtual view that supports autofill is exited. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the view. * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. */ public void notifyViewExited(@NonNull View view, int childId) { public void notifyViewExited(@NonNull View view, int virtualId) { if (!hasAutofillFeature()) { return; } Loading @@ -555,7 +581,7 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); if (mEnabled && mSessionId != NO_SESSION) { final AutofillId id = getAutofillId(view, childId); final AutofillId id = getAutofillId(view, virtualId); // Update focus on existing session. updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0); Loading Loading @@ -615,13 +641,13 @@ public final class AutofillManager { } /** * Called to indicate the value of an autofillable virtual {@link View} changed. * Called to indicate the value of an autofillable virtual view has changed. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the parent view. * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. * @param value new value of the child. */ public void notifyValueChanged(View view, int childId, AutofillValue value) { public void notifyValueChanged(View view, int virtualId, AutofillValue value) { if (!hasAutofillFeature()) { return; } Loading @@ -630,7 +656,7 @@ public final class AutofillManager { return; } final AutofillId id = getAutofillId(view, childId); final AutofillId id = getAutofillId(view, virtualId); updateSessionLocked(id, null, value, ACTION_VALUE_CHANGED, 0); } } Loading Loading @@ -765,8 +791,8 @@ public final class AutofillManager { return new AutofillId(view.getAccessibilityViewId()); } private static AutofillId getAutofillId(View parent, int childId) { return new AutofillId(parent.getAccessibilityViewId(), childId); private static AutofillId getAutofillId(View parent, int virtualId) { return new AutofillId(parent.getAccessibilityViewId(), virtualId); } private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds, Loading Loading @@ -1470,11 +1496,12 @@ public final class AutofillManager { * Called after a change in the autofill state associated with a virtual view. * * @param view parent view associated with the change. * @param childId id identifying the virtual child inside the parent view. * @param virtualId id identifying the virtual child inside the parent view. * * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}. */ public void onAutofillEvent(@NonNull View view, int childId, @AutofillEventType int event) { public void onAutofillEvent(@NonNull View view, int virtualId, @AutofillEventType int event) { } } Loading core/java/android/webkit/WebView.java +22 −15 Original line number Diff line number Diff line Loading @@ -2654,19 +2654,23 @@ public class WebView extends AbsoluteLayout * {@link ViewStructure#setAutofillHints(String[])}. * <li>The {@code type} attribute of {@code INPUT} tags maps to * {@link ViewStructure#setInputType(int)}. * <li>The {@code value} attribute maps to {@link ViewStructure#setText(CharSequence)}. * <li>The {@code value} attribute of {@code INPUT} tags maps to * {@link ViewStructure#setText(CharSequence)}. * <li>If the view is editalbe, the {@link ViewStructure#setAutofillType(int)} and * {@link ViewStructure#setAutofillValue(AutofillValue)} must be set. * <li>The {@code placeholder} attribute maps to {@link ViewStructure#setHint(CharSequence)}. * <li>{@link ViewStructure#setDataIsSensitive(boolean)} whould only be called with * {@code true} for form fields whose {@code value} attribute was not pre-loaded. * <li>Other HTML attributes can be represented through * {@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}. * </ol> * * <p>It should also call {@code structure.setDataIsSensitive(false)} for fields whose value * were not dynamically changed (for example, through Javascript). * * <p>Example1: an HTML form with 2 fields for username and password. * * <pre class="prettyprint"> * <input type="text" name="username" id="user" value="mr.sparkle" autocomplete="username" placeholder="Email or username"> * <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password"> * <input type="text" name="username" id="user" value="Type your username" autocomplete="username" placeholder="Email or username"> * <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password"> * </pre> * * <p>Would map to: Loading @@ -2674,38 +2678,40 @@ public class WebView extends AbsoluteLayout * <pre class="prettyprint"> * int index = structure.addChildCount(2); * ViewStructure username = structure.newChild(index); * username.setAutofillId(structure, 1); // id 1 - first child * username.setAutofillId(structure.getAutofillId(), 1); // id 1 - first child * username.setClassName("input"); * username.setInputType("android.widget.EditText"); * username.setAutofillHints("username"); * username.setHtmlInfo(child.newHtmlInfoBuilder("input") * username.setHtmlInfo(username.newHtmlInfoBuilder("input") * .addAttribute("type", "text") * .addAttribute("name", "username") * .addAttribute("id", "user") * .build()); * username.setHint("Email or username"); * username.setAutofillType(View.AUTOFILL_TYPE_TEXT); * username.setAutofillValue(AutofillValue.forText("mr.sparkle")); * username.setText("mr.sparkle"); * username.setDataIsSensitive(true); // Contains real username, which is sensitive * username.setAutofillValue(AutofillValue.forText("Type your username")); * username.setText("Type your username"); * // Value of the field is not sensitive because it was not dynamically changed: * username.setDataIsSensitive(false); * * ViewStructure password = structure.newChild(index + 1); * username.setAutofillId(structure, 2); // id 2 - second child * password.setInputType("android.widget.EditText"); * password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); * password.setAutofillHints("current-password"); * password.setHtmlInfo(child.newHtmlInfoBuilder("input") * password.setHtmlInfo(password.newHtmlInfoBuilder("input") * .addAttribute("type", "password") * .addAttribute("name", "password") * .addAttribute("id", "pass") * .build()); * password.setHint("Password"); * password.setAutofillType(View.AUTOFILL_TYPE_TEXT); * password.setDataIsSensitive(false); // Value is not set * </pre> * * <p>Example2: an IFRAME tag. * * <pre class="prettyprint"> * <iframe src="https://example.com/login"/> * <iframe src="https://example.com/login"/> * </pre> * * <p>Would map to: Loading @@ -2713,8 +2719,9 @@ public class WebView extends AbsoluteLayout * <pre class="prettyprint"> * int index = structure.addChildCount(1); * ViewStructure iframe = structure.newChildFor(index); * iframe.setHtmlInfo(child.newHtmlInfoBuilder("iframe") * .addAttribute("url", "https://example.com/login") * iframe.setAutofillId(structure.getAutofillId(), 1); * iframe.setHtmlInfo(iframe.newHtmlInfoBuilder("iframe") * .addAttribute("src", "https://example.com/login") * .build()); * </pre> */ Loading Loading
core/java/android/view/View.java +3 −2 Original line number Diff line number Diff line Loading @@ -1189,7 +1189,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, public @interface AutofillFlags {} /** * Flag requesting you to add views not-important for autofill to the assist data. * Flag requesting you to add views that are marked as not important for autofill * (see {@link #setImportantForAutofill(int)}) to a {@link ViewStructure}. */ public static final int AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS = 0x1; Loading Loading @@ -7484,7 +7485,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * <li>Call {@link AutofillManager#commit()} when the autofill context * of the view structure changed and you want the current autofill interaction if such * to be commited. * <li>Call {@link AutofillManager#cancel()} ()} when the autofill context * <li>Call {@link AutofillManager#cancel()} when the autofill context * of the view structure changed and you want the current autofill interaction if such * to be cancelled. * <li> The {@code left} and {@code top} values set in Loading
core/java/android/view/autofill/AutofillManager.java +59 −32 Original line number Diff line number Diff line Loading @@ -388,9 +388,10 @@ public final class AutofillManager { /** * Explicitly requests a new autofill context. * * <p>Normally, the autofill context is automatically started when autofillable views are * focused, but this method should be used in the cases where it must be explicitly requested, * like a view that provides a contextual menu allowing users to autofill the activity. * <p>Normally, the autofill context is automatically started if necessary when * {@link #notifyViewEntered(View)} is called, but this method should be used in the * cases where it must be explicitly started. For example, when the view offers an AUTOFILL * option on its contextual overflow menu, and the user selects it. * * @param view view requesting the new autofill context. */ Loading @@ -401,16 +402,29 @@ public final class AutofillManager { /** * Explicitly requests a new autofill context for virtual views. * * <p>Normally, the autofill context is automatically started when autofillable views are * focused, but this method should be used in the cases where it must be explicitly requested, * like a virtual view that provides a contextual menu allowing users to autofill the activity. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the view. * @param bounds child boundaries, relative to the top window. * <p>Normally, the autofill context is automatically started if necessary when * {@link #notifyViewEntered(View, int, Rect)} is called, but this method should be used in the * cases where it must be explicitly started. For example, when the virtual view offers an * AUTOFILL option on its contextual overflow menu, and the user selects it. * * <p>The virtual view boundaries must be absolute screen coordinates. For example, if the * parent view uses {@code bounds} to draw the virtual view inside its Canvas, * the absolute bounds could be calculated by: * * <pre class="prettyprint"> * int offset[] = new int[2]; * getLocationOnScreen(offset); * Rect absBounds = new Rect(bounds.left + offset[0], * bounds.top + offset[1], * bounds.right + offset[0], bounds.bottom + offset[1]); * </pre> * * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. * @param absBounds absolute boundaries of the virtual view in the screen. */ public void requestAutofill(@NonNull View view, int childId, @NonNull Rect bounds) { notifyViewEntered(view, childId, bounds, FLAG_MANUAL_REQUEST); public void requestAutofill(@NonNull View view, int virtualId, @NonNull Rect absBounds) { notifyViewEntered(view, virtualId, absBounds, FLAG_MANUAL_REQUEST); } /** Loading Loading @@ -502,15 +516,27 @@ public final class AutofillManager { /** * Called when a virtual view that supports autofill is entered. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the view. * @param bounds child boundaries, relative to the top window. * <p>The virtual view boundaries must be absolute screen coordinates. For example, if the * parent, non-virtual view uses {@code bounds} to draw the virtual view inside its Canvas, * the absolute bounds could be calculated by: * * <pre class="prettyprint"> * int offset[] = new int[2]; * getLocationOnScreen(offset); * Rect absBounds = new Rect(bounds.left + offset[0], * bounds.top + offset[1], * bounds.right + offset[0], bounds.bottom + offset[1]); * </pre> * * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. * @param absBounds absolute boundaries of the virtual view in the screen. */ public void notifyViewEntered(@NonNull View view, int childId, @NonNull Rect bounds) { notifyViewEntered(view, childId, bounds, 0); public void notifyViewEntered(@NonNull View view, int virtualId, @NonNull Rect absBounds) { notifyViewEntered(view, virtualId, absBounds, 0); } private void notifyViewEntered(View view, int childId, Rect bounds, int flags) { private void notifyViewEntered(View view, int virtualId, Rect bounds, int flags) { if (!hasAutofillFeature()) { return; } Loading @@ -523,7 +549,7 @@ public final class AutofillManager { callback = mCallback; } } else { final AutofillId id = getAutofillId(view, childId); final AutofillId id = getAutofillId(view, virtualId); if (mSessionId == NO_SESSION) { // Starts new session. Loading @@ -536,7 +562,7 @@ public final class AutofillManager { } if (callback != null) { callback.onAutofillEvent(view, childId, callback.onAutofillEvent(view, virtualId, AutofillCallback.EVENT_INPUT_UNAVAILABLE); } } Loading @@ -544,10 +570,10 @@ public final class AutofillManager { /** * Called when a virtual view that supports autofill is exited. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the view. * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. */ public void notifyViewExited(@NonNull View view, int childId) { public void notifyViewExited(@NonNull View view, int virtualId) { if (!hasAutofillFeature()) { return; } Loading @@ -555,7 +581,7 @@ public final class AutofillManager { ensureServiceClientAddedIfNeededLocked(); if (mEnabled && mSessionId != NO_SESSION) { final AutofillId id = getAutofillId(view, childId); final AutofillId id = getAutofillId(view, virtualId); // Update focus on existing session. updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0); Loading Loading @@ -615,13 +641,13 @@ public final class AutofillManager { } /** * Called to indicate the value of an autofillable virtual {@link View} changed. * Called to indicate the value of an autofillable virtual view has changed. * * @param view the {@link View} whose descendant is the virtual view. * @param childId id identifying the virtual child inside the parent view. * @param view the virtual view parent. * @param virtualId id identifying the virtual child inside the parent view. * @param value new value of the child. */ public void notifyValueChanged(View view, int childId, AutofillValue value) { public void notifyValueChanged(View view, int virtualId, AutofillValue value) { if (!hasAutofillFeature()) { return; } Loading @@ -630,7 +656,7 @@ public final class AutofillManager { return; } final AutofillId id = getAutofillId(view, childId); final AutofillId id = getAutofillId(view, virtualId); updateSessionLocked(id, null, value, ACTION_VALUE_CHANGED, 0); } } Loading Loading @@ -765,8 +791,8 @@ public final class AutofillManager { return new AutofillId(view.getAccessibilityViewId()); } private static AutofillId getAutofillId(View parent, int childId) { return new AutofillId(parent.getAccessibilityViewId(), childId); private static AutofillId getAutofillId(View parent, int virtualId) { return new AutofillId(parent.getAccessibilityViewId(), virtualId); } private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds, Loading Loading @@ -1470,11 +1496,12 @@ public final class AutofillManager { * Called after a change in the autofill state associated with a virtual view. * * @param view parent view associated with the change. * @param childId id identifying the virtual child inside the parent view. * @param virtualId id identifying the virtual child inside the parent view. * * @param event currently either {@link #EVENT_INPUT_SHOWN} or {@link #EVENT_INPUT_HIDDEN}. */ public void onAutofillEvent(@NonNull View view, int childId, @AutofillEventType int event) { public void onAutofillEvent(@NonNull View view, int virtualId, @AutofillEventType int event) { } } Loading
core/java/android/webkit/WebView.java +22 −15 Original line number Diff line number Diff line Loading @@ -2654,19 +2654,23 @@ public class WebView extends AbsoluteLayout * {@link ViewStructure#setAutofillHints(String[])}. * <li>The {@code type} attribute of {@code INPUT} tags maps to * {@link ViewStructure#setInputType(int)}. * <li>The {@code value} attribute maps to {@link ViewStructure#setText(CharSequence)}. * <li>The {@code value} attribute of {@code INPUT} tags maps to * {@link ViewStructure#setText(CharSequence)}. * <li>If the view is editalbe, the {@link ViewStructure#setAutofillType(int)} and * {@link ViewStructure#setAutofillValue(AutofillValue)} must be set. * <li>The {@code placeholder} attribute maps to {@link ViewStructure#setHint(CharSequence)}. * <li>{@link ViewStructure#setDataIsSensitive(boolean)} whould only be called with * {@code true} for form fields whose {@code value} attribute was not pre-loaded. * <li>Other HTML attributes can be represented through * {@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}. * </ol> * * <p>It should also call {@code structure.setDataIsSensitive(false)} for fields whose value * were not dynamically changed (for example, through Javascript). * * <p>Example1: an HTML form with 2 fields for username and password. * * <pre class="prettyprint"> * <input type="text" name="username" id="user" value="mr.sparkle" autocomplete="username" placeholder="Email or username"> * <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password"> * <input type="text" name="username" id="user" value="Type your username" autocomplete="username" placeholder="Email or username"> * <input type="password" name="password" id="pass" autocomplete="current-password" placeholder="Password"> * </pre> * * <p>Would map to: Loading @@ -2674,38 +2678,40 @@ public class WebView extends AbsoluteLayout * <pre class="prettyprint"> * int index = structure.addChildCount(2); * ViewStructure username = structure.newChild(index); * username.setAutofillId(structure, 1); // id 1 - first child * username.setAutofillId(structure.getAutofillId(), 1); // id 1 - first child * username.setClassName("input"); * username.setInputType("android.widget.EditText"); * username.setAutofillHints("username"); * username.setHtmlInfo(child.newHtmlInfoBuilder("input") * username.setHtmlInfo(username.newHtmlInfoBuilder("input") * .addAttribute("type", "text") * .addAttribute("name", "username") * .addAttribute("id", "user") * .build()); * username.setHint("Email or username"); * username.setAutofillType(View.AUTOFILL_TYPE_TEXT); * username.setAutofillValue(AutofillValue.forText("mr.sparkle")); * username.setText("mr.sparkle"); * username.setDataIsSensitive(true); // Contains real username, which is sensitive * username.setAutofillValue(AutofillValue.forText("Type your username")); * username.setText("Type your username"); * // Value of the field is not sensitive because it was not dynamically changed: * username.setDataIsSensitive(false); * * ViewStructure password = structure.newChild(index + 1); * username.setAutofillId(structure, 2); // id 2 - second child * password.setInputType("android.widget.EditText"); * password.setInputType(InputType.TYPE_TEXT_VARIATION_PASSWORD); * password.setAutofillHints("current-password"); * password.setHtmlInfo(child.newHtmlInfoBuilder("input") * password.setHtmlInfo(password.newHtmlInfoBuilder("input") * .addAttribute("type", "password") * .addAttribute("name", "password") * .addAttribute("id", "pass") * .build()); * password.setHint("Password"); * password.setAutofillType(View.AUTOFILL_TYPE_TEXT); * password.setDataIsSensitive(false); // Value is not set * </pre> * * <p>Example2: an IFRAME tag. * * <pre class="prettyprint"> * <iframe src="https://example.com/login"/> * <iframe src="https://example.com/login"/> * </pre> * * <p>Would map to: Loading @@ -2713,8 +2719,9 @@ public class WebView extends AbsoluteLayout * <pre class="prettyprint"> * int index = structure.addChildCount(1); * ViewStructure iframe = structure.newChildFor(index); * iframe.setHtmlInfo(child.newHtmlInfoBuilder("iframe") * .addAttribute("url", "https://example.com/login") * iframe.setAutofillId(structure.getAutofillId(), 1); * iframe.setHtmlInfo(iframe.newHtmlInfoBuilder("iframe") * .addAttribute("src", "https://example.com/login") * .build()); * </pre> */ Loading