// Copyright 2014 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; import android.content.Context; import android.os.Handler; import android.view.View; import android.widget.AdapterView; import android.widget.PopupWindow; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.ui.DropdownPopupWindow; import org.chromium.ui.R; import org.chromium.ui.base.WindowAndroid; /** * JNI call glue for password generation between native and Java objects. */ @JNINamespace("autofill") public class PasswordGenerationPopupBridge implements AdapterView.OnItemClickListener, PopupWindow.OnDismissListener, PasswordGenerationAdapter.Delegate { private final long mNativePasswordGenerationPopupViewAndroid; private final Context mContext; private final DropdownPopupWindow mPopup; private final View mAnchorView; /** * A convenience method for the constructor to be invoked from the native counterpart. * @param anchorView View anchored for popup. * @param nativePopup The pointer to the native counterpart. * @param windowAndroid The browser window. */ @CalledByNative private static PasswordGenerationPopupBridge create(View anchorView, long nativePopup, WindowAndroid windowAndroid) { return new PasswordGenerationPopupBridge(anchorView, nativePopup, windowAndroid); } /** * Builds the bridge between native and Java objects. * @param anchorView View anchored for popup. * @param nativePopup The pointer to the native counterpart. * @param windowAndroid The browser window. */ public PasswordGenerationPopupBridge(View anchorView, long nativePopup, WindowAndroid windowAndroid) { mNativePasswordGenerationPopupViewAndroid = nativePopup; mContext = windowAndroid.getActivity().get(); mAnchorView = anchorView; // mContext could've been garbage collected. if (mContext == null) { mPopup = null; // Prevent destroying the native counterpart when it's about to derefence its own // members in UpdateBoundsAndRedrawPopup(). new Handler().post(new Runnable() { @Override public void run() { onDismiss(); } }); } else { mPopup = new DropdownPopupWindow(mContext, anchorView); mPopup.setOnItemClickListener(this); mPopup.setOnDismissListener(this); mPopup.disableHideOnOutsideTap(); mPopup.setContentDescriptionForAccessibility( mContext.getString(R.string.password_generation_popup_content_description)); } } /** * Handles clicks on popup list elements. Only suggestion element is enabled. Clicking on the * suggestion element notifies the native counterpart that the suggested password was selected. * @param parent The parent view where the click happened. * @param view The view that was provided by the adapter that was clicked. * @param position The position of the view in the adapter. * @param id The row id of the clicked element. */ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { nativePasswordSelected(mNativePasswordGenerationPopupViewAndroid); } private native void nativePasswordSelected(long nativePasswordGenerationPopupViewAndroid); /** * Handles dismissing the popup window. The native counterpart is notified to destroy the * controller. */ @Override public void onDismiss() { nativeDismissed(mNativePasswordGenerationPopupViewAndroid); } private native void nativeDismissed(long nativePasswordGenerationPopupViewAndroid); /** * Shows a password generation popup with specified data. Should be called after * setAnchorRect(). * @param isRtl True if the popup should be RTL. * @param passwordDisplayed Whether the generated password should be displayed. * @param password The auto-generated password to suggest. * @param suggestionTitle The translated title of the suggestion part of the popup. * @param explanationText The translated text that explains the popup. * @param explanationTextLinkRangeStart The start of the range in the explanation text that * should be a link to the saved passwords. * @param explanationTextLinkRangeEnd The end of the range in the explanation text that should * be a link to the saved passwords. */ @CalledByNative private void show(boolean isRtl, boolean passwordDisplayed, String password, String suggestionTitle, String explanationText, int explanationTextLinkRangeStart, int explanationTextLinkRangeEnd) { if (mPopup != null) { float anchorWidth = mAnchorView.getLayoutParams().width; assert anchorWidth > 0; PasswordGenerationAdapter adapter = new PasswordGenerationAdapter(mContext, this, passwordDisplayed, password, suggestionTitle, explanationText, explanationTextLinkRangeStart, explanationTextLinkRangeEnd, anchorWidth); mPopup.setAdapter(adapter); mPopup.setRtl(isRtl); mPopup.show(); } } /** * Called from adapter when the "saved passwords" link is clicked. */ @Override public void onSavedPasswordsLinkClicked() { nativeSavedPasswordsLinkClicked(mNativePasswordGenerationPopupViewAndroid); } private native void nativeSavedPasswordsLinkClicked( long nativePasswordGenerationPopupViewAndroid); /** * Hides the password generation popup. */ @CalledByNative private void hide() { if (mPopup != null) mPopup.dismiss(); } }