OLD | NEW |
---|---|
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/views/sad_tab_view.h" | 5 #include "chrome/browser/ui/views/sad_tab_view.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/metrics/field_trial.h" | 9 #include "base/metrics/field_trial.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
12 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
13 #include "chrome/browser/ui/browser_finder.h" | 13 #include "chrome/browser/ui/browser_finder.h" |
14 #include "chrome/browser/ui/chrome_pages.h" | 14 #include "chrome/browser/ui/chrome_pages.h" |
15 #include "chrome/common/url_constants.h" | 15 #include "chrome/common/url_constants.h" |
16 #include "chrome/grit/generated_resources.h" | 16 #include "chrome/grit/generated_resources.h" |
17 #include "components/feedback/feedback_util.h" | 17 #include "components/feedback/feedback_util.h" |
18 #include "content/public/browser/navigation_controller.h" | 18 #include "content/public/browser/navigation_controller.h" |
19 #include "content/public/browser/web_contents.h" | 19 #include "content/public/browser/web_contents.h" |
20 #include "grit/components_strings.h" | 20 #include "grit/components_strings.h" |
21 #include "grit/theme_resources.h" | 21 #include "grit/theme_resources.h" |
22 #include "ui/base/l10n/l10n_util.h" | 22 #include "ui/base/l10n/l10n_util.h" |
23 #include "ui/base/resource/resource_bundle.h" | 23 #include "ui/base/resource/resource_bundle.h" |
24 #include "ui/views/background.h" | 24 #include "ui/views/background.h" |
25 #include "ui/views/controls/button/blue_button.h" | |
25 #include "ui/views/controls/button/label_button.h" | 26 #include "ui/views/controls/button/label_button.h" |
26 #include "ui/views/controls/button/label_button_border.h" | 27 #include "ui/views/controls/button/label_button_border.h" |
27 #include "ui/views/controls/image_view.h" | 28 #include "ui/views/controls/image_view.h" |
28 #include "ui/views/controls/label.h" | 29 #include "ui/views/controls/label.h" |
29 #include "ui/views/controls/link.h" | 30 #include "ui/views/controls/link.h" |
31 #include "ui/views/controls/styled_label.h" | |
30 #include "ui/views/layout/grid_layout.h" | 32 #include "ui/views/layout/grid_layout.h" |
33 #include "ui/views/layout/layout_constants.h" | |
31 #include "ui/views/widget/widget.h" | 34 #include "ui/views/widget/widget.h" |
32 | 35 |
33 using content::OpenURLParams; | 36 using content::OpenURLParams; |
34 using content::WebContents; | 37 using content::WebContents; |
35 | 38 |
36 namespace { | 39 namespace { |
37 | 40 |
38 const int kPadding = 20; | 41 const int kMaxContentWidth = 600; |
39 const float kMessageSize = 0.65f; | 42 const int kMinColumnWidth = 120; |
40 const SkColor kTextColor = SK_ColorWHITE; | |
41 const SkColor kCrashColor = SkColorSetRGB(35, 48, 64); | |
42 const SkColor kKillColor = SkColorSetRGB(57, 48, 88); | |
43 | |
44 const char kCategoryTagCrash[] = "Crash"; | 43 const char kCategoryTagCrash[] = "Crash"; |
45 | 44 |
46 } // namespace | 45 } // namespace |
47 | 46 |
48 SadTabView::SadTabView(WebContents* web_contents, chrome::SadTabKind kind) | 47 SadTabView::SadTabView(WebContents* web_contents, chrome::SadTabKind kind) |
49 : web_contents_(web_contents), | 48 : web_contents_(web_contents), |
50 kind_(kind), | 49 kind_(kind), |
51 painted_(false), | 50 painted_(false), |
52 message_(NULL), | 51 message_(nullptr), |
53 help_link_(NULL), | 52 help_link_(nullptr), |
54 feedback_link_(NULL), | 53 feedback_link_(nullptr), |
55 reload_button_(NULL) { | 54 reload_button_(nullptr), |
55 title_(nullptr), | |
56 help_message_(nullptr) { | |
56 DCHECK(web_contents); | 57 DCHECK(web_contents); |
57 | 58 |
58 // Sometimes the user will never see this tab, so keep track of the total | 59 // Sometimes the user will never see this tab, so keep track of the total |
59 // number of creation events to compare to display events. | 60 // number of creation events to compare to display events. |
60 // TODO(jamescook): Remove this after R20 stable. Keep it for now so we can | 61 // TODO(jamescook): Remove this after R20 stable. Keep it for now so we can |
61 // compare R20 to earlier versions. | 62 // compare R20 to earlier versions. |
62 UMA_HISTOGRAM_COUNTS("SadTab.Created", kind_); | 63 UMA_HISTOGRAM_COUNTS("SadTab.Created", kind_); |
63 | 64 |
64 // These stats should use the same counting approach and bucket size used for | 65 // These stats should use the same counting approach and bucket size used for |
65 // tab discard events in chromeos::OomPriorityManager so they can be | 66 // tab discard events in chromeos::OomPriorityManager so they can be |
(...skipping 11 matching lines...) Expand all Loading... | |
77 static int killed = 0; | 78 static int killed = 0; |
78 killed++; | 79 killed++; |
79 UMA_HISTOGRAM_CUSTOM_COUNTS( | 80 UMA_HISTOGRAM_CUSTOM_COUNTS( |
80 "Tabs.SadTab.KillCreated", killed, 1, 1000, 50); | 81 "Tabs.SadTab.KillCreated", killed, 1, 1000, 50); |
81 break; | 82 break; |
82 } | 83 } |
83 default: | 84 default: |
84 NOTREACHED(); | 85 NOTREACHED(); |
85 } | 86 } |
86 | 87 |
88 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
msw
2015/05/18 19:24:51
nit: move this down to where it's used.
edwardjung
2015/05/19 12:21:12
Done.
| |
89 | |
87 // Set the background color. | 90 // Set the background color. |
88 set_background(views::Background::CreateSolidBackground( | 91 set_background( |
89 (kind_ == chrome::SAD_TAB_KIND_CRASHED) ? kCrashColor : kKillColor)); | 92 views::Background::CreateSolidBackground(GetNativeTheme()->GetSystemColor( |
93 ui::NativeTheme::kColorId_DialogBackground))); | |
90 | 94 |
91 views::GridLayout* layout = new views::GridLayout(this); | 95 views::GridLayout* layout = new views::GridLayout(this); |
92 SetLayoutManager(layout); | 96 SetLayoutManager(layout); |
93 | 97 |
94 const int column_set_id = 0; | 98 const int column_set_id = 0; |
95 views::ColumnSet* columns = layout->AddColumnSet(column_set_id); | 99 views::ColumnSet* columns = layout->AddColumnSet(column_set_id); |
96 columns->AddPaddingColumn(1, kPadding); | 100 columns->AddPaddingColumn(1, views::kPanelSubVerticalSpacing); |
97 columns->AddColumn(views::GridLayout::CENTER, views::GridLayout::CENTER, | 101 columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0, |
98 0, views::GridLayout::USE_PREF, 0, 0); | 102 views::GridLayout::USE_PREF, 0, kMinColumnWidth); |
99 columns->AddPaddingColumn(1, kPadding); | 103 columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::LEADING, 0, |
104 views::GridLayout::USE_PREF, 0, kMinColumnWidth); | |
105 columns->AddPaddingColumn(1, views::kPanelSubVerticalSpacing); | |
100 | 106 |
101 views::ImageView* image = new views::ImageView(); | 107 views::ImageView* image = new views::ImageView(); |
102 image->SetImage(ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( | 108 image->SetImage( |
103 (kind_ == chrome::SAD_TAB_KIND_CRASHED) ? IDR_SAD_TAB : IDR_KILLED_TAB)); | 109 ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(IDR_SAD_TAB)); |
104 layout->StartRowWithPadding(0, column_set_id, 1, kPadding); | 110 layout->AddPaddingRow(2, views::kPanelVerticalSpacing); |
msw
2015/05/18 19:24:51
q: I'm not totally sure how these |vertical_resize
edwardjung
2015/05/19 12:21:12
It's meant to be a percentage, but yes 1, 2 does s
| |
105 layout->AddView(image); | 111 layout->StartRow(0, column_set_id); |
112 layout->AddView(image, 2, 1); | |
106 | 113 |
107 views::Label* title = CreateLabel(l10n_util::GetStringUTF16( | 114 const bool is_crashed_type = kind_ == chrome::SAD_TAB_KIND_CRASHED; |
108 (kind_ == chrome::SAD_TAB_KIND_CRASHED) ? | 115 |
109 IDS_SAD_TAB_TITLE : IDS_KILLED_TAB_TITLE)); | 116 title_ = CreateLabel(l10n_util::GetStringUTF16( |
110 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | 117 is_crashed_type ? IDS_SAD_TAB_TITLE : IDS_KILLED_TAB_TITLE)); |
111 title->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont)); | 118 title_->SetFontList(rb.GetFontList(ui::ResourceBundle::LargeFont)); |
112 layout->StartRowWithPadding(0, column_set_id, 0, kPadding); | 119 title_->SetMultiLine(true); |
113 layout->AddView(title); | 120 title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
121 layout->StartRowWithPadding(0, column_set_id, 0, | |
122 views::kPanelVerticalSpacing); | |
123 layout->AddView(title_, 2, 1); | |
124 | |
125 const SkColor text_color = GetNativeTheme()->GetSystemColor( | |
126 ui::NativeTheme::kColorId_LabelDisabledColor); | |
114 | 127 |
115 message_ = CreateLabel(l10n_util::GetStringUTF16( | 128 message_ = CreateLabel(l10n_util::GetStringUTF16( |
116 (kind_ == chrome::SAD_TAB_KIND_CRASHED) ? | 129 is_crashed_type ? IDS_SAD_TAB_MESSAGE : IDS_KILLED_TAB_MESSAGE)); |
117 IDS_SAD_TAB_MESSAGE : IDS_KILLED_TAB_MESSAGE)); | |
118 message_->SetMultiLine(true); | 130 message_->SetMultiLine(true); |
119 layout->StartRowWithPadding(0, column_set_id, 0, kPadding); | 131 message_->SetEnabledColor(text_color); |
120 layout->AddView(message_); | 132 message_->SetHorizontalAlignment(gfx::ALIGN_LEFT); |
133 message_->SetLineHeight(views::kPanelSubVerticalSpacing); | |
134 | |
135 layout->StartRowWithPadding(0, column_set_id, 0, views::kPanelVertMargin); | |
136 layout->AddView(message_, 2, 1, views::GridLayout::LEADING, | |
137 views::GridLayout::LEADING); | |
121 | 138 |
122 if (web_contents_) { | 139 if (web_contents_) { |
123 layout->StartRowWithPadding(0, column_set_id, 0, kPadding); | 140 reload_button_ = new views::BlueButton( |
124 reload_button_ = new views::LabelButton( | 141 this, l10n_util::GetStringUTF16(IDS_SAD_TAB_RELOAD_LABEL)); |
125 this, | |
126 l10n_util::GetStringUTF16(IDS_SAD_TAB_RELOAD_LABEL)); | |
127 reload_button_->SetStyle(views::Button::STYLE_BUTTON); | |
128 // Always render the reload button with chrome style borders; never rely on | |
129 // native styles. | |
130 reload_button_->SetBorder(scoped_ptr<views::Border>( | |
131 new views::LabelButtonBorder(reload_button_->style()))); | |
132 layout->AddView(reload_button_); | |
133 | 142 |
134 help_link_ = CreateLink(l10n_util::GetStringUTF16( | 143 if (is_crashed_type) { |
135 (kind_ == chrome::SAD_TAB_KIND_CRASHED) ? | |
136 IDS_SAD_TAB_HELP_LINK : IDS_LEARN_MORE)); | |
137 | |
138 if (kind_ == chrome::SAD_TAB_KIND_CRASHED) { | |
139 size_t offset = 0; | 144 size_t offset = 0; |
140 base::string16 help_text( | 145 base::string16 help_text( |
141 l10n_util::GetStringFUTF16(IDS_SAD_TAB_HELP_MESSAGE, | 146 l10n_util::GetStringFUTF16(IDS_SAD_TAB_HELP_MESSAGE, |
142 base::string16(), &offset)); | 147 base::string16(), &offset)); |
143 views::Label* help_prefix = CreateLabel(help_text.substr(0, offset)); | |
144 views::Label* help_suffix = CreateLabel(help_text.substr(offset)); | |
145 | 148 |
146 const int help_column_set_id = 1; | 149 base::string16 link_text = |
147 views::ColumnSet* help_columns = layout->AddColumnSet(help_column_set_id); | 150 l10n_util::GetStringUTF16(IDS_SAD_TAB_HELP_LINK); |
148 help_columns->AddPaddingColumn(1, kPadding); | |
149 // Center three middle columns for the help's [prefix][link][suffix]. | |
150 for (size_t column = 0; column < 3; column++) | |
151 help_columns->AddColumn(views::GridLayout::CENTER, | |
152 views::GridLayout::CENTER, 0, views::GridLayout::USE_PREF, 0, 0); | |
153 help_columns->AddPaddingColumn(1, kPadding); | |
154 | 151 |
155 layout->StartRowWithPadding(0, help_column_set_id, 0, kPadding); | 152 base::string16 help_prefix = help_text.substr(0, offset); |
156 layout->AddView(help_prefix); | 153 base::string16 help_suffix = help_text.substr(offset); |
157 layout->AddView(help_link_); | 154 base::string16 help_message_string = help_prefix; |
158 layout->AddView(help_suffix); | 155 help_message_string.append(link_text).append(help_suffix); |
156 | |
157 help_message_ = new views::StyledLabel(help_message_string, this); | |
158 | |
159 views::StyledLabel::RangeStyleInfo link_style = | |
160 views::StyledLabel::RangeStyleInfo::CreateForLink(); | |
161 link_style.font_style = gfx::Font::UNDERLINE; | |
162 link_style.color = text_color; | |
163 | |
164 views::StyledLabel::RangeStyleInfo normal_style = | |
165 views::StyledLabel::RangeStyleInfo(); | |
166 normal_style.color = text_color; | |
167 | |
168 help_message_->SetDefaultStyle(normal_style); | |
169 help_message_->SetLineHeight(views::kPanelSubVerticalSpacing); | |
170 | |
171 help_message_->AddStyleRange( | |
172 gfx::Range(help_prefix.length(), | |
173 help_prefix.length() + link_text.length()), | |
174 link_style); | |
175 | |
176 layout->StartRowWithPadding(0, column_set_id, 0, views::kPanelVertMargin); | |
177 layout->AddView(help_message_, 2, 1, views::GridLayout::LEADING, | |
178 views::GridLayout::TRAILING); | |
179 layout->StartRowWithPadding(0, column_set_id, 0, | |
180 views::kPanelVerticalSpacing); | |
181 layout->SkipColumns(1); | |
159 } else { | 182 } else { |
160 layout->StartRowWithPadding(0, column_set_id, 0, kPadding); | 183 feedback_link_ = CreateLink( |
161 layout->AddView(help_link_); | 184 l10n_util::GetStringUTF16(IDS_KILLED_TAB_FEEDBACK_LINK), text_color); |
185 feedback_link_->SetLineHeight(views::kPanelSubVerticalSpacing); | |
186 feedback_link_->SetMultiLine(true); | |
187 feedback_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT); | |
162 | 188 |
163 feedback_link_ = CreateLink( | 189 layout->StartRowWithPadding(0, column_set_id, 0, |
164 l10n_util::GetStringUTF16(IDS_KILLED_TAB_FEEDBACK_LINK)); | 190 views::kPanelSubVerticalSpacing); |
165 layout->StartRowWithPadding(0, column_set_id, 0, kPadding); | 191 layout->AddView(feedback_link_, 2, 1, views::GridLayout::LEADING, |
166 layout->AddView(feedback_link_); | 192 views::GridLayout::LEADING); |
193 | |
194 help_link_ = | |
195 CreateLink(l10n_util::GetStringUTF16(IDS_LEARN_MORE), text_color); | |
196 layout->StartRowWithPadding(0, column_set_id, 0, | |
197 views::kPanelVerticalSpacing); | |
198 layout->AddView(help_link_, 1, 1, views::GridLayout::LEADING, | |
199 views::GridLayout::CENTER); | |
167 } | 200 } |
201 layout->AddView(reload_button_, 1, 1, views::GridLayout::TRAILING, | |
202 views::GridLayout::LEADING); | |
168 } | 203 } |
169 layout->AddPaddingRow(1, kPadding); | 204 layout->AddPaddingRow(4, views::kPanelSubVerticalSpacing); |
170 } | 205 } |
171 | 206 |
172 SadTabView::~SadTabView() {} | 207 SadTabView::~SadTabView() {} |
173 | 208 |
174 void SadTabView::LinkClicked(views::Link* source, int event_flags) { | 209 void SadTabView::LinkClicked(views::Link* source, int event_flags) { |
175 DCHECK(web_contents_); | 210 DCHECK(web_contents_); |
176 if (source == help_link_) { | 211 if (source == help_link_) { |
177 GURL help_url((kind_ == chrome::SAD_TAB_KIND_CRASHED) ? | 212 GURL help_url((kind_ == chrome::SAD_TAB_KIND_CRASHED) ? |
178 chrome::kCrashReasonURL : chrome::kKillReasonURL); | 213 chrome::kCrashReasonURL : chrome::kKillReasonURL); |
179 OpenURLParams params( | 214 OpenURLParams params( |
180 help_url, content::Referrer(), CURRENT_TAB, | 215 help_url, content::Referrer(), CURRENT_TAB, |
181 ui::PAGE_TRANSITION_LINK, false); | 216 ui::PAGE_TRANSITION_LINK, false); |
182 web_contents_->OpenURL(params); | 217 web_contents_->OpenURL(params); |
183 } else if (source == feedback_link_) { | 218 } else if (source == feedback_link_) { |
184 chrome::ShowFeedbackPage( | 219 chrome::ShowFeedbackPage( |
185 chrome::FindBrowserWithWebContents(web_contents_), | 220 chrome::FindBrowserWithWebContents(web_contents_), |
186 l10n_util::GetStringUTF8(IDS_KILLED_TAB_FEEDBACK_MESSAGE), | 221 l10n_util::GetStringUTF8(IDS_KILLED_TAB_FEEDBACK_MESSAGE), |
187 std::string(kCategoryTagCrash)); | 222 std::string(kCategoryTagCrash)); |
188 } | 223 } |
189 } | 224 } |
190 | 225 |
226 void SadTabView::StyledLabelLinkClicked(const gfx::Range& range, | |
227 int event_flags) { | |
228 LinkClicked(help_link_, event_flags); | |
229 } | |
230 | |
191 void SadTabView::ButtonPressed(views::Button* sender, | 231 void SadTabView::ButtonPressed(views::Button* sender, |
192 const ui::Event& event) { | 232 const ui::Event& event) { |
193 DCHECK(web_contents_); | 233 DCHECK(web_contents_); |
194 DCHECK_EQ(reload_button_, sender); | 234 DCHECK_EQ(reload_button_, sender); |
195 web_contents_->GetController().Reload(true); | 235 web_contents_->GetController().Reload(true); |
196 } | 236 } |
197 | 237 |
198 void SadTabView::Layout() { | 238 void SadTabView::Layout() { |
199 // Specify the maximum message width explicitly. | 239 // Specify the maximum message width explicitly. |
200 message_->SizeToFit(static_cast<int>(width() * kMessageSize)); | 240 const int max_width = |
241 std::min(width() - views::kPanelSubVerticalSpacing * 2, kMaxContentWidth); | |
242 message_->SizeToFit(max_width); | |
243 title_->SizeToFit(max_width); | |
244 | |
245 if (feedback_link_ != nullptr) { | |
msw
2015/05/18 19:24:50
nit: remove curly braces.
edwardjung
2015/05/19 12:21:12
Done.
| |
246 feedback_link_->SizeToFit(max_width); | |
247 } else if (help_message_ != nullptr) { | |
msw
2015/05/18 19:24:50
nit: maybe don't bother with the else here, it's n
edwardjung
2015/05/19 12:21:12
Done.
| |
248 help_message_->SizeToFit(max_width); | |
249 } | |
201 View::Layout(); | 250 View::Layout(); |
202 } | 251 } |
203 | 252 |
204 void SadTabView::OnPaint(gfx::Canvas* canvas) { | 253 void SadTabView::OnPaint(gfx::Canvas* canvas) { |
205 if (!painted_) { | 254 if (!painted_) { |
206 // User actually saw the error, keep track for user experience stats. | 255 // User actually saw the error, keep track for user experience stats. |
207 // TODO(jamescook): Remove this after R20 stable. Keep it for now so we can | 256 // TODO(jamescook): Remove this after R20 stable. Keep it for now so we can |
208 // compare R20 to earlier versions. | 257 // compare R20 to earlier versions. |
209 UMA_HISTOGRAM_COUNTS("SadTab.Displayed", kind_); | 258 UMA_HISTOGRAM_COUNTS("SadTab.Displayed", kind_); |
210 | 259 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 } | 303 } |
255 | 304 |
256 void SadTabView::Close() { | 305 void SadTabView::Close() { |
257 if (GetWidget()) | 306 if (GetWidget()) |
258 GetWidget()->Close(); | 307 GetWidget()->Close(); |
259 } | 308 } |
260 | 309 |
261 views::Label* SadTabView::CreateLabel(const base::string16& text) { | 310 views::Label* SadTabView::CreateLabel(const base::string16& text) { |
262 views::Label* label = new views::Label(text); | 311 views::Label* label = new views::Label(text); |
263 label->SetBackgroundColor(background()->get_color()); | 312 label->SetBackgroundColor(background()->get_color()); |
264 label->SetEnabledColor(kTextColor); | |
265 return label; | 313 return label; |
266 } | 314 } |
267 | 315 |
268 views::Link* SadTabView::CreateLink(const base::string16& text) { | 316 views::Link* SadTabView::CreateLink(const base::string16& text, |
317 const SkColor& color) { | |
269 views::Link* link = new views::Link(text); | 318 views::Link* link = new views::Link(text); |
270 link->SetBackgroundColor(background()->get_color()); | 319 link->SetBackgroundColor(background()->get_color()); |
271 link->SetEnabledColor(kTextColor); | 320 link->SetEnabledColor(color); |
272 link->set_listener(this); | 321 link->set_listener(this); |
273 return link; | 322 return link; |
274 } | 323 } |
275 | 324 |
276 namespace chrome { | 325 namespace chrome { |
277 | 326 |
278 SadTab* SadTab::Create(content::WebContents* web_contents, | 327 SadTab* SadTab::Create(content::WebContents* web_contents, |
279 SadTabKind kind) { | 328 SadTabKind kind) { |
280 return new SadTabView(web_contents, kind); | 329 return new SadTabView(web_contents, kind); |
281 } | 330 } |
282 | 331 |
283 } // namespace chrome | 332 } // namespace chrome |
OLD | NEW |