Refactor common, platform-independent code for the repost form warning dialog on all platforms into a delegate.

The platform-dependent ConstrainedWindow{Gtk,Mac,Win} classes each have their own platform-dependent |ConstrainedWindowDelegate| to inherit from, so instead of a common superclass they now have a RepostFormWarningDelegate.

Also, change the RELOADING notification to REPOST_WARNING_SHOWN to avoid trying to close the dialog while it's already in the process of being closed.

BUG=none
TEST=RepostFormWarningTest.*

Review URL: http://codereview.chromium.org/1520023

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@44074 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index a425f79..186ec86 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -321,9 +321,8 @@
   NOTIMPLEMENTED();
 }
 
-void BrowserWindowCocoa::ShowRepostFormWarningDialog(
-    TabContents* tab_contents) {
-  new RepostFormWarningMac(GetNativeHandle(), tab_contents);
+void BrowserWindowCocoa::ShowRepostFormWarningDialog(TabContents* tab_contents) {
+  RepostFormWarningMac::Create(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 a9c480a..7139be6 100644
--- a/chrome/browser/cocoa/repost_form_warning_mac.h
+++ b/chrome/browser/cocoa/repost_form_warning_mac.h
@@ -8,49 +8,31 @@
 #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;
-@class RepostDelegate;
-class RepostFormWarningMac;
+class RepostFormWarningController;
 
-// Displays a dialog that warns the user that they are about to resubmit a form.
-// 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,
-                             public ConstrainedWindowMacDelegateSystemSheet {
+// Displays a dialog that warns the user that they are about to resubmit
+// a form. To show the dialog, call the |Create| method. It will open the
+// dialog and then delete itself when the user dismisses the dialog.
+class RepostFormWarningMac : public ConstrainedDialogDelegate {
  public:
-  RepostFormWarningMac(NSWindow* parent,
-                       TabContents* tab_contents);
-  virtual ~RepostFormWarningMac();
+  // Convenience method that creates a new |RepostFormWarningController| and
+  // then a new |RepostFormWarningMac| from that.
+  static RepostFormWarningMac* Create(NSWindow* parent,
+                                     TabContents* tab_contents);
 
+  RepostFormWarningMac(NSWindow* parent,
+                       RepostFormWarningController* controller);
+
+  // ConstrainedWindowDelegateMacSystemSheet methods:
   virtual void DeleteDelegate();
 
-  void Confirm();
-  void Cancel();
-
  private:
-  // NotificationObserver implementation.
-  // Watch for a new load or a closed tab and dismiss the dialog if they occur.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
+  virtual ~RepostFormWarningMac();
 
   // 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();
-
-  NotificationRegistrar registrar_;
-
-  // Navigation controller, used to continue the reload.
-  NavigationController* navigation_controller_;
-
-  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 31292c04..adfe54e8 100644
--- a/chrome/browser/cocoa/repost_form_warning_mac.mm
+++ b/chrome/browser/cocoa/repost_form_warning_mac.mm
@@ -5,24 +5,22 @@
 #include "chrome/browser/cocoa/repost_form_warning_mac.h"
 
 #include "app/l10n_util_mac.h"
-#include "base/message_loop.h"
-#include "chrome/browser/tab_contents/navigation_controller.h"
-#include "chrome/common/notification_service.h"
+#include "chrome/browser/repost_form_warning_controller.h"
 #include "grit/generated_resources.h"
 
 // The delegate of the NSAlert used to display the dialog. Forwards the alert's
-// completion event to the C++ class |RepostFormWarningMac|.
+// completion event to the C++ class |RepostFormWarningController|.
 @interface RepostDelegate : NSObject {
-  RepostFormWarningMac* warning_;  // weak, owns us.
+  RepostFormWarningController* warning_;  // weak
 }
-- (id)initWithWarning:(RepostFormWarningMac*)warning;
+- (id)initWithWarning:(RepostFormWarningController*)warning;
 - (void)alertDidEnd:(NSAlert*)alert
          returnCode:(int)returnCode
         contextInfo:(void*)contextInfo;
 @end
 
 @implementation RepostDelegate
-- (id)initWithWarning:(RepostFormWarningMac*)warning {
+- (id)initWithWarning:(RepostFormWarningController*)warning {
   if ((self = [super init])) {
     warning_ = warning;
   }
@@ -32,20 +30,28 @@
 - (void)alertDidEnd:(NSAlert*)alert
          returnCode:(int)returnCode
         contextInfo:(void*)contextInfo {
-  if (returnCode == NSAlertFirstButtonReturn)
-    warning_->Confirm();
-  else
+  if (returnCode == NSAlertFirstButtonReturn) {
+    warning_->Continue();
+  } else {
     warning_->Cancel();
+  }
 }
 @end
 
+RepostFormWarningMac* RepostFormWarningMac::Create(NSWindow* parent,
+                                                  TabContents* tab_contents) {
+  return new RepostFormWarningMac(
+      parent,
+      new RepostFormWarningController(tab_contents));
+}
+
 RepostFormWarningMac::RepostFormWarningMac(
     NSWindow* parent,
-    TabContents* tab_contents)
+    RepostFormWarningController* controller)
     : ConstrainedWindowMacDelegateSystemSheet(
-        [[[RepostDelegate alloc] initWithWarning:this] autorelease],
-        @selector(alertDidEnd:returnCode:contextInfo:)),
-      navigation_controller_(&tab_contents->controller()) {
+        [[[RepostDelegate alloc] initWithWarning:controller]
+            autorelease],
+        @selector(alertDidEnd:returnCode:contextInfo:)) {
   scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
   [alert setMessageText:
       l10n_util::GetNSStringWithFixup(IDS_HTTP_POST_WARNING_TITLE)];
@@ -58,67 +64,21 @@
 
   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);
+  controller->Show(this);
 }
 
 RepostFormWarningMac::~RepostFormWarningMac() {
 }
 
 void RepostFormWarningMac::DeleteDelegate() {
-  window_ = NULL;
   Dismiss();
   delete this;
 }
 
-void RepostFormWarningMac::Confirm() {
-  if (navigation_controller_) {
-    navigation_controller_->ContinuePendingReload();
-  }
-  Destroy();
-}
-
-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]
+  NSWindow* window = [(NSAlert*)sheet() window];
+  if (window && is_sheet_open()) {
+    [NSApp endSheet: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 ((type == NotificationType::LOAD_START ||
-       type == NotificationType::TAB_CLOSING ||
-       type == NotificationType::RELOADING)) {
-    DCHECK_EQ(Source<NavigationController>(source).ptr(),
-              navigation_controller_);
-    Dismiss();
-  }
-}
-
-void RepostFormWarningMac::Destroy() {
-  navigation_controller_ = NULL;
-  if (sheet()) {
-    set_sheet(nil);
-  }
-  if (window_) {
-    window_->CloseConstrainedWindow();
-  }
-}
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 9ce3119..a574c90a 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -879,8 +879,7 @@
   NOTIMPLEMENTED();
 }
 
-void BrowserWindowGtk::ShowRepostFormWarningDialog(
-    TabContents* tab_contents) {
+void BrowserWindowGtk::ShowRepostFormWarningDialog(TabContents* tab_contents) {
   new RepostFormWarningGtk(GetNativeHandle(), tab_contents);
 }
 
diff --git a/chrome/browser/gtk/repost_form_warning_gtk.cc b/chrome/browser/gtk/repost_form_warning_gtk.cc
index a3f4681..2c3e010 100644
--- a/chrome/browser/gtk/repost_form_warning_gtk.cc
+++ b/chrome/browser/gtk/repost_form_warning_gtk.cc
@@ -8,14 +8,15 @@
 #include "app/l10n_util.h"
 #include "base/message_loop.h"
 #include "chrome/browser/gtk/gtk_util.h"
+#include "chrome/browser/repost_form_warning_controller.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
-#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
 #include "grit/generated_resources.h"
 
 RepostFormWarningGtk::RepostFormWarningGtk(GtkWindow* parent,
                                            TabContents* tab_contents)
-    : navigation_controller_(&tab_contents->controller()) {
+    : controller_(new RepostFormWarningController(tab_contents)) {
   dialog_ = gtk_vbox_new(NULL, gtk_util::kContentAreaBorder);
   gtk_box_set_spacing(GTK_BOX(dialog_), gtk_util::kContentAreaSpacing);
   GtkWidget* label = gtk_label_new(
@@ -56,18 +57,7 @@
   g_signal_connect(cancel_, "hierarchy-changed",
                    G_CALLBACK(OnHierarchyChangedThunk), this);
 
-  window_ = tab_contents->CreateConstrainedDialog(this);
-
-  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_));
-
-}
-
-RepostFormWarningGtk::~RepostFormWarningGtk() {
+  controller_->Show(this);
 }
 
 GtkWidget* RepostFormWarningGtk::GetWidgetRoot() {
@@ -75,45 +65,26 @@
 }
 
 void RepostFormWarningGtk::DeleteDelegate() {
-  MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+  Dismiss();
+  delete this;
 }
 
-void RepostFormWarningGtk::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 (dialog_ && navigation_controller_ &&
-      (type == NotificationType::LOAD_START ||
-       type == NotificationType::TAB_CLOSING ||
-       type == NotificationType::RELOADING)) {
-    DCHECK_EQ(Source<NavigationController>(source).ptr(),
-              navigation_controller_);
-    OnCancel(dialog_);
-  }
+RepostFormWarningGtk::~RepostFormWarningGtk() {
 }
 
-void RepostFormWarningGtk::Destroy() {
+void RepostFormWarningGtk::Dismiss() {
   if (dialog_) {
     gtk_widget_destroy(dialog_);
     dialog_ = NULL;
   }
-  window_->CloseConstrainedWindow();
 }
 
 void RepostFormWarningGtk::OnRefresh(GtkWidget* widget) {
-  if (navigation_controller_) {
-    navigation_controller_->ContinuePendingReload();
-    // reloading the page will close the dialog.
-  }
+  controller_->Continue();
 }
 
 void RepostFormWarningGtk::OnCancel(GtkWidget* widget) {
-  if (navigation_controller_) {
-    navigation_controller_->CancelPendingReload();
-  }
-  Destroy();
+  controller_->Cancel();
 }
 
 void RepostFormWarningGtk::OnHierarchyChanged(GtkWidget* root,
diff --git a/chrome/browser/gtk/repost_form_warning_gtk.h b/chrome/browser/gtk/repost_form_warning_gtk.h
index 4382fbc..1c04fda 100644
--- a/chrome/browser/gtk/repost_form_warning_gtk.h
+++ b/chrome/browser/gtk/repost_form_warning_gtk.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -7,38 +7,31 @@
 
 #include <gtk/gtk.h>
 
-#include "chrome/common/notification_registrar.h"
-#include "chrome/browser/gtk/constrained_window_gtk.h"
 #include "app/gtk_signal.h"
+#include "chrome/browser/gtk/constrained_window_gtk.h"
 
-class NavigationController;
-class TabContents;
+class RepostFormWarningController;
 
-// Displays a dialog that warns the user that they are about to resubmit a form.
+// Displays a dialog that warns the user that they are about to resubmit
+// a form.
 // 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 RepostFormWarningGtk : public NotificationObserver,
-    ConstrainedWindowGtkDelegate {
+class RepostFormWarningGtk : public ConstrainedDialogDelegate {
  public:
   RepostFormWarningGtk(GtkWindow* parent, TabContents* tab_contents);
-  virtual ~RepostFormWarningGtk();
 
+  // ConstrainedDialogDelegate methods
   virtual GtkWidget* GetWidgetRoot();
 
   virtual void DeleteDelegate();
 
  private:
-  // NotificationObserver implementation.
-  // Watch for a new load or a closed tab and dismiss the dialog if they occur.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
+  virtual ~RepostFormWarningGtk();
 
-  // Tell Gtk to destroy the dialog window.  This will only be done once, even
-  // if Destroy is called multiple times.
-  void Destroy();
+  void Dismiss();
 
+  // Callbacks
   CHROMEGTK_CALLBACK_0(RepostFormWarningGtk, void, OnRefresh);
   CHROMEGTK_CALLBACK_0(RepostFormWarningGtk, void, OnCancel);
   CHROMEGTK_CALLBACK_1(RepostFormWarningGtk,
@@ -46,17 +39,12 @@
                        OnHierarchyChanged,
                        GtkWidget*);
 
-  NotificationRegistrar registrar_;
-
-  // Navigation controller, used to continue the reload.
-  NavigationController* navigation_controller_;
+  RepostFormWarningController* controller_;
 
   GtkWidget* dialog_;
   GtkWidget* ok_;
   GtkWidget* cancel_;
 
-  ConstrainedWindow* window_;
-
   DISALLOW_COPY_AND_ASSIGN(RepostFormWarningGtk);
 };
 
diff --git a/chrome/browser/repost_form_warning_controller.cc b/chrome/browser/repost_form_warning_controller.cc
new file mode 100644
index 0000000..7b38c4c
--- /dev/null
+++ b/chrome/browser/repost_form_warning_controller.cc
@@ -0,0 +1,66 @@
+// 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 "chrome/browser/repost_form_warning_controller.h"
+
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/common/notification_service.h"
+
+RepostFormWarningController::RepostFormWarningController(
+    TabContents* tab_contents)
+    : tab_contents_(tab_contents),
+      window_(NULL) {
+  NavigationController* controller = &tab_contents->controller();
+  registrar_.Add(this, NotificationType::LOAD_START,
+                 Source<NavigationController>(controller));
+  registrar_.Add(this, NotificationType::TAB_CLOSING,
+                 Source<NavigationController>(controller));
+  registrar_.Add(this, NotificationType::REPOST_WARNING_SHOWN,
+                 Source<NavigationController>(controller));
+}
+
+RepostFormWarningController::~RepostFormWarningController() {
+}
+
+void RepostFormWarningController::Show(
+    ConstrainedWindowDelegate* window_delegate) {
+  window_ = tab_contents_->CreateConstrainedDialog(window_delegate);
+}
+
+void RepostFormWarningController::Cancel() {
+  if (tab_contents_) {
+    tab_contents_->controller().CancelPendingReload();
+    CloseDialog();
+  }
+}
+
+void RepostFormWarningController::Continue() {
+  if (tab_contents_) {
+    tab_contents_->controller().ContinuePendingReload();
+    // If we reload the page, the dialog will be closed anyway.
+  }
+}
+
+void RepostFormWarningController::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 ((type == NotificationType::LOAD_START ||
+       type == NotificationType::TAB_CLOSING ||
+       type == NotificationType::REPOST_WARNING_SHOWN)) {
+    DCHECK_EQ(Source<NavigationController>(source).ptr(),
+              &tab_contents_->controller());
+    Cancel();
+  }
+}
+
+void RepostFormWarningController::CloseDialog() {
+  tab_contents_ = NULL;
+  if (window_) {
+    window_->CloseConstrainedWindow();
+  }
+  delete this;
+}
diff --git a/chrome/browser/repost_form_warning_controller.h b/chrome/browser/repost_form_warning_controller.h
new file mode 100644
index 0000000..2b2c0a81
--- /dev/null
+++ b/chrome/browser/repost_form_warning_controller.h
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef CHROME_BROWSER_REPOST_FORM_WARNING_CONTROLLER_H_
+#define CHROME_BROWSER_REPOST_FORM_WARNING_CONTROLLER_H_
+
+#include "chrome/browser/tab_contents/constrained_window.h"
+#include "chrome/common/notification_registrar.h"
+
+class NavigationController;
+class TabContents;
+
+// This class is used to continue or cancel a pending reload when the
+// repost form warning is shown. It is owned by the platform-dependent
+// |RepostFormWarning{Gtk,Mac,View}| classes and deletes itself after closing
+// the dialog.
+class RepostFormWarningController : public NotificationObserver {
+ public:
+  explicit RepostFormWarningController(TabContents* tab_contents);
+
+  // Show the warning dialog.
+  void Show(ConstrainedWindowDelegate* window_delegate);
+
+  // Cancel the reload.
+  void Cancel();
+
+  // Continue the reload.
+  void Continue();
+
+ private:
+  virtual ~RepostFormWarningController();
+
+  // NotificationObserver implementation.
+  // Watch for a new load or a closed tab and dismiss the dialog if they occur.
+  void Observe(NotificationType type,
+               const NotificationSource& source,
+               const NotificationDetails& details);
+
+  // Close the warning dialog.
+  void CloseDialog();
+
+  NotificationRegistrar registrar_;
+
+  // Tab contents, used to continue the reload.
+  TabContents* tab_contents_;
+
+  ConstrainedWindow* window_;
+
+  DISALLOW_COPY_AND_ASSIGN(RepostFormWarningController);
+};
+
+#endif  // CHROME_BROWSER_REPOST_FORM_WARNING_CONTROLLER_H_
diff --git a/chrome/browser/tab_contents/navigation_controller.cc b/chrome/browser/tab_contents/navigation_controller.cc
index 991b289b8..141712f 100644
--- a/chrome/browser/tab_contents/navigation_controller.cc
+++ b/chrome/browser/tab_contents/navigation_controller.cc
@@ -204,15 +204,16 @@
     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.
+    NotificationService::current()->Notify(
+        NotificationType::REPOST_WARNING_SHOWN,
+        Source<NavigationController>(this),
+        NotificationService::NoDetails());
+
     pending_reload_ = reload_type;
     tab_contents_->Activate();
     tab_contents_->delegate()->ShowRepostFormWarningDialog(tab_contents_);
@@ -235,7 +236,7 @@
     NOTREACHED();
   } else {
     ReloadInternal(false, pending_reload_);
-    CancelPendingReload();
+    pending_reload_ = NO_RELOAD;
   }
 }
 
diff --git a/chrome/browser/views/repost_form_warning_view.cc b/chrome/browser/views/repost_form_warning_view.cc
index a2ef324..7d7ed67d 100644
--- a/chrome/browser/views/repost_form_warning_view.cc
+++ b/chrome/browser/views/repost_form_warning_view.cc
@@ -8,6 +8,7 @@
 #include "app/message_box_flags.h"
 #include "chrome/browser/browser_list.h"
 #include "chrome/browser/browser_window.h"
+#include "chrome/browser/repost_form_warning_controller.h"
 #include "chrome/browser/tab_contents/navigation_controller.h"
 #include "chrome/browser/tab_contents/tab_contents.h"
 #include "chrome/common/notification_service.h"
@@ -31,20 +32,13 @@
 RepostFormWarningView::RepostFormWarningView(
     gfx::NativeWindow parent_window,
     TabContents* tab_contents)
-      : navigation_controller_(&tab_contents->controller()),
+      : controller_(new RepostFormWarningController(tab_contents)),
         message_box_view_(NULL) {
   message_box_view_ = new MessageBoxView(
       MessageBoxFlags::kIsConfirmMessageBox,
       l10n_util::GetString(IDS_HTTP_POST_WARNING),
       std::wstring());
-  dialog_ = tab_contents->CreateConstrainedDialog(this);
-
-  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_));
+  controller_->Show(this);
 }
 
 RepostFormWarningView::~RepostFormWarningView() {
@@ -66,56 +60,23 @@
   return std::wstring();
 }
 
-void RepostFormWarningView::DeleteDelegate() {
-  delete this;
-}
-
-bool RepostFormWarningView::Cancel() {
-  if (navigation_controller_) {
-    navigation_controller_->CancelPendingReload();
-    Close();
-  }
-  return true;
-}
-
-bool RepostFormWarningView::Accept() {
-  if (navigation_controller_) {
-    navigation_controller_->ContinuePendingReload();
-    Close();
-  }
-  return true;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// RepostFormWarningView, views::WindowDelegate implementation:
-
 views::View* RepostFormWarningView::GetContentsView() {
   return message_box_view_;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-// RepostFormWarningView, private:
-
-void RepostFormWarningView::Close() {
-  navigation_controller_ = NULL;
-  if (dialog_) {
-    dialog_->CloseConstrainedWindow();
-  }
+bool RepostFormWarningView::Cancel() {
+  controller_->Cancel();
+  return true;
 }
 
-void RepostFormWarningView::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 (window() && navigation_controller_ &&
-      (type == NotificationType::LOAD_START ||
-       type == NotificationType::TAB_CLOSING ||
-       type == NotificationType::RELOADING)) {
-    DCHECK_EQ(Source<NavigationController>(source).ptr(),
-              navigation_controller_);
-    navigation_controller_ = NULL;
-    Close();
-  }
+bool RepostFormWarningView::Accept() {
+  controller_->Continue();
+  return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// RepostFormWarningView, RepostFormWarning implementation:
+
+void RepostFormWarningView::DeleteDelegate() {
+  delete this;
 }
diff --git a/chrome/browser/views/repost_form_warning_view.h b/chrome/browser/views/repost_form_warning_view.h
index b8a4a8c..dcac48ab9 100644
--- a/chrome/browser/views/repost_form_warning_view.h
+++ b/chrome/browser/views/repost_form_warning_view.h
@@ -10,30 +10,32 @@
 #include "gfx/native_widget_types.h"
 #include "views/window/dialog_delegate.h"
 
+class ConstrainedWindow;
 class MessageBoxView;
 class NavigationController;
+class RepostFormWarningController;
 class TabContents;
 namespace views {
 class Window;
 }
 
-// Displays a dialog that warns the user that they are about to resubmit a form.
+// Displays a dialog that warns the user that they are about to resubmit
+// a form.
 // 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 RepostFormWarningView : public ConstrainedDialogDelegate,
-                              public NotificationObserver {
+class RepostFormWarningView : public ConstrainedDialogDelegate {
  public:
   // Use BrowserWindow::ShowRepostFormWarningDialog to use.
   RepostFormWarningView(gfx::NativeWindow parent_window,
                         TabContents* tab_contents);
-  virtual ~RepostFormWarningView();
 
   // views::DialogDelegate Methods:
   virtual std::wstring GetWindowTitle() const;
   virtual std::wstring GetDialogButtonLabel(
       MessageBoxFlags::DialogButton button) const;
   virtual void DeleteDelegate();
+
   virtual bool Cancel();
   virtual bool Accept();
 
@@ -41,26 +43,12 @@
   virtual views::View* GetContentsView();
 
  private:
-
-  // NotificationObserver implementation.
-  // Watch for a new load or a closed tab and dismiss the dialog if they occur.
-  virtual void Observe(NotificationType type,
-                       const NotificationSource& source,
-                       const NotificationDetails& details);
-
-  // Close the ConstrainedWindow.
-  void Close();
-
-  NotificationRegistrar registrar_;
+  virtual ~RepostFormWarningView();
 
   // The message box view whose commands we handle.
   MessageBoxView* message_box_view_;
 
-  // The dialog shown.
-  ConstrainedWindow* dialog_;
-
-  // Navigation controller, used to continue the reload.
-  NavigationController* navigation_controller_;
+  RepostFormWarningController* controller_;
 
   DISALLOW_COPY_AND_ASSIGN(RepostFormWarningView);
 };
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 7c328e8..b323f802 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1848,6 +1848,8 @@
         'browser/renderer_host/x509_user_cert_resource_handler.h',
         'browser/renderer_preferences_util.cc',
         'browser/renderer_preferences_util.h',
+        'browser/repost_form_warning_controller.cc',
+        'browser/repost_form_warning_controller.h',
         'browser/rlz/rlz.cc',
         'browser/rlz/rlz.h',
         'browser/safe_browsing/bloom_filter.cc',
diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h
index 3c7806bf..e3e478c 100644
--- a/chrome/common/notification_type.h
+++ b/chrome/common/notification_type.h
@@ -942,9 +942,9 @@
     PANEL_STATE_CHANGED,
 #endif
 
-    // Sent before a page is reloaded or the repost form warning is brought up.
+    // Sent before the repost form warning is brought up.
     // The source is a NavigationController.
-    RELOADING,
+    REPOST_WARNING_SHOWN,
 
 #if defined(TOOLKIT_VIEWS)
     // Sent when a bookmark's context menu is shown. Used to notify