hung_renderer_view.h revision f2477e01787aa58f445919b809d89e252beef54f
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
6#define CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
7
8#include "base/memory/scoped_vector.h"
9#include "chrome/browser/favicon/favicon_tab_helper.h"
10#include "content/public/browser/web_contents_observer.h"
11#include "ui/base/models/table_model.h"
12#include "ui/views/controls/button/button.h"
13#include "ui/views/controls/table/table_grouper.h"
14#include "ui/views/controls/table/table_view.h"
15#include "ui/views/window/dialog_delegate.h"
16
17namespace content {
18class WebContents;
19}
20
21namespace views {
22class LabelButton;
23}
24
25// Provides functionality to display information about a hung renderer.
26class HungPagesTableModel : public ui::TableModel, public views::TableGrouper {
27 public:
28  // The Delegate is notified any time a WebContents the model is listening to
29  // is destroyed.
30  class Delegate {
31   public:
32    virtual void TabDestroyed() = 0;
33
34   protected:
35    virtual ~Delegate() {}
36  };
37
38  explicit HungPagesTableModel(Delegate* delegate);
39  virtual ~HungPagesTableModel();
40
41  void InitForWebContents(content::WebContents* hung_contents);
42
43  // Returns the first RenderProcessHost, or NULL if there aren't any
44  // WebContents.
45  content::RenderProcessHost* GetRenderProcessHost();
46
47  // Returns the first RenderViewHost, or NULL if there aren't any WebContents.
48  content::RenderViewHost* GetRenderViewHost();
49
50  // Overridden from ui::TableModel:
51  virtual int RowCount() OVERRIDE;
52  virtual string16 GetText(int row, int column_id) OVERRIDE;
53  virtual gfx::ImageSkia GetIcon(int row) OVERRIDE;
54  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
55
56  // Overridden from views::TableGrouper:
57  virtual void GetGroupRange(int model_index,
58                             views::GroupRange* range) OVERRIDE;
59
60 private:
61  // Used to track a single WebContents. If the WebContents is destroyed
62  // TabDestroyed() is invoked on the model.
63  class WebContentsObserverImpl : public content::WebContentsObserver {
64   public:
65    WebContentsObserverImpl(HungPagesTableModel* model,
66                            content::WebContents* tab);
67
68    content::WebContents* web_contents() const {
69      return content::WebContentsObserver::web_contents();
70    }
71
72    FaviconTabHelper* favicon_tab_helper() {
73      return FaviconTabHelper::FromWebContents(web_contents());
74    }
75
76    // WebContentsObserver overrides:
77    virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
78    virtual void WebContentsDestroyed(content::WebContents* tab) OVERRIDE;
79
80   private:
81    HungPagesTableModel* model_;
82
83    DISALLOW_COPY_AND_ASSIGN(WebContentsObserverImpl);
84  };
85
86  // Invoked when a WebContents is destroyed. Cleans up |tab_observers_| and
87  // notifies the observer and delegate.
88  void TabDestroyed(WebContentsObserverImpl* tab);
89
90  typedef ScopedVector<WebContentsObserverImpl> TabObservers;
91  TabObservers tab_observers_;
92
93  ui::TableModelObserver* observer_;
94  Delegate* delegate_;
95
96  DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
97};
98
99// This class displays a dialog which contains information about a hung
100// renderer process.
101class HungRendererDialogView : public views::DialogDelegateView,
102                               public views::ButtonListener,
103                               public HungPagesTableModel::Delegate {
104 public:
105  // Factory function for creating an instance of the HungRendererDialogView
106  // class. At any given point only one instance can be active.
107  static HungRendererDialogView* Create(gfx::NativeView context);
108
109  // Returns a pointer to the singleton instance if any.
110  static HungRendererDialogView* GetInstance();
111
112  // Platform specific function to kill the renderer process identified by the
113  // handle passed in.
114  static void KillRendererProcess(base::ProcessHandle process_handle);
115
116  // Returns true if the frame is in the foreground.
117  static bool IsFrameActive(content::WebContents* contents);
118
119  virtual void ShowForWebContents(content::WebContents* contents);
120  virtual void EndForWebContents(content::WebContents* contents);
121
122  // views::DialogDelegateView overrides:
123  virtual string16 GetWindowTitle() const OVERRIDE;
124  virtual void WindowClosing() OVERRIDE;
125  virtual int GetDialogButtons() const OVERRIDE;
126  virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
127  virtual views::View* CreateExtraView() OVERRIDE;
128  virtual bool Accept(bool window_closing)  OVERRIDE;
129  virtual bool UseNewStyleForThisDialog() const OVERRIDE;
130
131  // views::ButtonListener overrides:
132  virtual void ButtonPressed(views::Button* sender,
133                             const ui::Event& event) OVERRIDE;
134
135  // HungPagesTableModel::Delegate overrides:
136  virtual void TabDestroyed() OVERRIDE;
137
138 protected:
139  HungRendererDialogView();
140  virtual ~HungRendererDialogView();
141
142  // views::View overrides:
143  virtual void ViewHierarchyChanged(
144      const ViewHierarchyChangedDetails& details) OVERRIDE;
145
146  static HungRendererDialogView* g_instance_;
147
148 private:
149  // Initialize the controls in this dialog.
150  void Init();
151
152  // Returns the bounds the dialog should be displayed at to be meaningfully
153  // associated with the specified WebContents.
154  gfx::Rect GetDisplayBounds(content::WebContents* contents);
155
156  static void InitClass();
157
158  // Controls within the dialog box.
159  views::TableView* hung_pages_table_;
160
161  // The extra button inserted into the ClientView to kill the errant process.
162  views::LabelButton* kill_button_;
163
164  // The model that provides the contents of the table that shows a list of
165  // pages affected by the hang.
166  scoped_ptr<HungPagesTableModel> hung_pages_table_model_;
167
168  // Whether or not we've created controls for ourself.
169  bool initialized_;
170
171  // An amusing icon image.
172  static gfx::ImageSkia* frozen_icon_;
173
174  DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView);
175};
176
177#endif  // CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
178