diff options
28 files changed, 1194 insertions, 715 deletions
diff --git a/chrome/browser/app_modal_dialog.cc b/chrome/browser/app_modal_dialog.cc index af02d02..815b25f 100644 --- a/chrome/browser/app_modal_dialog.cc +++ b/chrome/browser/app_modal_dialog.cc @@ -5,72 +5,18 @@ #include "chrome/browser/app_modal_dialog.h" #include "chrome/browser/app_modal_dialog_queue.h" -#include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_service.h" #include "chrome/common/notification_type.h" -#include "ipc/ipc_message.h" -AppModalDialog::AppModalDialog(JavaScriptMessageBoxClient* client, - 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::AppModalDialog(TabContents* tab_contents, + const std::wstring& title) : dialog_(NULL), - client_(client), - tab_contents_(client_->AsTabContents()), - extension_host_(client_->AsExtensionHost()), - skip_this_dialog_(false), + tab_contents_(tab_contents), title_(title), - dialog_flags_(dialog_flags), - message_text_(message_text), - default_prompt_text_(default_prompt_text), - display_suppress_checkbox_(display_suppress_checkbox), - is_before_unload_dialog_(is_before_unload_dialog), - reply_msg_(reply_msg) { - InitNotifications(); - DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL)); + skip_this_dialog_(false) { } -void AppModalDialog::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 client, since it's now invalid. - skip_this_dialog_ = true; - client_ = NULL; - CloseModalDialog(); -} - -void AppModalDialog::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 AppModalDialog::ShowModalDialog() { // If the TabContents or ExtensionHost that created this dialog navigated @@ -92,57 +38,14 @@ void AppModalDialog::ShowModalDialog() { NotificationService::NoDetails()); } -void AppModalDialog::OnCancel() { - // 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. - Singleton<AppModalDialogQueue>()->ShowNextDialog(); - - if (!skip_this_dialog_) { - client_->OnMessageBoxClosed(reply_msg_, false, std::wstring()); - } - - Cleanup(); +void AppModalDialog::Cleanup() { + NotificationService::current()->Notify( + NotificationType::APP_MODAL_DIALOG_CLOSED, + Source<AppModalDialog>(this), + NotificationService::NoDetails()); } -void AppModalDialog::OnAccept(const std::wstring& prompt_text, - bool suppress_js_messages) { +void AppModalDialog::CompleteDialog() { Singleton<AppModalDialogQueue>()->ShowNextDialog(); - - if (!skip_this_dialog_) { - client_->OnMessageBoxClosed(reply_msg_, true, prompt_text); - if (suppress_js_messages) - client_->SetSuppressMessageBoxes(true); - } - - Cleanup(); } -void AppModalDialog::OnClose() { - Cleanup(); -} - -void AppModalDialog::Cleanup() { - if (skip_this_dialog_) { - // We can't use the client_, 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 - } - NotificationService::current()->Notify( - NotificationType::APP_MODAL_DIALOG_CLOSED, - Source<AppModalDialog>(this), - NotificationService::NoDetails()); -} diff --git a/chrome/browser/app_modal_dialog.h b/chrome/browser/app_modal_dialog.h index bbb352a..715e12e 100644 --- a/chrome/browser/app_modal_dialog.h +++ b/chrome/browser/app_modal_dialog.h @@ -11,9 +11,10 @@ #include "chrome/common/notification_observer.h" #include "chrome/common/notification_registrar.h" +// Define NativeDialog type as platform specific dialog view. #if defined(OS_WIN) -class JavascriptMessageBoxDialog; -typedef JavascriptMessageBoxDialog* NativeDialog; +class ModalDialogDelegate; +typedef ModalDialogDelegate* NativeDialog; #elif defined(OS_MACOSX) #if __OBJC__ @class NSAlert; @@ -22,33 +23,25 @@ class NSAlert; #endif typedef NSAlert* NativeDialog; #elif defined(OS_POSIX) +typedef struct _GtkDialog GtkDialog; typedef struct _GtkWidget GtkWidget; +typedef int gint; typedef GtkWidget* NativeDialog; #endif -class ExtensionHost; -class JavaScriptMessageBoxClient; class TabContents; namespace IPC { class Message; } -// A controller+model class for javascript alert, confirm, prompt, and -// onbeforeunload dialog boxes. |NativeDialog| is a platform specific -// view. -class AppModalDialog : public NotificationObserver { +// A controller+model base class for modal dialogs. +class AppModalDialog { public: // A union of data necessary to determine the type of message box to - // show. |dialog_flags| is a MessageBox flag. - AppModalDialog(JavaScriptMessageBoxClient* client, - 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(); + // show. |tab_contents| parameter is optional, if provided that tab will be + // activated before the modal dialog is displayed. + AppModalDialog(TabContents* tab_contents, const std::wstring& title); + virtual ~AppModalDialog(); // Called by the app modal window queue when it is time to show this window. void ShowModalDialog(); @@ -60,7 +53,15 @@ class AppModalDialog : public NotificationObserver { // NativeDialog is closed, it should call OnAccept or OnCancel to notify the // renderer of the user's action. The NativeDialog is also expected to // delete the AppModalDialog associated with it. - void CreateAndShowDialog(); + virtual void CreateAndShowDialog(); + +#if defined(OS_LINUX) + virtual void HandleDialogResponse(GtkDialog* dialog, gint response_id) = 0; + // Callback for dialog response calls, passes results to specialized + // HandleDialogResponse() implementation. + static void OnDialogResponse(GtkDialog* dialog, gint response_id, + AppModalDialog* app_modal_dialog); +#endif // Close the dialog if it is showing. void CloseModalDialog(); @@ -68,72 +69,38 @@ class AppModalDialog : public NotificationObserver { // Called by the app modal window queue to activate the window. void ActivateModalDialog(); - ///////////////////////////////////////////////////////////////////////////// - // Getters so NativeDialog can get information about the message box. - JavaScriptMessageBoxClient* client() { - return client_; - } - int dialog_flags() { - return dialog_flags_; - } + // Completes dialog handling, shows next modal dialog from the queue. + void CompleteDialog(); + + // Dialog window title. std::wstring title() { return title_; } - bool is_before_unload_dialog() { - return is_before_unload_dialog_; - } - - // Callbacks from NativeDialog when the user accepts or cancels the dialog. - void OnCancel(); - void OnAccept(const std::wstring& prompt_text, bool suppress_js_messages); - void OnClose(); // Helper methods used to query or control the dialog. This is used by // automation. - int GetDialogButtons(); - void AcceptWindow(); - void CancelWindow(); - - private: - void InitNotifications(); - - // NotificationObserver implementation. - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); + virtual int GetDialogButtons() = 0; + virtual void AcceptWindow() = 0; + virtual void CancelWindow() = 0; - // Cleans up after the dialog closes for any reason: sends close - // notification and re-enables input events. - void Cleanup(); - - NotificationRegistrar registrar_; + protected: + // Cleans up the dialog class. + virtual void Cleanup(); + // Creates the actual platform specific dialog view class. + virtual NativeDialog CreateNativeDialog() = 0; // A reference to the platform native dialog box. NativeDialog dialog_; - // An implementation of the client interface to provide supporting methods - // and receive results. - JavaScriptMessageBoxClient* client_; - - // The client_ as an ExtensionHost, cached for use during notifications that - // may arrive after the client has entered its destructor (and is thus - // treated as a base JavaScriptMessageBoxClient). This will be NULL if the - // client is not an ExtensionHost. + // Parent tab contents. TabContents* tab_contents_; - ExtensionHost* extension_host_; + + // Information about the message box is held in the following variables. + std::wstring title_; // True if the dialog should no longer be shown, e.g. because the underlying // tab navigated away while the dialog was queued. bool skip_this_dialog_; - - // Information about the message box is held in the following variables. - std::wstring title_; - int dialog_flags_; - std::wstring message_text_; - std::wstring default_prompt_text_; - bool display_suppress_checkbox_; - bool is_before_unload_dialog_; - IPC::Message* reply_msg_; }; #endif // CHROME_BROWSER_APP_MODAL_DIALOG_H_ diff --git a/chrome/browser/app_modal_dialog_gtk.cc b/chrome/browser/app_modal_dialog_gtk.cc index a58e3d3..2cdcf00 100644 --- a/chrome/browser/app_modal_dialog_gtk.cc +++ b/chrome/browser/app_modal_dialog_gtk.cc @@ -18,172 +18,16 @@ #include "grit/generated_resources.h" #include "grit/locale_settings.h" -namespace { - -// We stash pointers to widgets on the gtk_dialog so we can refer to them -// after dialog creation. -const char kPromptTextId[] = "chrome_prompt_text"; -const char kSuppressCheckboxId[] = "chrome_suppress_checkbox"; - -// If there's a text entry in the dialog, get the text from the first one and -// return it. -std::wstring GetPromptText(GtkDialog* dialog) { - GtkWidget* widget = static_cast<GtkWidget*>( - g_object_get_data(G_OBJECT(dialog), kPromptTextId)); - if (widget) - return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(widget))); - return std::wstring(); -} - -// If there's a toggle button in the dialog, return the toggled state. -// Otherwise, return false. -bool ShouldSuppressJSDialogs(GtkDialog* dialog) { - GtkWidget* widget = static_cast<GtkWidget*>( - g_object_get_data(G_OBJECT(dialog), kSuppressCheckboxId)); - if (widget) - return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); - return false; -} - -void OnDialogResponse(GtkDialog* dialog, gint response_id, - AppModalDialog* app_modal_dialog) { - switch (response_id) { - case GTK_RESPONSE_OK: - // The first arg is the prompt text and the second is true if we want to - // suppress additional popups from the page. - app_modal_dialog->OnAccept(GetPromptText(dialog), - ShouldSuppressJSDialogs(dialog)); - break; - - case GTK_RESPONSE_CANCEL: - case GTK_RESPONSE_DELETE_EVENT: // User hit the X on the dialog. - app_modal_dialog->OnCancel(); - break; - - default: - NOTREACHED(); - } - gtk_widget_destroy(GTK_WIDGET(dialog)); - - // Now that the dialog is gone, we can put all the windows into separate - // window groups so other dialogs are no longer app modal. - for (BrowserList::const_iterator it = BrowserList::begin(); - it != BrowserList::end(); ++it) { - GtkWindowGroup* window_group = gtk_window_group_new(); - gtk_window_group_add_window(window_group, - (*it)->window()->GetNativeHandle()); - g_object_unref(window_group); - } - - delete app_modal_dialog; -} - -} // namespace - AppModalDialog::~AppModalDialog() { } void AppModalDialog::CreateAndShowDialog() { - GtkButtonsType buttons = GTK_BUTTONS_NONE; - GtkMessageType message_type = GTK_MESSAGE_OTHER; - // We add in the OK button manually later because we want to focus it - // explicitly. - switch (dialog_flags_) { - case MessageBoxFlags::kIsJavascriptAlert: - buttons = GTK_BUTTONS_NONE; - message_type = GTK_MESSAGE_WARNING; - break; - - case MessageBoxFlags::kIsJavascriptConfirm: - if (is_before_unload_dialog_) { - // onbeforeunload also uses a confirm prompt, it just has custom - // buttons. We add the buttons using gtk_dialog_add_button below. - buttons = GTK_BUTTONS_NONE; - } else { - buttons = GTK_BUTTONS_CANCEL; - } - message_type = GTK_MESSAGE_QUESTION; - break; - - case MessageBoxFlags::kIsJavascriptPrompt: - buttons = GTK_BUTTONS_CANCEL; - message_type = GTK_MESSAGE_QUESTION; - break; - - default: - NOTREACHED(); - } - - // We want the alert to be app modal so put all the browser windows into the - // same window group. - GtkWindowGroup* window_group = gtk_window_group_new(); - for (BrowserList::const_iterator it = BrowserList::begin(); - it != BrowserList::end(); ++it) { - gtk_window_group_add_window(window_group, - (*it)->window()->GetNativeHandle()); - } - g_object_unref(window_group); - - gfx::NativeWindow window = client_->GetMessageBoxRootWindow(); - dialog_ = gtk_message_dialog_new(window, GTK_DIALOG_MODAL, - message_type, buttons, "%s", WideToUTF8(message_text_).c_str()); - gtk_util::ApplyMessageDialogQuirks(dialog_); - gtk_window_set_title(GTK_WINDOW(dialog_), WideToUTF8(title_).c_str()); - - // Adjust content area as needed. Set up the prompt text entry or - // suppression check box. - if (MessageBoxFlags::kIsJavascriptPrompt == dialog_flags_) { - // TODO(tc): Replace with gtk_dialog_get_content_area() when using GTK 2.14+ - GtkWidget* contents_vbox = GTK_DIALOG(dialog_)->vbox; - GtkWidget* text_box = gtk_entry_new(); - gtk_entry_set_text(GTK_ENTRY(text_box), - WideToUTF8(default_prompt_text_).c_str()); - gtk_box_pack_start(GTK_BOX(contents_vbox), text_box, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(dialog_), kPromptTextId, text_box); - gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE); - } - - if (display_suppress_checkbox_) { - GtkWidget* contents_vbox = GTK_DIALOG(dialog_)->vbox; - GtkWidget* check_box = gtk_check_button_new_with_label( - l10n_util::GetStringUTF8( - IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION).c_str()); - gtk_box_pack_start(GTK_BOX(contents_vbox), check_box, TRUE, TRUE, 0); - g_object_set_data(G_OBJECT(dialog_), kSuppressCheckboxId, check_box); - } - - // Adjust buttons/action area as needed. - if (is_before_unload_dialog_) { - std::string button_text = l10n_util::GetStringUTF8( - IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); - gtk_dialog_add_button(GTK_DIALOG(dialog_), button_text.c_str(), - GTK_RESPONSE_OK); - - button_text = l10n_util::GetStringUTF8( - IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL); - gtk_dialog_add_button(GTK_DIALOG(dialog_), button_text.c_str(), - GTK_RESPONSE_CANCEL); - } else { - // Add the OK button and focus it. - GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(dialog_), - GTK_STOCK_OK, GTK_RESPONSE_OK); - if (MessageBoxFlags::kIsJavascriptPrompt != dialog_flags_) - gtk_widget_grab_focus(ok_button); - } - - gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK); - g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponse), this); - - gtk_widget_show_all(GTK_WIDGET(GTK_DIALOG(dialog_))); +} - // Suggest a minimum size. - gint width; - GtkRequisition req; - gtk_widget_size_request(dialog_, &req); - gtk_util::GetWidgetSizeFromResources(dialog_, IDS_ALERT_DIALOG_WIDTH_CHARS, 0, - &width, NULL); - if (width > req.width) - gtk_widget_set_size_request(dialog_, width, -1); +// static +void AppModalDialog::OnDialogResponse(GtkDialog* dialog, gint response_id, + AppModalDialog* app_modal_dialog) { + app_modal_dialog->HandleDialogResponse(dialog, response_id); } void AppModalDialog::ActivateModalDialog() { @@ -191,31 +35,13 @@ void AppModalDialog::ActivateModalDialog() { } void AppModalDialog::CloseModalDialog() { - OnDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_DELETE_EVENT, this); -} - -int AppModalDialog::GetDialogButtons() { - switch (dialog_flags_) { - case MessageBoxFlags::kIsJavascriptAlert: - return MessageBoxFlags::DIALOGBUTTON_OK; - - case MessageBoxFlags::kIsJavascriptConfirm: - return MessageBoxFlags::DIALOGBUTTON_OK | - MessageBoxFlags::DIALOGBUTTON_CANCEL; - - case MessageBoxFlags::kIsJavascriptPrompt: - return MessageBoxFlags::DIALOGBUTTON_OK; - - default: - NOTREACHED(); - return 0; - } + HandleDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_DELETE_EVENT); } void AppModalDialog::AcceptWindow() { - OnDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_OK, this); + HandleDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_OK); } void AppModalDialog::CancelWindow() { - OnDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_CANCEL, this); + HandleDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_CANCEL); } diff --git a/chrome/browser/app_modal_dialog_mac.mm b/chrome/browser/app_modal_dialog_mac.mm index 3b64a87..3d1c82a 100644 --- a/chrome/browser/app_modal_dialog_mac.mm +++ b/chrome/browser/app_modal_dialog_mac.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -6,150 +6,11 @@ #import <Cocoa/Cocoa.h> -#include "app/l10n_util_mac.h" -#include "app/message_box_flags.h" -#import "base/cocoa_protocols_mac.h" -#include "base/sys_string_conversions.h" -#include "grit/app_strings.h" -#include "grit/generated_resources.h" - -// Helper object that receives the notification that the dialog/sheet is -// going away. Is responsible for cleaning itself up. -@interface AppModalDialogHelper : NSObject<NSAlertDelegate> { - @private - NSAlert* alert_; - NSTextField* textField_; // WEAK; owned by alert_ -} - -- (NSAlert*)alert; -- (NSTextField*)textField; -- (void)alertDidEnd:(NSAlert *)alert - returnCode:(int)returnCode - contextInfo:(void*)contextInfo; - -@end - -@implementation AppModalDialogHelper - -- (NSAlert*)alert { - alert_ = [[NSAlert alloc] init]; - return alert_; -} - -- (NSTextField*)textField { - textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; - [alert_ setAccessoryView:textField_]; - [textField_ release]; - - return textField_; -} - -- (void)dealloc { - [alert_ release]; - [super dealloc]; -} - -// |contextInfo| is the bridge back to the C++ AppModalDialog. When complete, -// autorelease to clean ourselves up. -- (void)alertDidEnd:(NSAlert*)alert - returnCode:(int)returnCode - contextInfo:(void*)contextInfo { - AppModalDialog* bridge = reinterpret_cast<AppModalDialog*>(contextInfo); - std::wstring input; - if (textField_) - input = base::SysNSStringToWide([textField_ stringValue]); - switch (returnCode) { - case NSAlertFirstButtonReturn: { // OK - bool shouldSuppress = false; - if ([alert showsSuppressionButton]) - shouldSuppress = [[alert suppressionButton] state] == NSOnState; - bridge->OnAccept(input, shouldSuppress); - break; - } - case NSAlertSecondButtonReturn: { // Cancel - bridge->OnCancel(); - break; - } - case NSRunStoppedResponse: { // Window was closed underneath us - // Need to call OnCancel() because there is some cleanup that needs - // to be done. It won't call back to the javascript since the - // AppModalDialog knows that the TabContents was destroyed. - bridge->OnCancel(); - break; - } - default: { - NOTREACHED(); - } - } - [self autorelease]; - delete bridge; // Done with the dialog, it needs be destroyed. -} -@end - AppModalDialog::~AppModalDialog() { } void AppModalDialog::CreateAndShowDialog() { - // Determine the names of the dialog buttons based on the flags. "Default" - // is the OK button. "Other" is the cancel button. We don't use the - // "Alternate" button in NSRunAlertPanel. - NSString* default_button = l10n_util::GetNSStringWithFixup(IDS_APP_OK); - NSString* other_button = l10n_util::GetNSStringWithFixup(IDS_APP_CANCEL); - bool text_field = false; - bool one_button = false; - switch (dialog_flags_) { - case MessageBoxFlags::kIsJavascriptAlert: - one_button = true; - break; - case MessageBoxFlags::kIsJavascriptConfirm: - if (is_before_unload_dialog_) { - default_button = l10n_util::GetNSStringWithFixup( - IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); - other_button = l10n_util::GetNSStringWithFixup( - IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL); - } - break; - case MessageBoxFlags::kIsJavascriptPrompt: - text_field = true; - break; - - default: - NOTREACHED(); - } - - // Create a helper which will receive the sheet ended selector. It will - // delete itself when done. It doesn't need anything passed to its init - // as it will get a contextInfo parameter. - AppModalDialogHelper* helper = [[AppModalDialogHelper alloc] init]; - - // Show the modal dialog. - NSAlert* alert = [helper alert]; - dialog_ = alert; - NSTextField* field = nil; - if (text_field) { - field = [helper textField]; - [field setStringValue:base::SysWideToNSString(default_prompt_text_)]; - } - [alert setDelegate:helper]; - [alert setInformativeText:base::SysWideToNSString(message_text_)]; - [alert setMessageText:base::SysWideToNSString(title_)]; - [alert addButtonWithTitle:default_button]; - if (!one_button) - [alert addButtonWithTitle:other_button]; - if (display_suppress_checkbox_) { - [alert setShowsSuppressionButton:YES]; - NSString* suppression_title = l10n_util::GetNSStringWithFixup( - IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION); - [[alert suppressionButton] setTitle:suppression_title]; - } - - [alert beginSheetModalForWindow:nil // nil here makes it app-modal - modalDelegate:helper - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) - contextInfo:this]; - - if (field) - [[alert window] makeFirstResponder:field]; + NOTIMPLEMENTED(); } void AppModalDialog::ActivateModalDialog() { @@ -162,16 +23,3 @@ void AppModalDialog::CloseModalDialog() { [NSApp endSheet:[alert window]]; dialog_ = nil; } - -int AppModalDialog::GetDialogButtons() { - NOTIMPLEMENTED(); - return 0; -} - -void AppModalDialog::AcceptWindow() { - NOTIMPLEMENTED(); -} - -void AppModalDialog::CancelWindow() { - NOTIMPLEMENTED(); -} diff --git a/chrome/browser/app_modal_dialog_win.cc b/chrome/browser/app_modal_dialog_win.cc index 897c811..c892881 100644 --- a/chrome/browser/app_modal_dialog_win.cc +++ b/chrome/browser/app_modal_dialog_win.cc @@ -6,14 +6,14 @@ #include "base/logging.h" #include "chrome/browser/views/jsmessage_box_dialog.h" +#include "views/window/dialog_delegate.h" #include "views/window/window.h" AppModalDialog::~AppModalDialog() { } void AppModalDialog::CreateAndShowDialog() { - dialog_ = new JavascriptMessageBoxDialog(this, message_text_, - default_prompt_text_, display_suppress_checkbox_); + dialog_ = CreateNativeDialog(); DCHECK(dialog_->IsModal()); dialog_->ShowModalDialog(); } @@ -25,19 +25,3 @@ void AppModalDialog::ActivateModalDialog() { void AppModalDialog::CloseModalDialog() { dialog_->CloseModalDialog(); } - -int AppModalDialog::GetDialogButtons() { - return dialog_->GetDialogButtons(); -} - -void AppModalDialog::AcceptWindow() { - views::DialogClientView* client_view = - dialog_->window()->GetClientView()->AsDialogClientView(); - client_view->AcceptWindow(); -} - -void AppModalDialog::CancelWindow() { - views::DialogClientView* client_view = - dialog_->window()->GetClientView()->AsDialogClientView(); - client_view->CancelWindow(); -} diff --git a/chrome/browser/browser_browsertest.cc b/chrome/browser/browser_browsertest.cc index efae3ad..cfd54bf 100644 --- a/chrome/browser/browser_browsertest.cc +++ b/chrome/browser/browser_browsertest.cc @@ -13,6 +13,7 @@ #include "chrome/browser/defaults.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/extensions_service.h" +#include "chrome/browser/js_modal_dialog.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -260,7 +261,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTest, MAYBE_SingleBeforeUnloadAfterWindowClose) { alert->AcceptWindow(); alert = ui_test_utils::WaitForAppModalDialog(); - EXPECT_FALSE(alert->is_before_unload_dialog()); + EXPECT_FALSE(static_cast<JavaScriptAppModalDialog*>(alert)-> + is_before_unload_dialog()); alert->AcceptWindow(); } diff --git a/chrome/browser/cookie_modal_dialog.cc b/chrome/browser/cookie_modal_dialog.cc new file mode 100644 index 0000000..c6ccdc1 --- /dev/null +++ b/chrome/browser/cookie_modal_dialog.cc @@ -0,0 +1,33 @@ +// 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/cookie_modal_dialog.h" + +#include "chrome/browser/views/cookie_prompt_view.h" +#include "googleurl/src/gurl.h" + +CookiePromptModalDialog::CookiePromptModalDialog( + TabContents* tab_contents, + const GURL& url, + const std::string& cookie_line, + CookiePromptModalDialogDelegate* delegate) + : AppModalDialog(tab_contents, std::wstring()), + url_(url), + cookie_line_(cookie_line), + cookie_ui_(true), + delegate_(delegate) { +} + + +CookiePromptModalDialog::CookiePromptModalDialog( + TabContents* tab_contents, + const BrowsingDataLocalStorageHelper::LocalStorageInfo& storage_info, + CookiePromptModalDialogDelegate* delegate) + : AppModalDialog(tab_contents, std::wstring()), + storage_info_(storage_info), + cookie_ui_(false), + delegate_(delegate) { +} + + diff --git a/chrome/browser/cookie_modal_dialog.h b/chrome/browser/cookie_modal_dialog.h new file mode 100644 index 0000000..390e6137 --- /dev/null +++ b/chrome/browser/cookie_modal_dialog.h @@ -0,0 +1,65 @@ +// 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. + +#ifndef CHROME_BROWSER_COOKIE_MODAL_DIALOG_H_ +#define CHROME_BROWSER_COOKIE_MODAL_DIALOG_H_ + +#include <string> + +#include "chrome/browser/app_modal_dialog.h" +#include "chrome/browser/browsing_data_local_storage_helper.h" +#include "chrome/browser/cookie_prompt_modal_dialog_delegate.h" +#include "googleurl/src/gurl.h" + + +// A controller+model class for cookie and local storage warning prompt. +// |NativeDialog| is a platform specific view. +class CookiePromptModalDialog : public AppModalDialog { + public: + // A union of data necessary to determine the type of message box to + // show. + CookiePromptModalDialog(TabContents* tab_contents, + const GURL& url, + const std::string& cookie_line, + CookiePromptModalDialogDelegate* delegate); + CookiePromptModalDialog( + TabContents* tab_contents, + const BrowsingDataLocalStorageHelper::LocalStorageInfo& storage_info, + CookiePromptModalDialogDelegate* delegate); + virtual ~CookiePromptModalDialog() {} + + // AppModalDialog overrides. + virtual int GetDialogButtons(); + virtual void AcceptWindow(); + virtual void CancelWindow(); + + protected: + // AppModalDialog overrides. + virtual NativeDialog CreateNativeDialog(); +#if defined(OS_LINUX) + virtual void HandleDialogResponse(GtkDialog* dialog, gint response_id); +#endif + + private: + // Cookie url. + GURL url_; + + // Cookie to display. + std::string cookie_line_; + + // Local storage info to display. + BrowsingDataLocalStorageHelper::LocalStorageInfo storage_info_; + + // Whether we're showing cookie UI as opposed to other site data. + bool cookie_ui_; + + // Delegate. The caller should provide one in order to receive results + // from this delegate. + CookiePromptModalDialogDelegate* delegate_; + + DISALLOW_COPY_AND_ASSIGN(CookiePromptModalDialog); +}; + +#endif // CHROME_BROWSER_COOKIE_MODAL_DIALOG_H_ + diff --git a/chrome/browser/cookie_modal_dialog_views.cc b/chrome/browser/cookie_modal_dialog_views.cc new file mode 100644 index 0000000..4324059 --- /dev/null +++ b/chrome/browser/cookie_modal_dialog_views.cc @@ -0,0 +1,55 @@ +// 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/cookie_modal_dialog.h" + +#include "base/logging.h" +#include "chrome/browser/views/cookie_prompt_view.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "views/window/window.h" + + +// TODO(zelidrag): Make this work on Linux (views). + +int CookiePromptModalDialog::GetDialogButtons() { +#if defined(OS_WIN) + return dialog_->GetDialogButtons(); +#else + return 0; +#endif +} + +void CookiePromptModalDialog::AcceptWindow() { +#if defined(OS_WIN) + views::DialogClientView* client_view = + dialog_->window()->GetClientView()->AsDialogClientView(); + client_view->AcceptWindow(); +#endif +} + +void CookiePromptModalDialog::CancelWindow() { +#if defined(OS_WIN) + views::DialogClientView* client_view = + dialog_->window()->GetClientView()->AsDialogClientView(); + client_view->CancelWindow(); +#endif +} + + +NativeDialog CookiePromptModalDialog::CreateNativeDialog() { +#if defined(OS_WIN) + if (cookie_ui_) { + return new CookiePromptView(this, + tab_contents_->GetMessageBoxRootWindow(), + tab_contents_->profile(), + url_, cookie_line_, delegate_); + } + return new CookiePromptView(this, + tab_contents_->GetMessageBoxRootWindow(), + tab_contents_->profile(), + storage_info_, delegate_); +#else + return NULL; +#endif +} diff --git a/chrome/browser/cookie_prompt_modal_dialog_delegate.h b/chrome/browser/cookie_prompt_modal_dialog_delegate.h new file mode 100644 index 0000000..0be9b85 --- /dev/null +++ b/chrome/browser/cookie_prompt_modal_dialog_delegate.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef CHROME_BROWSER_COOKIE_PROMPT_MODAL_DIALOG_DELEGATE_H_ +#define CHROME_BROWSER_COOKIE_PROMPT_MODAL_DIALOG_DELEGATE_H_ + +// Delegate for handling modal dialog results from CookiePromptModalDialog. +class CookiePromptModalDialogDelegate { + public: + // Allow site data to be set. If |remember| is true, record this decision + // for this host. + virtual void AllowSiteData(bool remember, bool session_expire) = 0; + + // Block site data from being stored. If |remember| is true, record this + // decision for this host. + virtual void BlockSiteData(bool remember) = 0; + + protected: + virtual ~CookiePromptModalDialogDelegate() {} +}; + +#endif // CHROME_BROWSER_COOKIE_PROMPT_MODAL_DIALOG_DELEGATE_H_ + diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index ec519ff..4ca6e18 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -23,7 +23,7 @@ #include "chrome/browser/extensions/extension_tabs_module.h" #include "chrome/browser/in_process_webkit/dom_storage_context.h" #include "chrome/browser/in_process_webkit/webkit_context.h" -#include "chrome/browser/jsmessage_box_handler.h" +#include "chrome/browser/message_box_handler.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/render_process_host.h" diff --git a/chrome/browser/js_modal_dialog.cc b/chrome/browser/js_modal_dialog.cc new file mode 100644 index 0000000..eae6359 --- /dev/null +++ b/chrome/browser/js_modal_dialog.cc @@ -0,0 +1,125 @@ +// 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/js_modal_dialog.h" + +#include "chrome/browser/extensions/extension_host.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" +#include "ipc/ipc_message.h" + +JavaScriptAppModalDialog::JavaScriptAppModalDialog( + JavaScriptMessageBoxClient* client, + 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(client->AsTabContents(), title), + client_(client), + extension_host_(client->AsExtensionHost()), + dialog_flags_(dialog_flags), + message_text_(message_text), + default_prompt_text_(default_prompt_text), + display_suppress_checkbox_(display_suppress_checkbox), + is_before_unload_dialog_(is_before_unload_dialog), + reply_msg_(reply_msg) { + DCHECK((tab_contents_ != NULL) != (extension_host_ != NULL)); +} + +JavaScriptAppModalDialog::~JavaScriptAppModalDialog() { +} + +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 client, since it's now invalid. + skip_this_dialog_ = true; + client_ = NULL; + 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() { + // 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_) { + client_->OnMessageBoxClosed(reply_msg_, false, std::wstring()); + } + + Cleanup(); +} + +void JavaScriptAppModalDialog::OnAccept(const std::wstring& prompt_text, + bool suppress_js_messages) { + CompleteDialog(); + + if (!skip_this_dialog_) { + client_->OnMessageBoxClosed(reply_msg_, true, prompt_text); + if (suppress_js_messages) + client_->SetSuppressMessageBoxes(true); + } + + Cleanup(); +} + +void JavaScriptAppModalDialog::OnClose() { + Cleanup(); +} + +void JavaScriptAppModalDialog::Cleanup() { + if (skip_this_dialog_) { + // We can't use the client_, 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 + } + AppModalDialog::Cleanup(); +} + diff --git a/chrome/browser/js_modal_dialog.h b/chrome/browser/js_modal_dialog.h new file mode 100644 index 0000000..1ec75ac --- /dev/null +++ b/chrome/browser/js_modal_dialog.h @@ -0,0 +1,102 @@ +// Copyright (c) 2009 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_MODAL_DIALOG_H_ +#define CHROME_BROWSER_JS_MODAL_DIALOG_H_ + +#include <string> + +#include "build/build_config.h" +#include "chrome/browser/app_modal_dialog.h" +#include "chrome/common/notification_observer.h" +#include "chrome/common/notification_registrar.h" +#include "net/base/cookie_monster.h" + +class ExtensionHost; +class JavaScriptMessageBoxClient; + +// A controller+model class for JavaScript alert, confirm, prompt, and +// onbeforeunload dialog boxes. +class JavaScriptAppModalDialog : public AppModalDialog, + public NotificationObserver { + public: + // A union of data necessary to determine the type of message box to + // show. |dialog_flags| is a MessageBox flag. + JavaScriptAppModalDialog(JavaScriptMessageBoxClient* client, + 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); + virtual ~JavaScriptAppModalDialog(); + + // AppModalDialog overrides. +#if defined(OS_LINUX) || defined(OS_MACOSX) + virtual void CreateAndShowDialog(); +#endif +#if defined(OS_LINUX) + virtual void HandleDialogResponse(GtkDialog* dialog, gint response_id); +#endif + virtual int GetDialogButtons(); + virtual void AcceptWindow(); + virtual void CancelWindow(); + + ///////////////////////////////////////////////////////////////////////////// + // Getters so NativeDialog can get information about the message box. + JavaScriptMessageBoxClient* client() { + return client_; + } + int dialog_flags() { + return dialog_flags_; + } + bool is_before_unload_dialog() { + return is_before_unload_dialog_; + } + + // Callbacks from NativeDialog when the user accepts or cancels the dialog. + void OnCancel(); + void OnAccept(const std::wstring& prompt_text, bool suppress_js_messages); + void OnClose(); + + protected: + // AppModalDialog overrides. + virtual void Cleanup(); + virtual NativeDialog CreateNativeDialog(); + + private: + // NotificationObserver implementation. + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + // Initializes for notifications to listen. + void InitNotifications(); + + NotificationRegistrar registrar_; + + // An implementation of the client interface to provide supporting methods + // and receive results. + JavaScriptMessageBoxClient* client_; + + // The client_ as an ExtensionHost, cached for use during notifications that + // may arrive after the client has entered its destructor (and is thus + // treated as a base JavaScriptMessageBoxClient). This will be NULL if the + // client is not an ExtensionHost. + ExtensionHost* extension_host_; + + // Information about the message box is held in the following variables. + int dialog_flags_; + std::wstring message_text_; + std::wstring default_prompt_text_; + bool display_suppress_checkbox_; + bool is_before_unload_dialog_; + IPC::Message* reply_msg_; + + DISALLOW_COPY_AND_ASSIGN(JavaScriptAppModalDialog); +}; + +#endif // CHROME_BROWSER_JS_MODAL_DIALOG_H_ + diff --git a/chrome/browser/js_modal_dialog_gtk.cc b/chrome/browser/js_modal_dialog_gtk.cc new file mode 100644 index 0000000..bf42fb6 --- /dev/null +++ b/chrome/browser/js_modal_dialog_gtk.cc @@ -0,0 +1,215 @@ +// Copyright (c) 2009 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_modal_dialog.h" + +#include <gtk/gtk.h> + +#include "app/l10n_util.h" +#include "app/message_box_flags.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_contents_view.h" +#include "chrome/common/gtk_util.h" +#include "grit/generated_resources.h" +#include "grit/locale_settings.h" + +namespace { + +// We stash pointers to widgets on the gtk_dialog so we can refer to them +// after dialog creation. +const char kPromptTextId[] = "chrome_prompt_text"; +const char kSuppressCheckboxId[] = "chrome_suppress_checkbox"; + +// If there's a text entry in the dialog, get the text from the first one and +// return it. +std::wstring GetPromptText(GtkDialog* dialog) { + GtkWidget* widget = static_cast<GtkWidget*>( + g_object_get_data(G_OBJECT(dialog), kPromptTextId)); + if (widget) + return UTF8ToWide(gtk_entry_get_text(GTK_ENTRY(widget))); + return std::wstring(); +} + +// If there's a toggle button in the dialog, return the toggled state. +// Otherwise, return false. +bool ShouldSuppressJSDialogs(GtkDialog* dialog) { + GtkWidget* widget = static_cast<GtkWidget*>( + g_object_get_data(G_OBJECT(dialog), kSuppressCheckboxId)); + if (widget) + return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); + return false; +} + +} // namespace + +void JavaScriptAppModalDialog::CreateAndShowDialog() { + dialog_ = CreateNativeDialog(); + gtk_widget_show_all(GTK_WIDGET(GTK_DIALOG(dialog_))); + + // Suggest a minimum size. + gint width; + GtkRequisition req; + gtk_widget_size_request(dialog_, &req); + gtk_util::GetWidgetSizeFromResources(dialog_, IDS_ALERT_DIALOG_WIDTH_CHARS, 0, + &width, NULL); + if (width > req.width) + gtk_widget_set_size_request(dialog_, width, -1); +} + +void JavaScriptAppModalDialog::HandleDialogResponse(GtkDialog* dialog, + gint response_id) { + switch (response_id) { + case GTK_RESPONSE_OK: + // The first arg is the prompt text and the second is true if we want to + // suppress additional popups from the page. + OnAccept(GetPromptText(dialog), ShouldSuppressJSDialogs(dialog)); + break; + + case GTK_RESPONSE_CANCEL: + case GTK_RESPONSE_DELETE_EVENT: // User hit the X on the dialog. + OnCancel(); + break; + + default: + NOTREACHED(); + } + gtk_widget_destroy(GTK_WIDGET(dialog)); + + // Now that the dialog is gone, we can put all the windows into separate + // window groups so other dialogs are no longer app modal. + for (BrowserList::const_iterator it = BrowserList::begin(); + it != BrowserList::end(); ++it) { + GtkWindowGroup* window_group = gtk_window_group_new(); + gtk_window_group_add_window(window_group, + (*it)->window()->GetNativeHandle()); + g_object_unref(window_group); + } + delete this; +} + +int JavaScriptAppModalDialog::GetDialogButtons() { + switch (dialog_flags_) { + case MessageBoxFlags::kIsJavascriptAlert: + return MessageBoxFlags::DIALOGBUTTON_OK; + + case MessageBoxFlags::kIsJavascriptConfirm: + return MessageBoxFlags::DIALOGBUTTON_OK | + MessageBoxFlags::DIALOGBUTTON_CANCEL; + + case MessageBoxFlags::kIsJavascriptPrompt: + return MessageBoxFlags::DIALOGBUTTON_OK; + + default: + NOTREACHED(); + return 0; + } +} + +void JavaScriptAppModalDialog::AcceptWindow() { + HandleDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_OK); +} + +void JavaScriptAppModalDialog::CancelWindow() { + HandleDialogResponse(GTK_DIALOG(dialog_), GTK_RESPONSE_CANCEL); +} + +NativeDialog JavaScriptAppModalDialog::CreateNativeDialog() { + GtkButtonsType buttons = GTK_BUTTONS_NONE; + GtkMessageType message_type = GTK_MESSAGE_OTHER; + // We add in the OK button manually later because we want to focus it + // explicitly. + switch (dialog_flags_) { + case MessageBoxFlags::kIsJavascriptAlert: + buttons = GTK_BUTTONS_NONE; + message_type = GTK_MESSAGE_WARNING; + break; + + case MessageBoxFlags::kIsJavascriptConfirm: + if (is_before_unload_dialog_) { + // onbeforeunload also uses a confirm prompt, it just has custom + // buttons. We add the buttons using gtk_dialog_add_button below. + buttons = GTK_BUTTONS_NONE; + } else { + buttons = GTK_BUTTONS_CANCEL; + } + message_type = GTK_MESSAGE_QUESTION; + break; + + case MessageBoxFlags::kIsJavascriptPrompt: + buttons = GTK_BUTTONS_CANCEL; + message_type = GTK_MESSAGE_QUESTION; + break; + + default: + NOTREACHED(); + } + + // We want the alert to be app modal so put all the browser windows into the + // same window group. + GtkWindowGroup* window_group = gtk_window_group_new(); + for (BrowserList::const_iterator it = BrowserList::begin(); + it != BrowserList::end(); ++it) { + gtk_window_group_add_window(window_group, + (*it)->window()->GetNativeHandle()); + } + g_object_unref(window_group); + + gfx::NativeWindow window = client_->GetMessageBoxRootWindow(); + NativeDialog dialog = gtk_message_dialog_new(window, GTK_DIALOG_MODAL, + message_type, buttons, "%s", WideToUTF8(message_text_).c_str()); + gtk_util::ApplyMessageDialogQuirks(dialog); + gtk_window_set_title(GTK_WINDOW(dialog), WideToUTF8(title_).c_str()); + + // Adjust content area as needed. Set up the prompt text entry or + // suppression check box. + if (MessageBoxFlags::kIsJavascriptPrompt == dialog_flags_) { + // TODO(tc): Replace with gtk_dialog_get_content_area() when using GTK 2.14+ + GtkWidget* contents_vbox = GTK_DIALOG(dialog)->vbox; + GtkWidget* text_box = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(text_box), + WideToUTF8(default_prompt_text_).c_str()); + gtk_box_pack_start(GTK_BOX(contents_vbox), text_box, TRUE, TRUE, 0); + g_object_set_data(G_OBJECT(dialog), kPromptTextId, text_box); + gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE); + } + + if (display_suppress_checkbox_) { + GtkWidget* contents_vbox = GTK_DIALOG(dialog)->vbox; + GtkWidget* check_box = gtk_check_button_new_with_label( + l10n_util::GetStringUTF8( + IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION).c_str()); + gtk_box_pack_start(GTK_BOX(contents_vbox), check_box, TRUE, TRUE, 0); + g_object_set_data(G_OBJECT(dialog), kSuppressCheckboxId, check_box); + } + + // Adjust buttons/action area as needed. + if (is_before_unload_dialog_) { + std::string button_text = l10n_util::GetStringUTF8( + IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); + gtk_dialog_add_button(GTK_DIALOG(dialog), button_text.c_str(), + GTK_RESPONSE_OK); + + button_text = l10n_util::GetStringUTF8( + IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL); + gtk_dialog_add_button(GTK_DIALOG(dialog), button_text.c_str(), + GTK_RESPONSE_CANCEL); + } else { + // Add the OK button and focus it. + GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(dialog), + GTK_STOCK_OK, GTK_RESPONSE_OK); + if (MessageBoxFlags::kIsJavascriptPrompt != dialog_flags_) + gtk_widget_grab_focus(ok_button); + } + + gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); + g_signal_connect(dialog, "response", + G_CALLBACK(AppModalDialog::OnDialogResponse), + reinterpret_cast<AppModalDialog*>(this)); + return dialog; +} + diff --git a/chrome/browser/js_modal_dialog_mac.mm b/chrome/browser/js_modal_dialog_mac.mm new file mode 100644 index 0000000..8519433 --- /dev/null +++ b/chrome/browser/js_modal_dialog_mac.mm @@ -0,0 +1,170 @@ +// 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/js_modal_dialog.h" + +#import <Cocoa/Cocoa.h> + +#include "app/l10n_util_mac.h" +#include "app/message_box_flags.h" +#import "base/cocoa_protocols_mac.h" +#include "base/sys_string_conversions.h" +#include "grit/app_strings.h" +#include "grit/generated_resources.h" + +// Helper object that receives the notification that the dialog/sheet is +// going away. Is responsible for cleaning itself up. +@interface JavaScriptAppModalDialogHelper : NSObject<NSAlertDelegate> { + @private + NSAlert* alert_; + NSTextField* textField_; // WEAK; owned by alert_ +} + +- (NSAlert*)alert; +- (NSTextField*)textField; +- (void)alertDidEnd:(NSAlert *)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo; + +@end + +@implementation JavaScriptAppModalDialogHelper + +- (NSAlert*)alert { + alert_ = [[NSAlert alloc] init]; + return alert_; +} + +- (NSTextField*)textField { + textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; + [alert_ setAccessoryView:textField_]; + [textField_ release]; + + return textField_; +} + +- (void)dealloc { + [alert_ release]; + [super dealloc]; +} + +// |contextInfo| is the bridge back to the C++ JavaScriptAppModalDialog. When +// complete, autorelease to clean ourselves up. +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo { + JavaScriptAppModalDialog* bridge = + reinterpret_cast<JavaScriptAppModalDialog*>(contextInfo); + std::wstring input; + if (textField_) + input = base::SysNSStringToWide([textField_ stringValue]); + switch (returnCode) { + case NSAlertFirstButtonReturn: { // OK + bool shouldSuppress = false; + if ([alert showsSuppressionButton]) + shouldSuppress = [[alert suppressionButton] state] == NSOnState; + bridge->OnAccept(input, shouldSuppress); + break; + } + case NSAlertSecondButtonReturn: { // Cancel + bridge->OnCancel(); + break; + } + case NSRunStoppedResponse: { // Window was closed underneath us + // Need to call OnCancel() because there is some cleanup that needs + // to be done. It won't call back to the javascript since the + // JavaScriptAppModalDialog knows that the TabContents was destroyed. + bridge->OnCancel(); + break; + } + default: { + NOTREACHED(); + } + } + [self autorelease]; + delete bridge; // Done with the dialog, it needs be destroyed. +} +@end + +void JavaScriptAppModalDialog::CreateAndShowDialog() { + // Determine the names of the dialog buttons based on the flags. "Default" + // is the OK button. "Other" is the cancel button. We don't use the + // "Alternate" button in NSRunAlertPanel. + NSString* default_button = l10n_util::GetNSStringWithFixup(IDS_APP_OK); + NSString* other_button = l10n_util::GetNSStringWithFixup(IDS_APP_CANCEL); + bool text_field = false; + bool one_button = false; + switch (dialog_flags_) { + case MessageBoxFlags::kIsJavascriptAlert: + one_button = true; + break; + case MessageBoxFlags::kIsJavascriptConfirm: + if (is_before_unload_dialog_) { + default_button = l10n_util::GetNSStringWithFixup( + IDS_BEFOREUNLOAD_MESSAGEBOX_OK_BUTTON_LABEL); + other_button = l10n_util::GetNSStringWithFixup( + IDS_BEFOREUNLOAD_MESSAGEBOX_CANCEL_BUTTON_LABEL); + } + break; + case MessageBoxFlags::kIsJavascriptPrompt: + text_field = true; + break; + + default: + NOTREACHED(); + } + + // Create a helper which will receive the sheet ended selector. It will + // delete itself when done. It doesn't need anything passed to its init + // as it will get a contextInfo parameter. + JavaScriptAppModalDialogHelper* helper = + [[JavaScriptAppModalDialogHelper alloc] init]; + + // Show the modal dialog. + NSAlert* alert = [helper alert]; + dialog_ = alert; + NSTextField* field = nil; + if (text_field) { + field = [helper textField]; + [field setStringValue:base::SysWideToNSString(default_prompt_text_)]; + } + [alert setDelegate:helper]; + [alert setInformativeText:base::SysWideToNSString(message_text_)]; + [alert setMessageText:base::SysWideToNSString(title_)]; + [alert addButtonWithTitle:default_button]; + if (!one_button) + [alert addButtonWithTitle:other_button]; + if (display_suppress_checkbox_) { + [alert setShowsSuppressionButton:YES]; + NSString* suppression_title = l10n_util::GetNSStringWithFixup( + IDS_JAVASCRIPT_MESSAGEBOX_SUPPRESS_OPTION); + [[alert suppressionButton] setTitle:suppression_title]; + } + + [alert beginSheetModalForWindow:nil // nil here makes it app-modal + modalDelegate:helper + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:this]; + + if (field) + [[alert window] makeFirstResponder:field]; +} + +int JavaScriptAppModalDialog::GetDialogButtons() { + NOTIMPLEMENTED(); + return 0; +} + +void JavaScriptAppModalDialog::AcceptWindow() { + NOTIMPLEMENTED(); +} + +void JavaScriptAppModalDialog::CancelWindow() { + NOTIMPLEMENTED(); +} + +NativeDialog JavaScriptAppModalDialog::CreateNativeDialog() { + NOTIMPLEMENTED(); + return nil; +} diff --git a/chrome/browser/js_modal_dialog_win.cc b/chrome/browser/js_modal_dialog_win.cc new file mode 100644 index 0000000..8bb2525 --- /dev/null +++ b/chrome/browser/js_modal_dialog_win.cc @@ -0,0 +1,32 @@ +// 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/js_modal_dialog.h" + +#include "base/logging.h" +#include "chrome/browser/views/jsmessage_box_dialog.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "views/window/window.h" + +int JavaScriptAppModalDialog::GetDialogButtons() { + return dialog_->GetDialogButtons(); +} + +void JavaScriptAppModalDialog::AcceptWindow() { + views::DialogClientView* client_view = + dialog_->window()->GetClientView()->AsDialogClientView(); + client_view->AcceptWindow(); +} + +void JavaScriptAppModalDialog::CancelWindow() { + views::DialogClientView* client_view = + dialog_->window()->GetClientView()->AsDialogClientView(); + client_view->CancelWindow(); +} + +NativeDialog JavaScriptAppModalDialog::CreateNativeDialog() { + return new JavaScriptMessageBoxDialog(this, message_text_, + default_prompt_text_, display_suppress_checkbox_); +} + diff --git a/chrome/browser/jsmessage_box_handler.cc b/chrome/browser/message_box_handler.cc index 428c8a3..3e1793c 100644 --- a/chrome/browser/jsmessage_box_handler.cc +++ b/chrome/browser/message_box_handler.cc @@ -1,14 +1,18 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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/jsmessage_box_handler.h" +#include "chrome/browser/message_box_handler.h" #include "app/l10n_util.h" #include "app/message_box_flags.h" #include "build/build_config.h" #include "chrome/browser/app_modal_dialog_queue.h" +#include "chrome/browser/browsing_data_local_storage_helper.h" +#include "chrome/browser/cookie_modal_dialog.h" +#include "chrome/browser/cookie_prompt_modal_dialog_delegate.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/js_modal_dialog.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "googleurl/src/gurl.h" #include "grit/generated_resources.h" @@ -37,10 +41,9 @@ void RunJavascriptMessageBox(JavaScriptMessageBoxClient* client, std::wstring title = client->GetMessageBoxTitle(frame_url, (dialog_flags == MessageBoxFlags::kIsJavascriptAlert)); Singleton<AppModalDialogQueue>()->AddDialog( - new AppModalDialog(client, title, - dialog_flags, MakeTextSafe(message_text), - default_prompt_text, display_suppress_checkbox, - false, reply_msg)); + new JavaScriptAppModalDialog(client, title, dialog_flags, + MakeTextSafe(message_text), default_prompt_text, + display_suppress_checkbox, false, reply_msg)); } void RunBeforeUnloadDialog(TabContents* tab_contents, @@ -49,8 +52,28 @@ void RunBeforeUnloadDialog(TabContents* tab_contents, std::wstring full_message = message_text + L"\n\n" + l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_FOOTER); - Singleton<AppModalDialogQueue>()->AddDialog(new AppModalDialog( + Singleton<AppModalDialogQueue>()->AddDialog(new JavaScriptAppModalDialog( tab_contents, l10n_util::GetString(IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE), MessageBoxFlags::kIsJavascriptConfirm, MakeTextSafe(message_text), std::wstring(), false, true, reply_msg)); } + +#if defined(OS_WIN) +void RunCookiePrompt(TabContents* tab_contents, + const GURL& url, + const std::string& cookie_line, + CookiePromptModalDialogDelegate* delegate) { + Singleton<AppModalDialogQueue>()->AddDialog( + new CookiePromptModalDialog(tab_contents, url, cookie_line, delegate)); +} + + +void RunLocalStoragePrompt( + TabContents* tab_contents, + const BrowsingDataLocalStorageHelper::LocalStorageInfo& local_storage_info, + CookiePromptModalDialogDelegate* delegate) { + Singleton<AppModalDialogQueue>()->AddDialog( + new CookiePromptModalDialog(tab_contents, local_storage_info, delegate)); +} +#endif + diff --git a/chrome/browser/jsmessage_box_handler.h b/chrome/browser/message_box_handler.h index 313b579..d7382bb 100644 --- a/chrome/browser/jsmessage_box_handler.h +++ b/chrome/browser/message_box_handler.h @@ -2,13 +2,17 @@ // 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_H_ -#define CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_H_ +#ifndef CHROME_BROWSER_MESSAGE_BOX_HANDLER_H_ +#define CHROME_BROWSER_MESSAGE_BOX_HANDLER_H_ #include <string> +#include "chrome/browser/browsing_data_local_storage_helper.h" +#include "googleurl/src/gurl.h" #include "ipc/ipc_message.h" +#include "net/base/cookie_monster.h" +class CookiePromptModalDialogDelegate; class GURL; class JavaScriptMessageBoxClient; class TabContents; @@ -35,4 +39,24 @@ void RunBeforeUnloadDialog(TabContents* tab_contents, const std::wstring& message_text, IPC::Message* reply_msg); -#endif // CHROME_BROWSER_JSMESSAGE_BOX_HANDLER_H_ +// TODO(zelidrag): bug 32719, implement these modal dialogs on Linux and Mac. +#if defined(OS_WIN) +// This will display a modal dialog box with cookie information asking +// user to accept or reject the cookie. The caller should pass |delegate| +// that will handle the reply from the dialog. +void RunCookiePrompt(TabContents* tab_contents, + const GURL& url, + const std::string& cookie_line, + CookiePromptModalDialogDelegate* delegate); + +// This will display a modal dialog box with local storage information asking +// user to accept or reject it. The caller should pass |delegate| +// that will handle the reply from the dialog. +void RunLocalStoragePrompt( + TabContents* tab_contents, + const BrowsingDataLocalStorageHelper::LocalStorageInfo& local_storage_info, + CookiePromptModalDialogDelegate* delegate); +#endif + +#endif // CHROME_BROWSER_MESSAGE_BOX_HANDLER_H_ + diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index aa59881..3f61ddb 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -34,7 +34,7 @@ #include "chrome/browser/google_util.h" #include "chrome/browser/host_content_settings_map.h" #include "chrome/browser/hung_renderer_dialog.h" -#include "chrome/browser/jsmessage_box_handler.h" +#include "chrome/browser/message_box_handler.h" #include "chrome/browser/load_from_memory_cache_details.h" #include "chrome/browser/load_notification_details.h" #include "chrome/browser/metrics/metric_event_duration_details.h" diff --git a/chrome/browser/views/cookie_info_view.cc b/chrome/browser/views/cookie_info_view.cc index a0cfb3e..da51988 100644 --- a/chrome/browser/views/cookie_info_view.cc +++ b/chrome/browser/views/cookie_info_view.cc @@ -89,6 +89,41 @@ void CookieInfoView::SetCookie( Layout(); } +void CookieInfoView::SetCookieString( + const std::string& domain, + const net::CookieMonster::ParsedCookie& cookie) { + name_value_field_->SetText(UTF8ToWide(cookie.Name())); + content_value_field_->SetText(UTF8ToWide(cookie.Value())); + domain_value_field_->SetText(UTF8ToWide(domain)); + path_value_field_->SetText(UTF8ToWide(cookie.Path())); + created_value_field_->SetText( + base::TimeFormatFriendlyDateAndTime(base::Time::Now())); + + std::wstring expire_text = cookie.HasExpires() ? + base::TimeFormatFriendlyDateAndTime( + net::CookieMonster::ParseCookieTime(cookie.Expires())) : + l10n_util::GetString(IDS_COOKIES_COOKIE_EXPIRES_SESSION); + + if (editable_expiration_date_) { + expire_combo_values_.clear(); + if (cookie.HasExpires()) + expire_combo_values_.push_back(expire_text); + expire_combo_values_.push_back( + l10n_util::GetString(IDS_COOKIES_COOKIE_EXPIRES_SESSION)); + expires_value_combobox_->ModelChanged(); + expires_value_combobox_->SetSelectedItem(0); + expires_value_combobox_->SetEnabled(true); + } else { + expires_value_field_->SetText(expire_text); + } + + send_for_value_field_->SetText(cookie.IsSecure() ? + l10n_util::GetString(IDS_COOKIES_COOKIE_SENDFOR_SECURE) : + l10n_util::GetString(IDS_COOKIES_COOKIE_SENDFOR_ANY)); + EnableCookieDisplay(true); + Layout(); +} + void CookieInfoView::ClearCookieDisplay() { std::wstring no_cookie_string = diff --git a/chrome/browser/views/cookie_info_view.h b/chrome/browser/views/cookie_info_view.h index 5846146..b0be231 100644 --- a/chrome/browser/views/cookie_info_view.h +++ b/chrome/browser/views/cookie_info_view.h @@ -47,6 +47,10 @@ class CookieInfoView : public views::View, void SetCookie(const std::string& domain, const net::CookieMonster::CanonicalCookie& cookie_node); + // Update the display from the specified cookie string. + void SetCookieString(const std::string& domain, + const net::CookieMonster::ParsedCookie& cookie); + // Clears the cookie display to indicate that no or multiple cookies are // selected. void ClearCookieDisplay(); diff --git a/chrome/browser/views/cookie_prompt_view.cc b/chrome/browser/views/cookie_prompt_view.cc index b65d221..d08fb49 100644 --- a/chrome/browser/views/cookie_prompt_view.cc +++ b/chrome/browser/views/cookie_prompt_view.cc @@ -12,6 +12,7 @@ #include "base/i18n/time_formatting.h" #include "base/message_loop.h" #include "base/string_util.h" +#include "chrome/browser/cookie_modal_dialog.h" #include "chrome/browser/profile.h" #include "chrome/browser/views/cookie_info_view.h" #include "chrome/browser/views/local_storage_info_view.h" @@ -30,100 +31,94 @@ static const int kCookiePromptViewInsetSize = 5; /////////////////////////////////////////////////////////////////////////////// -// CookiesPromptView, public: - -// static -void CookiesPromptView::ShowCookiePromptWindow( - gfx::NativeWindow parent, - Profile* profile, - const std::string& domain, - const net::CookieMonster::CanonicalCookie& cookie, - CookiesPromptViewDelegate* delegate) { - CookiesPromptView* cookies_view = new CookiesPromptView(profile, delegate); - cookies_view->SetCookie(domain, cookie); - views::Window::CreateChromeWindow(parent, - gfx::Rect(), - cookies_view)->Show(); -} - -// static -void CookiesPromptView::ShowLocalStoragePromptWindow( - gfx::NativeWindow parent, - Profile* profile, - const std::string& domain, - const BrowsingDataLocalStorageHelper::LocalStorageInfo& local_storage_info, - CookiesPromptViewDelegate* delegate) { - CookiesPromptView* cookies_view = new CookiesPromptView(profile, delegate); - cookies_view->SetLocalStorage(domain, local_storage_info); - views::Window::CreateChromeWindow(parent, - gfx::Rect(), - cookies_view)->Show(); -} - - -CookiesPromptView::~CookiesPromptView() { -} - -void CookiesPromptView::SetCookie( - const std::string& domain, - const net::CookieMonster::CanonicalCookie& cookie) { +// CookiePromptView, public: + +CookiePromptView::CookiePromptView( + CookiePromptModalDialog* parent, + gfx::NativeWindow root_window, + Profile* profile, + const GURL& url, + const std::string& cookie_line, + CookiePromptModalDialogDelegate* delegate) + : parent_(parent), + root_window_(root_window), + profile_(profile), + delegate_(delegate) { cookie_ui_ = true; - InitializeViewResources(domain); - cookie_ = cookie; + net::CookieMonster::ParsedCookie cookie(cookie_line); + InitializeViewResources(cookie.HasDomain() ? cookie.Domain() : url.host()); } -void CookiesPromptView::SetLocalStorage( - const std::string& domain, - const BrowsingDataLocalStorageHelper::LocalStorageInfo storage_info) { +CookiePromptView::CookiePromptView( + CookiePromptModalDialog* parent, + gfx::NativeWindow root_window, + Profile* profile, + const BrowsingDataLocalStorageHelper::LocalStorageInfo& storage_info, + CookiePromptModalDialogDelegate* delegate) + : parent_(parent), + root_window_(root_window), + profile_(profile), + local_storage_info_(storage_info), + delegate_(delegate) { cookie_ui_ = false; - InitializeViewResources(domain); - local_storage_info_ = storage_info; + InitializeViewResources(storage_info.host); +} + +CookiePromptView::~CookiePromptView() { } /////////////////////////////////////////////////////////////////////////////// -// CookiesPromptView, views::View overrides: +// CookiePromptView, views::View overrides: -gfx::Size CookiesPromptView::GetPreferredSize() { +gfx::Size CookiePromptView::GetPreferredSize() { gfx::Size client_size = views::View::GetPreferredSize(); return gfx::Size(client_size.width(), client_size.height() + GetExtendedViewHeight()); } -void CookiesPromptView::ViewHierarchyChanged(bool is_add, - views::View* parent, - views::View* child) { +void CookiePromptView::ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child) { if (is_add && child == this) Init(); } /////////////////////////////////////////////////////////////////////////////// -// CookiesPromptView, views::DialogDelegate implementation: +// CookiePromptView, ModalDialogDelegate implementation: + +gfx::NativeWindow CookiePromptView::GetDialogRootWindow() { + return root_window_; +} -std::wstring CookiesPromptView::GetWindowTitle() const { +/////////////////////////////////////////////////////////////////////////////// +// CookiePromptView, views::DialogDelegate implementation: + +std::wstring CookiePromptView::GetWindowTitle() const { return title_; } -void CookiesPromptView::WindowClosing() { +void CookiePromptView::WindowClosing() { if (!signaled_ && delegate_) delegate_->BlockSiteData(false); + parent_->CompleteDialog(); } -views::View* CookiesPromptView::GetContentsView() { +views::View* CookiePromptView::GetContentsView() { return this; } // CookieInfoViewDelegate overrides: -void CookiesPromptView::ModifyExpireDate(bool session_expire) { +void CookiePromptView::ModifyExpireDate(bool session_expire) { session_expire_ = session_expire; } /////////////////////////////////////////////////////////////////////////////// -// CookiesPromptView, views::ButtonListener implementation: +// CookiePromptView, views::ButtonListener implementation: -void CookiesPromptView::ButtonPressed(views::Button* sender, - const views::Event& event) { +void CookiePromptView::ButtonPressed(views::Button* sender, + const views::Event& event) { if (sender == allow_button_) { if (delegate_) { delegate_->AllowSiteData(remember_radio_->checked(), session_expire_); @@ -140,8 +135,8 @@ void CookiesPromptView::ButtonPressed(views::Button* sender, } /////////////////////////////////////////////////////////////////////////////// -// CookiesPromptView, views::LinkController implementation: -void CookiesPromptView::LinkActivated(views::Link* source, int event_flags) { +// CookiePromptView, views::LinkController implementation: +void CookiePromptView::LinkActivated(views::Link* source, int event_flags) { if (source == show_cookie_link_) ToggleDetailsViewExpand(); else if (source == manage_cookies_link_) @@ -151,10 +146,10 @@ void CookiesPromptView::LinkActivated(views::Link* source, int event_flags) { } /////////////////////////////////////////////////////////////////////////////// -// CookiesPromptView, private: +// CookiePromptView, private: -CookiesPromptView::CookiesPromptView(Profile* profile, - CookiesPromptViewDelegate* delegate) +CookiePromptView::CookiePromptView(Profile* profile, + CookiePromptModalDialogDelegate* delegate) : remember_radio_(NULL), ask_radio_(NULL), allow_button_(NULL), @@ -169,7 +164,7 @@ CookiesPromptView::CookiesPromptView(Profile* profile, profile_(profile) { } -void CookiesPromptView::Init() { +void CookiePromptView::Init() { views::Label* description_label = new views::Label(l10n_util::GetStringF( cookie_ui_ ? IDS_COOKIE_ALERT_LABEL : IDS_DATA_ALERT_LABEL, display_domain_)); @@ -267,7 +262,8 @@ void CookiesPromptView::Init() { cookie_info_view->set_delegate(this); layout->AddView(cookie_info_view, 1, 1, GridLayout::FILL, GridLayout::CENTER); - cookie_info_view->SetCookie(domain_, cookie_); + + cookie_info_view->SetCookieString(domain_, cookie_line_); info_view_ = cookie_info_view; } else { LocalStorageInfoView* local_storage_info_view = new LocalStorageInfoView(); @@ -282,13 +278,13 @@ void CookiesPromptView::Init() { ask_radio_->SetChecked(true); } -int CookiesPromptView::GetExtendedViewHeight() { +int CookiePromptView::GetExtendedViewHeight() { DCHECK(info_view_); return expanded_view_ ? kRelatedControlVerticalSpacing : -info_view_->GetPreferredSize().height(); } -void CookiesPromptView::ToggleDetailsViewExpand() { +void CookiePromptView::ToggleDetailsViewExpand() { expanded_view_ = !expanded_view_; views::Window* parent = GetWindow(); gfx::Size non_client_size = parent->GetNonClientView()->GetPreferredSize(); @@ -300,11 +296,11 @@ void CookiesPromptView::ToggleDetailsViewExpand() { Layout(); } -void CookiesPromptView::InitializeViewResources(const std::string& domain) { +void CookiePromptView::InitializeViewResources(const std::string& domain) { domain_ = domain; std::string display_domain = domain; if (!domain.empty() && domain[0] == '.') - display_domain = display_domain.substr(1); + display_domain = display_domain.substr(1); display_domain_ = UTF8ToWide(display_domain); title_ = l10n_util::GetStringF( cookie_ui_ ? IDS_COOKIE_ALERT_TITLE : IDS_DATA_ALERT_TITLE, diff --git a/chrome/browser/views/cookie_prompt_view.h b/chrome/browser/views/cookie_prompt_view.h index 1dc5e9d..756687e 100644 --- a/chrome/browser/views/cookie_prompt_view.h +++ b/chrome/browser/views/cookie_prompt_view.h @@ -9,8 +9,10 @@ #include "base/task.h" #include "chrome/browser/browsing_data_local_storage_helper.h" +#include "chrome/browser/cookie_prompt_modal_dialog_delegate.h" #include "chrome/browser/views/cookie_info_view.h" -#include "net/base/cookie_monster.h" +#include "chrome/browser/views/modal_dialog_delegate.h" +#include "googleurl/src/gurl.h" #include "views/controls/button/button.h" #include "views/controls/link.h" #include "views/view.h" @@ -23,56 +25,36 @@ class RadioButton; } class CookieInfoView; +class CookiePromptModalDialog; class LocalStorageInfoView; class Profile; class Timer; -class CookiesPromptViewDelegate { - public: - // Allow site data to be set. If |remember| is true, record this decision - // for this host. - virtual void AllowSiteData(bool remember, bool session_expire) = 0; - - // Block site data from being stored. If |remember| is true, record this - // decision for this host. - virtual void BlockSiteData(bool remember) = 0; - - protected: - virtual ~CookiesPromptViewDelegate() {} -}; - // Cookie alert dialog UI. -class CookiesPromptView : public views::View, - public views::DialogDelegate, +class CookiePromptView : public views::View, + public ModalDialogDelegate, public views::ButtonListener, public views::LinkController, public CookieInfoViewDelegate { public: // Show the Cookies Window, creating one if necessary. - static void ShowCookiePromptWindow( - gfx::NativeWindow parent, + CookiePromptView( + CookiePromptModalDialog* parent, + gfx::NativeWindow root_window, Profile* profile, - const std::string& domain, - const net::CookieMonster::CanonicalCookie& cookie, - CookiesPromptViewDelegate* delegate); + const GURL& url, + const std::string& cookie_line, + CookiePromptModalDialogDelegate* delegate); - static void CookiesPromptView::ShowLocalStoragePromptWindow( - gfx::NativeWindow parent, + CookiePromptView( + CookiePromptModalDialog* parent, + gfx::NativeWindow root_window, Profile* profile, - const std::string& domain, const BrowsingDataLocalStorageHelper::LocalStorageInfo& local_storage_info, - CookiesPromptViewDelegate* delegate); - - virtual ~CookiesPromptView(); - - // Initializes component for displaying cookie information. - void SetCookie(const std::string& domain, - const net::CookieMonster::CanonicalCookie& cookie_node); + CookiePromptModalDialogDelegate* delegate); - // Initializes component for displaying locale storage information. - void SetLocalStorage(const std::string& domain, - const BrowsingDataLocalStorageHelper::LocalStorageInfo); + virtual ~CookiePromptView(); protected: // views::View overrides. @@ -81,11 +63,15 @@ class CookiesPromptView : public views::View, views::View* parent, views::View* child); + // ModalDialogDelegate overrides. + virtual gfx::NativeWindow GetDialogRootWindow(); + // views::DialogDelegate overrides. virtual bool CanResize() const { return false; } virtual std::wstring GetWindowTitle() const; virtual void WindowClosing(); virtual views::View* GetContentsView(); + virtual bool IsModal() const { return true; } // views::ButtonListener overrides. virtual void ButtonPressed(views::Button* sender, const views::Event& event); @@ -103,8 +89,8 @@ class CookiesPromptView : public views::View, private: // Use the static factory method to show. - explicit CookiesPromptView(Profile* profile, - CookiesPromptViewDelegate* delegate); + explicit CookiePromptView(Profile* profile, + CookiePromptModalDialogDelegate* delegate); // Initialize the dialog layout. void Init(); @@ -141,24 +127,29 @@ class CookiesPromptView : public views::View, // Whether we're showing cookie UI as opposed to other site data. bool cookie_ui_; - CookiesPromptViewDelegate* delegate_; + // A pointer to the AppModalDialog that owns us. + CookiePromptModalDialog* parent_; + + gfx::NativeWindow root_window_; - // Cookie domain. + // The Profile for which Cookies are displayed. + Profile* profile_; + + // Cookie / local storage domain. std::string domain_; - // Cookie domain formatted for displaying (removed leading '.'). + // Domain name formatted for displaying (removed leading '.'). std::wstring display_domain_; - // Displayed cookie. Only used when |cookie_ui_| is true. - net::CookieMonster::CanonicalCookie cookie_; + // Displayed cookie. Only used when |cookie_ui_| is true. + std::string cookie_line_; // Displayed local storage info. Only used when |cookie_ui_| is false. BrowsingDataLocalStorageHelper::LocalStorageInfo local_storage_info_; - // The Profile for which Cookies are displayed. - Profile* profile_; + CookiePromptModalDialogDelegate* delegate_; - DISALLOW_COPY_AND_ASSIGN(CookiesPromptView); + DISALLOW_COPY_AND_ASSIGN(CookiePromptView); }; #endif // CHROME_BROWSER_VIEWS_COOKIE_PROMPT_VIEW_H_ diff --git a/chrome/browser/views/jsmessage_box_dialog.cc b/chrome/browser/views/jsmessage_box_dialog.cc index b83242f..9e78f1d 100644 --- a/chrome/browser/views/jsmessage_box_dialog.cc +++ b/chrome/browser/views/jsmessage_box_dialog.cc @@ -13,13 +13,12 @@ #include "views/controls/message_box_view.h" #include "views/window/window.h" -JavascriptMessageBoxDialog::JavascriptMessageBoxDialog( - AppModalDialog* parent, +JavaScriptMessageBoxDialog::JavaScriptMessageBoxDialog( + JavaScriptAppModalDialog* parent, const std::wstring& message_text, const std::wstring& default_prompt_text, bool display_suppress_checkbox) : parent_(parent), - dialog_(NULL), message_box_view_(new MessageBoxView( parent->dialog_flags() | MessageBoxFlags::kAutoDetectAlignment, message_text, default_prompt_text)) { @@ -33,39 +32,17 @@ JavascriptMessageBoxDialog::JavascriptMessageBoxDialog( } } -JavascriptMessageBoxDialog::~JavascriptMessageBoxDialog() { +JavaScriptMessageBoxDialog::~JavaScriptMessageBoxDialog() { } -void JavascriptMessageBoxDialog::ShowModalDialog() { - gfx::NativeWindow root_hwnd = client()->GetMessageBoxRootWindow(); - // GetMessageBoxRootWindow() will be NULL if there's no selected tab (e.g., - // during shutdown), in which case we simply skip showing this dialog. - if (!root_hwnd) { - Cancel(); - } else { - dialog_ = views::Window::CreateChromeWindow(root_hwnd, gfx::Rect(), this); - dialog_->Show(); - } -} - -void JavascriptMessageBoxDialog::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(); -} - -void JavascriptMessageBoxDialog::CloseModalDialog() { - // If the dialog is visible close it. - if (dialog_) - dialog_->Close(); +gfx::NativeWindow JavaScriptMessageBoxDialog::GetDialogRootWindow() { + return client()->GetMessageBoxRootWindow(); } ////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxDialog, views::DialogDelegate implementation: +// JavaScriptMessageBoxDialog, views::DialogDelegate implementation: -int JavascriptMessageBoxDialog::GetDialogButtons() const { +int JavaScriptMessageBoxDialog::GetDialogButtons() const { int dialog_buttons = 0; if (parent_->dialog_flags() & MessageBoxFlags::kFlagHasOKButton) dialog_buttons = MessageBoxFlags::DIALOGBUTTON_OK; @@ -76,36 +53,36 @@ int JavascriptMessageBoxDialog::GetDialogButtons() const { return dialog_buttons; } -std::wstring JavascriptMessageBoxDialog::GetWindowTitle() const { +std::wstring JavaScriptMessageBoxDialog::GetWindowTitle() const { return parent_->title(); } -void JavascriptMessageBoxDialog::WindowClosing() { +void JavaScriptMessageBoxDialog::WindowClosing() { dialog_ = NULL; } -void JavascriptMessageBoxDialog::DeleteDelegate() { +void JavaScriptMessageBoxDialog::DeleteDelegate() { delete parent_; delete this; } -bool JavascriptMessageBoxDialog::Cancel() { +bool JavaScriptMessageBoxDialog::Cancel() { parent_->OnCancel(); return true; } -bool JavascriptMessageBoxDialog::Accept() { +bool JavaScriptMessageBoxDialog::Accept() { parent_->OnAccept(message_box_view_->GetInputText(), message_box_view_->IsCheckBoxSelected()); return true; } -void JavascriptMessageBoxDialog::OnClose() { +void JavaScriptMessageBoxDialog::OnClose() { parent_->OnClose(); } -std::wstring JavascriptMessageBoxDialog::GetDialogButtonLabel( +std::wstring JavaScriptMessageBoxDialog::GetDialogButtonLabel( MessageBoxFlags::DialogButton button) const { if (parent_->is_before_unload_dialog()) { if (button == MessageBoxFlags::DIALOGBUTTON_OK) { @@ -119,13 +96,13 @@ std::wstring JavascriptMessageBoxDialog::GetDialogButtonLabel( } /////////////////////////////////////////////////////////////////////////////// -// JavascriptMessageBoxDialog, views::WindowDelegate implementation: +// JavaScriptMessageBoxDialog, views::WindowDelegate implementation: -views::View* JavascriptMessageBoxDialog::GetContentsView() { +views::View* JavaScriptMessageBoxDialog::GetContentsView() { return message_box_view_; } -views::View* JavascriptMessageBoxDialog::GetInitiallyFocusedView() { +views::View* JavaScriptMessageBoxDialog::GetInitiallyFocusedView() { if (message_box_view_->text_box()) return message_box_view_->text_box(); return views::DialogDelegate::GetInitiallyFocusedView(); diff --git a/chrome/browser/views/jsmessage_box_dialog.h b/chrome/browser/views/jsmessage_box_dialog.h index 92a2635..62fcf51 100644 --- a/chrome/browser/views/jsmessage_box_dialog.h +++ b/chrome/browser/views/jsmessage_box_dialog.h @@ -5,30 +5,28 @@ #ifndef CHROME_BROWSER_VIEWS_JSMESSAGE_BOX_DIALOG_H_ #define CHROME_BROWSER_VIEWS_JSMESSAGE_BOX_DIALOG_H_ +#include "chrome/browser/js_modal_dialog.h" + #include <string> -#include "chrome/browser/app_modal_dialog.h" -#include "views/window/dialog_delegate.h" +#include "app/message_box_flags.h" +#include "chrome/browser/jsmessage_box_client.h" +#include "chrome/browser/views/modal_dialog_delegate.h" class MessageBoxView; class JavaScriptMessageBoxClient; -namespace views { -class Window; -} -class JavascriptMessageBoxDialog : public views::DialogDelegate { +class JavaScriptMessageBoxDialog : public ModalDialogDelegate { public: - JavascriptMessageBoxDialog(AppModalDialog* parent, + JavaScriptMessageBoxDialog(JavaScriptAppModalDialog* parent, const std::wstring& message_text, const std::wstring& default_prompt_text, bool display_suppress_checkbox); - virtual ~JavascriptMessageBoxDialog(); + virtual ~JavaScriptMessageBoxDialog(); - // Methods called from AppModalDialog. - void ShowModalDialog(); - void ActivateModalDialog(); - void CloseModalDialog(); + // ModalDialogDelegate overrides. + virtual gfx::NativeWindow GetDialogRootWindow(); // views::DialogDelegate Methods: virtual int GetDialogButtons() const; @@ -52,15 +50,12 @@ class JavascriptMessageBoxDialog : public views::DialogDelegate { } // A pointer to the AppModalDialog that owns us. - AppModalDialog* parent_; + JavaScriptAppModalDialog* parent_; // The message box view whose commands we handle. MessageBoxView* message_box_view_; - // The dialog if it is currently visible. - views::Window* dialog_; - - DISALLOW_COPY_AND_ASSIGN(JavascriptMessageBoxDialog); + DISALLOW_COPY_AND_ASSIGN(JavaScriptMessageBoxDialog); }; #endif // CHROME_BROWSER_VIEWS_JSMESSAGE_BOX_DIALOG_H_ diff --git a/chrome/browser/views/modal_dialog_delegate.cc b/chrome/browser/views/modal_dialog_delegate.cc new file mode 100644 index 0000000..586b9f6 --- /dev/null +++ b/chrome/browser/views/modal_dialog_delegate.cc @@ -0,0 +1,37 @@ +// 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/views/modal_dialog_delegate.h" + +#include "views/window/window.h" + +void ModalDialogDelegate::ShowModalDialog() { + gfx::NativeWindow root_hwnd = GetDialogRootWindow(); + // GetMessageBoxRootWindow() will be NULL if there's no selected tab (e.g., + // during shutdown), in which case we simply skip showing this dialog. + if (!root_hwnd) { + Cancel(); + } else { + dialog_ = views::Window::CreateChromeWindow(root_hwnd, gfx::Rect(), this); + dialog_->Show(); + } +} + +void ModalDialogDelegate::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(); +} + +void ModalDialogDelegate::CloseModalDialog() { + // If the dialog is visible close it. + if (dialog_) + dialog_->Close(); +} + +ModalDialogDelegate::ModalDialogDelegate() : dialog_(NULL) { +} + diff --git a/chrome/browser/views/modal_dialog_delegate.h b/chrome/browser/views/modal_dialog_delegate.h new file mode 100644 index 0000000..4fe2c1d --- /dev/null +++ b/chrome/browser/views/modal_dialog_delegate.h @@ -0,0 +1,32 @@ +// 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_VIEWS_MODAL_DIALOG_DELEGATE_H_ +#define CHROME_BROWSER_VIEWS_MODAL_DIALOG_DELEGATE_H_ + +#include <string> + +#include "views/window/dialog_delegate.h" + +namespace views { +class Window; +} + +class ModalDialogDelegate : public views::DialogDelegate { + public: + virtual ~ModalDialogDelegate() {} + // Methods called from AppModalDialog. + virtual gfx::NativeWindow GetDialogRootWindow() = 0; + virtual void ShowModalDialog(); + virtual void ActivateModalDialog(); + virtual void CloseModalDialog(); + protected: + ModalDialogDelegate(); + + // The dialog if it is currently visible. + views::Window* dialog_; +}; + +#endif // CHROME_BROWSER_VIEWS_MODAL_DIALOG_DELEGATE_H_ + diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index 133b951..859d8b2 100755 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -631,6 +631,10 @@ 'browser/cocoa/window_size_autosaver.mm', 'browser/command_updater.cc', 'browser/command_updater.h', + 'browser/cookie_modal_dialog.cc', + 'browser/cookie_modal_dialog.h', + 'browser/cookie_modal_dialog_views.cc', + 'browser/cookie_prompt_modal_dialog_delegate.h', 'browser/cookies_tree_model.cc', 'browser/cookies_tree_model.h', 'browser/cross_site_request_manager.cc', @@ -1217,9 +1221,12 @@ 'browser/jankometer.h', 'browser/jumplist.cc', 'browser/jumplist.h', + 'browser/js_modal_dialog.cc', + 'browser/js_modal_dialog.h', + 'browser/js_modal_dialog_gtk.cc', + 'browser/js_modal_dialog_mac.mm', + 'browser/js_modal_dialog_win.cc', 'browser/jsmessage_box_client.h', - 'browser/jsmessage_box_handler.cc', - 'browser/jsmessage_box_handler.h', 'browser/keychain_mac.cc', 'browser/keychain_mac.h', 'browser/language_combobox_model.cc', @@ -1245,6 +1252,8 @@ 'browser/memory_details.h', 'browser/memory_purger.cc', 'browser/memory_purger.h', + 'browser/message_box_handler.cc', + 'browser/message_box_handler.h', 'browser/meta_table_helper.cc', 'browser/meta_table_helper.h', 'browser/metrics/metric_event_duration_details.h', @@ -1882,6 +1891,8 @@ 'browser/views/location_bar_view.h', 'browser/views/login_view.cc', 'browser/views/login_view.h', + 'browser/views/modal_dialog_delegate.cc', + 'browser/views/modal_dialog_delegate.h', 'browser/views/new_profile_dialog.cc', 'browser/views/new_profile_dialog.h', 'browser/views/new_browser_window_widget.cc', @@ -2129,6 +2140,7 @@ 'browser/automation/automation_provider_list_generic.cc', 'browser/bookmarks/bookmark_context_menu.cc', 'browser/bookmarks/bookmark_drop_info.cc', + 'browser/cookie_modal_dialog.cc', 'browser/dock_info.cc', 'browser/jankometer.cc', 'browser/password_manager/password_store_gnome.h', @@ -2431,6 +2443,8 @@ ['include', '^browser/views/location_bar_view.cc'], ['include', '^browser/views/location_bar_view.h'], ['include', '^browser/views/page_info_window_view.cc'], + ['include', '^browser/views/modal_dialog_delegate.cc'], + ['include', '^browser/views/modal_dialog_delegate.h'], ['include', '^browser/views/notifications/balloon_view_host.cc'], ['include', '^browser/views/notifications/balloon_view_host.h'], # Not necessary unless you're trying to build ChromeOS+views. |