From 7eb2300f13b081bcd0adcfe28202e82d1310f70d Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Fri, 30 Jan 2009 19:34:38 +0000 Subject: Allow porting of the JS message boxes. I split out the implementation into platform-specific files, and have WebContents just use the platform-independent header that declares the creation functions. Review URL: http://codereview.chromium.org/19719 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8978 0039d316-1c4b-4281-b951-d872f2087c98 --- chrome/browser/browser.scons | 10 +- chrome/browser/browser.vcproj | 14 +- chrome/browser/js_before_unload_handler.cc | 57 ------- chrome/browser/js_before_unload_handler.h | 43 ++--- chrome/browser/js_before_unload_handler_win.cc | 52 ++++++ chrome/browser/js_before_unload_handler_win.h | 28 ++++ chrome/browser/jsmessage_box_handler.cc | 213 ------------------------- chrome/browser/jsmessage_box_handler.h | 90 ++--------- chrome/browser/jsmessage_box_handler_win.cc | 209 ++++++++++++++++++++++++ chrome/browser/jsmessage_box_handler_win.h | 76 +++++++++ chrome/browser/tab_contents/web_contents.cc | 13 +- 11 files changed, 412 insertions(+), 393 deletions(-) delete mode 100644 chrome/browser/js_before_unload_handler.cc create mode 100644 chrome/browser/js_before_unload_handler_win.cc create mode 100644 chrome/browser/js_before_unload_handler_win.h delete mode 100644 chrome/browser/jsmessage_box_handler.cc create mode 100644 chrome/browser/jsmessage_box_handler_win.cc create mode 100644 chrome/browser/jsmessage_box_handler_win.h diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index 0fc702f..5a56ec1 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -185,10 +185,12 @@ input_files = ChromeFileList([ 'dock_info.cc', 'dock_info.h', 'find_notification_details.h', - 'js_before_unload_handler.cc', 'js_before_unload_handler.h', - 'jsmessage_box_handler.cc', + 'js_before_unload_handler_win.cc', + 'js_before_unload_handler_win.h', 'jsmessage_box_handler.h', + 'jsmessage_box_handler_win.cc', + 'jsmessage_box_handler_win.h', 'load_from_memory_cache_details.h', 'load_notification_details.h', 'login_prompt.cc', @@ -737,8 +739,6 @@ if not env.Bit('windows'): 'importer/importer.cc', 'importer/toolbar_importer.cc', 'jankometer.cc', - 'js_before_unload_handler.cc', - 'jsmessage_box_handler.cc', 'login_prompt.cc', 'memory_details.cc', 'metrics/metrics_service.cc', @@ -820,6 +820,8 @@ if not env.Bit('windows'): input_files.Remove( 'browser_main_win.cc', 'importer/firefox_profile_lock_win.cc', + 'js_before_unload_handler_win.cc', + 'jsmessage_box_handler_win.cc', 'password_manager/password_form_manager_win.cc', 'renderer_host/render_widget_host_view_win.cc', 'tab_contents/web_contents_view_win.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 7a166a1..b76a16f 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -718,15 +718,15 @@ > + + + + diff --git a/chrome/browser/js_before_unload_handler.cc b/chrome/browser/js_before_unload_handler.cc deleted file mode 100644 index 01fca94..0000000 --- a/chrome/browser/js_before_unload_handler.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) 2006-2008 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/js_before_unload_handler.h" - -#include "chrome/browser/app_modal_dialog_queue.h" -#include "chrome/common/l10n_util.h" -#include "chrome/views/message_box_view.h" - -#include "generated_resources.h" - -/////////////////////////////////////////////////////////////////////////////// -// JavascriptBeforeUnloadHandler, public: - -// static -void JavascriptBeforeUnloadHandler::RunBeforeUnloadDialog( - WebContents* web_contents, - const std::wstring& message_text, - IPC::Message* reply_msg) { - std::wstring full_message = - message_text + L"\n\n" + - l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_FOOTER); - JavascriptBeforeUnloadHandler* handler = - new JavascriptBeforeUnloadHandler(web_contents, full_message, reply_msg); - AppModalDialogQueue::AddDialog(handler); -} - -////////////////////////////////////////////////////////////////////////////// -// JavascriptBeforeUnloadHandler, views::DialogDelegate implementation: - -std::wstring JavascriptBeforeUnloadHandler::GetWindowTitle() const { - return l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE); -} - -std::wstring JavascriptBeforeUnloadHandler::GetDialogButtonLabel( - DialogButton button) const { - if (button == DialogDelegate::DIALOGBUTTON_OK) { - return l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); - } else if (button == DialogDelegate::DIALOGBUTTON_CANCEL) { - return l10n_util::GetString( - IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL); - } - return L""; -} - -JavascriptBeforeUnloadHandler::JavascriptBeforeUnloadHandler( - WebContents* web_contents, - const std::wstring& message_text, - IPC::Message* reply_msg) - : JavascriptMessageBoxHandler(web_contents, - MessageBoxView::kIsJavascriptConfirm, - message_text, - L"", - false, - reply_msg) {} - diff --git a/chrome/browser/js_before_unload_handler.h b/chrome/browser/js_before_unload_handler.h index bb75356..3d85a3c 100644 --- a/chrome/browser/js_before_unload_handler.h +++ b/chrome/browser/js_before_unload_handler.h @@ -2,35 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_H__ -#define CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_H__ - -#include "chrome/browser/jsmessage_box_handler.h" - -class JavascriptBeforeUnloadHandler : public JavascriptMessageBoxHandler { - public: - // This will display a modal dialog box with a header and footer asking the - // the user if they wish to navigate away from a page, with additional text - // |message_text| between the header and footer. The users response is - // returned to the renderer using |reply_msg|. - static void RunBeforeUnloadDialog(WebContents* web_contents, - const std::wstring& message_text, - IPC::Message* reply_msg); - virtual ~JavascriptBeforeUnloadHandler() {} - - // views::DialogDelegate Methods: - virtual std::wstring GetWindowTitle() const; - virtual std::wstring GetDialogButtonLabel(DialogButton button) const; - - private: - // Called from RunBeforeUnloadDialog. Calls JavascriptMessageBoxHandler's - // constructor. - JavascriptBeforeUnloadHandler(WebContents* web_contents, - const std::wstring& message_text, - IPC::Message* reply_msg); - - DISALLOW_EVIL_CONSTRUCTORS(JavascriptBeforeUnloadHandler); -}; - -#endif // CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_H__ +#ifndef CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_H_ +#define CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_H_ + +// This will display a modal dialog box with a header and footer asking the +// the user if they wish to navigate away from a page, with additional text +// |message_text| between the header and footer. The users response is +// returned to the renderer using |reply_msg|. +void RunBeforeUnloadDialog(WebContents* web_contents, + const std::wstring& message_text, + IPC::Message* reply_msg); + +#endif // CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_H_ diff --git a/chrome/browser/js_before_unload_handler_win.cc b/chrome/browser/js_before_unload_handler_win.cc new file mode 100644 index 0000000..6b651b9 --- /dev/null +++ b/chrome/browser/js_before_unload_handler_win.cc @@ -0,0 +1,52 @@ +// Copyright (c) 2006-2008 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/js_before_unload_handler_win.h" + +#include "chrome/browser/app_modal_dialog_queue.h" +#include "chrome/common/l10n_util.h" +#include "chrome/views/message_box_view.h" + +#include "generated_resources.h" + +void RunBeforeUnloadDialog( + WebContents* web_contents, + const std::wstring& message_text, + IPC::Message* reply_msg) { + std::wstring full_message = + message_text + L"\n\n" + + l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_FOOTER); + JavascriptBeforeUnloadHandler* handler = + new JavascriptBeforeUnloadHandler(web_contents, full_message, reply_msg); + AppModalDialogQueue::AddDialog(handler); +} + +// JavascriptBeforeUnloadHandler ----------------------------------------------- + +JavascriptBeforeUnloadHandler::JavascriptBeforeUnloadHandler( + WebContents* web_contents, + const std::wstring& message_text, + IPC::Message* reply_msg) + : JavascriptMessageBoxHandler(web_contents, + MessageBoxView::kIsJavascriptConfirm, + message_text, + L"", + false, + reply_msg) { +} + +std::wstring JavascriptBeforeUnloadHandler::GetWindowTitle() const { + return l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE); +} + +std::wstring JavascriptBeforeUnloadHandler::GetDialogButtonLabel( + DialogButton button) const { + if (button == DialogDelegate::DIALOGBUTTON_OK) { + return l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); + } else if (button == DialogDelegate::DIALOGBUTTON_CANCEL) { + return l10n_util::GetString( + IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL); + } + return L""; +} diff --git a/chrome/browser/js_before_unload_handler_win.h b/chrome/browser/js_before_unload_handler_win.h new file mode 100644 index 0000000..4cd6067 --- /dev/null +++ b/chrome/browser/js_before_unload_handler_win.h @@ -0,0 +1,28 @@ +// Copyright (c) 2006-2008 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. + +#ifndef CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_WIN_H_ +#define CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_WIN_H_ + +#include "chrome/browser/jsmessage_box_handler_win.h" + +class WebContents; + +class JavascriptBeforeUnloadHandler : public JavascriptMessageBoxHandler { + public: + // Cross-platform code should use RunBeforeUnloadDialog. + JavascriptBeforeUnloadHandler(WebContents* web_contents, + const std::wstring& message_text, + IPC::Message* reply_msg); + virtual ~JavascriptBeforeUnloadHandler() {} + + // views::DialogDelegate Methods: + virtual std::wstring GetWindowTitle() const; + virtual std::wstring GetDialogButtonLabel(DialogButton button) const; + + private: + DISALLOW_COPY_AND_ASSIGN(JavascriptBeforeUnloadHandler); +}; + +#endif // CHROME_BROWSER_JS_BEFORE_UNLOAD_HANDLER_WIN_H_ diff --git a/chrome/browser/jsmessage_box_handler.cc b/chrome/browser/jsmessage_box_handler.cc deleted file mode 100644 index bf8b65d..0000000 --- a/chrome/browser/jsmessage_box_handler.cc +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2006-2008 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/jsmessage_box_handler.h" - -#include "chrome/browser/app_modal_dialog_queue.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/tab_contents/web_contents.h" -#include "chrome/common/gfx/text_elider.h" -#include "chrome/common/l10n_util.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/notification_types.h" -#include "chrome/common/pref_names.h" -#include "chrome/common/pref_service.h" -#include "chrome/views/message_box_view.h" -#include "chrome/views/window.h" - -#include "generated_resources.h" - -/////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxHandler, public: - -// static -void JavascriptMessageBoxHandler::RunJavascriptMessageBox( - WebContents* web_contents, - int dialog_flags, - const std::wstring& message_text, - const std::wstring& default_prompt_text, - bool display_suppress_checkbox, - IPC::Message* reply_msg) { - JavascriptMessageBoxHandler* handler = - new JavascriptMessageBoxHandler(web_contents, dialog_flags, - message_text, default_prompt_text, - display_suppress_checkbox, reply_msg); - AppModalDialogQueue::AddDialog(handler); -} - -JavascriptMessageBoxHandler::~JavascriptMessageBoxHandler() { -} - -////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxHandler, views::DialogDelegate implementation: - -int JavascriptMessageBoxHandler::GetDialogButtons() const { - int dialog_buttons = 0; - if (dialog_flags_ & MessageBoxView::kFlagHasOKButton) - dialog_buttons = DIALOGBUTTON_OK; - - if (dialog_flags_ & MessageBoxView::kFlagHasCancelButton) - dialog_buttons |= DIALOGBUTTON_CANCEL; - - return dialog_buttons; -} - -std::wstring JavascriptMessageBoxHandler::GetWindowTitle() const { - if (!web_contents_) - return std::wstring(); - - GURL url = web_contents_->GetURL(); - if (!url.has_host()) - return l10n_util::GetString(IDS_JAVASCRIPT_MESSAGEBOX_DEFAULT_TITLE); - - // We really only want the scheme, hostname, and port. - GURL::Replacements replacements; - replacements.ClearUsername(); - replacements.ClearPassword(); - replacements.ClearPath(); - replacements.ClearQuery(); - replacements.ClearRef(); - GURL clean_url = url.ReplaceComponents(replacements); - - // TODO(brettw) it should be easier than this to do the correct language - // handling without getting the accept language from the profile. - std::wstring base_address = gfx::ElideUrl(clean_url, ChromeFont(), 0, - web_contents_->profile()->GetPrefs()->GetString(prefs::kAcceptLanguages)); - // Force URL to have LTR directionality. - if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) - l10n_util::WrapStringWithLTRFormatting(&base_address); - return l10n_util::GetStringF(IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base_address); -} - -void JavascriptMessageBoxHandler::WindowClosing() { - dialog_ = NULL; - - if (message_box_view_->IsCheckBoxSelected() && web_contents_) - web_contents_->set_suppress_javascript_messages(true); - - delete this; -} - -bool JavascriptMessageBoxHandler::Cancel() { - // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame - // will receive it's 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. - AppModalDialogQueue::ShowNextDialog(); - - if (web_contents_) { - web_contents_->OnJavaScriptMessageBoxClosed(reply_msg_, false, - EmptyWString()); - } - return true; -} - -bool JavascriptMessageBoxHandler::Accept() { - AppModalDialogQueue::ShowNextDialog(); - - if (web_contents_) { - web_contents_->OnJavaScriptMessageBoxClosed( - reply_msg_, true, message_box_view_->GetInputText()); - } - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxHandler, views::AppModalDialogDelegate -// implementation: - -void JavascriptMessageBoxHandler::ShowModalDialog() { - // If the WebContents that created this dialog navigated away before this - // dialog became visible, simply show the next dialog if any. - if (!web_contents_) { - AppModalDialogQueue::ShowNextDialog(); - delete this; - return; - } - - web_contents_->Activate(); - HWND root_hwnd = GetAncestor(web_contents_->GetContainerHWND(), GA_ROOT); - dialog_ = views::Window::CreateChromeWindow(root_hwnd, gfx::Rect(), this); - dialog_->Show(); -} - -void JavascriptMessageBoxHandler::ActivateModalDialog() { - // Ensure that the dialog is visible and at the top of the z-order. These - // conditions may not be true if the dialog was opened on a different virtual - // desktop to the one the browser window is on. - dialog_->Show(); - dialog_->Activate(); -} - -/////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxHandler, views::WindowDelegate implementation: - -views::View* JavascriptMessageBoxHandler::GetContentsView() { - return message_box_view_; -} - -views::View* JavascriptMessageBoxHandler::GetInitiallyFocusedView() const { - if (message_box_view_->text_box()) - return message_box_view_->text_box(); - return views::AppModalDialogDelegate::GetInitiallyFocusedView(); -} - -/////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxHandler, private: - -void JavascriptMessageBoxHandler::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - bool web_contents_gone = false; - if (!web_contents_) - return; - - if (type == NOTIFY_NAV_ENTRY_COMMITTED && - Source(source).ptr() == web_contents_->controller()) - web_contents_gone = true; - - if (type == NOTIFY_TAB_CONTENTS_DESTROYED && - Source(source).ptr() == - static_cast(web_contents_)) - web_contents_gone = true; - - if (web_contents_gone) { - web_contents_ = NULL; - - // If the dialog is visible close it. - if (dialog_) - dialog_->Close(); - } -} - -JavascriptMessageBoxHandler::JavascriptMessageBoxHandler( - WebContents* web_contents, - int dialog_flags, - const std::wstring& message_text, - const std::wstring& default_prompt_text, - bool display_suppress_checkbox, - IPC::Message* reply_msg) - : web_contents_(web_contents), - reply_msg_(reply_msg), - dialog_flags_(dialog_flags), - dialog_(NULL), - message_box_view_(new MessageBoxView(dialog_flags, message_text, - default_prompt_text)) { - DCHECK(message_box_view_); - DCHECK(reply_msg_); - - if (display_suppress_checkbox) { - message_box_view_->SetCheckBoxLabel( - l10n_util::GetString(IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION)); - } - - // Make sure we get navigation notifications so we know when our parent - // contents will disappear or navigate to a different page. - registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, - NotificationService::AllSources()); - registrar_.Add(this, NOTIFY_TAB_CONTENTS_DESTROYED, - NotificationService::AllSources()); -} diff --git a/chrome/browser/jsmessage_box_handler.h b/chrome/browser/jsmessage_box_handler.h index 920d03d..0e33681 100644 --- a/chrome/browser/jsmessage_box_handler.h +++ b/chrome/browser/jsmessage_box_handler.h @@ -5,85 +5,23 @@ #ifndef CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_H_ #define CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_H_ +#include + #include "chrome/common/ipc_message.h" -#include "chrome/views/app_modal_dialog_delegate.h" -#include "chrome/common/notification_service.h" -#include "chrome/common/notification_registrar.h" -class MessageBoxView; class WebContents; -namespace views { -class Window; -} - -class JavascriptMessageBoxHandler - : public views::AppModalDialogDelegate, - public NotificationObserver { - public: - // Creates and runs a Javascript Message Box dialog. - // The dialog type is specified within |dialog_flags|, the - // default static display text is in |message_text| and if the dialog box is - // a user input prompt() box, the default text for the text field is in - // |default_prompt_text|. The result of the operation is returned using - // |reply_msg|. - static void RunJavascriptMessageBox(WebContents* web_contents, - int dialog_flags, - const std::wstring& message_text, - const std::wstring& default_prompt_text, - bool display_suppress_checkbox, - IPC::Message* reply_msg); - virtual ~JavascriptMessageBoxHandler(); - - // views::DialogDelegate Methods: - virtual int GetDialogButtons() const; - virtual std::wstring GetWindowTitle() const; - virtual void WindowClosing(); - virtual bool Cancel(); - virtual bool Accept(); - - // views::AppModalDialogDelegate - virtual void ShowModalDialog(); - virtual void ActivateModalDialog(); - - // views::WindowDelegate Methods: - virtual bool IsModal() const { return true; } - virtual views::View* GetContentsView(); - virtual views::View* GetInitiallyFocusedView() const; - - protected: - // Use RunJavaScriptMessageBox to use. - JavascriptMessageBoxHandler(WebContents* web_contents, - int dialog_flags, - const std::wstring& message_text, - const std::wstring& default_prompt_text, - bool display_suppress_checkbox, - IPC::Message* reply_msg); - - private: - // NotificationObserver implementation. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); - - NotificationRegistrar registrar_; - - // The message box view whose commands we handle. - MessageBoxView* message_box_view_; - - // The IPC message used to reply to the renderer when the message box - // is dismissed. - IPC::Message* reply_msg_; - - // The associated WebContents. Used to send IPC messages to the renderer. - WebContents* web_contents_; - - // Stores flags defined in message_box_view.h which describe the dialog box. - int dialog_flags_; - - // The dialog if it is currently visible. - views::Window* dialog_; - DISALLOW_EVIL_CONSTRUCTORS(JavascriptMessageBoxHandler); -}; +// Creates and runs a Javascript Message Box dialog. +// The dialog type is specified within |dialog_flags|, the +// default static display text is in |message_text| and if the dialog box is +// a user input prompt() box, the default text for the text field is in +// |default_prompt_text|. The result of the operation is returned using +// |reply_msg|. +void RunJavascriptMessageBox(WebContents* web_contents, + int dialog_flags, + const std::wstring& message_text, + const std::wstring& default_prompt_text, + bool display_suppress_checkbox, + IPC::Message* reply_msg); #endif // CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_H_ diff --git a/chrome/browser/jsmessage_box_handler_win.cc b/chrome/browser/jsmessage_box_handler_win.cc new file mode 100644 index 0000000..39d19cd --- /dev/null +++ b/chrome/browser/jsmessage_box_handler_win.cc @@ -0,0 +1,209 @@ +// Copyright (c) 2006-2008 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/jsmessage_box_handler_win.h" + +#include "chrome/browser/app_modal_dialog_queue.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/tab_contents/web_contents.h" +#include "chrome/common/gfx/text_elider.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_types.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/views/message_box_view.h" +#include "chrome/views/window.h" + +#include "generated_resources.h" + +void RunJavascriptMessageBox(WebContents* web_contents, + int dialog_flags, + const std::wstring& message_text, + const std::wstring& default_prompt_text, + bool display_suppress_checkbox, + IPC::Message* reply_msg) { + JavascriptMessageBoxHandler* handler = + new JavascriptMessageBoxHandler(web_contents, dialog_flags, + message_text, default_prompt_text, + display_suppress_checkbox, reply_msg); + AppModalDialogQueue::AddDialog(handler); +} + +JavascriptMessageBoxHandler::JavascriptMessageBoxHandler( + WebContents* web_contents, + int dialog_flags, + const std::wstring& message_text, + const std::wstring& default_prompt_text, + bool display_suppress_checkbox, + IPC::Message* reply_msg) + : web_contents_(web_contents), + reply_msg_(reply_msg), + dialog_flags_(dialog_flags), + dialog_(NULL), + message_box_view_(new MessageBoxView(dialog_flags, message_text, + default_prompt_text)) { + DCHECK(message_box_view_); + DCHECK(reply_msg_); + + if (display_suppress_checkbox) { + message_box_view_->SetCheckBoxLabel( + l10n_util::GetString(IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION)); + } + + // Make sure we get navigation notifications so we know when our parent + // contents will disappear or navigate to a different page. + registrar_.Add(this, NOTIFY_NAV_ENTRY_COMMITTED, + NotificationService::AllSources()); + registrar_.Add(this, NOTIFY_TAB_CONTENTS_DESTROYED, + NotificationService::AllSources()); +} + +JavascriptMessageBoxHandler::~JavascriptMessageBoxHandler() { +} + +////////////////////////////////////////////////////////////////////////////// +// JavascriptMessageBoxHandler, views::DialogDelegate implementation: + +int JavascriptMessageBoxHandler::GetDialogButtons() const { + int dialog_buttons = 0; + if (dialog_flags_ & MessageBoxView::kFlagHasOKButton) + dialog_buttons = DIALOGBUTTON_OK; + + if (dialog_flags_ & MessageBoxView::kFlagHasCancelButton) + dialog_buttons |= DIALOGBUTTON_CANCEL; + + return dialog_buttons; +} + +std::wstring JavascriptMessageBoxHandler::GetWindowTitle() const { + if (!web_contents_) + return std::wstring(); + + GURL url = web_contents_->GetURL(); + if (!url.has_host()) + return l10n_util::GetString(IDS_JAVASCRIPT_MESSAGEBOX_DEFAULT_TITLE); + + // We really only want the scheme, hostname, and port. + GURL::Replacements replacements; + replacements.ClearUsername(); + replacements.ClearPassword(); + replacements.ClearPath(); + replacements.ClearQuery(); + replacements.ClearRef(); + GURL clean_url = url.ReplaceComponents(replacements); + + // TODO(brettw) it should be easier than this to do the correct language + // handling without getting the accept language from the profile. + std::wstring base_address = gfx::ElideUrl(clean_url, ChromeFont(), 0, + web_contents_->profile()->GetPrefs()->GetString(prefs::kAcceptLanguages)); + // Force URL to have LTR directionality. + if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) + l10n_util::WrapStringWithLTRFormatting(&base_address); + return l10n_util::GetStringF(IDS_JAVASCRIPT_MESSAGEBOX_TITLE, base_address); +} + +void JavascriptMessageBoxHandler::WindowClosing() { + dialog_ = NULL; + + if (message_box_view_->IsCheckBoxSelected() && web_contents_) + web_contents_->set_suppress_javascript_messages(true); + + delete this; +} + +bool JavascriptMessageBoxHandler::Cancel() { + // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame + // will receive it's 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. + AppModalDialogQueue::ShowNextDialog(); + + if (web_contents_) { + web_contents_->OnJavaScriptMessageBoxClosed(reply_msg_, false, + EmptyWString()); + } + return true; +} + +bool JavascriptMessageBoxHandler::Accept() { + AppModalDialogQueue::ShowNextDialog(); + + if (web_contents_) { + web_contents_->OnJavaScriptMessageBoxClosed( + reply_msg_, true, message_box_view_->GetInputText()); + } + return true; +} + +////////////////////////////////////////////////////////////////////////////// +// JavascriptMessageBoxHandler, views::AppModalDialogDelegate +// implementation: + +void JavascriptMessageBoxHandler::ShowModalDialog() { + // If the WebContents that created this dialog navigated away before this + // dialog became visible, simply show the next dialog if any. + if (!web_contents_) { + AppModalDialogQueue::ShowNextDialog(); + delete this; + return; + } + + web_contents_->Activate(); + HWND root_hwnd = GetAncestor(web_contents_->GetContainerHWND(), GA_ROOT); + dialog_ = views::Window::CreateChromeWindow(root_hwnd, gfx::Rect(), this); + dialog_->Show(); +} + +void JavascriptMessageBoxHandler::ActivateModalDialog() { + // Ensure that the dialog is visible and at the top of the z-order. These + // conditions may not be true if the dialog was opened on a different virtual + // desktop to the one the browser window is on. + dialog_->Show(); + dialog_->Activate(); +} + +/////////////////////////////////////////////////////////////////////////////// +// JavascriptMessageBoxHandler, views::WindowDelegate implementation: + +views::View* JavascriptMessageBoxHandler::GetContentsView() { + return message_box_view_; +} + +views::View* JavascriptMessageBoxHandler::GetInitiallyFocusedView() const { + if (message_box_view_->text_box()) + return message_box_view_->text_box(); + return views::AppModalDialogDelegate::GetInitiallyFocusedView(); +} + +/////////////////////////////////////////////////////////////////////////////// +// JavascriptMessageBoxHandler, private: + +void JavascriptMessageBoxHandler::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + bool web_contents_gone = false; + if (!web_contents_) + return; + + if (type == NOTIFY_NAV_ENTRY_COMMITTED && + Source(source).ptr() == web_contents_->controller()) + web_contents_gone = true; + + if (type == NOTIFY_TAB_CONTENTS_DESTROYED && + Source(source).ptr() == + static_cast(web_contents_)) + web_contents_gone = true; + + if (web_contents_gone) { + web_contents_ = NULL; + + // If the dialog is visible close it. + if (dialog_) + dialog_->Close(); + } +} + diff --git a/chrome/browser/jsmessage_box_handler_win.h b/chrome/browser/jsmessage_box_handler_win.h new file mode 100644 index 0000000..432f59b --- /dev/null +++ b/chrome/browser/jsmessage_box_handler_win.h @@ -0,0 +1,76 @@ +// Copyright (c) 2006-2008 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. + +#ifndef CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_WIN_H_ +#define CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_WIN_H_ + +#include "chrome/browser/jsmessage_box_handler.h" +#include "chrome/common/ipc_message.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_registrar.h" +#include "chrome/views/app_modal_dialog_delegate.h" + +class MessageBoxView; +class WebContents; +namespace views { +class Window; +} + +class JavascriptMessageBoxHandler + : public views::AppModalDialogDelegate, + public NotificationObserver { + public: + // Cross-platform code should use RunJavaScriptMessageBox. + JavascriptMessageBoxHandler(WebContents* web_contents, + int dialog_flags, + const std::wstring& message_text, + const std::wstring& default_prompt_text, + bool display_suppress_checkbox, + IPC::Message* reply_msg); + virtual ~JavascriptMessageBoxHandler(); + + // views::DialogDelegate Methods: + virtual int GetDialogButtons() const; + virtual std::wstring GetWindowTitle() const; + virtual void WindowClosing(); + virtual bool Cancel(); + virtual bool Accept(); + + // views::AppModalDialogDelegate + virtual void ShowModalDialog(); + virtual void ActivateModalDialog(); + + // views::WindowDelegate Methods: + virtual bool IsModal() const { return true; } + virtual views::View* GetContentsView(); + virtual views::View* GetInitiallyFocusedView() const; + + private: + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + NotificationRegistrar registrar_; + + // The message box view whose commands we handle. + MessageBoxView* message_box_view_; + + // The IPC message used to reply to the renderer when the message box + // is dismissed. + IPC::Message* reply_msg_; + + // The associated WebContents. Used to send IPC messages to the renderer. + WebContents* web_contents_; + + // Stores flags defined in message_box_view.h which describe the dialog box. + int dialog_flags_; + + // The dialog if it is currently visible. + views::Window* dialog_; + + DISALLOW_COPY_AND_ASSIGN(JavascriptMessageBoxHandler); +}; + +#endif // CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_WIN_H_ diff --git a/chrome/browser/tab_contents/web_contents.cc b/chrome/browser/tab_contents/web_contents.cc index 4f4af00..b834972 100644 --- a/chrome/browser/tab_contents/web_contents.cc +++ b/chrome/browser/tab_contents/web_contents.cc @@ -1026,12 +1026,8 @@ void WebContents::RunJavaScriptMessage( TimeDelta::FromMilliseconds(kJavascriptMessageExpectedDelay)) show_suppress_checkbox = true; - JavascriptMessageBoxHandler::RunJavascriptMessageBox(this, - flags, - message, - default_prompt, - show_suppress_checkbox, - reply_msg); + RunJavascriptMessageBox(this, flags, message, default_prompt, + show_suppress_checkbox, reply_msg); } else { // If we are suppressing messages, just reply as is if the user immediately // pressed "Cancel". @@ -1040,9 +1036,8 @@ void WebContents::RunJavaScriptMessage( } void WebContents::RunBeforeUnloadConfirm(const std::wstring& message, - IPC::Message* reply_msg) { - JavascriptBeforeUnloadHandler::RunBeforeUnloadDialog(this, message, - reply_msg); + IPC::Message* reply_msg) { + RunBeforeUnloadDialog(this, message, reply_msg); } void WebContents::ShowModalHTMLDialog(const GURL& url, int width, int height, -- cgit v1.1