| // Copyright 2012 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/app_modal_dialog_view_android.h" | |
| #include "base/android/jni_android.h" | |
| #include "base/android/jni_string.h" | |
| #include "base/memory/ptr_util.h" | |
| #include "components/javascript_dialogs/app_modal_dialog_controller.h" | |
| #include "components/javascript_dialogs/app_modal_dialog_manager.h" | |
| #include "components/javascript_dialogs/app_modal_dialog_queue.h" | |
| #include "content/public/browser/browser_thread.h" | |
| #include "content/public/browser/web_contents.h" | |
| #include "content/public/browser/web_contents_delegate.h" | |
| #include "content/public/common/javascript_dialog_type.h" | |
| #include "ui/android/window_android.h" | |
| // Must come after all headers that specialize FromJniType() / ToJniType(). | |
| #include "components/javascript_dialogs/android/jni_headers/JavascriptAppModalDialog_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 { | |
| AppModalDialogViewAndroid::AppModalDialogViewAndroid( | |
| JNIEnv* env, | |
| std::unique_ptr<javascript_dialogs::AppModalDialogController> controller, | |
| gfx::NativeWindow parent) | |
| : controller_(std::move(controller)), | |
| parent_jobject_weak_ref_(env, parent->GetJavaObject()) { | |
| controller_->web_contents()->GetDelegate()->ActivateContents( | |
| controller_->web_contents()); | |
| } | |
| void AppModalDialogViewAndroid::ShowAppModalDialog() { | |
| JNIEnv* env = AttachCurrentThread(); | |
| // Keep a strong ref to the parent window while we make the call to java to | |
| // display the dialog. | |
| ScopedJavaLocalRef<jobject> parent_jobj = parent_jobject_weak_ref_.get(env); | |
| if (parent_jobj.is_null()) { | |
| CancelAppModalDialog(); | |
| return; | |
| } | |
| ScopedJavaLocalRef<jobject> dialog_object; | |
| const std::u16string& title = controller_->title(); | |
| const std::u16string& message = controller_->message_text(); | |
| switch (controller_->javascript_dialog_type()) { | |
| case content::JAVASCRIPT_DIALOG_TYPE_ALERT: { | |
| dialog_object = Java_JavascriptAppModalDialog_createAlertDialog( | |
| env, title, message, controller_->display_suppress_checkbox()); | |
| break; | |
| } | |
| case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: { | |
| if (controller_->is_before_unload_dialog()) { | |
| dialog_object = Java_JavascriptAppModalDialog_createBeforeUnloadDialog( | |
| env, title, message, controller_->is_reload(), | |
| controller_->display_suppress_checkbox()); | |
| } else { | |
| dialog_object = Java_JavascriptAppModalDialog_createConfirmDialog( | |
| env, title, message, controller_->display_suppress_checkbox()); | |
| } | |
| break; | |
| } | |
| case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: { | |
| dialog_object = Java_JavascriptAppModalDialog_createPromptDialog( | |
| env, title, message, controller_->display_suppress_checkbox(), | |
| controller_->default_prompt_text()); | |
| break; | |
| } | |
| default: | |
| NOTREACHED(); | |
| } | |
| // Keep a ref to the java side object until we get a confirm or cancel. | |
| dialog_jobject_.Reset(dialog_object); | |
| Java_JavascriptAppModalDialog_showJavascriptAppModalDialog( | |
| env, dialog_object, parent_jobj, reinterpret_cast<intptr_t>(this)); | |
| } | |
| void AppModalDialogViewAndroid::ActivateAppModalDialog() { | |
| // This is called on desktop (Views) when interacting with a browser window | |
| // that does not host the currently active app modal dialog, as a way to | |
| // redirect activation to the app modal dialog host. It's not relevant on | |
| // Android. | |
| NOTREACHED(); | |
| } | |
| void AppModalDialogViewAndroid::CloseAppModalDialog() { | |
| CancelAppModalDialog(); | |
| } | |
| void AppModalDialogViewAndroid::AcceptAppModalDialog() { | |
| std::u16string prompt_text; | |
| controller_->OnAccept(prompt_text, false); | |
| delete this; | |
| } | |
| void AppModalDialogViewAndroid::DidAcceptAppModalDialog( | |
| const std::u16string& prompt, | |
| bool should_suppress_js_dialogs) { | |
| controller_->OnAccept(prompt, should_suppress_js_dialogs); | |
| delete this; | |
| } | |
| void AppModalDialogViewAndroid::CancelAppModalDialog() { | |
| controller_->OnCancel(false); | |
| delete this; | |
| } | |
| bool AppModalDialogViewAndroid::IsShowing() const { | |
| return true; | |
| } | |
| void AppModalDialogViewAndroid::DidCancelAppModalDialog( | |
| bool should_suppress_js_dialogs) { | |
| controller_->OnCancel(should_suppress_js_dialogs); | |
| delete this; | |
| } | |
| const ScopedJavaGlobalRef<jobject>& AppModalDialogViewAndroid::GetDialogObject() | |
| const { | |
| return dialog_jobject_; | |
| } | |
| AppModalDialogViewAndroid::~AppModalDialogViewAndroid() { | |
| // 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()) { | |
| JNIEnv* env = AttachCurrentThread(); | |
| Java_JavascriptAppModalDialog_dismiss(env, dialog_jobject_); | |
| } | |
| } | |
| // static | |
| static ScopedJavaLocalRef<jobject> | |
| JNI_JavascriptAppModalDialog_GetCurrentModalDialog(JNIEnv* env) { | |
| AppModalDialogController* controller = | |
| AppModalDialogQueue::GetInstance()->active_dialog(); | |
| if (!controller || !controller->view()) | |
| return ScopedJavaLocalRef<jobject>(); | |
| AppModalDialogViewAndroid* js_dialog = | |
| static_cast<AppModalDialogViewAndroid*>(controller->view()); | |
| return ScopedJavaLocalRef<jobject>(js_dialog->GetDialogObject()); | |
| } | |
| } // namespace javascript_dialogs | |
| DEFINE_JNI(JavascriptAppModalDialog) |