content: package fuzion24.device.vulnerability.test.ui;
  
  import android.Manifest;
  import android.content.Intent;
  import android.content.pm.PackageManager;
  import android.content.res.Configuration;
  import android.graphics.Color;
  import android.net.Uri;
  import android.os.Bundle;
  import android.support.design.widget.CoordinatorLayout;
  import android.support.design.widget.FloatingActionButton;
  import android.support.design.widget.Snackbar;
  import android.support.v4.app.ActivityCompat;
  import android.support.v4.content.ContextCompat;
  import android.support.v7.app.AppCompatActivity;
  import android.support.v7.widget.LinearLayoutManager;
  import android.support.v7.widget.RecyclerView;
  import android.support.v7.widget.Toolbar;
  import android.util.Log;
  import android.view.Menu;
  import android.view.MenuItem;
  import android.view.View;
  import android.widget.TextView;
  
  import com.afollestad.materialdialogs.DialogAction;
  import com.afollestad.materialdialogs.MaterialDialog;
  import com.evernote.android.job.JobManager;
  import com.evernote.android.job.JobRequest;
  import com.nowsecure.android.vts.R;
  
  import org.json.JSONException;
  import org.json.JSONObject;
  
  import java.util.ArrayList;
  import java.util.List;
  import java.util.concurrent.TimeUnit;
  
  import fuzion24.device.vulnerability.test.ResultsCallback;
  import fuzion24.device.vulnerability.test.ShareViaGoogleForm;
  import fuzion24.device.vulnerability.test.VulnerabilityTestResult;
  import fuzion24.device.vulnerability.test.VulnerabilityTestRunner;
  import fuzion24.device.vulnerability.test.adapter.RecyclerAdapter;
  import fuzion24.device.vulnerability.test.job.AndroidVTSJobCreator;
  import fuzion24.device.vulnerability.test.job.CheckForUpdatesJob;
  import fuzion24.device.vulnerability.util.DeviceInfo;
  import fuzion24.device.vulnerability.util.SharedPreferencesUtils;
  import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityResultSerialzier;
  
  public class MainActivity extends AppCompatActivity {
  
      private static final String SERIALIZABLE_RESULTS = "SERIALIZABLE_RESULTS";
  
      private static final String TAG = "VULN_TEST";
  
      private static final int CREATE_CHECK_FOR_UPDATES_JOB = 1;
      private static final int CHECK_FOR_UPDATES = 2;
  
      private DeviceInfo devInfo;
      private ArrayList<VulnerabilityTestResult> testResults;
      private TextView emptyView;
      private CoordinatorLayout coordinatorLayout;
      private RecyclerAdapter recyclerAdapter;
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
  
          Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
          toolbar.setTitleTextColor(Color.WHITE);
          setSupportActionBar(toolbar);
          getSupportActionBar().setTitle(R.string.app_name);
  
          if (savedInstanceState != null && savedInstanceState.containsKey(SERIALIZABLE_RESULTS)) {
              testResults = (ArrayList<VulnerabilityTestResult>) savedInstanceState.getSerializable(SERIALIZABLE_RESULTS);
          } else {
              testResults = new ArrayList<>();
          }
  
          RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
          coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
          emptyView = (TextView) findViewById(R.id.emptyView);
          recyclerAdapter = new RecyclerAdapter(MainActivity.this, testResults);
  
          recyclerView.setLayoutManager(new LinearLayoutManager(MainActivity.this));
          recyclerView.setAdapter(recyclerAdapter);
  
          final TextView tvKernelVersion = (TextView) findViewById(R.id.kernelVersion);
          final TextView tvBuildFingerPrint = (TextView) findViewById(R.id.buildFingerPrint);
          final TextView tvBuildID = (TextView) findViewById(R.id.buildID);
          final TextView tvBuildBrand = (TextView) findViewById(R.id.buildBrand);
          final TextView tvBuildManuf = (TextView) findViewById(R.id.buildManufacturer);
          final TextView tvBuildModel = (TextView) findViewById(R.id.buildModel);
          final TextView tvBuildRelease = (TextView) findViewById(R.id.buildRelease);
          final TextView tvBuildSDK = (TextView) findViewById(R.id.buildSDK);
          final TextView tvBuildABIList = (TextView) findViewById(R.id.buildABIList);
  
          devInfo = DeviceInfo.getDeviceInfo();
  
          tvBuildFingerPrint.setText(devInfo.getBuildFingerPrint());
          tvBuildID.setText(devInfo.getBuildID());
          tvKernelVersion.setText(devInfo.getKernelVersion());
          tvBuildBrand.setText(devInfo.getBuildBrand());
          tvBuildManuf.setText(devInfo.getBuildManufacturer());
          tvBuildModel.setText(devInfo.getBuildModel());
          tvBuildRelease.setText(devInfo.getBuildRelease());
          tvBuildSDK.setText(devInfo.getBuildSDK());
  
          StringBuilder sb = new StringBuilder();
  
          for (String s : devInfo.getSupportedABIS()) {
              sb.append(s);
              sb.append(" ");
          }
  
          tvBuildABIList.setText(sb.toString());
  
          FloatingActionButton fabStart = (FloatingActionButton) findViewById(R.id.fabStart);
  
          fabStart.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  runTestsSuit();
              }
          });
  
          // Creates the jobs to check for updates.
          JobManager.instance().cancelAllForTag(CheckForUpdatesJob.TAG);
  
          if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                  == PackageManager.PERMISSION_GRANTED) {
              createCheckForUpdatesJob();
          } else {
              ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                  CREATE_CHECK_FOR_UPDATES_JOB);
          }
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          getMenuInflater().inflate(R.menu.main_menu, menu);
  
          menu.getItem(2).setChecked(SharedPreferencesUtils.isAutomaticSharingEnable(MainActivity.this));
  
          return true;
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          int itemId = item.getItemId();
  
          switch (itemId) {
              case R.id.menu_export_results:
              case R.id.menu_share_results:
                  if (testResults == null || testResults.isEmpty()) {
                      Snackbar.make(coordinatorLayout, R.string.run_tests, Snackbar.LENGTH_LONG).setAction(R.string.start, new View.OnClickListener() {
                          @Override
                          public void onClick(View v) {
                              runTestsSuit();
                          }
  
                      }).show();
  
                      return true;
                  }
  
                  Intent intent = null;
                  try {
                      JSONObject json = VulnerabilityResultSerialzier.serializeResultsToJson(testResults, devInfo);
                      if (itemId == R.id.menu_export_results) {
                          intent = new Intent(Intent.ACTION_SEND);
                          intent.setType("text/plain");
                          intent.putExtra(Intent.EXTRA_SUBJECT, "Android VTS Results");
                          intent.putExtra(Intent.EXTRA_TEXT, json.toString(4));
                      } else if (itemId == R.id.menu_share_results) {
                          Uri formUri = new ShareViaGoogleForm(json).buildUri();
                          intent = new Intent(Intent.ACTION_VIEW, formUri);
                      }
                  } catch (JSONException e) {
                      Log.d(TAG, "Json exception: " + e.getMessage());
                      Snackbar.make(coordinatorLayout, R.string.error_exporting_results, Snackbar.LENGTH_LONG).show();
                  }
  
                  if (intent != null) {
                      startActivity(Intent.createChooser(intent, getString(R.string.share_results_via)));
                  }
  
                  return true;
  
              case R.id.menu_automatic_share_results:
                  new MaterialDialog.Builder(this)
                      .title(R.string.dialog_automatic_sharing_title)
                      .content(R.string.dialog_automatic_sharing_description)
                      .positiveText(R.string.global_sharing)
                      .negativeText(R.string.global_notsharing)
                      .onPositive(new MaterialDialog.SingleButtonCallback() {
                          @Override
                          public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                              SharedPreferencesUtils.setIsAutomaticSharingEnable(MainActivity.this, true);
                          }
                      })
                      .onNegative(new MaterialDialog.SingleButtonCallback() {
                          @Override
                          public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                              SharedPreferencesUtils.setIsAutomaticSharingEnable(MainActivity.this, false);
                          }
                      })
                      .onAny(new MaterialDialog.SingleButtonCallback() {
                          @Override
                          public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                              invalidateOptionsMenu();
                          }
                      })
                      .show();
  
                  return true;
  
              case R.id.menu_check_updates:
                  if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
                          == PackageManager.PERMISSION_GRANTED) {
                      checkForUpdates();
                  } else {
                      ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                          CHECK_FOR_UPDATES);
                  }
  
                  return true;
  
              case R.id.menu_opensource_licences:
                  Intent mainIntent = new Intent(MainActivity.this, OpenSourceLicencesActivity.class);
                  startActivity(mainIntent);
  
                  return true;
  
              default:
                  return super.onOptionsItemSelected(item);
          }
      }
  
      private void runTestsSuit() {
          new VulnerabilityTestRunner(MainActivity.this, true, new ResultsCallback() {
              @Override
              public void finished(final List<VulnerabilityTestResult> results) {
                  Log.d(TAG, "Device Vulnerability callback, finished");
  
                  testResults.clear();
                  testResults.addAll(results);
  
                  emptyView.setVisibility(View.GONE);
                  recyclerAdapter.updateResults(results);
  
                  showScanResume(results);
              }
          }).execute();
      }
  
      private void showScanResume(final List<VulnerabilityTestResult> results) {
          int numberOfFailed = 0;
  
          for (VulnerabilityTestResult result : results) {
              if (result.getException() != null) {
                  continue;
              }
  
              if (result.isVulnerable()) {
                  numberOfFailed++;
              }
          }
  
          MaterialDialog.Builder dialogBuilder = new MaterialDialog.Builder(this)
              .title(R.string.scan_details)
              .customView(R.layout.dialog_scan_details_layout, true)
              .positiveText(R.string.dismiss)
              .onAny(new MaterialDialog.SingleButtonCallback() {
                  @Override
                  public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                      if (SharedPreferencesUtils.isAutomaticSharingEnable(MainActivity.this)) {
                          try {
                              JSONObject json = VulnerabilityResultSerialzier.serializeResultsToJson(testResults, devInfo);
  
                              Uri formUri = new ShareViaGoogleForm(json).buildUri();
                              Intent intent = new Intent(Intent.ACTION_VIEW, formUri);
  
                              startActivity(Intent.createChooser(intent, getString(R.string.share_results_via)));
                          } catch (JSONException exception) {
                              exception.printStackTrace();
                          }
                      }
                  }
              });
  
          if (numberOfFailed > 0) {
              dialogBuilder.negativeText(R.string.my_device_is_vulnerable_info)
                  .onNegative(new MaterialDialog.SingleButtonCallback() {
                      @Override
                      public void onClick(MaterialDialog materialDialog, DialogAction dialogAction) {
                          Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.nowsecure.com/blog/2015/11/18/my-device-is-vulnerable-now-what/"));
                          startActivity(browserIntent);
                      }
                  });
          }
  
          View view = dialogBuilder.show().getCustomView();
  
          TextView state = (TextView) view.findViewById(R.id.scan_details_device_state);
          if (numberOfFailed > 0) {
              state.setText(R.string.scan_details_vulnerable_message);
              state.setTextColor(getResources().getColor(R.color.red));
          } else {
              state.setText(R.string.scan_details_secure_message);
              state.setTextColor(getResources().getColor(R.color.green));
          }
  
          TextView numberOfTests = (TextView) view.findViewById(R.id.scan_details_number_tests);
          numberOfTests.setText(String.valueOf(results.size()));
  
          TextView numberOfFailedTests = (TextView) view.findViewById(R.id.scan_details_failed_tests);
          numberOfFailedTests.setText(String.valueOf(numberOfFailed));
      }
  
      private void createCheckForUpdatesJob() {
          new JobRequest.Builder(CheckForUpdatesJob.TAG)
              .setPeriodic(TimeUnit.DAYS.toMillis(7))
              .setRequirementsEnforced(true)
              .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
              .setPersisted(true)
              .build()
              .schedule();
      }
  
      private void checkForUpdates() {
          final MaterialDialog progressDialog = new MaterialDialog.Builder(this)
              .title(R.string.loading)
              .content(R.string.checking_updates)
              .cancelable(false)
              .progress(true, 0)
              .show();
  
          CheckForUpdatesJob.checkForUpdates(this, progressDialog);
      }
  
      @Override
      public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
          switch (requestCode) {
              case CREATE_CHECK_FOR_UPDATES_JOB:
                  if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                      createCheckForUpdatesJob();
                  }
                  break;
  
              case CHECK_FOR_UPDATES:
                  if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                      checkForUpdates();
                  }
                  break;
          }
      }
  
      @Override
      public void onConfigurationChanged(Configuration newConfig) {
          super.onConfigurationChanged(newConfig);
      }
  
      @Override
      protected void onSaveInstanceState(final Bundle outState) {
          outState.putSerializable(SERIALIZABLE_RESULTS, testResults);
      }
  
  }
  