/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package info.guardianproject.otr.app.im.app;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.viewpagerindicator.PageIndicator;
import info.guardianproject.onionkit.ui.OrbotHelper;
import info.guardianproject.otr.OtrAndroidKeyManagerImpl;
import info.guardianproject.otr.OtrDebugLogger;
import info.guardianproject.otr.app.im.R;
import info.guardianproject.otr.app.im.plugin.xmpp.auth.GTalkOAuth2;
import info.guardianproject.otr.app.im.provider.Imps;
import java.util.List;
import java.util.UUID;
public class AccountWizardActivity extends ThemeableActivity {
private static final String TAG = ImApp.LOG_TAG;
private AccountAdapter mAdapter;
private ImApp mApp;
private SimpleAlertHandler mHandler;
private SignInHelper mSignInHelper;
private static final int REQUEST_CREATE_ACCOUNT = RESULT_FIRST_USER + 2;
private static final String GOOGLE_ACCOUNT = "google_account";
private static final String EXISTING_ACCOUNT = "existing_account";
private static final String NEW_ACCOUNT = "new_account";
private static final String BONJOUR_ACCOUNT = "bonjour_account";
private static final String BURNER_ACCOUNT = "secret_account";
/**
* The pager widget, which handles animation and allows swiping horizontally to access previous
* and next wizard steps.
*/
private ViewPager mPager;
/**
* The pager adapter, which provides the pages to the view pager widget.
*/
private PagerAdapter mPagerAdapter;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
protected void onCreate(Bundle icicle) {
if(Build.VERSION.SDK_INT >= 11)
getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
super.onCreate(icicle);
getSupportActionBar().hide();
mApp = (ImApp)getApplication();
mApp.maybeInit(this);
mApp.setAppTheme(this);
if (!Imps.isUnlocked(this)) {
onDBLocked();
return;
}
mHandler = new MyHandler(this);
mSignInHelper = new SignInHelper(this);
buildAccountList();
setContentView(R.layout.account_list_activity);
// Instantiate a ViewPager and a PagerAdapter.
mPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new WizardPagerAdapter(getSupportFragmentManager());
mPager.setAdapter(mPagerAdapter);
PageIndicator titleIndicator = (PageIndicator) findViewById(R.id.indicator);
titleIndicator.setViewPager(mPager);
}
AccountAdapter getAdapter() {
return mAdapter;
}
@Override
protected void onPause() {
mHandler.unregisterForBroadcastEvents();
super.onPause();
}
@Override
protected void onDestroy() {
if (mSignInHelper != null) // if !Imps.isUnlocked(this)
mSignInHelper.stop();
if (mAdapter != null)
mAdapter.swapCursor(null);
unbindDrawables(findViewById(R.id.RootView));
System.gc();
super.onDestroy();
}
private void unbindDrawables(View view) {
if (view != null)
{
if (view.getBackground() != null) {
view.getBackground().setCallback(null);
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
unbindDrawables(((ViewGroup) view).getChildAt(i));
}
((ViewGroup) view).removeAllViews();
}
}
}
@Override
protected void onResume() {
super.onResume();
mHandler.registerForBroadcastEvents();
}
protected void gotoChats()
{
Intent intent = new Intent(this, NewChatActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("showaccounts", true);
startActivity(intent);
finish();
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
return true;
}
private String[][] mAccountList;
private String mNewUser;
private ImPluginHelper helper = ImPluginHelper.getInstance(this);
Account[] mGoogleAccounts;
private void buildAccountList ()
{
int i = 0;
int accountProviders = 0;
mGoogleAccounts = AccountManager.get(this).getAccountsByType(GTalkOAuth2.TYPE_GOOGLE_ACCT);
if (mGoogleAccounts.length > 0) {
accountProviders = 5; //potentialProviders + google + create account + burner
mAccountList = new String[accountProviders][3];
mAccountList[i][0] = getString(R.string.i_want_to_chat_using_my_google_account);
mAccountList[i][1] = getString(R.string.account_google_full);
mAccountList[i][2] = GOOGLE_ACCOUNT;
i++;
} else {
accountProviders = 4;//listProviders.size() + 2; //potentialProviders + create account + burner
mAccountList = new String[accountProviders][3];
}
mAccountList[i][0] = getString(R.string.i_have_an_existing_xmpp_account);
mAccountList[i][1] = getString(R.string.account_existing_full);
mAccountList[i][2] = EXISTING_ACCOUNT;
i++;
mAccountList[i][0] = getString(R.string.i_need_a_new_account);
mAccountList[i][1] = getString(R.string.account_new_full);
mAccountList[i][2] = NEW_ACCOUNT;
i++;
mAccountList[i][0] = getString(R.string.i_want_to_chat_on_my_local_wifi_network_bonjour_zeroconf_);
mAccountList[i][1] = getString(R.string.account_wifi_full);
mAccountList[i][2] = BONJOUR_ACCOUNT;
i++;
mAccountList[i][0] = getString(R.string.i_need_a_burner_one_time_throwaway_account_);
mAccountList[i][1] = getString(R.string.account_burner_full);
mAccountList[i][2] = BURNER_ACCOUNT;
i++;
}
private Handler mHandlerGoogleAuth = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
private void addGoogleAccount ()
{
// mNewUser = newUser;
AlertDialog.Builder builderSingle = new AlertDialog.Builder(
this);
// builderSingle.setTitle("Select One Name:-");
final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
this,
android.R.layout.select_dialog_singlechoice);
for (Account gAccount : mGoogleAccounts)
arrayAdapter.add(gAccount.name);
builderSingle.setNegativeButton(R.string.cancel,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builderSingle.setAdapter(arrayAdapter,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
mNewUser = arrayAdapter.getItem(which);
Thread thread = new Thread ()
{
@Override
public void run ()
{
//get the oauth token
//don't store anything just make sure it works!
String password = GTalkOAuth2.NAME + ':' + GTalkOAuth2.getGoogleAuthTokenAllow(mNewUser, getApplicationContext(), AccountWizardActivity.this,mHandlerGoogleAuth);
//use the XMPP type plugin for google accounts, and the .NAME "X-GOOGLE-TOKEN" as the password
showSetupAccountForm(helper.getProviderNames().get(0), mNewUser,password, false, getString(R.string.google_account),false);
}
};
thread.start();
}
});
builderSingle.show();
}
public void showSetupAccountForm (String providerType, String username, String token, boolean createAccount, String formTitle, boolean hideTor)
{
long providerId = helper.createAdditionalProvider(providerType);//xmpp
// mApp.resetProviderSettings(); //clear cached provider list
Intent intent = new Intent();
intent.setAction(Intent.ACTION_INSERT);
intent.setData(ContentUris.withAppendedId(Imps.Provider.CONTENT_URI, providerId));
intent.addCategory(ImApp.IMPS_CATEGORY);
if (username != null)
intent.putExtra("newuser", username);
if (token != null)
intent.putExtra("newpass", token);
if (formTitle != null)
intent.putExtra("title", formTitle);
intent.putExtra("hideTor", hideTor);
intent.putExtra("register", createAccount);
startActivityForResult(intent,REQUEST_CREATE_ACCOUNT);
}
public void createBurnerAccount ()
{
OrbotHelper oh = new OrbotHelper(this);
if (!oh.isOrbotInstalled())
{
oh.promptToInstall(this);
return;
}
else if (!oh.isOrbotRunning())
{
oh.requestOrbotStart(this);
return;
}
//need to generate proper IMA url for account setup
String regUser = java.util.UUID.randomUUID().toString().substring(0,10).replace('-','a');
String regPass = UUID.randomUUID().toString().substring(0,16);
String regDomain = "jabber.calyxinstitute.org";
Uri uriAccountData = Uri.parse("ima://" + regUser + ':' + regPass + '@' + regDomain);
Intent intent = new Intent(this, AccountActivity.class);
intent.setAction(Intent.ACTION_INSERT);
intent.setData(uriAccountData);
intent.putExtra("useTor", true);
startActivityForResult(intent,REQUEST_CREATE_ACCOUNT);
}
private final class MyHandler extends SimpleAlertHandler {
public MyHandler(Activity activity) {
super(activity);
}
@Override
public void handleMessage(Message msg) {
if (msg.what == ImApp.EVENT_CONNECTION_DISCONNECTED) {
promptDisconnectedEvent(msg);
}
super.handleMessage(msg);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == IntentIntegrator.REQUEST_CODE) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode,
data);
if (scanResult != null) {
OtrAndroidKeyManagerImpl.handleKeyScanResult(scanResult.getContents(), this);
}
}
else if (requestCode == REQUEST_CREATE_ACCOUNT)
{
// if (resultCode == RESULT_OK)
// {
gotoChats();
// }
}
}
public void onDBLocked() {
Intent intent = new Intent(getApplicationContext(), WelcomeActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
public static class WizardPageFragment extends Fragment {
private TextView mAccountInfo = null;
private TextView mAccountDetail = null;
private Button mButtonAddAccount = null;
private String mAccountInfoText = null;
private String mAccountDetailText = null;
private String mButtonText = null;
private OnClickListener mOcl = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.account_wizard_slider, container, false);
mAccountInfo = (TextView)rootView.findViewById(R.id.lblAccountTypeInfo);
mAccountDetail = (TextView)rootView.findViewById(R.id.lblAccountTypeDetail);
mButtonAddAccount = (Button)rootView.findViewById(R.id.btnAddAccount);
if (mButtonText != null)
mButtonAddAccount.setText(mButtonText);
mAccountInfo.setText(mAccountInfoText);
mAccountDetail.setText(mAccountDetailText);
mButtonAddAccount.setOnClickListener(mOcl);
setRetainInstance(true);
return rootView;
}
public void setAccountInfo (String accountInfoText, String accountDetailText, String mButtonText)
{
mAccountInfoText = accountInfoText;
mAccountDetailText = accountDetailText;
}
public void setOnClickListener(OnClickListener ocl)
{
mOcl = ocl;
}
}
/**
* A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
* sequence.
*/
private class WizardPagerAdapter extends FragmentStatePagerAdapter {
public WizardPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(final int pos) {
WizardPageFragment wpf = new WizardPageFragment();
wpf.setAccountInfo(mAccountList[pos][0],mAccountList[pos][1],null);
wpf.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v) {
String accountType = mAccountList[pos][2];
if (TextUtils.equals(accountType, EXISTING_ACCOUNT))
{
//otherwise support the actual plugin-type
showSetupAccountForm(helper.getProviderNames().get(0),null, null, false,helper.getProviderNames().get(0),false);
}
else if (TextUtils.equals(accountType, BONJOUR_ACCOUNT))
{
String username = "";
String passwordPlaceholder = "password";//zeroconf doesn't need a password
showSetupAccountForm(helper.getProviderNames().get(1),username,passwordPlaceholder, false,helper.getProviderNames().get(1),true);
}
else if (TextUtils.equals(accountType, NEW_ACCOUNT))
{
showSetupAccountForm(helper.getProviderNames().get(0), null, null, true, null,false);
}
else if (TextUtils.equals(accountType, BURNER_ACCOUNT))
{
createBurnerAccount();
}
else if (TextUtils.equals(accountType, GOOGLE_ACCOUNT))
{
addGoogleAccount();
}
else
throw new IllegalArgumentException("Mystery account type!");
}
});
return wpf;
}
@Override
public int getCount() {
return mAccountList.length;
}
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
Window window = getWindow();
window.setFormat(PixelFormat.RGBA_8888);
}
}