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
134
135
|
// 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 "base/logging.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/ui/sad_tab_types.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/ui/gtk/sad_tab_gtk.h"
#include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_gtk.h"
#endif
DEFINE_WEB_CONTENTS_USER_DATA_KEY(SadTabHelper)
SadTabHelper::SadTabHelper(content::WebContents* web_contents)
: content::WebContentsObserver(web_contents) {
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
content::Source<content::WebContents>(web_contents));
}
SadTabHelper::~SadTabHelper() {
}
bool SadTabHelper::HasSadTab() const {
return sad_tab_.get() != NULL;
}
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;
if (status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ||
status == base::TERMINATION_STATUS_PROCESS_CRASHED)
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(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK)
chrome::SadTabKind kind =
(status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) ?
chrome::SAD_TAB_KIND_KILLED : chrome::SAD_TAB_KIND_CRASHED;
#endif
#if defined(OS_MACOSX)
sad_tab_.reset(
sad_tab_controller_mac::CreateSadTabController(web_contents()));
#elif defined(TOOLKIT_VIEWS)
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(), kind));
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
}
|