Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / sad_tab_gtk.cc
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_gtk.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