aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/BaseOperation.java
blob: 99d1768b1c11e04e9edf3343d1c3b2831622541f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
 * Copyright (C) 2014-2015 Vincent Breitmoser <v.breitmoser@mugenguild.com>
 *
 * 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.operations;

import android.content.Context;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import android.support.annotation.StringRes;

import org.sufficientlysecure.keychain.Constants.key;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.pgp.PassphraseCacheInterface;
import org.sufficientlysecure.keychain.pgp.Progressable;
import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.provider.ProviderHelper.NotFoundException;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.util.Passphrase;

import java.util.concurrent.atomic.AtomicBoolean;

public abstract class BaseOperation <T extends Parcelable> implements PassphraseCacheInterface {

    final public Context mContext;
    final public Progressable mProgressable;
    final public AtomicBoolean mCancelled;

    final public ProviderHelper mProviderHelper;

    /** An abstract base class for all *Operation classes. It provides a number
     * of common methods for progress, cancellation and passphrase cache handling.
     *
     * An "operation" in this sense is a high level operation which is called
     * by the KeychainService or OpenPgpService services. Concrete
     * subclasses of this class should implement either a single or a group of
     * related operations. An operation must rely solely on its input
     * parameters for operation specifics. It should also write a log of its
     * operation using the OperationLog class, and return an OperationResult
     * subclass of its specific type.
     *
     * An operation must *not* throw exceptions of any kind, errors should be
     * handled as part of the OperationResult! Consequently, all handling of
     * errors in KeychainService and OpenPgpService should consist of
     * informational rather than operational means.
     *
     * Note that subclasses of this class should be either Android- or
     * BouncyCastle-related, and use as few imports from the other type as
     * possible.  A class with Pgp- prefix is considered BouncyCastle-related,
     * if there is no prefix it is considered Android-related.
     *
     */
    public BaseOperation(Context context, ProviderHelper providerHelper, Progressable progressable) {
        this.mContext = context;
        this.mProgressable = progressable;
        this.mProviderHelper = providerHelper;
        mCancelled = null;
    }

    public BaseOperation(Context context, ProviderHelper providerHelper,
                         Progressable progressable, AtomicBoolean cancelled) {
        mContext = context;
        mProgressable = progressable;
        mProviderHelper = providerHelper;
        mCancelled = cancelled;
    }

    @NonNull
    public abstract OperationResult execute(T input, CryptoInputParcel cryptoInput);

    public void updateProgress(@StringRes int message, int current, int total) {
        if (mProgressable != null) {
            mProgressable.setProgress(message, current, total);
        }
    }

    public void updateProgress(String message, int current, int total) {
        if (mProgressable != null) {
            mProgressable.setProgress(message, current, total);
        }
    }

    public void updateProgress(int current, int total) {
        if (mProgressable != null) {
            mProgressable.setProgress(current, total);
        }
    }

    protected boolean checkCancelled() {
        return mCancelled != null && mCancelled.get();
    }

    protected void setPreventCancel () {
        if (mProgressable != null) {
            mProgressable.setPreventCancel();
        }
    }

    @Override
    public Passphrase getCachedPassphrase(long subKeyId) throws NoSecretKeyException {
        try {
            if (subKeyId != key.symmetric) {
                long masterKeyId = mProviderHelper.getMasterKeyId(subKeyId);
                return getCachedPassphrase(masterKeyId, subKeyId);
            }
            return getCachedPassphrase(key.symmetric, key.symmetric);
        } catch (NotFoundException e) {
            throw new PassphraseCacheInterface.NoSecretKeyException();
        }
    }

    @Override
    public Passphrase getCachedPassphrase(long masterKeyId, long subKeyId) throws NoSecretKeyException {
        try {
            return PassphraseCacheService.getCachedPassphrase(
                    mContext, masterKeyId, subKeyId);
        } catch (PassphraseCacheService.KeyNotFoundException e) {
            throw new PassphraseCacheInterface.NoSecretKeyException();
        }
    }

}