diff options
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 3 | ||||
-rw-r--r-- | chrome/browser/browser.cc | 2 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_cocoa.mm | 2 | ||||
-rw-r--r-- | chrome/browser/cocoa/repost_form_warning_mac.h | 17 | ||||
-rw-r--r-- | chrome/browser/cocoa/repost_form_warning_mac.mm | 68 | ||||
-rw-r--r-- | chrome/browser/cocoa/toolbar_controller.mm | 3 | ||||
-rw-r--r-- | chrome/browser/repost_form_warning_uitest.cc | 78 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_controller.cc | 38 | ||||
-rw-r--r-- | chrome/browser/tab_contents/navigation_controller.h | 9 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 | ||||
-rw-r--r-- | chrome/common/notification_type.h | 4 | ||||
-rw-r--r-- | chrome/test/data/form.html | 8 |
12 files changed, 190 insertions, 43 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 8ae593b..25f9d87 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -2299,7 +2299,8 @@ void AutomationProvider::ReloadAsync(int tab_handle) { return; } - tab->Reload(false); + const bool check_for_repost = true; + tab->Reload(check_for_repost); } } diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index af98839..3dc499b 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -2787,7 +2787,7 @@ void Browser::UpdateCommandsForTabState() { !(type() & TYPE_APP) && tab_count() > 1); // Current navigation entry, may be NULL. - NavigationEntry* active_entry = current_tab->controller().GetActiveEntry(); + NavigationEntry* active_entry = nc.GetActiveEntry(); // Page-related commands window_->SetStarredState(current_tab->is_starred()); diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm index 8380256..01d592e 100644 --- a/chrome/browser/cocoa/browser_window_cocoa.mm +++ b/chrome/browser/cocoa/browser_window_cocoa.mm @@ -333,7 +333,7 @@ void BrowserWindowCocoa::ShowNewProfileDialog() { void BrowserWindowCocoa::ShowRepostFormWarningDialog( TabContents* tab_contents) { - new RepostFormWarningMac(GetNativeHandle(), &tab_contents->controller()); + new RepostFormWarningMac(GetNativeHandle(), tab_contents); } void BrowserWindowCocoa::ShowContentSettingsWindow( diff --git a/chrome/browser/cocoa/repost_form_warning_mac.h b/chrome/browser/cocoa/repost_form_warning_mac.h index 91586cf..a9c480a 100644 --- a/chrome/browser/cocoa/repost_form_warning_mac.h +++ b/chrome/browser/cocoa/repost_form_warning_mac.h @@ -8,6 +8,8 @@ #import <Cocoa/Cocoa.h> #include "base/scoped_nsobject.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/cocoa/constrained_window_mac.h" #include "chrome/common/notification_registrar.h" class NavigationController; @@ -18,12 +20,15 @@ class RepostFormWarningMac; // To display the dialog, allocate this object on the heap. It will open the // dialog from its constructor and then delete itself when the user dismisses // the dialog. -class RepostFormWarningMac : public NotificationObserver { +class RepostFormWarningMac : public NotificationObserver, + public ConstrainedWindowMacDelegateSystemSheet { public: RepostFormWarningMac(NSWindow* parent, - NavigationController* navigation_controller); + TabContents* tab_contents); virtual ~RepostFormWarningMac(); + virtual void DeleteDelegate(); + void Confirm(); void Cancel(); @@ -34,7 +39,9 @@ class RepostFormWarningMac : public NotificationObserver { const NotificationSource& source, const NotificationDetails& details); - // Close the sheet. This will only be done once, even if Destroy is called + // Close the sheet. + void Dismiss(); + // Clean up. This will only be done once, even if Destroy is called // multiple times (eg, from both Confirm and Observe.) void Destroy(); @@ -43,9 +50,7 @@ class RepostFormWarningMac : public NotificationObserver { // Navigation controller, used to continue the reload. NavigationController* navigation_controller_; - scoped_nsobject<NSAlert> alert_; - - scoped_nsobject<RepostDelegate> delegate_; + ConstrainedWindow* window_; DISALLOW_COPY_AND_ASSIGN(RepostFormWarningMac); }; diff --git a/chrome/browser/cocoa/repost_form_warning_mac.mm b/chrome/browser/cocoa/repost_form_warning_mac.mm index 2ca64d8..31292c0 100644 --- a/chrome/browser/cocoa/repost_form_warning_mac.mm +++ b/chrome/browser/cocoa/repost_form_warning_mac.mm @@ -41,64 +41,84 @@ RepostFormWarningMac::RepostFormWarningMac( NSWindow* parent, - NavigationController* navigation_controller) - : navigation_controller_(navigation_controller), - alert_([[NSAlert alloc] init]), - delegate_([[RepostDelegate alloc] initWithWarning:this]) { - [alert_ setMessageText: + TabContents* tab_contents) + : ConstrainedWindowMacDelegateSystemSheet( + [[[RepostDelegate alloc] initWithWarning:this] autorelease], + @selector(alertDidEnd:returnCode:contextInfo:)), + navigation_controller_(&tab_contents->controller()) { + scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]); + [alert setMessageText: l10n_util::GetNSStringWithFixup(IDS_HTTP_POST_WARNING_TITLE)]; - [alert_ setInformativeText: + [alert setInformativeText: l10n_util::GetNSStringWithFixup(IDS_HTTP_POST_WARNING)]; - [alert_ addButtonWithTitle: + [alert addButtonWithTitle: l10n_util::GetNSStringWithFixup(IDS_HTTP_POST_WARNING_RESEND)]; - [alert_ addButtonWithTitle: + [alert addButtonWithTitle: l10n_util::GetNSStringWithFixup(IDS_CANCEL)]; - [alert_ beginSheetModalForWindow:parent - modalDelegate:delegate_.get() - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) - contextInfo:nil]; + set_sheet(alert); registrar_.Add(this, NotificationType::LOAD_START, Source<NavigationController>(navigation_controller_)); registrar_.Add(this, NotificationType::TAB_CLOSING, Source<NavigationController>(navigation_controller_)); + registrar_.Add(this, NotificationType::RELOADING, + Source<NavigationController>(navigation_controller_)); + window_ = tab_contents->CreateConstrainedDialog(this); } RepostFormWarningMac::~RepostFormWarningMac() { } +void RepostFormWarningMac::DeleteDelegate() { + window_ = NULL; + Dismiss(); + delete this; +} + void RepostFormWarningMac::Confirm() { + if (navigation_controller_) { + navigation_controller_->ContinuePendingReload(); + } Destroy(); - if (navigation_controller_) - navigation_controller_->Reload(false); } void RepostFormWarningMac::Cancel() { + if (navigation_controller_) { + navigation_controller_->CancelPendingReload(); + } Destroy(); } +void RepostFormWarningMac::Dismiss() { + if (sheet() && is_sheet_open()) { + // This will call |Cancel()|. + [NSApp endSheet:[(NSAlert*)sheet() window] + returnCode:NSAlertSecondButtonReturn]; + } +} + void RepostFormWarningMac::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { // Close the dialog if we load a page (because reloading might not apply to // the same page anymore) or if the tab is closed, because then we won't have // a navigation controller anymore. - if (alert_ && navigation_controller_ && - (type == NotificationType::LOAD_START || - type == NotificationType::TAB_CLOSING)) { + if ((type == NotificationType::LOAD_START || + type == NotificationType::TAB_CLOSING || + type == NotificationType::RELOADING)) { DCHECK_EQ(Source<NavigationController>(source).ptr(), navigation_controller_); - navigation_controller_ = NULL; - - // This will call |Cancel()|. - [NSApp endSheet:[alert_ window] returnCode:NSAlertSecondButtonReturn]; + Dismiss(); } } void RepostFormWarningMac::Destroy() { - if (alert_) { - alert_.reset(NULL); - MessageLoop::current()->DeleteSoon(FROM_HERE, this); + navigation_controller_ = NULL; + if (sheet()) { + set_sheet(nil); + } + if (window_) { + window_->CloseConstrainedWindow(); } } diff --git a/chrome/browser/cocoa/toolbar_controller.mm b/chrome/browser/cocoa/toolbar_controller.mm index bf32934..431932b 100644 --- a/chrome/browser/cocoa/toolbar_controller.mm +++ b/chrome/browser/cocoa/toolbar_controller.mm @@ -384,6 +384,9 @@ class PrefObserverBridge : public NotificationObserver { case IDC_FORWARD: button = forwardButton_; break; + case IDC_RELOAD: + button = reloadButton_; + break; case IDC_HOME: button = homeButton_; break; diff --git a/chrome/browser/repost_form_warning_uitest.cc b/chrome/browser/repost_form_warning_uitest.cc new file mode 100644 index 0000000..755ae85 --- /dev/null +++ b/chrome/browser/repost_form_warning_uitest.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2010 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 <string> + +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/net/url_fixer_upper.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/automation/browser_proxy.h" +#include "chrome/test/ui/ui_test.h" +#include "net/url_request/url_request_unittest.h" + +using std::wstring; + +namespace { + +const wchar_t kDocRoot[] = L"chrome/test/data"; + +} // namespace + +class RepostFormWarningTest : public UITest { +}; + + +TEST_F(RepostFormWarningTest, TestDoubleReload) { + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot, NULL); + ASSERT_TRUE(NULL != server.get()); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + EXPECT_TRUE(browser.get()); + + scoped_refptr<TabProxy> tab(browser->GetTab(0)); + + // Load a form. + ASSERT_TRUE(tab->NavigateToURL(server->TestServerPageW(L"files/form.html"))); + // Submit it. + ASSERT_TRUE(tab->NavigateToURL(GURL( + "javascript:document.getElementById('form').submit()"))); + + // Try to reload it twice, checking for repost. + tab->ReloadAsync(); + tab->ReloadAsync(); + + // Navigate away from the page (this is when the test usually crashes). + ASSERT_TRUE(tab->NavigateToURL(server->TestServerPageW(L"bar"))); +} + +TEST_F(RepostFormWarningTest, TestLoginAfterRepost) { + scoped_refptr<HTTPTestServer> server = + HTTPTestServer::CreateServer(kDocRoot, NULL); + ASSERT_TRUE(NULL != server.get()); + scoped_refptr<BrowserProxy> browser(automation()->GetBrowserWindow(0)); + ASSERT_TRUE(browser.get()); + + scoped_refptr<TabProxy> tab(browser->GetTab(0)); + + // Load a form. + ASSERT_TRUE(tab->NavigateToURL(server->TestServerPageW(L"files/form.html"))); + // Submit it. + ASSERT_TRUE(tab->NavigateToURL(GURL( + "javascript:document.getElementById('form').submit()"))); + + // Try to reload it, checking for repost. + tab->ReloadAsync(); + + // Navigate to a page that requires authentication, bringing up another + // tab-modal sheet. + ASSERT_TRUE(tab->NavigateToURL(server->TestServerPageW(L"auth-basic"))); + + // Try to reload it again. + tab->ReloadAsync(); + + // Navigate away from the page. + ASSERT_TRUE(tab->NavigateToURL(server->TestServerPageW(L"bar"))); +} diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc index 96e5fa9..bdcc811 100644 --- a/chrome/browser/tab_contents/navigation_controller.cc +++ b/chrome/browser/tab_contents/navigation_controller.cc @@ -146,7 +146,8 @@ NavigationController::NavigationController(TabContents* contents, needs_reload_(false), user_gesture_observed_(false), session_storage_namespace_id_(profile->GetWebKitContext()-> - dom_storage_context()->AllocateSessionStorageNamespaceId()) { + dom_storage_context()->AllocateSessionStorageNamespaceId()), + pending_reload_(NO_RELOAD) { DCHECK(profile_); } @@ -195,22 +196,25 @@ void NavigationController::ReloadInternal(bool check_for_repost, DiscardNonCommittedEntriesInternal(); int current_index = GetCurrentEntryIndex(); - if (check_for_repost_ && check_for_repost && current_index != -1 && + // If we are no where, then we can't reload. TODO(darin): We should add a + // CanReload method. + if (current_index == -1) { + return; + } + + NotificationService::current()->Notify(NotificationType::RELOADING, + Source<NavigationController>(this), + NotificationService::NoDetails()); + + if (check_for_repost_ && check_for_repost && GetEntryAtIndex(current_index)->has_post_data()) { // The user is asking to reload a page with POST data. Prompt to make sure // they really want to do this. If they do, the dialog will call us back // with check_for_repost = false. + pending_reload_ = reload_type; tab_contents_->Activate(); tab_contents_->delegate()->ShowRepostFormWarningDialog(tab_contents_); } else { - // Base the navigation on where we are now... - int current_index = GetCurrentEntryIndex(); - - // If we are no where, then we can't reload. TODO(darin): We should add a - // CanReload method. - if (current_index == -1) - return; - DiscardNonCommittedEntriesInternal(); pending_entry_index_ = current_index; @@ -219,6 +223,20 @@ void NavigationController::ReloadInternal(bool check_for_repost, } } +void NavigationController::CancelPendingReload() { + DCHECK(pending_reload_ != NO_RELOAD); + pending_reload_ = NO_RELOAD; +} + +void NavigationController::ContinuePendingReload() { + if (pending_reload_ == NO_RELOAD) { + NOTREACHED(); + } else { + ReloadInternal(false, pending_reload_); + CancelPendingReload(); + } +} + NavigationEntry* NavigationController::GetEntryWithPageID( SiteInstance* instance, int32 page_id) const { int index = GetEntryIndexWithPageID(instance, page_id); diff --git a/chrome/browser/tab_contents/navigation_controller.h b/chrome/browser/tab_contents/navigation_controller.h index 1efdc3d..c2dae3f 100644 --- a/chrome/browser/tab_contents/navigation_controller.h +++ b/chrome/browser/tab_contents/navigation_controller.h @@ -400,6 +400,11 @@ class NavigationController { } static size_t max_entry_count() { return max_entry_count_; } + // Cancels a repost that brought up a warning. + void CancelPendingReload(); + // Continues a repost that brought up a warning. + void ContinuePendingReload(); + private: class RestoreHelper; friend class RestoreHelper; @@ -557,6 +562,10 @@ class NavigationController { // The maximum number of entries that a navigation controller can store. static size_t max_entry_count_; + // If a repost is pending, its type (RELOAD or RELOAD_IGNORING_CACHE), + // NO_RELOAD otherwise. + ReloadType pending_reload_; + DISALLOW_COPY_AND_ASSIGN(NavigationController); }; diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 0034769..368cb2a 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -297,6 +297,7 @@ 'browser/process_singleton_linux_uitest.cc', 'browser/process_singleton_win_uitest.cc', 'browser/renderer_host/resource_dispatcher_host_uitest.cc', + 'browser/repost_form_warning_uitest.cc', 'browser/sanity_uitest.cc', 'browser/session_history_uitest.cc', 'browser/sessions/session_restore_uitest.cc', diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 40211d5..b379f8a 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -885,6 +885,10 @@ class NotificationType { LOGIN_AUTHENTICATION, #endif + // Sent before a page is reloaded or the repost form warning is brought up. + // The source is a NavigationController. + RELOADING, + // Count (must be last) ---------------------------------------------------- // Used to determine the number of notification types. Not valid as // a type parameter when registering for or posting notifications. diff --git a/chrome/test/data/form.html b/chrome/test/data/form.html new file mode 100644 index 0000000..5e98542 --- /dev/null +++ b/chrome/test/data/form.html @@ -0,0 +1,8 @@ +<html> +<head> +</head> +<body> +<!-- A form leading to an empty page. The form is submitted via javascript, so + we don't need a submit button. --> +<form id="form" action="/moose" method="post"></form> +</body>
\ No newline at end of file |