1package eu.siacs.conversations.ui;
2
3import android.Manifest;
4import android.content.ActivityNotFoundException;
5import android.content.Intent;
6import android.content.pm.ActivityInfo;
7import android.content.pm.PackageManager;
8import android.databinding.DataBindingUtil;
9import android.os.Bundle;
10import android.security.KeyChain;
11import android.security.KeyChainAliasCallback;
12import android.support.annotation.NonNull;
13import android.support.v7.app.AppCompatActivity;
14import android.support.v7.widget.Toolbar;
15import android.util.Log;
16import android.view.Menu;
17import android.view.MenuItem;
18import android.widget.Toast;
19
20import java.util.Arrays;
21import java.util.List;
22
23import eu.siacs.conversations.Config;
24import eu.siacs.conversations.R;
25import eu.siacs.conversations.databinding.ActivityWelcomeBinding;
26import eu.siacs.conversations.entities.Account;
27import eu.siacs.conversations.services.XmppConnectionService;
28import eu.siacs.conversations.utils.InstallReferrerUtils;
29import eu.siacs.conversations.utils.SignupUtils;
30import eu.siacs.conversations.utils.XmppUri;
31import eu.siacs.conversations.xmpp.Jid;
32
33import static eu.siacs.conversations.utils.PermissionUtils.allGranted;
34import static eu.siacs.conversations.utils.PermissionUtils.writeGranted;
35
36public class WelcomeActivity extends XmppActivity implements XmppConnectionService.OnAccountCreated, KeyChainAliasCallback {
37
38 private static final int REQUEST_IMPORT_BACKUP = 0x63fb;
39
40 private XmppUri inviteUri;
41
42 public static void launch(AppCompatActivity activity) {
43 Intent intent = new Intent(activity, WelcomeActivity.class);
44 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
45 activity.startActivity(intent);
46 activity.overridePendingTransition(0, 0);
47 }
48
49 public void onInstallReferrerDiscovered(final String referrer) {
50 Log.d(Config.LOGTAG, "welcome activity: on install referrer discovered " + referrer);
51 if (referrer != null) {
52 final XmppUri xmppUri = new XmppUri(referrer);
53 runOnUiThread(() -> processXmppUri(xmppUri));
54 }
55 }
56
57 private boolean processXmppUri(final XmppUri xmppUri) {
58 if (xmppUri.isValidJid()) {
59 final String preauth = xmppUri.getParameter("preauth");
60 final Jid jid = xmppUri.getJid();
61 final Intent intent;
62 if (xmppUri.isAction(XmppUri.ACTION_REGISTER)) {
63 intent = SignupUtils.getTokenRegistrationIntent(this, jid, preauth);
64 } else if (xmppUri.isAction(XmppUri.ACTION_ROSTER) && "y".equals(xmppUri.getParameter("ibr"))) {
65 intent = SignupUtils.getTokenRegistrationIntent(this, Jid.ofDomain(jid.getDomain()), preauth);
66 intent.putExtra(StartConversationActivity.EXTRA_INVITE_URI, xmppUri.toString());
67 } else {
68 intent = null;
69 }
70 if (intent != null) {
71 startActivity(intent);
72 finish();
73 return true;
74 }
75 this.inviteUri = xmppUri;
76 }
77 return false;
78 }
79
80 @Override
81 protected void refreshUiReal() {
82
83 }
84
85 @Override
86 void onBackendConnected() {
87
88 }
89
90 @Override
91 public void onStart() {
92 super.onStart();
93 final int theme = findTheme();
94 if (this.mTheme != theme) {
95 recreate();
96 }
97 new InstallReferrerUtils(this);
98 }
99
100 @Override
101 public void onStop() {
102 super.onStop();
103 }
104
105 @Override
106 public void onNewIntent(Intent intent) {
107 if (intent != null) {
108 setIntent(intent);
109 }
110 }
111
112 @Override
113 protected void onCreate(final Bundle savedInstanceState) {
114 if (getResources().getBoolean(R.bool.portrait_only)) {
115 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
116 }
117 super.onCreate(savedInstanceState);
118 ActivityWelcomeBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_welcome);
119 setSupportActionBar((Toolbar) binding.toolbar);
120 configureActionBar(getSupportActionBar(), false);
121 binding.registerNewAccount.setOnClickListener(v -> {
122 final Intent intent = new Intent(this, PickServerActivity.class);
123 addInviteUri(intent);
124 startActivity(intent);
125 });
126 binding.useExisting.setOnClickListener(v -> {
127 final List<Account> accounts = xmppConnectionService.getAccounts();
128 Intent intent = new Intent(WelcomeActivity.this, EditAccountActivity.class);
129 intent.putExtra(EditAccountActivity.EXTRA_FORCE_REGISTER, false);
130 if (accounts.size() == 1) {
131 intent.putExtra("jid", accounts.get(0).getJid().asBareJid().toString());
132 intent.putExtra("init", true);
133 } else if (accounts.size() >= 1) {
134 intent = new Intent(WelcomeActivity.this, ManageAccountActivity.class);
135 }
136 addInviteUri(intent);
137 startActivity(intent);
138 });
139
140 }
141
142 @Override
143 public boolean onCreateOptionsMenu(Menu menu) {
144 getMenuInflater().inflate(R.menu.welcome_menu, menu);
145 final MenuItem scan = menu.findItem(R.id.action_scan_qr_code);
146 scan.setVisible(getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA));
147 return super.onCreateOptionsMenu(menu);
148 }
149
150 @Override
151 public boolean onOptionsItemSelected(MenuItem item) {
152 switch (item.getItemId()) {
153 case R.id.action_import_backup:
154 if (hasStoragePermission(REQUEST_IMPORT_BACKUP)) {
155 startActivity(new Intent(this, ImportBackupActivity.class));
156 }
157 break;
158 case R.id.action_scan_qr_code:
159 UriHandlerActivity.scan(this);
160 break;
161 case R.id.action_add_account_with_cert:
162 addAccountFromKey();
163 break;
164 }
165 return super.onOptionsItemSelected(item);
166 }
167
168 private void addAccountFromKey() {
169 try {
170 KeyChain.choosePrivateKeyAlias(this, this, null, null, null, -1, null);
171 } catch (ActivityNotFoundException e) {
172 Toast.makeText(this, R.string.device_does_not_support_certificates, Toast.LENGTH_LONG).show();
173 }
174 }
175
176 @Override
177 public void alias(final String alias) {
178 if (alias != null) {
179 xmppConnectionService.createAccountFromKey(alias, this);
180 }
181 }
182
183 @Override
184 public void onAccountCreated(final Account account) {
185 final Intent intent = new Intent(this, EditAccountActivity.class);
186 intent.putExtra("jid", account.getJid().asBareJid().toString());
187 intent.putExtra("init", true);
188 addInviteUri(intent);
189 startActivity(intent);
190 }
191
192 @Override
193 public void informUser(final int r) {
194 runOnUiThread(() -> Toast.makeText(this, r, Toast.LENGTH_LONG).show());
195 }
196
197 @Override
198 public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
199 UriHandlerActivity.onRequestPermissionResult(this, requestCode, grantResults);
200 if (grantResults.length > 0) {
201 if (allGranted(grantResults)) {
202 switch (requestCode) {
203 case REQUEST_IMPORT_BACKUP:
204 startActivity(new Intent(this, ImportBackupActivity.class));
205 break;
206 }
207 } else if (Arrays.asList(permissions).contains(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
208 Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
209 }
210 }
211 if (writeGranted(grantResults, permissions)) {
212 if (xmppConnectionService != null) {
213 xmppConnectionService.restartFileObserver();
214 }
215 }
216 }
217
218 public void addInviteUri(Intent to) {
219 final Intent from = getIntent();
220 if (from != null && from.hasExtra(StartConversationActivity.EXTRA_INVITE_URI)) {
221 final String invite = from.getStringExtra(StartConversationActivity.EXTRA_INVITE_URI);
222 to.putExtra(StartConversationActivity.EXTRA_INVITE_URI, invite);
223 } else if (this.inviteUri != null) {
224 Log.d(Config.LOGTAG, "injecting referrer uri into on-boarding flow");
225 to.putExtra(StartConversationActivity.EXTRA_INVITE_URI, this.inviteUri.toString());
226 }
227 }
228
229}