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) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog_queue.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/web_contents.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_client.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/javascript_message_type.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS) 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/extension_system.h" 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/browser/process_manager.h" 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(ENABLE_EXTENSIONS) 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using content::BrowserContext; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using content::JavaScriptDialogManager; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS) 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::Extension; 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(ENABLE_EXTENSIONS) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS) 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns the ProcessManager for the browser context from |web_contents|. 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extensions::ProcessManager* GetExtensionsProcessManager( 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContents* web_contents) { 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return extensions::ExtensionSystem::Get( 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) web_contents->GetBrowserContext())->process_manager(); 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Returns the extension associated with |web_contents| or NULL if there is no 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// associated extension (or extensions are not supported). 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const Extension* GetExtensionForWebContents(WebContents* web_contents) { 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::ProcessManager* pm = GetExtensionsProcessManager(web_contents); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return pm->GetExtensionForRenderViewHost(web_contents->GetRenderViewHost()); 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(ENABLE_EXTENSIONS) 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Keeps an |extension| from shutting down its lazy background page. If an 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// extension opens a dialog its lazy background page must stay alive until the 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// dialog closes. 591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid IncrementLazyKeepaliveCount(WebContents* web_contents) { 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS) 611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension = GetExtensionForWebContents(web_contents); 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (extension == NULL) 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(web_contents); 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::ProcessManager* pm = GetExtensionsProcessManager(web_contents); 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pm) 685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pm->IncrementLazyKeepaliveCount(extension); 691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(ENABLE_EXTENSIONS) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Allows an |extension| to shut down its lazy background page after a dialog 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// closes (if nothing else is keeping it open). 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid DecrementLazyKeepaliveCount(WebContents* web_contents) { 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS) 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension = GetExtensionForWebContents(web_contents); 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (extension == NULL) 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(web_contents); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::ProcessManager* pm = GetExtensionsProcessManager(web_contents); 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pm) 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pm->DecrementLazyKeepaliveCount(extension); 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(ENABLE_EXTENSIONS) 855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ChromeJavaScriptDialogManager : public JavaScriptDialogManager { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static ChromeJavaScriptDialogManager* GetInstance(); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void RunJavaScriptDialog( 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents, 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& accept_lang, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::JavaScriptMessageType message_type, 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& message_text, 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& default_prompt_text, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DialogClosedCallback& callback, 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* did_suppress_message) OVERRIDE; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void RunBeforeUnloadDialog( 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents, 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& message_text, 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_reload, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DialogClosedCallback& callback) OVERRIDE; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool HandleJavaScriptDialog( 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* web_contents, 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool accept, 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16* prompt_override) OVERRIDE; 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual void CancelActiveAndPendingDialogs( 113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) WebContents* web_contents) OVERRIDE; 114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) friend struct DefaultSingletonTraits<ChromeJavaScriptDialogManager>; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChromeJavaScriptDialogManager(); 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~ChromeJavaScriptDialogManager(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 GetTitle(WebContents* web_contents, 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& origin_url, 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& accept_lang, 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_alert); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Wrapper around a DialogClosedCallback so that we can intercept it before 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // passing it onto the original callback. 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void OnDialogClosed(WebContents* web_contents, 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DialogClosedCallback callback, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success, 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& user_input); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mapping between the WebContents and their extra data. The key 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is a void* because the pointer is just a cookie and is never dereferenced. 13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) JavaScriptAppModalDialog::ExtraDataMap javascript_dialog_extra_data_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ChromeJavaScriptDialogManager); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ChromeJavaScriptDialogManager, public: 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ChromeJavaScriptDialogManager::ChromeJavaScriptDialogManager() { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeJavaScriptDialogManager::~ChromeJavaScriptDialogManager() { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChromeJavaScriptDialogManager* ChromeJavaScriptDialogManager::GetInstance() { 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return Singleton<ChromeJavaScriptDialogManager>::get(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeJavaScriptDialogManager::RunJavaScriptDialog( 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& origin_url, 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& accept_lang, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::JavaScriptMessageType message_type, 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& message_text, 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& default_prompt_text, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DialogClosedCallback& callback, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool* did_suppress_message) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *did_suppress_message = false; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChromeJavaScriptDialogExtraData* extra_data = 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &javascript_dialog_extra_data_[web_contents]; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extra_data->suppress_javascript_messages_) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *did_suppress_message = true; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta time_since_last_message = base::TimeTicks::Now() - 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_data->last_javascript_message_dismissal_; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool display_suppress_checkbox = false; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Show a checkbox offering to suppress further messages if this message is 179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // being displayed within kJavaScriptMessageExpectedDelay of the last one. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (time_since_last_message < 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds( 182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) chrome::kJavaScriptMessageExpectedDelay)) { 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_suppress_checkbox = true; 184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } else { 185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) display_suppress_checkbox = false; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_alert = message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT; 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 dialog_title = 1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetTitle(web_contents, origin_url, accept_lang, is_alert); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IncrementLazyKeepaliveCount(web_contents); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppModalDialogQueue::GetInstance()->AddDialog(new JavaScriptAppModalDialog( 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents, 19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &javascript_dialog_extra_data_, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dialog_title, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_type, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) message_text, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default_prompt_text, 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_suppress_checkbox, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, // is_before_unload_dialog 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, // is_reload 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ChromeJavaScriptDialogManager::OnDialogClosed, 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this), web_contents, callback))); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeJavaScriptDialogManager::RunBeforeUnloadDialog( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents, 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& message_text, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_reload, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DialogClosedCallback& callback) { 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16 title = l10n_util::GetStringUTF16(is_reload ? 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_BEFORERELOAD_MESSAGEBOX_TITLE : IDS_BEFOREUNLOAD_MESSAGEBOX_TITLE); 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16 footer = l10n_util::GetStringUTF16(is_reload ? 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDS_BEFORERELOAD_MESSAGEBOX_FOOTER : IDS_BEFOREUNLOAD_MESSAGEBOX_FOOTER); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::string16 full_message = 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) message_text + base::ASCIIToUTF16("\n\n") + footer; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IncrementLazyKeepaliveCount(web_contents); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppModalDialogQueue::GetInstance()->AddDialog(new JavaScriptAppModalDialog( 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents, 22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) &javascript_dialog_extra_data_, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) title, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM, 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) full_message, 229a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16(), // default_prompt_text 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) false, // display_suppress_checkbox 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, // is_before_unload_dialog 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_reload, 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ChromeJavaScriptDialogManager::OnDialogClosed, 2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Unretained(this), web_contents, callback))); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ChromeJavaScriptDialogManager::HandleJavaScriptDialog( 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebContents* web_contents, 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool accept, 240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16* prompt_override) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AppModalDialogQueue* dialog_queue = AppModalDialogQueue::GetInstance(); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!dialog_queue->HasActiveDialog() || 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !dialog_queue->active_dialog()->IsJavaScriptModalDialog() || 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog_queue->active_dialog()->web_contents() != web_contents) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) JavaScriptAppModalDialog* dialog = static_cast<JavaScriptAppModalDialog*>( 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog_queue->active_dialog()); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (accept) { 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (prompt_override) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog->SetOverridePromptText(*prompt_override); 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog->native_dialog()->AcceptAppModalDialog(); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dialog->native_dialog()->CancelAppModalDialog(); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ChromeJavaScriptDialogManager::WebContentsDestroyed( 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents) { 261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CancelActiveAndPendingDialogs(web_contents); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) javascript_dialog_extra_data_.erase(web_contents); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 ChromeJavaScriptDialogManager::GetTitle( 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContents* web_contents, 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const GURL& origin_url, 2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& accept_lang, 2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_alert) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the URL hasn't any host, return the default string. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!origin_url.has_host()) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l10n_util::GetStringUTF16( 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_alert ? IDS_JAVASCRIPT_ALERT_DEFAULT_TITLE 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : IDS_JAVASCRIPT_MESSAGEBOX_DEFAULT_TITLE); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // For extensions, show the extension name, but only if the origin of 2780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // the alert matches the top-level WebContents. 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_EXTENSIONS) 2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension = GetExtensionForWebContents(web_contents); 2810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (extension && 2820529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch web_contents->GetLastCommittedURL().GetOrigin() == origin_url) { 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return base::UTF8ToUTF16(extension->name()); 2840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(ENABLE_EXTENSIONS) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise, return the formatted URL. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In this case, force URL to have LTR directionality. 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 url_string = net::FormatUrl(origin_url, accept_lang); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return l10n_util::GetStringFUTF16( 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_alert ? IDS_JAVASCRIPT_ALERT_TITLE 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : IDS_JAVASCRIPT_MESSAGEBOX_TITLE, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::i18n::GetDisplayStringInLTRDirectionality(url_string)); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ChromeJavaScriptDialogManager::CancelActiveAndPendingDialogs( 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppModalDialogQueue* queue = AppModalDialogQueue::GetInstance(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AppModalDialog* active_dialog = queue->active_dialog(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (active_dialog && active_dialog->web_contents() == web_contents) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_dialog->Invalidate(); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (AppModalDialogQueue::iterator i = queue->begin(); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != queue->end(); ++i) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((*i)->web_contents() == web_contents) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*i)->Invalidate(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChromeJavaScriptDialogManager::OnDialogClosed( 3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebContents* web_contents, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DialogClosedCallback callback, 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success, 313a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& user_input) { 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If an extension opened this dialog then the extension may shut down its 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // lazy background page after the dialog closes. (Dialogs are closed before 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // their WebContents is destroyed so |web_contents| is still valid here.) 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DecrementLazyKeepaliveCount(web_contents); 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(success, user_input); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)content::JavaScriptDialogManager* GetJavaScriptDialogManagerInstance() { 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ChromeJavaScriptDialogManager::GetInstance(); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 327