package info.guardianproject.securereaderinterface;
import info.guardianproject.securereader.Settings.UiLanguage;
import info.guardianproject.securereaderinterface.models.LockScreenCallbacks;
import info.guardianproject.securereaderinterface.ui.LayoutFactoryWrapper;
import info.guardianproject.securereaderinterface.uiutil.UIHelpers;
import info.guardianproject.securereaderinterface.widgets.DropdownSpinner;
import info.guardianproject.securereader.SocialReader;
import info.guardianproject.securereaderinterface.R;
import info.guardianproject.cacheword.CacheWordActivityHandler;
import info.guardianproject.cacheword.CacheWordSettings;
import info.guardianproject.cacheword.ICacheWordSubscriber;
import java.security.GeneralSecurityException;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.text.TextUtils;
import android.text.method.PasswordTransformationMethod;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListAdapter;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;
public class LockScreenActivity extends Activity implements LockScreenCallbacks, OnFocusChangeListener, ICacheWordSubscriber
{
private static final String TAG = "LockScreenActivity";
private EditText mEnterPassphrase;
private EditText mNewPassphrase;
private EditText mConfirmNewPassphrase;
private Button mBtnOpen;
private CacheWordActivityHandler mCacheWord;
private info.guardianproject.securereaderinterface.LockScreenActivity.SetUiLanguageReceiver mSetUiLanguageReceiver;
private DropdownSpinner mDropdownLanguage;
private String[] mLanguageNames;
private UiLanguage[] mLanguageCodes;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
CacheWordSettings settings = null;
mCacheWord = new CacheWordActivityHandler(this, settings);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
{
getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE);
}
}
@Override
protected void onResume()
{
super.onResume();
mSetUiLanguageReceiver = new SetUiLanguageReceiver();
registerReceiver(mSetUiLanguageReceiver, new IntentFilter(App.SET_UI_LANGUAGE_BROADCAST_ACTION), App.EXIT_BROADCAST_PERMISSION, null);
}
@Override
protected void onPause() {
super.onPause();
if (mSetUiLanguageReceiver != null)
{
unregisterReceiver(mSetUiLanguageReceiver);
mSetUiLanguageReceiver = null;
}
}
@Override
protected void onStart()
{
super.onStart();
App.getInstance().onLockScreenResumed(this);
mCacheWord.onResume();
}
@Override
protected void onStop()
{
super.onStop();
App.getInstance().onLockScreenPaused(this);
mCacheWord.onPause();
}
@Override
public boolean isInternalActivityOpened()
{
return false;
}
private Bitmap takeSnapshot(View view)
{
if (view.getWidth() == 0 || view.getHeight() == 0)
return null;
view.setDrawingCacheEnabled(true);
Bitmap bmp = view.getDrawingCache();
Bitmap bitmap = Bitmap.createBitmap(bmp, 0, 0, view.getWidth(), view.getHeight()).copy(bmp.getConfig(), false);
view.setDrawingCacheEnabled(false);
return bitmap;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
// Back from lock screen means quit app. So send a kill signal to
// any open activity and finish!
Intent intent = new Intent(App.EXIT_BROADCAST_ACTION);
this.sendOrderedBroadcast(intent, App.EXIT_BROADCAST_PERMISSION, new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
finish();
}
}, null, Activity.RESULT_OK, null, null);
return true;
}
return super.onKeyDown(keyCode, event);
}
private void createFirstTimeView()
{
setContentView(R.layout.activity_lock_screen);
// Passphrase is not set, so allow the user to create one!
//
Button btnCreate = (Button) findViewById(R.id.btnStartCreatePassphrase);
btnCreate.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
createCreatePassphraseView();
}
});
mDropdownLanguage = (DropdownSpinner) findViewById(R.id.languagePopup);
if (App.UI_ENABLE_LANGUAGE_CHOICE)
{
mLanguageNames = new String[] {
getString(R.string.settings_language_english_nt),
getString(R.string.settings_language_tibetan_nt),
getString(R.string.settings_language_chinese_nt),
getString(R.string.settings_language_ukrainian_nt),
getString(R.string.settings_language_russian_nt)
};
mLanguageCodes = new UiLanguage[] {
UiLanguage.English,
UiLanguage.Tibetan,
UiLanguage.Chinese,
UiLanguage.Ukrainian,
UiLanguage.Russian
};
ListAdapter adapter = new LanguageListAdapter(this, mLanguageNames);
mDropdownLanguage.setAdapter(adapter);
selectLanguageByUiLanguage(App.getSettings().uiLanguage(), false);
mDropdownLanguage.setOnSelectionChangedListener(new DropdownSpinner.OnSelectionChangedListener() {
@Override
public void onSelectionChanged(int position) {
App.getSettings().setUiLanguage(mLanguageCodes[position]);
}
});
}
else
{
// Hide language selection!
mDropdownLanguage.setVisibility(View.GONE);
}
}
private boolean selectLanguageByUiLanguage(UiLanguage language, boolean sendNotification)
{
for (int i = 0; i < mLanguageCodes.length; i++)
{
if (mLanguageCodes[i].equals(language))
{
mDropdownLanguage.setCurrentSelection(i, sendNotification);
return true;
}
}
return false;
}
private void createCreatePassphraseView()
{
setContentView(R.layout.lock_screen_create_passphrase);
mNewPassphrase = (EditText) findViewById(R.id.editNewPassphrase);
mConfirmNewPassphrase = (EditText) findViewById(R.id.editConfirmNewPassphrase);
// Passphrase is not set, so allow the user to create one!
//
Button btnCreate = (Button) findViewById(R.id.btnCreate);
btnCreate.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
// Disallow empty fields (user just pressing "create")
if (mNewPassphrase.getText().length() == 0 && mConfirmNewPassphrase.getText().length() == 0)
return;
// Compare the two text fields!
if (!mNewPassphrase.getText().toString().equals(mConfirmNewPassphrase.getText().toString()))
{
Toast.makeText(LockScreenActivity.this, getString(R.string.lock_screen_passphrases_not_matching), Toast.LENGTH_SHORT).show();
mNewPassphrase.setText("");
mConfirmNewPassphrase.setText("");
mNewPassphrase.requestFocus();
return; // Try again...
}
// Store
try {
mCacheWord.setPassphrase(mNewPassphrase.getText().toString().toCharArray());
} catch (GeneralSecurityException e) {
Log.e(TAG, "Cacheword initialization failed: " + e.getMessage());
}
}
});
}
private void createLockView()
{
setContentView(R.layout.lock_screen_return);
View root = findViewById(R.id.llRoot);
root.setOnFocusChangeListener(this);
root.findViewById(R.id.tvError).setVisibility(View.GONE);
mEnterPassphrase = (EditText) findViewById(R.id.editEnterPassphrase);
mEnterPassphrase.setTypeface(Typeface.DEFAULT);
mEnterPassphrase.setTransformationMethod(new PasswordTransformationMethod());
mBtnOpen = (Button) findViewById(R.id.btnOpen);
mBtnOpen.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
if (TextUtils.isEmpty(mEnterPassphrase.getText()))
return;
if (App.getSettings().useKillPassphrase() && mEnterPassphrase.getText().toString().equals(App.getSettings().killPassphrase()))
{
// Kill password entered, wipe!
App.getInstance().wipe(SocialReader.DATA_WIPE);
mEnterPassphrase.setText("");
findViewById(R.id.tvError).setVisibility(View.VISIBLE);
return; // Try again...
}
// Check passphrase
try {
mCacheWord.setPassphrase(mEnterPassphrase.getText().toString().toCharArray());
} catch (GeneralSecurityException e) {
Log.e(TAG, "Cacheword pass verification failed: " + e.getMessage());
int failedAttempts = App.getSettings().currentNumberOfPasswordAttempts();
failedAttempts++;
App.getSettings().setCurrentNumberOfPasswordAttempts(failedAttempts);
if (failedAttempts == App.getSettings().numberOfPasswordAttempts())
{
// Ooops, to many attempts! Wipe the data...
App.getInstance().wipe(SocialReader.DATA_WIPE);
}
mEnterPassphrase.setText("");
findViewById(R.id.tvError).setVisibility(View.VISIBLE);
return; // Try again...
}
App.getSettings().setCurrentNumberOfPasswordAttempts(0);
UIHelpers.hideSoftKeyboard(LockScreenActivity.this);
}
});
mEnterPassphrase.setOnEditorActionListener(new OnEditorActionListener()
{
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_GO)
{
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
Handler threadHandler = new Handler();
imm.hideSoftInputFromWindow(v.getWindowToken(), 0, new ResultReceiver(threadHandler)
{
@Override
protected void onReceiveResult(int resultCode, Bundle resultData)
{
super.onReceiveResult(resultCode, resultData);
mBtnOpen.performClick();
}
});
return true;
}
return false;
}
});
}
@Override
public void onFocusChange(View v, boolean hasFocus)
{
if (hasFocus && !(v instanceof EditText))
{
LockScreenActivity.hideSoftKeyboard(this);
}
}
public static void hideSoftKeyboard(Activity activity)
{
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
@SuppressLint("NewApi")
protected void onUiLanguageChanged()
{
Intent intentThis = getIntent();
intentThis.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
finish();
overridePendingTransition(0, 0);
startActivity(intentThis);
overridePendingTransition(0, 0);
}
@Override
public void onCacheWordUninitialized() {
createFirstTimeView();
}
@Override
public void onCacheWordLocked() {
createLockView();
}
@Override
public void onCacheWordOpened() {
App.getSettings().setCurrentNumberOfPasswordAttempts(0);
Intent intent = (Intent) getIntent().getParcelableExtra("originalIntent");
if (intent == null)
intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bitmap snap = takeSnapshot(((ViewGroup) (getWindow().getDecorView())).getChildAt(0));
App.getInstance().putTransitionBitmap(snap);
startActivity(intent);
finish();
LockScreenActivity.this.overridePendingTransition(0, 0);
}
@Override
public Object getSystemService(String name)
{
if (LAYOUT_INFLATER_SERVICE.equals(name))
{
LayoutInflater mParent = (LayoutInflater) super.getSystemService(name);
LayoutInflater inflater = mParent.cloneInContext(this);
inflater.setFactory(new LayoutFactoryWrapper(this));
return inflater;
}
return super.getSystemService(name);
}
private final class SetUiLanguageReceiver extends BroadcastReceiver
{
@Override
public void onReceive(Context context, Intent intent)
{
new Handler().post(new Runnable()
{
@Override
public void run()
{
onUiLanguageChanged();
}
});
}
}
private class LanguageListAdapter extends ArrayAdapter<String>
{
public LanguageListAdapter(Context context, String[] languages)
{
super(context, R.layout.dropdown_language_item, R.id.tvLanguageName, languages);
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
// User super class to create the View
View v = super.getView(position, convertView, parent);
TextView tv = (TextView) v.findViewById(R.id.tvLanguageName);
tv.setText(getItem(position));
return v;
}
}
public void onUnlocked()
{
App.getSettings().setCurrentNumberOfPasswordAttempts(0);
Intent intent = (Intent) getIntent().getParcelableExtra("originalIntent");
if (intent == null)
intent = new Intent(this, MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
Bitmap snap = takeSnapshot(((ViewGroup) (getWindow().getDecorView())).getChildAt(0));
App.getInstance().putTransitionBitmap(snap);
startActivity(intent);
finish();
LockScreenActivity.this.overridePendingTransition(0, 0);
}
}