| 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..93af2bb344d57a0599afc16fc510a9080ad00e44 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,14 +5,20 @@
|
| 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.text.Layout;
|
| +import android.text.SpannableString;
|
| +import android.text.SpannableStringBuilder;
|
| 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;
|
| @@ -22,30 +28,46 @@ import org.chromium.ui.text.SpanApplier.SpanInfo;
|
| * A factory class for creating the "Sad Tab" view, which is shown in place of a crashed renderer.
|
| */
|
| public class SadTabViewFactory {
|
| -
|
| /**
|
| * @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 suggestionAction {@link Runnable} to be executed when user clicks "try these
|
| + * suggestions".
|
| + * @param buttonAction {@link Runnable} to be executed when the button is pressed.
|
| + * (e.g., refreshing the page or sending feedback)
|
| + * @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 Runnable suggestionAction,
|
| + final Runnable buttonAction, final boolean showSendFeedbackView) {
|
| // 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);
|
| - reloadButton.setText(buttonTextId);
|
| - reloadButton.setOnClickListener(reloadButtonAction);
|
| + Button button = (Button) sadTabView.findViewById(R.id.sad_tab_button);
|
| + int buttonTextId = showSendFeedbackView ? R.string.sad_tab_send_feedback_label
|
| + : R.string.sad_tab_reload_label;
|
| + button.setText(buttonTextId);
|
| + button.setOnClickListener(new OnClickListener() {
|
| + @Override
|
| + public void onClick(View v) {
|
| + SadTabViewFactory.recordEvent(showSendFeedbackView, SadTabEvent.BUTTON_CLICKED);
|
| + buttonAction.run();
|
| + }
|
| + });
|
| +
|
| + SadTabViewFactory.recordEvent(showSendFeedbackView, SadTabEvent.DISPLAYED);
|
|
|
| return sadTabView;
|
| }
|
| @@ -53,19 +75,103 @@ 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 Runnable suggestionAction, final boolean showSendFeedback) {
|
| + NoUnderlineClickableSpan linkSpan = new NoUnderlineClickableSpan() {
|
| @Override
|
| public void onClick(View view) {
|
| - suggestionAction.onClick(view);
|
| + SadTabViewFactory.recordEvent(showSendFeedback, SadTabEvent.HELP_LINK_CLICKED);
|
| + suggestionAction.run();
|
| }
|
| };
|
| - 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);
|
| +
|
| + TextView suggestions = (TextView) sadTabView.findViewById(R.id.sad_tab_suggestions);
|
| + suggestions.setVisibility(View.VISIBLE);
|
| + suggestions.setText(
|
| + new SpannableStringBuilder()
|
| + .append(generateBulletedString(
|
| + context, R.string.sad_tab_reload_close_notabs))
|
| + .append("\n")
|
| + .append(generateBulletedString(context, R.string.sad_tab_reload_incognito))
|
| + .append("\n")
|
| + .append(generateBulletedString(
|
| + context, R.string.sad_tab_reload_restart_browser))
|
| + .append("\n")
|
| + .append(generateBulletedString(
|
| + context, R.string.sad_tab_reload_restart_device))
|
| + .append("\n"));
|
| + }
|
| +
|
| + /**
|
| + * Generates a bulleted {@link SpannableString}.
|
| + * @param context The {@link Context} used to retrieve the String.
|
| + * @param stringResId The resource id of the String to bullet.
|
| + * @return A {@link SpannableString} with a bullet in front of the provided String.
|
| + */
|
| + private static SpannableString generateBulletedString(Context context, int stringResId) {
|
| + SpannableString bullet = new SpannableString(context.getString(stringResId));
|
| + bullet.setSpan(new SadTabBulletSpan(context), 0, bullet.length(), 0);
|
| + return bullet;
|
| + }
|
| +
|
| + /**
|
| + * 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.
|
| + */
|
| + private static void recordEvent(boolean sendFeedbackView, int event) {
|
| + if (sendFeedbackView) {
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Tabs.SadTab.Feedback.Event", event, SadTabEvent.MAX_SAD_TAB_EVENT);
|
| + } else {
|
| + RecordHistogram.recordEnumeratedHistogram(
|
| + "Tabs.SadTab.Reload.Event", event, SadTabEvent.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_bullet_gap));
|
| + mXOffset = context.getResources().getDimensionPixelSize(
|
| + R.dimen.sad_tab_bullet_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
|
| + // cut off.
|
| + super.drawLeadingMargin(
|
| + c, p, x + mXOffset, dir, top, baseline, bottom, text, start, end, first, l);
|
| + }
|
| }
|
| }
|
|
|