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 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 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 130 // views::ButtonListener overrides: 131 virtual void ButtonPressed(views::Button* sender, 132 const ui::Event& event) OVERRIDE; 133 134 // HungPagesTableModel::Delegate overrides: 135 virtual void TabDestroyed() OVERRIDE; 136 137 protected: 138 HungRendererDialogView(); 139 virtual ~HungRendererDialogView(); 140 141 // views::View overrides: 142 virtual void ViewHierarchyChanged( 143 const ViewHierarchyChangedDetails& details) OVERRIDE; 144 145 static HungRendererDialogView* g_instance_; 146 147 private: 148 // Initialize the controls in this dialog. 149 void Init(); 150 151 // Returns the bounds the dialog should be displayed at to be meaningfully 152 // associated with the specified WebContents. 153 gfx::Rect GetDisplayBounds(content::WebContents* contents); 154 155 static void InitClass(); 156 157 // Controls within the dialog box. 158 views::TableView* hung_pages_table_; 159 160 // The extra button inserted into the ClientView to kill the errant process. 161 views::LabelButton* kill_button_; 162 163 // The model that provides the contents of the table that shows a list of 164 // pages affected by the hang. 165 scoped_ptr<HungPagesTableModel> hung_pages_table_model_; 166 167 // Whether or not we've created controls for ourself. 168 bool initialized_; 169 170 // An amusing icon image. 171 static gfx::ImageSkia* frozen_icon_; 172 173 DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView); 174 }; 175 176 #endif // CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_ 177