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

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

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
« no previous file with comments | « no previous file | chrome/browser/ui/views/hung_renderer_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #ifndef CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
6 #define CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
6 7
7 #if defined(OS_WIN) && !defined(USE_AURA)
8 #include <windows.h>
9 #endif
10
11 #include "base/i18n/rtl.h"
12 #include "base/memory/scoped_vector.h" 8 #include "base/memory/scoped_vector.h"
13 #include "base/process_util.h"
14 #include "base/utf_string_conversions.h"
15 #include "chrome/browser/favicon/favicon_tab_helper.h"
16 #include "chrome/browser/platform_util.h"
17 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
18 #include "chrome/browser/ui/tab_contents/tab_contents.h" 9 #include "chrome/browser/ui/tab_contents/tab_contents.h"
19 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
20 #include "chrome/common/chrome_constants.h"
21 #include "chrome/common/logging_chrome.h"
22 #include "content/public/browser/render_process_host.h"
23 #include "content/public/browser/render_view_host.h"
24 #include "content/public/browser/web_contents.h" 10 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/result_codes.h" 11 #include "content/public/browser/web_contents_observer.h"
26 #include "grit/chromium_strings.h"
27 #include "grit/generated_resources.h"
28 #include "grit/theme_resources.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/canvas.h"
32 #include "ui/views/controls/button/text_button.h" 12 #include "ui/views/controls/button/text_button.h"
33 #include "ui/views/controls/image_view.h"
34 #include "ui/views/controls/label.h"
35 #include "ui/views/controls/table/group_table_model.h" 13 #include "ui/views/controls/table/group_table_model.h"
36 #include "ui/views/controls/table/group_table_view.h" 14 #include "ui/views/controls/table/group_table_view.h"
37 #include "ui/views/layout/grid_layout.h"
38 #include "ui/views/layout/layout_constants.h"
39 #include "ui/views/widget/widget.h"
40 #include "ui/views/window/client_view.h"
41 #include "ui/views/window/dialog_delegate.h" 15 #include "ui/views/window/dialog_delegate.h"
42 16
43 #if defined(USE_AURA)
44 #include "ui/aura/window.h"
45 #endif
46
47 #if defined(OS_WIN)
48 #include "chrome/browser/hang_monitor/hang_crash_dump_win.h"
49 #endif
50
51 class HungRendererDialogView;
52
53 using content::RenderViewHost; 17 using content::RenderViewHost;
54 using content::WebContents; 18 using content::WebContents;
55 19
56 namespace { 20 // Provides functionality to display information about a hung renderer.
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 { 21 class HungPagesTableModel : public views::GroupTableModel {
65 public: 22 public:
66 // The Delegate is notified any time a WebContents the model is listening to 23 // The Delegate is notified any time a WebContents the model is listening to
67 // is destroyed. 24 // is destroyed.
68 class Delegate { 25 class Delegate {
69 public: 26 public:
70 virtual void TabDestroyed() = 0; 27 virtual void TabDestroyed() = 0;
71 28
72 protected: 29 protected:
73 virtual ~Delegate() {} 30 virtual ~Delegate() {}
74 }; 31 };
75 32
76 explicit HungPagesTableModel(Delegate* delegate); 33 explicit HungPagesTableModel(Delegate* delegate);
77 virtual ~HungPagesTableModel(); 34 virtual ~HungPagesTableModel();
78 35
79 void InitForWebContents(WebContents* hung_contents); 36 void InitForWebContents(WebContents* hung_contents);
80 37
81 // Returns the first RenderProcessHost, or NULL if there aren't any 38 // Returns the first RenderProcessHost, or NULL if there aren't any
82 // WebContents. 39 // WebContents.
83 content::RenderProcessHost* GetRenderProcessHost(); 40 content::RenderProcessHost* GetRenderProcessHost();
84 41
85 // Returns the first RenderViewHost, or NULL if there aren't any WebContents. 42 // Returns the first RenderViewHost, or NULL if there aren't any WebContents.
86 RenderViewHost* GetRenderViewHost(); 43 RenderViewHost* GetRenderViewHost();
87 44
88 // Overridden from views::GroupTableModel: 45 // Overridden from views::GroupTableModel:
89 virtual int RowCount(); 46 virtual int RowCount() OVERRIDE;
90 virtual string16 GetText(int row, int column_id); 47 virtual string16 GetText(int row, int column_id) OVERRIDE;
91 virtual gfx::ImageSkia GetIcon(int row); 48 virtual gfx::ImageSkia GetIcon(int row) OVERRIDE;
92 virtual void SetObserver(ui::TableModelObserver* observer); 49 virtual void SetObserver(ui::TableModelObserver* observer) OVERRIDE;
93 virtual void GetGroupRangeForItem(int item, views::GroupRange* range); 50 virtual void GetGroupRangeForItem(int item, views::GroupRange* range)
51 OVERRIDE;
94 52
95 private: 53 private:
96 // Used to track a single WebContents. If the WebContents is destroyed 54 // Used to track a single WebContents. If the WebContents is destroyed
97 // TabDestroyed() is invoked on the model. 55 // TabDestroyed() is invoked on the model.
98 class WebContentsObserverImpl : public content::WebContentsObserver { 56 class WebContentsObserverImpl : public content::WebContentsObserver {
99 public: 57 public:
100 WebContentsObserverImpl(HungPagesTableModel* model, 58 WebContentsObserverImpl(HungPagesTableModel* model,
101 TabContents* tab); 59 TabContents* tab);
102 60
103 WebContents* web_contents() const { 61 WebContents* web_contents() const {
(...skipping 21 matching lines...) Expand all
125 83
126 typedef ScopedVector<WebContentsObserverImpl> TabObservers; 84 typedef ScopedVector<WebContentsObserverImpl> TabObservers;
127 TabObservers tab_observers_; 85 TabObservers tab_observers_;
128 86
129 ui::TableModelObserver* observer_; 87 ui::TableModelObserver* observer_;
130 Delegate* delegate_; 88 Delegate* delegate_;
131 89
132 DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel); 90 DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
133 }; 91 };
134 92
135 /////////////////////////////////////////////////////////////////////////////// 93 // This class displays a dialog which contains information about a hung
136 // HungPagesTableModel, public: 94 // renderer process.
137
138 HungPagesTableModel::HungPagesTableModel(Delegate* delegate)
139 : observer_(NULL),
140 delegate_(delegate) {
141 }
142
143 HungPagesTableModel::~HungPagesTableModel() {
144 }
145
146 content::RenderProcessHost* HungPagesTableModel::GetRenderProcessHost() {
147 return tab_observers_.empty() ? NULL :
148 tab_observers_[0]->web_contents()->GetRenderProcessHost();
149 }
150
151 RenderViewHost* HungPagesTableModel::GetRenderViewHost() {
152 return tab_observers_.empty() ? NULL :
153 tab_observers_[0]->web_contents()->GetRenderViewHost();
154 }
155
156 void HungPagesTableModel::InitForWebContents(WebContents* hung_contents) {
157 tab_observers_.clear();
158 if (hung_contents) {
159 // Force hung_contents to be first.
160 TabContents* hung_tab_contents =
161 TabContents::FromWebContents(hung_contents);
162 if (hung_tab_contents) {
163 tab_observers_.push_back(new WebContentsObserverImpl(this,
164 hung_tab_contents));
165 }
166 for (TabContentsIterator it; !it.done(); ++it) {
167 if (*it != hung_tab_contents &&
168 it->web_contents()->GetRenderProcessHost() ==
169 hung_contents->GetRenderProcessHost())
170 tab_observers_.push_back(new WebContentsObserverImpl(this, *it));
171 }
172 }
173 // The world is different.
174 if (observer_)
175 observer_->OnModelChanged();
176 }
177
178 ///////////////////////////////////////////////////////////////////////////////
179 // HungPagesTableModel, views::GroupTableModel implementation:
180
181 int HungPagesTableModel::RowCount() {
182 return static_cast<int>(tab_observers_.size());
183 }
184
185 string16 HungPagesTableModel::GetText(int row, int column_id) {
186 DCHECK(row >= 0 && row < RowCount());
187 string16 title = tab_observers_[row]->web_contents()->GetTitle();
188 if (title.empty())
189 title = CoreTabHelper::GetDefaultTitle();
190 // TODO(xji): Consider adding a special case if the title text is a URL,
191 // since those should always have LTR directionality. Please refer to
192 // http://crbug.com/6726 for more information.
193 base::i18n::AdjustStringForLocaleDirection(&title);
194 return title;
195 }
196
197 gfx::ImageSkia HungPagesTableModel::GetIcon(int row) {
198 DCHECK(row >= 0 && row < RowCount());
199 return tab_observers_[row]->favicon_tab_helper()->GetFavicon();
200 }
201
202 void HungPagesTableModel::SetObserver(ui::TableModelObserver* observer) {
203 observer_ = observer;
204 }
205
206 void HungPagesTableModel::GetGroupRangeForItem(int item,
207 views::GroupRange* range) {
208 DCHECK(range);
209 range->start = 0;
210 range->length = RowCount();
211 }
212
213 void HungPagesTableModel::TabDestroyed(WebContentsObserverImpl* tab) {
214 // Clean up tab_observers_ and notify our observer.
215 TabObservers::iterator i = std::find(
216 tab_observers_.begin(), tab_observers_.end(), tab);
217 DCHECK(i != tab_observers_.end());
218 int index = static_cast<int>(i - tab_observers_.begin());
219 tab_observers_.erase(i);
220 if (observer_)
221 observer_->OnItemsRemoved(index, 1);
222
223 // Notify the delegate.
224 delegate_->TabDestroyed();
225 // WARNING: we've likely been deleted.
226 }
227
228 HungPagesTableModel::WebContentsObserverImpl::WebContentsObserverImpl(
229 HungPagesTableModel* model,
230 TabContents* tab)
231 : content::WebContentsObserver(tab->web_contents()),
232 model_(model),
233 tab_(tab) {
234 }
235
236 void HungPagesTableModel::WebContentsObserverImpl::RenderViewGone(
237 base::TerminationStatus status) {
238 model_->TabDestroyed(this);
239 }
240
241 void HungPagesTableModel::WebContentsObserverImpl::WebContentsDestroyed(
242 WebContents* tab) {
243 model_->TabDestroyed(this);
244 }
245
246 ///////////////////////////////////////////////////////////////////////////////
247 // HungRendererDialogView
248
249 class HungRendererDialogView : public views::DialogDelegateView, 95 class HungRendererDialogView : public views::DialogDelegateView,
250 public views::ButtonListener, 96 public views::ButtonListener,
251 public HungPagesTableModel::Delegate { 97 public HungPagesTableModel::Delegate {
252 public: 98 public:
253 HungRendererDialogView(); 99 // Factory function for creating an instance of the HungRendererDialogView
254 ~HungRendererDialogView(); 100 // class. At any given point only one instance can be active.
101 static HungRendererDialogView* Create();
102 // Returns a pointer to the singleton instance if any.
103 static HungRendererDialogView* GetInstance();
255 104
256 void ShowForWebContents(WebContents* contents); 105 virtual void ShowForWebContents(WebContents* contents);
257 void EndForWebContents(WebContents* contents); 106 virtual void EndForWebContents(WebContents* contents);
258 107
259 // views::DialogDelegateView overrides: 108 // views::DialogDelegateView overrides:
260 virtual string16 GetWindowTitle() const OVERRIDE; 109 virtual string16 GetWindowTitle() const OVERRIDE;
261 virtual void WindowClosing() OVERRIDE; 110 virtual void WindowClosing() OVERRIDE;
262 virtual int GetDialogButtons() const OVERRIDE; 111 virtual int GetDialogButtons() const OVERRIDE;
263 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE; 112 virtual string16 GetDialogButtonLabel(ui::DialogButton button) const OVERRIDE;
264 virtual views::View* GetExtraView() OVERRIDE; 113 virtual views::View* GetExtraView() OVERRIDE;
265 virtual bool Accept(bool window_closing) OVERRIDE; 114 virtual bool Accept(bool window_closing) OVERRIDE;
266 virtual views::View* GetContentsView() OVERRIDE; 115 virtual views::View* GetContentsView() OVERRIDE;
267 116
268 // views::ButtonListener overrides: 117 // views::ButtonListener overrides:
269 virtual void ButtonPressed(views::Button* sender, 118 virtual void ButtonPressed(views::Button* sender,
270 const views::Event& event) OVERRIDE; 119 const views::Event& event) OVERRIDE;
271 120
272 // HungPagesTableModel::Delegate overrides: 121 // HungPagesTableModel::Delegate overrides:
273 virtual void TabDestroyed() OVERRIDE; 122 virtual void TabDestroyed() OVERRIDE;
274 123
275 protected: 124 protected:
125 HungRendererDialogView();
126 virtual ~HungRendererDialogView();
127
276 // views::View overrides: 128 // views::View overrides:
277 virtual void ViewHierarchyChanged(bool is_add, 129 virtual void ViewHierarchyChanged(bool is_add,
278 views::View* parent, 130 views::View* parent,
279 views::View* child) OVERRIDE; 131 views::View* child) OVERRIDE;
280 132
133 // Returns true if the frame is in the foreground.
134 bool IsFrameActive(WebContents* contents);
135
136 static HungRendererDialogView* g_instance_;
137
281 private: 138 private:
282 // Initialize the controls in this dialog. 139 // Initialize the controls in this dialog.
283 void Init(); 140 void Init();
284 void CreateKillButtonView(); 141 void CreateKillButtonView();
285 142
286 // Returns the bounds the dialog should be displayed at to be meaningfully 143 // Returns the bounds the dialog should be displayed at to be meaningfully
287 // associated with the specified WebContents. 144 // associated with the specified WebContents.
288 gfx::Rect GetDisplayBounds(WebContents* contents); 145 gfx::Rect GetDisplayBounds(WebContents* contents);
289 146
290 static void InitClass(); 147 static void InitClass();
(...skipping 13 matching lines...) Expand all
304 161
305 // Whether or not we've created controls for ourself. 162 // Whether or not we've created controls for ourself.
306 bool initialized_; 163 bool initialized_;
307 164
308 // An amusing icon image. 165 // An amusing icon image.
309 static gfx::ImageSkia* frozen_icon_; 166 static gfx::ImageSkia* frozen_icon_;
310 167
311 DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView); 168 DISALLOW_COPY_AND_ASSIGN(HungRendererDialogView);
312 }; 169 };
313 170
314 // static 171 #endif // CHROME_BROWSER_UI_VIEWS_HUNG_RENDERER_VIEW_H_
315 gfx::ImageSkia* HungRendererDialogView::frozen_icon_ = NULL;
316
317 // The distance in pixels from the top of the relevant contents to place the
318 // warning window.
319 static const int kOverlayContentsOffsetY = 50;
320
321 // The dimensions of the hung pages list table view, in pixels.
322 static const int kTableViewWidth = 300;
323 static const int kTableViewHeight = 100;
324
325 ///////////////////////////////////////////////////////////////////////////////
326 // HungRendererDialogView, public:
327
328 HungRendererDialogView::HungRendererDialogView()
329 : hung_pages_table_(NULL),
330 kill_button_(NULL),
331 kill_button_container_(NULL),
332 initialized_(false) {
333 InitClass();
334 }
335
336 HungRendererDialogView::~HungRendererDialogView() {
337 hung_pages_table_->SetModel(NULL);
338 }
339
340 void HungRendererDialogView::ShowForWebContents(WebContents* contents) {
341 DCHECK(contents && GetWidget());
342
343 // 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
345 // application selected, activating ourselves is rude.
346 gfx::NativeView frame_view =
347 platform_util::GetTopLevel(contents->GetNativeView());
348 if (!platform_util::IsWindowActive(frame_view) &&
349 !platform_util::IsWindowActive(GetWidget()->GetNativeWindow())) {
350 return;
351 }
352
353 if (!GetWidget()->IsActive()) {
354 gfx::Rect bounds = GetDisplayBounds(contents);
355 views::Widget* insert_after =
356 views::Widget::GetWidgetForNativeView(frame_view);
357 GetWidget()->SetBoundsConstrained(bounds);
358 if (insert_after)
359 GetWidget()->StackAboveWidget(insert_after);
360
361 // 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
363 // 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
365 // the list of hung pages for a potentially unrelated renderer while this
366 // one is showing.
367 hung_pages_table_model_->InitForWebContents(contents);
368 GetWidget()->Show();
369 }
370 }
371
372 void HungRendererDialogView::EndForWebContents(WebContents* contents) {
373 DCHECK(contents);
374 if (hung_pages_table_model_->RowCount() == 0 ||
375 hung_pages_table_model_->GetRenderProcessHost() ==
376 contents->GetRenderProcessHost()) {
377 GetWidget()->Close();
378 // Close is async, make sure we drop our references to the tab immediately
379 // (it may be going away).
380 hung_pages_table_model_->InitForWebContents(NULL);
381 }
382 }
383
384 ///////////////////////////////////////////////////////////////////////////////
385 // HungRendererDialogView, views::DialogDelegate implementation:
386
387 string16 HungRendererDialogView::GetWindowTitle() const {
388 return l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_TITLE);
389 }
390
391 void HungRendererDialogView::WindowClosing() {
392 // We are going to be deleted soon, so make sure our instance is destroyed.
393 g_instance = NULL;
394 }
395
396 int HungRendererDialogView::GetDialogButtons() const {
397 // 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
399 // 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
401 // additional button (which we create) to kill the process (which will result
402 // in the dialog being destroyed).
403 return ui::DIALOG_BUTTON_OK;
404 }
405
406 string16 HungRendererDialogView::GetDialogButtonLabel(
407 ui::DialogButton button) const {
408 if (button == ui::DIALOG_BUTTON_OK)
409 return l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_WAIT);
410 return string16();
411 }
412
413 views::View* HungRendererDialogView::GetExtraView() {
414 return kill_button_container_;
415 }
416
417 bool HungRendererDialogView::Accept(bool window_closing) {
418 // Don't do anything if we're being called only because the dialog is being
419 // destroyed and we don't supply a Cancel function...
420 if (window_closing)
421 return true;
422
423 // Start waiting again for responsiveness.
424 if (hung_pages_table_model_->GetRenderViewHost())
425 hung_pages_table_model_->GetRenderViewHost()->RestartHangMonitorTimeout();
426 return true;
427 }
428
429 views::View* HungRendererDialogView::GetContentsView() {
430 return this;
431 }
432
433 ///////////////////////////////////////////////////////////////////////////////
434 // HungRendererDialogView, views::ButtonListener implementation:
435
436 void HungRendererDialogView::ButtonPressed(
437 views::Button* sender, const views::Event& event) {
438 if (sender == kill_button_ &&
439 hung_pages_table_model_->GetRenderProcessHost()) {
440
441 base::ProcessHandle process_handle =
442 hung_pages_table_model_->GetRenderProcessHost()->GetHandle();
443
444 #if defined(OS_WIN)
445 // Try to generate a crash report for the hung process.
446 CrashDumpAndTerminateHungChildProcess(process_handle);
447 #else
448 // Kill the process.
449 base::KillProcess(process_handle, content::RESULT_CODE_HUNG, false);
450 #endif
451 }
452 }
453
454 ///////////////////////////////////////////////////////////////////////////////
455 // HungRendererDialogView, HungPagesTableModel::Delegate overrides:
456
457 void HungRendererDialogView::TabDestroyed() {
458 GetWidget()->Close();
459 }
460
461 ///////////////////////////////////////////////////////////////////////////////
462 // HungRendererDialogView, views::View overrides:
463
464 void HungRendererDialogView::ViewHierarchyChanged(bool is_add,
465 views::View* parent,
466 views::View* child) {
467 if (!initialized_ && is_add && child == this && GetWidget())
468 Init();
469 }
470
471 ///////////////////////////////////////////////////////////////////////////////
472 // HungRendererDialogView, private:
473
474 void HungRendererDialogView::Init() {
475 views::ImageView* frozen_icon_view = new views::ImageView;
476 frozen_icon_view->SetImage(frozen_icon_);
477
478 views::Label* info_label = new views::Label(
479 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER));
480 info_label->SetMultiLine(true);
481 info_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
482
483 hung_pages_table_model_.reset(new HungPagesTableModel(this));
484 std::vector<ui::TableColumn> columns;
485 columns.push_back(ui::TableColumn());
486 hung_pages_table_ = new views::GroupTableView(
487 hung_pages_table_model_.get(), columns, views::ICON_AND_TEXT, true,
488 false, true, false);
489
490 CreateKillButtonView();
491
492 using views::GridLayout;
493 using views::ColumnSet;
494
495 GridLayout* layout = GridLayout::CreatePanel(this);
496 SetLayoutManager(layout);
497
498 const int double_column_set_id = 0;
499 ColumnSet* column_set = layout->AddColumnSet(double_column_set_id);
500 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
501 GridLayout::FIXED, frozen_icon_->width(), 0);
502 column_set->AddPaddingColumn(
503 0, views::kUnrelatedControlLargeHorizontalSpacing);
504 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
505 GridLayout::USE_PREF, 0, 0);
506
507 layout->StartRow(0, double_column_set_id);
508 layout->AddView(frozen_icon_view, 1, 3);
509 // Add the label with a preferred width of 1, this way it doesn't effect the
510 // overall preferred size of the dialog.
511 layout->AddView(
512 info_label, 1, 1, GridLayout::FILL, GridLayout::LEADING, 1, 0);
513
514 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
515
516 layout->StartRow(0, double_column_set_id);
517 layout->SkipColumns(1);
518 layout->AddView(hung_pages_table_->CreateParentIfNecessary(), 1, 1,
519 views::GridLayout::FILL,
520 views::GridLayout::FILL, kTableViewWidth, kTableViewHeight);
521
522 initialized_ = true;
523 }
524
525 void HungRendererDialogView::CreateKillButtonView() {
526 kill_button_ = new views::NativeTextButton(this,
527 l10n_util::GetStringUTF16(IDS_BROWSER_HANGMONITOR_RENDERER_END));
528
529 kill_button_container_ = new View;
530
531 using views::GridLayout;
532 using views::ColumnSet;
533
534 GridLayout* layout = new GridLayout(kill_button_container_);
535 kill_button_container_->SetLayoutManager(layout);
536
537 const int single_column_set_id = 0;
538 ColumnSet* column_set = layout->AddColumnSet(single_column_set_id);
539 column_set->AddPaddingColumn(0, frozen_icon_->width() +
540 views::kPanelHorizMargin + views::kUnrelatedControlHorizontalSpacing);
541 column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
542 GridLayout::USE_PREF, 0, 0);
543
544 layout->StartRow(0, single_column_set_id);
545 layout->AddView(kill_button_);
546 }
547
548 gfx::Rect HungRendererDialogView::GetDisplayBounds(
549 WebContents* contents) {
550 #if defined(USE_AURA)
551 gfx::Rect contents_bounds(contents->GetNativeView()->GetBoundsInRootWindow());
552 #elif defined(OS_WIN)
553 HWND contents_hwnd = contents->GetNativeView();
554 RECT contents_bounds_rect;
555 GetWindowRect(contents_hwnd, &contents_bounds_rect);
556 gfx::Rect contents_bounds(contents_bounds_rect);
557 #endif
558 gfx::Rect window_bounds = GetWidget()->GetWindowBoundsInScreen();
559
560 int window_x = contents_bounds.x() +
561 (contents_bounds.width() - window_bounds.width()) / 2;
562 int window_y = contents_bounds.y() + kOverlayContentsOffsetY;
563 return gfx::Rect(window_x, window_y, window_bounds.width(),
564 window_bounds.height());
565 }
566
567 // static
568 void HungRendererDialogView::InitClass() {
569 static bool initialized = false;
570 if (!initialized) {
571 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
572 frozen_icon_ = rb.GetImageSkiaNamed(IDR_FROZEN_TAB_ICON);
573 initialized = true;
574 }
575 }
576
577 static HungRendererDialogView* CreateHungRendererDialogView() {
578 HungRendererDialogView* cv = new HungRendererDialogView;
579 views::Widget::CreateWindow(cv);
580 return cv;
581 }
582
583 namespace chrome {
584
585 void ShowHungRendererDialog(WebContents* contents) {
586 if (!logging::DialogsAreSuppressed()) {
587 if (!g_instance)
588 g_instance = CreateHungRendererDialogView();
589 g_instance->ShowForWebContents(contents);
590 }
591 }
592
593 void HideHungRendererDialog(WebContents* contents) {
594 if (!logging::DialogsAreSuppressed() && g_instance)
595 g_instance->EndForWebContents(contents);
596 }
597
598 } // namespace chrome
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/ui/views/hung_renderer_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698