summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/ui/cocoa/hung_renderer_controller.h9
-rw-r--r--chrome/browser/ui/cocoa/hung_renderer_controller.mm34
2 files changed, 43 insertions, 0 deletions
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.h b/chrome/browser/ui/cocoa/hung_renderer_controller.h
index 957e5fb..7d4fd1c 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller.h
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller.h
@@ -22,9 +22,11 @@
#import "base/mac/cocoa_protocols.h"
#import "base/memory/scoped_nsobject.h"
+#import "base/memory/scoped_ptr.h"
@class MultiKeyEquivalentButton;
class TabContents;
+class TabContentsObserverBridge;
@interface HungRendererController : NSWindowController<NSTableViewDataSource> {
@private
@@ -38,6 +40,9 @@ class TabContents;
// NULL while this dialog is open.
TabContents* hungContents_;
+ // Observes |hungContents_| in case it closes while the panel is up.
+ scoped_ptr<TabContentsObserverBridge> hungContentsObserver_;
+
// Backing data for |tableView_|. Titles of each TabContents that
// shares a renderer process with |hungContents_|.
scoped_nsobject<NSArray> hungTitles_;
@@ -65,6 +70,10 @@ class TabContents;
// If |contents| has a different process, this function does nothing.
- (void)endForTabContents:(TabContents*)contents;
+// Called by |hungContentsObserver_| to indicate that |hungContents_|
+// has gone away.
+- (void)renderViewGone;
+
@end // HungRendererController
diff --git a/chrome/browser/ui/cocoa/hung_renderer_controller.mm b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
index f8dc950..bab2472 100644
--- a/chrome/browser/ui/cocoa/hung_renderer_controller.mm
+++ b/chrome/browser/ui/cocoa/hung_renderer_controller.mm
@@ -36,6 +36,29 @@ namespace {
HungRendererController* g_instance = NULL;
} // namespace
+class TabContentsObserverBridge : public TabContentsObserver {
+ public:
+ TabContentsObserverBridge(TabContents* tab_contents,
+ HungRendererController* controller)
+ : TabContentsObserver(tab_contents),
+ controller_(controller) {
+ }
+
+ protected:
+ // TabContentsObserver overrides:
+ virtual void RenderViewGone() OVERRIDE {
+ [controller_ renderViewGone];
+ }
+ virtual void TabContentsDestroyed(TabContents* tab) OVERRIDE {
+ [controller_ renderViewGone];
+ }
+
+ private:
+ HungRendererController* controller_; // weak
+
+ DISALLOW_COPY_AND_ASSIGN(TabContentsObserverBridge);
+};
+
@implementation HungRendererController
- (id)initWithWindowNibName:(NSString*)nibName {
@@ -134,9 +157,15 @@ HungRendererController* g_instance = NULL;
[self autorelease];
}
+// TODO(shess): This could observe all of the tabs referenced in the
+// loop, updating the dialog and keeping it up so long as any remain.
+// Tabs closed by their renderer will close the dialog (that's
+// activity!), so it would not add much value. Also, the views
+// implementation only monitors the initiating tab.
- (void)showForTabContents:(TabContents*)contents {
DCHECK(contents);
hungContents_ = contents;
+ hungContentsObserver_.reset(new TabContentsObserverBridge(contents, self));
scoped_nsobject<NSMutableArray> titles([[NSMutableArray alloc] init]);
scoped_nsobject<NSMutableArray> favicons([[NSMutableArray alloc] init]);
for (TabContentsIterator it; !it.done(); ++it) {
@@ -167,6 +196,11 @@ HungRendererController* g_instance = NULL;
}
}
+- (void)renderViewGone {
+ // Cannot call performClose:, because the close button is disabled.
+ [self close];
+}
+
@end
@implementation HungRendererController (JustForTesting)