blob: 6f3f94da9ca9bad0373d55f7d4ceb39745c3346a [file] [log] [blame]
// Copyright 2017 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.
#include "chrome/browser/ui/android/javascript_dialog_android.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "chrome/browser/android/tab_android.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "jni/JavascriptTabModalDialog_jni.h"
#include "ui/android/window_android.h"
using base::android::AttachCurrentThread;
using base::android::ConvertUTF16ToJavaString;
using base::android::JavaParamRef;
using base::android::ScopedJavaGlobalRef;
using base::android::ScopedJavaLocalRef;
// JavaScriptDialogAndroid:
JavaScriptDialogAndroid::~JavaScriptDialogAndroid() {
// In case the dialog is still displaying, tell it to close itself.
// This can happen if you trigger a dialog but close the Tab before it's
// shown, and then accept the dialog.
if (!dialog_jobject_.is_null()) {
Java_JavascriptTabModalDialog_dismiss(AttachCurrentThread(),
dialog_jobject_);
}
}
base::WeakPtr<JavaScriptDialogAndroid> JavaScriptDialogAndroid::Create(
content::WebContents* parent_web_contents,
content::WebContents* alerting_web_contents,
const base::string16& title,
content::JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
content::JavaScriptDialogManager::DialogClosedCallback
callback_on_button_clicked,
base::OnceClosure callback_on_cancelled) {
return (new JavaScriptDialogAndroid(parent_web_contents,
alerting_web_contents, title, dialog_type,
message_text, default_prompt_text,
std::move(callback_on_button_clicked),
std::move(callback_on_cancelled)))
->weak_factory_.GetWeakPtr();
}
void JavaScriptDialogAndroid::CloseDialogWithoutCallback() {
delete this;
}
base::string16 JavaScriptDialogAndroid::GetUserInput() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> prompt =
Java_JavascriptTabModalDialog_getUserInput(env, dialog_jobject_);
return base::android::ConvertJavaStringToUTF16(env, prompt);
}
void JavaScriptDialogAndroid::Accept(JNIEnv* env,
const JavaParamRef<jobject>&,
const JavaParamRef<jstring>& prompt) {
if (callback_on_button_clicked_) {
base::string16 prompt_text =
base::android::ConvertJavaStringToUTF16(env, prompt);
std::move(callback_on_button_clicked_).Run(true, prompt_text);
}
delete this;
}
void JavaScriptDialogAndroid::Cancel(JNIEnv* env,
const JavaParamRef<jobject>&,
jboolean button_clicked) {
if (button_clicked) {
if (callback_on_button_clicked_) {
std::move(callback_on_button_clicked_).Run(false, base::string16());
}
} else if (callback_on_cancelled_) {
std::move(callback_on_cancelled_).Run();
}
delete this;
}
JavaScriptDialogAndroid::JavaScriptDialogAndroid(
content::WebContents* parent_web_contents,
content::WebContents* alerting_web_contents,
const base::string16& title,
content::JavaScriptDialogType dialog_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
content::JavaScriptDialogManager::DialogClosedCallback
callback_on_button_clicked,
base::OnceClosure callback_on_cancelled)
: callback_on_button_clicked_(std::move(callback_on_button_clicked)),
callback_on_cancelled_(std::move(callback_on_cancelled)),
weak_factory_(this) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
jwindow_weak_ref_ = JavaObjectWeakGlobalRef(
env,
parent_web_contents->GetTopLevelNativeWindow()->GetJavaObject().obj());
// Keep a strong ref to the parent window while we make the call to java to
// display the dialog.
ScopedJavaLocalRef<jobject> jwindow = jwindow_weak_ref_.get(env);
ScopedJavaLocalRef<jobject> dialog_object;
ScopedJavaLocalRef<jstring> title_ref = ConvertUTF16ToJavaString(env, title);
ScopedJavaLocalRef<jstring> message_ref =
ConvertUTF16ToJavaString(env, message_text);
switch (dialog_type) {
case content::JAVASCRIPT_DIALOG_TYPE_ALERT: {
dialog_object = Java_JavascriptTabModalDialog_createAlertDialog(
env, title_ref, message_ref);
break;
}
case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: {
dialog_object = Java_JavascriptTabModalDialog_createConfirmDialog(
env, title_ref, message_ref);
break;
}
case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: {
ScopedJavaLocalRef<jstring> default_prompt_text_ref =
ConvertUTF16ToJavaString(env, default_prompt_text);
dialog_object = Java_JavascriptTabModalDialog_createPromptDialog(
env, title_ref, message_ref, default_prompt_text_ref);
break;
}
default:
NOTREACHED();
}
// Keep a ref to the java side object until we get accept or cancel.
dialog_jobject_.Reset(dialog_object);
Java_JavascriptTabModalDialog_showDialog(env, dialog_object, jwindow,
reinterpret_cast<intptr_t>(this));
}