15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_shutdown.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents_view.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/text/text_elider.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/root_window.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::JavaScriptDialogManager; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Control maximum sizes of various texts passed to us from javascript. 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Two-dimensional eliding. Reformat the text of the message dialog 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inserting line breaks because otherwise a single long line can overflow 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the message dialog (and crash/hang the GTK, depending on the version). 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMessageTextMaxRows = 32; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMessageTextMaxCols = 132; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultPromptMaxRows = 24; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultPromptMaxCols = 132; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnforceMaxTextSize(const string16& in_string, string16* out_string) { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ElideRectangleString(in_string, kMessageTextMaxRows, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMessageTextMaxCols, false, out_string); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnforceMaxPromptSize(const string16& in_string, string16* out_string) { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ElideRectangleString(in_string, kDefaultPromptMaxRows, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kDefaultPromptMaxCols, false, out_string); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// One-dimensional eliding. Trust the window system to break the string 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// appropriately, but limit its overall length to something reasonable. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMessageTextMaxSize = 3000; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultPromptMaxSize = 2000; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnforceMaxTextSize(const string16& in_string, string16* out_string) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ElideString(in_string, kMessageTextMaxSize, out_string); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnforceMaxPromptSize(const string16& in_string, string16* out_string) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ElideString(in_string, kDefaultPromptMaxSize, out_string); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeJavaScriptDialogExtraData::ChromeJavaScriptDialogExtraData() 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : suppress_javascript_messages_(false) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaScriptAppModalDialog::JavaScriptAppModalDialog( 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents, 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtraDataMap* extra_data_map, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& title, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::JavaScriptMessageType javascript_message_type, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& message_text, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& default_prompt_text, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool display_suppress_checkbox, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_before_unload_dialog, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_reload, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const JavaScriptDialogManager::DialogClosedCallback& callback) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : AppModalDialog(web_contents, title), 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extra_data_map_(extra_data_map), 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) javascript_message_type_(javascript_message_type), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_suppress_checkbox_(display_suppress_checkbox), 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_before_unload_dialog_(is_before_unload_dialog), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_reload_(is_reload), 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback), 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_override_prompt_text_(false) { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnforceMaxTextSize(message_text, &message_text_); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnforceMaxPromptSize(default_prompt_text, &default_prompt_text_); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)JavaScriptAppModalDialog::~JavaScriptAppModalDialog() { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NativeAppModalDialog* JavaScriptAppModalDialog::CreateNativeDialog() { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeWindow parent_window = 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents()->GetView()->GetTopLevelNativeWindow(); 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_AURA) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!parent_window->GetRootWindow()) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When we are part of a WebContents that isn't actually being displayed on 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the screen, we can't actually attach to it. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent_window = NULL; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // defined(USE_AURA) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NativeAppModalDialog::CreateNativeJavaScriptPrompt(this, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_window); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool JavaScriptAppModalDialog::IsJavaScriptModalDialog() { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JavaScriptAppModalDialog::Invalidate() { 10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!IsValid()) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AppModalDialog::Invalidate(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Reset(); 11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (native_dialog()) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseModalDialog(); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JavaScriptAppModalDialog::OnCancel(bool suppress_js_messages) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are shutting down and this is an onbeforeunload dialog, cancel the 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_before_unload_dialog_) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_shutdown::SetTryingToQuit(false); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to do this before WM_DESTROY (WindowClosing()) as any parent frame 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will receive its activation messages before this dialog receives 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // WM_DESTROY. The parent frame would then try to activate any modal dialogs 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that were still open in the ModalDialogQueue, which would send activation 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // back to this one. The framework should be improved to handle this, so this 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is a temporary workaround. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompleteDialog(); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyDelegate(false, string16(), suppress_js_messages); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JavaScriptAppModalDialog::OnAccept(const string16& prompt_text, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool suppress_js_messages) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string16 prompt_text_to_use = prompt_text; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is only for testing. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_override_prompt_text_) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prompt_text_to_use = override_prompt_text_; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompleteDialog(); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyDelegate(true, prompt_text_to_use, suppress_js_messages); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JavaScriptAppModalDialog::OnClose() { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NotifyDelegate(false, string16(), false); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JavaScriptAppModalDialog::SetOverridePromptText( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& override_prompt_text) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) override_prompt_text_ = override_prompt_text; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_override_prompt_text_ = true; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void JavaScriptAppModalDialog::NotifyDelegate(bool success, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string16& user_input, 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool suppress_js_messages) { 15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!IsValid()) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(success, user_input); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // The callback_ above may delete web_contents_, thus removing the extra 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // data from the map owned by ChromeJavaScriptDialogManager. Make sure 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // to only use the data if still present. http://crbug.com/236476 16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtraDataMap::iterator extra_data = extra_data_map_->find(web_contents()); 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (extra_data != extra_data_map_->end()) { 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extra_data->second.last_javascript_message_dismissal_ = 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::TimeTicks::Now(); 16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) extra_data->second.suppress_javascript_messages_ = suppress_js_messages; 16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On Views, we can end up coming through this code path twice :(. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See crbug.com/63732. 17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AppModalDialog::Invalidate(); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 174