OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 package org.chromium.chrome.browser.tab; | 5 package org.chromium.chrome.browser.tab; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.support.annotation.StringRes; | 8 import android.graphics.Canvas; |
| 9 import android.graphics.Paint; |
| 10 import android.text.Layout; |
| 11 import android.text.SpannableString; |
| 12 import android.text.SpannableStringBuilder; |
9 import android.text.method.LinkMovementMethod; | 13 import android.text.method.LinkMovementMethod; |
| 14 import android.text.style.BulletSpan; |
10 import android.view.LayoutInflater; | 15 import android.view.LayoutInflater; |
11 import android.view.View; | 16 import android.view.View; |
12 import android.view.View.OnClickListener; | 17 import android.view.View.OnClickListener; |
13 import android.widget.Button; | 18 import android.widget.Button; |
14 import android.widget.TextView; | 19 import android.widget.TextView; |
15 | 20 |
| 21 import org.chromium.base.metrics.RecordHistogram; |
16 import org.chromium.chrome.R; | 22 import org.chromium.chrome.R; |
17 import org.chromium.ui.text.NoUnderlineClickableSpan; | 23 import org.chromium.ui.text.NoUnderlineClickableSpan; |
18 import org.chromium.ui.text.SpanApplier; | 24 import org.chromium.ui.text.SpanApplier; |
19 import org.chromium.ui.text.SpanApplier.SpanInfo; | 25 import org.chromium.ui.text.SpanApplier.SpanInfo; |
20 | 26 |
21 /** | 27 /** |
22 * A factory class for creating the "Sad Tab" view, which is shown in place of a
crashed renderer. | 28 * A factory class for creating the "Sad Tab" view, which is shown in place of a
crashed renderer. |
23 */ | 29 */ |
24 public class SadTabViewFactory { | 30 public class SadTabViewFactory { |
25 | |
26 /** | 31 /** |
27 * @param context Context of the resulting Sad Tab view. | 32 * @param context Context of the resulting Sad Tab view. |
28 * @param suggestionAction Action to be executed when user clicks "try these
suggestions". | 33 * @param suggestionAction {@link Runnable} to be executed when user clicks
"try these |
29 * @param reloadButtonAction Action to be executed when Reload button is pre
ssed. | 34 * suggestions". |
30 * (e.g., refreshing the page) | 35 * @param buttonAction {@link Runnable} to be executed when the button is pr
essed. |
31 * @param buttonTextId The string resource for the button text label. | 36 * (e.g., refreshing the page or sending feedback) |
| 37 * @param showSendFeedbackView Whether to show the "send feedback" version o
f the Sad Tab view. |
32 * @return A "Sad Tab" view instance which is used in place of a crashed ren
derer. | 38 * @return A "Sad Tab" view instance which is used in place of a crashed ren
derer. |
33 */ | 39 */ |
34 public static View createSadTabView( | 40 public static View createSadTabView(Context context, final Runnable suggesti
onAction, |
35 Context context, final OnClickListener suggestionAction, | 41 final Runnable buttonAction, final boolean showSendFeedbackView) { |
36 OnClickListener reloadButtonAction, @StringRes int buttonTextId) { | |
37 // Inflate Sad tab and initialize. | 42 // Inflate Sad tab and initialize. |
38 LayoutInflater inflater = (LayoutInflater) context.getSystemService( | 43 LayoutInflater inflater = (LayoutInflater) context.getSystemService( |
39 Context.LAYOUT_INFLATER_SERVICE); | 44 Context.LAYOUT_INFLATER_SERVICE); |
40 View sadTabView = inflater.inflate(R.layout.sad_tab, null); | 45 View sadTabView = inflater.inflate(R.layout.sad_tab, null); |
41 | 46 |
| 47 TextView titleText = (TextView) sadTabView.findViewById(R.id.sad_tab_tit
le); |
| 48 int titleTextId = |
| 49 showSendFeedbackView ? R.string.sad_tab_reload_title : R.string.
sad_tab_title; |
| 50 titleText.setText(titleTextId); |
| 51 |
| 52 if (showSendFeedbackView) intializeSuggestionsViews(context, sadTabView)
; |
| 53 |
42 TextView messageText = (TextView) sadTabView.findViewById(R.id.sad_tab_m
essage); | 54 TextView messageText = (TextView) sadTabView.findViewById(R.id.sad_tab_m
essage); |
43 messageText.setText(getHelpMessage(context, suggestionAction)); | 55 messageText.setText(getHelpMessage(context, suggestionAction, showSendFe
edbackView)); |
44 messageText.setMovementMethod(LinkMovementMethod.getInstance()); | 56 messageText.setMovementMethod(LinkMovementMethod.getInstance()); |
45 | 57 |
46 Button reloadButton = (Button) sadTabView.findViewById(R.id.sad_tab_relo
ad_button); | 58 Button button = (Button) sadTabView.findViewById(R.id.sad_tab_button); |
47 reloadButton.setText(buttonTextId); | 59 int buttonTextId = showSendFeedbackView ? R.string.sad_tab_send_feedback
_label |
48 reloadButton.setOnClickListener(reloadButtonAction); | 60 : R.string.sad_tab_reload_label; |
| 61 button.setText(buttonTextId); |
| 62 button.setOnClickListener(new OnClickListener() { |
| 63 @Override |
| 64 public void onClick(View v) { |
| 65 SadTabViewFactory.recordEvent(showSendFeedbackView, SadTabEvent.
BUTTON_CLICKED); |
| 66 buttonAction.run(); |
| 67 } |
| 68 }); |
| 69 |
| 70 SadTabViewFactory.recordEvent(showSendFeedbackView, SadTabEvent.DISPLAYE
D); |
49 | 71 |
50 return sadTabView; | 72 return sadTabView; |
51 } | 73 } |
52 | 74 |
53 /** | 75 /** |
54 * Construct and return help message to be displayed on R.id.sad_tab_message
. | 76 * Construct and return help message to be displayed on R.id.sad_tab_message
. |
55 * @param context Context of the resulting Sad Tab view. This is needed to l
oad the strings. | 77 * @param context Context of the resulting Sad Tab view. This is needed to l
oad the strings. |
56 * @param suggestionAction Action to be executed when user clicks "try these
suggestions". | 78 * @param suggestionAction Action to be executed when user clicks "try these
suggestions" |
| 79 * or "learn more". |
57 * @return Help message to be displayed on R.id.sad_tab_message. | 80 * @return Help message to be displayed on R.id.sad_tab_message. |
58 */ | 81 */ |
59 private static CharSequence getHelpMessage( | 82 private static CharSequence getHelpMessage( |
60 Context context, final OnClickListener suggestionAction) { | 83 Context context, final Runnable suggestionAction, final boolean show
SendFeedback) { |
61 String helpMessage = context.getString(R.string.sad_tab_message) | 84 NoUnderlineClickableSpan linkSpan = new NoUnderlineClickableSpan() { |
62 + "\n\n" + context.getString(R.string.sad_tab_suggestions); | |
63 NoUnderlineClickableSpan span = new NoUnderlineClickableSpan() { | |
64 @Override | 85 @Override |
65 public void onClick(View view) { | 86 public void onClick(View view) { |
66 suggestionAction.onClick(view); | 87 SadTabViewFactory.recordEvent(showSendFeedback, SadTabEvent.HELP
_LINK_CLICKED); |
| 88 suggestionAction.run(); |
67 } | 89 } |
68 }; | 90 }; |
69 return SpanApplier.applySpans(helpMessage, new SpanInfo("<link>", "</lin
k>", span)); | 91 |
| 92 if (showSendFeedback) { |
| 93 SpannableString learnMoreLink = |
| 94 new SpannableString(context.getString(R.string.sad_tab_reloa
d_learn_more)); |
| 95 learnMoreLink.setSpan(linkSpan, 0, learnMoreLink.length(), 0); |
| 96 return learnMoreLink; |
| 97 } else { |
| 98 String helpMessage = context.getString(R.string.sad_tab_message) + "
\n\n" |
| 99 + context.getString(R.string.sad_tab_suggestions); |
| 100 return SpanApplier.applySpans(helpMessage, new SpanInfo("<link>", "<
/link>", linkSpan)); |
| 101 } |
| 102 } |
| 103 |
| 104 /** |
| 105 * Initializes the TextViews that display tips for handling repeated crashes
. |
| 106 * @param context Context of the resulting Sad Tab view. |
| 107 * @param sadTabView The parent Sad Tab view that contains the TextViews. |
| 108 */ |
| 109 private static void intializeSuggestionsViews(Context context, View sadTabVi
ew) { |
| 110 TextView suggestionsTitle = |
| 111 (TextView) sadTabView.findViewById(R.id.sad_tab_suggestions_titl
e); |
| 112 suggestionsTitle.setVisibility(View.VISIBLE); |
| 113 suggestionsTitle.setText(R.string.sad_tab_reload_try); |
| 114 |
| 115 TextView suggestions = (TextView) sadTabView.findViewById(R.id.sad_tab_s
uggestions); |
| 116 suggestions.setVisibility(View.VISIBLE); |
| 117 suggestions.setText( |
| 118 new SpannableStringBuilder() |
| 119 .append(generateBulletedString( |
| 120 context, R.string.sad_tab_reload_close_notabs)) |
| 121 .append("\n") |
| 122 .append(generateBulletedString(context, R.string.sad_tab
_reload_incognito)) |
| 123 .append("\n") |
| 124 .append(generateBulletedString( |
| 125 context, R.string.sad_tab_reload_restart_browser
)) |
| 126 .append("\n") |
| 127 .append(generateBulletedString( |
| 128 context, R.string.sad_tab_reload_restart_device)
) |
| 129 .append("\n")); |
| 130 } |
| 131 |
| 132 /** |
| 133 * Generates a bulleted {@link SpannableString}. |
| 134 * @param context The {@link Context} used to retrieve the String. |
| 135 * @param stringResId The resource id of the String to bullet. |
| 136 * @return A {@link SpannableString} with a bullet in front of the provided
String. |
| 137 */ |
| 138 private static SpannableString generateBulletedString(Context context, int s
tringResId) { |
| 139 SpannableString bullet = new SpannableString(context.getString(stringRes
Id)); |
| 140 bullet.setSpan(new SadTabBulletSpan(context), 0, bullet.length(), 0); |
| 141 return bullet; |
| 142 } |
| 143 |
| 144 /** |
| 145 * Records enumerated histograms for {@link SadTabEvent}. |
| 146 * @param sendFeedbackView Whether the event is for the "send feedback" vers
ion of the Sad Tab. |
| 147 * @param event The {@link SadTabEvent} to record. |
| 148 */ |
| 149 private static void recordEvent(boolean sendFeedbackView, int event) { |
| 150 if (sendFeedbackView) { |
| 151 RecordHistogram.recordEnumeratedHistogram( |
| 152 "Tabs.SadTab.Feedback.Event", event, SadTabEvent.MAX_SAD_TAB
_EVENT); |
| 153 } else { |
| 154 RecordHistogram.recordEnumeratedHistogram( |
| 155 "Tabs.SadTab.Reload.Event", event, SadTabEvent.MAX_SAD_TAB_E
VENT); |
| 156 } |
| 157 } |
| 158 |
| 159 private static class SadTabBulletSpan extends BulletSpan { |
| 160 private int mXOffset; |
| 161 |
| 162 public SadTabBulletSpan(Context context) { |
| 163 super(context.getResources().getDimensionPixelSize(R.dimen.sad_tab_b
ullet_gap)); |
| 164 mXOffset = context.getResources().getDimensionPixelSize( |
| 165 R.dimen.sad_tab_bullet_leading_offset); |
| 166 } |
| 167 |
| 168 @Override |
| 169 public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top
, int baseline, |
| 170 int bottom, CharSequence text, int start, int end, boolean first
, Layout l) { |
| 171 // Android cuts off the bullet points. Adjust the x-position so that
the bullets aren't |
| 172 // cut off. |
| 173 super.drawLeadingMargin( |
| 174 c, p, x + mXOffset, dir, top, baseline, bottom, text, start,
end, first, l); |
| 175 } |
70 } | 176 } |
71 } | 177 } |
OLD | NEW |