Split RemoteServiceActivity into multiple activities

This commit is contained in:
Dominik Schürmann 2016-02-15 13:10:29 +01:00
parent 0b00410123
commit bb997920f5
12 changed files with 489 additions and 385 deletions

View file

@ -283,8 +283,7 @@
<data android:mimeType="text/pgp" />
<!--
This links to attached asc files in AOSP mail. It is deactivated because of
https://github.com/open-keychain/open-keychain/issues/290
This links to attached asc files in AOSP Mail
-->
<data android:mimeType="text/plain" />
</intent-filter>
@ -783,7 +782,7 @@
</intent-filter>
</activity>
<activity
android:name=".ui.ExitActivity"
android:name=".ui.PanicExitActivity"
android:theme="@android:style/Theme.NoDisplay" />
<!-- Internal services/content providers (not exported) -->
@ -807,9 +806,21 @@
android:exported="false"
android:label="@string/keyserver_sync_settings_title" />
<!-- Internal classes of the remote APIs (not exported) -->
<!-- Internal classes of the remote APIs (not exported!) -->
<activity
android:name=".remote.ui.RemoteServiceActivity"
android:name=".remote.ui.RemoteCreateAccountActivity"
android:exported="false"
android:label="@string/app_name" />
<activity
android:name=".remote.ui.RemoteErrorActivity"
android:exported="false"
android:label="@string/app_name" />
<activity
android:name=".remote.ui.RemoteRegisterActivity"
android:exported="false"
android:label="@string/app_name" />
<activity
android:name=".remote.ui.RemoteSelectPubKeyActivity"
android:exported="false"
android:label="@string/app_name" />
<activity
@ -835,8 +846,7 @@
android:exported="false" />
<!-- DEPRECATED service,
using this service may lead to truncated data being returned to the caller
-->
using this service may lead to truncated data being returned to the caller -->
<service
android:name=".remote.OpenPgpService"
android:enabled="true"
@ -864,6 +874,7 @@
<!-- Contact Sync services -->
<service
android:name=".service.DummyAccountService"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="android.accounts.AccountAuthenticator" />
@ -890,6 +901,7 @@
android:resource="@xml/sync_adapter_contacts_structure" />
</service>
<!-- keyserver sync service -->
<service
android:name=".service.KeyserverSyncAdapterService"
android:exported="true"
@ -904,7 +916,8 @@
android:resource="@xml/sync_adapter_keys" />
</service>
<!-- Storage Provider for temporary decrypted files -->
<!-- Storage Provider for temporary decrypted files.
For security considerations, read class! -->
<provider
android:name=".provider.TemporaryFileProvider"
android:authorities="${applicationId}.tempstorage"

View file

