// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_ #define CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_ #include "base/memory/scoped_vector.h" #include "chrome/browser/favicon/favicon_tab_helper.h" #include "content/public/browser/web_contents_observer.h" #include "ui/base/models/table_model.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/table/table_grouper.h" #include "ui/views/controls/table/table_view.h" #include "ui/views/window/dialog_delegate.h" namespace content { class WebContents; } namespace views { class LabelButton; } // Provides functionality to display information about a hung renderer. class HungPagesTableModel : public ui::TableModel, public views::TableGrouper { public: // The Delegate is notified any time a WebContents the model is listening to // is destroyed. class Delegate { public: virtual void TabDestroyed() = 0; protected: virtual ~Delegate() {} }; explicit HungPagesTableModel(Delegate* delegate); virtual ~HungPagesTableModel(); void InitForWebContents(content::WebContents* hung_contents); // Returns the first RenderProcessHost, or NULL if there aren't any // WebContents. content::RenderProcessHost* GetRenderProcessHost(); // Returns the first RenderViewHost, or NULL if there aren't any WebContents. content::RenderViewHost* GetRenderViewHost(); // Overridden from ui::TableModel: virtual int RowCount() OVERRIDE; virtual base::string16 GetText(int row, int column_id) OVERRIDE; virtual gfx::ImageSkia GetIcon(int row) OVERRIDE; virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE; // Overridden from views::TableGrouper: virtual void GetGroupRange(int model_index, views::GroupRange* range) OVERRIDE; private: // Used to track a single WebContents. If the WebContents is destroyed // TabDestroyed() is invoked on the model. class WebContentsObserverImpl : public content::WebContentsObserver { public: WebContentsObserverImpl(HungPagesTableModel* model, content::WebContents* tab); content::WebContents* web_contents() const { return content::WebContentsObserver::web_contents(); } FaviconTabHelper* favicon_tab_helper() { return FaviconTabHelper::FromWebContents(web_contents()); } // WebContentsObserver overrides: virtual void RenderProcessGone(base::TerminationStatus status) OVERRIDE; virtual void WebContentsDestroyed() OVERRIDE; private: HungPagesTableModel* model_; DISALLOW_COPY_AND_ASSIGN(WebContentsObserverImpl); }; // Invoked when a WebContents is destroyed. Cleans up |tab_observers_| and // notifies the observer and delegate. void TabDestroyed(WebContentsObserverImpl* tab); typedef ScopedVector TabObservers; TabObservers tab_observers_; ui::TableModelObserver* observer_; Delegate* delegate_; DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel); }; // This class displays a dialog which contains information about a hung // renderer process. class HungRendererDialogView : public views::DialogDelegateView, public views::ButtonListener, public HungPagesTableModel::Delegate { public: // Factory function for creating an instance of the HungRendererDialogView // class. At any given point only one instance can be active. static HungRendererDialogView* Create(gfx::NativeView context); // Returns a pointer to the singleton instance if any. static HungRendererDialogView* GetInstance(); // Platform specific function to kill the renderer process identified by the // handle passed in. static void KillRendererProcess(base::ProcessHandle process_handle); // Returns true if the frame is in the foreground. static bool IsFrameActive(content::WebContents* contents); virtual void ShowForWebContents(content::WebContents* contents); virtual void EndForWebContents(content::WebContents* contents); // views::DialogDelegateView overrides: virtual base::string16 GetWindowTitle() const OVERRIDE; virtual void WindowClosing() OVERRIDE; virtual int GetDialogButtons() const OVERRIDE; virtual base::string16 GetDialogButtonLabel( ui::DialogButton button) const OVERRIDE; virtual views::View* CreateExtraView() OVERRIDE; virtual bool Accept(bool window_closing) OVERRIDE; virtual bool UseNewStyleForThisDialog() const OVERRIDE; // views::ButtonListener overrides: virtual void ButtonPressed(views::Button* sender, const ui::Event& event) OVERRIDE; // HungPagesTableModel::Delegate overrides: virtual void TabDestroyed() OVERRIDE; protected: HungRendererDialogView(); virtual ~HungRendererDialogView(); // views::View overrides: virtual void ViewHierarchyChanged( const ViewHierarchyChangedDetails& details) OVERRIDE; static HungRendererDialogView* g_instance_; private: // Initialize the controls in this dialog. void Init(); static void InitClass(); // Controls within the dialog box. views::TableView* hung_pages_table_; // The extra button inserted into the ClientView to kill the errant process. views::LabelButton* kill_button_; // The model that provides the contents of the table that shows a list of // pages affected by the hang. scoped_ptr hung_pages_table_model_; // Whether or not we've created controls for ourself. bool initialized_; // An amusing icon image. static gfx::ImageSkia* frozen_icon_; DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView); }; #endif // CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_