| // 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)); |
| } |