javascript_app_modal_dialog.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" 6 7#include "chrome/browser/browser_shutdown.h" 8#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" 9#include "content/public/browser/web_contents.h" 10#include "content/public/browser/web_contents_view.h" 11#include "ui/base/text/text_elider.h" 12 13using content::JavaScriptDialogCreator; 14using content::WebContents; 15 16namespace { 17 18// Control maximum sizes of various texts passed to us from javascript. 19#if defined(OS_POSIX) && !defined(OS_MACOSX) 20// Two-dimensional eliding. Reformat the text of the message dialog 21// inserting line breaks because otherwise a single long line can overflow 22// the message dialog (and crash/hang the GTK, depending on the version). 23const int kMessageTextMaxRows = 32; 24const int kMessageTextMaxCols = 132; 25const int kDefaultPromptMaxRows = 24; 26const int kDefaultPromptMaxCols = 132; 27void EnforceMaxTextSize(const string16& in_string, string16* out_string) { 28 ui::ElideRectangleString(in_string, kMessageTextMaxRows, 29 kMessageTextMaxCols, false, out_string); 30} 31void EnforceMaxPromptSize(const string16& in_string, string16* out_string) { 32 ui::ElideRectangleString(in_string, kDefaultPromptMaxRows, 33 kDefaultPromptMaxCols, false, out_string); 34} 35#else 36// One-dimensional eliding. Trust the window system to break the string 37// appropriately, but limit its overall length to something reasonable. 38const int kMessageTextMaxSize = 3000; 39const int kDefaultPromptMaxSize = 2000; 40void EnforceMaxTextSize(const string16& in_string, string16* out_string) { 41 ui::ElideString(in_string, kMessageTextMaxSize, out_string); 42} 43void EnforceMaxPromptSize(const string16& in_string, string16* out_string) { 44 ui::ElideString(in_string, kDefaultPromptMaxSize, out_string); 45} 46#endif 47 48} // namespace 49 50ChromeJavaScriptDialogExtraData::ChromeJavaScriptDialogExtraData() 51 : suppress_javascript_messages_(false) { 52} 53 54JavaScriptAppModalDialog::JavaScriptAppModalDialog( 55 WebContents* web_contents, 56 ChromeJavaScriptDialogExtraData* extra_data, 57 const string16& title, 58 content::JavaScriptMessageType javascript_message_type, 59 const string16& message_text, 60 const string16& default_prompt_text, 61 bool display_suppress_checkbox, 62 bool is_before_unload_dialog, 63 bool is_reload, 64 const JavaScriptDialogCreator::DialogClosedCallback& callback) 65 : AppModalDialog(web_contents, title), 66 extra_data_(extra_data), 67 javascript_message_type_(javascript_message_type), 68 display_suppress_checkbox_(display_suppress_checkbox), 69 is_before_unload_dialog_(is_before_unload_dialog), 70 is_reload_(is_reload), 71 callback_(callback), 72 use_override_prompt_text_(false) { 73 EnforceMaxTextSize(message_text, &message_text_); 74 EnforceMaxPromptSize(default_prompt_text, &default_prompt_text_); 75} 76 77JavaScriptAppModalDialog::~JavaScriptAppModalDialog() { 78} 79 80NativeAppModalDialog* JavaScriptAppModalDialog::CreateNativeDialog() { 81 gfx::NativeWindow parent_window = 82 web_contents()->GetView()->GetTopLevelNativeWindow(); 83 return NativeAppModalDialog::CreateNativeJavaScriptPrompt(this, 84 parent_window); 85} 86 87bool JavaScriptAppModalDialog::IsJavaScriptModalDialog() { 88 return true; 89} 90 91void JavaScriptAppModalDialog::Invalidate() { 92 if (!valid_) 93 return; 94 95 valid_ = false; 96 callback_.Reset(); 97 if (native_dialog_) 98 CloseModalDialog(); 99} 100 101void JavaScriptAppModalDialog::OnCancel(bool suppress_js_messages) { 102 // If we are shutting down and this is an onbeforeunload dialog, cancel the 103 // shutdown. 104 if (is_before_unload_dialog_) 105 browser_shutdown::SetTryingToQuit(false); 106 107 // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame 108 // will receive its activation messages before this dialog receives 109 // WM_DESTROY. The parent frame would then try to activate any modal dialogs 110 // that were still open in the ModalDialogQueue, which would send activation 111 // back to this one. The framework should be improved to handle this, so this 112 // is a temporary workaround. 113 CompleteDialog(); 114 115 NotifyDelegate(false, string16(), suppress_js_messages); 116} 117 118void JavaScriptAppModalDialog::OnAccept(const string16& prompt_text, 119 bool suppress_js_messages) { 120 string16 prompt_text_to_use = prompt_text; 121 // This is only for testing. 122 if (use_override_prompt_text_) 123 prompt_text_to_use = override_prompt_text_; 124 125 CompleteDialog(); 126 NotifyDelegate(true, prompt_text_to_use, suppress_js_messages); 127} 128 129void JavaScriptAppModalDialog::OnClose() { 130 NotifyDelegate(false, string16(), false); 131} 132 133void JavaScriptAppModalDialog::SetOverridePromptText( 134 const string16& override_prompt_text) { 135 override_prompt_text_ = override_prompt_text; 136 use_override_prompt_text_ = true; 137} 138 139void JavaScriptAppModalDialog::NotifyDelegate(bool success, 140 const string16& user_input, 141 bool suppress_js_messages) { 142 if (!valid_) 143 return; 144 145 callback_.Run(success, user_input); 146 147 extra_data_->last_javascript_message_dismissal_ = base::TimeTicks::Now(); 148 extra_data_->suppress_javascript_messages_ = suppress_js_messages; 149 150 // On Views, we can end up coming through this code path twice :(. 151 // See crbug.com/63732. 152 valid_ = false; 153} 154