Index: chrome/android/java/src/org/chromium/chrome/browser/tab/SadTabViewFactory.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/SadTabViewFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/SadTabViewFactory.java |
index 71204a5c8c04b203ec143cb51d04099ab9830fcc..de06b07b7cd48e44aa3e27e8f1bac33c84199f4a 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/SadTabViewFactory.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/SadTabViewFactory.java |
@@ -5,45 +5,73 @@ |
package org.chromium.chrome.browser.tab; |
import android.content.Context; |
-import android.support.annotation.StringRes; |
+import android.graphics.Canvas; |
+import android.graphics.Paint; |
+import android.support.annotation.IntDef; |
+import android.text.Layout; |
+import android.text.SpannableString; |
+import android.text.TextUtils; |
import android.text.method.LinkMovementMethod; |
+import android.text.style.BulletSpan; |
import android.view.LayoutInflater; |
import android.view.View; |
import android.view.View.OnClickListener; |
import android.widget.Button; |
import android.widget.TextView; |
+import org.chromium.base.metrics.RecordHistogram; |
import org.chromium.chrome.R; |
import org.chromium.ui.text.NoUnderlineClickableSpan; |
import org.chromium.ui.text.SpanApplier; |
import org.chromium.ui.text.SpanApplier.SpanInfo; |
+import java.lang.annotation.Retention; |
+import java.lang.annotation.RetentionPolicy; |
+ |
/** |
* A factory class for creating the "Sad Tab" view, which is shown in place of a crashed renderer. |
*/ |
public class SadTabViewFactory { |
+ // This IntDef backs an UMA histogram, so it should be treated as append-only. |
+ // A native counterpart exists in sad_tab.cc. |
+ @IntDef({SAD_TAB_EVENT_DISPLAYED, SAD_TAB_EVENT_BUTTON_CLICKED, |
Ted C
2017/05/10 15:59:46
can we generate the enum in java from the c++ side
Theresa
2017/05/10 18:20:22
Done.
|
+ SAD_TAB_EVENT_HELP_LINK_CLICKED}) |
+ @Retention(RetentionPolicy.SOURCE) |
+ public @interface SadTabEvent {} |
+ public static final int SAD_TAB_EVENT_DISPLAYED = 0; |
+ public static final int SAD_TAB_EVENT_BUTTON_CLICKED = 1; |
+ public static final int SAD_TAB_EVENT_HELP_LINK_CLICKED = 2; |
+ private static final int MAX_SAD_TAB_EVENT = 3; |
/** |
* @param context Context of the resulting Sad Tab view. |
* @param suggestionAction Action to be executed when user clicks "try these suggestions". |
* @param reloadButtonAction Action to be executed when Reload button is pressed. |
* (e.g., refreshing the page) |
- * @param buttonTextId The string resource for the button text label. |
+ * @param showSendFeedbackView Whether to show the "send feedback" version of the Sad Tab view. |
* @return A "Sad Tab" view instance which is used in place of a crashed renderer. |
*/ |
- public static View createSadTabView( |
- Context context, final OnClickListener suggestionAction, |
- OnClickListener reloadButtonAction, @StringRes int buttonTextId) { |
+ public static View createSadTabView(Context context, final OnClickListener suggestionAction, |
+ OnClickListener reloadButtonAction, boolean showSendFeedbackView) { |
Ted C
2017/05/10 15:59:46
Seeing that we need to expose the UMA events to be
Theresa
2017/05/10 18:20:21
Done.
|
// Inflate Sad tab and initialize. |
LayoutInflater inflater = (LayoutInflater) context.getSystemService( |
Context.LAYOUT_INFLATER_SERVICE); |
View sadTabView = inflater.inflate(R.layout.sad_tab, null); |
+ TextView titleText = (TextView) sadTabView.findViewById(R.id.sad_tab_title); |
+ int titleTextId = |
+ showSendFeedbackView ? R.string.sad_tab_reload_title : R.string.sad_tab_title; |
+ titleText.setText(titleTextId); |
+ |
+ if (showSendFeedbackView) intializeSuggestionsViews(context, sadTabView); |
+ |
TextView messageText = (TextView) sadTabView.findViewById(R.id.sad_tab_message); |
- messageText.setText(getHelpMessage(context, suggestionAction)); |
+ messageText.setText(getHelpMessage(context, suggestionAction, showSendFeedbackView)); |
messageText.setMovementMethod(LinkMovementMethod.getInstance()); |
Button reloadButton = (Button) sadTabView.findViewById(R.id.sad_tab_reload_button); |
+ int buttonTextId = showSendFeedbackView ? R.string.sad_tab_send_feedback_label |
+ : R.string.sad_tab_reload_label; |
reloadButton.setText(buttonTextId); |
reloadButton.setOnClickListener(reloadButtonAction); |
@@ -53,19 +81,94 @@ public class SadTabViewFactory { |
/** |
* Construct and return help message to be displayed on R.id.sad_tab_message. |
* @param context Context of the resulting Sad Tab view. This is needed to load the strings. |
- * @param suggestionAction Action to be executed when user clicks "try these suggestions". |
+ * @param suggestionAction Action to be executed when user clicks "try these suggestions" |
+ * or "learn more". |
* @return Help message to be displayed on R.id.sad_tab_message. |
*/ |
private static CharSequence getHelpMessage( |
- Context context, final OnClickListener suggestionAction) { |
- String helpMessage = context.getString(R.string.sad_tab_message) |
- + "\n\n" + context.getString(R.string.sad_tab_suggestions); |
- NoUnderlineClickableSpan span = new NoUnderlineClickableSpan() { |
+ Context context, final OnClickListener suggestionAction, boolean showSendFeedback) { |
+ NoUnderlineClickableSpan linkSpan = new NoUnderlineClickableSpan() { |
@Override |
public void onClick(View view) { |
suggestionAction.onClick(view); |
} |
}; |
- return SpanApplier.applySpans(helpMessage, new SpanInfo("<link>", "</link>", span)); |
+ |
+ if (showSendFeedback) { |
+ SpannableString learnMoreLink = |
+ new SpannableString(context.getString(R.string.sad_tab_reload_learn_more)); |
+ learnMoreLink.setSpan(linkSpan, 0, learnMoreLink.length(), 0); |
+ return learnMoreLink; |
+ } else { |
+ String helpMessage = context.getString(R.string.sad_tab_message) + "\n\n" |
+ + context.getString(R.string.sad_tab_suggestions); |
+ return SpanApplier.applySpans(helpMessage, new SpanInfo("<link>", "</link>", linkSpan)); |
+ } |
+ } |
+ |
+ /** |
+ * Initializes the TextViews that display tips for handling repeated crashes. |
+ * @param context Context of the resulting Sad Tab view. |
+ * @param sadTabView The parent Sad Tab view that contains the TextViews. |
+ */ |
+ private static void intializeSuggestionsViews(Context context, View sadTabView) { |
+ TextView suggestionsTitle = |
+ (TextView) sadTabView.findViewById(R.id.sad_tab_suggestions_title); |
+ suggestionsTitle.setVisibility(View.VISIBLE); |
+ suggestionsTitle.setText(R.string.sad_tab_reload_try); |
+ |
+ SpannableString bullet1 = |
Ted C
2017/05/10 15:59:46
I would pull out a helper function that takes just
Theresa
2017/05/10 18:20:22
Done.
|
+ new SpannableString(context.getString(R.string.sad_tab_reload_close_notabs)); |
+ bullet1.setSpan(new SadTabBulletSpan(context), 0, bullet1.length(), 0); |
+ |
+ SpannableString bullet2 = |
+ new SpannableString(context.getString(R.string.sad_tab_reload_incognito)); |
+ bullet2.setSpan(new SadTabBulletSpan(context), 0, bullet2.length(), 0); |
+ |
+ SpannableString bullet3 = |
+ new SpannableString(context.getString(R.string.sad_tab_reload_restart_browser)); |
+ bullet3.setSpan(new SadTabBulletSpan(context), 0, bullet3.length(), 0); |
+ |
+ SpannableString bullet4 = |
+ new SpannableString(context.getString(R.string.sad_tab_reload_restart_device)); |
+ bullet4.setSpan(new SadTabBulletSpan(context), 0, bullet4.length(), 0); |
+ |
+ TextView suggestions = (TextView) sadTabView.findViewById(R.id.sad_tab_suggestions); |
+ suggestions.setVisibility(View.VISIBLE); |
+ suggestions.setText( |
+ TextUtils.concat(bullet1, "\n", bullet2, "\n", bullet3, "\n", bullet4, "\n")); |
+ } |
+ |
+ /** |
+ * Records enumerated histograms for {@link SadTabEvent}. |
+ * @param sendFeedbackView Whether the event is for the "send feedback" version of the Sad Tab. |
+ * @param event The {@link SadTabEvent} to record. |
+ */ |
+ public static void recordEvent(boolean sendFeedbackView, @SadTabEvent int event) { |
+ if (sendFeedbackView) { |
+ RecordHistogram.recordEnumeratedHistogram( |
+ "Tabs.SadTab.Feedback.Event", event, MAX_SAD_TAB_EVENT); |
+ } else { |
+ RecordHistogram.recordEnumeratedHistogram( |
+ "Tabs.SadTab.Reload.Event", event, MAX_SAD_TAB_EVENT); |
+ } |
+ } |
+ |
+ private static class SadTabBulletSpan extends BulletSpan { |
+ private int mXOffset; |
+ |
+ public SadTabBulletSpan(Context context) { |
+ super(context.getResources().getDimensionPixelSize(R.dimen.sad_tab_gap)); |
+ mXOffset = context.getResources().getDimensionPixelSize(R.dimen.sad_tab_leading_offset); |
+ } |
+ |
+ @Override |
+ public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, |
+ int bottom, CharSequence text, int start, int end, boolean first, Layout l) { |
+ // Android cuts off the bullet points. Adjust the x-position so that the bullets aren't |
Ted C
2017/05/10 15:59:46
WAH?! sadness
|
+ // cut off. |
+ super.drawLeadingMargin( |
+ c, p, x + mXOffset, dir, top, baseline, bottom, text, start, end, first, l); |
+ } |
} |
} |