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 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. 101 class 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 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