diff options
author | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-19 16:10:51 +0000 |
---|---|---|
committer | flackr@chromium.org <flackr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-19 16:10:51 +0000 |
commit | c5e22aee57bd524acf0fb620192a05cdcfc4c1ab (patch) | |
tree | 860c7d622ab4ca210a17539235863112feea5adf /chrome | |
parent | 1da813714de79af80d4790b7797ea6788822c9be (diff) | |
download | chromium_src-c5e22aee57bd524acf0fb620192a05cdcfc4c1ab.zip chromium_src-c5e22aee57bd524acf0fb620192a05cdcfc4c1ab.tar.gz chromium_src-c5e22aee57bd524acf0fb620192a05cdcfc4c1ab.tar.bz2 |
Close created HtmlDialogs on closing of the browser that opened them.
BUG=103595
TEST=Open a dialog from a new browser (test incognito browser too), and close that browser. The dialog should close avoiding the use of the invalid profile.
Review URL: http://codereview.chromium.org/9051004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@118301 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
22 files changed, 254 insertions, 63 deletions
diff --git a/chrome/browser/chromeos/choose_mobile_network_dialog.cc b/chrome/browser/chromeos/choose_mobile_network_dialog.cc index e525f62..19cf4d4 100644 --- a/chrome/browser/chromeos/choose_mobile_network_dialog.cc +++ b/chrome/browser/chromeos/choose_mobile_network_dialog.cc @@ -30,15 +30,16 @@ namespace chromeos { // static void ChooseMobileNetworkDialog::ShowDialog(gfx::NativeWindow owning_window) { Profile* profile; + Browser* browser = NULL; if (UserManager::Get()->user_is_logged_in()) { - Browser* browser = BrowserList::GetLastActive(); + browser = BrowserList::GetLastActive(); DCHECK(browser); profile = browser->profile(); } else { profile = ProfileManager::GetDefaultProfile(); } HtmlDialogView* html_view = - new HtmlDialogView(profile, new ChooseMobileNetworkDialog); + new HtmlDialogView(profile, browser, new ChooseMobileNetworkDialog); html_view->InitDialog(); browser::CreateViewsWindow(owning_window, html_view, STYLE_FLUSH); html_view->GetWidget()->Show(); diff --git a/chrome/browser/chromeos/login/login_html_dialog.cc b/chrome/browser/chromeos/login/login_html_dialog.cc index d751a5c..b4e64bc 100644 --- a/chrome/browser/chromeos/login/login_html_dialog.cc +++ b/chrome/browser/chromeos/login/login_html_dialog.cc @@ -59,7 +59,7 @@ LoginHtmlDialog::~LoginHtmlDialog() { void LoginHtmlDialog::Show() { HtmlDialogView* html_view = - new HtmlDialogView(ProfileManager::GetDefaultProfile(), this); + new HtmlDialogView(ProfileManager::GetDefaultProfile(), NULL, this); #if defined(USE_AURA) // TODO(saintlou): Until the new Bubble have been landed. views::Widget::CreateWindowWithParent(html_view, parent_window_); diff --git a/chrome/browser/chromeos/sim_dialog_delegate.cc b/chrome/browser/chromeos/sim_dialog_delegate.cc index 4d6335f..c592708 100644 --- a/chrome/browser/chromeos/sim_dialog_delegate.cc +++ b/chrome/browser/chromeos/sim_dialog_delegate.cc @@ -49,15 +49,16 @@ namespace chromeos { void SimDialogDelegate::ShowDialog(gfx::NativeWindow owning_window, SimDialogMode mode) { Profile* profile; + Browser* browser = NULL; if (UserManager::Get()->user_is_logged_in()) { - Browser* browser = BrowserList::GetLastActive(); + browser = BrowserList::GetLastActive(); DCHECK(browser); profile = browser->profile(); } else { profile = ProfileManager::GetDefaultProfile(); } HtmlDialogView* html_view = - new HtmlDialogView(profile, new SimDialogDelegate(mode)); + new HtmlDialogView(profile, browser, new SimDialogDelegate(mode)); html_view->InitDialog(); browser::CreateViewsWindow(owning_window, html_view, STYLE_FLUSH); html_view->GetWidget()->Show(); diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc index 0304866..6709e62 100644 --- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc +++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc @@ -62,6 +62,7 @@ CloudPrintSetupFlow* CloudPrintSetupFlow::OpenDialog( const base::WeakPtr<Delegate>& delegate, gfx::NativeWindow parent_window) { DCHECK(profile); + Browser* browser = BrowserList::GetLastActiveWithProfile(profile); // Set the arguments for showing the gaia login page. DictionaryValue args; args.SetString("user", ""); @@ -83,12 +84,9 @@ CloudPrintSetupFlow* CloudPrintSetupFlow::OpenDialog( // invoked in the context of a "token expired" notfication. If we don't have // a brower, use the underlying dialog system to show the dialog without // using a browser. - if (!parent_window) { - Browser* browser = BrowserList::GetLastActive(); - if (browser && browser->window()) - parent_window = browser->window()->GetNativeHandle(); - } - browser::ShowHtmlDialog(parent_window, profile, flow, STYLE_GENERIC); + if (!parent_window && browser && browser->window()) + parent_window = browser->window()->GetNativeHandle(); + browser::ShowHtmlDialog(parent_window, profile, browser, flow, STYLE_GENERIC); return flow; } diff --git a/chrome/browser/printing/print_dialog_cloud.cc b/chrome/browser/printing/print_dialog_cloud.cc index ca5c0fd..579b73b 100644 --- a/chrome/browser/printing/print_dialog_cloud.cc +++ b/chrome/browser/printing/print_dialog_cloud.cc @@ -624,6 +624,7 @@ void CreateDialogImpl(const FilePath& path_to_file, g_browser_process->profile_manager()->GetLoadedProfiles(); DCHECK_GT(loaded_profiles.size(), 0U); profile = loaded_profiles[0]; + browser = BrowserList::GetLastActiveWithProfile(profile); } DCHECK(profile); PrefService* pref_service = profile->GetPrefs(); @@ -650,7 +651,7 @@ void CreateDialogImpl(const FilePath& path_to_file, DCHECK(browser); #if defined(USE_AURA) HtmlDialogView* html_view = - new HtmlDialogView(profile, dialog_delegate); + new HtmlDialogView(profile, browser, dialog_delegate); views::Widget::CreateWindowWithParent(html_view, browser->window()->GetNativeHandle()); html_view->InitDialog(); @@ -659,7 +660,11 @@ void CreateDialogImpl(const FilePath& path_to_file, browser->BrowserShowHtmlDialog(dialog_delegate, NULL, STYLE_GENERIC); #endif } else { - browser::ShowHtmlDialog(NULL, profile, dialog_delegate, STYLE_GENERIC); + browser::ShowHtmlDialog(NULL, + profile, + browser, + dialog_delegate, + STYLE_GENERIC); } } diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index ac18f52..3080871 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -1277,7 +1277,11 @@ gfx::NativeWindow Browser::BrowserShowHtmlDialog( if (!parent_window) parent_window = window_->GetNativeHandle(); - return browser::ShowHtmlDialog(parent_window, profile_, delegate, style); + return browser::ShowHtmlDialog(parent_window, + profile_, + this, + delegate, + style); } void Browser::BrowserRenderWidgetShowing() { diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h index e395ad1..970f272 100644 --- a/chrome/browser/ui/browser_dialogs.h +++ b/chrome/browser/ui/browser_dialogs.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -36,12 +36,16 @@ void ShowAboutIPCDialog(); #endif // IPC_MESSAGE_LOG_ENABLED // Creates and shows an HTML dialog with the given delegate and profile. -// The window is automatically destroyed when it is closed. +// The window is automatically destroyed when it is closed. |browser| can be +// NULL if the profile used is not incognito, otherwise the window will be +// closed if the browser is closed. // Returns the created window. // // Make sure to use the returned window only when you know it is safe // to do so, i.e. before OnDialogClosed() is called on the delegate. -gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile, +gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, + Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate, DialogStyle style); diff --git a/chrome/browser/ui/cocoa/html_dialog_window_controller.h b/chrome/browser/ui/cocoa/html_dialog_window_controller.h index 2ba46a5..93d0d83 100644 --- a/chrome/browser/ui/cocoa/html_dialog_window_controller.h +++ b/chrome/browser/ui/cocoa/html_dialog_window_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -13,6 +13,7 @@ #include "base/memory/scoped_ptr.h" #include "chrome/browser/ui/webui/html_dialog_ui.h" +class Browser; class HtmlDialogWindowDelegateBridge; class Profile; class TabContentsWrapper; @@ -28,13 +29,15 @@ class TabContentsWrapper; } // Creates and shows an HtmlDialogWindowController with the given -// delegate and profile. The window is automatically destroyed when -// it is closed. Returns the created window. +// delegate and profile whose lifetime is controlled by the given +// browser. The window is automatically destroyed when it, or its +// controlling browser is closed. Returns the created window. // // Make sure to use the returned window only when you know it is safe // to do so, i.e. before OnDialogClosed() is called on the delegate. + (NSWindow*)showHtmlDialog:(HtmlDialogUIDelegate*)delegate - profile:(Profile*)profile; + profile:(Profile*)profile + browser:(Browser*)browser; @end @@ -43,7 +46,8 @@ class TabContentsWrapper; // This is the designated initializer. However, this is exposed only // for testing; use showHtmlDialog instead. - (id)initWithDelegate:(HtmlDialogUIDelegate*)delegate - profile:(Profile*)profile; + profile:(Profile*)profile + browser:(Browser*)browser; // Loads the HTML content from the delegate; this is not a lightweight // process which is why it is not part of the constructor. Must be diff --git a/chrome/browser/ui/cocoa/html_dialog_window_controller.mm b/chrome/browser/ui/cocoa/html_dialog_window_controller.mm index a312567..f57af53 100644 --- a/chrome/browser/ui/cocoa/html_dialog_window_controller.mm +++ b/chrome/browser/ui/cocoa/html_dialog_window_controller.mm @@ -9,11 +9,13 @@ #include "base/property_bag.h" #include "base/sys_string_conversions.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" #import "chrome/browser/ui/browser_dialogs.h" #import "chrome/browser/ui/cocoa/browser_command_executor.h" #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h" #include "chrome/browser/ui/dialog_style.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/webui/html_dialog_controller.h" #include "chrome/browser/ui/webui/html_dialog_tab_contents_delegate.h" #include "chrome/browser/ui/webui/html_dialog_ui.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -33,6 +35,7 @@ public: // All parameters must be non-NULL/non-nil. HtmlDialogWindowDelegateBridge(HtmlDialogWindowController* controller, Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate); virtual ~HtmlDialogWindowDelegateBridge(); @@ -62,6 +65,7 @@ public: private: HtmlDialogWindowController* controller_; // weak HtmlDialogUIDelegate* delegate_; // weak, owned by controller_ + HtmlDialogController* dialog_controller_; // Calls delegate_'s OnDialogClosed() exactly once, nulling it out // afterwards so that no other HtmlDialogUIDelegate calls are sent @@ -85,28 +89,25 @@ namespace browser { gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate, DialogStyle style) { - // It's not always safe to display an html dialog with an off the record - // profile. If the last browser with that profile is closed it will go - // away. - // On most platforms we insist on the dialog being modal if we're off the - // record to prevent that. That wont work on the Mac since we don't have - // modal dialogs. - // Fall back to the old (incorrect) behavior of grabbing the original - // profile. - // NOTE: Use the parent parameter once we implement modal dialogs. return [HtmlDialogWindowController showHtmlDialog:delegate - profile:profile->GetOriginalProfile()]; + profile:profile + browser:browser]; } } // namespace html_dialog_window_controller HtmlDialogWindowDelegateBridge::HtmlDialogWindowDelegateBridge( - HtmlDialogWindowController* controller, Profile* profile, + HtmlDialogWindowController* controller, + Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate) : HtmlDialogTabContentsDelegate(profile), - controller_(controller), delegate_(delegate) { + controller_(controller), + delegate_(delegate), + dialog_controller_(new HtmlDialogController(this, profile, browser)) { DCHECK(controller_); DCHECK(delegate_); } @@ -115,6 +116,7 @@ HtmlDialogWindowDelegateBridge::~HtmlDialogWindowDelegateBridge() {} void HtmlDialogWindowDelegateBridge::WindowControllerClosed() { Detach(); + delete dialog_controller_; controller_ = nil; DelegateOnDialogClosed(""); } @@ -250,17 +252,20 @@ void HtmlDialogWindowDelegateBridge::HandleKeyboardEvent( // in once we implement modal dialogs. + (NSWindow*)showHtmlDialog:(HtmlDialogUIDelegate*)delegate - profile:(Profile*)profile { + profile:(Profile*)profile + browser:(Browser*)browser { HtmlDialogWindowController* htmlDialogWindowController = [[HtmlDialogWindowController alloc] initWithDelegate:delegate - profile:profile]; + profile:profile + browser:browser]; [htmlDialogWindowController loadDialogContents]; [htmlDialogWindowController showWindow:nil]; return [htmlDialogWindowController window]; } - (id)initWithDelegate:(HtmlDialogUIDelegate*)delegate - profile:(Profile*)profile { + profile:(Profile*)profile + browser:(Browser*)browser { DCHECK(delegate); DCHECK(profile); @@ -287,7 +292,8 @@ void HtmlDialogWindowDelegateBridge::HandleKeyboardEvent( [window setTitle:base::SysUTF16ToNSString(delegate->GetDialogTitle())]; [window setMinSize:dialogRect.size]; [window center]; - delegate_.reset(new HtmlDialogWindowDelegateBridge(self, profile, delegate)); + delegate_.reset( + new HtmlDialogWindowDelegateBridge(self, profile, browser, delegate)); return self; } diff --git a/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm b/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm index e655e23..80f3cdc 100644 --- a/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/html_dialog_window_controller_unittest.mm @@ -90,7 +90,8 @@ TEST_F(HtmlDialogWindowControllerTest, showDialog) { HtmlDialogWindowController* html_dialog_window_controller = [[HtmlDialogWindowController alloc] initWithDelegate:&delegate_ - profile:profile()]; + profile:profile() + browser:browser()]; [html_dialog_window_controller loadDialogContents]; [html_dialog_window_controller showWindow:nil]; diff --git a/chrome/browser/ui/gtk/html_dialog_gtk.cc b/chrome/browser/ui/gtk/html_dialog_gtk.cc index 210e28c..12dfaa4 100644 --- a/chrome/browser/ui/gtk/html_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/html_dialog_gtk.cc @@ -15,6 +15,7 @@ #include "chrome/browser/ui/gtk/gtk_util.h" #include "chrome/browser/ui/gtk/tab_contents_container_gtk.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" +#include "chrome/browser/ui/webui/html_dialog_controller.h" #include "chrome/browser/ui/webui/html_dialog_ui.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -24,19 +25,16 @@ using content::WebUIMessageHandler; namespace browser { -gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile, +gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, + Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate, DialogStyle style) { - // It's not always safe to display an html dialog with an off the record - // profile. If the last browser with that profile is closed it will go - // away. // Ignore style for now. The style parameter only used in the implementation // in html_dialog_view.cc file. // TODO (bshe): Add style parameter to HtmlDialogGtk. - DCHECK(!profile->IsOffTheRecord() || - delegate->GetDialogModalType() != ui::MODAL_TYPE_NONE); HtmlDialogGtk* html_dialog = - new HtmlDialogGtk(profile, delegate, parent); + new HtmlDialogGtk(profile, browser, delegate, parent); return html_dialog->InitDialog(); } @@ -66,12 +64,14 @@ void SetDialogStyle() { // HtmlDialogGtk, public: HtmlDialogGtk::HtmlDialogGtk(Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate, gfx::NativeWindow parent_window) : HtmlDialogTabContentsDelegate(profile), delegate_(delegate), parent_window_(parent_window), - dialog_(NULL) { + dialog_(NULL), + dialog_controller_(new HtmlDialogController(this, profile, browser)) { } HtmlDialogGtk::~HtmlDialogGtk() { diff --git a/chrome/browser/ui/gtk/html_dialog_gtk.h b/chrome/browser/ui/gtk/html_dialog_gtk.h index 2f3fe0d..52c06a7 100644 --- a/chrome/browser/ui/gtk/html_dialog_gtk.h +++ b/chrome/browser/ui/gtk/html_dialog_gtk.h @@ -19,6 +19,8 @@ typedef struct _GtkWidget GtkWidget; +class Browser; +class HtmlDialogController; class Profile; class TabContents; class TabContentsContainerGtk; @@ -27,7 +29,9 @@ class TabContentsWrapper; class HtmlDialogGtk : public HtmlDialogTabContentsDelegate, public HtmlDialogUIDelegate { public: - HtmlDialogGtk(Profile* profile, HtmlDialogUIDelegate* delegate, + HtmlDialogGtk(Profile* profile, + Browser* browser, + HtmlDialogUIDelegate* delegate, gfx::NativeWindow parent_window); virtual ~HtmlDialogGtk(); @@ -65,6 +69,7 @@ class HtmlDialogGtk : public HtmlDialogTabContentsDelegate, GtkWidget* dialog_; + scoped_ptr<HtmlDialogController> dialog_controller_; scoped_ptr<TabContentsWrapper> tab_; scoped_ptr<TabContentsContainerGtk> tab_contents_container_; diff --git a/chrome/browser/ui/views/html_dialog_view.cc b/chrome/browser/ui/views/html_dialog_view.cc index d58608b..abe5c86 100644 --- a/chrome/browser/ui/views/html_dialog_view.cc +++ b/chrome/browser/ui/views/html_dialog_view.cc @@ -10,6 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/views/window.h" +#include "chrome/browser/ui/webui/html_dialog_controller.h" #include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" @@ -34,14 +35,10 @@ namespace browser { // Declared in browser_dialogs.h so that others don't need to depend on our .h. gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate, DialogStyle style) { - // It's not always safe to display an html dialog with an off the record - // profile. If the last browser with that profile is closed it will go - // away. - DCHECK(!profile->IsOffTheRecord() || - delegate->GetDialogModalType() != ui::MODAL_TYPE_NONE); - HtmlDialogView* html_view = new HtmlDialogView(profile, delegate); + HtmlDialogView* html_view = new HtmlDialogView(profile, browser, delegate); browser::CreateViewsWindow(parent, html_view, style); html_view->InitDialog(); html_view->GetWidget()->Show(); @@ -54,11 +51,13 @@ gfx::NativeWindow ShowHtmlDialog(gfx::NativeWindow parent, // HtmlDialogView, public: HtmlDialogView::HtmlDialogView(Profile* profile, + Browser* browser, HtmlDialogUIDelegate* delegate) : DOMView(), HtmlDialogTabContentsDelegate(profile), initialized_(false), - delegate_(delegate) { + delegate_(delegate), + dialog_controller_(new HtmlDialogController(this, profile, browser)) { } HtmlDialogView::~HtmlDialogView() { diff --git a/chrome/browser/ui/views/html_dialog_view.h b/chrome/browser/ui/views/html_dialog_view.h index fb439d0..fb5f3ce 100644 --- a/chrome/browser/ui/views/html_dialog_view.h +++ b/chrome/browser/ui/views/html_dialog_view.h @@ -19,6 +19,8 @@ #include "ui/views/widget/widget_delegate.h" class Browser; +class HtmlDialogController; +class Profile; //////////////////////////////////////////////////////////////////////////////// // @@ -40,7 +42,9 @@ class HtmlDialogView public views::WidgetDelegate, public TabFirstRenderWatcher::Delegate { public: - HtmlDialogView(Profile* profile, HtmlDialogUIDelegate* delegate); + HtmlDialogView(Profile* profile, + Browser* browser, + HtmlDialogUIDelegate* delegate); virtual ~HtmlDialogView(); // Initializes the contents of the dialog (the DOMView and the callbacks). @@ -111,6 +115,9 @@ class HtmlDialogView // using this variable. HtmlDialogUIDelegate* delegate_; + // Controls lifetime of dialog. + scoped_ptr<HtmlDialogController> dialog_controller_; + DISALLOW_COPY_AND_ASSIGN(HtmlDialogView); }; diff --git a/chrome/browser/ui/views/html_dialog_view_browsertest.cc b/chrome/browser/ui/views/html_dialog_view_browsertest.cc index d1fb2b7..e98beb7 100644 --- a/chrome/browser/ui/views/html_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/html_dialog_view_browsertest.cc @@ -32,8 +32,10 @@ const int kInitialHeight = 40; class TestHtmlDialogView: public HtmlDialogView { public: - TestHtmlDialogView(Profile* profile, HtmlDialogUIDelegate* delegate) - : HtmlDialogView(profile, delegate), + TestHtmlDialogView(Profile* profile, + Browser* browser, + HtmlDialogUIDelegate* delegate) + : HtmlDialogView(profile, browser, delegate), painted_(false), should_quit_on_size_change_(false) { delegate->GetDialogSize(&last_size_); @@ -107,7 +109,7 @@ IN_PROC_BROWSER_TEST_F(HtmlDialogBrowserTest, MAYBE_SizeWindow) { delegate->set_size(kInitialWidth, kInitialHeight); TestHtmlDialogView* html_view = - new TestHtmlDialogView(browser()->profile(), delegate); + new TestHtmlDialogView(browser()->profile(), browser(), delegate); WebContents* web_contents = browser()->GetSelectedWebContents(); ASSERT_TRUE(web_contents != NULL); views::Widget::CreateWindowWithParent( @@ -188,7 +190,7 @@ IN_PROC_BROWSER_TEST_F(HtmlDialogBrowserTest, DISABLED_WebContentRendered) { GURL(chrome::kChromeUIChromeURLsURL)); TestHtmlDialogView* html_view = - new TestHtmlDialogView(browser()->profile(), delegate); + new TestHtmlDialogView(browser()->profile(), browser(), delegate); WebContents* web_contents = browser()->GetSelectedWebContents(); ASSERT_TRUE(web_contents != NULL); views::Widget::CreateWindowWithParent( diff --git a/chrome/browser/ui/views/keyboard_overlay_dialog_view.cc b/chrome/browser/ui/views/keyboard_overlay_dialog_view.cc index a1fcac6..366cf48 100644 --- a/chrome/browser/ui/views/keyboard_overlay_dialog_view.cc +++ b/chrome/browser/ui/views/keyboard_overlay_dialog_view.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -37,7 +37,7 @@ KeyboardOverlayDialogView::KeyboardOverlayDialogView( Profile* profile, HtmlDialogUIDelegate* delegate, BrowserView* parent_view) - : HtmlDialogView(profile, delegate), + : HtmlDialogView(profile, NULL, delegate), parent_view_(parent_view) { } diff --git a/chrome/browser/ui/webui/html_dialog_controller.cc b/chrome/browser/ui/webui/html_dialog_controller.cc new file mode 100644 index 0000000..a4642ce --- /dev/null +++ b/chrome/browser/ui/webui/html_dialog_controller.cc @@ -0,0 +1,40 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/html_dialog_controller.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/common/chrome_notification_types.h" +#include "content/public/browser/notification_service.h" +#include "content/public/browser/notification_source.h" + +HtmlDialogController::HtmlDialogController(HtmlDialogUIDelegate* delegate, + Profile* profile, + Browser* browser) + : dialog_delegate_(delegate) { + // It's only safe to show an off the record profile if we have a browser which + // has this profile to maintain its existence. + DCHECK(!profile->IsOffTheRecord() || (browser && + browser->profile() == profile)); + // If we're passed a browser it should own the profile we're using. + DCHECK(!browser || browser->profile() == profile); + if (browser) { + registrar_.Add(this, + chrome::NOTIFICATION_BROWSER_CLOSING, + content::Source<Browser>(browser)); + } +} + +// content::NotificationObserver implementation: +void HtmlDialogController::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK(type == chrome::NOTIFICATION_BROWSER_CLOSING); + + // If the browser creating this dialog is closed, close the dialog to prevent + // using potentially destroyed profiles. + dialog_delegate_->OnDialogClosed(std::string()); +} diff --git a/chrome/browser/ui/webui/html_dialog_controller.h b/chrome/browser/ui/webui/html_dialog_controller.h new file mode 100644 index 0000000..6786475 --- /dev/null +++ b/chrome/browser/ui/webui/html_dialog_controller.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_HTML_DIALOG_CONTROLLER_H_ +#define CHROME_BROWSER_UI_WEBUI_HTML_DIALOG_CONTROLLER_H_ +#pragma once + +#include "chrome/browser/ui/webui/html_dialog_ui.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" + +class Browser; +class Profile; + +// This provides the common functionality for HtmlDialogs of notifying the +// dialog that it should close when the browser that created it has closed to +// avoid using an old Profile object. +class HtmlDialogController : public content::NotificationObserver { + public: + HtmlDialogController(HtmlDialogUIDelegate* delegate, + Profile* profile, + Browser* browser); + + // content::NotificationObserver implementation. + virtual void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) OVERRIDE; + + private: + // The delegate controlled by this instance. This class is owned by the + // delegate. + HtmlDialogUIDelegate* dialog_delegate_; + + // Used for notification of parent browser closing. + content::NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(HtmlDialogController); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_HTML_DIALOG_CONTROLLER_H_ diff --git a/chrome/browser/ui/webui/html_dialog_controller_browsertest.cc b/chrome/browser/ui/webui/html_dialog_controller_browsertest.cc new file mode 100644 index 0000000..1fadb62 --- /dev/null +++ b/chrome/browser/ui/webui/html_dialog_controller_browsertest.cc @@ -0,0 +1,64 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/webui/test_html_dialog_ui_delegate.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +class TestDialogClosedDelegate : public test::TestHtmlDialogUIDelegate { + public: + TestDialogClosedDelegate() + : test::TestHtmlDialogUIDelegate(GURL(chrome::kChromeUIChromeURLsURL)), + dialog_closed_(false) { + } + + // Overridden from HtmlDialogUIDelegate: + virtual ui::ModalType GetDialogModalType() const OVERRIDE { + return ui::MODAL_TYPE_NONE; + } + + // Overridden from HtmlDialogUIDelegate: + virtual void OnDialogClosed(const std::string& json_retval) OVERRIDE { + dialog_closed_ = true; + } + + bool dialog_closed() { + return dialog_closed_; + } + + private: + bool dialog_closed_; +}; + +} // namespace + +class HtmlDialogControllerBrowserTest : public InProcessBrowserTest { + public: + HtmlDialogControllerBrowserTest() {} +}; + +// Tests that an HtmlDialog can be shown for an incognito browser and that when +// that browser is closed the dialog created by that browser is closed. +IN_PROC_BROWSER_TEST_F(HtmlDialogControllerBrowserTest, IncognitoBrowser) { + Browser* browser = CreateIncognitoBrowser(); + scoped_ptr<TestDialogClosedDelegate> delegate(new TestDialogClosedDelegate()); + + // Create the dialog and make sure the initial "closed" state is what we + // expect. + browser->BrowserShowHtmlDialog(delegate.get(), NULL, STYLE_GENERIC); + ui_test_utils::RunAllPendingInMessageLoop(); + ASSERT_FALSE(delegate->dialog_closed()); + + // Closing the browser should close the dialogs associated with that browser. + browser->CloseWindow(); + ui_test_utils::RunAllPendingInMessageLoop(); + ASSERT_TRUE(delegate->dialog_closed()); +} diff --git a/chrome/browser/ui/webui/task_manager_dialog.cc b/chrome/browser/ui/webui/task_manager_dialog.cc index 9bd6557..deca53f 100644 --- a/chrome/browser/ui/webui/task_manager_dialog.cc +++ b/chrome/browser/ui/webui/task_manager_dialog.cc @@ -11,6 +11,7 @@ #include "chrome/browser/platform_util.h" #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/scoped_user_pref_update.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/browser_list.h" @@ -168,7 +169,12 @@ void TaskManagerDialogImpl::OnCloseDialog() { void TaskManagerDialogImpl::OpenHtmlDialog() { Browser* browser = BrowserList::GetLastActive(); - window_ = browser->BrowserShowHtmlDialog(this, NULL, STYLE_GENERIC); + DCHECK(browser); + window_ = browser::ShowHtmlDialog(NULL, + browser->profile()->GetOriginalProfile(), + NULL, + this, + STYLE_GENERIC); } // **************************************************** diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index dbd5e99..2156f08 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -3830,6 +3830,8 @@ 'browser/ui/webui/input_window_dialog_ui.h', 'browser/ui/webui/input_window_dialog_webui.cc', 'browser/ui/webui/input_window_dialog_webui.h', + 'browser/ui/webui/html_dialog_controller.cc', + 'browser/ui/webui/html_dialog_controller.h', 'browser/ui/webui/html_dialog_tab_contents_delegate.cc', 'browser/ui/webui/html_dialog_tab_contents_delegate.h', 'browser/ui/webui/html_dialog_ui.cc', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 8446758..2c36ff5 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2734,6 +2734,7 @@ 'browser/ui/webui/test_chrome_web_ui_factory_browsertest.cc', 'browser/ui/webui/bidi_checker_web_ui_test.cc', 'browser/ui/webui/bidi_checker_web_ui_test.h', + 'browser/ui/webui/html_dialog_controller_browsertest.cc', 'browser/ui/webui/net_internals/net_internals_ui_browsertest.cc', 'browser/ui/webui/net_internals/net_internals_ui_browsertest.h', 'browser/ui/webui/ntp/new_tab_ui_browsertest.cc', |