| 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 |