chromium/chrome/browser/ui/android/passwords/all_passwords_bottom_sheet_view_impl.cc

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/android/passwords/all_passwords_bottom_sheet_view_impl.h"

#include <vector>

#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/passwords/ui_utils.h"
#include "chrome/grit/generated_resources.h"
#include "components/affiliations/core/browser/affiliation_utils.h"
#include "components/password_manager/core/browser/password_form.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
#include "ui/android/window_android.h"
#include "ui/base/l10n/l10n_util.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "chrome/android/features/keyboard_accessory/internal/jni/AllPasswordsBottomSheetBridge_jni.h"
#include "chrome/android/features/keyboard_accessory/internal/jni/Credential_jni.h"

using autofill::mojom::FocusedFieldType;
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF16;
using base::android::ConvertUTF16ToJavaString;
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaParamRef;


AllPasswordsBottomSheetViewImpl::AllPasswordsBottomSheetViewImpl(
    AllPasswordsBottomSheetController* controller)
    : controller_(controller) {}

AllPasswordsBottomSheetViewImpl::~AllPasswordsBottomSheetViewImpl() {
  if (java_object_internal_) {
    // Don't create an object just for destruction.
    Java_AllPasswordsBottomSheetBridge_destroy(AttachCurrentThread(),
                                               java_object_internal_);
  }
}

void AllPasswordsBottomSheetViewImpl::Show(
    const std::vector<std::unique_ptr<password_manager::PasswordForm>>&
        credentials,
    FocusedFieldType focused_field_type) {
  auto java_object = GetOrCreateJavaObject();
  if (!java_object)
    return;

  JNIEnv* env = AttachCurrentThread();

  std::vector<base::android::ScopedJavaLocalRef<jobject>> java_credentials;
  java_credentials.reserve(credentials.size());
  for (const auto& credential : credentials) {
    auto facet = affiliations::FacetURI::FromPotentiallyInvalidSpec(
        credential->signon_realm);
    std::string app_display_name = credential->app_display_name;
    if (facet.IsValidAndroidFacetURI() && app_display_name.empty()) {
      app_display_name = l10n_util::GetStringFUTF8(
          IDS_SETTINGS_PASSWORDS_ANDROID_APP,
          base::UTF8ToUTF16(facet.android_package_name()));
    }

    java_credentials.emplace_back(Java_Credential_Constructor(
        env, credential->username_value, credential->password_value,
        GetDisplayUsername(*credential), credential->url.spec(),
        facet.IsValidAndroidFacetURI(), app_display_name,
        controller_->IsPlusAddress(
            base::UTF16ToUTF8(credential->username_value))));
  }

  const bool is_password_field =
      focused_field_type == FocusedFieldType::kFillablePasswordField;
  Java_AllPasswordsBottomSheetBridge_showCredentials(
      env, java_object, java_credentials, is_password_field);
}

void AllPasswordsBottomSheetViewImpl::OnCredentialSelected(
    JNIEnv* env,
    std::u16string& username,
    std::u16string& password,
    jboolean requests_to_fill_password) {
  controller_->OnCredentialSelected(
      username, password,
      AllPasswordsBottomSheetController::RequestsToFillPassword(
          requests_to_fill_password));
}

void AllPasswordsBottomSheetViewImpl::OnDismiss(JNIEnv* env) {
  controller_->OnDismiss();
}

base::android::ScopedJavaGlobalRef<jobject>
AllPasswordsBottomSheetViewImpl::GetOrCreateJavaObject() {
  if (java_object_internal_) {
    return java_object_internal_;
  }
  if (controller_->GetNativeView() == nullptr ||
      controller_->GetNativeView()->GetWindowAndroid() == nullptr) {
    return nullptr;  // No window attached (yet or anymore).
  }
  return java_object_internal_ = Java_AllPasswordsBottomSheetBridge_create(
             AttachCurrentThread(), reinterpret_cast<intptr_t>(this),
             controller_->GetProfile()->GetJavaObject(),
             controller_->GetNativeView()->GetWindowAndroid()->GetJavaObject(),
             controller_->GetFrameUrl().spec());
}