From 6352bd4753c1d32334a237b0f3718480a87843fe Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 21:31:46 -0400 Subject: [PATCH 01/44] convert app description to XLIFF to make translation management easier --- .tx/config | 13 +++++++ description/source.xlf | 86 ++++++++++++++++++++++++++++++++++++++++++ external/.tx/config | 15 -------- 3 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 description/source.xlf delete mode 100644 external/.tx/config diff --git a/.tx/config b/.tx/config index 44d0e0a4..e5c960f2 100644 --- a/.tx/config +++ b/.tx/config @@ -7,4 +7,17 @@ file_filter = res/values-/strings.xml host = https://www.transifex.com source_file = res/values/strings.xml source_lang = en +type = ANDROID +[orbot.description] +file_filter = description/.xlf +host = https://www.transifex.com +source_file = description/source.xlf +source_lang = en +type = XLIFF + +[orbot.olddescription] +file_filter = releases/assets/-description.txt +host = https://www.transifex.com +source_file = releases/assets/description.txt +source_lang = en diff --git a/description/source.xlf b/description/source.xlf new file mode 100644 index 00000000..86693ef6 --- /dev/null +++ b/description/source.xlf @@ -0,0 +1,86 @@ + + + +
+ Google places strick character limits on the various text fields in Google Play. The title is 30 characters, the short description is 80 characters, and the rest of the strings, which all go together in the description, are limited to 4000 characters. +
+ + + Orbot + This is limited by Google to 30 characters + + + Protect your privacy with this proxy with Tor + This is limited by Google to 80 characters + + + Orbot is a free proxy app that empowers other apps to use the internet more securely. Orbot uses Tor to encrypt your Internet traffic and then hides it by bouncing through a series of computers around the world. Tor is free software and an open network that helps you defend against a form of network surveillance that threatens personal freedom and privacy, confidential business activities and relationships, and state security known as traffic analysis. + + + Orbot is the only app that creates a truly private internet connection. As the New York Times writes, “when a communication arrives from Tor, you can never know where or whom it’s from.” Tor won the 2012 Electronic Frontier Foundation (EFF) Pioneer Award. + + + ACCEPT NO SUBSTITUTES: Orbot is the safest way to use the Internet on Android. Period. Orbot bounces your encrypted traffic several times through computers around the world, instead of connecting you directly like VPNs and proxies. This process takes a little longer, but the strongest privacy and identity protection available is worth the wait. + + + PRIVATE WEB SURFING: Use with Orweb, the most anonymous way to access any website, even if it’s normally blocked, monitored, or on the hidden web. Get Orweb: https://goo.gl/s3mLa + + + PRIVATE CHAT MESSAGING: Use Gibberbot with Orbot to chat confidentially with anyone, anywhere for free. Get Gibberbot: https://goo.gl/O3FfS + + + PRIVACY FOR APPS: Any installed app can use Tor if it has a proxy feature, using the settings found here: https://goo.gl/2OA1y Use Orbot with Twitter, or try private web searching with DuckDuckGo: https://goo.gl/lgh1p + + + PRIVACY FOR EVERYONE: Tor can help you confidentially research a competitor, get around the Facebook block at school, or circumvent a firewall to watch sports at work. +PRIVACY MADE EASY: Check out our fun, interactive walkthrough: https://guardianproject.info/howto/browsefreely +IT’S OFFICIAL: This is the official version of the Tor onion routing service for Android. + + + ***Expert Root Mode*** + + + UNIVERSAL MODE: Orbot can be configured to transparently proxy all of your Internet traffic through Tor. You can also choose which specific apps you want to use through Tor. + + + ★ WE SPEAK YOUR LANGUAGE: Orbot is available for friends who speak: + + + العربية, azərbaycanca, български, català, Čeština, dansk, Deutsch, Ελληνικά, English, español, eesti, euskara, فارسی, suomi, français, galego, hrvatski, magyar, עברית, íslenska, italiano, 日本語, 한국어, lietuvių, latviešu, Македонци, Bahasa Melayu, Nederlands, norsk, polski, português, Русский, slovenčina, slovenščina, српски, svenska, Türkçe, українська, Tagalog, Tiếng Việt, 中文(简体), 中文(台灣) + Do not translate the names of the languages, leave them just like this. + + + Don’t see your language? Join us and help translate the app: + + + https://www.transifex.com/projects/p/orbot + Do not translate this. + + + ***Learn More*** + + + ★ ABOUT US: Guardian Project is a group of developers that make secure mobile apps and open-source code for a better tomorrow + + + ★ OUR WEBSITE: https://GuardianProject.info + + + ★ ABOUT TOR: https://TorProject.org + + + ★ ON TWITTER: https://twitter.com/guardianproject + + + ★ FREE SOFTWARE: Orbot is free software. Take a look at our source code, or join the community to make it better: + + + https://gitweb.torproject.org/orbot.git + Do not translate this. + + + ★ MESSAGE US: Are we missing your favorite feature? Found an annoying bug? Please tell us! We’d love to hear from you. Send us an email: support@guardianproject.info or find us in our chat room https://guardianproject.info/contact + + +
+
\ No newline at end of file diff --git a/external/.tx/config b/external/.tx/config deleted file mode 100644 index 8f5c518d..00000000 --- a/external/.tx/config +++ /dev/null @@ -1,15 +0,0 @@ -[main] -host = https://www.transifex.com -lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil_PH: tl-rPH, fil: tl, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he_IL: he-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id_ID: id-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr_BA: sr-rBA, sr_CS: sr-rCS, sr_ME: sr-rME, sr_RS: sr-rRS, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh_CN: zh-rCN, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA - -[orbot.stringsxml] -file_filter = ../res/values-/strings.xml -host = https://www.transifex.com -source_file = ../res/values/strings.xml -source_lang = en - -[orbot.description] -file_filter = ../releases/assets/-description.txt -host = https://www.transifex.com -source_file = ../releases/assets/description.txt -source_lang = en From 356e79a163bee025aecefdf34decaff7a6cc5761 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 14:28:13 -0400 Subject: [PATCH 02/44] remove unused IntentFilter from TorService --- AndroidManifest.xml | 16 ++++++---------- src/org/torproject/android/OrbotConstants.java | 2 -- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 30249799..f95ec157 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -88,16 +88,12 @@ - - - - - - + + Date: Mon, 8 Jun 2015 14:54:38 -0400 Subject: [PATCH 03/44] convert status variable to String for easy sharing in Intents Instead of making the apps who receive the broadcasts decipher a number scheme, send the string of the status. Then it'll be self-documenting. --- .../torproject/android/OrbotMainActivity.java | 4 +-- .../android/service/TorService.java | 26 +++++++------------ .../android/service/TorServiceConstants.java | 9 ++++--- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 786849a8..e9c96998 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -87,7 +87,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon private Toolbar mToolbar; /* Some tracking bits */ - private int torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service + private String torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service private SharedPreferences mPrefs = null; @@ -178,7 +178,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } else if (intent.hasExtra("status")) { - torStatus = intent.getIntExtra("status", TorServiceConstants.STATUS_OFF); + torStatus = intent.getStringExtra("status"); updateStatus(""); } diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 195fe98f..7a97e70a 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -84,7 +84,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public static boolean ENABLE_DEBUG_LOG = true; - private int mCurrentStatus = STATUS_OFF; + private String mCurrentStatus = STATUS_OFF; private final static int CONTROL_SOCKET_TIMEOUT = 0; @@ -223,14 +223,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - - public int getTorStatus () - { - + public String getTorStatus() { return mCurrentStatus; - } - + private void clearNotifications () { if (mNotificationManager != null) @@ -1427,7 +1423,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - public void setTorProfile(int newState) { + public void setTorProfile(String newState) { if (newState == STATUS_ON) { @@ -2111,17 +2107,13 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - private void sendCallbackStatus (int currentStatus) - { - - - Intent intent = new Intent("status"); - // You can also include some extra data. - intent.putExtra("status", currentStatus); - LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + private void sendCallbackStatus(String currentStatus) { + Intent intent = new Intent("status"); // TODO rename to proper action + // You can also include some extra data. + intent.putExtra("status", currentStatus); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } - /* * Another way to do this would be to use the Observer pattern by defining the diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 55ff6c3b..29ac47bf 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -66,10 +66,11 @@ public interface TorServiceConstants { //control port public final static String TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE = "Bootstrapped 100%"; - - public final static int STATUS_OFF = 0; - public final static int STATUS_ON = 1; - public final static int STATUS_CONNECTING = 2; + + public final static String STATUS_OFF = "OFF"; + public final static String STATUS_ON = "ON"; + public final static String STATUS_CONNECTING = "CONNECTING"; + public final static String STATUS_DISCONNECTING = "DISCONNECTING"; public static final int STATUS_MSG = 1; public static final int ENABLE_TOR_MSG = 2; From fd23da52372729166fcd4c5d59f4b9fe1ff190c8 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 15:38:22 -0400 Subject: [PATCH 04/44] purge troublesome half-disabled Wizard, rename menu to "Get Apps..." When clicking on "Wizard" from the menu, then clicking back, it gets stuck in a strange back stack purgatory, and then randomly changes the language. So purge the wizard stuff for now, and add back the parts that are still needed once that is all figured out. This also simplifies the refactoring of the Intent handling. --- AndroidManifest.xml | 3 +- ..._wizard_tips.xml => layout_promo_apps.xml} | 0 res/layout/layout_wizard.xml | 22 ---- res/layout/layout_wizard_locale.xml | 57 --------- res/menu/orbot_main.xml | 4 +- res/values/strings.xml | 2 +- .../torproject/android/OrbotMainActivity.java | 39 +------ .../ui/{wizard => }/PromoAppsActivity.java | 61 +--------- .../ui/wizard/ChooseLocaleWizardActivity.java | 108 ------------------ 9 files changed, 9 insertions(+), 287 deletions(-) rename res/layout/{layout_wizard_tips.xml => layout_promo_apps.xml} (100%) delete mode 100644 res/layout/layout_wizard.xml delete mode 100644 res/layout/layout_wizard_locale.xml rename src/org/torproject/android/ui/{wizard => }/PromoAppsActivity.java (82%) delete mode 100644 src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index f95ec157..d7912e57 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -81,8 +81,7 @@ /> - - + diff --git a/res/layout/layout_wizard_tips.xml b/res/layout/layout_promo_apps.xml similarity index 100% rename from res/layout/layout_wizard_tips.xml rename to res/layout/layout_promo_apps.xml diff --git a/res/layout/layout_wizard.xml b/res/layout/layout_wizard.xml deleted file mode 100644 index 848f7443..00000000 --- a/res/layout/layout_wizard.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/res/layout/layout_wizard_locale.xml b/res/layout/layout_wizard_locale.xml deleted file mode 100644 index ae3aecb0..00000000 --- a/res/layout/layout_wizard_locale.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/res/menu/orbot_main.xml b/res/menu/orbot_main.xml index cff67e90..f37373a8 100644 --- a/res/menu/orbot_main.xml +++ b/res/menu/orbot_main.xml @@ -57,8 +57,8 @@ --> - Start Stop About - Wizard + Get apps… Download Upload Help diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index e9c96998..15faf31b 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -14,8 +14,8 @@ import org.torproject.android.service.TorServiceConstants; import org.torproject.android.service.TorServiceUtils; import org.torproject.android.settings.SettingsPreferences; import org.torproject.android.ui.ImageProgressView; +import org.torproject.android.ui.PromoAppsActivity; import org.torproject.android.ui.Rotate3dAnimation; -import org.torproject.android.ui.wizard.PromoAppsActivity; import android.annotation.TargetApi; import android.app.Activity; @@ -32,7 +32,6 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; -import android.content.res.Configuration; import android.net.Uri; import android.net.VpnService; import android.os.Build; @@ -392,7 +391,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon Intent intent = new Intent(OrbotMainActivity.this, SettingsPreferences.class); startActivityForResult(intent, REQUEST_SETTINGS); } - else if (item.getItemId() == R.id.menu_wizard) + else if (item.getItemId() == R.id.menu_promo_apps) { startActivity(new Intent(OrbotMainActivity.this, PromoAppsActivity.class)); @@ -653,26 +652,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } } } - else - { - - showWizard = mPrefs.getBoolean("show_wizard",showWizard); - - //let's not show the wizard now for new users - - if (showWizard) - { - Editor pEdit = mPrefs.edit(); - pEdit.putBoolean("show_wizard",false); - pEdit.commit(); - showWizard = false; - - - showAlert(getString(R.string.app_name),getString(R.string.wizard_final_msg),true); - - } - - } updateStatus(""); @@ -698,19 +677,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon mBtnBridges.setChecked(true); enableBridges(true); - } - - private boolean showWizard = true; - - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - - // doLayout(); - //updateStatus(""); - } - + } /* * Launch the system activity for Uri viewing with the provided url diff --git a/src/org/torproject/android/ui/wizard/PromoAppsActivity.java b/src/org/torproject/android/ui/PromoAppsActivity.java similarity index 82% rename from src/org/torproject/android/ui/wizard/PromoAppsActivity.java rename to src/org/torproject/android/ui/PromoAppsActivity.java index 048528fd..5d120d31 100644 --- a/src/org/torproject/android/ui/wizard/PromoAppsActivity.java +++ b/src/org/torproject/android/ui/PromoAppsActivity.java @@ -1,4 +1,4 @@ -package org.torproject.android.ui.wizard; +package org.torproject.android.ui; import android.app.Activity; import android.content.Intent; @@ -10,14 +10,12 @@ import android.net.Uri; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; -import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import org.torproject.android.OrbotConstants; import org.torproject.android.R; - import java.util.List; public class PromoAppsActivity extends Activity implements OrbotConstants { @@ -42,7 +40,7 @@ public class PromoAppsActivity extends Activity implements OrbotConstants { protected void onStart() { super.onStart(); - setContentView(R.layout.layout_wizard_tips); + setContentView(R.layout.layout_promo_apps); stepFive(); @@ -169,43 +167,16 @@ public class PromoAppsActivity extends Activity implements OrbotConstants { } }); - - // Button back = ((Button)findViewById(R.id.btnWizard1)); Button next = ((Button)findViewById(R.id.btnWizard2)); - - /* - back.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - finish(); - startActivityForResult(new Intent(PromoAppsActivity.this, ChooseLocaleWizardActivity.class), 1); - } - });*/ - next.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - //showWizardFinal(); - finish(); } }); } - - - //Code to override the back button! - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ - finish(); - startActivity(new Intent(getBaseContext(), ChooseLocaleWizardActivity.class)); - return true; - } - return false; - } - boolean isAppInstalled(PackageManager pm, String packageName) { try { pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES); @@ -239,32 +210,4 @@ public class PromoAppsActivity extends Activity implements OrbotConstants { } return intent; } - - /* - private void showWizardFinal () - { - String title = null; - String msg = null; - - - title = context.getString(R.string.wizard_final); - msg = context.getString(R.string.wizard_final_msg); - - DialogInterface.OnClickListener ocListener = new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - context.startActivity(new Intent(context, Orbot.class)); - - } - }; - - - new AlertDialog.Builder(context) - .setIcon(R.drawable.icon) - .setTitle(title) - .setPositiveButton(R.string.button_close, ocListener) - .setMessage(msg) - .show(); - }*/ } diff --git a/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java b/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java deleted file mode 100644 index a804f45c..00000000 --- a/src/org/torproject/android/ui/wizard/ChooseLocaleWizardActivity.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.torproject.android.ui.wizard; - -import android.app.Activity; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.content.res.Configuration; -import android.os.Bundle; -import android.view.KeyEvent; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ListView; -import android.widget.Toast; - -import info.guardianproject.util.Languages; - -import org.torproject.android.OrbotApp; -import org.torproject.android.OrbotConstants; -import org.torproject.android.R; -import org.torproject.android.service.TorServiceUtils; - -import java.util.Locale; - -public class ChooseLocaleWizardActivity extends Activity implements OrbotConstants { - - private ListView listLocales; - private String[] localeValues; - - protected void onCreate(Bundle savedInstanceState) - { - super.onCreate(savedInstanceState); - - setContentView(R.layout.layout_wizard_locale); - - listLocales = (ListView)findViewById(R.id.wizard_locale_list); - Button next = ((Button)findViewById(R.id.btnWizard2)); - // next.setEnabled(false); - - Languages languages = OrbotApp.getLanguages(this); - localeValues = languages.getSupportedLocales(); - ArrayAdapter adapter = new ArrayAdapter(this, - android.R.layout.simple_list_item_1, android.R.id.text1, - languages.getAllNames()); - listLocales.setAdapter(adapter); - - listLocales.setSelection(0); - listLocales.setOnItemClickListener(new OnItemClickListener() { - - @Override - public void onItemClick(AdapterView arg0, View arg1, - int arg2, long arg3) { - - setLocalePref(arg2); - finish(); - startActivity(new Intent(ChooseLocaleWizardActivity.this, PromoAppsActivity.class)); - } - }); - - next.setOnClickListener(new View.OnClickListener() { - - public void onClick(View v) { - setLocalePref(0); - finish(); - startActivity(new Intent(ChooseLocaleWizardActivity.this, PromoAppsActivity.class)); - - } - }); - } - - private void setLocalePref(int selId) - { - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - Configuration config = getResources().getConfiguration(); - - String lang = localeValues[selId]; - - Editor pEdit = prefs.edit(); - pEdit.putString(PREF_DEFAULT_LOCALE, lang); - pEdit.commit(); - Locale locale = null; - - if (lang.equals("xx")) - { - locale = Locale.getDefault(); - - } - else - locale = new Locale(lang); - - Locale.setDefault(locale); - config.locale = locale; - getResources().updateConfiguration(config, getResources().getDisplayMetrics()); - } - - //Code to override the back button! - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if(keyCode == KeyEvent.KEYCODE_BACK){ - Toast.makeText(getApplicationContext(), R.string.wizard_exit_at_first_screen_toast, Toast.LENGTH_SHORT).show(); - return true; - } - return false; - } -} \ No newline at end of file From f09379d86c3c529e77b057627a34577208d35e7b Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 20:04:29 -0400 Subject: [PATCH 05/44] create String constants for Intent actions and extras Following the Android system naming convention, this uses constants for the action and extra names for Intents. This makes it much easier to track which "log" is which, since there are "log" actions, extras, and messages. --- .../torproject/android/OrbotMainActivity.java | 20 +++++++++---------- .../android/service/TorService.java | 12 +++++------ .../android/service/TorServiceConstants.java | 6 ++++++ .../android/ui/OrbotLogActivity.java | 7 ++++--- 4 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 15faf31b..fa176556 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -105,14 +105,14 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon doLayout(); - // Register to receive messages. - // We are registering an observer (mMessageReceiver) to receive Intents - // with actions named "custom-event-name". - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, - new IntentFilter("status")); + /* receive the internal status broadcasts, which are separate from the public + * status broadcasts to prevent other apps from sending fake/wrong status + * info to this app */ + LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, + new IntentFilter(TorServiceConstants.LOCAL_ACTION_STATUS)); LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, - new IntentFilter("log")); + new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); mHandler.postDelayed(new Runnable () { @@ -155,9 +155,9 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon public void onReceive(Context context, Intent intent) { // Get extra data included in the Intent - if (intent.hasExtra("log")) + if (intent.hasExtra(TorServiceConstants.LOCAL_EXTRA_LOG)) { - String log = intent.getStringExtra("log"); + String log = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); updateStatus(log); } else if (intent.hasExtra("up")) @@ -175,9 +175,9 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon mHandler.sendMessage(msg); } - else if (intent.hasExtra("status")) + else if (intent.hasExtra(TorServiceConstants.EXTRA_STATUS)) { - torStatus = intent.getStringExtra("status"); + torStatus = intent.getStringExtra(TorServiceConstants.EXTRA_STATUS); updateStatus(""); } diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 7a97e70a..012bbef6 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -2083,7 +2083,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon { - Intent intent = new Intent("log"); + Intent intent = new Intent(LOCAL_ACTION_LOG); // You can also include some extra data. intent.putExtra("up",upload); intent.putExtra("down",download); @@ -2100,19 +2100,17 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon { - Intent intent = new Intent("log"); + Intent intent = new Intent(LOCAL_ACTION_LOG); // You can also include some extra data. - intent.putExtra("log", logMessage); + intent.putExtra(LOCAL_EXTRA_LOG, logMessage); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } private void sendCallbackStatus(String currentStatus) { - Intent intent = new Intent("status"); // TODO rename to proper action - // You can also include some extra data. - intent.putExtra("status", currentStatus); + Intent intent = new Intent(ACTION_STATUS); + intent.putExtra(EXTRA_STATUS, currentStatus); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); - } /* diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 29ac47bf..a269ef01 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -67,6 +67,12 @@ public interface TorServiceConstants { //control port public final static String TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE = "Bootstrapped 100%"; + public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS"; + public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; + public final static String LOCAL_ACTION_STATUS = "status"; + public final static String LOCAL_ACTION_LOG = "log"; + public final static String LOCAL_EXTRA_LOG = "log"; + public final static String STATUS_OFF = "OFF"; public final static String STATUS_ON = "ON"; public final static String STATUS_CONNECTING = "CONNECTING"; diff --git a/src/org/torproject/android/ui/OrbotLogActivity.java b/src/org/torproject/android/ui/OrbotLogActivity.java index 4a24d3f1..fbf05d2b 100644 --- a/src/org/torproject/android/ui/OrbotLogActivity.java +++ b/src/org/torproject/android/ui/OrbotLogActivity.java @@ -4,6 +4,7 @@ package org.torproject.android.ui; import org.torproject.android.OrbotConstants; +import org.torproject.android.service.TorServiceConstants; import android.app.Activity; import android.content.BroadcastReceiver; @@ -23,7 +24,7 @@ public class OrbotLogActivity extends Activity implements OrbotConstants doLayout(); LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, - new IntentFilter("log")); + new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); } @@ -38,9 +39,9 @@ public class OrbotLogActivity extends Activity implements OrbotConstants public void onReceive(Context context, Intent intent) { // Get extra data included in the Intent - if (intent.hasExtra("log")) + if (intent.hasExtra(TorServiceConstants.LOCAL_EXTRA_LOG)) { - String log = intent.getStringExtra("log"); + String log = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); updateStatus(log); } From ae83f011b24f4725c9443b75b4b7f7f26ac2f9e6 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 20:22:03 -0400 Subject: [PATCH 06/44] purge CMD_INIT/initialize() from TorService, an IntentService doesn't need it when switching to an IntentService, a new Intent will always start the Service, and onCreate() can be used to initialize the Service. --- src/org/torproject/android/OrbotMainActivity.java | 10 ---------- src/org/torproject/android/service/OnBootReceiver.java | 3 --- src/org/torproject/android/service/TorService.java | 8 -------- .../android/service/TorServiceConstants.java | 1 - 4 files changed, 22 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index fa176556..2f1e67a9 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -113,16 +113,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); - - mHandler.postDelayed(new Runnable () - { - - public void run () - { - startService(TorServiceConstants.CMD_INIT); - } - },INIT_DELAY); - } diff --git a/src/org/torproject/android/service/OnBootReceiver.java b/src/org/torproject/android/service/OnBootReceiver.java index a97091e1..bc667b26 100644 --- a/src/org/torproject/android/service/OnBootReceiver.java +++ b/src/org/torproject/android/service/OnBootReceiver.java @@ -20,13 +20,10 @@ public class OnBootReceiver extends BroadcastReceiver { if (startOnBoot) { - - startService(TorServiceConstants.CMD_INIT,context); startService(TorServiceConstants.CMD_START,context); if (useVPN) startVpnService(context); - } } diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 012bbef6..4e23e727 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -375,9 +375,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon setTorProfile(STATUS_ON); }else if (action.equals(CMD_STOP)){ setTorProfile(STATUS_OFF); - }else if (action.equals(CMD_INIT)){ - initialize(); - sendCallbackStatus(mCurrentStatus); }else if (action.equals(CMD_NEWNYM)){ newIdentity(); }else if (action.equals(CMD_FLUSH)){ @@ -623,11 +620,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon @Override public void onCreate() { super.onCreate(); - initialize(); - } - - private void initialize() - { try { mNumberFormat = NumberFormat.getInstance(Locale.getDefault()); //localized numbers! diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index a269ef01..2a238952 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -87,7 +87,6 @@ public interface TorServiceConstants { public static final String CMD_STOP = "stop"; public static final String CMD_FLUSH = "flush"; public static final String CMD_NEWNYM = "newnym"; - public static final String CMD_INIT = "init"; public static final String CMD_VPN = "vpn"; public static final String CMD_VPN_CLEAR = "vpnclear"; public static final String CMD_UPDATE = "update"; From 12d92f48f5f43ccb80da63698765478df46eb46e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 20:42:18 -0400 Subject: [PATCH 07/44] handle logging native process Exceptions closer to the source Instead of passing Exceptions through many layers only to log them, just log them where they are thrown. Keeps things neater. --- .../android/service/TorService.java | 70 ++++++++----------- .../android/service/TorTransProxy.java | 20 +++--- 2 files changed, 40 insertions(+), 50 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 4e23e727..23801f33 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -348,11 +348,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon * @see android.app.Service#onStart(android.content.Intent, int) */ public int onStartCommand(Intent intent, int flags, int startId) { + if (intent != null) + new Thread (new TorStarter(intent)).start(); + else + Log.d(TAG, "Got null onStartCommand() intent"); - new Thread (new TorStarter(intent)).start(); - return Service.START_STICKY; - } private class TorStarter implements Runnable @@ -364,36 +365,27 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mIntent = intent; } - public void run (){ - try{ - //if this is a start on boot launch turn tor on - if (mIntent != null){ - String action = mIntent.getAction(); - - if (action!=null){ - if(action.equals(Intent.ACTION_BOOT_COMPLETED)||action.equals(CMD_START)){ - setTorProfile(STATUS_ON); - }else if (action.equals(CMD_STOP)){ - setTorProfile(STATUS_OFF); - }else if (action.equals(CMD_NEWNYM)){ - newIdentity(); - }else if (action.equals(CMD_FLUSH)){ - flushTransparentProxyRules(); - }else if (action.equals(CMD_UPDATE)){ - processSettings(); - }else if (action.equals(CMD_VPN)){ - enableVpnProxy(); - } - else if (action.equals(CMD_VPN_CLEAR)){ - clearVpnProxy(); - } - } - }else{ - Log.d(TAG, "Got null onStartCommand() intent"); + public void run() { + String action = mIntent.getAction(); + + if (action != null) { + if (action.equals(Intent.ACTION_BOOT_COMPLETED) || action.equals(CMD_START)) { + setTorProfile(STATUS_ON); + } else if (action.equals(CMD_STOP)) { + setTorProfile(STATUS_OFF); + } else if (action.equals(CMD_NEWNYM)) { + newIdentity(); + } else if (action.equals(CMD_FLUSH)) { + flushTransparentProxyRules(); + } else if (action.equals(CMD_UPDATE)) { + processSettings(); + } else if (action.equals(CMD_VPN)) { + enableVpnProxy(); + } else if (action.equals(CMD_VPN_CLEAR)) { + clearVpnProxy(); + } else { + Log.w(TAG, "unhandled TorService Intent: " + action); } - - }catch (Exception e){ - Log.e(TAG,"error onBind",e); } } } @@ -879,18 +871,18 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon shellUser.close(); } - private boolean flushTransparentProxyRules () throws Exception - { - + private boolean flushTransparentProxyRules () { if (mHasRoot) { if (mTransProxy == null) - { mTransProxy = new TorTransProxy(this, fileXtables); - + + try { + mTransProxy.flushTransproxyRules(this); + } catch (Exception e) { + e.printStackTrace(); + return false; } - - mTransProxy.flushTransproxyRules(this); return true; } diff --git a/src/org/torproject/android/service/TorTransProxy.java b/src/org/torproject/android/service/TorTransProxy.java index 89663fbc..d63abb24 100644 --- a/src/org/torproject/android/service/TorTransProxy.java +++ b/src/org/torproject/android/service/TorTransProxy.java @@ -3,8 +3,6 @@ package org.torproject.android.service; import java.io.File; import java.io.IOException; import java.util.ArrayList; -import java.util.concurrent.TimeoutException; - import org.sufficientlysecure.rootcommands.Shell; import org.sufficientlysecure.rootcommands.command.SimpleCommand; import org.torproject.android.OrbotConstants; @@ -12,7 +10,6 @@ import org.torproject.android.settings.TorifiedApp; import android.content.Context; import android.content.SharedPreferences; -import android.util.Log; public class TorTransProxy implements TorServiceConstants { @@ -335,7 +332,7 @@ public class TorTransProxy implements TorServiceConstants { return code; }*/ - public int setTransparentProxyingByApp(Context context, ArrayList apps, boolean enableRule, Shell shell) throws Exception + public int setTransparentProxyingByApp(Context context, ArrayList apps, boolean enableRule, Shell shell) { String ipTablesPath = getIpTablesPath(context); @@ -439,10 +436,13 @@ public class TorTransProxy implements TorServiceConstants { return lastExit; } - private int executeCommand (Shell shell, String cmdString) throws IOException, TimeoutException - { + private int executeCommand (Shell shell, String cmdString) { SimpleCommand cmd = new SimpleCommand(cmdString); - shell.add(cmd); + try { + shell.add(cmd); + } catch (IOException e) { + e.printStackTrace(); + } int exitCode = cmd.getExitCode(); String output = cmd.getOutput(); @@ -524,8 +524,7 @@ public class TorTransProxy implements TorServiceConstants { } - public int dropAllIPv6Traffic (Context context, int appUid, boolean enableDrop, Shell shell) throws Exception - { + public int dropAllIPv6Traffic (Context context, int appUid, boolean enableDrop, Shell shell) { String action = " -A "; String chain = "OUTPUT"; @@ -575,8 +574,7 @@ public class TorTransProxy implements TorServiceConstants { return lastExit; }*/ - public int flushTransproxyRules (Context context) throws Exception - { + public int flushTransproxyRules (Context context) throws IOException { int exit = -1; String ipTablesPath = getIpTablesPath(context); From 6e13a7e369a8a33ed14602672872e5445a3bd01c Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 20:43:02 -0400 Subject: [PATCH 08/44] purge dead and unused code from TorService --- .../android/service/TorService.java | 94 +------------------ 1 file changed, 2 insertions(+), 92 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 23801f33..38b4bd3f 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -146,7 +146,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private boolean mUseVPN = false; boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; - private ExecutorService mExecutor = Executors.newFixedThreadPool(1); private NumberFormat mNumberFormat = null; @@ -210,7 +209,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon else return false; } - /* (non-Javadoc) * @see android.app.Service#onLowMemory() @@ -223,10 +221,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - public String getTorStatus() { - return mCurrentStatus; - } - private void clearNotifications () { if (mNotificationManager != null) @@ -235,7 +229,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon hmBuiltNodes.clear(); mNotificationShowing = false; - } @SuppressLint("NewApi") @@ -280,27 +273,21 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mNotification = mNotifyBuilder.build(); if (Build.VERSION.SDK_INT >= 16 && mShowExpandedNotifications) { - - // Create remote view that needs to be set as bigContentView for the notification. RemoteViews expandedView = new RemoteViews(this.getPackageName(), R.layout.layout_notification_expanded); StringBuffer sbInfo = new StringBuffer(); - if (notifyType == NOTIFY_ID) expandedView.setTextViewText(R.id.text, notifyMsg); else { expandedView.setTextViewText(R.id.info, notifyMsg); - } if (hmBuiltNodes.size() > 0) { - //sbInfo.append(getString(R.string.your_tor_public_ips_) + '\n '); - Set itBuiltNodes = hmBuiltNodes.keySet(); for (String key : itBuiltNodes) { @@ -626,7 +613,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - initBinariesAndDirectories(); updateSettings(); @@ -1107,11 +1093,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private int initControlConnection (int maxTries, boolean isReconnect) throws Exception, RuntimeException { - int i = 0; int controlPort = -1; - int attempt = 0; - logNotice( "Waiting for control port..."); @@ -1148,9 +1131,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon // logNotice("waiting..."); Thread.sleep(1000); } catch (Exception e){} - - - } if (conn != null) @@ -1332,45 +1312,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return result; } - - /* - private void getTorStatus () throws IOException - { - try - { - - if (conn != null) - { - // get a single value. - - // get several values - - if (mCurrentStatus == STATUS_CONNECTING) - { - //Map vals = conn.getInfo(Arrays.asList(new String[]{ - // "status/bootstrap-phase", "status","version"})); - - String bsPhase = conn.getInfo("status/bootstrap-phase"); - Log.d(TAG, "bootstrap-phase: " + bsPhase); - - - } - else - { - // String status = conn.getInfo("status/circuit-established"); - // Log.d(TAG, "status/circuit-established=" + status); - } - } - } - catch (Exception e) - { - Log.d(TAG, "Unable to get Tor status from control port"); - mCurrentStatus = STATUS_UNAVAILABLE; - } - - }*/ - - + public void addEventHandler () throws Exception { // We extend NullEventHandler so that we don't need to provide empty @@ -1386,9 +1328,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon // "DEBUG", "INFO", "NOTICE", "WARN", "ERR"})); logNotice( "SUCCESS added control port event handler"); - - - } /** @@ -1406,7 +1345,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return mPortSOCKS; } - public void setTorProfile(String newState) { if (newState == STATUS_ON) @@ -2473,7 +2411,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - if (mUseVPN) { extraLines.append("DNSListenAddress" + ' ' + "10.0.0.1:" + TorServiceConstants.TOR_DNS_PORT_DEFAULT).append('\n'); @@ -2492,34 +2429,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } return new String(out); } - - /* - private void enableSocks (String socks, boolean safeSocks) throws RemoteException - { - updateConfiguration("SOCKSPort", socks, false); - updateConfiguration("SafeSocks", safeSocks ? "1" : "0", false); - updateConfiguration("TestSocks", "1", false); - updateConfiguration("WarnUnsafeSocks", "1", false); - saveConfiguration(); - - } - - private void enableTransProxyAndDNSPorts (String transPort, String dnsPort) throws RemoteException - { - logMessage ("Transparent Proxying: enabling port..."); - - updateConfiguration("TransPort",transPort,false); - updateConfiguration("DNSPort",dnsPort,false); - updateConfiguration("VirtualAddrNetwork","10.192.0.0/10",false); - updateConfiguration("AutomapHostsOnResolve","1",false); - saveConfiguration(); - }*/ - - private void blockPlaintextPorts (String portList) throws RemoteException - { - updateConfiguration("RejectPlaintextPorts",portList,false); - } - + //using Google DNS for now as the public DNS server private String writeDNSFile () throws IOException { From a3d37e8b2a3d7da43188ca54bd471d209f38bc02 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 22:57:42 -0400 Subject: [PATCH 09/44] make prefs called directly when needed instead of requiring refresh The code was using global variables that were refreshed from the prefs on certain occasions. That means that the global vars could easily get out of sync with the actual values. Instead, just read the prefs directly when the values are needed, and they will always be up-to-date. --- src/org/torproject/android/OrbotApp.java | 16 +- .../torproject/android/OrbotConstants.java | 13 -- .../torproject/android/OrbotMainActivity.java | 62 +++----- src/org/torproject/android/Prefs.java | 116 ++++++++++++++ .../android/service/OnBootReceiver.java | 15 +- .../android/service/TorService.java | 141 ++++++------------ .../android/service/TorServiceConstants.java | 2 +- .../android/service/TorTransProxy.java | 16 +- 8 files changed, 191 insertions(+), 190 deletions(-) create mode 100644 src/org/torproject/android/Prefs.java diff --git a/src/org/torproject/android/OrbotApp.java b/src/org/torproject/android/OrbotApp.java index 070d7d73..c6f47971 100644 --- a/src/org/torproject/android/OrbotApp.java +++ b/src/org/torproject/android/OrbotApp.java @@ -5,8 +5,6 @@ import android.annotation.TargetApi; import android.app.Activity; import android.app.Application; import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.os.Build; import android.text.TextUtils; @@ -14,29 +12,26 @@ import android.util.Log; import info.guardianproject.util.Languages; -import org.torproject.android.service.TorServiceUtils; - import java.util.Locale; public class OrbotApp extends Application implements OrbotConstants { private Locale locale; - private SharedPreferences prefs; @Override public void onCreate() { super.onCreate(); + Prefs.setContext(this); - prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - setNewLocale(prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage())); + setNewLocale(Prefs.getDefaultLocale()); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.i(TAG, "onConfigurationChanged " + newConfig.locale.getLanguage()); - setNewLocale(prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage())); + setNewLocale(Prefs.getDefaultLocale()); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) @@ -65,10 +60,7 @@ public class OrbotApp extends Application implements OrbotConstants * wrong. If setting the locale causes an Exception, it should be set in * the preferences, otherwise ChatSecure will be stuck in a crash loop. */ - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(this); - Editor prefEdit = prefs.edit(); - prefEdit.putString(PREF_DEFAULT_LOCALE, language); - prefEdit.apply(); + Prefs.setDefaultLocale(language); Log.i(TAG, "setNewLocale complete: locale: " + locale.getLanguage() + " Locale.getDefault: " + Locale.getDefault().getLanguage()); } diff --git a/src/org/torproject/android/OrbotConstants.java b/src/org/torproject/android/OrbotConstants.java index f1521e8e..373ff3fd 100644 --- a/src/org/torproject/android/OrbotConstants.java +++ b/src/org/torproject/android/OrbotConstants.java @@ -6,7 +6,6 @@ package org.torproject.android; public interface OrbotConstants { public final static String TAG = "Orbot"; - public final static String PREFS_KEY = "OrbotPrefs"; public final static String PREFS_KEY_TORIFIED = "PrefTord"; @@ -22,27 +21,15 @@ public interface OrbotConstants { public final static String HANDLER_TOR_MSG = "torServiceMsg"; - public final static String PREF_BRIDGES_ENABLED = "pref_bridges_enabled"; public final static String PREF_BRIDGES_UPDATED = "pref_bridges_enabled"; - public final static String PREF_BRIDGES_LIST = "pref_bridges_list"; //public final static String PREF_BRIDGES_OBFUSCATED = "pref_bridges_obfuscated"; public final static String PREF_OR = "pref_or"; public final static String PREF_OR_PORT = "pref_or_port"; public final static String PREF_OR_NICKNAME = "pref_or_nickname"; public final static String PREF_REACHABLE_ADDRESSES = "pref_reachable_addresses"; public final static String PREF_REACHABLE_ADDRESSES_PORTS = "pref_reachable_addresses_ports"; - public final static String PREF_TRANSPARENT = "pref_transparent"; - public final static String PREF_TRANSPARENT_ALL = "pref_transparent_all"; - - public final static String PREF_HAS_ROOT = "has_root"; public final static int RESULT_CLOSE_ALL = 0; - public final static String PREF_USE_SYSTEM_IPTABLES = "pref_use_sys_iptables"; - - public final static String PREF_PERSIST_NOTIFICATIONS = "pref_persistent_notifications"; - - public final static String PREF_DEFAULT_LOCALE = "pref_default_locale"; - public final static String PREF_DISABLE_NETWORK = "pref_disable_network"; public final static String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences"; diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 2f1e67a9..b68c9aa7 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -92,14 +92,13 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon private boolean autoStartFromIntent = false; - private final static long INIT_DELAY = 100; private final static int REQUEST_VPN = 8888; private final static int REQUEST_SETTINGS = 0x9874; /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); mPrefs.registerOnSharedPreferenceChangeListener(this); @@ -238,7 +237,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon mBtnVPN = (ToggleButton)findViewById(R.id.btnVPN); - boolean useVPN = mPrefs.getBoolean("pref_vpn", false); + boolean useVPN = Prefs.useVpn(); mBtnVPN.setChecked(useVPN); if (useVPN) @@ -262,12 +261,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon }); - mBtnBridges = (ToggleButton)findViewById(R.id.btnBridges); - boolean useBridges = mPrefs.getBoolean("pref_bridges_enabled", false); - mBtnBridges.setChecked(useBridges); - - - + mBtnBridges = (ToggleButton)findViewById(R.id.btnBridges); + mBtnBridges.setChecked(Prefs.bridgesEnabled()); mBtnBridges.setOnClickListener(new View.OnClickListener () { @@ -407,7 +402,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon else if (item.getItemId() == R.id.menu_share_bridge) { - String bridges = mPrefs.getString(OrbotConstants.PREF_BRIDGES_LIST, null); + String bridges = Prefs.getBridgesList(); if (bridges != null && bridges.length() > 0) { @@ -655,12 +650,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon showAlert(getString(R.string.bridges_updated),getString(R.string.restart_orbot_to_use_this_bridge_) + newBridgeValue,false); - Editor pEdit = mPrefs.edit(); - - pEdit.putString(OrbotConstants.PREF_BRIDGES_LIST,newBridgeValue); //set the string to a preference - pEdit.putBoolean(OrbotConstants.PREF_BRIDGES_ENABLED,true); - - pEdit.commit(); + Prefs.setBridgesList(newBridgeValue); //set the string to a preference + Prefs.putBridgesEnabled(true); setResult(RESULT_OK); @@ -675,7 +666,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon private void openBrowser(final String browserLaunchUrl,boolean forceExternal) { boolean isOrwebInstalled = appInstalledOrNot("info.guardianproject.browser"); - boolean isTransProxy = mPrefs.getBoolean("pref_transparent", false); if (mBtnVPN.isChecked()||forceExternal) { @@ -684,7 +674,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } - else if (isTransProxy) + else if (Prefs.useTransparentProxying()) { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(browserLaunchUrl)); intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP|Intent.FLAG_ACTIVITY_NEW_TASK); @@ -793,7 +783,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } else if (torStatus == TorServiceConstants.STATUS_ON) { - updateSettings(); + updateTransProxy(); Toast.makeText(this, R.string.you_may_need_to_stop_and_start_orbot_for_settings_change_to_be_enabled_, Toast.LENGTH_SHORT).show(); } @@ -867,17 +857,17 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon break; case 3: //azure - mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"2").commit(); + Prefs.setBridgesList("2"); enableBridges(true); break; case 4: //amazon - mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"1").commit(); + Prefs.setBridgesList("1"); enableBridges(true); break; case 5: //google - mPrefs.edit().putString(OrbotConstants.PREF_BRIDGES_LIST,"0").commit(); + Prefs.setBridgesList("0"); enableBridges(true); break; @@ -974,24 +964,17 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon private void enableBridges (boolean enable) { + Prefs.putBridgesEnabled(enable); - Editor edit = mPrefs.edit(); - edit.putBoolean(OrbotConstants.PREF_BRIDGES_ENABLED, enable); - edit.commit(); - - updateSettings(); - if (torStatus == TorServiceConstants.STATUS_ON) { - String bridgeList = mPrefs.getString(OrbotConstants.PREF_BRIDGES_LIST,null); + String bridgeList = Prefs.getBridgesList(); if (bridgeList != null && bridgeList.length() > 0) { restartTor (); } } - - } private void restartTor () @@ -1038,11 +1021,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon @Override public void onClick(DialogInterface dialog, int which) { - - mPrefs.edit().putBoolean("pref_vpn", true).commit(); - + Prefs.putUseVpn(true); startVpnService(); - } @@ -1090,10 +1070,9 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon return true; } - private boolean updateSettings () + private boolean updateTransProxy () { - //todo send service command - startService(TorServiceConstants.CMD_UPDATE); + startService(TorServiceConstants.CMD_UPDATE_TRANS_PROXY); return true; } @@ -1103,11 +1082,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon if (mPrefs != null) { - boolean useVPN = mPrefs.getBoolean("pref_vpn", false); - mBtnVPN.setChecked(useVPN); - - boolean useBridges = mPrefs.getBoolean("pref_bridges_enabled", false); - mBtnBridges.setChecked(useBridges); + mBtnVPN.setChecked(Prefs.useVpn()); + mBtnBridges.setChecked(Prefs.bridgesEnabled()); } mHandler.postDelayed(new Runnable () diff --git a/src/org/torproject/android/Prefs.java b/src/org/torproject/android/Prefs.java new file mode 100644 index 00000000..b1b17931 --- /dev/null +++ b/src/org/torproject/android/Prefs.java @@ -0,0 +1,116 @@ + +package org.torproject.android; + +import android.content.Context; +import android.content.SharedPreferences; +import org.torproject.android.service.TorServiceUtils; + +import java.util.Locale; + +public class Prefs { + private final static String PREF_BRIDGES_ENABLED = "pref_bridges_enabled"; + private final static String PREF_BRIDGES_LIST = "pref_bridges_list"; + private final static String PREF_DEFAULT_LOCALE = "pref_default_locale"; + private final static String PREF_ENABLE_LOGGING = "pref_enable_logging"; + private final static String PREF_EXPANDED_NOTIFICATIONS = "pref_expanded_notifications"; + private final static String PREF_HAS_ROOT = "has_root"; + private final static String PREF_PERSIST_NOTIFICATIONS = "pref_persistent_notifications"; + private final static String PREF_START_ON_BOOT = "pref_start_boot"; + private final static String PREF_TRANSPARENT = "pref_transparent"; + private final static String PREF_TRANSPARENT_ALL = "pref_transparent_all"; + private final static String PREF_TRANSPARENT_TETHERING = "pref_transparent_tethering"; + private final static String PREF_TRANSPROXY_REFRESH = "pref_transproxy_refresh"; + private final static String PREF_USE_SYSTEM_IPTABLES = "pref_use_sys_iptables"; + private final static String PREF_USE_VPN = "pref_vpn"; + + private static SharedPreferences prefs; + + public static void setContext(Context context) { + if (prefs == null) + prefs = TorServiceUtils.getSharedPrefs(context); + } + + private static void putBoolean(String key, boolean value) { + prefs.edit().putBoolean(key, value).apply(); + } + + private static void putString(String key, String value) { + prefs.edit().putString(key, value).apply(); + } + + public static boolean bridgesEnabled() { + return prefs.getBoolean(PREF_BRIDGES_ENABLED, false); + } + + public static void putBridgesEnabled(boolean value) { + putBoolean(PREF_BRIDGES_ENABLED, value); + } + + public static String getBridgesList() { + return prefs.getString(PREF_BRIDGES_LIST, ""); + } + + public static void setBridgesList(String value) { + putString(PREF_BRIDGES_LIST, value); + } + + public static String getDefaultLocale() { + return prefs.getString(PREF_DEFAULT_LOCALE, Locale.getDefault().getLanguage()); + } + + public static void setDefaultLocale(String value) { + putString(PREF_DEFAULT_LOCALE, value); + } + + public static boolean useSystemIpTables() { + return prefs.getBoolean(PREF_USE_SYSTEM_IPTABLES, false); + } + + public static boolean useRoot() { + return prefs.getBoolean(PREF_HAS_ROOT, false); + } + + public static boolean useTransparentProxying() { + return prefs.getBoolean(PREF_TRANSPARENT, false); + } + + public static boolean transparentProxyAll() { + return prefs.getBoolean(PREF_TRANSPARENT_ALL, false); + } + + public static boolean transparentTethering() { + return prefs.getBoolean(PREF_TRANSPARENT_TETHERING, false); + } + + public static boolean transProxyNetworkRefresh() { + return prefs.getBoolean(PREF_TRANSPROXY_REFRESH, false); + } + + public static boolean expandedNotifications() { + return prefs.getBoolean(PREF_EXPANDED_NOTIFICATIONS, false); + } + + public static boolean useDebugLogging() { + return prefs.getBoolean(PREF_ENABLE_LOGGING, false); + } + + public static boolean persistNotifications() { + return prefs.getBoolean(PREF_PERSIST_NOTIFICATIONS, true); + } + + public static boolean useVpn() { + return prefs.getBoolean(PREF_USE_VPN, false); + } + + public static void putUseVpn(boolean value) { + putBoolean(PREF_USE_VPN, value); + } + + public static boolean startOnBoot() { + return prefs.getBoolean(PREF_START_ON_BOOT, true); + } + + public static void putStartOnBoot(boolean value) { + putBoolean(PREF_START_ON_BOOT, value); + } +} diff --git a/src/org/torproject/android/service/OnBootReceiver.java b/src/org/torproject/android/service/OnBootReceiver.java index bc667b26..49c4ab8c 100644 --- a/src/org/torproject/android/service/OnBootReceiver.java +++ b/src/org/torproject/android/service/OnBootReceiver.java @@ -5,27 +5,22 @@ import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.net.VpnService; +import org.torproject.android.Prefs; + public class OnBootReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(context.getApplicationContext()); - - boolean startOnBoot = prefs.getBoolean("pref_start_boot",true); - boolean useVPN = prefs.getBoolean("pref_vpn",true); - - if (startOnBoot) + Prefs.setContext(context); + if (Prefs.startOnBoot()) { startService(TorServiceConstants.CMD_START,context); - if (useVPN) + if (Prefs.useVpn()) startVpnService(context); } - } @SuppressLint("NewApi") diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 38b4bd3f..9baf7231 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -8,6 +8,7 @@ package org.torproject.android.service; +import org.torproject.android.Prefs; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -82,8 +83,6 @@ import android.widget.RemoteViews; public class TorService extends Service implements TorServiceConstants, OrbotConstants, EventHandler { - public static boolean ENABLE_DEBUG_LOG = true; - private String mCurrentStatus = STATUS_OFF; private final static int CONTROL_SOCKET_TIMEOUT = 0; @@ -101,8 +100,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private static final int ERROR_NOTIFY_ID = 3; private static final int HS_NOTIFY_ID = 4; - private boolean prefPersistNotifications = true; - private static final int MAX_START_TRIES = 3; private ArrayList configBuffer = null; @@ -134,16 +131,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private NotificationManager mNotificationManager = null; private Builder mNotifyBuilder; private Notification mNotification; - private boolean mShowExpandedNotifications = false; private boolean mNotificationShowing = false; - - private boolean mHasRoot = false; - private boolean mEnableTransparentProxy = false; - private boolean mTransProxyAll = false; - private boolean mTransProxyTethering = false; - private boolean mTransProxyNetworkRefresh = false; - - private boolean mUseVPN = false; + boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP; private ExecutorService mExecutor = Executors.newFixedThreadPool(1); @@ -152,7 +141,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public void debug(String msg) { - if (ENABLE_DEBUG_LOG) + if (Prefs.useDebugLogging()) { Log.d(TAG,msg); sendCallbackLogMessage(msg); @@ -162,7 +151,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public void logException(String msg, Exception e) { - if (ENABLE_DEBUG_LOG) + if (Prefs.useDebugLogging()) { Log.e(TAG,msg,e); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -268,11 +257,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mNotifyBuilder.setTicker(null); } - mNotifyBuilder.setOngoing(prefPersistNotifications); + mNotifyBuilder.setOngoing(Prefs.persistNotifications()); mNotification = mNotifyBuilder.build(); - if (Build.VERSION.SDK_INT >= 16 && mShowExpandedNotifications) { + if (Build.VERSION.SDK_INT >= 16 && Prefs.expandedNotifications()) { // Create remote view that needs to be set as bigContentView for the notification. RemoteViews expandedView = new RemoteViews(this.getPackageName(), R.layout.layout_notification_expanded); @@ -317,7 +306,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mNotification.bigContentView = expandedView; } - if (prefPersistNotifications && (!mNotificationShowing)) + if (Prefs.persistNotifications() && (!mNotificationShowing)) { startForeground(NOTIFY_ID, mNotification); logNotice("Set background service to FOREGROUND"); @@ -364,8 +353,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon newIdentity(); } else if (action.equals(CMD_FLUSH)) { flushTransparentProxyRules(); - } else if (action.equals(CMD_UPDATE)) { - processSettings(); + } else if (action.equals(CMD_UPDATE_TRANS_PROXY)) { + processTransparentProxying(); } else if (action.equals(CMD_VPN)) { enableVpnProxy(); } else if (action.equals(CMD_VPN_CLEAR)) { @@ -394,6 +383,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon @Override public void onDestroy () { + Log.i("TorService", "onDestroy"); String msg = ("TorService is being DESTROYED... shutting down!"); Log.d(TAG, msg); sendCallbackLogMessage(msg); @@ -417,7 +407,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mCurrentStatus = STATUS_OFF; sendCallbackStatus(mCurrentStatus); - if (mHasRoot && mEnableTransparentProxy) + if (Prefs.useRoot() && Prefs.useTransparentProxying()) { Shell shellRoot = Shell.startRootShell(); disableTransparentProxy(shellRoot); @@ -564,7 +554,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon * uninstall/reinstall with different UID. */ Shell shell; - if (mHasRoot && killAttempts > 2) { + if (Prefs.useRoot() && killAttempts > 2) { shell = Shell.startRootShell(); Log.i(TAG, "using a root shell"); } else { @@ -589,7 +579,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon { if (msg != null && msg.trim().length() > 0) { - if (ENABLE_DEBUG_LOG) + if (Prefs.useDebugLogging()) Log.d(TAG, msg); sendCallbackLogMessage(msg); @@ -599,6 +589,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon @Override public void onCreate() { super.onCreate(); + Log.i("TorService", "onCreate"); + try { mNumberFormat = NumberFormat.getInstance(Locale.getDefault()); //localized numbers! @@ -614,7 +606,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } initBinariesAndDirectories(); - updateSettings(); new Thread(new Runnable () { @@ -703,7 +694,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon fileControlPort = new File(appBinHome,"control.txt"); extraLines.append(TORRC_CONTROLPORT_FILE_KEY).append(' ').append(fileControlPort.getCanonicalPath()).append('\n'); - if (mTransProxyTethering) + if (Prefs.transparentTethering()) { extraLines.append("TransListenAddress 0.0.0.0").append('\n'); extraLines.append("DNSListenAddress 0.0.0.0").append('\n'); @@ -768,29 +759,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return fileBin.canExecute(); } - - private void updateSettings () throws TimeoutException, IOException - { - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - mHasRoot = prefs.getBoolean(PREF_HAS_ROOT,false); - - mEnableTransparentProxy = prefs.getBoolean("pref_transparent", false); - mTransProxyAll = prefs.getBoolean("pref_transparent_all", false); - mTransProxyTethering = prefs.getBoolean("pref_transparent_tethering", false); - mTransProxyNetworkRefresh = prefs.getBoolean("pref_transproxy_refresh", false); - - mShowExpandedNotifications = prefs.getBoolean("pref_expanded_notifications", false); - - ENABLE_DEBUG_LOG = prefs.getBoolean("pref_enable_logging",false); - Log.i(TAG,"debug logging:" + ENABLE_DEBUG_LOG); - - prefPersistNotifications = prefs.getBoolean(OrbotConstants.PREF_PERSIST_NOTIFICATIONS, true); - - mUseVPN = prefs.getBoolean("pref_vpn", false); - } - private void startTor () throws Exception { @@ -805,19 +773,14 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon enableBinExec(fileObfsclient); enableBinExec(fileMeekclient); enableBinExec(fileXtables); - - updateSettings (); logNotice(getString(R.string.status_starting_up)); sendCallbackLogMessage(getString(R.string.status_starting_up)); ArrayList customEnv = new ArrayList(); - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - boolean useBridges = prefs.getBoolean(OrbotConstants.PREF_BRIDGES_ENABLED, false); - if (useBridges) - if (mUseVPN && !mIsLollipop) + if (Prefs.bridgesEnabled()) + if (Prefs.useVpn() && !mIsLollipop) customEnv.add("TOR_PT_PROXY=socks5://127.0.0.1:" + OrbotVpnService.mSocksProxyPort); String baseDirectory = fileTor.getParent(); @@ -830,7 +793,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (mPortHTTP != -1) runPolipoShellCmd(shellUser); - if (mHasRoot && mEnableTransparentProxy) + if (Prefs.useRoot() && Prefs.useTransparentProxying()) { Shell shellRoot = Shell.startRootShell(); @@ -840,7 +803,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon shellRoot.close(); } - if (mUseVPN) //we need to turn on VPN here so the proxy is running + if (Prefs.useVpn()) //we need to turn on VPN here so the proxy is running { enableVpnProxy(); } @@ -858,7 +821,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } private boolean flushTransparentProxyRules () { - if (mHasRoot) + if (Prefs.useRoot()) { if (mTransProxy == null) mTransProxy = new TorTransProxy(this, fileXtables); @@ -909,7 +872,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon int code = 0; // Default state is "okay" - if(mTransProxyAll) + if(Prefs.transparentProxyAll()) { code = mTransProxy.setTransparentProxyingAll(this, true, shell); @@ -926,7 +889,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (code == 0) { - if (mTransProxyTethering) + if (Prefs.transparentTethering()) { showToolbarNotification(getString(R.string.transproxy_enabled_for_tethering_), TRANSPROXY_NOTIFY_ID, R.drawable.ic_stat_tor); @@ -1404,17 +1367,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } public void enableVpnProxy () { - debug ("enabling VPN Proxy"); - - mUseVPN = true; - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - Editor ePrefs = prefs.edit(); - ePrefs.putBoolean("pref_vpn", true); - ePrefs.commit(); - - processSettings(); + Prefs.putUseVpn(true); + processTransparentProxying(); Intent intent = new Intent(TorService.this, OrbotVpnService.class); intent.setAction("start"); @@ -1458,16 +1414,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public void clearVpnProxy () { debug ("clearing VPN Proxy"); - - mUseVPN = false; - - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - Editor ePrefs = prefs.edit(); - ePrefs.putBoolean("pref_vpn", false); - ePrefs.commit(); - - processSettings(); + Prefs.putUseVpn(false); + processTransparentProxying(); Intent intent = new Intent(TorService.this, OrbotVpnService.class); intent.setAction("stop"); @@ -1556,7 +1504,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (read > 0 || written > 0) iconId = R.drawable.ic_stat_tor_xfer; - if (mConnectivity && prefPersistNotifications) + if (mConnectivity && Prefs.persistNotifications()) showToolbarNotification(sb.toString(), NOTIFY_ID, iconId); mTotalTrafficWritten += written; @@ -1631,7 +1579,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon sb.append (" > "); } - if (ENABLE_DEBUG_LOG) + if (Prefs.useDebugLogging()) debug(sb.toString()); else if(status.equals("BUILT")) { @@ -1651,7 +1599,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - if (mShowExpandedNotifications) + if (Prefs.expandedNotifications()) { //get IP from last nodename if(status.equals("BUILT")){ @@ -1707,7 +1655,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon Proxy proxy = null; - if (!mUseVPN) //if not on the VPN then we should proxy + if (!Prefs.useVpn()) //if not on the VPN then we should proxy { proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8118)); conn = new URL(ONIONOO_BASE_URL + mNode.id).openConnection(proxy); @@ -1787,21 +1735,16 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon else return node; } - - - public void processSettings (){ + public void processTransparentProxying() { try{ - boolean hadEnableTransparentProxy = mEnableTransparentProxy; - updateSettings (); - if (mHasRoot) + if (Prefs.useRoot()) { Shell shell = Shell.startRootShell(); - if (hadEnableTransparentProxy){ - disableTransparentProxy(shell); - } - if (mEnableTransparentProxy){ + if (Prefs.useTransparentProxying()){ enableTransparentProxy(shell); + } else { + disableTransparentProxy(shell); } shell.close(); } @@ -2101,7 +2044,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon { if (mConnectivity) { - if (mHasRoot && mEnableTransparentProxy && mTransProxyNetworkRefresh) + if (Prefs.useRoot() && Prefs.useTransparentProxying() && Prefs.transProxyNetworkRefresh()) { Shell shell = Shell.startRootShell(); @@ -2111,7 +2054,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon shell.close(); } - else if (mUseVPN) //we need to turn on VPN here so the proxy is running + else if (Prefs.useVpn()) //we need to turn on VPN here so the proxy is running refreshVpnProxy(); } @@ -2145,7 +2088,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon enableTransProxyAndDNSPorts(transPort, dnsPort); */ - boolean useBridges = prefs.getBoolean(OrbotConstants.PREF_BRIDGES_ENABLED, false); + boolean useBridges = Prefs.bridgesEnabled(); boolean becomeRelay = prefs.getBoolean(OrbotConstants.PREF_OR, false); boolean ReachableAddresses = prefs.getBoolean(OrbotConstants.PREF_REACHABLE_ADDRESSES,false); @@ -2161,7 +2104,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon extraLines.append("UseBridges 0").append('\n'); - if (mUseVPN) //set the proxy here if we aren't using a bridge + if (Prefs.useVpn()) //set the proxy here if we aren't using a bridge { if (!mIsLollipop) @@ -2212,7 +2155,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon extraLines.append("UseBridges 1").append('\n'); - String bridgeList = new String(prefs.getString(OrbotConstants.PREF_BRIDGES_LIST,"").getBytes("ISO-8859-1")); + String bridgeList = new String(Prefs.getBridgesList().getBytes("ISO-8859-1")); if (bridgeList != null && bridgeList.length() > 1) //longer then 1 = some real values here { @@ -2411,7 +2354,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - if (mUseVPN) + if (Prefs.useVpn()) { extraLines.append("DNSListenAddress" + ' ' + "10.0.0.1:" + TorServiceConstants.TOR_DNS_PORT_DEFAULT).append('\n'); } diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 2a238952..f466dae1 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -89,7 +89,7 @@ public interface TorServiceConstants { public static final String CMD_NEWNYM = "newnym"; public static final String CMD_VPN = "vpn"; public static final String CMD_VPN_CLEAR = "vpnclear"; - public static final String CMD_UPDATE = "update"; + public static final String CMD_UPDATE_TRANS_PROXY = "update"; public static final String BINARY_TOR_VERSION = "0.2.6.7"; diff --git a/src/org/torproject/android/service/TorTransProxy.java b/src/org/torproject/android/service/TorTransProxy.java index d63abb24..f88e46b0 100644 --- a/src/org/torproject/android/service/TorTransProxy.java +++ b/src/org/torproject/android/service/TorTransProxy.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import org.sufficientlysecure.rootcommands.Shell; import org.sufficientlysecure.rootcommands.command.SimpleCommand; import org.torproject.android.OrbotConstants; +import org.torproject.android.Prefs; import org.torproject.android.settings.TorifiedApp; import android.content.Context; @@ -13,7 +14,6 @@ import android.content.SharedPreferences; public class TorTransProxy implements TorServiceConstants { - private boolean useSystemIpTables = false; private String mSysIptables = null; private TorService mTorService = null; private File mFileXtables = null; @@ -43,12 +43,8 @@ public class TorTransProxy implements TorServiceConstants { { String ipTablesPath = null; - - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(context); - useSystemIpTables = prefs.getBoolean(OrbotConstants.PREF_USE_SYSTEM_IPTABLES, false); - - if (useSystemIpTables) + if (Prefs.useSystemIpTables()) { ipTablesPath = findSystemIPTables(); } @@ -67,11 +63,7 @@ public class TorTransProxy implements TorServiceConstants { String ipTablesPath = null; - SharedPreferences prefs = TorServiceUtils.getSharedPrefs(context); - - useSystemIpTables = prefs.getBoolean(OrbotConstants.PREF_USE_SYSTEM_IPTABLES, false); - - if (useSystemIpTables) + if (Prefs.useSystemIpTables()) { ipTablesPath = findSystemIP6Tables(); } @@ -674,7 +666,7 @@ public class TorTransProxy implements TorServiceConstants { script = new StringBuilder(); - if (TorService.ENABLE_DEBUG_LOG) + if (Prefs.useDebugLogging()) { //XXX: Comment the following rules for non-debug builds script.append(ipTablesPath); From 73658ce3cfdee85d0d4d1eacf4881f87648e8d1f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 23:21:21 -0400 Subject: [PATCH 10/44] use Java methods for setting permissions on native executables As of android-9, java.io.File has native methods for setting permissions, inherited from Java 1.6. Using these will help deal with compatibility across devices, since some devices might not have chmod installed. --- .../android/service/TorResourceInstaller.java | 15 +++++-- .../android/service/TorService.java | 40 +------------------ 2 files changed, 14 insertions(+), 41 deletions(-) diff --git a/src/org/torproject/android/service/TorResourceInstaller.java b/src/org/torproject/android/service/TorResourceInstaller.java index 3d992258..648f7524 100644 --- a/src/org/torproject/android/service/TorResourceInstaller.java +++ b/src/org/torproject/android/service/TorResourceInstaller.java @@ -8,12 +8,10 @@ import java.io.DataOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; -import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; -import java.io.PrintWriter; import java.io.StringBufferInputStream; import java.util.ArrayList; import java.util.concurrent.TimeoutException; @@ -96,11 +94,13 @@ public class TorResourceInstaller implements TorServiceConstants { outFile = new File(installFolder, OBFSCLIENT_ASSET_KEY); shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); streamToFile(is,outFile, false, true); + setExecutable(outFile); is = context.getResources().openRawResource(R.raw.meek); outFile = new File(installFolder, MEEK_ASSET_KEY); shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); streamToFile(is,outFile, false, true); + setExecutable(outFile); cpuPath = "armeabi"; } @@ -111,17 +111,19 @@ public class TorResourceInstaller implements TorServiceConstants { outFile = new File(installFolder, TOR_ASSET_KEY); shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); streamToFile(is,outFile, false, true); + setExecutable(outFile); is = context.getAssets().open(cpuPath + "/polipo.mp3"); outFile = new File(installFolder, POLIPO_ASSET_KEY); shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); streamToFile(is,outFile, false, true); + setExecutable(outFile); is = context.getAssets().open(cpuPath + "/xtables.mp3"); outFile = new File(installFolder, IPTABLES_ASSET_KEY); shell.add(new SimpleCommand(COMMAND_RM_FORCE + outFile.getAbsolutePath())).waitForFinish(); streamToFile(is,outFile, false, true); - + setExecutable(outFile); return true; } @@ -359,4 +361,11 @@ public class TorResourceInstaller implements TorServiceConstants { }*/ + private void setExecutable(File fileBin) { + fileBin.setReadable(true); + fileBin.setExecutable(true); + fileBin.setWritable(false); + fileBin.setWritable(true, true); + } + } diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 9baf7231..599d8c82 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -649,17 +649,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon appCacheHome = getDir(DIRECTORY_TOR_DATA,Application.MODE_PRIVATE); fileTor= new File(appBinHome, TOR_ASSET_KEY); - filePolipo = new File(appBinHome, POLIPO_ASSET_KEY); - fileObfsclient = new File(appBinHome, OBFSCLIENT_ASSET_KEY); - fileMeekclient = new File(appBinHome, MEEK_ASSET_KEY); - fileTorRc = new File(appBinHome, TORRC_ASSET_KEY); - fileXtables = new File(appBinHome, IPTABLES_ASSET_KEY); - + SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); String version = prefs.getString(PREF_BINARY_TOR_VERSION_INSTALLED,null); @@ -678,8 +673,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } updateTorConfigFile (); - - } private boolean updateTorConfigFile () throws FileNotFoundException, IOException, TimeoutException @@ -737,28 +730,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return success; } - - private boolean enableBinExec (File fileBin) throws Exception - { - - logNotice(fileBin.getName() + ": PRE: Is binary exec? " + fileBin.canExecute()); - - if (!fileBin.canExecute()) - { - logNotice("(re)Setting permission on binary: " + fileBin.getCanonicalPath()); - - Shell shell = Shell.startShell(); - shell.add(new SimpleCommand("chmod " + CHMOD_EXE_VALUE + ' ' + fileBin.getCanonicalPath())).waitForFinish(); - - File fileTest = new File(fileBin.getCanonicalPath()); - logNotice(fileTest.getName() + ": POST: Is binary exec? " + fileTest.canExecute()); - - shell.close(); - } - - return fileBin.canExecute(); - } - + private void startTor () throws Exception { @@ -767,12 +739,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (fileTor == null) initBinariesAndDirectories(); - - enableBinExec(fileTor); - enableBinExec(filePolipo); - enableBinExec(fileObfsclient); - enableBinExec(fileMeekclient); - enableBinExec(fileXtables); logNotice(getString(R.string.status_starting_up)); sendCallbackLogMessage(getString(R.string.status_starting_up)); @@ -1361,8 +1327,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mCurrentStatus = STATUS_OFF; sendCallbackStatus(mCurrentStatus); - - } } From 2bc85a4a3a8e260ab62b7378a933ca37ff6fffac Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 8 Jun 2015 23:38:56 -0400 Subject: [PATCH 11/44] rework killing all daemons to continue trying after a failure Before, it would quit the process on the first exception while killing. This makes it keep on trying each daemon. --- .../android/service/TorService.java | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 599d8c82..26a7df84 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -399,7 +399,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon { Log.d(TAG,"Tor is stopping NOW"); - shutdownTorProcess (); + killAllDaemons (); //stop the foreground priority and make sure to remove the persistant notification stopForeground(true); @@ -505,31 +505,49 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - private void shutdownTorProcess () throws Exception - { - - if (conn != null) - { - + private void killAllDaemons() throws CannotKillException { + if (conn != null) { logNotice("Using control port to shutdown Tor"); - try { logNotice("sending HALT signal to Tor process"); conn.shutdownTor("HALT"); - } catch (Exception e) { - Log.d(TAG,"error shutting down Tor via connection",e); + } catch (IOException e) { + Log.d(TAG, "error shutting down Tor via connection", e); } conn = null; } - killProcess(fileTor); - - killProcess(filePolipo); - killProcess(fileObfsclient); - killProcess(fileMeekclient); + // try these separately in case one fails, then it can try the next + File cannotKillFile = null; + try { + killProcess(fileObfsclient); + } catch (IOException e) { + e.printStackTrace(); + cannotKillFile = fileObfsclient; + } + try { + killProcess(fileMeekclient); + } catch (IOException e) { + e.printStackTrace(); + cannotKillFile = fileMeekclient; + } + try { + killProcess(filePolipo); + } catch (IOException e) { + e.printStackTrace(); + cannotKillFile = filePolipo; + } + try { + killProcess(fileTor); + } catch (IOException e) { + e.printStackTrace(); + cannotKillFile = fileTor; + } + if (cannotKillFile != null) + throw new CannotKillException(cannotKillFile); } public class CannotKillException extends IllegalStateException { @@ -540,7 +558,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } } - private void killProcess(File fileProcBin) throws IOException { + private void killProcess(File fileProcBin) throws IOException, CannotKillException { int procId = -1; int killAttempts = 0; From cf0adc27d6fb4e83816622bcfbf0ba53d0a6d7be Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 10:49:10 -0400 Subject: [PATCH 12/44] on start and tor daemon not running, kill all daemons before starting again To make sure there are not any other daemons still running when trying to start the whole thing again, kill all daemons before starting tor afresh. --- src/org/torproject/android/service/TorService.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 26a7df84..d56d09ab 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -167,8 +167,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } - private boolean findExistingProc () - { + private boolean findExistingTorDaemon() { if (fileTor != null) { try @@ -631,7 +630,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon { try { - findExistingProc (); + findExistingTorDaemon(); } catch (Exception e) { @@ -1305,13 +1304,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon try { - boolean found = findExistingProc (); + boolean found = findExistingTorDaemon(); if (!found) { - killProcess(fileTor); - killProcess(filePolipo); - + killAllDaemons(); startTor(); } } From 86593df6fb40ded939891011b32755ed48bbf791 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 11:23:56 -0400 Subject: [PATCH 13/44] rename status to STARTING and STOPPING since it also starts/stops daemons The CONNECTING status also is starting up daemons as well as connecting to the tor daemon. --- src/org/torproject/android/OrbotMainActivity.java | 4 ++-- src/org/torproject/android/service/TorService.java | 6 +++--- src/org/torproject/android/service/TorServiceConstants.java | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index b68c9aa7..417e8664 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -1181,7 +1181,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon Log.e(TAG, "autoStartFromIntent finish"); } } - else if (torStatus == TorServiceConstants.STATUS_CONNECTING) + else if (torStatus == TorServiceConstants.STATUS_STARTING) { imgStatus.setImageResource(R.drawable.torstarting); @@ -1225,7 +1225,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon startService (TorServiceConstants.CMD_START); - torStatus = TorServiceConstants.STATUS_CONNECTING; + torStatus = TorServiceConstants.STATUS_STARTING; mTxtOrbotLog.setText(""); diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index d56d09ab..b119a5e3 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -751,7 +751,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private void startTor () throws Exception { - mCurrentStatus = STATUS_CONNECTING; + mCurrentStatus = STATUS_STARTING; sendCallbackStatus(mCurrentStatus); if (fileTor == null) @@ -1110,7 +1110,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon conn.setConf("Log", "debug file " + fileLog2.getCanonicalPath()); }*/ - mCurrentStatus = STATUS_CONNECTING; + mCurrentStatus = STATUS_STARTING; sendCallbackStatus(mCurrentStatus); String confSocks = conn.getInfo("net/listeners/socks"); @@ -1563,7 +1563,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon else if(status.equals("BUILT")) { - if (mCurrentStatus == STATUS_CONNECTING) + if (mCurrentStatus == STATUS_STARTING) mCurrentStatus = STATUS_ON; sendCallbackStatus(mCurrentStatus); diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index f466dae1..fdf5e77f 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -75,8 +75,8 @@ public interface TorServiceConstants { public final static String STATUS_OFF = "OFF"; public final static String STATUS_ON = "ON"; - public final static String STATUS_CONNECTING = "CONNECTING"; - public final static String STATUS_DISCONNECTING = "DISCONNECTING"; + public final static String STATUS_STARTING = "STARTING"; + public final static String STATUS_STOPPING = "STOPPING"; public static final int STATUS_MSG = 1; public static final int ENABLE_TOR_MSG = 2; From 82f82e1c1032519356b11acaa26206ce02084671 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 12:16:17 -0400 Subject: [PATCH 14/44] mark TorService methods from EventHandler as overridden This keeps me from getting confused... --- .../android/service/TorService.java | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index b119a5e3..fad50a83 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -1401,35 +1401,28 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon startService(intent); } - - + @Override public void message(String severity, String msg) { - logNotice(severity + ": " + msg); if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1) { mCurrentStatus = STATUS_ON; sendCallbackStatus(mCurrentStatus); - showToolbarNotification(getString(R.string.status_activated), NOTIFY_ID, R.drawable.ic_stat_tor); } - - - } - + @Override public void newDescriptors(List orList) { } - + @Override public void orConnStatus(String status, String orName) { - StringBuilder sb = new StringBuilder(); sb.append("orConnStatus ("); sb.append(parseNodeName(orName) ); @@ -1437,10 +1430,9 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon sb.append(status); debug(sb.toString()); - } - + @Override public void streamStatus(String status, String streamID, String target) { StringBuilder sb = new StringBuilder(); @@ -1450,10 +1442,9 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon sb.append(status); logNotice(sb.toString()); - } - + @Override public void unrecognized(String type, String msg) { StringBuilder sb = new StringBuilder(); @@ -1463,10 +1454,9 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon sb.append(msg); logNotice(sb.toString()); - - } - + + @Override public void bandwidthUsed(long read, long written) { if (read != lastRead || written != lastWritten) @@ -1488,15 +1478,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon mTotalTrafficWritten += written; mTotalTrafficRead += read; - - } lastWritten = written; lastRead = read; sendCallbackStatusMessage(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead); - } private String formatCount(long count) { @@ -1516,7 +1503,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public void circuitStatus(String status, String circID, String path) { - StringBuilder sb = new StringBuilder(); sb.append("Circuit ("); sb.append((circID)); From 4470771c0dd4b9966ba53e5aa4d0539a8901c6bd Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 13:14:23 -0400 Subject: [PATCH 15/44] rename startService() to sendIntentToService() to reflect what it does Even though this method is a wrapper around startService(), it is really used to send various Intents to the Service, not only starting it. --- .../torproject/android/OrbotMainActivity.java | 35 +++++-------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 417e8664..e010e854 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -116,13 +116,10 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon - private void startService (String action) - { - + private void sendIntentToService(String action) { Intent torService = new Intent(this, TorService.class); torService.setAction(action); startService(torService); - } private void stopService () @@ -790,11 +787,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } else if (request == REQUEST_VPN && response == RESULT_OK) { - startService(TorServiceConstants.CMD_VPN); - - // if (torStatus == TorServiceConstants.STATUS_ON) - // restartTor (); - + sendIntentToService(TorServiceConstants.CMD_VPN); } IntentResult scanResult = IntentIntegrator.parseActivityResult(request, response, data); @@ -1051,28 +1044,24 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } else { - startService(TorServiceConstants.CMD_VPN); - // if (torStatus == TorServiceConstants.STATUS_ON) - // restartTor (); - + sendIntentToService(TorServiceConstants.CMD_VPN); } } public void stopVpnService () { - startService(TorServiceConstants.CMD_VPN_CLEAR); - // restartTor (); + sendIntentToService(TorServiceConstants.CMD_VPN_CLEAR); } private boolean flushTransProxy () { - startService(TorServiceConstants.CMD_FLUSH); + sendIntentToService(TorServiceConstants.CMD_FLUSH); return true; } private boolean updateTransProxy () { - startService(TorServiceConstants.CMD_UPDATE_TRANS_PROXY); + sendIntentToService(TorServiceConstants.CMD_UPDATE_TRANS_PROXY); return true; } @@ -1222,9 +1211,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon // to start Tor private void startTor () throws RemoteException { - - - startService (TorServiceConstants.CMD_START); + sendIntentToService (TorServiceConstants.CMD_START); torStatus = TorServiceConstants.STATUS_STARTING; mTxtOrbotLog.setText(""); @@ -1238,19 +1225,15 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); msg.getData().putString(HANDLER_TOR_MSG, getString(R.string.status_starting_up)); mHandler.sendMessage(msg); - - } //now we stop Tor! amazing! private void stopTor () throws RemoteException { - - startService (TorServiceConstants.CMD_STOP); + sendIntentToService (TorServiceConstants.CMD_STOP); torStatus = TorServiceConstants.STATUS_OFF; Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); mHandler.sendMessage(msg); - } /* @@ -1409,7 +1392,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon public void spinOrbot (float direction) { - startService (TorServiceConstants.CMD_NEWNYM); + sendIntentToService (TorServiceConstants.CMD_NEWNYM); Toast.makeText(this, R.string.newnym, Toast.LENGTH_SHORT).show(); From 780abf003ed38830b2140c4753312fc405c964f0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 13:20:38 -0400 Subject: [PATCH 16/44] rework start/stop procedure to have clear points for ON, OFF, STARTING, STOPPING In order to send reliable information to any app using Tor, Orbot itself needs reliable state broadcasts. Before, there the ON/OFF/STARTING state were being set multiple times during the process, and sometimes not even in a useful order (i.e. STARTING ON STARTING ON ON). This reworks the start/stop procedure into startTor() and stopTor(). --- .../android/service/TorService.java | 225 +++++++----------- 1 file changed, 86 insertions(+), 139 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index fad50a83..db2216e9 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -8,7 +8,45 @@ package org.torproject.android.service; +import android.annotation.SuppressLint; +import android.app.Application; +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Build; +import android.os.IBinder; +import android.os.RemoteException; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationCompat.Builder; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; +import android.widget.RemoteViews; + +import net.freehaven.tor.control.ConfigEntry; +import net.freehaven.tor.control.EventHandler; +import net.freehaven.tor.control.TorControlConnection; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.sufficientlysecure.rootcommands.Shell; +import org.sufficientlysecure.rootcommands.command.SimpleCommand; +import org.torproject.android.OrbotConstants; +import org.torproject.android.OrbotMainActivity; import org.torproject.android.Prefs; +import org.torproject.android.R; +import org.torproject.android.settings.AppManager; +import org.torproject.android.settings.TorifiedApp; +import org.torproject.android.vpn.OrbotVpnService; + import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -42,44 +80,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeoutException; -import net.freehaven.tor.control.ConfigEntry; -import net.freehaven.tor.control.EventHandler; -import net.freehaven.tor.control.TorControlConnection; - -import org.json.JSONArray; -import org.json.JSONObject; -import org.sufficientlysecure.rootcommands.Shell; -import org.sufficientlysecure.rootcommands.command.SimpleCommand; -import org.torproject.android.OrbotConstants; -import org.torproject.android.OrbotMainActivity; -import org.torproject.android.R; -import org.torproject.android.settings.AppManager; -import org.torproject.android.settings.TorifiedApp; -import org.torproject.android.vpn.OrbotVpnService; - -import android.annotation.SuppressLint; -import android.app.Application; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.os.Build; -import android.os.IBinder; -import android.os.RemoteException; -import android.support.v4.app.NotificationCompat; -import android.support.v4.app.NotificationCompat.Builder; -import android.support.v4.content.LocalBroadcastManager; -import android.util.Log; -import android.widget.RemoteViews; - public class TorService extends Service implements TorServiceConstants, OrbotConstants, EventHandler { @@ -344,10 +344,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon String action = mIntent.getAction(); if (action != null) { - if (action.equals(Intent.ACTION_BOOT_COMPLETED) || action.equals(CMD_START)) { - setTorProfile(STATUS_ON); + if (action.equals(CMD_START)) { + startTor(); } else if (action.equals(CMD_STOP)) { - setTorProfile(STATUS_OFF); + stopTor(); } else if (action.equals(CMD_NEWNYM)) { newIdentity(); } else if (action.equals(CMD_FLUSH)) { @@ -391,21 +391,20 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon super.onDestroy(); } - private void stopTor () - { + private void stopTor() { + Log.i("TorService", "stopTor"); + try { + mCurrentStatus = STATUS_STOPPING; + sendCallbackStatus(mCurrentStatus); - try - { + sendCallbackLogMessage(getString(R.string.status_shutting_down)); Log.d(TAG,"Tor is stopping NOW"); - killAllDaemons (); + killAllDaemons(); //stop the foreground priority and make sure to remove the persistant notification stopForeground(true); - mCurrentStatus = STATUS_OFF; - sendCallbackStatus(mCurrentStatus); - if (Prefs.useRoot() && Prefs.useTransparentProxying()) { Shell shellRoot = Shell.startRootShell(); @@ -416,7 +415,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon clearNotifications(); sendCallbackLogMessage(getString(R.string.status_disabled)); - } catch (CannotKillException e) { @@ -431,8 +429,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon Log.d(TAG, "An error occured stopping Tor",e); logNotice("An error occured stopping Tor: " + e.getMessage()); sendCallbackLogMessage(getString(R.string.something_bad_happened)); - } + + mCurrentStatus = STATUS_OFF; + sendCallbackStatus(mCurrentStatus); } @@ -748,17 +748,31 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return success; } - private void startTor () throws Exception - { + private void startTor() { + if (mCurrentStatus == STATUS_STARTING || mCurrentStatus == STATUS_STOPPING) { + // these states should probably be handled better + sendCallbackLogMessage("Ignoring start request, currently " + mCurrentStatus); + return; + } else if (mCurrentStatus == STATUS_ON) { + sendCallbackLogMessage("Ignoring start request, already started."); + return; + } mCurrentStatus = STATUS_STARTING; sendCallbackStatus(mCurrentStatus); - + sendCallbackLogMessage(getString(R.string.status_starting_up)); + logNotice(getString(R.string.status_starting_up)); + + if (findExistingTorDaemon()) { + return; // an old tor is already running, nothing to do + } + + // make sure there are no stray daemons running + killAllDaemons(); + + try { if (fileTor == null) initBinariesAndDirectories(); - - logNotice(getString(R.string.status_starting_up)); - sendCallbackLogMessage(getString(R.string.status_starting_up)); ArrayList customEnv = new ArrayList(); @@ -797,10 +811,23 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon else { showToolbarNotification(getString(R.string.unable_to_start_tor), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - } - shellUser.close(); + + mCurrentStatus = STATUS_ON; + sendCallbackStatus(mCurrentStatus); + } catch (CannotKillException e) { + logException(e.getMessage(), e); + showToolbarNotification(getString(R.string.unable_to_reset_tor), + ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); + stopTor(); + } catch (Exception e) { + logException("Unable to start Tor: " + e.toString(), e); + showToolbarNotification( + getString(R.string.unable_to_start_tor) + ": " + e.getMessage(), + ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); + stopTor(); + } } private boolean flushTransparentProxyRules () { @@ -1110,9 +1137,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon conn.setConf("Log", "debug file " + fileLog2.getCanonicalPath()); }*/ - mCurrentStatus = STATUS_STARTING; - sendCallbackStatus(mCurrentStatus); - String confSocks = conn.getInfo("net/listeners/socks"); StringTokenizer st = new StringTokenizer(confSocks," "); @@ -1290,60 +1314,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public int getSOCKSPort() throws RemoteException { return mPortSOCKS; } - - public void setTorProfile(String newState) { - - if (newState == STATUS_ON) - { - - if (mCurrentStatus == STATUS_OFF) - { - sendCallbackLogMessage (getString(R.string.status_starting_up)); - - - try - { - - boolean found = findExistingTorDaemon(); - - if (!found) - { - killAllDaemons(); - startTor(); - } - } - catch (CannotKillException e) - { - logException(e.getMessage(), e); - mCurrentStatus = STATUS_OFF; - sendCallbackStatus(mCurrentStatus); - showToolbarNotification(getString(R.string.unable_to_reset_tor), - ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - stopTor(); - } - catch (Exception e) - { - - logException("Unable to start Tor: " + e.toString(),e); - mCurrentStatus = STATUS_OFF; - sendCallbackStatus(mCurrentStatus); - - showToolbarNotification(getString(R.string.unable_to_start_tor) + ": " + e.getMessage(), ERROR_NOTIFY_ID, R.drawable.ic_stat_notifyerr); - stopTor(); - } - - } - } - else if (newState == STATUS_OFF) - { - sendCallbackLogMessage (getString(R.string.status_shutting_down)); - - stopTor(); - - mCurrentStatus = STATUS_OFF; - sendCallbackStatus(mCurrentStatus); - } - } public void enableVpnProxy () { debug ("enabling VPN Proxy"); @@ -1403,21 +1373,11 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon @Override public void message(String severity, String msg) { - logNotice(severity + ": " + msg); - - if (msg.indexOf(TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)!=-1) - { - mCurrentStatus = STATUS_ON; - sendCallbackStatus(mCurrentStatus); - - showToolbarNotification(getString(R.string.status_activated), NOTIFY_ID, R.drawable.ic_stat_tor); - } } @Override public void newDescriptors(List orList) { - } @Override @@ -1547,23 +1507,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (Prefs.useDebugLogging()) debug(sb.toString()); else if(status.equals("BUILT")) - { - - if (mCurrentStatus == STATUS_STARTING) - mCurrentStatus = STATUS_ON; - - sendCallbackStatus(mCurrentStatus); - - logNotice(sb.toString()); - - } else if (status.equals("CLOSED")) - { logNotice(sb.toString()); - } - if (Prefs.expandedNotifications()) { //get IP from last nodename From 3580cbe05d76924ef0f83d1fed47c85346736de8 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 13:33:57 -0400 Subject: [PATCH 17/44] only set mCurrentStatus in sendCallbackStatus(), the one stop shop Make sendCallbackStatus() the one thing that updates the all of the bits related to running status. --- .../android/service/TorService.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index db2216e9..a345e54f 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -178,10 +178,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (mLastProcessId != -1 && conn != null) { sendCallbackLogMessage (getString(R.string.found_existing_tor_process)); - - mCurrentStatus = STATUS_ON; - sendCallbackStatus(mCurrentStatus); - + sendCallbackStatus(STATUS_ON); return true; } @@ -394,8 +391,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private void stopTor() { Log.i("TorService", "stopTor"); try { - mCurrentStatus = STATUS_STOPPING; - sendCallbackStatus(mCurrentStatus); + sendCallbackStatus(STATUS_STOPPING); sendCallbackLogMessage(getString(R.string.status_shutting_down)); Log.d(TAG,"Tor is stopping NOW"); @@ -431,8 +427,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon sendCallbackLogMessage(getString(R.string.something_bad_happened)); } - mCurrentStatus = STATUS_OFF; - sendCallbackStatus(mCurrentStatus); + sendCallbackStatus(STATUS_OFF); } @@ -758,8 +753,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return; } - mCurrentStatus = STATUS_STARTING; - sendCallbackStatus(mCurrentStatus); + sendCallbackStatus(STATUS_STARTING); sendCallbackLogMessage(getString(R.string.status_starting_up)); logNotice(getString(R.string.status_starting_up)); @@ -814,8 +808,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } shellUser.close(); - mCurrentStatus = STATUS_ON; - sendCallbackStatus(mCurrentStatus); + sendCallbackStatus(STATUS_ON); } catch (CannotKillException e) { logException(e.getMessage(), e); showToolbarNotification(getString(R.string.unable_to_reset_tor), @@ -1885,6 +1878,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } private void sendCallbackStatus(String currentStatus) { + mCurrentStatus = currentStatus; + Intent intent = new Intent(ACTION_STATUS); intent.putExtra(EXTRA_STATUS, currentStatus); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); From 4d8a9dab27c0ba676239ac030b083e1151aa2eae Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 13:34:14 -0400 Subject: [PATCH 18/44] broadcast Tor state to any app that might want to know In order for apps to follow the current state of Tor, this broadcasts the state both locally, since global broadcasts are insecure, and globally, for any app to receive. The internal workings of Orbot need to use a local broadcast, otherwise any app could trigger stop, start, etc or DoS in other ways. --- src/org/torproject/android/service/TorService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index a345e54f..58aa9ce1 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -1882,7 +1882,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon Intent intent = new Intent(ACTION_STATUS); intent.putExtra(EXTRA_STATUS, currentStatus); + // send for Orbot internals, using secure local broadcast LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + // send for any apps that are interested + sendBroadcast(intent); } /* From bfb0a80a18b3c35cf568dbdd9839dd7580751b6c Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 13:36:58 -0400 Subject: [PATCH 19/44] rename mHandler to mStatusUpdateHandler Hopefully this will make the code a little easier to follow... --- .../torproject/android/OrbotMainActivity.java | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index e010e854..d286c471 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -153,12 +153,12 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon long written = intent.getLongExtra("written",0); long read = intent.getLongExtra("read",0); - Message msg = mHandler.obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); + Message msg = mStatusUpdateHandler.obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); msg.getData().putLong("download", download); msg.getData().putLong("upload", upload); msg.getData().putLong("readTotal", read); msg.getData().putLong("writeTotal", written); - mHandler.sendMessage(msg); + mStatusUpdateHandler.sendMessage(msg); } else if (intent.hasExtra(TorServiceConstants.EXTRA_STATUS)) @@ -977,8 +977,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon //do auto restart stopTor (); - mHandler.postDelayed(new Runnable () { - + mStatusUpdateHandler.postDelayed(new Runnable () { public void run () { try @@ -1027,9 +1026,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon public void onClick(DialogInterface dialog, int which) { mBtnVPN.setChecked(false); - } - }) .show(); @@ -1075,7 +1072,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon mBtnBridges.setChecked(Prefs.bridgesEnabled()); } - mHandler.postDelayed(new Runnable () + mStatusUpdateHandler.postDelayed(new Runnable () { public void run () { @@ -1222,9 +1219,9 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon lblStatus.setText(getString(R.string.status_starting_up)); //we send a message here to the progressDialog i believe, but we can clarify that shortly - Message msg = mHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); + Message msg = mStatusUpdateHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); msg.getData().putString(HANDLER_TOR_MSG, getString(R.string.status_starting_up)); - mHandler.sendMessage(msg); + mStatusUpdateHandler.sendMessage(msg); } //now we stop Tor! amazing! @@ -1232,8 +1229,8 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon { sendIntentToService (TorServiceConstants.CMD_STOP); torStatus = TorServiceConstants.STATUS_OFF; - Message msg = mHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); - mHandler.sendMessage(msg); + Message msg = mStatusUpdateHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); + mStatusUpdateHandler.sendMessage(msg); } /* @@ -1270,13 +1267,9 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } - - - - // this is what takes messages or values from the callback threads or other non-mainUI threads //and passes them back into the main UI thread for display to the user - private Handler mHandler = new Handler() { + private Handler mStatusUpdateHandler = new Handler() { private String lastServiceMsg = null; From 6ac9a2cee6e4b0635c69706e184b66acae048eda Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 14:01:01 -0400 Subject: [PATCH 20/44] use context.stopService() to shutdown TorService instead of custom message Since running stopService() automatically triggers Service.onDestroy(), there is a nice way to hook in and run the shutdown procedure. This provides an obvious point of entry as well as simplifying the shutdown procedure. --- res/values/strings.xml | 2 +- .../torproject/android/OrbotMainActivity.java | 114 +++++------------- .../android/service/TorService.java | 26 +--- .../android/service/TorServiceConstants.java | 1 - 4 files changed, 38 insertions(+), 105 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 7030a37f..87aa35fe 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11,7 +11,7 @@ Orbot is starting… Connected to the Tor network Orbot is deactivated - Orbot is shutting down + TorService is shutting down Starting Tor client… complete. waiting. diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index d286c471..7b0bb311 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -121,22 +121,16 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon torService.setAction(action); startService(torService); } - - private void stopService () - { - - Intent torService = new Intent(this, TorService.class); - stopService(torService); - - } - - + + private void stopTor() { + Intent torService = new Intent(this, TorService.class); + stopService(torService); + } + // Our handler for received Intents. This will be called whenever an Intent // with an action named "custom-event-name" is broadcasted. private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { - - - + @Override public void onReceive(Context context, Intent intent) { // Get extra data included in the Intent @@ -425,34 +419,21 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon } - - /** - * This is our attempt to REALLY exit Orbot, and stop the background service - * However, Android doesn't like people "quitting" apps, and/or our code may not - * be quite right b/c no matter what we do, it seems like the TorService still exists - **/ - private void doExit () - { - try { - - //one of the confusing things about all of this code is the multiple - //places where things like "stopTor" are called, both in the Activity and the Service - //not something to tackle in your first iteration, but i thin we can talk about fixing - //terminology but also making sure there are clear distinctions in control - stopTor(); - stopService (); - - - } catch (RemoteException e) { - Log.w(TAG, e); - } - - //Kill all the wizard activities - setResult(RESULT_CLOSE_ALL); - finish(); - - } - + + /** + * This is our attempt to REALLY exit Orbot, and stop the background service + * However, Android doesn't like people "quitting" apps, and/or our code may + * not be quite right b/c no matter what we do, it seems like the TorService + * still exists + **/ + private void doExit() { + stopTor(); + + // Kill all the wizard activities + setResult(RESULT_CLOSE_ALL); + finish(); + } + protected void onPause() { try { @@ -1223,49 +1204,20 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon msg.getData().putString(HANDLER_TOR_MSG, getString(R.string.status_starting_up)); mStatusUpdateHandler.sendMessage(msg); } - - //now we stop Tor! amazing! - private void stopTor () throws RemoteException - { - sendIntentToService (TorServiceConstants.CMD_STOP); - torStatus = TorServiceConstants.STATUS_OFF; - Message msg = mStatusUpdateHandler.obtainMessage(TorServiceConstants.DISABLE_TOR_MSG); - mStatusUpdateHandler.sendMessage(msg); - } - - /* - * (non-Javadoc) - * @see android.view.View.OnClickListener#onClick(android.view.View) - */ - public boolean onLongClick(View view) { - - try - { - - if (torStatus == TorServiceConstants.STATUS_OFF) - { - startTor(); - } - else - { - - stopTor(); - stopService (); - - } - - return true; - + public boolean onLongClick(View view) { + try { + if (torStatus == TorServiceConstants.STATUS_OFF) { + startTor(); + } else { + stopTor(); } - catch (Exception e) - { - Log.d(TAG,"error onclick",e); - } - - return false; - + return true; + } catch (RemoteException e) { + Log.d(TAG, "error onclick", e); } + return false; + } // this is what takes messages or values from the callback threads or other non-mainUI threads //and passes them back into the main UI thread for display to the user diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 58aa9ce1..5884f62d 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -343,8 +343,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (action != null) { if (action.equals(CMD_START)) { startTor(); - } else if (action.equals(CMD_STOP)) { - stopTor(); + // stopTor() is called when the Service is destroyed } else if (action.equals(CMD_NEWNYM)) { newIdentity(); } else if (action.equals(CMD_FLUSH)) { @@ -371,20 +370,9 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } @Override - public boolean stopService(Intent name) { - logNotice("TorService is being stopped: " + name); - return super.stopService(name); - } - - @Override - public void onDestroy () - { - Log.i("TorService", "onDestroy"); - String msg = ("TorService is being DESTROYED... shutting down!"); - Log.d(TAG, msg); - sendCallbackLogMessage(msg); + public void onDestroy() { + stopTor(); unregisterReceiver(mNetworkStateReceiver); - clearNotifications (); super.onDestroy(); } @@ -392,9 +380,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon Log.i("TorService", "stopTor"); try { sendCallbackStatus(STATUS_STOPPING); - sendCallbackLogMessage(getString(R.string.status_shutting_down)); - Log.d(TAG,"Tor is stopping NOW"); killAllDaemons(); @@ -408,13 +394,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon shellRoot.close(); } - clearNotifications(); - sendCallbackLogMessage(getString(R.string.status_disabled)); } catch (CannotKillException e) { - Log.d(TAG, "An error occured stopping Tor", e); logNotice("An error occured stopping Tor: " + e.getMessage()); sendCallbackLogMessage(getString(R.string.unable_to_reset_tor)); showToolbarNotification(getString(R.string.unable_to_reset_tor), @@ -422,11 +405,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } catch (Exception e) { - Log.d(TAG, "An error occured stopping Tor",e); logNotice("An error occured stopping Tor: " + e.getMessage()); sendCallbackLogMessage(getString(R.string.something_bad_happened)); } - + clearNotifications(); sendCallbackStatus(STATUS_OFF); } diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index fdf5e77f..7a5a14a5 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -84,7 +84,6 @@ public interface TorServiceConstants { public static final int LOG_MSG = 4; public static final String CMD_START = "start"; - public static final String CMD_STOP = "stop"; public static final String CMD_FLUSH = "flush"; public static final String CMD_NEWNYM = "newnym"; public static final String CMD_VPN = "vpn"; From 21c3bfb3c55a26f80914c52537360a9de390f99e Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 14:27:39 -0400 Subject: [PATCH 21/44] use "SIGNAL HUP" to request Tor re-read its config The tor daemon supports both "SIGNAL HUP" via its control port or the UNIX signal `kill -HUP` via the terminal as a way to trigger the tor daemon to reload its config. This is needed for new bridges and hidden services. It is not necessary to restart everything to add those. https://stem.torproject.org/faq.html#how-do-i-reload-my-torrc --- .../torproject/android/OrbotMainActivity.java | 42 ++++--------------- .../android/service/TorService.java | 31 ++++++++++++-- .../android/service/TorServiceConstants.java | 1 + 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 7b0bb311..e588e9c0 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -447,7 +447,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon //can happen on exit/shutdown } } - + private void doTorCheck () { @@ -479,13 +479,11 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon if (onionHostname == null || onionHostname.length() == 0) { - stopTor(); - startTor(); - + requestTorRereadConfig(); + new Thread () { - - - public void run () + + public void run () { String onionHostname = mPrefs.getString("pref_hs_hostname",""); @@ -945,37 +943,13 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon String bridgeList = Prefs.getBridgesList(); if (bridgeList != null && bridgeList.length() > 0) { - restartTor (); + requestTorRereadConfig (); } - } } - private void restartTor () - { - try - { - //do auto restart - stopTor (); - - mStatusUpdateHandler.postDelayed(new Runnable () { - public void run () - { - try - { - startTor(); - } - catch (Exception e) - { - Log.e(TAG,"can't start orbot",e); - } - } - }, 2000); - } - catch (Exception e) - { - Log.e(TAG,"can't stop orbot",e); - } + private void requestTorRereadConfig() { + sendIntentToService (TorServiceConstants.CMD_START); } public void promptStartVpnService () diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 5884f62d..516b56e7 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -344,6 +344,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (action.equals(CMD_START)) { startTor(); // stopTor() is called when the Service is destroyed + } else if (action.equals(CMD_SIGNAL_HUP)) { + requestTorRereadConfig(); } else if (action.equals(CMD_NEWNYM)) { newIdentity(); } else if (action.equals(CMD_FLUSH)) { @@ -534,7 +536,28 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } } + private void requestTorRereadConfig() { + try { + conn.signal("HUP"); + return; + } catch (IOException e) { + e.printStackTrace(); + } + // if that fails, try again using native utils + try { + killProcess(fileTor, "-1"); // this is -HUP + } catch (CannotKillException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + private void killProcess(File fileProcBin) throws IOException, CannotKillException { + killProcess(fileProcBin, "-9"); // this is -KILL + } + + private void killProcess(File fileProcBin, String signal) throws IOException, CannotKillException { int procId = -1; int killAttempts = 0; @@ -554,10 +577,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } else { shell = Shell.startShell(); } - shell.add(new SimpleCommand("busybox killall " + fileProcBin.getName())); - shell.add(new SimpleCommand("toolbox kill -9 " + pidString)); - shell.add(new SimpleCommand("busybox kill -9 " + pidString)); - shell.add(new SimpleCommand("kill -9 " + pidString)); + shell.add(new SimpleCommand("busybox killall " + signal + " " + fileProcBin.getName())); + shell.add(new SimpleCommand("toolbox kill " + signal + " " + pidString)); + shell.add(new SimpleCommand("busybox kill " + signal + " " + pidString)); + shell.add(new SimpleCommand("kill " + signal + " " + pidString)); try { Thread.sleep(1000); } catch (InterruptedException e) { diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 7a5a14a5..745d74f7 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -84,6 +84,7 @@ public interface TorServiceConstants { public static final int LOG_MSG = 4; public static final String CMD_START = "start"; + public static final String CMD_SIGNAL_HUP = "signal_hup"; public static final String CMD_FLUSH = "flush"; public static final String CMD_NEWNYM = "newnym"; public static final String CMD_VPN = "vpn"; From 65d880100510562c74399d1c9d1ce7a009c147c8 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 14:44:13 -0400 Subject: [PATCH 22/44] rename mMessageReceiver to mLocalBroadcastReceiver --- src/org/torproject/android/OrbotMainActivity.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index e588e9c0..a73e0db9 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -107,10 +107,10 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon /* receive the internal status broadcasts, which are separate from the public * status broadcasts to prevent other apps from sending fake/wrong status * info to this app */ - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, + LocalBroadcastManager.getInstance(this).registerReceiver(mLocalBroadcastReceiver, new IntentFilter(TorServiceConstants.LOCAL_ACTION_STATUS)); - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, + LocalBroadcastManager.getInstance(this).registerReceiver(mLocalBroadcastReceiver, new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); } @@ -129,7 +129,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon // Our handler for received Intents. This will be called whenever an Intent // with an action named "custom-event-name" is broadcasted. - private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { + private BroadcastReceiver mLocalBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1255,7 +1255,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon @Override protected void onDestroy() { super.onDestroy(); - LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); + LocalBroadcastManager.getInstance(this).unregisterReceiver(mLocalBroadcastReceiver); } From 90b731cc8d6c7935cf3ac95144e642b0b6eedc71 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 15:10:52 -0400 Subject: [PATCH 23/44] strictly target local broadcasts This sets an action for each kind of local broadcast, and uses the action to choose how to handle it. Before, it was a mix of the action and which extras the Intent included. --- .../torproject/android/OrbotMainActivity.java | 81 ++++++++++--------- .../android/service/TorService.java | 26 ++---- .../android/service/TorServiceConstants.java | 1 + 3 files changed, 49 insertions(+), 59 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index a73e0db9..c5401632 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -107,11 +107,13 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon /* receive the internal status broadcasts, which are separate from the public * status broadcasts to prevent other apps from sending fake/wrong status * info to this app */ - LocalBroadcastManager.getInstance(this).registerReceiver(mLocalBroadcastReceiver, - new IntentFilter(TorServiceConstants.LOCAL_ACTION_STATUS)); - - LocalBroadcastManager.getInstance(this).registerReceiver(mLocalBroadcastReceiver, - new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); + lbm.registerReceiver(mLocalBroadcastReceiver, + new IntentFilter(TorServiceConstants.LOCAL_ACTION_STATUS)); + lbm.registerReceiver(mLocalBroadcastReceiver, + new IntentFilter(TorServiceConstants.LOCAL_ACTION_BANDWIDTH)); + lbm.registerReceiver(mLocalBroadcastReceiver, + new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); } @@ -127,43 +129,44 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon stopService(torService); } - // Our handler for received Intents. This will be called whenever an Intent - // with an action named "custom-event-name" is broadcasted. + /** + * The state and log info from {@link TorService} are sent to the UI here in + * the form of a local broadcast. Regular broadcasts can be sent by any app, + * so local ones are used here so other apps cannot interfere with Orbot's + * operation. + */ private BroadcastReceiver mLocalBroadcastReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - // Get extra data included in the Intent - - if (intent.hasExtra(TorServiceConstants.LOCAL_EXTRA_LOG)) - { - String log = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); - updateStatus(log); - } - else if (intent.hasExtra("up")) - { - long upload = intent.getLongExtra("up",0); - long download = intent.getLongExtra("down",0); - long written = intent.getLongExtra("written",0); - long read = intent.getLongExtra("read",0); - - Message msg = mStatusUpdateHandler.obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); - msg.getData().putLong("download", download); - msg.getData().putLong("upload", upload); - msg.getData().putLong("readTotal", read); - msg.getData().putLong("writeTotal", written); - mStatusUpdateHandler.sendMessage(msg); - - } - else if (intent.hasExtra(TorServiceConstants.EXTRA_STATUS)) - { - torStatus = intent.getStringExtra(TorServiceConstants.EXTRA_STATUS); - updateStatus(""); - } - - } - }; + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action == null) + return; + if (action.equals(TorServiceConstants.LOCAL_ACTION_LOG)) { + String log = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); + updateStatus(log); + + } else if (action.equals(TorServiceConstants.LOCAL_ACTION_BANDWIDTH)) { + long upload = intent.getLongExtra("up", 0); + long download = intent.getLongExtra("down", 0); + long written = intent.getLongExtra("written", 0); + long read = intent.getLongExtra("read", 0); + + Message msg = mStatusUpdateHandler + .obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); + msg.getData().putLong("download", download); + msg.getData().putLong("upload", upload); + msg.getData().putLong("readTotal", read); + msg.getData().putLong("writeTotal", written); + mStatusUpdateHandler.sendMessage(msg); + + } else if (action.equals(TorServiceConstants.LOCAL_ACTION_STATUS)) { + torStatus = intent.getStringExtra(TorServiceConstants.EXTRA_STATUS); + updateStatus(""); + } + } + }; private void doLayout () { diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 516b56e7..089e2c65 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -1441,7 +1441,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon lastWritten = written; lastRead = read; - sendCallbackStatusMessage(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead); + sendCallbackBandwidth(lastWritten, lastRead, mTotalTrafficWritten, mTotalTrafficRead); } private String formatCount(long count) { @@ -1841,39 +1841,25 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } catch (Exception ioe) { - logException("Unable to update Tor configuration: " + ioe.getMessage(),ioe); - } return false; - } - - - - - private void sendCallbackStatusMessage (long upload, long download, long written, long read) - { - - - Intent intent = new Intent(LOCAL_ACTION_LOG); - // You can also include some extra data. + private void sendCallbackBandwidth(long upload, long download, long written, long read) { + Intent intent = new Intent(LOCAL_ACTION_BANDWIDTH); + intent.putExtra("up",upload); intent.putExtra("down",download); intent.putExtra("written",written); intent.putExtra("read",read); - - LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); } - - // private ArrayList mLogBuffer = new ArrayList(); - + private void sendCallbackLogMessage (String logMessage) { - Intent intent = new Intent(LOCAL_ACTION_LOG); // You can also include some extra data. diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 745d74f7..a79b7d78 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -71,6 +71,7 @@ public interface TorServiceConstants { public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; public final static String LOCAL_ACTION_STATUS = "status"; public final static String LOCAL_ACTION_LOG = "log"; + public final static String LOCAL_ACTION_BANDWIDTH = "bandwidth"; public final static String LOCAL_EXTRA_LOG = "log"; public final static String STATUS_OFF = "OFF"; From 2f7ddc44237779b0713936aeaa2408808f9735dc Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 15:11:01 -0400 Subject: [PATCH 24/44] purge unused OrbotLogActivity --- AndroidManifest.xml | 8 +- .../android/ui/OrbotLogActivity.java | 76 ------------------- 2 files changed, 1 insertion(+), 83 deletions(-) delete mode 100644 src/org/torproject/android/ui/OrbotLogActivity.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d7912e57..603ac703 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -56,13 +56,7 @@ - - - - + diff --git a/src/org/torproject/android/ui/OrbotLogActivity.java b/src/org/torproject/android/ui/OrbotLogActivity.java deleted file mode 100644 index fbf05d2b..00000000 --- a/src/org/torproject/android/ui/OrbotLogActivity.java +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - https://guardianproject.info */ -/* See LICENSE for licensing information */ - -package org.torproject.android.ui; - -import org.torproject.android.OrbotConstants; -import org.torproject.android.service.TorServiceConstants; - -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.os.Bundle; -import android.support.v4.content.LocalBroadcastManager; - - -public class OrbotLogActivity extends Activity implements OrbotConstants -{ - - /** Called when the activity is first created. */ - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - doLayout(); - LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, - new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); - - - } - - // Our handler for received Intents. This will be called whenever an Intent - // with an action named "custom-event-name" is broadcasted. - private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { - - - - @Override - public void onReceive(Context context, Intent intent) { - // Get extra data included in the Intent - - if (intent.hasExtra(TorServiceConstants.LOCAL_EXTRA_LOG)) - { - String log = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); - updateStatus(log); - } - - - } - }; - - - - private void doLayout () - { - - - } - - - private void updateStatus(String log) - { - - } - - - @Override - protected void onDestroy() { - super.onDestroy(); - LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); - - } - - - -} From bf3572eb82d888142fcc5002cf2364a533f07361 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 15:30:28 -0400 Subject: [PATCH 25/44] use the same action string for local and broadcast status No need to have separate action strings, using the LocalBroadcastManager enforces the local-only messaging, and Orbot does not claim the global broadcasts in any kind of receiver. --- src/org/torproject/android/OrbotMainActivity.java | 4 ++-- src/org/torproject/android/service/TorServiceConstants.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index c5401632..6eff421d 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -109,7 +109,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon * info to this app */ LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); lbm.registerReceiver(mLocalBroadcastReceiver, - new IntentFilter(TorServiceConstants.LOCAL_ACTION_STATUS)); + new IntentFilter(TorServiceConstants.ACTION_STATUS)); lbm.registerReceiver(mLocalBroadcastReceiver, new IntentFilter(TorServiceConstants.LOCAL_ACTION_BANDWIDTH)); lbm.registerReceiver(mLocalBroadcastReceiver, @@ -161,7 +161,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon msg.getData().putLong("writeTotal", written); mStatusUpdateHandler.sendMessage(msg); - } else if (action.equals(TorServiceConstants.LOCAL_ACTION_STATUS)) { + } else if (action.equals(TorServiceConstants.ACTION_STATUS)) { torStatus = intent.getStringExtra(TorServiceConstants.EXTRA_STATUS); updateStatus(""); } diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index a79b7d78..c2c326a1 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -69,7 +69,7 @@ public interface TorServiceConstants { public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS"; public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; - public final static String LOCAL_ACTION_STATUS = "status"; + public final static String LOCAL_ACTION_LOG = "log"; public final static String LOCAL_ACTION_BANDWIDTH = "bandwidth"; public final static String LOCAL_EXTRA_LOG = "log"; From 2f1d52f02d93eef32df8e6a3bdf3913c22e95486 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 16:01:42 -0400 Subject: [PATCH 26/44] purge unused code from OrbotMainActivity mItemOnOff no longer exists, there is no more start/stop button on the menu and this code was trying to update menu.getItem(0), which is currently the settings button. onSharedPreferenceChanged() was entirely empty, and the prefs are all handled in their own Activity --- .../torproject/android/OrbotMainActivity.java | 61 ++----------------- 1 file changed, 6 insertions(+), 55 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 6eff421d..8d28db0c 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -28,7 +28,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; @@ -65,13 +64,13 @@ import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; -public class OrbotMainActivity extends Activity implements OrbotConstants, OnLongClickListener, OnTouchListener, OnSharedPreferenceChangeListener -{ +public class OrbotMainActivity extends Activity + implements OrbotConstants, OnLongClickListener, OnTouchListener { + /* Useful UI bits */ private TextView lblStatus = null; //the main text display widget private ImageProgressView imgStatus = null; //the main touchable image for activating Orbot - private MenuItem mItemOnOff = null; private TextView downloadText = null; private TextView uploadText = null; private TextView mTxtOrbotLog = null; @@ -79,8 +78,7 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon private Button mBtnBrowser = null; private ToggleButton mBtnVPN = null; private ToggleButton mBtnBridges = null; - - + private DrawerLayout mDrawer; private ActionBarDrawerToggle mDrawerToggle; private Toolbar mToolbar; @@ -100,7 +98,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon super.onCreate(savedInstanceState); mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - mPrefs.registerOnSharedPreferenceChangeListener(this); doLayout(); @@ -115,8 +112,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon lbm.registerReceiver(mLocalBroadcastReceiver, new IntentFilter(TorServiceConstants.LOCAL_ACTION_LOG)); } - - private void sendIntentToService(String action) { Intent torService = new Intent(this, TorService.class); @@ -299,40 +294,10 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.orbot_main, menu); - - mItemOnOff = menu.getItem(0); - + return true; } - - /** - private void appConflictChecker () - { - SharedPreferences sprefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - - boolean showAppConflict = true;//sprefs.getBoolean("pref_show_conflict",true); - - String[] badApps = {"com.sec.msc.nts.android.proxy:com.sec.msc.nts.android.proxy","com.sec.pcw:Samsung Link"}; - - for (String badApp : badApps) - { - String[] badAppParts = badApp.split(":"); - - if (appInstalledOrNot(badAppParts[0])) - { - String msg = getString(R.string.please_disable_this_app_in_android_settings_apps_if_you_are_having_problems_with_orbot_) + badAppParts[1]; - - if (showAppConflict) - showAlert(getString(R.string.app_conflict),msg,true); - - // appendLogTextAndScroll(msg); - } - } - - sprefs.edit().putBoolean("pref_show_conflict", false).commit(); - - }*/ - + private void showAbout () { @@ -1094,8 +1059,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon mBtnBrowser.setEnabled(true); - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); if (lblStatus != null && torServiceMsg != null) if (torServiceMsg.indexOf('%')!=-1) @@ -1130,8 +1093,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon imgStatus.setImageResource(R.drawable.torstarting); - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_stop); if (lblStatus != null && torServiceMsg != null) if (torServiceMsg.indexOf('%')!=-1) @@ -1146,8 +1107,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon lblStatus.setText(getString(R.string.press_to_start)); mBtnBrowser.setEnabled(false); - if (mItemOnOff != null) - mItemOnOff.setTitle(R.string.menu_start); } @@ -1219,7 +1178,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon break; case TorServiceConstants.ENABLE_TOR_MSG: - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); break; @@ -1302,13 +1260,6 @@ public class OrbotMainActivity extends Activity implements OrbotConstants, OnLon + getString(R.string.mb); } - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, - String key) { - - - } - private static final float ROTATE_FROM = 0.0f; private static final float ROTATE_TO = 360.0f*4f;// 3.141592654f * 32.0f; From 5c2d4501fa10235b69965c090552ce4f4e6566c6 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 16:20:41 -0400 Subject: [PATCH 27/44] make updateStatus() more closely match the state given from TorService This aims to make the UI more tighly in sync with the data coming from TorService. It is not currently perfect in the UI, but it means that the UI will represent the status bugs in TorService. This is important because that status info is now broadcast to any app that wants it. So the visible part of Orbot should show want the apps are seeing to aid debugging. And status report bugs should be fixed in TorService so that everyone gets the correctinfo. --- .../torproject/android/OrbotMainActivity.java | 146 ++++++++---------- 1 file changed, 64 insertions(+), 82 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 8d28db0c..a2e97502 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -98,7 +98,9 @@ public class OrbotMainActivity extends Activity super.onCreate(savedInstanceState); mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - + + /* Create the widgets before registering for broadcasts to guarantee + * that the widgets exist when the status updates try to update them */ doLayout(); /* receive the internal status broadcasts, which are separate from the public @@ -1044,89 +1046,73 @@ public class OrbotMainActivity extends Activity aDialog.setCanceledOnTouchOutside(true); } - - private void updateStatus (String torServiceMsg) - { - - //now update the layout_main UI based on the status - if (imgStatus != null) - { - - if (torStatus == TorServiceConstants.STATUS_ON) - { - - imgStatus.setImageResource(R.drawable.toron); - - mBtnBrowser.setEnabled(true); - - - if (lblStatus != null && torServiceMsg != null) - if (torServiceMsg.indexOf('%')!=-1) - lblStatus.setText(torServiceMsg); - else - lblStatus.setText(""); - - boolean showFirstTime = mPrefs.getBoolean("connect_first_time",true); - - if (showFirstTime) - { - - Editor pEdit = mPrefs.edit(); - - pEdit.putBoolean("connect_first_time",false); - - pEdit.commit(); - - showAlert(getString(R.string.status_activated),getString(R.string.connect_first_time),true); - - } - - if (autoStartFromIntent) - { - autoStartFromIntent = false; - finish(); - Log.e(TAG, "autoStartFromIntent finish"); - } - } - else if (torStatus == TorServiceConstants.STATUS_STARTING) - { - - imgStatus.setImageResource(R.drawable.torstarting); - - - if (lblStatus != null && torServiceMsg != null) - if (torServiceMsg.indexOf('%')!=-1) - lblStatus.setText(torServiceMsg); - - - - } - else if (torStatus == TorServiceConstants.STATUS_OFF) - { - imgStatus.setImageResource(R.drawable.toroff); - lblStatus.setText(getString(R.string.press_to_start)); - mBtnBrowser.setEnabled(false); - - } - - if (torServiceMsg != null && torServiceMsg.length() > 0) - { - mTxtOrbotLog.append(torServiceMsg + '\n'); - } + /** + * Update the layout_main UI based on the status of {@link TorService}. + * {@code torServiceMsg} must never be {@code null} + */ + private void updateStatus(String torServiceMsg) { + + if (torStatus == TorServiceConstants.STATUS_ON) { + imgStatus.setImageResource(R.drawable.toron); + + mBtnBrowser.setEnabled(true); + + // everything is running, clear the status message + lblStatus.setText(""); + + boolean showFirstTime = mPrefs.getBoolean("connect_first_time", true); + + if (showFirstTime) + { + Editor pEdit = mPrefs.edit(); + pEdit.putBoolean("connect_first_time", false); + pEdit.commit(); + showAlert(getString(R.string.status_activated), + getString(R.string.connect_first_time), true); } - - + + if (autoStartFromIntent) + { + autoStartFromIntent = false; + finish(); + Log.e(TAG, "autoStartFromIntent finish"); + } + + } else if (torStatus == TorServiceConstants.STATUS_STARTING) { + + imgStatus.setImageResource(R.drawable.torstarting); + + // only show Tor daemon's percentage complete messages + if (torServiceMsg.indexOf('%') != -1) + lblStatus.setText(torServiceMsg); + mBtnBrowser.setEnabled(false); + + } else if (torStatus == TorServiceConstants.STATUS_STOPPING) { + + imgStatus.setImageResource(R.drawable.torstarting); + lblStatus.setText(torServiceMsg); + mBtnBrowser.setEnabled(false); + + } else if (torStatus == TorServiceConstants.STATUS_OFF) { + + imgStatus.setImageResource(R.drawable.toroff); + lblStatus.setText(getString(R.string.press_to_start)); + mBtnBrowser.setEnabled(false); + } + + if (torServiceMsg != null && torServiceMsg.length() > 0) + { + mTxtOrbotLog.append(torServiceMsg + '\n'); + } } - - - + // guess what? this start's Tor! actually no it just requests via the local ITorService to the remote TorService instance // to start Tor private void startTor () throws RemoteException { + Log.i("OrbotMainActivity", "startTor"); sendIntentToService (TorServiceConstants.CMD_START); - torStatus = TorServiceConstants.STATUS_STARTING; mTxtOrbotLog.setText(""); @@ -1198,12 +1184,8 @@ public class OrbotMainActivity extends Activity downloadText.setText(formatCount(datacount.Download) + " / " + formatTotal(totalRead)); uploadText.setText(formatCount(datacount.Upload) + " / " + formatTotal(totalWrite)); - - if (torStatus != TorServiceConstants.STATUS_ON) - { - updateStatus(""); - } - + + break; default: super.handleMessage(msg); } From 25a6bb63b24c377a7c0505e5d2677cf6c90b88fb Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 17:02:21 -0400 Subject: [PATCH 28/44] force all UI status updates through mStatusUpdateHandler The Handler is a message queue for the main thread, so it should help keep the UI working while status updates are coming in. * This removes the constants in TorServiceConstants because the Handler messages are only for OrbotMainActivity * this uses the handy shortcut msg.obj for the status message --- .../torproject/android/OrbotConstants.java | 6 +- .../torproject/android/OrbotMainActivity.java | 63 +++++++------------ .../android/service/TorServiceConstants.java | 12 +--- 3 files changed, 24 insertions(+), 57 deletions(-) diff --git a/src/org/torproject/android/OrbotConstants.java b/src/org/torproject/android/OrbotConstants.java index 373ff3fd..10309fb7 100644 --- a/src/org/torproject/android/OrbotConstants.java +++ b/src/org/torproject/android/OrbotConstants.java @@ -16,11 +16,7 @@ public interface OrbotConstants { public final static String URL_TOR_CHECK = "https://check.torproject.org"; public final static String URL_TOR_BRIDGES = "https://bridges.torproject.org/bridges?transport="; - - public final static String NEWLINE = "\n"; - - public final static String HANDLER_TOR_MSG = "torServiceMsg"; - + public final static String PREF_BRIDGES_UPDATED = "pref_bridges_enabled"; //public final static String PREF_BRIDGES_OBFUSCATED = "pref_bridges_obfuscated"; public final static String PREF_OR = "pref_or"; diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index a2e97502..c9c13b00 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -92,7 +92,11 @@ public class OrbotMainActivity extends Activity private final static int REQUEST_VPN = 8888; private final static int REQUEST_SETTINGS = 0x9874; - + + // message types for mStatusUpdateHandler + private final static int STATUS_UPDATE = 1; + private static final int MESSAGE_TRAFFIC_COUNT = 2; + /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -141,8 +145,9 @@ public class OrbotMainActivity extends Activity return; if (action.equals(TorServiceConstants.LOCAL_ACTION_LOG)) { - String log = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); - updateStatus(log); + Message msg = mStatusUpdateHandler.obtainMessage(STATUS_UPDATE); + msg.obj = intent.getStringExtra(TorServiceConstants.LOCAL_EXTRA_LOG); + mStatusUpdateHandler.sendMessage(msg); } else if (action.equals(TorServiceConstants.LOCAL_ACTION_BANDWIDTH)) { long upload = intent.getLongExtra("up", 0); @@ -150,8 +155,7 @@ public class OrbotMainActivity extends Activity long written = intent.getLongExtra("written", 0); long read = intent.getLongExtra("read", 0); - Message msg = mStatusUpdateHandler - .obtainMessage(TorServiceConstants.MESSAGE_TRAFFIC_COUNT); + Message msg = mStatusUpdateHandler.obtainMessage(MESSAGE_TRAFFIC_COUNT); msg.getData().putLong("download", download); msg.getData().putLong("upload", upload); msg.getData().putLong("readTotal", read); @@ -160,7 +164,9 @@ public class OrbotMainActivity extends Activity } else if (action.equals(TorServiceConstants.ACTION_STATUS)) { torStatus = intent.getStringExtra(TorServiceConstants.EXTRA_STATUS); - updateStatus(""); + Message msg = mStatusUpdateHandler.obtainMessage(STATUS_UPDATE); + msg.obj = ""; + mStatusUpdateHandler.sendMessage(msg); } } }; @@ -1122,8 +1128,8 @@ public class OrbotMainActivity extends Activity lblStatus.setText(getString(R.string.status_starting_up)); //we send a message here to the progressDialog i believe, but we can clarify that shortly - Message msg = mStatusUpdateHandler.obtainMessage(TorServiceConstants.ENABLE_TOR_MSG); - msg.getData().putString(HANDLER_TOR_MSG, getString(R.string.status_starting_up)); + Message msg = mStatusUpdateHandler.obtainMessage(STATUS_UPDATE); + msg.obj = getString(R.string.status_starting_up); mStatusUpdateHandler.sendMessage(msg); } @@ -1144,38 +1150,16 @@ public class OrbotMainActivity extends Activity // this is what takes messages or values from the callback threads or other non-mainUI threads //and passes them back into the main UI thread for display to the user private Handler mStatusUpdateHandler = new Handler() { - - private String lastServiceMsg = null; - - public void handleMessage(Message msg) { + + @Override + public void handleMessage(final Message msg) { switch (msg.what) { - case TorServiceConstants.STATUS_MSG: - case TorServiceConstants.LOG_MSG: - - String torServiceMsg = (String)msg.getData().getString(HANDLER_TOR_MSG); - - if (lastServiceMsg == null || !lastServiceMsg.equals(torServiceMsg)) - { - updateStatus(torServiceMsg); - - lastServiceMsg = torServiceMsg; - } - + case STATUS_UPDATE: + updateStatus((String) msg.obj); break; - case TorServiceConstants.ENABLE_TOR_MSG: - - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); - - break; - case TorServiceConstants.DISABLE_TOR_MSG: - - updateStatus((String)msg.getData().getString(HANDLER_TOR_MSG)); - - break; - - case TorServiceConstants.MESSAGE_TRAFFIC_COUNT : - + case MESSAGE_TRAFFIC_COUNT: + Bundle data = msg.getData(); DataCount datacount = new DataCount(data.getLong("upload"),data.getLong("download")); @@ -1190,12 +1174,9 @@ public class OrbotMainActivity extends Activity super.handleMessage(msg); } } - - - }; - @Override + @Override protected void onDestroy() { super.onDestroy(); LocalBroadcastManager.getInstance(this).unregisterReceiver(mLocalBroadcastReceiver); diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index c2c326a1..c31a6703 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -78,12 +78,7 @@ public interface TorServiceConstants { public final static String STATUS_ON = "ON"; public final static String STATUS_STARTING = "STARTING"; public final static String STATUS_STOPPING = "STOPPING"; - - public static final int STATUS_MSG = 1; - public static final int ENABLE_TOR_MSG = 2; - public static final int DISABLE_TOR_MSG = 3; - public static final int LOG_MSG = 4; - + public static final String CMD_START = "start"; public static final String CMD_SIGNAL_HUP = "signal_hup"; public static final String CMD_FLUSH = "flush"; @@ -100,11 +95,6 @@ public interface TorServiceConstants { public static final String OBFSCLIENT_ASSET_KEY = "obfs4proxy"; public static final String MEEK_ASSET_KEY = "meek-client"; - - - public static final int MESSAGE_TRAFFIC_COUNT = 5; - - //name of the iptables binary public final static String IPTABLES_ASSET_KEY = "xtables"; From 13d29878f92ec3b7b9176cc68c1e8eb836a0b2ce Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 9 Jun 2015 17:27:01 -0400 Subject: [PATCH 29/44] a couple tweaks to make the long press feel more responsive --- src/org/torproject/android/OrbotMainActivity.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index c9c13b00..38d3a809 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -126,6 +126,7 @@ public class OrbotMainActivity extends Activity } private void stopTor() { + imgStatus.setImageResource(R.drawable.torstarting); Intent torService = new Intent(this, TorService.class); stopService(torService); } @@ -1118,7 +1119,6 @@ public class OrbotMainActivity extends Activity private void startTor () throws RemoteException { Log.i("OrbotMainActivity", "startTor"); - sendIntentToService (TorServiceConstants.CMD_START); mTxtOrbotLog.setText(""); @@ -1126,6 +1126,8 @@ public class OrbotMainActivity extends Activity //might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense imgStatus.setImageResource(R.drawable.torstarting); lblStatus.setText(getString(R.string.status_starting_up)); + + sendIntentToService(TorServiceConstants.CMD_START); //we send a message here to the progressDialog i believe, but we can clarify that shortly Message msg = mStatusUpdateHandler.obtainMessage(STATUS_UPDATE); From f433a5e6556c93386c5e018285efe038c83afa8f Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 10 Jun 2015 14:46:05 -0400 Subject: [PATCH 30/44] expose start action via a BroadcastReceiver that any app can send to This allows any app to broadcast an Intent to Orbot in order to make Orbot start in the background. closes #3117 https://dev.guardianproject.info/issues/3117 --- AndroidManifest.xml | 10 +++++++++- .../torproject/android/OrbotMainActivity.java | 10 +++++----- .../android/service/OnBootReceiver.java | 4 ++-- .../android/service/StartTorReceiver.java | 20 +++++++++++++++++++ .../android/service/TorService.java | 2 +- .../android/service/TorServiceConstants.java | 2 +- 6 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/org/torproject/android/service/StartTorReceiver.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 603ac703..23f5e4e5 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -87,7 +87,15 @@ android:permission="org.torproject.android.MANAGE_TOR" android:stopWithTask="false" > - + + + + + + + Date: Wed, 10 Jun 2015 17:39:57 -0400 Subject: [PATCH 31/44] on receiving ACTION_START, only send status reply if EXTRA_PACKAGE_NAME set In order to receive a targeted reply, an app has to send its packageName to Orbot as an String extra in an ACTION_START Intent. Also, when Orbot internally uses ACTION_START, it shouldn't receive replies. --- .../android/service/StartTorReceiver.java | 12 ++++++--- .../android/service/TorService.java | 21 +++++++++++++++ .../android/service/TorServiceConstants.java | 26 +++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/org/torproject/android/service/StartTorReceiver.java b/src/org/torproject/android/service/StartTorReceiver.java index c236484b..89df5964 100644 --- a/src/org/torproject/android/service/StartTorReceiver.java +++ b/src/org/torproject/android/service/StartTorReceiver.java @@ -11,10 +11,14 @@ public class StartTorReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { /* sanitize the Intent before forwarding it to TorService */ - if (TextUtils.equals(intent.getAction(), TorServiceConstants.ACTION_START)) { - Intent startTorService = new Intent(context, TorService.class); - startTorService.setAction(intent.getAction()); - context.startService(startTorService); + String action = intent.getAction(); + if (TextUtils.equals(action, TorServiceConstants.ACTION_START)) { + Intent startTorIntent = new Intent(context, TorService.class); + startTorIntent.setAction(action); + String packageName = intent.getStringExtra(TorServiceConstants.EXTRA_PACKAGE_NAME); + if (packageName != null) + startTorIntent.putExtra(TorServiceConstants.EXTRA_PACKAGE_NAME, packageName); + context.startService(startTorIntent); } } } diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index efde5c66..ccfc4c84 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -28,6 +28,7 @@ import android.os.RemoteException; import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat.Builder; import android.support.v4.content.LocalBroadcastManager; +import android.text.TextUtils; import android.util.Log; import android.widget.RemoteViews; @@ -342,6 +343,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon if (action != null) { if (action.equals(ACTION_START)) { + replyWithStatus(mIntent); startTor(); // stopTor() is called when the Service is destroyed } else if (action.equals(CMD_SIGNAL_HUP)) { @@ -748,6 +750,25 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon return success; } + /** + * Send Orbot's status in reply to an + * {@link TorServiceConstants#ACTION_START} {@link Intent}, targeted only to + * the app that sent the initial request. + */ + private void replyWithStatus(Intent startRequest) { + String packageName = startRequest.getStringExtra(EXTRA_PACKAGE_NAME); + if (TextUtils.isEmpty(packageName)) { + return; + } + Intent reply = new Intent(ACTION_STATUS); + reply.putExtra(EXTRA_STATUS, mCurrentStatus); + reply.setPackage(packageName); + sendBroadcast(reply); + } + + /** + * The entire process for starting tor and related services is run from this method. + */ private void startTor() { if (mCurrentStatus == STATUS_STARTING || mCurrentStatus == STATUS_STOPPING) { // these states should probably be handled better diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 96715b6e..7921ddcc 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -1,7 +1,10 @@ /* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */ /* See LICENSE for licensing information */ + package org.torproject.android.service; +import android.content.Intent; + public interface TorServiceConstants { public final static String TOR_APP_USERNAME = "org.torproject.android"; @@ -67,19 +70,42 @@ public interface TorServiceConstants { //control port public final static String TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE = "Bootstrapped 100%"; + /** + * A request to Orbot to transparently start Tor services + */ public final static String ACTION_START = "org.torproject.android.intent.action.START"; + /** + * {@link Intent} send by Orbot with {@code ON/OFF/STARTING/STOPPING} status + */ public final static String ACTION_STATUS = "org.torproject.android.intent.action.STATUS"; + /** + * {@code String} that contains a status constant: {@link #STATUS_ON}, + * {@link #STATUS_OFF}, {@link #STATUS_STARTING}, or + * {@link #STATUS_STOPPING} + */ public final static String EXTRA_STATUS = "org.torproject.android.intent.extra.STATUS"; + /** + * A {@link String} {@code packageName} for Orbot to direct its status reply + * to, used in {@link #ACTION_START} {@link Intent}s sent to Orbot + */ + public final static String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME"; public final static String LOCAL_ACTION_LOG = "log"; public final static String LOCAL_ACTION_BANDWIDTH = "bandwidth"; public final static String LOCAL_EXTRA_LOG = "log"; + /** + * All tor-related services and daemons are stopped + */ public final static String STATUS_OFF = "OFF"; + /** + * All tor-related services and daemons have completed starting + */ public final static String STATUS_ON = "ON"; public final static String STATUS_STARTING = "STARTING"; public final static String STATUS_STOPPING = "STOPPING"; + // actions for internal command Intents public static final String CMD_SIGNAL_HUP = "signal_hup"; public static final String CMD_FLUSH = "flush"; public static final String CMD_NEWNYM = "newnym"; From ac8329c7f279b1e3afb747cff8b15c2fa1821bf1 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Wed, 10 Jun 2015 18:00:30 -0400 Subject: [PATCH 32/44] create a new pref: "Allow Background Starts" This lets the user disable the new ACTION_START Intent, in case they have more sensitive needs. --- res/values/strings.xml | 2 ++ res/xml/preferences.xml | 5 +++++ src/org/torproject/android/Prefs.java | 5 +++++ src/org/torproject/android/service/StartTorReceiver.java | 6 +++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 87aa35fe..decd8920 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -126,6 +126,8 @@ Entrance Nodes Fingerprints, nicks, countries and addresses for the first hop Enter Entrance Nodes + Allow Background Starts + Let any app tell Orbot to start Tor and related services Proxy All Proxy None diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index d910fee2..e1e1828a 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -22,6 +22,11 @@ android:summary="@string/pref_use_expanded_notifications" android:enabled="true" android:title="@string/pref_use_expanded_notifications_title"/> + Date: Wed, 10 Jun 2015 18:15:29 -0400 Subject: [PATCH 33/44] let the requesting app know that the user has disabled starting via Intent If an app is using ACTION_START to start Orbot in the background, but the user had disabled that using the allowBackgroundStarts pref, then the app will want to know about that so it can fallback on prompting the user to bring up Orbot itself for the user to manually start it. refs #3117 https://dev.guardianproject.info/issues/3117 --- .../android/service/StartTorReceiver.java | 26 ++++++++++++------- .../android/service/TorServiceConstants.java | 8 ++++-- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/org/torproject/android/service/StartTorReceiver.java b/src/org/torproject/android/service/StartTorReceiver.java index c89d8808..087b01f4 100644 --- a/src/org/torproject/android/service/StartTorReceiver.java +++ b/src/org/torproject/android/service/StartTorReceiver.java @@ -8,21 +8,29 @@ import android.text.TextUtils; import org.torproject.android.Prefs; -public class StartTorReceiver extends BroadcastReceiver { +public class StartTorReceiver extends BroadcastReceiver implements TorServiceConstants { @Override public void onReceive(Context context, Intent intent) { /* sanitize the Intent before forwarding it to TorService */ Prefs.setContext(context); String action = intent.getAction(); - if (Prefs.allowBackgroundStarts() - && TextUtils.equals(action, TorServiceConstants.ACTION_START)) { - Intent startTorIntent = new Intent(context, TorService.class); - startTorIntent.setAction(action); - String packageName = intent.getStringExtra(TorServiceConstants.EXTRA_PACKAGE_NAME); - if (packageName != null) - startTorIntent.putExtra(TorServiceConstants.EXTRA_PACKAGE_NAME, packageName); - context.startService(startTorIntent); + if (TextUtils.equals(action, ACTION_START)) { + String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME); + if (Prefs.allowBackgroundStarts()) { + Intent startTorIntent = new Intent(context, TorService.class); + startTorIntent.setAction(action); + if (packageName != null) + startTorIntent.putExtra(EXTRA_PACKAGE_NAME, packageName); + context.startService(startTorIntent); + } else if (!TextUtils.isEmpty(packageName)) { + // let the requesting app know that the user has disabled + // starting via Intent + Intent startsDisabledIntent = new Intent(ACTION_STATUS); + startsDisabledIntent.putExtra(EXTRA_STATUS, STATUS_STARTS_DISABLED); + startsDisabledIntent.setPackage(packageName); + context.sendBroadcast(startsDisabledIntent); + } } } } diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 7921ddcc..80b37f8d 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -104,6 +104,11 @@ public interface TorServiceConstants { public final static String STATUS_ON = "ON"; public final static String STATUS_STARTING = "STARTING"; public final static String STATUS_STOPPING = "STOPPING"; + /** + * The user has disabled the ability for background starts triggered by + * apps. Fallback to the old Intent that brings up Orbot. + */ + public final static String STATUS_STARTS_DISABLED = "STARTS_DISABLED"; // actions for internal command Intents public static final String CMD_SIGNAL_HUP = "signal_hup"; @@ -112,8 +117,7 @@ public interface TorServiceConstants { public static final String CMD_VPN = "vpn"; public static final String CMD_VPN_CLEAR = "vpnclear"; public static final String CMD_UPDATE_TRANS_PROXY = "update"; - - + public static final String BINARY_TOR_VERSION = "0.2.6.7"; public static final String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED"; From 623084548d2f5fc8d87a63e21c7f9b413e3633f0 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 11 Jun 2015 16:31:39 -0400 Subject: [PATCH 34/44] standardize network port constant variables use consistent naming and types for code clarity --- .../torproject/android/OrbotMainActivity.java | 8 ++++---- .../torproject/android/service/TorService.java | 3 ++- .../android/service/TorServiceConstants.java | 18 +++++------------- .../android/vpn/OrbotVpnService.java | 3 ++- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index bfa777d6..978d8ccf 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -559,12 +559,12 @@ public class OrbotMainActivity extends Activity startTor(); Intent resultIntent = new Intent(intent); - resultIntent.putExtra("socks_proxy", "socks://127.0.0.1:" + TorServiceConstants.PORT_SOCKS_DEFAULT); + resultIntent.putExtra("socks_proxy", "socks://127.0.0.1:" + TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); resultIntent.putExtra("socks_proxy_host", "127.0.0.1"); - resultIntent.putExtra("socks_proxy_port", TorServiceConstants.PORT_SOCKS_DEFAULT); - resultIntent.putExtra("http_proxy", "http://127.0.0.1" + TorServiceConstants.PORT_HTTP); + resultIntent.putExtra("socks_proxy_port", TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); + resultIntent.putExtra("http_proxy", "http://127.0.0.1" + TorServiceConstants.HTTP_PROXY_PORT_DEFAULT); resultIntent.putExtra("http_proxy_host", "127.0.0.1"); - resultIntent.putExtra("http_proxy_port", TorServiceConstants.PORT_HTTP); + resultIntent.putExtra("http_proxy_port", TorServiceConstants.HTTP_PROXY_PORT_DEFAULT); setResult(RESULT_OK, resultIntent); finish(); } catch (RemoteException e) { diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index ccfc4c84..018adb27 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -1168,7 +1168,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext()); - String socksPortPref = prefs.getString(OrbotConstants.PREF_SOCKS, TorServiceConstants.PORT_SOCKS_DEFAULT); + String socksPortPref = prefs.getString(OrbotConstants.PREF_SOCKS, + String.valueOf(TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT)); if (socksPortPref.indexOf(':')!=-1) socksPortPref = socksPortPref.split(":")[1]; diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index 80b37f8d..a0aed24d 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -49,21 +49,16 @@ public interface TorServiceConstants { public final static String CHMOD_EXE_VALUE = "770"; public final static int FILE_WRITE_BUFFER_SIZE = 1024; - - //HTTP Proxy server port - public static int PORT_HTTP = 8118; //just like Privoxy! - - //Socks port client connects to, server is the Tor binary - public static String PORT_SOCKS_DEFAULT = "9050"; - - - //what is says! + public final static String IP_LOCALHOST = "127.0.0.1"; public final static int UPDATE_TIMEOUT = 1000; public final static int TOR_TRANSPROXY_PORT_DEFAULT = 9040; public final static int STANDARD_DNS_PORT = 53; public final static int TOR_DNS_PORT_DEFAULT = 5400; - + public final static int CONTROL_PORT_DEFAULT = 9051; + public final static int HTTP_PROXY_PORT_DEFAULT = 8118; // like Privoxy! + public final static int SOCKS_PROXY_PORT_DEFAULT = 9050; + //path to check Tor against public final static String URL_TOR_CHECK = "https://check.torproject.org"; @@ -127,8 +122,5 @@ public interface TorServiceConstants { public static final String MEEK_ASSET_KEY = "meek-client"; //name of the iptables binary public final static String IPTABLES_ASSET_KEY = "xtables"; - - public final static int DEFAULT_CONTROL_PORT = 9051; - } diff --git a/src/org/torproject/android/vpn/OrbotVpnService.java b/src/org/torproject/android/vpn/OrbotVpnService.java index 10969060..e2020781 100644 --- a/src/org/torproject/android/vpn/OrbotVpnService.java +++ b/src/org/torproject/android/vpn/OrbotVpnService.java @@ -241,7 +241,8 @@ public class OrbotVpnService extends VpnService implements Handler.Callback { final String virtualGateway = "10.0.0.1"; final String virtualIP = "10.0.0.2"; final String virtualNetMask = "255.255.255.0"; - final String localSocks = "127.0.0.1:" + TorServiceConstants.PORT_SOCKS_DEFAULT; + final String localSocks = "127.0.0.1:" + + String.valueOf(TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); final String localDNS = "10.0.0.1:" + TorServiceConstants.TOR_DNS_PORT_DEFAULT; Builder builder = new Builder(); From 0937c8838fe49cdc970fb995f72c5c375b799098 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 11 Jun 2015 16:32:31 -0400 Subject: [PATCH 35/44] use constants for setting default ports, and variables when running --- src/org/torproject/android/service/TorService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 018adb27..46b55ae9 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -93,8 +93,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon private int mLastProcessId = -1; - private int mPortHTTP = 8118; - private int mPortSOCKS = 9050; + private int mPortHTTP = HTTP_PROXY_PORT_DEFAULT; + private int mPortSOCKS = SOCKS_PROXY_PORT_DEFAULT; private static final int NOTIFY_ID = 1; private static final int TRANSPROXY_NOTIFY_ID = 2; @@ -1077,7 +1077,7 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon logNotice(log.toString()); } - sendCallbackLogMessage(getString(R.string.privoxy_is_running_on_port_) + PORT_HTTP); + sendCallbackLogMessage(getString(R.string.privoxy_is_running_on_port_) + mPortHTTP); logNotice("Polipo process id=" + polipoProcId); From b620f828a1a86875bf93fa3291c7a753d02070fd Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Thu, 11 Jun 2015 17:02:56 -0400 Subject: [PATCH 36/44] include dynamic proxy config info in ACTION_STATUS replies This includes extras in the Intents that are sent as replies to the two different requests to start tor (ACTION_START and ACTION_START_TOR). These extras give all of the current SOCKS and HTTP proxy settings, so that the app can dynamically use the correct settings. Sometimes there are port conflicts, so apps should dynamically adjust in order to reliably find tor. closes #3612 https://dev.guardianproject.info/issues/3612 refs #4419 https://dev.guardianproject.info/issues/4419 refs #3690 https://dev.guardianproject.info/issues/3690 refs #3687 https://dev.guardianproject.info/issues/3687 refs #3859 https://dev.guardianproject.info/issues/3859 --- .../torproject/android/OrbotMainActivity.java | 35 +++++++++---------- .../android/service/TorService.java | 6 ++++ .../android/service/TorServiceConstants.java | 12 +++++++ 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 978d8ccf..b1635f28 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -85,7 +85,8 @@ public class OrbotMainActivity extends Activity /* Some tracking bits */ private String torStatus = TorServiceConstants.STATUS_OFF; //latest status reported from the tor service - + private Intent lastStatusIntent; // the last ACTION_STATUS Intent received + private SharedPreferences mPrefs = null; private boolean autoStartFromIntent = false; @@ -164,6 +165,7 @@ public class OrbotMainActivity extends Activity mStatusUpdateHandler.sendMessage(msg); } else if (action.equals(TorServiceConstants.ACTION_STATUS)) { + lastStatusIntent = intent; torStatus = intent.getStringExtra(TorServiceConstants.EXTRA_STATUS); Message msg = mStatusUpdateHandler.obtainMessage(STATUS_UPDATE); msg.obj = ""; @@ -554,24 +556,21 @@ public class OrbotMainActivity extends Activity else if (action.equals("org.torproject.android.START_TOR")) { autoStartFromIntent = true; - try { - Log.i(TAG, "action equals org.torproject.android.START_TOR"); - startTor(); - - Intent resultIntent = new Intent(intent); - resultIntent.putExtra("socks_proxy", "socks://127.0.0.1:" + TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); - resultIntent.putExtra("socks_proxy_host", "127.0.0.1"); - resultIntent.putExtra("socks_proxy_port", TorServiceConstants.SOCKS_PROXY_PORT_DEFAULT); - resultIntent.putExtra("http_proxy", "http://127.0.0.1" + TorServiceConstants.HTTP_PROXY_PORT_DEFAULT); - resultIntent.putExtra("http_proxy_host", "127.0.0.1"); - resultIntent.putExtra("http_proxy_port", TorServiceConstants.HTTP_PROXY_PORT_DEFAULT); - setResult(RESULT_OK, resultIntent); - finish(); - } catch (RemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } + try { + startTor(); + Intent resultIntent; + if (lastStatusIntent == null) { + resultIntent = new Intent(intent); + } else { + resultIntent = lastStatusIntent; + } + resultIntent.putExtra(TorServiceConstants.EXTRA_STATUS, torStatus); + setResult(RESULT_OK, resultIntent); + finish(); + } catch (RemoteException e) { + e.printStackTrace(); + } } else if (action.equals(Intent.ACTION_VIEW)) { diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 46b55ae9..7e057a0a 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -762,6 +762,12 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } Intent reply = new Intent(ACTION_STATUS); reply.putExtra(EXTRA_STATUS, mCurrentStatus); + reply.putExtra(EXTRA_SOCKS_PROXY, "socks://127.0.0.1:" + mPortSOCKS); + reply.putExtra(EXTRA_SOCKS_PROXY_HOST, "127.0.0.1"); + reply.putExtra(EXTRA_SOCKS_PROXY_PORT, mPortSOCKS); + reply.putExtra(EXTRA_HTTP_PROXY, "http://127.0.0.1" + mPortHTTP); + reply.putExtra(EXTRA_HTTP_PROXY_HOST, "127.0.0.1"); + reply.putExtra(EXTRA_HTTP_PROXY_PORT, mPortHTTP); reply.setPackage(packageName); sendBroadcast(reply); } diff --git a/src/org/torproject/android/service/TorServiceConstants.java b/src/org/torproject/android/service/TorServiceConstants.java index a0aed24d..adaa6740 100644 --- a/src/org/torproject/android/service/TorServiceConstants.java +++ b/src/org/torproject/android/service/TorServiceConstants.java @@ -84,6 +84,18 @@ public interface TorServiceConstants { * to, used in {@link #ACTION_START} {@link Intent}s sent to Orbot */ public final static String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME"; + /** + * The SOCKS proxy settings in URL form. + */ + public final static String EXTRA_SOCKS_PROXY = "org.torproject.android.intent.extra.SOCKS_PROXY"; + public final static String EXTRA_SOCKS_PROXY_HOST = "org.torproject.android.intent.extra.SOCKS_PROXY_HOST"; + public final static String EXTRA_SOCKS_PROXY_PORT = "org.torproject.android.intent.extra.SOCKS_PROXY_PORT"; + /** + * The HTTP proxy settings in URL form. + */ + public final static String EXTRA_HTTP_PROXY = "org.torproject.android.intent.extra.HTTP_PROXY"; + public final static String EXTRA_HTTP_PROXY_HOST = "org.torproject.android.intent.extra.HTTP_PROXY_HOST"; + public final static String EXTRA_HTTP_PROXY_PORT = "org.torproject.android.intent.extra.HTTP_PROXY_PORT"; public final static String LOCAL_ACTION_LOG = "log"; public final static String LOCAL_ACTION_BANDWIDTH = "bandwidth"; From ff04bde300651b6f035beae562b66278693a54d4 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 12 Jun 2015 14:24:57 -0400 Subject: [PATCH 37/44] announce Orbot is ON once the first circuit is complete Before, it was announcing tor was started when it had completed starting the daemons. But that does not guarantee that Tor is actually connected and working. So instead, this waits for the first circuit to be built, then announces Tor is ON. --- src/org/torproject/android/service/TorService.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 7e057a0a..fd7bcc89 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -840,7 +840,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon } shellUser.close(); - sendCallbackStatus(STATUS_ON); } catch (CannotKillException e) { logException(e.getMessage(), e); showToolbarNotification(getString(R.string.unable_to_reset_tor), @@ -1489,6 +1488,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon public void circuitStatus(String status, String circID, String path) { + /* once the first circuit is complete, then announce that Orbot is on*/ + if (mCurrentStatus == STATUS_STARTING && TextUtils.equals(status, "BUILT")) + sendCallbackStatus(STATUS_ON); + StringBuilder sb = new StringBuilder(); sb.append("Circuit ("); sb.append((circID)); From 8f57b42e68ea96f784c92655b0039e0196f05200 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 12 Jun 2015 14:46:47 -0400 Subject: [PATCH 38/44] rename TorStarter to IncomingIntentRouter, it handles all Intents TorStarter does lots of things besides starting Tor --- src/org/torproject/android/service/TorService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index fd7bcc89..a78769ce 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -322,18 +322,18 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon */ public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) - new Thread (new TorStarter(intent)).start(); + new Thread (new IncomingIntentRouter(intent)).start(); else Log.d(TAG, "Got null onStartCommand() intent"); return Service.START_STICKY; } - private class TorStarter implements Runnable + private class IncomingIntentRouter implements Runnable { Intent mIntent; - public TorStarter (Intent intent) + public IncomingIntentRouter (Intent intent) { mIntent = intent; } From 232098eeafef79c024a5b255e3de82cb3a8e92b4 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 12 Jun 2015 14:49:19 -0400 Subject: [PATCH 39/44] set STATUS_STARTING in TorService.onCreate(), that's where it begins The very first place that the whole tor start sequence starts is from TorService's onCreate(), so that is where STATUS_STARTING should be announced from. The open question is whether Intents besides ACTION_START ever cause TorService to start. In theory, TorService should already be running when any Intent is sent besides ACTION_START. --- src/org/torproject/android/service/TorService.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index a78769ce..f5fe6e1c 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -608,7 +608,10 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon @Override public void onCreate() { super.onCreate(); - Log.i("TorService", "onCreate"); + + sendCallbackStatus(STATUS_STARTING); + sendCallbackLogMessage(getString(R.string.status_starting_up)); + logNotice(getString(R.string.status_starting_up)); try { @@ -776,7 +779,8 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon * The entire process for starting tor and related services is run from this method. */ private void startTor() { - if (mCurrentStatus == STATUS_STARTING || mCurrentStatus == STATUS_STOPPING) { + // STATUS_STARTING is set in onCreate() + if (mCurrentStatus == STATUS_STOPPING) { // these states should probably be handled better sendCallbackLogMessage("Ignoring start request, currently " + mCurrentStatus); return; @@ -784,10 +788,6 @@ public class TorService extends Service implements TorServiceConstants, OrbotCon sendCallbackLogMessage("Ignoring start request, already started."); return; } - - sendCallbackStatus(STATUS_STARTING); - sendCallbackLogMessage(getString(R.string.status_starting_up)); - logNotice(getString(R.string.status_starting_up)); if (findExistingTorDaemon()) { return; // an old tor is already running, nothing to do From ddaae1d941d0f1a565438f5ddea73e8be1497547 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 12 Jun 2015 14:54:04 -0400 Subject: [PATCH 40/44] drive main screen UI updated entirely from TorService status updates Now that STATUS_STARTING is sent in TorService.onCreate(), the response time is snappy enough that we don't need hacks in OrbotMainActivity to show that long press happened. --- .../torproject/android/OrbotMainActivity.java | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index b1635f28..5707960c 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -1113,25 +1113,13 @@ public class OrbotMainActivity extends Activity } } - // guess what? this start's Tor! actually no it just requests via the local ITorService to the remote TorService instance - // to start Tor - private void startTor () throws RemoteException - { - Log.i("OrbotMainActivity", "startTor"); - - mTxtOrbotLog.setText(""); - - //here we update the UI which is a bit sloppy and mixed up code wise - //might be best to just call updateStatus() instead of directly manipulating UI in this method - yep makes sense - imgStatus.setImageResource(R.drawable.torstarting); - lblStatus.setText(getString(R.string.status_starting_up)); - + /** + * Starts tor and related daemons by sending an + * {@link TorServiceConstants#ACTION_START} {@link Intent} to + * {@link TorService} + */ + private void startTor() throws RemoteException { sendIntentToService(TorServiceConstants.ACTION_START); - - //we send a message here to the progressDialog i believe, but we can clarify that shortly - Message msg = mStatusUpdateHandler.obtainMessage(STATUS_UPDATE); - msg.obj = getString(R.string.status_starting_up); - mStatusUpdateHandler.sendMessage(msg); } public boolean onLongClick(View view) { From f16394b7dba6ba6ed216c669eb75b4fd2fee9755 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Fri, 12 Jun 2015 14:55:17 -0400 Subject: [PATCH 41/44] include all status messages with "start" in them in the starting sequence Before, the startup sequence showed "Orbot is starting..." for a long time, then quickly showed the final tor percentage messages. This adds a few more messages to provide useful feedback. --- src/org/torproject/android/OrbotMainActivity.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org/torproject/android/OrbotMainActivity.java b/src/org/torproject/android/OrbotMainActivity.java index 5707960c..e13f55de 100644 --- a/src/org/torproject/android/OrbotMainActivity.java +++ b/src/org/torproject/android/OrbotMainActivity.java @@ -1090,8 +1090,11 @@ public class OrbotMainActivity extends Activity imgStatus.setImageResource(R.drawable.torstarting); // only show Tor daemon's percentage complete messages - if (torServiceMsg.indexOf('%') != -1) + if (torServiceMsg.indexOf('%') != -1) { lblStatus.setText(torServiceMsg); + } else if (torServiceMsg.contains("tart")) { // Start and start + lblStatus.setText(torServiceMsg); + } mBtnBrowser.setEnabled(false); } else if (torStatus == TorServiceConstants.STATUS_STOPPING) { From 67d1652e57c86c20b2cac83f8334190996559cb1 Mon Sep 17 00:00:00 2001 From: Nathan Freitas Date: Mon, 22 Jun 2015 11:30:56 -0400 Subject: [PATCH 42/44] update tor to 0.2.6.9 --- external/tor | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/tor b/external/tor index 9ccf019b..d41ab972 160000 --- a/external/tor +++ b/external/tor @@ -1 +1 @@ -Subproject commit 9ccf019b168909ef6674c71aebda9f90516bb6a1 +Subproject commit d41ab97294ec69c748566f4cb610f899d9976572 From e132a79a610deb730713b203299ce783533e3aaa Mon Sep 17 00:00:00 2001 From: Nathan Freitas Date: Mon, 22 Jun 2015 12:25:37 -0400 Subject: [PATCH 43/44] improve status request/callback interaction and status UI layout --- res/layout/layout_main.xml | 82 ++++++---- .../torproject/android/OrbotMainActivity.java | 149 +++++++++++------- .../android/service/TorService.java | 53 ++++--- .../android/service/TorServiceConstants.java | 4 +- 4 files changed, 181 insertions(+), 107 deletions(-) diff --git a/res/layout/layout_main.xml b/res/layout/layout_main.xml index 1b46e551..a0fc1a66 100644 --- a/res/layout/layout_main.xml +++ b/res/layout/layout_main.xml @@ -4,6 +4,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/panel_background_main" + > - - + + - + + + + - -