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 17 namespace content { 18 class WebContents; 19 } 20 21 namespace views { 22 class LabelButton; 23 } 24 25 // Provides functionality to display information about a hung renderer. 26 class 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 base::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 FaviconTabHelper* favicon_tab_helper() { 69 return FaviconTabHelper::FromWebContents(web_contents()); 70 } 71 72 // WebContentsObserver overrides: 73 virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; 74 virtual void WebContentsDestroyed() OVERRIDE; 75 76 private: 77 HungPagesTableModel* model_; 78 79 DISALLOW_COPY_AND_ASSIGN(WebContentsObserverImpl); 80 }; 81 82 // Invoked when a WebContents is destroyed. Cleans up |tab_observers_| and 83 // notifies the observer and delegate. 84 void TabDestroyed(WebContentsObserverImpl* tab); 85 86 typedef ScopedVector<WebContentsObserverImpl> TabObservers; 87 TabObservers tab_observers_; 88 89 ui::TableModelObserver* observer_; 90 Delegate* delegate_; 91 92 DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel); 93 }; 94 95 // This class displays a dialog which contains information about a hung 96 // renderer process. 97 class HungRendererDialogView : public views::DialogDelegateView, 98 public views::ButtonListener, 99 public HungPagesTableModel::Delegate { 100 public: 101 // Factory function for creating an instance of the HungRendererDialogView 102 // class. At any given point only one instance can be active. 103 static HungRendererDialogView* Create(gfx::NativeView context); 104 105 // Returns a pointer to the singleton instance if any. 106 static HungRendererDialogView* GetInstance(); 107 108 // Platform specific function to kill the renderer process identified by the 109 // handle passed in. 110 static void KillRendererProcess(base::ProcessHandle process_handle); 111 112 // Returns true if the frame is in the foreground. 113 static bool IsFrameActive(content::WebContents* contents); 114 115 virtual void ShowForWebContents(content::WebContents* contents); 116 virtual void EndForWebContents(content::WebContents* contents); 117 118 // views::DialogDelegateView overrides: 119 virtual base::string16 GetWindowTitle() const OVERRIDE; 120 virtual void WindowClosing() OVERRIDE; 121 virtual int GetDialogButtons() const OVERRIDE; 122 virtual base::string16 GetDialogButtonLabel( 123 ui::DialogButton button) const OVERRIDE; 124 virtual views::View* CreateExtraView() OVERRIDE; 125 virtual bool Accept(bool window_closing) OVERRIDE; 126 virtual bool UseNewStyleForThisDialog() const OVERRIDE; 127 128 // views::ButtonListener overrides: 129 virtual void ButtonPressed(views::Button* sender, 130 const ui::Event& event) OVERRIDE; 131 132 // HungPagesTableModel::Delegate overrides: 133 virtual void TabDestroyed() OVERRIDE; 134 135 protected: 136 HungRendererDialogView(); 137 virtual ~HungRendererDialogView(); 138 139 // views::View overrides: 140 virtual void ViewHierarchyChanged( 141 const ViewHierarchyChangedDetails& details) OVERRIDE; 142 143 static HungRendererDialogView* g_instance_; 144 145 private: 146 // Initialize the controls in this dialog. 147 void Init(); 148 149 static void InitClass(); 150 151 // Controls within the dialog box. 152 views::TableView* hung_pages_table_; 153 154 // The extra button inserted into the ClientView to kill the errant process. 155 views::LabelButton* kill_button_; 156 157 // The model that provides the contents of the table that shows a list of 158 // pages affected by the hang. 159 scoped_ptr<HungPagesTableModel> hung_pages_table_model_; 160 161 // Whether or not we've created controls for ourself. 162 bool initialized_; 163 164 // An amusing icon image. 165 static gfx::ImageSkia* frozen_icon_; 166 167 DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView); 168 }; 169 170 #endif // CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_ 171