OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/ui/gtk/sad_tab_gtk.h" | |
6 | |
7 #include "base/metrics/histogram.h" | |
8 #include "base/strings/utf_string_conversions.h" | |
9 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" | |
10 #include "chrome/browser/ui/gtk/tab_contents/chrome_web_contents_view_delegate_g
tk.h" | |
11 #include "chrome/common/url_constants.h" | |
12 #include "content/public/browser/web_contents.h" | |
13 #include "grit/generated_resources.h" | |
14 #include "grit/locale_settings.h" | |
15 #include "grit/theme_resources.h" | |
16 #include "ui/base/gtk/gtk_hig_constants.h" | |
17 #include "ui/base/l10n/l10n_util.h" | |
18 #include "ui/base/resource/resource_bundle.h" | |
19 #include "ui/gfx/image/image.h" | |
20 | |
21 using content::OpenURLParams; | |
22 using content::WebContents; | |
23 | |
24 namespace { | |
25 | |
26 // Background color of the content (a grayish blue) for a crashed tab. | |
27 const GdkColor kCrashedBackgroundColor = GDK_COLOR_RGB(35, 48, 64); | |
28 | |
29 // Background color of the content (a grayish purple) for a killed | |
30 // tab. TODO(gspencer): update this for the "real" color when the UI | |
31 // team provides one. See http://crosbug.com/10711 | |
32 const GdkColor kKilledBackgroundColor = GDK_COLOR_RGB(57, 48, 88); | |
33 | |
34 // Construct a centered GtkLabel with a white foreground. | |
35 // |format| is a printf-style format containing a %s; | |
36 // |str| is substituted into the format. | |
37 GtkWidget* MakeWhiteMarkupLabel(const char* format, const std::string& str) { | |
38 GtkWidget* label = gtk_label_new(NULL); | |
39 char* markup = g_markup_printf_escaped(format, str.c_str()); | |
40 gtk_label_set_markup(GTK_LABEL(label), markup); | |
41 g_free(markup); | |
42 | |
43 // Center align and justify it. | |
44 gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5); | |
45 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); | |
46 | |
47 // Set text to white. | |
48 GdkColor white = ui::kGdkWhite; | |
49 gtk_widget_modify_fg(label, GTK_STATE_NORMAL, &white); | |
50 | |
51 return label; | |
52 } | |
53 | |
54 } // namespace | |
55 | |
56 SadTabGtk::SadTabGtk(WebContents* web_contents, chrome::SadTabKind kind) | |
57 : web_contents_(web_contents), | |
58 kind_(kind) { | |
59 DCHECK(web_contents_); | |
60 | |
61 switch (kind_) { | |
62 case chrome::SAD_TAB_KIND_CRASHED: { | |
63 static int crashed = 0; | |
64 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
65 "Tabs.SadTab.CrashCreated", ++crashed, 1, 1000, 50); | |
66 break; | |
67 } | |
68 case chrome::SAD_TAB_KIND_KILLED: { | |
69 static int killed = 0; | |
70 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
71 "Tabs.SadTab.KilledCreated", ++killed, 1, 1000, 50); | |
72 break; | |
73 } | |
74 default: | |
75 NOTREACHED(); | |
76 } | |
77 | |
78 // Use an event box to get the background painting correctly. | |
79 event_box_.Own(gtk_event_box_new()); | |
80 gtk_widget_modify_bg(event_box_.get(), GTK_STATE_NORMAL, | |
81 (kind == chrome::SAD_TAB_KIND_CRASHED) ? | |
82 &kCrashedBackgroundColor : &kKilledBackgroundColor); | |
83 // Allow ourselves to be resized arbitrarily small. | |
84 gtk_widget_set_size_request(event_box_.get(), 0, 0); | |
85 | |
86 GtkWidget* centering = gtk_alignment_new(0.5, 0.5, 0.0, 0.0); | |
87 gtk_container_add(GTK_CONTAINER(event_box_.get()), centering); | |
88 | |
89 // Use a vertical box to contain icon, title, message and link. | |
90 GtkWidget* vbox = gtk_vbox_new(FALSE, 0); | |
91 gtk_container_add(GTK_CONTAINER(centering), vbox); | |
92 | |
93 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
94 // Add center-aligned image. | |
95 GtkWidget* image = gtk_image_new_from_pixbuf(rb.GetNativeImageNamed( | |
96 (kind == chrome::SAD_TAB_KIND_CRASHED) ? | |
97 IDR_SAD_TAB : IDR_KILLED_TAB).ToGdkPixbuf()); | |
98 gtk_misc_set_alignment(GTK_MISC(image), 0.5, 0.5); | |
99 gtk_box_pack_start(GTK_BOX(vbox), image, FALSE, FALSE, 0); | |
100 | |
101 // Add spacer between image and title. | |
102 GtkWidget* spacer = gtk_label_new(NULL); | |
103 gtk_label_set_markup(GTK_LABEL(spacer), "<span size=\"larger\"> </span>"); | |
104 gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0); | |
105 | |
106 // Add center-aligned title. | |
107 GtkWidget* title = MakeWhiteMarkupLabel( | |
108 "<span size=\"larger\" style=\"normal\"><b>%s</b></span>", | |
109 l10n_util::GetStringUTF8((kind == chrome::SAD_TAB_KIND_CRASHED) ? | |
110 IDS_SAD_TAB_TITLE : IDS_KILLED_TAB_TITLE)); | |
111 gtk_box_pack_start(GTK_BOX(vbox), title, FALSE, FALSE, 0); | |
112 | |
113 // Add spacer between title and message. | |
114 spacer = gtk_label_new(" "); | |
115 gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0); | |
116 | |
117 // Add center-aligned message. | |
118 GtkWidget* message = MakeWhiteMarkupLabel( | |
119 "<span style=\"normal\">%s</span>", | |
120 l10n_util::GetStringUTF8((kind == chrome::SAD_TAB_KIND_CRASHED) ? | |
121 IDS_SAD_TAB_MESSAGE : IDS_KILLED_TAB_MESSAGE)); | |
122 gtk_label_set_line_wrap(GTK_LABEL(message), TRUE); | |
123 gtk_box_pack_start(GTK_BOX(vbox), message, FALSE, FALSE, 0); | |
124 | |
125 // Add spacer between message and link. | |
126 spacer = gtk_label_new(" "); | |
127 gtk_box_pack_start(GTK_BOX(vbox), spacer, FALSE, FALSE, 0); | |
128 | |
129 if (web_contents_) { | |
130 // Create the help link and alignment. | |
131 std::string link_text(l10n_util::GetStringUTF8( | |
132 (kind == chrome::SAD_TAB_KIND_CRASHED) ? | |
133 IDS_SAD_TAB_HELP_LINK : IDS_LEARN_MORE)); | |
134 GtkWidget* link = gtk_chrome_link_button_new(link_text.c_str()); | |
135 gtk_chrome_link_button_set_normal_color(GTK_CHROME_LINK_BUTTON(link), | |
136 &ui::kGdkWhite); | |
137 g_signal_connect(link, "clicked", G_CALLBACK(OnLinkButtonClickThunk), this); | |
138 GtkWidget* help_alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0); | |
139 | |
140 if (kind == chrome::SAD_TAB_KIND_CRASHED) { | |
141 // Use a horizontal box to contain the help text and link. | |
142 GtkWidget* help_hbox = gtk_hbox_new(FALSE, 0); | |
143 gtk_container_add(GTK_CONTAINER(vbox), help_hbox); | |
144 | |
145 size_t offset = 0; | |
146 base::string16 help_text( | |
147 l10n_util::GetStringFUTF16(IDS_SAD_TAB_HELP_MESSAGE, | |
148 base::string16(), &offset)); | |
149 std::string help_prefix_text( | |
150 base::UTF16ToUTF8(help_text.substr(0, offset))); | |
151 std::string help_suffix_text( | |
152 base::UTF16ToUTF8(help_text.substr(offset))); | |
153 | |
154 GtkWidget* help_prefix = MakeWhiteMarkupLabel( | |
155 "<span style=\"normal\">%s</span>", help_prefix_text); | |
156 GtkWidget* help_suffix = MakeWhiteMarkupLabel( | |
157 "<span style=\"normal\">%s</span>", help_suffix_text); | |
158 | |
159 // Add the help link and text to the horizontal box. | |
160 gtk_box_pack_start(GTK_BOX(help_hbox), help_prefix, FALSE, FALSE, 0); | |
161 GtkWidget* link_alignment = gtk_alignment_new(0.5, 0.5, 0.0, 0.0); | |
162 gtk_container_add(GTK_CONTAINER(link_alignment), link); | |
163 gtk_box_pack_start(GTK_BOX(help_hbox), link_alignment, FALSE, FALSE, 0); | |
164 gtk_box_pack_start(GTK_BOX(help_hbox), help_suffix, FALSE, FALSE, 0); | |
165 } else { | |
166 // Add just the help link to a centered alignment. | |
167 gtk_container_add(GTK_CONTAINER(help_alignment), link); | |
168 } | |
169 gtk_box_pack_start(GTK_BOX(vbox), help_alignment, FALSE, FALSE, 0); | |
170 } | |
171 | |
172 gtk_widget_show_all(event_box_.get()); | |
173 } | |
174 | |
175 SadTabGtk::~SadTabGtk() { | |
176 event_box_.Destroy(); | |
177 } | |
178 | |
179 void SadTabGtk::Show() { | |
180 switch (kind_) { | |
181 case chrome::SAD_TAB_KIND_CRASHED: { | |
182 static int crashed = 0; | |
183 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
184 "Tabs.SadTab.CrashDisplayed", ++crashed, 1, 1000, 50); | |
185 break; | |
186 } | |
187 case chrome::SAD_TAB_KIND_KILLED: { | |
188 static int killed = 0; | |
189 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
190 "Tabs.SadTab.KilledDisplayed", ++killed, 1, 1000, 50); | |
191 break; | |
192 } | |
193 default: | |
194 NOTREACHED(); | |
195 } | |
196 | |
197 GtkWidget* expanded_container = | |
198 ChromeWebContentsViewDelegateGtk::GetFor(web_contents_)-> | |
199 expanded_container(); | |
200 gtk_container_add(GTK_CONTAINER(expanded_container), event_box_.get()); | |
201 gtk_widget_show(event_box_.get()); | |
202 } | |
203 | |
204 void SadTabGtk::Close() { | |
205 GtkWidget* expanded_container = | |
206 ChromeWebContentsViewDelegateGtk::GetFor(web_contents_)-> | |
207 expanded_container(); | |
208 gtk_container_remove(GTK_CONTAINER(expanded_container), event_box_.get()); | |
209 } | |
210 | |
211 void SadTabGtk::OnLinkButtonClick(GtkWidget* sender) { | |
212 if (web_contents_) { | |
213 GURL help_url((kind_ == chrome::SAD_TAB_KIND_CRASHED) ? | |
214 chrome::kCrashReasonURL : chrome::kKillReasonURL); | |
215 OpenURLParams params(help_url, content::Referrer(), CURRENT_TAB, | |
216 content::PAGE_TRANSITION_LINK, false); | |
217 web_contents_->OpenURL(params); | |
218 } | |
219 } | |
220 | |
221 namespace chrome { | |
222 | |
223 SadTab* SadTab::Create(content::WebContents* web_contents, SadTabKind kind) { | |
224 return new SadTabGtk(web_contents, kind); | |
225 } | |
226 | |
227 } // namespace chrome | |
OLD | NEW |