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