Merge pull request #2586 from open-keychain/drop-more-stuff
Drop more stuff
This commit is contained in:
commit
258cd4c836
|
@ -49,9 +49,6 @@ dependencies {
|
|||
// Nordpol
|
||||
implementation 'com.fidesmo:nordpol-android:0.1.22'
|
||||
|
||||
// piwik
|
||||
implementation 'org.piwik.sdk:piwik-sdk:3.0.3'
|
||||
|
||||
// libs as submodules
|
||||
implementation project(':openpgp-api-lib')
|
||||
implementation project(':nfcsweetspot')
|
||||
|
|
|
@ -54,21 +54,6 @@
|
|||
|
||||
<!-- CAMERA permission requested by ZXing library -->
|
||||
|
||||
<!-- contact group -->
|
||||
<!--
|
||||
AUTHENTICATE_ACCOUNTS and MANAGE_ACCOUNTS removed in Android >= 6,
|
||||
see https://code.google.com/p/android-developer-preview/issues/detail?id=2592
|
||||
also READ_PROFILE, WRITE_PROFILE?
|
||||
-->
|
||||
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.READ_PROFILE" />
|
||||
<uses-permission android:name="android.permission.WRITE_PROFILE" />
|
||||
|
||||
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
|
||||
|
||||
<!-- storage group -->
|
||||
<!--
|
||||
No need on >= Android 4.4 for WRITE_EXTERNAL_STORAGE, because we use Storage Access Framework,
|
||||
|
@ -1012,36 +997,6 @@
|
|||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<!-- Contact Sync services -->
|
||||
<service
|
||||
android:name=".service.DummyAccountService"
|
||||
android:exported="true"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="android.accounts.AccountAuthenticator" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.accounts.AccountAuthenticator"
|
||||
android:resource="@xml/account_desc" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".service.ContactSyncAdapterService"
|
||||
android:exported="true"
|
||||
android:process=":sync"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.SyncAdapter" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.content.SyncAdapter"
|
||||
android:resource="@xml/sync_adapter_contacts" />
|
||||
<meta-data
|
||||
android:name="android.provider.CONTACTS_STRUCTURE"
|
||||
android:resource="@xml/sync_adapter_contacts_structure" />
|
||||
</service>
|
||||
|
||||
<!-- Storage Provider for temporary decrypted files.
|
||||
For security considerations, read class! -->
|
||||
<provider
|
||||
|
|
|
@ -20,8 +20,6 @@ package org.sufficientlysecure.keychain;
|
|||
|
||||
import java.io.File;
|
||||
import java.net.Proxy;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import android.os.Environment;
|
||||
|
||||
|
@ -159,10 +157,6 @@ public final class Constants {
|
|||
|
||||
public static final String KEY_SIGNATURES_TABLE_INITIALIZED = "key_signatures_table_initialized";
|
||||
|
||||
public static final String KEY_ANALYTICS_ASKED_POLITELY = "analytics_asked";
|
||||
public static final String KEY_ANALYTICS_CONSENT = "analytics_consent";
|
||||
public static final String KEY_ANALYTICS_LAST_ASKED = "analytics_last_asked";
|
||||
|
||||
public static final class Theme {
|
||||
public static final String LIGHT = "light";
|
||||
public static final String DARK = "dark";
|
||||
|
@ -173,14 +167,6 @@ public final class Constants {
|
|||
public static final String TYPE_HTTP = "proxyHttp";
|
||||
public static final String TYPE_SOCKS = "proxySocks";
|
||||
}
|
||||
|
||||
// we generally only track booleans. never snoop around in the user's string settings!!
|
||||
public static final List<String> ANALYTICS_PREFS = Arrays.asList(USE_NORMAL_PROXY, USE_TOR_PROXY,
|
||||
SYNC_CONTACTS, SYNC_KEYSERVER, ENABLE_WIFI_SYNC_ONLY,
|
||||
EXPERIMENTAL_USB_ALLOW_UNTESTED,
|
||||
PASSPHRASE_CACHE_SUBS, SEARCH_KEYSERVER, SEARCH_WEB_KEY_DIRECTORY,
|
||||
TEXT_USE_COMPRESSION, TEXT_SELF_ENCRYPT, FILE_USE_COMPRESSION, FILE_SELF_ENCRYPT, USE_ARMOR,
|
||||
USE_NUMKEYPAD_FOR_SECURITY_TOKEN_PIN, ENCRYPT_FILENAMES);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,15 +30,15 @@ import android.app.Application;
|
|||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.sufficientlysecure.keychain.analytics.AnalyticsManager;
|
||||
import org.sufficientlysecure.keychain.keysync.KeyserverSyncManager;
|
||||
import org.sufficientlysecure.keychain.network.TlsCertificatePinning;
|
||||
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.util.PRNGFixes;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
@ -46,8 +46,6 @@ import timber.log.Timber.DebugTree;
|
|||
|
||||
|
||||
public class KeychainApplication extends Application {
|
||||
AnalyticsManager analyticsManager;
|
||||
|
||||
/**
|
||||
* Called when the application is starting, before any activity, service, or receiver objects
|
||||
* (excluding content providers) have been created.
|
||||
|
@ -88,15 +86,9 @@ public class KeychainApplication extends Application {
|
|||
}
|
||||
*/
|
||||
|
||||
// Add OpenKeychain account to Android to link contacts with keys and keyserver sync
|
||||
createAccountIfNecessary(this);
|
||||
|
||||
Preferences preferences = Preferences.getPreferences(this);
|
||||
if (preferences.isAppExecutedFirstTime()) {
|
||||
preferences.setAppExecutedFirstTime(false);
|
||||
|
||||
ContactSyncAdapterService.enableContactsSync(this);
|
||||
|
||||
preferences.setPrefVersionToCurrentVersion();
|
||||
}
|
||||
|
||||
|
@ -116,36 +108,6 @@ public class KeychainApplication extends Application {
|
|||
KeyserverSyncManager.updateKeyserverSyncScheduleAsync(this, false);
|
||||
|
||||
TemporaryFileProvider.scheduleCleanupImmediately(getApplicationContext());
|
||||
|
||||
analyticsManager = AnalyticsManager.getInstance(getApplicationContext());
|
||||
analyticsManager.initialize(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the OpenKeychain contact/keyserver sync account if it exists or was successfully
|
||||
* created, null otherwise
|
||||
*/
|
||||
public static @Nullable Account createAccountIfNecessary(Context context) {
|
||||
try {
|
||||
AccountManager manager = AccountManager.get(context);
|
||||
Account[] accounts = manager.getAccountsByType(Constants.ACCOUNT_TYPE);
|
||||
|
||||
Account account = new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE);
|
||||
if (accounts.length == 0) {
|
||||
if (!manager.addAccountExplicitly(account, null, null)) {
|
||||
Timber.d("error when adding account via addAccountExplicitly");
|
||||
return null;
|
||||
} else {
|
||||
return account;
|
||||
}
|
||||
} else {
|
||||
return accounts[0];
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
Timber.e(e, "SecurityException when adding the account");
|
||||
Toast.makeText(context, R.string.reinstall_openkeychain, Toast.LENGTH_LONG).show();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String,Bitmap> qrCodeCache = new HashMap<>();
|
||||
|
@ -167,10 +129,6 @@ public class KeychainApplication extends Application {
|
|||
}
|
||||
}
|
||||
|
||||
public AnalyticsManager getAnalyticsManager() {
|
||||
return analyticsManager;
|
||||
}
|
||||
|
||||
public static String getProcessName() {
|
||||
if (Build.VERSION.SDK_INT >= 28)
|
||||
return Application.getProcessName();
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
package org.sufficientlysecure.keychain.analytics;
|
||||
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.sufficientlysecure.keychain.BuildConfig;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.SettingsActivity;
|
||||
import org.sufficientlysecure.keychain.ui.SettingsActivity.ExperimentalPrefsFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
|
||||
public class AnalyticsConsentRequester {
|
||||
private final Activity activity;
|
||||
|
||||
public static AnalyticsConsentRequester getInstance(Activity activity) {
|
||||
return new AnalyticsConsentRequester(activity);
|
||||
}
|
||||
|
||||
private AnalyticsConsentRequester(Activity activity) {
|
||||
this.activity = activity;
|
||||
}
|
||||
|
||||
public void maybeAskForAnalytics() {
|
||||
Preferences preferences = Preferences.getPreferences(activity);
|
||||
if (preferences.isAnalyticsHasConsent()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean askedBeforeAndWasRejected =
|
||||
preferences.isAnalyticsAskedPolitely() && !preferences.isAnalyticsHasConsent();
|
||||
if (askedBeforeAndWasRejected) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
long firstInstallTime =
|
||||
activity.getPackageManager().getPackageInfo(BuildConfig.APPLICATION_ID, 0).firstInstallTime;
|
||||
long threeDaysAgo = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(3);
|
||||
boolean installedLessThanThreeDaysAgo = firstInstallTime > threeDaysAgo;
|
||||
if (installedLessThanThreeDaysAgo) {
|
||||
return;
|
||||
}
|
||||
} catch (NameNotFoundException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
long twentyFourHoursAgo = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1);
|
||||
boolean askedLessThan24HoursAgo = preferences.getAnalyticsLastAsked() > twentyFourHoursAgo;
|
||||
if (askedLessThan24HoursAgo) {
|
||||
return;
|
||||
}
|
||||
|
||||
preferences.setAnalyticsLastAskedNow();
|
||||
|
||||
AnalyticsManager analyticsManager = ((KeychainApplication) activity.getApplication()).getAnalyticsManager();
|
||||
AlertDialog alertDialog = new Builder(activity)
|
||||
.setMessage(R.string.dialog_analytics_consent)
|
||||
.setPositiveButton(R.string.button_analytics_yes, (dialog, which) -> {
|
||||
preferences.setAnalyticsAskedPolitely();
|
||||
preferences.setAnalyticsGotUserConsent(true);
|
||||
analyticsManager.refreshSettings(activity);
|
||||
Notify.create(activity, R.string.snack_analytics_accept, Style.OK,
|
||||
this::startExperimentalSettingsActivity, R.string.snackbutton_analytics_settings).show();
|
||||
})
|
||||
.setNegativeButton(R.string.button_analytics_no, (dialog, which) -> {
|
||||
preferences.setAnalyticsAskedPolitely();
|
||||
preferences.setAnalyticsGotUserConsent(false);
|
||||
analyticsManager.refreshSettings(activity);
|
||||
Notify.create(activity, R.string.snack_analytics_reject, Style.OK,
|
||||
this::startExperimentalSettingsActivity, R.string.snackbutton_analytics_settings).show();
|
||||
})
|
||||
.show();
|
||||
alertDialog.<TextView>findViewById(android.R.id.message).setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
private void startExperimentalSettingsActivity() {
|
||||
Intent resultIntent = new Intent(activity, SettingsActivity.class);
|
||||
String experimentalPrefsName = ExperimentalPrefsFragment.class.getName();
|
||||
resultIntent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT, experimentalPrefsName);
|
||||
activity.startActivity(resultIntent);
|
||||
}
|
||||
}
|
|
@ -1,180 +0,0 @@
|
|||
package org.sufficientlysecure.keychain.analytics;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.app.Application.ActivityLifecycleCallbacks;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.piwik.sdk.Piwik;
|
||||
import org.piwik.sdk.Tracker;
|
||||
import org.piwik.sdk.TrackerConfig;
|
||||
import org.piwik.sdk.extra.DownloadTracker.Extra.ApkChecksum;
|
||||
import org.piwik.sdk.extra.TrackHelper;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.Constants.Defaults;
|
||||
import org.sufficientlysecure.keychain.Constants.Pref;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public class AnalyticsManager implements OnSharedPreferenceChangeListener {
|
||||
private Tracker piwikTracker;
|
||||
|
||||
public static AnalyticsManager getInstance(Context context) {
|
||||
return new AnalyticsManager(context);
|
||||
}
|
||||
|
||||
private AnalyticsManager(Context context) {
|
||||
refreshSettings(context);
|
||||
}
|
||||
|
||||
public void initialize(Application application) {
|
||||
if (piwikTracker != null) {
|
||||
TrackHelper.track().download().identifier(new ApkChecksum(application)).with(piwikTracker);
|
||||
}
|
||||
|
||||
application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
|
||||
@Override
|
||||
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStarted(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResumed(Activity activity) {
|
||||
if (piwikTracker == null) {
|
||||
return;
|
||||
}
|
||||
TrackHelper.track().screen(activity.getClass().getSimpleName()).with(piwikTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityPaused(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityStopped(Activity activity) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed(Activity activity) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Preferences preferences = Preferences.getPreferences(application);
|
||||
preferences.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||
}
|
||||
|
||||
// we generally only track booleans. never snoop around in the user's string settings!!
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (piwikTracker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// small exception: check if the user uses a custom keyserver, or one of the well-known ones
|
||||
if (Pref.KEY_SERVERS.equals(key)) {
|
||||
Timber.d("Tracking pref %s", key);
|
||||
String keyServers = sharedPreferences.getString(Pref.KEY_SERVERS, Defaults.KEY_SERVERS);
|
||||
String current = keyServers.substring(keyServers.indexOf(','));
|
||||
|
||||
String coarseGranularityKeyserver;
|
||||
if (current.contains("keyserver.ubuntu.com")) {
|
||||
coarseGranularityKeyserver = "ubuntu";
|
||||
} else if (current.contains("pgp.mit.edu")) {
|
||||
coarseGranularityKeyserver = "mit";
|
||||
} else if (current.contains("pool.sks-keyservers.net")) {
|
||||
coarseGranularityKeyserver = "pool";
|
||||
} else {
|
||||
coarseGranularityKeyserver = "custom";
|
||||
}
|
||||
TrackHelper.track().interaction("pref_" + Pref.KEY_SERVERS, coarseGranularityKeyserver).with(piwikTracker);
|
||||
return;
|
||||
}
|
||||
// unpack an enum
|
||||
if (Pref.THEME.equals(key)) {
|
||||
String value = sharedPreferences.getString(Pref.THEME, "empty");
|
||||
TrackHelper.track().interaction("pref_" + Pref.THEME, value).with(piwikTracker);
|
||||
return;
|
||||
}
|
||||
// all other values we track are individual booleans
|
||||
if (Pref.ANALYTICS_PREFS.contains(key)) {
|
||||
Timber.d("Tracking pref %s", key);
|
||||
if (!sharedPreferences.contains(key)) {
|
||||
TrackHelper.track().interaction("pref_" + key, "empty").with(piwikTracker);
|
||||
return;
|
||||
}
|
||||
boolean value = sharedPreferences.getBoolean(key, false);
|
||||
TrackHelper.track().interaction("pref_" + key, value ? "true" : "false").with(piwikTracker);
|
||||
}
|
||||
}
|
||||
|
||||
public void trackFragmentImpression(String opClassName, String fragmentName) {
|
||||
if (piwikTracker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TrackHelper.track().screen(opClassName + "/" + fragmentName).with(piwikTracker);
|
||||
}
|
||||
|
||||
public void trackInternalServiceCall(String opClassName) {
|
||||
if (piwikTracker == null) {
|
||||
return;
|
||||
}
|
||||
TrackHelper.track()
|
||||
.interaction("internalApiCall", opClassName)
|
||||
.with(piwikTracker);
|
||||
}
|
||||
|
||||
public void trackApiServiceCall(String opClassName, String currentCallingPackage) {
|
||||
if (piwikTracker == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TrackHelper.track()
|
||||
.interaction("externalApiCall", opClassName)
|
||||
.piece(currentCallingPackage.replace(".", "/"))
|
||||
.with(piwikTracker);
|
||||
}
|
||||
|
||||
public synchronized void refreshSettings(Context context) {
|
||||
boolean shouldEnableAnalytics = shouldEnableAnalytics(context);
|
||||
boolean analyticsEnabled = piwikTracker != null;
|
||||
if (shouldEnableAnalytics != analyticsEnabled) {
|
||||
if (shouldEnableAnalytics) {
|
||||
TrackerConfig trackerConfig;
|
||||
if (Constants.DEBUG) {
|
||||
trackerConfig = new TrackerConfig("https://piwik.openkeychain.org/", 3, "OpenKeychainDebug");
|
||||
} else {
|
||||
trackerConfig = new TrackerConfig("https://piwik.openkeychain.org/", 2, "OpenKeychain");
|
||||
}
|
||||
piwikTracker = Piwik.getInstance(context).newTracker(trackerConfig);
|
||||
piwikTracker.setDispatchInterval(60000);
|
||||
piwikTracker.setOptOut(false);
|
||||
} else {
|
||||
piwikTracker.setOptOut(true);
|
||||
piwikTracker = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldEnableAnalytics(Context context) {
|
||||
Preferences preferences = Preferences.getPreferences(context);
|
||||
return preferences.isAnalyticsHasConsent() && !preferences.getUseTorProxy();
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
package org.sufficientlysecure.keychain.keysync;
|
||||
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -29,11 +28,10 @@ import android.os.Build.VERSION_CODES;
|
|||
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.work.Constraints.Builder;
|
||||
import androidx.work.ExistingPeriodicWorkPolicy;
|
||||
import androidx.work.NetworkType;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.PeriodicWorkRequest;
|
||||
import androidx.work.WorkInfo;
|
||||
import androidx.work.WorkInfo.State;
|
||||
import androidx.work.WorkManager;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
import timber.log.Timber;
|
||||
|
@ -43,7 +41,8 @@ public class KeyserverSyncManager {
|
|||
private static final long SYNC_INTERVAL = 3;
|
||||
private static final TimeUnit SYNC_INTERVAL_UNIT = TimeUnit.DAYS;
|
||||
|
||||
private static final String PERIODIC_WORK_TAG = "keyserverSync";
|
||||
private static final String LEGACY_PERIODIC_WORK_TAG = "keyserverSync";
|
||||
private static final String WORK_UNIQUE_NAME = "periodicKeyserverSync";
|
||||
|
||||
public static void updateKeyserverSyncScheduleAsync(Context context, boolean forceReschedule) {
|
||||
new AsyncTask<Void,Void,Void>() {
|
||||
|
@ -60,27 +59,12 @@ public class KeyserverSyncManager {
|
|||
Preferences prefs = Preferences.getPreferences(context);
|
||||
WorkManager workManager = WorkManager.getInstance(context);
|
||||
|
||||
UUID workUuid = prefs.getKeyserverSyncWorkUuid();
|
||||
try {
|
||||
WorkInfo info = workUuid != null ? workManager.getWorkInfoById(workUuid).get() : null;
|
||||
|
||||
boolean workIsScheduled = info != null && info.getState() != State.CANCELLED;
|
||||
if (workIsScheduled == prefs.isKeyserverSyncEnabled()) {
|
||||
if (!forceReschedule) {
|
||||
Timber.d("Key sync already scheduled, no changes necessary");
|
||||
return;
|
||||
}
|
||||
Timber.d("Key sync already scheduled, but forcing reschedule");
|
||||
}
|
||||
} catch (ExecutionException | InterruptedException e) {
|
||||
Timber.e(e, "Error getting info for scheduled key sync work?");
|
||||
}
|
||||
|
||||
Timber.d("Cancelling sync tasks…");
|
||||
workManager.cancelAllWorkByTag(PERIODIC_WORK_TAG);
|
||||
// Cancel work that was scheduled by tag, as we used to do.
|
||||
workManager.cancelAllWorkByTag(LEGACY_PERIODIC_WORK_TAG);
|
||||
|
||||
if (!prefs.isKeyserverSyncEnabled()) {
|
||||
Timber.d("Key sync disabled");
|
||||
workManager.cancelUniqueWork(WORK_UNIQUE_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -96,10 +80,12 @@ public class KeyserverSyncManager {
|
|||
PeriodicWorkRequest workRequest =
|
||||
new PeriodicWorkRequest.Builder(KeyserverSyncWorker.class, SYNC_INTERVAL, SYNC_INTERVAL_UNIT)
|
||||
.setConstraints(constraints.build())
|
||||
.addTag(PERIODIC_WORK_TAG)
|
||||
.build();
|
||||
try {
|
||||
workManager.enqueue(workRequest).getResult().get();
|
||||
ExistingPeriodicWorkPolicy policy = forceReschedule
|
||||
? ExistingPeriodicWorkPolicy.REPLACE
|
||||
: ExistingPeriodicWorkPolicy.KEEP;
|
||||
workManager.enqueueUniquePeriodicWork(WORK_UNIQUE_NAME, policy, workRequest).getResult().get();
|
||||
Timber.d("Work id: %s", workRequest.getId());
|
||||
prefs.setKeyserverSyncScheduled(workRequest.getId());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
|||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel;
|
||||
import org.sufficientlysecure.keychain.service.CertifyActionsParcel.CertifyAction;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
|
@ -254,9 +253,6 @@ public class CertifyOperation extends BaseReadWriteOperation<CertifyActionsParce
|
|||
uploadOk, uploadError);
|
||||
}
|
||||
|
||||
// since only verified keys are synced to contacts, we need to initiate a sync now
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
log.add(LogType.MSG_CRT_SUCCESS, 0);
|
||||
if (uploadError != 0) {
|
||||
return new CertifyResult(CertifyResult.RESULT_WARNINGS, log, certifyOk, certifyError, uploadOk,
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.sufficientlysecure.keychain.operations.results.OperationResult.Operat
|
|||
import org.sufficientlysecure.keychain.operations.results.UpdateTrustResult;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.DeleteKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
|
@ -101,9 +100,6 @@ public class DeleteOperation extends BaseReadWriteOperation<DeleteKeyringParcel>
|
|||
|
||||
int result = DeleteResult.RESULT_OK;
|
||||
if (success > 0) {
|
||||
// make sure new data is synced into contacts
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
log.add(LogType.MSG_DEL_OK, 0, success);
|
||||
}
|
||||
if (fail > 0) {
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKeyRing;
|
|||
import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.UploadKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
|
@ -182,9 +181,6 @@ public class EditKeyOperation extends BaseReadWriteOperation<SaveKeyringParcel>
|
|||
|
||||
updateProgress(R.string.progress_done, 100, 100);
|
||||
|
||||
// make sure new data is synced into contacts
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
log.add(LogType.MSG_ED_SUCCESS, 0);
|
||||
return new EditKeyResult(EditKeyResult.RESULT_OK, log, ring.getMasterKeyId());
|
||||
|
||||
|
|
|
@ -32,9 +32,9 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.daos.KeyMetadataDao;
|
||||
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
||||
|
@ -55,7 +55,6 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedKeyRing;
|
|||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.service.ContactSyncAdapterService;
|
||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
|
@ -134,9 +133,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||
}
|
||||
|
||||
/**
|
||||
* Since the introduction of multithreaded import, we expect calling functions to handle the
|
||||
* contact-to-key sync i.e ContactSyncAdapterService.requestContactsSync()
|
||||
*
|
||||
* @param entries keys to import
|
||||
* @param numTotalKeys number of keys to import
|
||||
* @param hkpKeyserver contains uri of keyserver to import from, if it is an import from cloud
|
||||
|
@ -274,11 +270,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||
}
|
||||
}
|
||||
|
||||
// Special: make sure new data is synced into contacts
|
||||
// disabling sync right now since it reduces speed while multi-threading
|
||||
// so, we expect calling functions to take care of it. KeychainService handles this
|
||||
// ContactSyncAdapterService.requestContactsSync();
|
||||
|
||||
// convert to long array
|
||||
long[] importedMasterKeyIdsArray = new long[importedMasterKeyIds.size()];
|
||||
for (int i = 0; i < importedMasterKeyIds.size(); ++i) {
|
||||
|
@ -476,10 +467,6 @@ public class ImportOperation extends BaseReadWriteOperation<ImportKeyringParcel>
|
|||
|
||||
result = multiThreadedKeyImport(keyList, keyServer, proxy, skipSave, forceReinsert);
|
||||
}
|
||||
|
||||
if (!skipSave) {
|
||||
ContactSyncAdapterService.requestContactsSync();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.util.concurrent.TimeUnit;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ClipDescription;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
|
@ -41,6 +40,7 @@ import android.os.ParcelFileDescriptor;
|
|||
import android.provider.MediaStore;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.work.ExistingWorkPolicy;
|
||||
import androidx.work.OneTimeWorkRequest;
|
||||
import androidx.work.WorkManager;
|
||||
import androidx.work.Worker;
|
||||
|
@ -77,6 +77,7 @@ public class TemporaryFileProvider extends ContentProvider {
|
|||
public static final String AUTHORITY = Constants.TEMP_FILE_PROVIDER_AUTHORITY;
|
||||
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
|
||||
private static final int DB_VERSION = 3;
|
||||
public static final String WORK_NAME_CLEANUP = "cleanup";
|
||||
|
||||
interface TemporaryFileColumns {
|
||||
String COLUMN_UUID = "id";
|
||||
|
@ -315,20 +316,22 @@ public class TemporaryFileProvider extends ContentProvider {
|
|||
public static void scheduleCleanupAfterTtl(Context context) {
|
||||
OneTimeWorkRequest cleanupWork = new OneTimeWorkRequest.Builder(CleanupWorker.class)
|
||||
.setInitialDelay(Constants.TEMPFILE_TTL, TimeUnit.MILLISECONDS).build();
|
||||
workManagerEnqueue(context, cleanupWork);
|
||||
workManagerEnqueueCleanup(context, cleanupWork);
|
||||
}
|
||||
|
||||
public static void scheduleCleanupImmediately(Context context) {
|
||||
OneTimeWorkRequest cleanupWork = new OneTimeWorkRequest.Builder(CleanupWorker.class).build();
|
||||
workManagerEnqueue(context, cleanupWork);
|
||||
workManagerEnqueueCleanup(context, cleanupWork);
|
||||
}
|
||||
|
||||
private static void workManagerEnqueue(Context context, OneTimeWorkRequest cleanupWork) {
|
||||
private static void workManagerEnqueueCleanup(Context context, OneTimeWorkRequest cleanupWork) {
|
||||
// work manager is only available on the main thread
|
||||
if (!BuildConfig.APPLICATION_ID.equals(KeychainApplication.getProcessName())) {
|
||||
return;
|
||||
}
|
||||
WorkManager.getInstance(context).enqueue(cleanupWork);
|
||||
WorkManager
|
||||
.getInstance(context)
|
||||
.enqueueUniqueWork(TemporaryFileProvider.WORK_NAME_CLEANUP, ExistingWorkPolicy.REPLACE, cleanupWork);
|
||||
}
|
||||
|
||||
public static class CleanupWorker extends Worker {
|
||||
|
|
|
@ -38,10 +38,10 @@ import android.os.Messenger;
|
|||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream;
|
||||
import org.openintents.openpgp.AutocryptPeerUpdate;
|
||||
import org.openintents.openpgp.IOpenPgpService;
|
||||
|
@ -52,9 +52,12 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
|
|||
import org.openintents.openpgp.OpenPgpSignatureResult.AutocryptPeerResult;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.daos.ApiAppDao;
|
||||
import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.daos.OverriddenWarningsDao;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.analytics.AnalyticsManager;
|
||||
import org.sufficientlysecure.keychain.operations.BackupOperation;
|
||||
import org.sufficientlysecure.keychain.operations.results.DecryptVerifyResult;
|
||||
import org.sufficientlysecure.keychain.operations.results.ExportResult;
|
||||
|
@ -69,12 +72,7 @@ import org.sufficientlysecure.keychain.pgp.PgpSignEncryptData;
|
|||
import org.sufficientlysecure.keychain.pgp.PgpSignEncryptOperation;
|
||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||
import org.sufficientlysecure.keychain.pgp.SecurityProblem;
|
||||
import org.sufficientlysecure.keychain.daos.ApiAppDao;
|
||||
import org.sufficientlysecure.keychain.daos.AutocryptPeerDao;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainExternalContract.AutocryptStatus;
|
||||
import org.sufficientlysecure.keychain.daos.OverriddenWarningsDao;
|
||||
import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResult;
|
||||
import org.sufficientlysecure.keychain.remote.OpenPgpServiceKeyIdExtractor.KeyIdResultStatus;
|
||||
import org.sufficientlysecure.keychain.service.BackupKeyringParcel;
|
||||
|
@ -101,7 +99,6 @@ public class OpenPgpService extends Service {
|
|||
private ApiAppDao mApiAppDao;
|
||||
private OpenPgpServiceKeyIdExtractor mKeyIdExtractor;
|
||||
private ApiPendingIntentFactory mApiPendingIntentFactory;
|
||||
private AnalyticsManager analyticsManager;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
|
@ -111,8 +108,6 @@ public class OpenPgpService extends Service {
|
|||
mApiPermissionHelper = new ApiPermissionHelper(this, mApiAppDao);
|
||||
mApiPendingIntentFactory = new ApiPendingIntentFactory(getBaseContext());
|
||||
mKeyIdExtractor = OpenPgpServiceKeyIdExtractor.getInstance(getContentResolver(), mApiPendingIntentFactory);
|
||||
|
||||
analyticsManager = ((KeychainApplication) getApplication()).getAnalyticsManager();
|
||||
}
|
||||
|
||||
private Intent signImpl(Intent data, InputStream inputStream,
|
||||
|
@ -1032,8 +1027,6 @@ public class OpenPgpService extends Service {
|
|||
return errorResult;
|
||||
}
|
||||
|
||||
analyticsManager.trackApiServiceCall(data.getAction(), mApiPermissionHelper.getCurrentCallingPackage());
|
||||
|
||||
Progressable progressable = null;
|
||||
if (data.hasExtra(OpenPgpApi.EXTRA_PROGRESS_MESSENGER)) {
|
||||
Messenger messenger = data.getParcelableExtra(OpenPgpApi.EXTRA_PROGRESS_MESSENGER);
|
||||
|
|
|
@ -40,17 +40,15 @@ import org.openintents.ssh.authentication.response.PublicKeyResponse;
|
|||
import org.openintents.ssh.authentication.response.SigningResponse;
|
||||
import org.openintents.ssh.authentication.response.SshPublicKeyResponse;
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.analytics.AnalyticsManager;
|
||||
import org.sufficientlysecure.keychain.daos.ApiAppDao;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKey;
|
||||
import org.sufficientlysecure.keychain.pgp.SshPublicKey;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpKeyNotFoundException;
|
||||
import org.sufficientlysecure.keychain.daos.ApiAppDao;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository;
|
||||
import org.sufficientlysecure.keychain.daos.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.ssh.AuthenticationData;
|
||||
|
@ -67,8 +65,6 @@ public class SshAuthenticationService extends Service {
|
|||
private ApiAppDao mApiAppDao;
|
||||
private ApiPendingIntentFactory mApiPendingIntentFactory;
|
||||
|
||||
private AnalyticsManager analyticsManager;
|
||||
|
||||
private static final List<Integer> SUPPORTED_VERSIONS = Collections.unmodifiableList(Collections.singletonList(1));
|
||||
private static final int INVALID_API_VERSION = -1;
|
||||
|
||||
|
@ -82,8 +78,6 @@ public class SshAuthenticationService extends Service {
|
|||
mApiAppDao = ApiAppDao.getInstance(this);
|
||||
|
||||
mApiPendingIntentFactory = new ApiPendingIntentFactory(getBaseContext());
|
||||
|
||||
analyticsManager = ((KeychainApplication) getApplication()).getAnalyticsManager();
|
||||
}
|
||||
|
||||
private final ISshAuthenticationService.Stub mSSHAgent = new ISshAuthenticationService.Stub() {
|
||||
|
@ -109,8 +103,6 @@ public class SshAuthenticationService extends Service {
|
|||
}
|
||||
|
||||
private Intent executeInternal(Intent intent) {
|
||||
analyticsManager.trackApiServiceCall(intent.getAction(), mApiPermissionHelper.getCurrentCallingPackage());
|
||||
|
||||
switch (intent.getAction()) {
|
||||
case SshAuthenticationApi.ACTION_SIGN:
|
||||
return authenticate(intent);
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Schürmann & Breitmoser GbR
|
||||
*
|
||||
* 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.service;
|
||||
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.Service;
|
||||
import android.content.AbstractThreadedSyncAdapter;
|
||||
import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SyncResult;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.provider.ContactsContract;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.NotificationChannelManager;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.SettingsActivity;
|
||||
import org.sufficientlysecure.keychain.util.ContactHelper;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public class ContactSyncAdapterService extends Service {
|
||||
|
||||
private static final int NOTIFICATION_ID_SYNC_SETTINGS = 13;
|
||||
|
||||
private class ContactSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
|
||||
// private final AtomicBoolean importDone = new AtomicBoolean(false);
|
||||
|
||||
public ContactSyncAdapter() {
|
||||
super(ContactSyncAdapterService.this, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider,
|
||||
final SyncResult syncResult) {
|
||||
Timber.d("Performing a contact sync!");
|
||||
|
||||
new ContactHelper(ContactSyncAdapterService.this).writeKeysToContacts();
|
||||
|
||||
// importKeys();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSecurityException(Account account, Bundle extras, String authority, SyncResult syncResult) {
|
||||
super.onSecurityException(account, extras, authority, syncResult);
|
||||
|
||||
// deactivate sync
|
||||
ContentResolver.setSyncAutomatically(account, authority, false);
|
||||
|
||||
NotificationChannelManager.getInstance(getContext()).createNotificationChannelsIfNecessary();
|
||||
|
||||
// show notification linking to sync settings
|
||||
Intent resultIntent = new Intent(ContactSyncAdapterService.this, SettingsActivity.class);
|
||||
resultIntent.putExtra(PreferenceActivity.EXTRA_SHOW_FRAGMENT,
|
||||
SettingsActivity.SyncPrefsFragment.class.getName());
|
||||
PendingIntent resultPendingIntent =
|
||||
PendingIntent.getActivity(
|
||||
ContactSyncAdapterService.this,
|
||||
0,
|
||||
resultIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
);
|
||||
NotificationCompat.Builder mBuilder =
|
||||
new NotificationCompat.Builder(ContactSyncAdapterService.this, NotificationChannelManager.PERMISSION_REQUESTS)
|
||||
.setAutoCancel(true)
|
||||
.setSmallIcon(R.drawable.ic_stat_notify_24dp)
|
||||
.setColor(getResources().getColor(R.color.primary))
|
||||
.setContentTitle(getString(R.string.sync_notification_permission_required_title))
|
||||
.setContentText(getString(R.string.sync_notification_permission_required_text))
|
||||
.setContentIntent(resultPendingIntent);
|
||||
NotificationManagerCompat.from(ContactSyncAdapterService.this)
|
||||
.notify(NOTIFICATION_ID_SYNC_SETTINGS, mBuilder.build());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return new ContactSyncAdapter().getSyncAdapterBinder();
|
||||
}
|
||||
|
||||
public static void requestContactsSync() {
|
||||
// if user has disabled automatic sync, do nothing
|
||||
boolean isSyncEnabled = ContentResolver.getSyncAutomatically(new Account
|
||||
(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE), ContactsContract.AUTHORITY);
|
||||
|
||||
if (!isSyncEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
// no need to wait, do it immediately
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
|
||||
extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
|
||||
ContentResolver.requestSync(
|
||||
new Account(Constants.ACCOUNT_NAME, Constants.ACCOUNT_TYPE),
|
||||
ContactsContract.AUTHORITY,
|
||||
extras);
|
||||
}
|
||||
|
||||
public static void enableContactsSync(Context context) {
|
||||
Account account = KeychainApplication.createAccountIfNecessary(context);
|
||||
if (account == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ContentResolver.setIsSyncable(account, ContactsContract.AUTHORITY, 1);
|
||||
ContentResolver.setSyncAutomatically(account, ContactsContract.AUTHORITY, true);
|
||||
}
|
||||
|
||||
// TODO: Import is currently disabled, until we implement proper origin management
|
||||
// private static void importKeys() {
|
||||
// importDone.set(false);
|
||||
// KeychainApplication.setupAccountAsNeeded(ContactSyncAdapterService.this);
|
||||
// EmailKeyHelper.importContacts(getContext(), new Messenger(new Handler(Looper.getMainLooper(),
|
||||
// new Handler.Callback() {
|
||||
// @Override
|
||||
// public boolean handleMessage(Message msg) {
|
||||
// Bundle data = msg.getInputData();
|
||||
// switch (msg.arg1) {
|
||||
// case KeychainIntentServiceHandler.MESSAGE_OKAY:
|
||||
// Log.d(Constants.TAG, "Syncing... Done.");
|
||||
// synchronized (importDone) {
|
||||
// importDone.set(true);
|
||||
// importDone.notifyAll();
|
||||
// }
|
||||
// return true;
|
||||
// case KeychainIntentServiceHandler.MESSAGE_UPDATE_PROGRESS:
|
||||
// if (data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS) &&
|
||||
// data.containsKey(KeychainIntentServiceHandler.DATA_PROGRESS_MAX)) {
|
||||
// Log.d(Constants.TAG, "Syncing... Progress: " +
|
||||
// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS) + "/" +
|
||||
// data.getInt(KeychainIntentServiceHandler.DATA_PROGRESS_MAX));
|
||||
// return false;
|
||||
// }
|
||||
// default:
|
||||
// Log.d(Constants.TAG, "Syncing... " + msg.toString());
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// })));
|
||||
// synchronized (importDone) {
|
||||
// try {
|
||||
// if (!importDone.get()) importDone.wait();
|
||||
// } catch (InterruptedException e) {
|
||||
// Log.w(Constants.TAG, e);
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Schürmann & Breitmoser GbR
|
||||
*
|
||||
* 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.service;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
/**
|
||||
* This service actually does nothing, it's sole task is to show a Toast if the use tries to create an account.
|
||||
*/
|
||||
public class DummyAccountService extends Service {
|
||||
|
||||
private class Toaster {
|
||||
private static final String TOAST_MESSAGE = "toast_message";
|
||||
private Context context;
|
||||
private Handler handler = new Handler(new Handler.Callback() {
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
Toast.makeText(context, msg.getData().getString(TOAST_MESSAGE), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
private Toaster(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void toast(int resourceId) {
|
||||
toast(context.getString(resourceId));
|
||||
}
|
||||
|
||||
public void toast(String message) {
|
||||
Message msg = new Message();
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(TOAST_MESSAGE, message);
|
||||
msg.setData(bundle);
|
||||
handler.sendMessage(msg);
|
||||
}
|
||||
}
|
||||
|
||||
private class Authenticator extends AbstractAccountAuthenticator {
|
||||
|
||||
public Authenticator() {
|
||||
super(DummyAccountService.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response, String accountType) {
|
||||
Timber.d("DummyAccountService.editProperties");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType,
|
||||
String[] requiredFeatures, Bundle options) throws NetworkErrorException {
|
||||
response.onResult(new Bundle());
|
||||
toaster.toast(R.string.account_no_manual_account_creation);
|
||||
Timber.d("DummyAccountService.addAccount");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response, Account account, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.confirmCredentials");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType,
|
||||
Bundle options) throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.getAuthToken");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
Timber.d("DummyAccountService.getAuthTokenLabel");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response, Account account, String authTokenType,
|
||||
Bundle options) throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.updateCredentials");
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response, Account account, String[] features)
|
||||
throws NetworkErrorException {
|
||||
Timber.d("DummyAccountService.hasFeatures");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Toaster toaster;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
toaster = new Toaster(this);
|
||||
return new Authenticator().getIBinder();
|
||||
}
|
||||
}
|
|
@ -25,10 +25,8 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Parcelable;
|
||||
import androidx.core.os.CancellationSignal;
|
||||
|
||||
import org.sufficientlysecure.keychain.KeychainApplication;
|
||||
import org.sufficientlysecure.keychain.analytics.AnalyticsManager;
|
||||
import androidx.core.os.CancellationSignal;
|
||||
import org.sufficientlysecure.keychain.daos.KeyWritableRepository;
|
||||
import org.sufficientlysecure.keychain.operations.BackupOperation;
|
||||
import org.sufficientlysecure.keychain.operations.BaseOperation;
|
||||
|
@ -54,20 +52,15 @@ import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
|||
|
||||
|
||||
public class KeychainServiceTask {
|
||||
private final AnalyticsManager analyticsManager;
|
||||
|
||||
public static KeychainServiceTask create(Activity activity) {
|
||||
Context context = activity.getApplicationContext();
|
||||
KeyWritableRepository keyRepository = KeyWritableRepository.create(context);
|
||||
AnalyticsManager analyticsManager = ((KeychainApplication) activity.getApplication()).getAnalyticsManager();
|
||||
|
||||
return new KeychainServiceTask(context, keyRepository, analyticsManager);
|
||||
return new KeychainServiceTask(context, keyRepository);
|
||||
}
|
||||
|
||||
private KeychainServiceTask(Context context, KeyWritableRepository keyRepository, AnalyticsManager analyticsManager) {
|
||||
private KeychainServiceTask(Context context, KeyWritableRepository keyRepository) {
|
||||
this.context = context;
|
||||
this.keyRepository = keyRepository;
|
||||
this.analyticsManager = analyticsManager;
|
||||
}
|
||||
|
||||
private final Context context;
|
||||
|
@ -128,8 +121,6 @@ public class KeychainServiceTask {
|
|||
return null;
|
||||
}
|
||||
|
||||
analyticsManager.trackInternalServiceCall(op.getClass().getSimpleName());
|
||||