aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/OrbotRequiredDialogActivity.java
blob: 0e70cda14dccfd76f4b86c1a33e8841cc831627b (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
/*
 * Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
 * Copyright (C) 2015 Adithya Abraham Philip <adithyaphilip@gmail.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.ui;

import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.support.v4.app.FragmentActivity;
import android.view.ContextThemeWrapper;

import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
import org.sufficientlysecure.keychain.ui.util.ThemeChanger;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;

/**
 * Simply encapsulates a dialog. If orbot is not installed, it shows an install dialog, else a
 * dialog to enable orbot.
 */
public class OrbotRequiredDialogActivity extends FragmentActivity
        implements OrbotHelper.DialogActions {

    public static final int MESSAGE_ORBOT_STARTED = 1;
    public static final int MESSAGE_ORBOT_IGNORE = 2;
    public static final int MESSAGE_DIALOG_CANCEL = 3;

    // if suppplied and true will start Orbot directly without showing dialog
    public static final String EXTRA_START_ORBOT = "start_orbot";
    // used for communicating results when triggered from a service
    public static final String EXTRA_MESSENGER = "messenger";

    // to provide any previous crypto input into which proxy preference is merged
    public static final String EXTRA_CRYPTO_INPUT = "extra_crypto_input";

    public static final String RESULT_CRYPTO_INPUT = "result_crypto_input";

    private CryptoInputParcel mCryptoInputParcel;
    private Messenger mMessenger;

    private ProgressDialog mShowOrbotProgressDialog;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mCryptoInputParcel = getIntent().getParcelableExtra(EXTRA_CRYPTO_INPUT);
        if (mCryptoInputParcel == null) {
            // compatibility with usages that don't use a CryptoInputParcel
            mCryptoInputParcel = new CryptoInputParcel();
        }

        mMessenger = getIntent().getParcelableExtra(EXTRA_MESSENGER);

        boolean startOrbotDirect = getIntent().getBooleanExtra(EXTRA_START_ORBOT, false);
        if (startOrbotDirect) {
            ContextThemeWrapper theme = ThemeChanger.getDialogThemeWrapper(this);
            mShowOrbotProgressDialog = new ProgressDialog(theme);
            mShowOrbotProgressDialog.setTitle(R.string.progress_starting_orbot);
            mShowOrbotProgressDialog.setCancelable(false);
            mShowOrbotProgressDialog.show();
            OrbotHelper.bestPossibleOrbotStart(this, this, false);
        } else {
            showDialog();
        }
    }

    /**
     * Displays an install or start orbot dialog (or silent orbot start) depending on orbot's
     * presence and state
     */
    public void showDialog() {
        DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
            public void run() {

                if (OrbotHelper.putOrbotInRequiredState(OrbotRequiredDialogActivity.this,
                        OrbotRequiredDialogActivity.this)) {
                    // no action required after all
                    onOrbotStarted();
                }
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case OrbotHelper.START_TOR_RESULT: {
                dismissOrbotProgressDialog();
                // unfortunately, this result is returned immediately and not when Orbot is started
                // 10s is approximately the longest time Orbot has taken to start
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        onOrbotStarted(); // assumption that orbot was started
                    }
                }, 10000);
            }
        }
    }

    /**
     * for when Orbot is started without showing the dialog by the EXTRA_START_ORBOT intent extra
     */
    private void dismissOrbotProgressDialog() {
        if (mShowOrbotProgressDialog != null) {
            mShowOrbotProgressDialog.dismiss();
        }
    }

    @Override
    public void onOrbotStarted() {
        dismissOrbotProgressDialog();
        sendMessage(MESSAGE_ORBOT_STARTED);
        Intent intent = new Intent();
        // send back unmodified CryptoInputParcel for a retry
        intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
        setResult(RESULT_OK, intent);
        finish();
    }

    @Override
    public void onNeutralButton() {
        sendMessage(MESSAGE_ORBOT_IGNORE);
        Intent intent = new Intent();
        mCryptoInputParcel.addParcelableProxy(ParcelableProxy.getForNoProxy());
        intent.putExtra(RESULT_CRYPTO_INPUT, mCryptoInputParcel);
        setResult(RESULT_OK, intent);
        finish();
    }

    @Override
    public void onCancel() {
        sendMessage(MESSAGE_DIALOG_CANCEL);
        finish();
    }

    private void sendMessage(int what) {
        if (mMessenger != null) {
            Message msg = Message.obtain();
            msg.what = what;
            try {
                mMessenger.send(msg);
            } catch (RemoteException e) {
                Log.e(Constants.TAG, "Could not deliver message", e);
            }
        }
    }
}