hung_renderer_view.h revision 010d83a9304c5a91596085d917d248abff47903a
1ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek// Use of this source code is governed by a BSD-style license that can be
3ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek// found in the LICENSE file.
4ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek
5ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#ifndef CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
6ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#define CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
7ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek
8ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "base/memory/scoped_vector.h"
9ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "chrome/browser/favicon/favicon_tab_helper.h"
10ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "content/public/browser/web_contents_observer.h"
11ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "ui/base/models/table_model.h"
12ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "ui/views/controls/button/button.h"
13ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "ui/views/controls/table/table_grouper.h"
14ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "ui/views/controls/table/table_view.h"
15ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek#include "ui/views/window/dialog_delegate.h"
16ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek
17ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremeneknamespace content {
18686775deca8b8685eb90801495880e3abdd844c2Chris Lattnerclass WebContents;
19a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek}
20f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth
215595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenkonamespace views {
225595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenkoclass LabelButton;
23651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
24ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek
25ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek// Provides functionality to display information about a hung renderer.
26ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenekclass HungPagesTableModel : public ui::TableModel, public views::TableGrouper {
279c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko public:
289c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  // The Delegate is notified any time a WebContents the model is listening to
29ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek  // is destroyed.
30dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko  class Delegate {
31dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko   public:
32dc66adb40ee871b4c578ba615f45d82476c7119eDmitri Gribenko    virtual void TabDestroyed() = 0;
33dad4c1a9ac4ef1aa591ac2ef20dc4c30d96f9f2aDmitri Gribenko
3415a2aa0954bcf38411c14cf67c65e336022a7a1bDmitri Gribenko   protected:
3515a2aa0954bcf38411c14cf67c65e336022a7a1bDmitri Gribenko    virtual ~Delegate() {}
36dad4c1a9ac4ef1aa591ac2ef20dc4c30d96f9f2aDmitri Gribenko  };
37dad4c1a9ac4ef1aa591ac2ef20dc4c30d96f9f2aDmitri Gribenko
380c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  explicit HungPagesTableModel(Delegate* delegate);
390c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  virtual ~HungPagesTableModel();
400c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko
410c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  void InitForWebContents(content::WebContents* hung_contents);
420c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko
430c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  // Returns the first RenderProcessHost, or NULL if there aren't any
440c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  // WebContents.
450c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  content::RenderProcessHost* GetRenderProcessHost();
460c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko
470c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  // Returns the first RenderViewHost, or NULL if there aren't any WebContents.
480c4394c7f63008fbf4d335710b34f71afab362a3Dmitri Gribenko  content::RenderViewHost* GetRenderViewHost();
49ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek
505595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  // Overridden from ui::TableModel:
515595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  virtual int RowCount() OVERRIDE;
525595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  virtual base::string16 GetText(int row, int column_id) OVERRIDE;
535595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  virtual gfx::ImageSkia GetIcon(int row) OVERRIDE;
545595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
555595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko
565595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  // Overridden from views::TableGrouper:
575595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  virtual void GetGroupRange(int model_index,
585595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko                             views::GroupRange* range) OVERRIDE;
595595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko
605595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko private:
615595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  // Used to track a single WebContents. If the WebContents is destroyed
625595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  // TabDestroyed() is invoked on the model.
635595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko  class WebContentsObserverImpl : public content::WebContentsObserver {
645595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko   public:
655595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko    WebContentsObserverImpl(HungPagesTableModel* model,
665595ded882b22d77fdf535bd1a4c6c090110348aDmitri Gribenko                            content::WebContents* tab);
67a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek
68a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek    content::WebContents* web_contents() const {
69a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek      return content::WebContentsObserver::web_contents();
70a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek    }
719c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
729c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    FaviconTabHelper* favicon_tab_helper() {
739c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko      return FaviconTabHelper::FromWebContents(web_contents());
749c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    }
759c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
769c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    // WebContentsObserver overrides:
779c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE;
789c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    virtual void WebContentsDestroyed() OVERRIDE;
799c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
809c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko   private:
819c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    HungPagesTableModel* model_;
829c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
839c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko    DISALLOW_COPY_AND_ASSIGN(WebContentsObserverImpl);
849c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  };
859c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
869c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  // Invoked when a WebContents is destroyed. Cleans up |tab_observers_| and
879c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  // notifies the observer and delegate.
889c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  void TabDestroyed(WebContentsObserverImpl* tab);
899c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
909c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  typedef ScopedVector<WebContentsObserverImpl> TabObservers;
919c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko  TabObservers tab_observers_;
929c48d16a11872624410ab3a5944edcba0f32818cDmitri Gribenko
93a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  ui::TableModelObserver* observer_;
94a60ed47da13393796d8552b9fdca12abbb3eea42Ted Kremenek  Delegate* delegate_;
95ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek
96baf82b0fdf5c23dff80660add40bb92bd850bba0Ted Kremenek  DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
97baf82b0fdf5c23dff80660add40bb92bd850bba0Ted Kremenek};
98baf82b0fdf5c23dff80660add40bb92bd850bba0Ted Kremenek
99ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek// This class displays a dialog which contains information about a hung
100ef8225444452a1486bd721f3285301fe84643b00Stephen Hines// renderer process.
101ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesclass HungRendererDialogView : public views::DialogDelegateView,
102ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                               public views::ButtonListener,
103ef8225444452a1486bd721f3285301fe84643b00Stephen Hines                               public HungPagesTableModel::Delegate {
104ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek public:
105ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek  // Factory function for creating an instance of the HungRendererDialogView
106ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek  // class. At any given point only one instance can be active.
107ea834df7cd07d67a77e7dd6e48e8db27464be2fdTed Kremenek  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 base::string16 GetWindowTitle() const OVERRIDE;
124  virtual void WindowClosing() OVERRIDE;
125  virtual int GetDialogButtons() const OVERRIDE;
126  virtual base::string16 GetDialogButtonLabel(
127      ui::DialogButton button) const OVERRIDE;
128  virtual views::View* CreateExtraView() OVERRIDE;
129  virtual bool Accept(bool window_closing)  OVERRIDE;
130  virtual bool UseNewStyleForThisDialog() const OVERRIDE;
131
132  // views::ButtonListener overrides:
133  virtual void ButtonPressed(views::Button* sender,
134                             const ui::Event& event) OVERRIDE;
135
136  // HungPagesTableModel::Delegate overrides:
137  virtual void TabDestroyed() OVERRIDE;
138
139 protected:
140  HungRendererDialogView();
141  virtual ~HungRendererDialogView();
142
143  // views::View overrides:
144  virtual void ViewHierarchyChanged(
145      const ViewHierarchyChangedDetails& details) OVERRIDE;
146
147  static HungRendererDialogView* g_instance_;
148
149 private:
150  // Initialize the controls in this dialog.
151  void Init();
152
153  static void InitClass();
154
155  // Controls within the dialog box.
156  views::TableView* hung_pages_table_;
157
158  // The extra button inserted into the ClientView to kill the errant process.
159  views::LabelButton* kill_button_;
160
161  // The model that provides the contents of the table that shows a list of
162  // pages affected by the hang.
163  scoped_ptr<HungPagesTableModel> hung_pages_table_model_;
164
165  // Whether or not we've created controls for ourself.
166  bool initialized_;
167
168  // An amusing icon image.
169  static gfx::ImageSkia* frozen_icon_;
170
171  DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView);
172};
173
174#endif  // CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
175