1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// 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.
#include "chrome/browser/ui/sad_tab_helper.h"
#include "chrome/browser/browser_shutdown.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#if defined(OS_MACOSX)
#include "chrome/browser/ui/cocoa/tab_contents/sad_tab_controller.h"
#elif defined(TOOLKIT_VIEWS)
#include "chrome/browser/ui/views/sad_tab_view.h"
#include "ui/views/widget/widget.h"
#elif defined(TOOLKIT_GTK)
#include <gtk/gtk.h>
#include "chrome/browser/tab_contents/chrome_web_contents_view_delegate_gtk.h"
#include "chrome/browser/ui/gtk/sad_tab_gtk.h"
#endif
using content::WebContents;
SadTabHelper::SadTabHelper(WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
content::Source<WebContents>(web_contents));
}
SadTabHelper::~SadTabHelper() {
}
void SadTabHelper::RenderViewGone(base::TerminationStatus status) {
// Only show the sad tab if we're not in browser shutdown, so that WebContents
// objects that are not in a browser (e.g., HTML dialogs) and thus are
// visible do not flash a sad tab page.
if (browser_shutdown::GetShutdownType() != browser_shutdown::NOT_VALID)
return;
if (HasSadTab())
return;
InstallSadTab(status);
}
void SadTabHelper::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
switch (type) {
case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
if (HasSadTab()) {
#if defined(OS_MACOSX)
sad_tab_controller_mac::RemoveSadTab(sad_tab_.get());
#elif defined(TOOLKIT_VIEWS)
sad_tab_->Close();
// See http://crbug.com/117668. When the Widget is being destructed, we
// want calls to sad_tab() to return NULL.
scoped_ptr<views::Widget> local_sad_tab;
local_sad_tab.swap(sad_tab_);
#elif defined(TOOLKIT_GTK)
GtkWidget* expanded_container =
ChromeWebContentsViewDelegateGtk::GetFor(web_contents())->
expanded_container();
gtk_container_remove(
GTK_CONTAINER(expanded_container), sad_tab_->widget());
#else
#error Unknown platform
#endif
sad_tab_.reset();
}
break;
default:
NOTREACHED() << "Got a notification we didn't register for.";
}
}
void SadTabHelper::InstallSadTab(base::TerminationStatus status) {
#if defined(OS_MACOSX)
sad_tab_.reset(
sad_tab_controller_mac::CreateSadTabController(web_contents()));
#elif defined(TOOLKIT_VIEWS)
SadTabView::Kind kind =
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ?
SadTabView::KILLED : SadTabView::CRASHED;
views::Widget::InitParams sad_tab_params(
views::Widget::InitParams::TYPE_CONTROL);
// It is not possible to create a native_widget_win that has no parent in
// and later re-parent it.
// TODO(avi): This is a cheat. Can this be made cleaner?
sad_tab_params.parent = web_contents()->GetView()->GetNativeView();
#if defined(OS_WIN) && !defined(USE_AURA)
// Crash data indicates we can get here when the parent is no longer valid.
// Attempting to create a child window with a bogus parent crashes. So, we
// don't show a sad tab in this case in hopes the tab is in the process of
// shutting down.
if (!IsWindow(sad_tab_params.parent))
return;
#endif
sad_tab_params.ownership =
views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
sad_tab_.reset(new views::Widget);
sad_tab_->Init(sad_tab_params);
sad_tab_->SetContentsView(new SadTabView(web_contents(), kind));
views::Widget::ReparentNativeView(
sad_tab_->GetNativeView(), web_contents()->GetView()->GetNativeView());
gfx::Rect bounds;
web_contents()->GetView()->GetContainerBounds(&bounds);
sad_tab_->SetBounds(gfx::Rect(bounds.size()));
#elif defined(TOOLKIT_GTK)
sad_tab_.reset(new SadTabGtk(
web_contents(),
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED
? SadTabGtk::KILLED
: SadTabGtk::CRASHED));
GtkWidget* expanded_container =
ChromeWebContentsViewDelegateGtk::GetFor(web_contents())->
expanded_container();
gtk_container_add(GTK_CONTAINER(expanded_container), sad_tab_->widget());
gtk_widget_show(sad_tab_->widget());
#else
#error Unknown platform
#endif
}
bool SadTabHelper::HasSadTab() {
return sad_tab_.get() != NULL;
}
|