Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Side by Side Diff: chrome/browser/ui/views/hung_renderer_view.cc

Issue 10815060: Relanding this as the initial attempt was reverted because of linux chrome os compile failures. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/browser_dialogs.h" 5 #include "chrome/browser/ui/views/hung_renderer_view.h"
6 6
7 #if defined(OS_WIN) && !defined(USE_AURA) 7 #if defined(OS_WIN) && !defined(USE_AURA)
8 #include <windows.h> 8 #include <windows.h>
9 #endif 9 #endif
10 10
11 #include "base/i18n/rtl.h" 11 #include "base/i18n/rtl.h"
12 #include "base/memory/scoped_vector.h" 12 #include "base/memory/scoped_vector.h"
13 #include "base/process_util.h" 13 #include "base/process_util.h"
14 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h" 15 #include "chrome/browser/favicon/favicon_tab_helper.h"
16 #include "chrome/browser/platform_util.h" 16 #include "chrome/browser/platform_util.h"
17 #include "chrome/browser/ui/browser_dialogs.h"
17 #include "chrome/browser/ui/tab_contents/core_tab_helper.h" 18 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
18 #include "chrome/browser/ui/tab_contents/tab_contents.h"
19 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 19 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
20 #include "chrome/common/chrome_constants.h" 20 #include "chrome/common/chrome_constants.h"
21 #include "chrome/common/logging_chrome.h" 21 #include "chrome/common/logging_chrome.h"
22 #include "content/public/browser/render_process_host.h" 22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h" 23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/result_codes.h" 24 #include "content/public/common/result_codes.h"
26 #include "grit/chromium_strings.h" 25 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h" 26 #include "grit/generated_resources.h"
28 #include "grit/theme_resources.h" 27 #include "grit/theme_resources.h"
29 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h" 29 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/canvas.h" 30 #include "ui/gfx/canvas.h"
32 #include "ui/views/controls/button/text_button.h"
33 #include "ui/views/controls/image_view.h" 31 #include "ui/views/controls/image_view.h"
34 #include "ui/views/controls/label.h" 32 #include "ui/views/controls/label.h"
35 #include "ui/views/controls/table/group_table_model.h"
36 #include "ui/views/controls/table/group_table_view.h"
37 #include "ui/views/layout/grid_layout.h" 33 #include "ui/views/layout/grid_layout.h"
38 #include "ui/views/layout/layout_constants.h" 34 #include "ui/views/layout/layout_constants.h"
39 #include "ui/views/widget/widget.h" 35 #include "ui/views/widget/widget.h"
40 #include "ui/views/window/client_view.h" 36 #include "ui/views/window/client_view.h"
41 #include "ui/views/window/dialog_delegate.h"
42 37
43 #if defined(USE_AURA) 38 #if defined(USE_AURA)
44 #include "ui/aura/window.h" 39 #include "ui/aura/window.h"
45 #endif 40 #endif
46 41
47 #if defined(OS_WIN) 42 #if defined(OS_WIN)
48 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h" 43 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
49 #endif 44 #endif
50 45
51 class HungRendererDialogView; 46 HungRendererDialogView* HungRendererDialogView::g_instance_ = NULL;
52
53 using content::RenderViewHost;
54 using content::WebContents;
55
56 namespace {
57 // We only support showing one of these at a time per app.
58 HungRendererDialogView* g_instance = NULL;
59 }
60
61 ///////////////////////////////////////////////////////////////////////////////
62 // HungPagesTableModel
63
64 class HungPagesTableModel : public views::GroupTableModel {
65 public:
66 // The Delegate is notified any time a WebContents the model is listening to
67 // is destroyed.
68 class Delegate {
69 public:
70 virtual void TabDestroyed() = 0;
71
72 protected:
73 virtual ~Delegate() {}
74 };
75
76 explicit HungPagesTableModel(Delegate* delegate);
77 virtual ~HungPagesTableModel();
78
79 void InitForWebContents(WebContents* hung_contents);
80
81 // Returns the first RenderProcessHost, or NULL if there aren't any
82 // WebContents.
83 content::RenderProcessHost* GetRenderProcessHost();
84
85 // Returns the first RenderViewHost, or NULL if there aren't any WebContents.
86 RenderViewHost* GetRenderViewHost();
87
88 // Overridden from views::GroupTableModel:
89 virtual int RowCount();
90 virtual string16 GetText(int row, int column_id);
91 virtual gfx::ImageSkia GetIcon(int row);
92 virtual void SetObserver(ui::TableModelObserver* observer);
93 virtual void GetGroupRangeForItem(int item, views::GroupRange* range);
94
95 private:
96 // Used to track a single WebContents. If the WebContents is destroyed
97 // TabDestroyed() is invoked on the model.
98 class WebContentsObserverImpl : public content::WebContentsObserver {
99 public:
100 WebContentsObserverImpl(HungPagesTableModel* model,
101 TabContents* tab);
102
103 WebContents* web_contents() const {
104 return content::WebContentsObserver::web_contents();
105 }
106
107 FaviconTabHelper* favicon_tab_helper() {
108 return tab_->favicon_tab_helper();
109 }
110
111 // WebContentsObserver overrides:
112 virtual void RenderViewGone(base::TerminationStatus status) OVERRIDE;
113 virtual void WebContentsDestroyed(WebContents* tab) OVERRIDE;
114
115 private:
116 HungPagesTableModel* model_;
117 TabContents* tab_;
118
119 DISALLOW_COPY_AND_ASSIGN(WebContentsObserverImpl);
120 };
121
122 // Invoked when a WebContents is destroyed. Cleans up |tab_observers_| and
123 // notifies the observer and delegate.
124 void TabDestroyed(WebContentsObserverImpl* tab);
125
126 typedef ScopedVector<WebContentsObserverImpl> TabObservers;
127 TabObservers tab_observers_;
128
129 ui::TableModelObserver* observer_;
130 Delegate* delegate_;
131
132 DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
133 };
134 47
135 /////////////////////////////////////////////////////////////////////////////// 48 ///////////////////////////////////////////////////////////////////////////////
136 // HungPagesTableModel, public: 49 // HungPagesTableModel, public:
137 50
138 HungPagesTableModel::HungPagesTableModel(Delegate* delegate) 51 HungPagesTableModel::HungPagesTableModel(Delegate* delegate)
139 : observer_(NULL), 52 : observer_(NULL),
140 delegate_(delegate) { 53 delegate_(delegate) {
141 } 54 }
142 55
143 HungPagesTableModel::~HungPagesTableModel() { 56 HungPagesTableModel::~HungPagesTableModel() {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 } 152 }
240 153
241 void HungPagesTableModel::WebContentsObserverImpl::WebContentsDestroyed( 154 void HungPagesTableModel::WebContentsObserverImpl::WebContentsDestroyed(
242 WebContents* tab) { 155 WebContents* tab) {
243 model_->TabDestroyed(this); 156 model_->TabDestroyed(this);
244 } 157 }
245 158
246 /////////////////////////////////////////////////////////////////////////////// 159 ///////////////////////////////////////////////////////////////////////////////
247 // HungRendererDialogView 160 // HungRendererDialogView
248 161
249 class HungRendererDialogView : public views::DialogDelegateView,
250 public views::ButtonListener,
251 public HungPagesTableModel::Delegate {
252 public:
253 HungRendererDialogView();
254 ~HungRendererDialogView();
255
256 void ShowForWebContents(WebContents* contents);
257 void EndForWebContents(WebContents* contents);
258
259 // views::DialogDelegateView overrides:
260 virtual string16 GetWindowTitle() const OVERRIDE;
261 virtual void WindowClosing() OVERRIDE;
262 virtual int GetDialogButtons() const OVERRIDE;
263 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
264 virtual views::View* GetExtraView() OVERRIDE;
265 virtual bool Accept(bool window_closing) OVERRIDE;
266 virtual views::View* GetContentsView() OVERRIDE;
267
268 // views::ButtonListener overrides:
269 virtual void ButtonPressed(views::Button* sender,
270 const views::Event& event) OVERRIDE;
271
272 // HungPagesTableModel::Delegate overrides:
273 virtual void TabDestroyed() OVERRIDE;
274
275 protected:
276 // views::View overrides:
277 virtual void ViewHierarchyChanged(bool is_add,
278 views::View* parent,
279 views::View* child) OVERRIDE;
280
281 private:
282 // Initialize the controls in this dialog.
283 void Init();
284 void CreateKillButtonView();
285
286 // Returns the bounds the dialog should be displayed at to be meaningfully
287 // associated with the specified WebContents.
288 gfx::Rect GetDisplayBounds(WebContents* contents);
289
290 static void InitClass();
291
292 // Controls within the dialog box.
293 views::GroupTableView* hung_pages_table_;
294
295 // The button we insert into the ClientView to kill the errant process. This
296 // is parented to a container view that uses a grid layout to align it
297 // properly.
298 views::TextButton* kill_button_;
299 views::View* kill_button_container_;
300
301 // The model that provides the contents of the table that shows a list of
302 // pages affected by the hang.
303 scoped_ptr<HungPagesTableModel> hung_pages_table_model_;
304
305 // Whether or not we've created controls for ourself.
306 bool initialized_;
307
308 // An amusing icon image.
309 static gfx::ImageSkia* frozen_icon_;
310
311 DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView);
312 };
313
314 // static 162 // static
315 gfx::ImageSkia* HungRendererDialogView::frozen_icon_ = NULL; 163 gfx::ImageSkia* HungRendererDialogView::frozen_icon_ = NULL;
316 164
317 // The distance in pixels from the top of the relevant contents to place the 165 // The distance in pixels from the top of the relevant contents to place the
318 // warning window. 166 // warning window.
319 static const int kOverlayContentsOffsetY = 50; 167 static const int kOverlayContentsOffsetY = 50;
320 168
321 // The dimensions of the hung pages list table view, in pixels. 169 // The dimensions of the hung pages list table view, in pixels.
322 static const int kTableViewWidth = 300; 170 static const int kTableViewWidth = 300;
323 static const int kTableViewHeight = 100; 171 static const int kTableViewHeight = 100;
324 172
325 /////////////////////////////////////////////////////////////////////////////// 173 ///////////////////////////////////////////////////////////////////////////////
326 // HungRendererDialogView, public: 174 // HungRendererDialogView, public:
327 175
176 #if !defined(OS_WIN)
177
178 // static
179 HungRendererDialogView* HungRendererDialogView::Create() {
180 if (!g_instance_) {
181 g_instance_ = new HungRendererDialogView;
182 views::Widget::CreateWindow(g_instance_);
183 }
184 return g_instance_;
185 }
186 #endif // defined(OS_WIN)
187
188 // static
189 HungRendererDialogView* HungRendererDialogView::GetInstance() {
190 return g_instance_;
191 }
192
328 HungRendererDialogView::HungRendererDialogView() 193 HungRendererDialogView::HungRendererDialogView()
329 : hung_pages_table_(NULL), 194 : hung_pages_table_(NULL),
330 kill_button_(NULL), 195 kill_button_(NULL),
331 kill_button_container_(NULL), 196 kill_button_container_(NULL),
332 initialized_(false) { 197 initialized_(false) {
333 InitClass(); 198 InitClass();
334 } 199 }
335 200
336 HungRendererDialogView::~HungRendererDialogView() { 201 HungRendererDialogView::~HungRendererDialogView() {
337 hung_pages_table_->SetModel(NULL); 202 hung_pages_table_->SetModel(NULL);
338 } 203 }
339 204
340 void HungRendererDialogView::ShowForWebContents(WebContents* contents) { 205 void HungRendererDialogView::ShowForWebContents(WebContents* contents) {
341 DCHECK(contents && GetWidget()); 206 DCHECK(contents && GetWidget());
342 207
343 // Don't show the warning unless the foreground window is the frame, or this 208 // Don't show the warning unless the foreground window is the frame, or this
344 // window (but still invisible). If the user has another window or 209 // window (but still invisible). If the user has another window or
345 // application selected, activating ourselves is rude. 210 // application selected, activating ourselves is rude.
346 gfx::NativeView frame_view = 211 if (!IsFrameActive(contents))
347 platform_util::GetTopLevel(contents->GetNativeView());
348 if (!platform_util::IsWindowActive(frame_view) &&
349 !platform_util::IsWindowActive(GetWidget()->GetNativeWindow())) {
350 return; 212 return;
351 }
352 213
353 if (!GetWidget()->IsActive()) { 214 if (!GetWidget()->IsActive()) {
354 gfx::Rect bounds = GetDisplayBounds(contents); 215 gfx::Rect bounds = GetDisplayBounds(contents);
216
217 gfx::NativeView frame_view =
218 platform_util::GetTopLevel(contents->GetNativeView());
219
355 views::Widget* insert_after = 220 views::Widget* insert_after =
356 views::Widget::GetWidgetForNativeView(frame_view); 221 views::Widget::GetWidgetForNativeView(frame_view);
357 GetWidget()->SetBoundsConstrained(bounds); 222 GetWidget()->SetBoundsConstrained(bounds);
358 if (insert_after) 223 if (insert_after)
359 GetWidget()->StackAboveWidget(insert_after); 224 GetWidget()->StackAboveWidget(insert_after);
360 225
361 // We only do this if the window isn't active (i.e. hasn't been shown yet, 226 // We only do this if the window isn't active (i.e. hasn't been shown yet,
362 // or is currently shown but deactivated for another WebContents). This is 227 // or is currently shown but deactivated for another WebContents). This is
363 // because this window is a singleton, and it's possible another active 228 // because this window is a singleton, and it's possible another active
364 // renderer may hang while this one is showing, and we don't want to reset 229 // renderer may hang while this one is showing, and we don't want to reset
(...skipping 18 matching lines...) Expand all
383 248
384 /////////////////////////////////////////////////////////////////////////////// 249 ///////////////////////////////////////////////////////////////////////////////
385 // HungRendererDialogView, views::DialogDelegate implementation: 250 // HungRendererDialogView, views::DialogDelegate implementation:
386 251
387 string16 HungRendererDialogView::GetWindowTitle() const { 252 string16 HungRendererDialogView::GetWindowTitle() const {
388 return l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE); 253 return l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE);
389 } 254 }
390 255
391 void HungRendererDialogView::WindowClosing() { 256 void HungRendererDialogView::WindowClosing() {
392 // We are going to be deleted soon, so make sure our instance is destroyed. 257 // We are going to be deleted soon, so make sure our instance is destroyed.
393 g_instance = NULL; 258 g_instance_ = NULL;
394 } 259 }
395 260
396 int HungRendererDialogView::GetDialogButtons() const { 261 int HungRendererDialogView::GetDialogButtons() const {
397 // We specifically don't want a CANCEL button here because that code path is 262 // We specifically don't want a CANCEL button here because that code path is
398 // also called when the window is closed by the user clicking the X button in 263 // also called when the window is closed by the user clicking the X button in
399 // the window's titlebar, and also if we call Window::Close. Rather, we want 264 // the window's titlebar, and also if we call Window::Close. Rather, we want
400 // the OK button to wait for responsiveness (and close the dialog) and our 265 // the OK button to wait for responsiveness (and close the dialog) and our
401 // additional button (which we create) to kill the process (which will result 266 // additional button (which we create) to kill the process (which will result
402 // in the dialog being destroyed). 267 // in the dialog being destroyed).
403 return ui::DIALOG_BUTTON_OK; 268 return ui::DIALOG_BUTTON_OK;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 /////////////////////////////////////////////////////////////////////////////// 326 ///////////////////////////////////////////////////////////////////////////////
462 // HungRendererDialogView, views::View overrides: 327 // HungRendererDialogView, views::View overrides:
463 328
464 void HungRendererDialogView::ViewHierarchyChanged(bool is_add, 329 void HungRendererDialogView::ViewHierarchyChanged(bool is_add,
465 views::View* parent, 330 views::View* parent,
466 views::View* child) { 331 views::View* child) {
467 if (!initialized_ && is_add && child == this && GetWidget()) 332 if (!initialized_ && is_add && child == this && GetWidget())
468 Init(); 333 Init();
469 } 334 }
470 335
336 bool HungRendererDialogView::IsFrameActive(WebContents* contents) {
337 gfx::NativeView frame_view =
338 platform_util::GetTopLevel(contents->GetNativeView());
339 if (!platform_util::IsWindowActive(frame_view) &&
340 !platform_util::IsWindowActive(GetWidget()->GetNativeWindow())) {
341 return false;
342 }
343 return true;
344 }
345
471 /////////////////////////////////////////////////////////////////////////////// 346 ///////////////////////////////////////////////////////////////////////////////
472 // HungRendererDialogView, private: 347 // HungRendererDialogView, private:
473 348
474 void HungRendererDialogView::Init() { 349 void HungRendererDialogView::Init() {
475 views::ImageView* frozen_icon_view = new views::ImageView; 350 views::ImageView* frozen_icon_view = new views::ImageView;
476 frozen_icon_view->SetImage(frozen_icon_); 351 frozen_icon_view->SetImage(frozen_icon_);
477 352
478 views::Label* info_label = new views::Label( 353 views::Label* info_label = new views::Label(
479 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER)); 354 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER));
480 info_label->SetMultiLine(true); 355 info_label->SetMultiLine(true);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 // static 442 // static
568 void HungRendererDialogView::InitClass() { 443 void HungRendererDialogView::InitClass() {
569 static bool initialized = false; 444 static bool initialized = false;
570 if (!initialized) { 445 if (!initialized) {
571 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 446 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
572 frozen_icon_ = rb.GetImageSkiaNamed(IDR_FROZEN_TAB_ICON); 447 frozen_icon_ = rb.GetImageSkiaNamed(IDR_FROZEN_TAB_ICON);
573 initialized = true; 448 initialized = true;
574 } 449 }
575 } 450 }
576 451
577 static HungRendererDialogView* CreateHungRendererDialogView() {
578 HungRendererDialogView* cv = new HungRendererDialogView;
579 views::Widget::CreateWindow(cv);
580 return cv;
581 }
582
583 namespace chrome { 452 namespace chrome {
584 453
585 void ShowHungRendererDialog(WebContents* contents) { 454 void ShowHungRendererDialog(WebContents* contents) {
586 if (!logging::DialogsAreSuppressed()) { 455 if (!logging::DialogsAreSuppressed()) {
587 if (!g_instance) 456 HungRendererDialogView* view = HungRendererDialogView::Create();
588 g_instance = CreateHungRendererDialogView(); 457 view->ShowForWebContents(contents);
589 g_instance->ShowForWebContents(contents);
590 } 458 }
591 } 459 }
592 460
593 void HideHungRendererDialog(WebContents* contents) { 461 void HideHungRendererDialog(WebContents* contents) {
594 if (!logging::DialogsAreSuppressed() && g_instance) 462 if (!logging::DialogsAreSuppressed() &&
595 g_instance->EndForWebContents(contents); 463 HungRendererDialogView::GetInstance())
464 HungRendererDialogView::GetInstance()->EndForWebContents(contents);
596 } 465 }
597 466
598 } // namespace chrome 467 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/hung_renderer_view.h ('k') | chrome/browser/ui/views/hung_renderer_view_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698