tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

UnhandledExceptionHandler.java (3089B)


      1 /*
      2 *  Copyright 2013 The WebRTC Project Authors. All rights reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 package org.appspot.apprtc;
     12 
     13 import android.app.Activity;
     14 import android.app.AlertDialog;
     15 import android.content.DialogInterface;
     16 import android.util.Log;
     17 import android.util.TypedValue;
     18 import android.widget.ScrollView;
     19 import android.widget.TextView;
     20 
     21 import java.io.PrintWriter;
     22 import java.io.StringWriter;
     23 
     24 /**
     25 * Singleton helper: install a default unhandled exception handler which shows
     26 * an informative dialog and kills the app.  Useful for apps whose
     27 * error-handling consists of throwing RuntimeExceptions.
     28 * NOTE: almost always more useful to
     29 * Thread.setDefaultUncaughtExceptionHandler() rather than
     30 * Thread.setUncaughtExceptionHandler(), to apply to background threads as well.
     31 */
     32 public class UnhandledExceptionHandler implements Thread.UncaughtExceptionHandler {
     33  private static final String TAG = "AppRTCMobileActivity";
     34  private final Activity activity;
     35 
     36  public UnhandledExceptionHandler(final Activity activity) {
     37    this.activity = activity;
     38  }
     39 
     40  @Override
     41  public void uncaughtException(Thread unusedThread, final Throwable e) {
     42    activity.runOnUiThread(new Runnable() {
     43      @Override
     44      public void run() {
     45        String title = "Fatal error: " + getTopLevelCauseMessage(e);
     46        String msg = getRecursiveStackTrace(e);
     47        TextView errorView = new TextView(activity);
     48        errorView.setText(msg);
     49        errorView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 8);
     50        ScrollView scrollingContainer = new ScrollView(activity);
     51        scrollingContainer.addView(errorView);
     52        Log.e(TAG, title + "\n\n" + msg);
     53        DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
     54          @Override
     55          public void onClick(DialogInterface dialog, int which) {
     56            dialog.dismiss();
     57            System.exit(1);
     58          }
     59        };
     60        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
     61        builder.setTitle(title)
     62            .setView(scrollingContainer)
     63            .setPositiveButton("Exit", listener)
     64            .show();
     65      }
     66    });
     67  }
     68 
     69  // Returns the Message attached to the original Cause of `t`.
     70  private static String getTopLevelCauseMessage(Throwable t) {
     71    Throwable topLevelCause = t;
     72    while (topLevelCause.getCause() != null) {
     73      topLevelCause = topLevelCause.getCause();
     74    }
     75    return topLevelCause.getMessage();
     76  }
     77 
     78  // Returns a human-readable String of the stacktrace in `t`, recursively
     79  // through all Causes that led to `t`.
     80  private static String getRecursiveStackTrace(Throwable t) {
     81    StringWriter writer = new StringWriter();
     82    t.printStackTrace(new PrintWriter(writer));
     83    return writer.toString();
     84  }
     85 }