@ -40,7 +40,9 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteCreateAccountActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteErrorActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteRegisterActivity;
import org.sufficientlysecure.keychain.util.Log;
@ -94,11 +96,10 @@ public class ApiPermissionHelper {
}
Log.e(Constants.TAG, "Not allowed to use service! return PendingIntent for registration!");
Intent intent = new Intent(mContext, RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_REGISTER);
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_SIGNATURE, packageCertificate);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
Intent intent = new Intent(mContext, RemoteRegisterActivity.class);
intent.putExtra(RemoteRegisterActivity.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RemoteRegisterActivity.EXTRA_PACKAGE_SIGNATURE, packageCertificate);
intent.putExtra(RemoteRegisterActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(mContext, 0,
intent,
@ -114,11 +115,10 @@ public class ApiPermissionHelper {
} catch (WrongPackageCertificateException e) {
Log.e(Constants.TAG, "wrong signature!", e);
Intent intent = new Intent(mContext, RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_ERROR_MESSAGE);
intent.putExtra(RemoteServiceActivity.EXTRA_ERROR_MESSAGE,
Intent intent = new Intent(mContext, RemoteErrorActivity.class);
intent.putExtra(RemoteErrorActivity.EXTRA_ERROR_MESSAGE,
mContext.getString(R.string.api_error_wrong_signature));
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
intent.putExtra(RemoteErrorActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(mContext, 0,
intent,
@ -193,11 +193,10 @@ public class ApiPermissionHelper {
String packageName = getCurrentCallingPackage();
Log.d(Constants.TAG, "getCreateAccountIntent accountName: " + accountName);
Intent intent = new Intent(mContext, RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_CREATE_ACCOUNT);
intent.putExtra(RemoteServiceActivity.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RemoteServiceActivity.EXTRA_ACC_NAME, accountName);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
Intent intent = new Intent(mContext, RemoteCreateAccountActivity.class);
intent.putExtra(RemoteCreateAccountActivity.EXTRA_PACKAGE_NAME, packageName);
intent.putExtra(RemoteCreateAccountActivity.EXTRA_ACC_NAME, accountName);
intent.putExtra(RemoteCreateAccountActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(mContext, 0,
intent,

View file

@ -53,7 +53,7 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.ApiAccounts;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.ui.RemoteServiceActivity;
import org.sufficientlysecure.keychain.remote.ui.RemoteSelectPubKeyActivity;
import org.sufficientlysecure.keychain.remote.ui.SelectAllowedKeysActivity;
import org.sufficientlysecure.keychain.remote.ui.SelectSignKeyIdActivity;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
@ -151,13 +151,12 @@ public class OpenPgpService extends Service {
if (noUserIdsCheck || missingUserIdsCheck || duplicateUserIdsCheck) {
// allow the user to verify pub key selection
Intent intent = new Intent(getBaseContext(), RemoteServiceActivity.class);
intent.setAction(RemoteServiceActivity.ACTION_SELECT_PUB_KEYS);
intent.putExtra(RemoteServiceActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
intent.putExtra(RemoteServiceActivity.EXTRA_NO_USER_IDS_CHECK, noUserIdsCheck);
intent.putExtra(RemoteServiceActivity.EXTRA_MISSING_EMAILS, missingEmails);
intent.putExtra(RemoteServiceActivity.EXTRA_DUPLICATE_EMAILS, duplicateEmails);
intent.putExtra(RemoteServiceActivity.EXTRA_DATA, data);
Intent intent = new Intent(getBaseContext(), RemoteSelectPubKeyActivity.class);
intent.putExtra(RemoteSelectPubKeyActivity.EXTRA_SELECTED_MASTER_KEY_IDS, keyIdsArray);
intent.putExtra(RemoteSelectPubKeyActivity.EXTRA_NO_USER_IDS_CHECK, noUserIdsCheck);
intent.putExtra(RemoteSelectPubKeyActivity.EXTRA_MISSING_EMAILS, missingEmails);
intent.putExtra(RemoteSelectPubKeyActivity.EXTRA_DUPLICATE_EMAILS, duplicateEmails);
intent.putExtra(RemoteSelectPubKeyActivity.EXTRA_DATA, data);
PendingIntent pi = PendingIntent.getActivity(getBaseContext(), 0,
intent,

View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.util.Notify;
public class RemoteCreateAccountActivity extends BaseActivity {
public static final String EXTRA_ACC_NAME = "acc_name";
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String EXTRA_DATA = "data";
private AccountSettingsFragment mAccSettingsFragment;
boolean mUpdateExistingAccount;
@Override
protected void initLayout() {
setContentView(R.layout.api_remote_create_account);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle extras = getIntent().getExtras();
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
final String accName = extras.getString(EXTRA_ACC_NAME);
final ProviderHelper providerHelper = new ProviderHelper(this);
mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById(
R.id.api_account_settings_fragment);
TextView text = (TextView) findViewById(R.id.api_remote_create_account_text);
// update existing?
Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(packageName, accName);
AccountSettings settings = providerHelper.getApiAccountSettings(uri);
if (settings == null) {
// create new account
settings = new AccountSettings(accName);
mUpdateExistingAccount = false;
text.setText(R.string.api_create_account_text);
} else {
// update existing account
mUpdateExistingAccount = true;
text.setText(R.string.api_update_account_text);
}
mAccSettingsFragment.setAccSettings(settings);
// Inflate a "Done"/"Cancel" custom action bar view
setFullScreenDialogDoneClose(R.string.api_settings_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Save
// user needs to select a key if it has explicitly requested (None is only allowed for new accounts)
if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) {
Notify.create(RemoteCreateAccountActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR).show();
} else {
if (mUpdateExistingAccount) {
Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName);
Uri accountUri = baseUri.buildUpon().appendEncodedPath(accName).build();
providerHelper.updateApiAccount(
accountUri,
mAccSettingsFragment.getAccSettings());
} else {
providerHelper.insertApiAccount(
KeychainContract.ApiAccounts.buildBaseUri(packageName),
mAccSettingsFragment.getAccSettings());
}
// give data through for new service call
Intent resultData = extras.getParcelable(EXTRA_DATA);
RemoteCreateAccountActivity.this.setResult(RESULT_OK, resultData);
RemoteCreateAccountActivity.this.finish();
}
}
},
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Cancel
RemoteCreateAccountActivity.this.setResult(RESULT_CANCELED);
RemoteCreateAccountActivity.this.finish();
}
});
}
}

View file

@ -0,0 +1,70 @@
/*
* Copyright (C) 2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.remote.ui;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.view.View;
import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
public class RemoteErrorActivity extends BaseActivity {
public static final String EXTRA_ERROR_MESSAGE = "error_message";
public static final String EXTRA_DATA = "data";
@Override
protected void initLayout() {
setContentView(R.layout.api_remote_error_message);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String errorMessage = getIntent().getStringExtra(EXTRA_ERROR_MESSAGE);
Spannable redErrorMessage = new SpannableString(errorMessage);
redErrorMessage.setSpan(new ForegroundColorSpan(Color.RED), 0, errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
initToolbar();
// Inflate a "Done" custom action bar view
setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
RemoteErrorActivity.this.setResult(RESULT_CANCELED);
RemoteErrorActivity.this.finish();
}
}
);
// set text on view
TextView textView = (TextView) findViewById(R.id.api_app_error_message_text);
textView.setText(redErrorMessage);
}
}

View file

@ -0,0 +1,90 @@
/*
* Copyright (C) 2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.util.Log;
public class RemoteRegisterActivity extends BaseActivity {
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature";
public static final String EXTRA_DATA = "data";
private AppSettingsHeaderFragment mAppSettingsHeaderFragment;
@Override
protected void initLayout() {
setContentView(R.layout.api_remote_register_app);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle extras = getIntent().getExtras();
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName);
final ProviderHelper providerHelper = new ProviderHelper(this);
mAppSettingsHeaderFragment = (AppSettingsHeaderFragment) getSupportFragmentManager().findFragmentById(
R.id.api_app_settings_fragment);
AppSettings settings = new AppSettings(packageName, packageSignature);
mAppSettingsHeaderFragment.setAppSettings(settings);
// Inflate a "Done"/"Cancel" custom action bar view
setFullScreenDialogTwoButtons(
R.string.api_register_allow, R.drawable.ic_check_white_24dp,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Allow
providerHelper.insertApiApp(mAppSettingsHeaderFragment.getAppSettings());
// give data through for new service call
Intent resultData = extras.getParcelable(EXTRA_DATA);
RemoteRegisterActivity.this.setResult(RESULT_OK, resultData);
RemoteRegisterActivity.this.finish();
}
}, R.string.api_register_disallow, R.drawable.ic_close_white_24dp,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Disallow
RemoteRegisterActivity.this.setResult(RESULT_CANCELED);
RemoteRegisterActivity.this.finish();
}
}
);
}
}

View file

@ -0,0 +1,149 @@
/*
* Copyright (C) 2016 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.BulletSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.view.View;
import android.widget.TextView;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import java.util.ArrayList;
public class RemoteSelectPubKeyActivity extends BaseActivity {
public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids";
public static final String EXTRA_MISSING_EMAILS = "missing_emails";
public static final String EXTRA_DUPLICATE_EMAILS = "dublicate_emails";
public static final String EXTRA_NO_USER_IDS_CHECK = "no_user_ids";
public static final String EXTRA_DATA = "data";
// select pub keys view
private SelectPublicKeyFragment mSelectFragment;
@Override
protected void initLayout() {
setContentView(R.layout.api_remote_select_pub_keys);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final Bundle extras = getIntent().getExtras();
long[] selectedMasterKeyIds = getIntent().getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
boolean noUserIdsCheck = getIntent().getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true);
ArrayList<String> missingEmails = getIntent()
.getStringArrayListExtra(EXTRA_MISSING_EMAILS);
ArrayList<String> duplicateEmails = getIntent()
.getStringArrayListExtra(EXTRA_DUPLICATE_EMAILS);
SpannableStringBuilder ssb = new SpannableStringBuilder();
final SpannableString textIntro = new SpannableString(
noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids)
: getString(R.string.api_select_pub_keys_text)
);
textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(textIntro);
if (missingEmails != null && missingEmails.size() > 0) {
ssb.append("\n\n");
ssb.append(getString(R.string.api_select_pub_keys_missing_text));
ssb.append("\n");
for (String emails : missingEmails) {
SpannableString ss = new SpannableString(emails + "\n");
ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(ss);
}
}
if (duplicateEmails != null && duplicateEmails.size() > 0) {
ssb.append("\n\n");
ssb.append(getString(R.string.api_select_pub_keys_dublicates_text));
ssb.append("\n");
for (String email : duplicateEmails) {
SpannableString ss = new SpannableString(email + "\n");
ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(ss);
}
}
// Inflate a "Done"/"Cancel" custom action bar view
setFullScreenDialogDoneClose(R.string.btn_okay,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// add key ids to params Bundle for new request
Intent resultData = extras.getParcelable(EXTRA_DATA);
resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS,
mSelectFragment.getSelectedMasterKeyIds());
RemoteSelectPubKeyActivity.this.setResult(RESULT_OK, resultData);
RemoteSelectPubKeyActivity.this.finish();
}
},
new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
RemoteSelectPubKeyActivity.this.setResult(RESULT_CANCELED);
RemoteSelectPubKeyActivity.this.finish();
}
});
// set text on view
TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text);
textView.setText(ssb, TextView.BufferType.SPANNABLE);
// Load select pub keys fragment
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create an instance of the fragment
mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit();
}
}
}

View file

@ -1,345 +0,0 @@
/*
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.remote.ui;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.BulletSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.view.View;
import android.widget.TextView;
import org.openintents.openpgp.util.OpenPgpApi;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.remote.AccountSettings;
import org.sufficientlysecure.keychain.remote.AppSettings;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
import org.sufficientlysecure.keychain.ui.SelectPublicKeyFragment;
import org.sufficientlysecure.keychain.ui.util.Notify;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
// TODO: make extensible BaseRemoteServiceActivity and extend these cases from it
public class RemoteServiceActivity extends BaseActivity {
public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER";
public static final String ACTION_CREATE_ACCOUNT = Constants.INTENT_PREFIX
+ "API_ACTIVITY_CREATE_ACCOUNT";
public static final String ACTION_SELECT_PUB_KEYS = Constants.INTENT_PREFIX
+ "API_ACTIVITY_SELECT_PUB_KEYS";
public static final String ACTION_ERROR_MESSAGE = Constants.INTENT_PREFIX
+ "API_ACTIVITY_ERROR_MESSAGE";
public static final String EXTRA_MESSENGER = "messenger";
public static final String EXTRA_DATA = "data";
// passphrase action
public static final String EXTRA_SECRET_KEY_ID = "secret_key_id";
// register action
public static final String EXTRA_PACKAGE_NAME = "package_name";
public static final String EXTRA_PACKAGE_SIGNATURE = "package_signature";
// create acc action
public static final String EXTRA_ACC_NAME = "acc_name";
// select pub keys action
public static final String EXTRA_SELECTED_MASTER_KEY_IDS = "master_key_ids";
public static final String EXTRA_MISSING_EMAILS = "missing_emails";
public static final String EXTRA_DUPLICATE_EMAILS = "dublicate_emails";
public static final String EXTRA_NO_USER_IDS_CHECK = "no_user_ids";
// error message
public static final String EXTRA_ERROR_MESSAGE = "error_message";
// register view
private AppSettingsHeaderFragment mAppSettingsHeaderFragment;
// create acc view
private AccountSettingsFragment mAccSettingsFragment;
// select pub keys view
private SelectPublicKeyFragment mSelectFragment;
private ProviderHelper mProviderHelper;
// for ACTION_CREATE_ACCOUNT
boolean mUpdateExistingAccount;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mProviderHelper = new ProviderHelper(this);
handleActions(getIntent(), savedInstanceState);
}
@Override
protected void initLayout() {
// done in handleActions()
}
protected void handleActions(Intent intent, Bundle savedInstanceState) {
String action = intent.getAction();
final Bundle extras = intent.getExtras();
switch (action) {
case ACTION_REGISTER: {
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
final byte[] packageSignature = extras.getByteArray(EXTRA_PACKAGE_SIGNATURE);
Log.d(Constants.TAG, "ACTION_REGISTER packageName: " + packageName);
setContentView(R.layout.api_remote_register_app);
initToolbar();
mAppSettingsHeaderFragment = (AppSettingsHeaderFragment) getSupportFragmentManager().findFragmentById(
R.id.api_app_settings_fragment);
AppSettings settings = new AppSettings(packageName, packageSignature);
mAppSettingsHeaderFragment.setAppSettings(settings);
// Inflate a "Done"/"Cancel" custom action bar view
setFullScreenDialogTwoButtons(
R.string.api_register_allow, R.drawable.ic_check_white_24dp,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Allow
mProviderHelper.insertApiApp(mAppSettingsHeaderFragment.getAppSettings());
// give data through for new service call
Intent resultData = extras.getParcelable(EXTRA_DATA);
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
RemoteServiceActivity.this.finish();
}
}, R.string.api_register_disallow, R.drawable.ic_close_white_24dp,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Disallow
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
RemoteServiceActivity.this.finish();
}
}
);
break;
}
case ACTION_CREATE_ACCOUNT: {
final String packageName = extras.getString(EXTRA_PACKAGE_NAME);
final String accName = extras.getString(EXTRA_ACC_NAME);
setContentView(R.layout.api_remote_create_account);
initToolbar();
mAccSettingsFragment = (AccountSettingsFragment) getSupportFragmentManager().findFragmentById(
R.id.api_account_settings_fragment);
TextView text = (TextView) findViewById(R.id.api_remote_create_account_text);
// update existing?
Uri uri = KeychainContract.ApiAccounts.buildByPackageAndAccountUri(packageName, accName);
AccountSettings settings = mProviderHelper.getApiAccountSettings(uri);
if (settings == null) {
// create new account
settings = new AccountSettings(accName);
mUpdateExistingAccount = false;
text.setText(R.string.api_create_account_text);
} else {
// update existing account
mUpdateExistingAccount = true;
text.setText(R.string.api_update_account_text);
}
mAccSettingsFragment.setAccSettings(settings);
// Inflate a "Done"/"Cancel" custom action bar view
setFullScreenDialogDoneClose(R.string.api_settings_save,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Save
// user needs to select a key if it has explicitly requested (None is only allowed for new accounts)
if (mUpdateExistingAccount && mAccSettingsFragment.getAccSettings().getKeyId() == Constants.key.none) {
Notify.create(RemoteServiceActivity.this, getString(R.string.api_register_error_select_key), Notify.Style.ERROR).show();
} else {
if (mUpdateExistingAccount) {
Uri baseUri = KeychainContract.ApiAccounts.buildBaseUri(packageName);
Uri accountUri = baseUri.buildUpon().appendEncodedPath(accName).build();
mProviderHelper.updateApiAccount(
accountUri,
mAccSettingsFragment.getAccSettings());
} else {
mProviderHelper.insertApiAccount(
KeychainContract.ApiAccounts.buildBaseUri(packageName),
mAccSettingsFragment.getAccSettings());
}
// give data through for new service call
Intent resultData = extras.getParcelable(EXTRA_DATA);
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
RemoteServiceActivity.this.finish();
}
}
},
new View.OnClickListener() {
@Override
public void onClick(View v) {
// Cancel
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
RemoteServiceActivity.this.finish();
}
});
break;
}
case ACTION_SELECT_PUB_KEYS: {
long[] selectedMasterKeyIds = intent.getLongArrayExtra(EXTRA_SELECTED_MASTER_KEY_IDS);
boolean noUserIdsCheck = intent.getBooleanExtra(EXTRA_NO_USER_IDS_CHECK, true);
ArrayList<String> missingEmails = intent
.getStringArrayListExtra(EXTRA_MISSING_EMAILS);
ArrayList<String> duplicateEmails = intent
.getStringArrayListExtra(EXTRA_DUPLICATE_EMAILS);
SpannableStringBuilder ssb = new SpannableStringBuilder();
final SpannableString textIntro = new SpannableString(
noUserIdsCheck ? getString(R.string.api_select_pub_keys_text_no_user_ids)
: getString(R.string.api_select_pub_keys_text)
);
textIntro.setSpan(new StyleSpan(Typeface.BOLD), 0, textIntro.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(textIntro);
if (missingEmails != null && missingEmails.size() > 0) {
ssb.append("\n\n");
ssb.append(getString(R.string.api_select_pub_keys_missing_text));
ssb.append("\n");
for (String emails : missingEmails) {
SpannableString ss = new SpannableString(emails + "\n");
ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(ss);
}
}
if (duplicateEmails != null && duplicateEmails.size() > 0) {
ssb.append("\n\n");
ssb.append(getString(R.string.api_select_pub_keys_dublicates_text));
ssb.append("\n");
for (String email : duplicateEmails) {
SpannableString ss = new SpannableString(email + "\n");
ss.setSpan(new BulletSpan(15, Color.BLACK), 0, ss.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.append(ss);
}
}
setContentView(R.layout.api_remote_select_pub_keys);
initToolbar();
// Inflate a "Done"/"Cancel" custom action bar view
setFullScreenDialogDoneClose(R.string.btn_okay,
new View.OnClickListener() {
@Override
public void onClick(View v) {
// add key ids to params Bundle for new request
Intent resultData = extras.getParcelable(EXTRA_DATA);
resultData.putExtra(OpenPgpApi.EXTRA_KEY_IDS,
mSelectFragment.getSelectedMasterKeyIds());
RemoteServiceActivity.this.setResult(RESULT_OK, resultData);
RemoteServiceActivity.this.finish();
}
},
new View.OnClickListener() {
@Override
public void onClick(View v) {
// cancel
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
RemoteServiceActivity.this.finish();
}
});
// set text on view
TextView textView = (TextView) findViewById(R.id.api_select_pub_keys_text);
textView.setText(ssb, TextView.BufferType.SPANNABLE);
/* Load select pub keys fragment */
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.api_select_pub_keys_fragment_container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create an instance of the fragment
mSelectFragment = SelectPublicKeyFragment.newInstance(selectedMasterKeyIds);
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.api_select_pub_keys_fragment_container, mSelectFragment).commit();
}
break;
}
case ACTION_ERROR_MESSAGE: {
String errorMessage = intent.getStringExtra(EXTRA_ERROR_MESSAGE);
Spannable redErrorMessage = new SpannableString(errorMessage);
redErrorMessage.setSpan(new ForegroundColorSpan(Color.RED), 0, errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
setContentView(R.layout.api_remote_error_message);
initToolbar();
// Inflate a "Done" custom action bar view
setFullScreenDialogClose(
new View.OnClickListener() {
@Override
public void onClick(View v) {
RemoteServiceActivity.this.setResult(RESULT_CANCELED);
RemoteServiceActivity.this.finish();
}
}
);
// set text on view
TextView textView = (TextView) findViewById(R.id.api_app_error_message_text);
textView.setText(redErrorMessage);
break;
}
default:
Log.e(Constants.TAG, "Action does not exist!");
setResult(RESULT_CANCELED);
finish();
break;
}
}
}

View file

@ -33,8 +33,6 @@ public class SelectAllowedKeysActivity extends BaseActivity {
public static final String EXTRA_SERVICE_INTENT = "data";
private Uri mAppUri;
private AppSettingsAllowedKeysListFragment mAllowedKeysFragment;
Intent mServiceData;
@ -60,14 +58,14 @@ public class SelectAllowedKeysActivity extends BaseActivity {
Intent intent = getIntent();
mServiceData = intent.getParcelableExtra(EXTRA_SERVICE_INTENT);
mAppUri = intent.getData();
if (mAppUri == null) {
Uri appUri = intent.getData();
if (appUri == null) {
Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!");
finish();
return;
} else {
Log.d(Constants.TAG, "uri: " + mAppUri);
loadData(savedInstanceState, mAppUri);
Log.d(Constants.TAG, "uri: " + appUri);
loadData(savedInstanceState, appUri);
}
}

View file

@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.ui.widget.FixedListView;
import org.sufficientlysecure.keychain.util.Log;
public class SelectSignKeyIdListFragment extends ListFragmentWorkaround implements LoaderManager.LoaderCallbacks<Cursor> {
private static final String ARG_DATA_URI = "uri";
public static final String ARG_DATA = "data";

View file

@ -23,7 +23,10 @@ import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
public class ExitActivity extends Activity {
/**
* For Guardianproject's PANIC app
*/
public class PanicExitActivity extends Activity {
@SuppressLint("NewApi")
@Override
@ -40,7 +43,7 @@ public class ExitActivity extends Activity {
}
public static void exitAndRemoveFromRecentApps(Activity activity) {
Intent intent = new Intent(activity, ExitActivity.class);
Intent intent = new Intent(activity, PanicExitActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

View file

@ -25,6 +25,9 @@ import android.os.Bundle;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
/**
* Responder for Guardianproject's PANIC app
*/
public class PanicResponderActivity extends Activity {
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
@ -37,7 +40,7 @@ public class PanicResponderActivity extends Activity {
Intent intent = getIntent();
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
PassphraseCacheService.clearCachedPassphrases(this);
ExitActivity.exitAndRemoveFromRecentApps(this);
PanicExitActivity.exitAndRemoveFromRecentApps(this);
}
if (Build.VERSION.SDK_INT >= 21) {