From 9309eff074877606a9032fd628af683e459832e5 Mon Sep 17 00:00:00 2001 From: Norbel Ambanumben Date: Thu, 2 Nov 2023 12:33:05 +0100 Subject: [PATCH] Start implementation of `RunTests` flow --- app/src/main/AndroidManifest.xml | 5 + .../activity/runtests/RunTestsActivity.kt | 97 ++ .../activity/runtests/RunTestsViewModel.kt | 32 + .../RunTestsExpandableListViewAdapter.kt | 232 +++ .../activity/runtests/models/GroupItems.kt | 16 + .../ooniprobe/common/PreferenceManager.java | 19 + .../ooniprobe/di/ActivityComponent.java | 5 +- .../ooniprobe/fragment/DashboardFragment.java | 11 +- .../ooniprobe/test/suite/AbstractSuite.java | 19 +- .../ooniprobe/test/test/AbstractTest.java | 18 + app/src/main/res/drawable/check_box.xml | 5 + .../res/drawable/check_box_outline_blank.xml | 5 + app/src/main/res/drawable/expand_less.xml | 5 + app/src/main/res/drawable/expand_more.xml | 5 + .../main/res/layout/activity_run_tests.xml | 71 + .../res/layout/run_tests_child_list_item.xml | 27 + .../res/layout/run_tests_group_list_item.xml | 53 + app/src/main/res/values/strings.xml | 1263 ++++++++++------- engine/build.gradle | 5 +- .../org/openobservatory/engine/BaseNettest.kt | 13 + 20 files changed, 1364 insertions(+), 542 deletions(-) create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsActivity.kt create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsViewModel.kt create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt create mode 100644 app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/models/GroupItems.kt create mode 100644 app/src/main/res/drawable/check_box.xml create mode 100644 app/src/main/res/drawable/check_box_outline_blank.xml create mode 100644 app/src/main/res/drawable/expand_less.xml create mode 100644 app/src/main/res/drawable/expand_more.xml create mode 100644 app/src/main/res/layout/activity_run_tests.xml create mode 100644 app/src/main/res/layout/run_tests_child_list_item.xml create mode 100644 app/src/main/res/layout/run_tests_group_list_item.xml create mode 100644 engine/src/main/java/org/openobservatory/engine/BaseNettest.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1b717a3e5..7f53c91ba 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -38,6 +38,11 @@ android:name=".activity.OnboardingActivity" android:screenOrientation="userPortrait" android:theme="@style/Theme.MaterialComponents.NoActionBar.Onboarding" /> + ): Intent { + return Intent(context, RunTestsActivity::class.java).putExtras(Bundle().apply { + putSerializable(TESTS, testSuites as Serializable) + }) + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityRunTestsBinding.inflate(layoutInflater) + setContentView(binding.getRoot()) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + activityComponent?.inject(this) + + var testSuites: List? = intent.extras?.getParcelableArrayList(TESTS) + testSuites?.let { ts -> + val tsGroups: List = ts.map { testSuite -> + GroupItem( + selected = false, + name = testSuite.name, + nettests = testSuite.getTestList(preferenceManager).map { nettest -> + ChildItem( + selected = preferenceManager.resolveStatus(nettest.name), + name = nettest.name, + inputs = nettest.inputs + ) + }) + } + + mAdapter = RunTestsExpandableListViewAdapter(this, tsGroups, viewModel) + + binding.elv.setAdapter(mAdapter) + + viewModel.selectedAllBtnStatus.observe(this) { selectAllBtnStatus -> + if (!TextUtils.isEmpty(selectAllBtnStatus)) { + if (selectAllBtnStatus == SELECT_ALL) { + binding.ckbSelectAll.isChecked = true + } else { + binding.ckbSelectAll.isChecked = false + } + mAdapter.notifyDataSetChanged() + updateStatusIndicator() + } + } + } + + } + + private fun updateStatusIndicator() { + binding.bottomBar.setTitle(getString(R.string.OONIRun_URLs, getChildItemsSelectedIdList().size.toString())) + } + + private fun getChildItemsSelectedIdList(): List { + val childItemSelectedIdList: MutableList = ArrayList() + for (i in 0 until mAdapter.groupCount) { + val secondLevelItemList: List = mAdapter.getGroup(i).nettests + secondLevelItemList + .asSequence() + .filter { it.selected } + .mapTo(childItemSelectedIdList) { it.name } + } + return childItemSelectedIdList + } +} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsViewModel.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsViewModel.kt new file mode 100644 index 000000000..f0e868737 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/RunTestsViewModel.kt @@ -0,0 +1,32 @@ +package org.openobservatory.ooniprobe.activity.runtests + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import org.openobservatory.ooniprobe.common.PreferenceManager +import javax.inject.Inject + + +class RunTestsViewModel() : ViewModel() { + lateinit var preferenceManager: PreferenceManager + + @Inject + constructor(preferenceManager: PreferenceManager) : this() { + this.preferenceManager = preferenceManager + } + + val selectedAllBtnStatus: MutableLiveData = MutableLiveData() + + init { + selectedAllBtnStatus.postValue(SELECT_SOME) + } + + fun setSelectedAllBtnStatus(selectedStatus: String) { + selectedAllBtnStatus.postValue(selectedStatus) + } + + companion object { + const val SELECT_ALL = "SELECT_ALL" + const val SELECT_SOME = "SELECT_SOME" + const val NOT_SELECT_ANY = "NOT_SELECT_ANY" + } +} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt new file mode 100644 index 000000000..effbf28c1 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/adapter/RunTestsExpandableListViewAdapter.kt @@ -0,0 +1,232 @@ +package org.openobservatory.ooniprobe.activity.runtests.adapter + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.BaseExpandableListAdapter +import android.widget.CheckBox +import android.widget.ImageView +import android.widget.TextView +import org.openobservatory.ooniprobe.R +import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel +import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.NOT_SELECT_ANY +import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_ALL +import org.openobservatory.ooniprobe.activity.runtests.RunTestsViewModel.Companion.SELECT_SOME +import org.openobservatory.ooniprobe.activity.runtests.models.ChildItem +import org.openobservatory.ooniprobe.activity.runtests.models.GroupItem +import org.openobservatory.ooniprobe.test.suite.AbstractSuite +import org.openobservatory.ooniprobe.test.suite.ExperimentalSuite +import org.openobservatory.ooniprobe.test.test.AbstractTest + + +class RunTestsExpandableListViewAdapter( + private val mContext: Context, + private val mGroupListData: List, + private val mViewModel: RunTestsViewModel +) : BaseExpandableListAdapter() { + override fun getGroupCount(): Int { + return mGroupListData.size + } + + override fun getChildrenCount(groupPosition: Int): Int { + return mGroupListData[groupPosition].nettests.size + } + + override fun getGroup(groupPosition: Int): GroupItem { + return mGroupListData[groupPosition] + } + + override fun getChild(groupPosition: Int, childPosition: Int): ChildItem { + return mGroupListData[groupPosition].nettests[childPosition] + } + + override fun getGroupId(groupPosition: Int): Long { + return groupPosition.toLong() + } + + override fun getChildId(groupPosition: Int, childPosition: Int): Long { + return childPosition.toLong() + } + + override fun hasStableIds(): Boolean { + return false + } + + override fun getGroupView(groupPosition: Int, isExpanded: Boolean, convertView: View?, parent: ViewGroup): View? { + var convertView = + convertView ?: LayoutInflater.from(mContext).inflate(R.layout.run_tests_group_list_item, parent, false) + val groupItem = getGroup(groupPosition) + val testSuite = AbstractSuite.getTestSuiteByName(groupItem.name) + convertView.findViewById(R.id.group_name).text = parent.context.resources.getText(testSuite.title) + convertView.findViewById(R.id.group_icon).setImageResource(testSuite.icon) + val groupIndicator = convertView.findViewById(R.id.group_indicator) + val groupSelectionIndicator = convertView.findViewById(R.id.group_select_indicator) + val selectedAllBtnStatus = mViewModel.selectedAllBtnStatus.getValue() + if (selectedAllBtnStatus == SELECT_ALL) { + groupItem.selected = true + for (childItem in groupItem.nettests) { + childItem.selected = true + } + } else if (selectedAllBtnStatus == NOT_SELECT_ANY) { + groupItem.selected = false + for (childItem in groupItem.nettests) { + childItem.selected = false + } + } + if (groupItem.selected) { + if (isSelectAllChildItems(groupItem.nettests)) { + groupSelectionIndicator.setImageResource(R.drawable.check_box) + } else { + groupSelectionIndicator.setImageResource(R.drawable.check_box_outline_blank) + } + } else { + groupSelectionIndicator.setImageResource(R.drawable.check_box_outline_blank) + } + groupSelectionIndicator.setOnClickListener { + if (groupItem.selected && isSelectAllChildItems(groupItem.nettests)) { + groupItem.selected = false + for (childItem in groupItem.nettests) { + childItem.selected = false + } + if (isNotSelectedAnyGroupItem(mGroupListData)) { + mViewModel.setSelectedAllBtnStatus(NOT_SELECT_ANY) + } else { + mViewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } else { + groupItem.selected = true + for (childItem in groupItem.nettests) { + childItem.selected = true + } + if (isSelectedAllItems(mGroupListData)) { + mViewModel.setSelectedAllBtnStatus(SELECT_ALL) + } else { + mViewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } + notifyDataSetChanged() + } + if (isExpanded) { + groupIndicator.setImageResource(R.drawable.expand_less) + } else { + groupIndicator.setImageResource(R.drawable.expand_more) + } + return convertView + } + + override fun getChildView( + groupPosition: Int, + childPosition: Int, + isLastChild: Boolean, + convertView: View?, + parent: ViewGroup + ): View? { + var convertView = + convertView ?: LayoutInflater.from(mContext).inflate(R.layout.run_tests_child_list_item, parent, false) + val childItem = getChild(groupPosition, childPosition) + val groupItem = getGroup(groupPosition) + val nettest = AbstractTest.getTestByName(childItem.name) + convertView.findViewById(R.id.child_name)?.apply { + text = when (groupItem.name) { + ExperimentalSuite.NAME -> { + childItem.name + } + + else -> { + parent.context.resources.getText(nettest.labelResId) + } + } + } + convertView.findViewById(R.id.child_select).apply { + isChecked = childItem.selected + setOnCheckedChangeListener { buttonView, isChecked -> + + childItem.selected = isChecked + if (childItem.selected) { + if (isNotSelectedAnyChildItems(groupItem.nettests)) { + groupItem.selected = false + } + if (isNotSelectedAnyItems(mGroupListData)) { + mViewModel.setSelectedAllBtnStatus(NOT_SELECT_ANY) + } else { + mViewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } else { + groupItem.selected = true + if (isSelectedAllItems(mGroupListData)) { + mViewModel.setSelectedAllBtnStatus(SELECT_ALL) + } else { + mViewModel.setSelectedAllBtnStatus(SELECT_SOME) + } + } + notifyDataSetChanged() + } + } + return convertView + } + + override fun isChildSelectable(groupPosition: Int, childPosition: Int): Boolean { + return false + } + + private fun isNotSelectedAnyGroupItem(groupItemsList: List): Boolean { + for (groupItem in groupItemsList) { + if (groupItem.selected) { + return false + } + } + return true + } + + private fun isSelectedAllGroupItems(groupItemsList: List): Boolean { + for (groupItem in groupItemsList) { + if (!groupItem.selected) { + return false + } + } + return true + } + + private fun isNotSelectedAnyChildItems(childItemList: List): Boolean { + for (childItem in childItemList) { + if (childItem.selected) { + return false + } + } + return true + } + + private fun isSelectAllChildItems(childItemList: List): Boolean { + for (childItem in childItemList) { + if (!childItem.selected) { + return false + } + } + return true + } + + private fun isSelectedAllItems(groupItemList: List?): Boolean { + for (groupItem in groupItemList!!) { + if (!groupItem.selected) { + return false + } + if (!isSelectAllChildItems(groupItem.nettests)) { + return false + } + } + return true + } + + private fun isNotSelectedAnyItems(groupItemList: List?): Boolean { + for (groupItem in groupItemList!!) { + if (groupItem.selected) { + return false + } + if (!isNotSelectedAnyChildItems(groupItem.nettests)) { + return false + } + } + return true + } +} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/models/GroupItems.kt b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/models/GroupItems.kt new file mode 100644 index 000000000..49787fb22 --- /dev/null +++ b/app/src/main/java/org/openobservatory/ooniprobe/activity/runtests/models/GroupItems.kt @@ -0,0 +1,16 @@ +package org.openobservatory.ooniprobe.activity.runtests.models + +import org.openobservatory.engine.BaseDescriptor +import org.openobservatory.engine.BaseNettest + +data class ChildItem( + var selected: Boolean, + var name: String, + var inputs: List? +) + +data class GroupItem( + var selected: Boolean, + var name: String, + var nettests: List +) diff --git a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java index ba228a80b..5db0b25f8 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/common/PreferenceManager.java @@ -10,6 +10,7 @@ import org.openobservatory.ooniprobe.R; import org.openobservatory.ooniprobe.test.EngineProvider; +import org.openobservatory.ooniprobe.test.test.*; import java.net.URISyntaxException; import java.util.ArrayList; @@ -381,4 +382,22 @@ public boolean isLongRunningTestsInForeground(){ return sp.getBoolean(r.getString(R.string.long_running_tests_in_foreground), true); } + public boolean resolveStatus(String name) { + return switch (name) { + case Dash.NAME -> isRunDash(); + case FacebookMessenger.NAME -> isTestFacebookMessenger(); + case HttpHeaderFieldManipulation.NAME ->isRunHttpHeaderFieldManipulation(); + case HttpInvalidRequestLine.NAME -> isRunHttpInvalidRequestLine(); + case Ndt.NAME -> isRunNdt(); + case Psiphon.NAME -> isTestPsiphon(); + case RiseupVPN.NAME -> isTestRiseupVPN(); + case Signal.NAME -> isTestSignal(); + case Telegram.NAME -> isTestTelegram(); + case Tor.NAME -> isTestTor(); + case WebConnectivity.NAME -> countEnabledCategory()>0; + case Whatsapp.NAME -> isTestWhatsapp(); + case Experimental.NAME -> isExperimentalOn(); + default -> false; + }; + } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java b/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java index f88835ebf..eb5f90ba7 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/di/ActivityComponent.java @@ -9,6 +9,7 @@ import org.openobservatory.ooniprobe.activity.OverviewActivity; import org.openobservatory.ooniprobe.activity.ProxyActivity; import org.openobservatory.ooniprobe.activity.ResultDetailActivity; +import org.openobservatory.ooniprobe.activity.runtests.RunTestsActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; import org.openobservatory.ooniprobe.activity.TextActivity; import org.openobservatory.ooniprobe.di.annotations.PerActivity; @@ -28,4 +29,6 @@ public interface ActivityComponent { void inject(RunningActivity activity); void inject(TextActivity activity); void inject(LogActivity activity); -} \ No newline at end of file + + void inject(RunTestsActivity activity); +} diff --git a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java index 7eee1ca50..7b5c2a236 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/fragment/DashboardFragment.java @@ -17,6 +17,7 @@ import org.openobservatory.ooniprobe.activity.AbstractActivity; import org.openobservatory.ooniprobe.activity.OverviewActivity; import org.openobservatory.ooniprobe.activity.RunningActivity; +import org.openobservatory.ooniprobe.activity.runtests.RunTestsActivity; import org.openobservatory.ooniprobe.common.Application; import org.openobservatory.ooniprobe.common.PreferenceManager; import org.openobservatory.ooniprobe.common.ReachabilityManager; @@ -109,7 +110,8 @@ private void setLastTest() { } public void runAll() { - RunningActivity.runAsForegroundService((AbstractActivity) getActivity(), testSuites, this::onTestServiceStartedListener, preferenceManager); + ActivityCompat.startActivity(getContext(), RunTestsActivity.newIntent(getContext(), testSuites), null); + //RunningActivity.runAsForegroundService((AbstractActivity) getActivity(), testSuites, this::onTestServiceStartedListener, preferenceManager); } private void onTestServiceStartedListener() { @@ -125,12 +127,7 @@ private void onTestServiceStartedListener() { AbstractSuite testSuite = (AbstractSuite) v.getTag(); switch (v.getId()) { case R.id.run: - RunningActivity.runAsForegroundService( - (AbstractActivity) getActivity(), - testSuite.asArray(), - this::onTestServiceStartedListener, - preferenceManager - ); + ActivityCompat.startActivity(getContext(), RunTestsActivity.newIntent(getContext(), testSuite.asArray()), null); break; default: ActivityCompat.startActivity(getActivity(), OverviewActivity.newIntent(getActivity(), testSuite), null); diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/suite/AbstractSuite.java b/app/src/main/java/org/openobservatory/ooniprobe/test/suite/AbstractSuite.java index f797d3e3c..e3f5fc94d 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/suite/AbstractSuite.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/suite/AbstractSuite.java @@ -14,7 +14,7 @@ import org.openobservatory.ooniprobe.model.database.Result; import org.openobservatory.ooniprobe.model.database.Url; import org.openobservatory.ooniprobe.test.TestAsyncTask; -import org.openobservatory.ooniprobe.test.test.AbstractTest; +import org.openobservatory.ooniprobe.test.test.*; import java.io.Serializable; import java.util.ArrayList; @@ -163,5 +163,20 @@ public static AbstractSuite getSuite(Application app, } return null; } - + public static AbstractSuite getTestSuiteByName(String name){ + switch (name){ + case WebsitesSuite.NAME: + return new WebsitesSuite(); + case InstantMessagingSuite.NAME: + return new InstantMessagingSuite(); + case CircumventionSuite.NAME: + return new CircumventionSuite(); + case PerformanceSuite.NAME: + return new PerformanceSuite(); + case ExperimentalSuite.NAME: + return new ExperimentalSuite(); + default: + return new ExperimentalSuite(); + } + } } diff --git a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java index d1e964b38..09a283114 100644 --- a/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java +++ b/app/src/main/java/org/openobservatory/ooniprobe/test/test/AbstractTest.java @@ -374,6 +374,24 @@ public boolean isAutoRun() { return Objects.equals(origin, AUTORUN); } + public static AbstractTest getTestByName(String name){ + return switch (name) { + case Dash.NAME -> new Dash(); + case FacebookMessenger.NAME -> new FacebookMessenger(); + case HttpHeaderFieldManipulation.NAME -> new HttpHeaderFieldManipulation(); + case HttpInvalidRequestLine.NAME -> new HttpInvalidRequestLine(); + case Ndt.NAME -> new Ndt(); + case Psiphon.NAME -> new Psiphon(); + case RiseupVPN.NAME -> new RiseupVPN(); + case Signal.NAME -> new Signal(); + case Telegram.NAME -> new Telegram(); + case Tor.NAME -> new Tor(); + case WebConnectivity.NAME -> new WebConnectivity(); + case Whatsapp.NAME -> new Whatsapp(); + case Experimental.NAME -> new Experimental(name); + default -> new Experimental(name); + }; + } public interface TestCallback { void onStart(String name); diff --git a/app/src/main/res/drawable/check_box.xml b/app/src/main/res/drawable/check_box.xml new file mode 100644 index 000000000..2a4d09439 --- /dev/null +++ b/app/src/main/res/drawable/check_box.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/check_box_outline_blank.xml b/app/src/main/res/drawable/check_box_outline_blank.xml new file mode 100644 index 000000000..58000391e --- /dev/null +++ b/app/src/main/res/drawable/check_box_outline_blank.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/expand_less.xml b/app/src/main/res/drawable/expand_less.xml new file mode 100644 index 000000000..a31d83024 --- /dev/null +++ b/app/src/main/res/drawable/expand_less.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/expand_more.xml b/app/src/main/res/drawable/expand_more.xml new file mode 100644 index 000000000..48368f357 --- /dev/null +++ b/app/src/main/res/drawable/expand_more.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_run_tests.xml b/app/src/main/res/layout/activity_run_tests.xml new file mode 100644 index 000000000..c1abd310c --- /dev/null +++ b/app/src/main/res/layout/activity_run_tests.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/run_tests_child_list_item.xml b/app/src/main/res/layout/run_tests_child_list_item.xml new file mode 100644 index 000000000..3b8094bba --- /dev/null +++ b/app/src/main/res/layout/run_tests_child_list_item.xml @@ -0,0 +1,27 @@ + + + + + + + + diff --git a/app/src/main/res/layout/run_tests_group_list_item.xml b/app/src/main/res/layout/run_tests_group_list_item.xml new file mode 100644 index 000000000..b4b179e71 --- /dev/null +++ b/app/src/main/res/layout/run_tests_group_list_item.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db87e2f35..b878bc38b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,533 +1,736 @@ - OONI Probe - What is OONI Probe? - Your app for measuring internet censorship. \n\nAre websites and social media apps blocked? Is your internet connection unusually slow?\n\nRun OONI Probe to find out! - Got It - Heads-up! - OONI data is openly published and will include your network information. - Anyone monitoring your internet activity (e.g. government or ISP) will see that you are running OONI Probe. - You might test banned websites (but you can choose which sites to test). - I understand - Learn more - Pop Quiz - True - False - Go back - Continue - Question 1/2 - If someone is monitoring my internet activity, they will see that I am running OONI Probe. - Warning - OONI Probe is not a privacy tool. Anyone monitoring your internet activity will see which software you are running. - Question 2/2 - Every time I run OONI Probe, the network data I collect will automatically get published. - Warning - To increase transparency of internet censorship, the network data of all OONI Probe users is automatically published (unless they opt-out in the settings). - Automated testing - To measure internet censorship every day, please enable automated testing so that OONI Probe can run tests periodically.\n\nDon\'t worry, we\'ll be mindful of battery usage. \n\nYou can disable automated testing from the settings at any time. - Crash Reporting - To improve OONI Probe we would like to collect anonymous crash reports when the app does not work properly.\n\nWould you like to opt-in to submitting crash reports to the OONI development team? - Yes - No - Default Settings - We collect and publish: - Country code (e.g. IT for Italy) - Network information (including Autonomous System Number) - Time & date of testing - We do our best not to publish your IP address or any other potentially personally identifiable information.\n\nLearn more through [OONI\'s Data Policy](https://ooni.org/about/data-policy/). - By tapping \"OK\", you will share crash reports to help us improve OONI Probe. - Let\'s go - Change defaults - Dashboard - Run - N/A - Run - Last test: - Estimated: - Choose websites - Running: - Estimated time left: - %1$s seconds - Preparing test - Calculating ETA - Show Log - Close Log - Stopping test… - Finishing the currently pending tests, please wait… - Proxy in use - Tap card for more - ~%1$ss - Test the blocking of websites - Check whether websites are blocked using OONI\'s [Web Connectivity test](https://ooni.org/nettest/web-connectivity/).\n\nEvery time you tap Run, you test different websites from the Citizen Lab\'s [global](https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) and [country-specific](https://github.com/citizenlab/test-lists/tree/master/lists) test lists.\n\nTo test the sites of your choice, tap the Choose websites button or select categories of sites via the settings of this card. \n\nThis test measures whether websites are blocked by means of DNS tampering, TCP/IP blocking or by a transparent HTTP proxy.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/world/) and [OONI API](https://api.ooni.io/). - Check whether websites are blocked using OONI\'s [Web Connectivity test](https://ooni.org/nettest/web-connectivity/).\n\nYou will test the websites included in the Citizen Lab\'s [global](https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) and [country-specific](https://github.com/citizenlab/test-lists/tree/master/lists) test lists.\n\nThis test measures whether websites are blocked by means of DNS tampering, TCP/IP blocking or by a transparent HTTP proxy.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/). - Test your network speed and performance - Measure the speed and performance of your network using the [NDT](https://ooni.org/nettest/ndt/) test.\n\nMeasure video streaming performance using the [DASH](https://ooni.org/nettest/dash/) test.\n\nThese tests consume data depending on your network speed.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/world/) and [OONI API](https://api.ooni.io/).\n\nDisclaimer: These tests rely on third party servers. We therefore cannot guarantee that your IP address will not be collected. - By running the tests in this card, you will:\n\n- Measure the speed and performance of your network ([NDT](https://ooni.org/nettest/ndt/) test)\n- Measure video streaming performance ([DASH](https://ooni.org/nettest/dash/) test)\n- Check for the presence of [middlebox technologies](https://ooni.org/support/glossary/#middlebox) on your network ([HTTP Invalid Request Line](https://ooni.org/nettest/http-invalid-request-line/) and [HTTP Header Field Manipulation](https://ooni.org/nettest/http-header-field-manipulation/) tests)\n\nThese tests consume data depending on your network speed.\n\nYour test results will be published on [OONI Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/).\n\n**Disclaimer:** The [NDT](https://ooni.org/nettest/ndt/) and [DASH](https://ooni.org/nettest/dash/) tests are conducted against third-party servers provided by [Measurement Lab (M-Lab)](https://www.measurementlab.net/). If you run these tests, M-Lab will collect and publish your IP address (for research purposes), irrespective of your OONI Probe settings. Learn more about M-Lab’s data governance through its [privacy statement](https://www.measurementlab.net/privacy/). - Detect middleboxes in your network - Internet Service Providers often use network appliances (middleboxes) for various networking purposes (such as caching). Sometimes these middleboxes are used to implement internet censorship and/or surveillance.\n\nFind middleboxes in your network using OONI\'s [HTTP Invalid Request Line](https://ooni.org/nettest/http-invalid-request-line/) and [HTTP Header Field Manipulation](https://ooni.org/nettest/http-header-field-manipulation/) tests.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/world/) and [OONI API](https://api.ooni.io/). - Test the blocking of instant messaging apps - Check whether [WhatsApp](https://ooni.org/nettest/whatsapp/), [Facebook Messenger](https://ooni.org/nettest/facebook-messenger/), [Telegram](https://ooni.org/nettest/telegram/), and [Signal](https://ooni.org/nettest/signal) are blocked.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/world/) and [OONI API](https://api.ooni.io/). - Test the blocking of censorship circumvention tools - Check whether [Psiphon](https://ooni.org/nettest/psiphon/), [Tor](https://ooni.org/nettest/tor/) or [RiseupVPN](https://ooni.org/nettest/riseupvpn/) are blocked.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/). - Run new experimental tests - Run the following new experimental tests developed by the OONI team:\n%1$s\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/). - The following tests will only be run as part of automated testing: - Disabled Tests - Gbit/s - Mbit/s - kbit/s - ms - N/A - Unknown - Test Results - Test Results - Tests - Networks - Data Usage - Filter Tests - All Tests - Websites - Middleboxes - Performance - Instant Messaging - Circumvention - Experimental - No tests have been run yet. Try running one! - %1$s blocked - %1$s blocked - %1$s tested - %1$s tested - Detected - Not detected - Failed - %1$s blocked - %1$s blocked - %1$s accessible - %1$s accessible - %1$s blocked - %1$s blocked - %1$s available - %1$s available - Incomplete Result - Error - Error in Measurement - Results not uploaded - Date & Time - Network - Country - Data Usage - Total Runtime - WiFi - Mobile Data - No internet - Failed - Tested - Tested - Blocked - Blocked - Website - Websites - Accessible - Accessible - Video - Quality - Upload - Download - Ping - Detected - Not detected - Failed - Tested - Tested - Blocked - Blocked - Accessible - Accessible - App - Apps - Tested - Tested - Blocked - Blocked - Working - Working - Tool - Tools - Runtime - Methodology - View log - Data - Copy Explorer URL - Share Explorer URL - Copy to clipboard - Show in OONI Explorer - Failed - You can try to run this test again - Try Again - Learn how this test works [here](%1$s). - Accessible - %1$s is accessible. - Likely blocked - %1$s is likely blocked by means of %2$s.\n\nNote: False positives can occur. Learn more [here](https://ooni.org/support/faq/#what-are-false-positives). - Censorship Circumvention - **DNS tampering** - **TCP/IP based blocking** - **HTTP blocking (a blockpage might be served)** - **HTTP blocking (HTTP requests failed)** - Mobile App - OK - Failed - WhatsApp Web - OK - Failed - Registration - OK - Failed - Working - This test successfully connected to WhatsApp\'s endpoints, registration service and web interface (web.whatsapp.com). - Likely blocked - WhatsApp appears to be blocked. - Mobile App - OK - Failed - Telegram Web - OK - Failed - Working - This test successfully connected to Telegram\'s endpoints and web interface (web.telegram.org). - Likely blocked - Telegram appears to be blocked. - TCP connections - OK - Failed - DNS lookups - OK - Failed - Working - This test successfully connected to Facebook\'s endpoints and resolved to Facebook IP addresses. - Likely blocked - Facebook Messenger appears to be blocked. - Likely blocked - Signal appears to be blocked. - Working - This test successfully connected to Signal\'s endpoints. - No middleboxes detected - No network anomaly was detected when communicating with our servers. - Network tampering - Network traffic was manipulated when contacting our control servers.\n\nThis means that there may be a middlebox in your network, which could be responsible for censorship and/or surveillance. - No middleboxes detected - No network anomaly was detected when communicating with our servers. - Network tampering - Network traffic was manipulated when contacting our control servers.\n\nThis means that there may be a middlebox in your network, which could be responsible for censorship and/or surveillance. - You Sent - You Received - Upload - Download - Ping - Server - Retransmission Rate - Out of Order - Average Ping - Max Ping Estimate - MSS - Timeouts - You can stream up to %1$s without buffering. - Median Bitrate - Playout Delay - Likely blocked - Working - [Psiphon](https://psiphon.ca/) appears to be blocked. - We were able to successfully bootstrap a Psiphon connection. This means that [Psiphon](https://psiphon.ca/) should work. - Bootstrap Time - %1$s s - Likely blocked - Working - [Tor](https://www.torproject.org/) appears to be blocked. - We were able to successfully connect to the default Tor bridges and/or Tor directory authorities. This means that [Tor](https://www.torproject.org/) should work. - Default Bridges - %1$s/%2$s OK - Directory Authorities - %1$s/%2$s OK - Name - Address - Type - Connect - Handshake - Likely blocked - Working - [RiseupVPN](https://riseup.net/vpn) appears to be blocked. - We were able to successfully connect to RiseupVPN\'s bootstrap server and VPN gateways. This means that [RiseupVPN](https://riseup.net/vpn) should work. - Bootstrap server - OpenVPN connections - Bridged connections - Blocked - %1$s blocked - %1$s blocked - OK - This is an experimental test. - Feed - Feed - OK - Cancel - No, don\'t ask again - Delete - Error - Retry - Sounds great - No, thanks - Not now - Run anyways - Disable VPN - Always Run - Unable to run the test. Please check your internet connectivity. - Unable to download URL list. Please try again. - Please wait for the current running tests to finish, before starting a new test. - Notification permissions are required. Please enable them in the Settings of your phone and then enable them in your OONI Probe app. - Go to the Settings - This screen is locked while a test is running. - You need to be connected to the internet to download the raw measurement data. - Results not uploaded - Some of your test results have not been uploaded to OONI servers. If you\'d like to contribute to OONI\'s dataset, please upload them. - Upload - Uploading %1$s ... - OONI Probe cannot run automatically without battery optimization. Do you want to try again? - Please disable your VPN connection. - If you run OONI Probe with a VPN enabled, the test results may appear to come from the wrong country. Please disable your VPN connection. - Some measurements were taken over VPN. - If you upload measurements taken when VPN enabled, the test results may appear to come from the wrong country. - Upload successful - Display failure log - Get updates on internet censorship - Interested in running OONI Probe tests during emergent censorship events? Enable notifications to receive a message when we hear of internet censorship near you. - To improve the accuracy of tests, we need GPS permissions. OONI will only collect an approximation of your GPS position. - Do you want to delete all test results? - Do you want to delete this test? - Please enable at least one test - Please insert only digits in this field. - Re-run test - This test has failed. Re-run the test? - You are about to re-test %1$s websites. - Run - Your URLs will not be saved when you leave this screen. Are you sure you want to leave this screen? - Enable Manual Upload? - This setting allows you to manually re-upload unpublished measurements. - Enable - No, thanks - Upload failed - We have failed to upload %1$s/%2$s measurements. The failure log has been shared with OONI developers. - Log file not found - No valid URLs found - JSON empty - Do you want to interrupt this test? - This will interrupt the current test from this moment. - Would you like to run tests automatically? - By enabling automated testing, you will contribute OONI measurements on a regular basis. - Please allow the app to run in the background. - Remind me later - Copied to clipboard - Not uploaded - Upload - Some not uploaded - Upload All - Websites - Instant Messaging - Middleboxes - Performance - Circumvention - Experimental - HTTP Invalid Request Line Test - HTTP Header Field Manipulation Test - Web Connectivity Test - NDT Speed Test - DASH Streaming Test - WhatsApp Test - Telegram Test - Facebook Messenger Test - Psiphon Test - Tor Test - RiseupVPN Test - Signal Test - Settings - The amount of time you have set for the test duration is too low. - About OONI - The Open Observatory of Network Interference (OONI) is a free software project under The Tor Project that aims to increase transparency of internet censorship around the world.\n\nSince 2012, OONI\'s global community has been measuring networks in more than 200 countries. Some of these measurements serve as evidence of internet censorship. - Learn more - Blog - Reports - OONI Data Policy - Notifications - Enabled - Notify upon test completion - News Feed - Automated testing - Run tests automatically - Number of automated tests: %1$s. - Last automated test: %1$s. - Only on WiFi - Only while charging - By enabling automatic testing, OONI Probe tests will run automatically multiple times per day. Your test results will automatically get published on OONI Explorer: https://explorer.ooni.org/ \n\nImportant: If you have a VPN enabled, OONI Probe will not run tests automatically. Please turn off your VPN for automated OONI Probe testing. Learn more: https://ooni.org/support/faq/#can-i-run-ooni-probe-over-a-vpn - Sharing - Automatically Publish Results - Manual Result Upload - Include Network Info - Include approximate geo-location - Include my IP address - Include Country Code - This information (e.g. IT for Italy) is required to identify which country the measurements are collected from. Are you sure you want to disable this option? - By publishing results, you are increasing transparency of network interference and supporting the OONI community. \n\nNetwork information (i.e. Autonomous System Number) is required for identifying Internet Service Providers. - Test options - What you configure through the above test settings (e.g. disabling the WhatsApp test) will apply to tests run manually, as well as to tests run automatically (when automated testing is enabled). - Long running test - Run long running tests in foreground? - Privacy - Send crash reports - Advanced - Dark Mode - Debug logs - See recent logs - Language Setting - Select Language - Always use domain fronting - OONI backend proxy - Proxy - None - Psiphon - Custom Proxy - Custom Proxy URL - Custom proxy protocol - Connection - Hostname - Port - Credentials (optional) - Username - Password - Use Psiphon over custom proxy - Are you unable to use OONI Probe? Try enabling [Psiphon](https://psiphon.ca/) to circumvent potential OONI Probe blocking. Alternatively, you can use a custom proxy. - Limit test duration - Test duration - Website categories to test - %1$s categories enabled - Edit - Deselect All - Select All - Save - Unsaved Changes - You made some changes to the enabled categories. Would you like to save them? - Save - Discard - Choose websites to test - URL - No URLs entered - Run - Add website - Load from template - Number of tested websites (0 means all) - Test WhatsApp - Test Telegram - Test Facebook Messenger - Test Signal - Run the HTTP Invalid Request Line Test - Run the HTTP Header Field Manipulation Test - Run the NDT Speed Test - Automatic NDT server selection - NDT server address - NDT server port - Run the DASH Streaming Test - Automatic DASH server selection - DASH server - DASH server port - Test Psiphon - Test Tor - Test RiseupVPN - Warn when VPN is in use - Send email to support - Please describe the problem you are experiencing: - Please send an email to bugs@openobservatory.org with information on the app and iOS version. Tap \"Copy to clipboard\" below to copy our email address. - Current app language is %1$s - Language - Storage usage - Storage used - Delete - Clear - You are about to delete all OONI measurements from your device. If uploaded, they will still be available on [OONI Explorer](https://explorer.ooni.org) - Finished running - Stop test - Try mirror - Loading... - An unexpected error occurred. Please reload this page. - You are about to run an OONI Probe test. - %1$s URLs - Test Name - Test Details - Run - Out of date - You need a newer version of OONI Probe to run this test. - Update - Close - Invalid parameter - The OONI Run link is either malformed or your app is out of date. - You will test a random sample of websites. - Please wait for the test to finish running before tapping on an OONI Run link. - Drugs & Alcohol - Religion - Pornography - Provocative Attire - Political Criticism - Human Rights Issues - Environment - Terrorism and Militants - Hate Speech - News Media - Sex Education - Public Health - Gambling - Circumvention tools - Online Dating - Social Networking - LGBTQ+ - File-sharing - Hacking Tools - Communication Tools - Media sharing - Hosting and Blogging - Search Engines - Gaming - Culture - Economics - Government - E-commerce - Control content - Intergovernmental Orgs. - Miscellaneous content - Use and sale of drugs and alcohol - Religious issues, both supportive and critical - Hard-core and soft-core pornography - Provocative attire and portrayal of women wearing minimal clothing - Critical political viewpoints - Human rights issues - Discussions on environmental issues - Terrorism, violent militant or separatist movements - Disparaging of particular groups based on race, sex, sexuality or other characteristics - Major news websites, regional news outlets and independent media - Sexual health issues including contraception, STD\'s, rape prevention and abortion - Public health issues, such as COVID-19, HIV/AIDS, Ebola - Online gambling and betting - Anonymization, censorship circumvention and encryption - Online dating sites - Online social networking tools and platforms - LGBTQ+ communities discussing related issues (excluding pornography) - File sharing including cloud-based file storage, torrents and P2P - Computer security tools and news - Individual and group communication tools including VoIP, messaging and webmail - Video, audio and photo sharing - Web hosting, blogging and other online publishing - Search engines and portals - Online games and gaming platforms (excluding gambling sites) - Entertainment including history, literature, music, film, satire and humour - General economic development and poverty - Government-run websites, including military - Commercial services and products - Benign or innocuous content used for control - Intergovernmental organizations including The United Nations - Sites that haven\'t been categorized yet + OONI Probe + What is OONI Probe? + Your app for measuring internet censorship. \n\nAre websites and + social media apps blocked? Is your internet connection unusually slow?\n\nRun OONI Probe to find out! + + Got It + Heads-up! + OONI data is openly published and will include your network + information. + + Anyone monitoring your internet activity (e.g. government or ISP) + will see that you are running OONI Probe. + + You might test banned websites (but you can choose which sites to + test). + + I understand + Learn more + Pop Quiz + True + False + Go back + Continue + Question 1/2 + If someone is monitoring my internet activity, they will see that I am + running OONI Probe. + + Warning + OONI Probe is not a privacy tool. Anyone monitoring your + internet activity will see which software you are running. + + Question 2/2 + Every time I run OONI Probe, the network data I collect will + automatically get published. + + Warning + To increase transparency of internet censorship, the network + data of all OONI Probe users is automatically published (unless they opt-out in the settings). + + Automated testing + To measure internet censorship every day, please enable + automated testing so that OONI Probe can run tests periodically.\n\nDon\'t worry, we\'ll be mindful of battery + usage. \n\nYou can disable automated testing from the settings at any time. + + Crash Reporting + To improve OONI Probe we would like to collect anonymous crash reports + when the app does not work properly.\n\nWould you like to opt-in to submitting crash reports to the OONI + development team? + + Yes + No + Default Settings + We collect and publish: + Country code (e.g. IT for Italy) + Network information (including Autonomous System Number) + Time & date of testing + We do our best not to publish your IP address or any other + potentially personally identifiable information.\n\nLearn more through [OONI\'s Data + Policy](https://ooni.org/about/data-policy/). + + By tapping \"OK\", you will share crash reports to help us + improve OONI Probe. + + Let\'s go + Change defaults + Dashboard + Run + N/A + Run + Last test: + Estimated: + Choose websites + Running: + Estimated time left: + %1$s seconds + Preparing test + Calculating ETA + Show Log + Close Log + Stopping test… + Finishing the currently pending tests, please wait… + Proxy in use + Tap card for more + ~%1$ss + Test the blocking of websites + Check whether websites are blocked using OONI\'s [Web + Connectivity test](https://ooni.org/nettest/web-connectivity/).\n\nEvery time you tap Run, you test different + websites from the Citizen Lab\'s [global](https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) + and [country-specific](https://github.com/citizenlab/test-lists/tree/master/lists) test lists.\n\nTo test the + sites of your choice, tap the Choose websites button or select categories of sites via the settings of this + card. \n\nThis test measures whether websites are blocked by means of DNS tampering, TCP/IP blocking or by a + transparent HTTP proxy.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/world/) + and [OONI API](https://api.ooni.io/). + + Check whether websites are blocked using OONI\'s [Web + Connectivity test](https://ooni.org/nettest/web-connectivity/).\n\nYou will test the websites included in the + Citizen Lab\'s [global](https://github.com/citizenlab/test-lists/blob/master/lists/global.csv) and + [country-specific](https://github.com/citizenlab/test-lists/tree/master/lists) test lists.\n\nThis test measures + whether websites are blocked by means of DNS tampering, TCP/IP blocking or by a transparent HTTP proxy.\n\nYour + results will be published on [OONI Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/). + + Test your network speed and performance + Measure the speed and performance of your network using the + [NDT](https://ooni.org/nettest/ndt/) test.\n\nMeasure video streaming performance using the + [DASH](https://ooni.org/nettest/dash/) test.\n\nThese tests consume data depending on your network + speed.\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/world/) and [OONI + API](https://api.ooni.io/).\n\nDisclaimer: These tests rely on third party servers. We therefore cannot + guarantee that your IP address will not be collected. + + By running the tests in this card, you will:\n\n- + Measure the speed and performance of your network ([NDT](https://ooni.org/nettest/ndt/) test)\n- Measure video + streaming performance ([DASH](https://ooni.org/nettest/dash/) test)\n- Check for the presence of [middlebox + technologies](https://ooni.org/support/glossary/#middlebox) on your network ([HTTP Invalid Request + Line](https://ooni.org/nettest/http-invalid-request-line/) and [HTTP Header Field + Manipulation](https://ooni.org/nettest/http-header-field-manipulation/) tests)\n\nThese tests consume data + depending on your network speed.\n\nYour test results will be published on [OONI + Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/).\n\n**Disclaimer:** The + [NDT](https://ooni.org/nettest/ndt/) and [DASH](https://ooni.org/nettest/dash/) tests are conducted against + third-party servers provided by [Measurement Lab (M-Lab)](https://www.measurementlab.net/). If you run these + tests, M-Lab will collect and publish your IP address (for research purposes), irrespective of your OONI Probe + settings. Learn more about M-Lab’s data governance through its [privacy + statement](https://www.measurementlab.net/privacy/). + + Detect middleboxes in your network + Internet Service Providers often use network appliances + (middleboxes) for various networking purposes (such as caching). Sometimes these middleboxes are used to + implement internet censorship and/or surveillance.\n\nFind middleboxes in your network using OONI\'s [HTTP + Invalid Request Line](https://ooni.org/nettest/http-invalid-request-line/) and [HTTP Header Field + Manipulation](https://ooni.org/nettest/http-header-field-manipulation/) tests.\n\nYour results will be published + on [OONI Explorer](https://explorer.ooni.org/world/) and [OONI API](https://api.ooni.io/). + + Test the blocking of instant messaging apps + Check whether + [WhatsApp](https://ooni.org/nettest/whatsapp/), [Facebook + Messenger](https://ooni.org/nettest/facebook-messenger/), [Telegram](https://ooni.org/nettest/telegram/), and + [Signal](https://ooni.org/nettest/signal) are blocked.\n\nYour results will be published on [OONI + Explorer](https://explorer.ooni.org/world/) and [OONI API](https://api.ooni.io/). + + Test the blocking of censorship circumvention tools + Check whether + [Psiphon](https://ooni.org/nettest/psiphon/), [Tor](https://ooni.org/nettest/tor/) or + [RiseupVPN](https://ooni.org/nettest/riseupvpn/) are blocked.\n\nYour results will be published on [OONI + Explorer](https://explorer.ooni.org/) and [OONI API](https://api.ooni.io/). + + Run new experimental tests + Run the following new experimental tests developed by the + OONI team:\n%1$s\n\nYour results will be published on [OONI Explorer](https://explorer.ooni.org/) and [OONI + API](https://api.ooni.io/). + + The following tests will only be run as + part of automated testing: + + Disabled Tests + Gbit/s + Mbit/s + kbit/s + ms + N/A + Unknown + Test Results + Test Results + Tests + Networks + Data Usage + Filter Tests + All Tests + Websites + Middleboxes + Performance + Instant Messaging + Circumvention + Experimental + No tests have been run yet. Try running one! + %1$s blocked + %1$s blocked + %1$s tested + %1$s tested + Detected + Not detected + Failed + %1$s blocked + %1$s blocked + %1$s accessible + %1$s accessible + %1$s blocked + %1$s blocked + %1$s available + %1$s available + Incomplete Result + Error + Error in Measurement + Results not uploaded + Date & Time + Network + Country + Data Usage + Total Runtime + WiFi + Mobile Data + No internet + Failed + Tested + Tested + Blocked + Blocked + Website + Websites + Accessible + Accessible + Video + Quality + Upload + Download + Ping + Detected + Not detected + Failed + Tested + Tested + Blocked + Blocked + Accessible + Accessible + App + Apps + Tested + Tested + Blocked + Blocked + Working + Working + Tool + Tools + Runtime + Methodology + View log + Data + Copy Explorer URL + Share Explorer URL + Copy to clipboard + Show in OONI Explorer + Failed + You can try to run this test again + Try Again + Learn how this test works [here](%1$s). + Accessible + %1$s is accessible. + Likely blocked + %1$s is likely blocked by means of + %2$s.\n\nNote: False positives can occur. Learn more + [here](https://ooni.org/support/faq/#what-are-false-positives). + + Censorship Circumvention + + **DNS tampering** + **TCP/IP based blocking** + **HTTP blocking (a blockpage might + be served)** + + **HTTP blocking (HTTP requests + failed)** + + Mobile App + OK + Failed + WhatsApp Web + OK + Failed + Registration + OK + Failed + Working + This test successfully + connected to WhatsApp\'s endpoints, registration service and web interface (web.whatsapp.com). + + Likely blocked + WhatsApp appears to be + blocked. + + Mobile App + OK + Failed + Telegram Web + OK + Failed + Working + This test successfully + connected to Telegram\'s endpoints and web interface (web.telegram.org). + + Likely blocked + Telegram appears to be + blocked. + + TCP connections + OK + Failed + DNS lookups + OK + Failed + Working + This test + successfully connected to Facebook\'s endpoints and resolved to Facebook IP addresses. + + Likely blocked + + Facebook + Messenger appears to be blocked. + + Likely blocked + Signal appears to be + blocked. + + Working + This test successfully + connected to Signal\'s endpoints. + + No middleboxes detected + + No network anomaly + was detected when communicating with our servers. + + Network tampering + Network traffic was + manipulated when contacting our control servers.\n\nThis means that there may be a middlebox in your network, + which could be responsible for censorship and/or surveillance. + + No middleboxes + detected + + No network + anomaly was detected when communicating with our servers. + + Network tampering + + Network traffic + was manipulated when contacting our control servers.\n\nThis means that there may be a middlebox in your + network, which could be responsible for censorship and/or surveillance. + + You Sent + You Received + Upload + Download + Ping + Server + Retransmission Rate + Out of Order + Average Ping + Max Ping Estimate + MSS + Timeouts + You can stream up to %1$s without + buffering. + + Median Bitrate + Playout Delay + Likely blocked + Working + [Psiphon](https://psiphon.ca/) + appears to be blocked. + + We were able to successfully + bootstrap a Psiphon connection. This means that [Psiphon](https://psiphon.ca/) should work. + + Bootstrap Time + %1$s s + Likely blocked + Working + [Tor](https://www.torproject.org/) + appears to be blocked. + + We were able to successfully + connect to the default Tor bridges and/or Tor directory authorities. This means that + [Tor](https://www.torproject.org/) should work. + + Default Bridges + %1$s/%2$s OK + Directory Authorities + %1$s/%2$s OK + Name + Address + Type + Connect + Handshake + Likely blocked + Working + + [RiseupVPN](https://riseup.net/vpn) appears to be blocked. + + We were able to successfully + connect to RiseupVPN\'s bootstrap server and VPN gateways. This means that [RiseupVPN](https://riseup.net/vpn) + should work. + + Bootstrap server + OpenVPN connections + Bridged connections + Blocked + %1$s blocked + %1$s blocked + OK + This is an experimental test. + Feed + Feed + OK + Cancel + No, don\'t ask again + Delete + Error + Retry + Sounds great + No, thanks + Not now + Run anyways + Disable VPN + Always Run + Unable to run the test. Please check your internet connectivity. + Unable to download URL list. Please try again. + Please wait for the current running tests to finish, before starting a + new test. + + Notification permissions are required. Please enable them in the + Settings of your phone and then enable them in your OONI Probe app. + + Go to the Settings + This screen is locked while a test is running. + You need to be connected to the internet to download the raw + measurement data. + + Results not uploaded + Some of your test results have not been uploaded to OONI servers. + If you\'d like to contribute to OONI\'s dataset, please upload them. + + Upload + Uploading %1$s ... + OONI Probe cannot run automatically without battery optimization. + Do you want to try again? + + Please disable your VPN connection. + If you run OONI Probe with a VPN enabled, the test results may appear to + come from the wrong country. Please disable your VPN connection. + + Some measurements were taken over VPN. + If you upload measurements taken when VPN enabled, the test results + may appear to come from the wrong country. + + Upload successful + Display failure log + Get updates on internet censorship + Interested in running OONI Probe tests during emergent censorship + events? Enable notifications to receive a message when we hear of internet censorship near you. + + To improve the accuracy of tests, we need GPS permissions. OONI will only collect an + approximation of your GPS position. + + Do you want to delete all test results? + Do you want to delete this test? + Please enable at least one test + Please insert only digits in this field. + Re-run test + This test has failed. Re-run the test? + You are about to re-test %1$s websites. + Run + Your URLs will not be saved when you leave this screen. Are you sure you + want to leave this screen? + + Enable Manual Upload? + This setting allows you to manually re-upload unpublished + measurements. + + Enable + No, thanks + Upload failed + We have failed to upload %1$s/%2$s measurements. The failure log has + been shared with OONI developers. + + Log file not found + No valid URLs found + JSON empty + Do you want to interrupt this test? + This will interrupt the current test from this moment. + Would you like to run tests automatically? + By enabling automated testing, you will contribute OONI measurements on a + regular basis. + + Please allow the app to run in the background. + Remind me later + Copied to clipboard + Not uploaded + Upload + Some not uploaded + Upload All + Websites + Instant Messaging + Middleboxes + Performance + Circumvention + Experimental + HTTP Invalid Request Line Test + HTTP Header Field Manipulation Test + Web Connectivity Test + NDT Speed Test + DASH Streaming Test + WhatsApp Test + Telegram Test + Facebook Messenger Test + Psiphon Test + Tor Test + RiseupVPN Test + Signal Test + Settings + The amount of time you have set for the test duration is too low. + + About OONI + The Open Observatory of Network Interference (OONI) is a free + software project under The Tor Project that aims to increase transparency of internet censorship around the + world.\n\nSince 2012, OONI\'s global community has been measuring networks in more than 200 countries. Some of + these measurements serve as evidence of internet censorship. + + Learn more + Blog + Reports + OONI Data Policy + Notifications + Enabled + Notify upon test completion + News Feed + Automated testing + Run tests automatically + Number of automated tests: %1$s. + Last automated test: %1$s. + Only on WiFi + Only while charging + By enabling automatic testing, OONI Probe tests + will run automatically multiple times per day. Your test results will automatically get published on OONI + Explorer: https://explorer.ooni.org/ \n\nImportant: If you have a VPN enabled, OONI Probe will not run tests + automatically. Please turn off your VPN for automated OONI Probe testing. Learn more: + https://ooni.org/support/faq/#can-i-run-ooni-probe-over-a-vpn + + Sharing + Automatically Publish Results + Manual Result Upload + Include Network Info + Include approximate geo-location + Include my IP address + Include Country Code + This information (e.g. IT for Italy) is required to + identify which country the measurements are collected from. Are you sure you want to disable this option? + + By publishing results, you are increasing transparency of network + interference and supporting the OONI community. \n\nNetwork information (i.e. Autonomous System Number) is + required for identifying Internet Service Providers. + + Test options + What you configure through the above test settings (e.g. disabling the + WhatsApp test) will apply to tests run manually, as well as to tests run automatically (when automated testing + is enabled). + + Long running test + Run long running tests in foreground? + Privacy + Send crash reports + Advanced + Dark Mode + Debug logs + See recent logs + Language Setting + Select Language + Always use domain fronting + OONI backend proxy + Proxy + None + Psiphon + Custom Proxy + Custom Proxy URL + Custom proxy protocol + Connection + Hostname + Port + Credentials (optional) + Username + Password + Use Psiphon over custom proxy + Are you unable to use OONI Probe? Try enabling [Psiphon](https://psiphon.ca/) + to circumvent potential OONI Probe blocking. Alternatively, you can use a custom proxy. + + Limit test duration + Test duration + Website categories to test + %1$s categories enabled + Edit + Deselect All + Select All + Save + Unsaved Changes + You made some changes to the enabled categories. Would + you like to save them? + + Save + Discard + Choose websites to test + URL + No URLs entered + Run + Add website + Load from template + Number of tested websites (0 means all) + Test WhatsApp + Test Telegram + Test Facebook Messenger + Test Signal + Run the HTTP Invalid Request Line Test + Run the HTTP Header Field Manipulation Test + + Run the NDT Speed Test + Automatic NDT server selection + NDT server address + NDT server port + Run the DASH Streaming Test + Automatic DASH server selection + DASH server + DASH server port + Test Psiphon + Test Tor + Test RiseupVPN + Warn when VPN is in use + Send email to support + Please describe the problem you are experiencing: + Please send an email to bugs@openobservatory.org with information on the app + and iOS version. Tap \"Copy to clipboard\" below to copy our email address. + + Current app language is %1$s + Language + Storage usage + Storage used + Delete + Clear + You are about to delete all OONI measurements from your + device. If uploaded, they will still be available on [OONI Explorer](https://explorer.ooni.org) + + Finished running + Stop test + Try mirror + Loading... + An unexpected error occurred. Please reload this page. + You are about to run an OONI Probe test. + %1$s URLs + Test Name + Test Details + Run + Out of date + You need a newer version of OONI Probe to run this test. + Update + Close + Invalid parameter + The OONI Run link is either malformed or your app is out of date. + + You will test a random sample of websites. + Please wait for the test to finish running before tapping on an OONI Run + link. + + Drugs & Alcohol + Religion + Pornography + Provocative Attire + Political Criticism + Human Rights Issues + Environment + Terrorism and Militants + Hate Speech + News Media + Sex Education + Public Health + Gambling + Circumvention tools + Online Dating + Social Networking + LGBTQ+ + File-sharing + Hacking Tools + Communication Tools + Media sharing + Hosting and Blogging + Search Engines + Gaming + Culture + Economics + Government + E-commerce + Control content + Intergovernmental Orgs. + Miscellaneous content + Use and sale of drugs and alcohol + Religious issues, both supportive and critical + Hard-core and soft-core pornography + Provocative attire and portrayal of women wearing minimal clothing + + Critical political viewpoints + Human rights issues + Discussions on environmental issues + Terrorism, violent militant or separatist movements + Disparaging of particular groups based on race, sex, sexuality or other + characteristics + + Major news websites, regional news outlets and independent media + + Sexual health issues including contraception, STD\'s, rape prevention + and abortion + + Public health issues, such as COVID-19, HIV/AIDS, Ebola + Online gambling and betting + Anonymization, censorship circumvention and encryption + Online dating sites + Online social networking tools and platforms + LGBTQ+ communities discussing related issues (excluding pornography) + + File sharing including cloud-based file storage, torrents and P2P + + Computer security tools and news + Individual and group communication tools including VoIP, messaging and + webmail + + Video, audio and photo sharing + Web hosting, blogging and other online publishing + Search engines and portals + Online games and gaming platforms (excluding gambling sites) + Entertainment including history, literature, music, film, satire and + humour + + General economic development and poverty + Government-run websites, including military + Commercial services and products + Benign or innocuous content used for control + Intergovernmental organizations including The United Nations + Sites that haven\'t been categorized yet diff --git a/engine/build.gradle b/engine/build.gradle index a64cced29..73ca7270e 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -1,5 +1,6 @@ plugins { id 'com.android.library' + id 'kotlin-android' } android { @@ -11,8 +12,8 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } flavorDimensions 'testing' diff --git a/engine/src/main/java/org/openobservatory/engine/BaseNettest.kt b/engine/src/main/java/org/openobservatory/engine/BaseNettest.kt new file mode 100644 index 000000000..694c5728b --- /dev/null +++ b/engine/src/main/java/org/openobservatory/engine/BaseNettest.kt @@ -0,0 +1,13 @@ +package org.openobservatory.engine + +import java.io.Serializable + +open class BaseNettest( + open var name: String, + open var inputs: List? +) : Serializable + +open class BaseDescriptor( + open var name: String, + open var nettests: List +) : Serializable