summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc')
-rw-r--r--chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc155
1 files changed, 155 insertions, 0 deletions
diff --git a/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc
new file mode 100644
index 0000000..a1c72f0
--- /dev/null
+++ b/chrome/browser/ui/app_modal_dialogs/js_modal_dialog.cc
@@ -0,0 +1,155 @@
+// Copyright (c) 2010 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/app_modal_dialogs/js_modal_dialog.h"
+
+#include "base/string_util.h"
+#include "chrome/browser/browser_shutdown.h"
+#include "chrome/browser/extensions/extension_host.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "ipc/ipc_message.h"
+
+namespace {
+
+// The maximum sizes of various texts passed to us from javascript.
+const int kMessageTextMaxSize = 3000;
+const int kDefaultPromptTextSize = 2000;
+
+} // namespace
+
+JavaScriptAppModalDialog::JavaScriptAppModalDialog(
+ JavaScriptAppModalDialogDelegate* delegate,
+ const std::wstring& title,
+ int dialog_flags,
+ const std::wstring& message_text,
+ const std::wstring& default_prompt_text,
+ bool display_suppress_checkbox,
+ bool is_before_unload_dialog,
+ IPC::Message* reply_msg)
+ : AppModalDialog(delegate->AsTabContents(), title),
+ delegate_(delegate),
+ extension_host_(delegate->AsExtensionHost()),
+ dialog_flags_(dialog_flags),
+ display_suppress_checkbox_(display_suppress_checkbox),
+ is_before_unload_dialog_(is_before_unload_dialog),
+ reply_msg_(reply_msg) {
+ // We trim the various parts of the message dialog because otherwise we can
+ // overflow the message dialog (and crash/hang the GTK+ version).
+ ElideString(message_text, kMessageTextMaxSize, &message_text_);
+ ElideString(default_prompt_text, kDefaultPromptTextSize,
+ &default_prompt_text_);
+
+ DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL));
+ InitNotifications();
+}
+
+JavaScriptAppModalDialog::~JavaScriptAppModalDialog() {
+}
+
+NativeAppModalDialog* JavaScriptAppModalDialog::CreateNativeDialog() {
+ gfx::NativeWindow parent_window = tab_contents_ ?
+ tab_contents_->GetMessageBoxRootWindow() :
+ extension_host_->GetMessageBoxRootWindow();
+ return NativeAppModalDialog::CreateNativeJavaScriptPrompt(this,
+ parent_window);
+}
+
+void JavaScriptAppModalDialog::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (skip_this_dialog_)
+ return;
+
+ if (NotificationType::EXTENSION_HOST_DESTROYED == type &&
+ Details<ExtensionHost>(extension_host_) != details)
+ return;
+
+ // If we reach here, we know the notification is relevant to us, either
+ // because we're only observing applicable sources or because we passed the
+ // check above. Both of those indicate that we should ignore this dialog.
+ // Also clear the delegate, since it's now invalid.
+ skip_this_dialog_ = true;
+ delegate_ = NULL;
+ if (native_dialog_)
+ CloseModalDialog();
+}
+
+void JavaScriptAppModalDialog::InitNotifications() {
+ // Make sure we get relevant navigation notifications so we know when our
+ // parent contents will disappear or navigate to a different page.
+ if (tab_contents_) {
+ registrar_.Add(this, NotificationType::NAV_ENTRY_COMMITTED,
+ Source<NavigationController>(&tab_contents_->controller()));
+ registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED,
+ Source<TabContents>(tab_contents_));
+ } else if (extension_host_) {
+ // EXTENSION_HOST_DESTROYED uses the Profile as its source, but we care
+ // about the ExtensionHost (which is passed in the details).
+ registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED,
+ NotificationService::AllSources());
+ } else {
+ NOTREACHED();
+ }
+}
+
+void JavaScriptAppModalDialog::OnCancel(bool suppress_js_messages) {
+ // If we are shutting down and this is an onbeforeunload dialog, cancel the
+ // shutdown.
+ if (is_before_unload_dialog_)
+ browser_shutdown::SetTryingToQuit(false);
+
+ // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame
+ // will receive its activation messages before this dialog receives
+ // WM_DESTROY. The parent frame would then try to activate any modal dialogs
+ // that were still open in the ModalDialogQueue, which would send activation
+ // back to this one. The framework should be improved to handle this, so this
+ // is a temporary workaround.
+ CompleteDialog();
+
+ if (!skip_this_dialog_) {
+ delegate_->OnMessageBoxClosed(reply_msg_, false, std::wstring());
+ if (suppress_js_messages)
+ delegate_->SetSuppressMessageBoxes(true);
+ }
+
+ Cleanup();
+}
+
+void JavaScriptAppModalDialog::OnAccept(const std::wstring& prompt_text,
+ bool suppress_js_messages) {
+ CompleteDialog();
+
+ if (!skip_this_dialog_) {
+ delegate_->OnMessageBoxClosed(reply_msg_, true, prompt_text);
+ if (suppress_js_messages)
+ delegate_->SetSuppressMessageBoxes(true);
+ }
+
+ Cleanup();
+}
+
+void JavaScriptAppModalDialog::OnClose() {
+ Cleanup();
+}
+
+void JavaScriptAppModalDialog::Cleanup() {
+ if (skip_this_dialog_) {
+ // We can't use the |delegate_|, because we might be in the process of
+ // destroying it.
+ if (tab_contents_)
+ tab_contents_->OnMessageBoxClosed(reply_msg_, false, L"");
+// The extension_host_ will always be a dirty pointer on OS X because the alert
+// window will cause the extension popup to close since it is resigning its key
+// state, destroying the host. http://crbug.com/29355
+#if !defined(OS_MACOSX)
+ else if (extension_host_)
+ extension_host_->OnMessageBoxClosed(reply_msg_, false, L"");
+ else
+ NOTREACHED();
+#endif
+ }
+}