| // Copyright 2017 The Chromium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "components/javascript_dialogs/android/tab_modal_dialog_view_android.h" | |
| #include "base/android/jni_android.h" | |
| #include "base/android/jni_string.h" | |
| #include "base/functional/callback.h" | |
| #include "content/public/browser/browser_thread.h" | |
| #include "content/public/browser/web_contents.h" | |
| #include "content/public/browser/web_contents_delegate.h" | |
| #include "ui/android/window_android.h" | |
| // Must come after all headers that specialize FromJniType() / ToJniType(). | |
| #include "components/javascript_dialogs/android/jni_headers/JavascriptTabModalDialog_jni.h" | |
| using base::android::AttachCurrentThread; | |
| using base::android::ConvertUTF16ToJavaString; | |
| using base::android::JavaRef; | |
| using base::android::ScopedJavaGlobalRef; | |
| using base::android::ScopedJavaLocalRef; | |
| namespace javascript_dialogs { | |
| // static | |
| base::WeakPtr<TabModalDialogViewAndroid> TabModalDialogViewAndroid::Create( | |
| content::WebContents* parent_web_contents, | |
| content::WebContents* alerting_web_contents, | |
| const std::u16string& title, | |
| content::JavaScriptDialogType dialog_type, | |
| const std::u16string& message_text, | |
| const std::u16string& default_prompt_text, | |
| content::JavaScriptDialogManager::DialogClosedCallback | |
| callback_on_button_clicked, | |
| base::OnceClosure callback_on_cancelled) { | |
| TabModalDialogViewAndroid* dialog = new TabModalDialogViewAndroid( | |
| 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)); | |
| base::WeakPtr<TabModalDialogViewAndroid> weak_dialog = | |
| dialog->weak_factory_.GetWeakPtr(); | |
| dialog->Show(); | |
| return weak_dialog; | |
| } | |
| // TabModalDialogViewAndroid: | |
| TabModalDialogViewAndroid::~TabModalDialogViewAndroid() { | |
| // 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_); | |
| } | |
| } | |
| void TabModalDialogViewAndroid::CloseDialogWithoutCallback() { | |
| delete this; | |
| } | |
| std::u16string TabModalDialogViewAndroid::GetUserInput() { | |
| JNIEnv* env = AttachCurrentThread(); | |
| ScopedJavaLocalRef<jstring> prompt = | |
| Java_JavascriptTabModalDialog_getUserInput(env, dialog_jobject_); | |
| return base::android::ConvertJavaStringToUTF16(env, prompt); | |
| } | |
| void TabModalDialogViewAndroid::Accept(JNIEnv* env, | |
| const JavaRef<jstring>& prompt) { | |
| if (callback_on_button_clicked_) { | |
| std::u16string prompt_text = | |
| base::android::ConvertJavaStringToUTF16(env, prompt); | |
| std::move(callback_on_button_clicked_).Run(true, prompt_text); | |
| } | |
| delete this; | |
| } | |
| void TabModalDialogViewAndroid::Cancel(JNIEnv* env, bool button_clicked) { | |
| if (button_clicked) { | |
| if (callback_on_button_clicked_) { | |
| std::move(callback_on_button_clicked_).Run(false, std::u16string()); | |
| } | |
| } else if (callback_on_cancelled_) { | |
| std::move(callback_on_cancelled_).Run(); | |
| } | |
| delete this; | |
| } | |
| TabModalDialogViewAndroid::TabModalDialogViewAndroid( | |
| content::WebContents* parent_web_contents, | |
| content::WebContents* alerting_web_contents, | |
| const std::u16string& title, | |
| content::JavaScriptDialogType dialog_type, | |
| const std::u16string& message_text, | |
| const std::u16string& 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)) { | |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| JNIEnv* env = AttachCurrentThread(); | |
| jwindow_weak_ref_ = JavaObjectWeakGlobalRef( | |
| env, parent_web_contents->GetTopLevelNativeWindow()->GetJavaObject()); | |
| 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); | |
| } | |
| void TabModalDialogViewAndroid::Show() { | |
| JNIEnv* env = AttachCurrentThread(); | |
| ScopedJavaLocalRef<jobject> jwindow = jwindow_weak_ref_.get(env); | |
| if (jwindow) { | |
| Java_JavascriptTabModalDialog_showDialog(env, dialog_jobject_, jwindow, | |
| reinterpret_cast<intptr_t>(this)); | |
| } | |
| } | |
| } // namespace javascript_dialogs | |
| DEFINE_JNI(JavascriptTabModalDialog) |