7272import org .mozilla .vrbrowser .utils .ServoUtils ;
7373import org .mozilla .vrbrowser .utils .SystemUtils ;
7474
75+ import java .io .BufferedReader ;
76+ import java .io .File ;
77+ import java .io .FileInputStream ;
7578import java .io .IOException ;
79+ import java .io .InputStreamReader ;
7680import java .net .URISyntaxException ;
81+ import java .nio .charset .StandardCharsets ;
82+ import java .util .ArrayList ;
7783import java .util .Arrays ;
7884import java .util .HashMap ;
7985import java .util .HashSet ;
@@ -88,7 +94,7 @@ public class VRBrowserActivity extends PlatformActivity implements WidgetManager
8894 public void onReceive (Context context , Intent intent ) {
8995 if (intent .getAction ().equals (CrashReporterService .CRASH_ACTION )) {
9096 Intent crashIntent = intent .getParcelableExtra (CrashReporterService .DATA_TAG );
91- handleCrashIntent (crashIntent );
97+ handleContentCrashIntent (crashIntent );
9298 }
9399 }
94100 };
@@ -113,6 +119,7 @@ public void run() {
113119 static final int GestureSwipeRight = 1 ;
114120 static final int SwipeDelay = 1000 ; // milliseconds
115121 static final long RESET_CRASH_COUNT_DELAY = 5000 ;
122+ static final String CRASH_STATS_URL = "https://crash-stats.mozilla.com/report/index/" ;
116123
117124 static final String LOGTAG = SystemUtils .createLogtag (VRBrowserActivity .class );
118125 HashMap <Integer , Widget > mWidgets ;
@@ -255,6 +262,7 @@ protected void onCreate(Bundle savedInstanceState) {
255262
256263 mConnectivityReceiver = new ConnectivityReceiver ();
257264 mPoorPerformanceWhiteList = new HashSet <>();
265+ checkForCrash ();
258266 }
259267
260268 protected void initializeWidgets () {
@@ -420,7 +428,7 @@ protected void onNewIntent(final Intent intent) {
420428 loadFromIntent (intent );
421429 }
422430 } else if (GeckoRuntime .ACTION_CRASHED .equals (intent .getAction ())) {
423- handleCrashIntent ( intent );
431+ Log . e ( LOGTAG , "Restarted after a crash" );
424432 }
425433 }
426434
@@ -433,7 +441,7 @@ public void onConfigurationChanged(Configuration newConfig) {
433441
434442 void loadFromIntent (final Intent intent ) {
435443 if (GeckoRuntime .ACTION_CRASHED .equals (intent .getAction ())) {
436- handleCrashIntent ( intent );
444+ Log . e ( LOGTAG , "Loading from crash Intent" );
437445 }
438446
439447 Uri uri = intent .getData ();
@@ -481,44 +489,104 @@ private void handleConnectivityChange() {
481489 mConnectionAvailable = connected ;
482490 }
483491
484- private void handleCrashIntent (@ NonNull final Intent intent ) {
485- Log .e (LOGTAG , "======> Got crashed intent" );
486- Log .d (LOGTAG , "======> Dump File: " +
487- intent .getStringExtra (GeckoRuntime .EXTRA_MINIDUMP_PATH ));
488- Log .d (LOGTAG , "======> Extras File: " +
489- intent .getStringExtra (GeckoRuntime .EXTRA_EXTRAS_PATH ));
490- Log .d (LOGTAG , "======> Fatal: " +
491- intent .getBooleanExtra (GeckoRuntime .EXTRA_CRASH_FATAL , false ));
492-
492+ private void checkForCrash () {
493+ final ArrayList <String > files = CrashReporterService .findCrashFiles (getBaseContext ());
494+ if (files .isEmpty ()) {
495+ Log .d (LOGTAG , "No crash files found." );
496+ return ;
497+ }
493498 boolean isCrashReportingEnabled = SettingsStore .getInstance (this ).isCrashReportingEnabled ();
494499 if (isCrashReportingEnabled ) {
495- sendCrashData (intent );
496-
500+ postCrashFiles (files );
497501 } else {
498502 if (mCrashDialog == null ) {
499503 mCrashDialog = new CrashDialogWidget (this );
500- mCrashDialog .setCrashDialogDelegate (() -> sendCrashData (intent ));
501504 }
505+ mCrashDialog .setCrashDialogDelegate (
506+ new CrashDialogWidget .CrashDialogDelegate () {
507+ @ Override
508+ public void onSendData () {
509+ postCrashFiles (files );
510+ }
502511
512+ @ Override
513+ public void onDoNotSendData () {
514+ for (String file : files ) {
515+ Log .e (LOGTAG , "Deleting crashfile: " + file );
516+ getBaseContext ().deleteFile (file );
517+ }
518+ }
519+ }
520+ );
503521 mCrashDialog .show (UIWidget .REQUEST_FOCUS );
504522 }
505523 }
506524
507- private void sendCrashData (final Intent intent ) {
525+ private void handleContentCrashIntent (@ NonNull final Intent intent ) {
526+ Log .e (LOGTAG , "Got content crashed intent" );
527+ final String dumpFile = intent .getStringExtra (GeckoRuntime .EXTRA_MINIDUMP_PATH );
528+ final String extraFile = intent .getStringExtra (GeckoRuntime .EXTRA_EXTRAS_PATH );
529+ Log .d (LOGTAG , "Dump File: " + dumpFile );
530+ Log .d (LOGTAG , "Extras File: " + extraFile );
531+ Log .d (LOGTAG , "Fatal: " + intent .getBooleanExtra (GeckoRuntime .EXTRA_CRASH_FATAL , false ));
532+
533+ boolean isCrashReportingEnabled = SettingsStore .getInstance (this ).isCrashReportingEnabled ();
534+ if (isCrashReportingEnabled ) {
535+ postCrashFiles (dumpFile , extraFile );
536+ } else {
537+ if (mCrashDialog == null ) {
538+ mCrashDialog = new CrashDialogWidget (this );
539+ }
540+ mCrashDialog .setCrashDialogDelegate (() -> postCrashFiles (dumpFile , extraFile ));
541+ mCrashDialog .show (UIWidget .REQUEST_FOCUS );
542+ }
543+ }
544+
545+ private void sendCrashFiles (@ NonNull final String aDumpFile , @ NonNull final String aExtraFile ) {
546+ try {
547+ GeckoResult <String > result = CrashReporter .sendCrashReport (VRBrowserActivity .this , new File (aDumpFile ), new File (aExtraFile ), getString (R .string .crash_app_name ));
548+
549+ result .accept (crashID -> {
550+ Log .e (LOGTAG , "Submitted crash report id: " + crashID );
551+ Log .e (LOGTAG , "Report available at: " + CRASH_STATS_URL + crashID );
552+ }, ex -> {
553+ Log .e (LOGTAG , "Failed to submit crash report: " + (ex != null ? ex .getMessage () : "Exception is NULL" ));
554+ });
555+ } catch (IOException | URISyntaxException e ) {
556+ Log .e (LOGTAG , "Failed to send crash report: " + e .toString ());
557+ }
558+ }
559+
560+ private void postCrashFiles (@ NonNull final String aDumpFile , @ NonNull final String aExtraFile ) {
508561 ThreadUtils .postToBackgroundThread (() -> {
509- try {
510- GeckoResult <String > result = CrashReporter .sendCrashReport (VRBrowserActivity .this , intent , getString (R .string .crash_app_name ));
511-
512- result .then (crashID -> {
513- Log .e (LOGTAG , "Submitted crash report id: " + crashID );
514- Log .e (LOGTAG , "Report available at: https://crash-stats.mozilla.com/report/index/" + crashID );
515- return null ;
516- }, (GeckoResult .OnExceptionListener <Void >) ex -> {
517- Log .e (LOGTAG , "Failed to submit crash report: " + ex .getMessage ());
518- return null ;
519- });
520- } catch (IOException | URISyntaxException e ) {
521- Log .e (LOGTAG , "Failed to send crash report: " + e .toString ());
562+ sendCrashFiles (aDumpFile , aExtraFile );
563+ });
564+ }
565+
566+ private void postCrashFiles (final ArrayList <String > aFiles ) {
567+ ThreadUtils .postToBackgroundThread (() -> {
568+ for (String file : aFiles ) {
569+ try {
570+ ArrayList <String > list = new ArrayList <>(2 );
571+ try (FileInputStream in = getBaseContext ().openFileInput (file )) {
572+ try (BufferedReader br = new BufferedReader (new InputStreamReader (in , StandardCharsets .UTF_8 ))) {
573+ String line ;
574+ while ((line = br .readLine ()) != null ) {
575+ list .add (line );
576+ }
577+ }
578+ } catch (IOException e ) {
579+ e .printStackTrace ();
580+ }
581+ if (list .size () < 2 ) {
582+ Log .e (LOGTAG , "Failed read crash dump file names from: " + file );
583+ return ;
584+ }
585+ sendCrashFiles (list .get (0 ), list .get (1 ));
586+ } finally {
587+ Log .d (LOGTAG ,"Removing crash file: " + file );
588+ getBaseContext ().deleteFile (file );
589+ }
522590 }
523591 });
524592 }
0 commit comments