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