mirror of https://github.com/LeOS-GSI/LeOS-Genesis
parent
58329d826b
commit
48c2191eb2
|
@ -1,24 +1,10 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
<package name="io.ktor" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="XML">
|
||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
||||
<indentOptions>
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
|
@ -130,5 +116,8 @@
|
|||
</rules>
|
||||
</arrangement>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</component>
|
|
@ -0,0 +1,5 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="1.8" />
|
||||
<bytecodeTargetLevel target="11" />
|
||||
</component>
|
||||
</project>
|
|
@ -27,8 +27,8 @@
|
|||
</set>
|
||||
</option>
|
||||
<option name="resolveModulePerSourceSet" value="false" />
|
||||
<option name="useQualifiedModuleNames" value="true" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
<option name="offlineMode" value="true" />
|
||||
</component>
|
||||
</project>
|
|
@ -6,7 +6,7 @@
|
|||
<inspection_tool class="BooleanMethodIsAlwaysInverted" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="BusyWait" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="CollectionAddAllCanBeReplacedWithConstructor" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="ConstantConditions" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
|
||||
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
|
||||
</inspection_tool>
|
||||
|
@ -32,6 +32,9 @@
|
|||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SuspiciousListRemoveInLoop" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="SuspiciousMethodCalls" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
<option name="REPORT_CONVERTIBLE_METHOD_CALLS" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="TrivialIf" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="UNCHECKED_WARNING" enabled="false" level="WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="UnnecessaryLocalVariable" enabled="false" level="WARNING" enabled_by_default="false">
|
||||
|
|
|
@ -43,5 +43,5 @@
|
|||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
|
||||
</project>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.android.tools.idea.compose.preview.runconfiguration.ComposePreviewRunConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -31,18 +31,6 @@
|
|||
"versionName": "Build | Dark-Origin 1.1",
|
||||
"outputFile": "app-aarch64-x86-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
{
|
||||
"filterType": "ABI",
|
||||
"value": "arm64-v8a"
|
||||
}
|
||||
],
|
||||
"versionCode": 1001,
|
||||
"versionName": "Build | Dark-Origin 1.1",
|
||||
"outputFile": "app-aarch64-arm64-v8a-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
|
@ -54,6 +42,18 @@
|
|||
"versionCode": 1001,
|
||||
"versionName": "Build | Dark-Origin 1.1",
|
||||
"outputFile": "app-aarch64-armeabi-v7a-release.apk"
|
||||
},
|
||||
{
|
||||
"type": "ONE_OF_MANY",
|
||||
"filters": [
|
||||
{
|
||||
"filterType": "ABI",
|
||||
"value": "arm64-v8a"
|
||||
}
|
||||
],
|
||||
"versionCode": 1001,
|
||||
"versionName": "Build | Dark-Origin 1.1",
|
||||
"outputFile": "app-aarch64-arm64-v8a-release.apk"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -143,7 +143,9 @@
|
|||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="com.darkweb.genesissearchengine.externalNavigationManager.externalNavigationController">
|
||||
<activity android:name="com.darkweb.genesissearchengine.externalNavigationManager.externalNavigationController"
|
||||
android:launchMode="singleTask"
|
||||
>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mRealIndex.clear();
|
||||
mCurrentList.clear();
|
||||
this.mModelList.clear();
|
||||
onVerifyLongSelectedURL();
|
||||
onVerifyLongSelectedURL(true);
|
||||
|
||||
ArrayList<bookmarkRowModel> p_model_list = mPassedList;
|
||||
for(int counter = 0; counter< p_model_list.size(); counter++){
|
||||
|
@ -88,7 +88,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
}
|
||||
|
||||
mRealID.add(p_model_list.get(counter).getID());
|
||||
mRealIndex.add(m_real_counter);
|
||||
mRealIndex.add(counter);
|
||||
this.mModelList.add(p_model_list.get(counter));
|
||||
m_real_counter+=1;
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
}
|
||||
}
|
||||
clearLongSelectedURL();
|
||||
initializeModelWithDate(false);
|
||||
// initializeModelWithDate(false);
|
||||
}
|
||||
|
||||
private void clearLongSelectedURL(){
|
||||
|
@ -185,6 +185,15 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mSearchEnabled = p_is_searched;
|
||||
}
|
||||
|
||||
public void invokeSwipeClose(int pPosition){
|
||||
onClose(pPosition);
|
||||
invokeFilter(true);
|
||||
|
||||
if(mPopupWindow!=null){
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void onSelectView(View pItemView, String pUrl, View pMenuItem, ImageView pLogoImage, boolean pIsForced, int pId, Date pDate){
|
||||
if(!mSearchEnabled){
|
||||
try {
|
||||
|
@ -196,16 +205,21 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mLongSelectedDate.add(pDate);
|
||||
mLongSelectedIndex.add(pUrl);
|
||||
mLongSelectedID.add(pId);
|
||||
|
||||
if(mLongSelectedIndex.size()<=1){
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
onVerifyLongSelectedURL();
|
||||
onVerifyLongSelectedURL(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void onVerifyLongSelectedURL(){
|
||||
public void onVerifyLongSelectedURL(boolean pIsComputing){
|
||||
if(mLongSelectedIndex.size()>0){
|
||||
mEvent.invokeObserver(Collections.singletonList(false),enums.etype.on_verify_selected_url_menu);
|
||||
}else {
|
||||
if(!pIsComputing){
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
mEvent.invokeObserver(Collections.singletonList(true),enums.etype.on_verify_selected_url_menu);
|
||||
}
|
||||
}
|
||||
|
@ -217,12 +231,19 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mLongSelectedDate.remove(pDate);
|
||||
mLongSelectedIndex.remove(pUrl);
|
||||
mLongSelectedID.remove((Integer) pId);
|
||||
onVerifyLongSelectedURL();
|
||||
onVerifyLongSelectedURL(false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyFilter(){
|
||||
if(mFilter.length()>0){
|
||||
initializeModelWithDate(true);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public void onSwipe(View pItemView, String pUrl, View pMenuItem, ImageView pLogoImage, int pId, Date pDate){
|
||||
|
||||
|
@ -241,6 +262,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
pItemView.setPressed(false);
|
||||
pItemView.clearFocus();
|
||||
}
|
||||
notifyFilter();
|
||||
};
|
||||
|
||||
pItemView.setOnTouchListener((v, event) -> {
|
||||
|
@ -257,12 +279,14 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
bookmarkAdapter.this.onSelectView(pItemView, pUrl, pMenuItem, pLogoImage, false, pId, pDate);
|
||||
}
|
||||
}
|
||||
initializeModelWithDate(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
v.setPressed(false);
|
||||
handler.removeCallbacks(mLongPressed);
|
||||
mEvent.invokeObserver(Collections.singletonList(pUrl), enums.etype.url_triggered);
|
||||
initializeModelWithDate(true);
|
||||
return true;
|
||||
|
||||
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
|
@ -270,6 +294,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mLongPressedMenuActive = false;
|
||||
v.setPressed(true);
|
||||
handler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
|
||||
initializeModelWithDate(true);
|
||||
return true;
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
handler.removeCallbacks(mLongPressed);
|
||||
|
@ -279,10 +304,13 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
}
|
||||
handler.removeCallbacks(mLongPressed);
|
||||
|
||||
initializeModelWithDate(true);
|
||||
return true;
|
||||
}
|
||||
initializeModelWithDate(true);
|
||||
return false;
|
||||
});
|
||||
// initializeModelWithDate(false);
|
||||
}
|
||||
|
||||
void onOpenMenu(View pView, String pUrl, int pPosition, String pTitle){
|
||||
|
@ -295,6 +323,11 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenCurrentTab), pUrl, pPosition, pTitle);
|
||||
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenNewTab), pUrl, pPosition, pTitle);
|
||||
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuDelete), pUrl, pPosition, pTitle);
|
||||
|
||||
if(mFilter.length()>0){
|
||||
initializeModelWithDate(true);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPopupWindowEvents(View pView, String pUrl, int pPosition, String pTitle){
|
||||
|
@ -333,29 +366,19 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mEvent.invokeObserver(Collections.singletonList(mRealIndex.get(pIndex)),enums.etype.url_clear);
|
||||
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.url_clear_at);
|
||||
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.is_empty);
|
||||
boolean mDateVerify = false;
|
||||
if(mPassedList.size()>0){
|
||||
if(mCurrentList.size()>0 && (mCurrentList.size()>pIndex+1 || mCurrentList.size()==pIndex+1)){
|
||||
mDateVerify = true;
|
||||
}
|
||||
}else {
|
||||
|
||||
if(mPassedList.size()<=0){
|
||||
mCurrentList.clear();
|
||||
return;
|
||||
}
|
||||
int size = mCurrentList.size();
|
||||
|
||||
if(mDateVerify){
|
||||
mCurrentList.remove(pIndex);
|
||||
notifyItemRemoved(pIndex);
|
||||
notifyItemRangeChanged(pIndex, mCurrentList.size());
|
||||
}else {
|
||||
mCurrentList.remove(pIndex);
|
||||
notifyItemRemoved(pIndex);
|
||||
notifyItemChanged(mCurrentList.size()-1);
|
||||
}
|
||||
initializeModelWithDate(false);
|
||||
mCurrentList.remove(mRealIndex.get(pIndex));
|
||||
notifyItemRemoved(mRealIndex.get(pIndex));
|
||||
notifyItemRangeChanged(0, mCurrentList.size());
|
||||
clearLongSelectedURL();
|
||||
}
|
||||
|
||||
|
||||
/*View Holder Extensions*/
|
||||
class listViewHolder extends RecyclerView.ViewHolder
|
||||
{
|
||||
|
@ -411,8 +434,13 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
mDateContainer.setVisibility(View.GONE);
|
||||
mLoadingContainer.setVisibility(View.GONE);
|
||||
mRowContainer.setVisibility(View.VISIBLE);
|
||||
mRowMenu.setVisibility(View.VISIBLE);
|
||||
mRowMenu.setClickable(true);
|
||||
if(mLongSelectedID.size()>0){
|
||||
mRowMenu.setVisibility(View.INVISIBLE);
|
||||
mRowMenu.setClickable(false);
|
||||
}else {
|
||||
mRowMenu.setVisibility(View.VISIBLE);
|
||||
mRowMenu.setClickable(true);
|
||||
}
|
||||
mWebLogo.setVisibility(View.VISIBLE);
|
||||
mHeader.setText(model.getHeader());
|
||||
mWebLogo.setText((helperMethod.getDomainName(model.getHeader()).toUpperCase().charAt(0)+""));
|
||||
|
@ -443,7 +471,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
Bitmap mBitmap = helperMethod.drawableToBitmap(mHindTypeIconTemp.getDrawable());
|
||||
mFaviconLogo.setImageBitmap(mBitmap);
|
||||
});
|
||||
} catch (InterruptedException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
@ -475,7 +503,7 @@ public class bookmarkAdapter extends RecyclerView.Adapter<bookmarkAdapter.listVi
|
|||
|
||||
void invokeFilter(boolean notify){
|
||||
if(notify){
|
||||
notifyDataSetChanged();
|
||||
initializeModelWithDate(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,7 @@ public class bookmarkAdapterView
|
|||
helperMethod.vibrate(mContext);
|
||||
}
|
||||
|
||||
|
||||
pLogoImage.setAlpha(0f);
|
||||
pLogoImage.setVisibility(View.VISIBLE);
|
||||
pLogoImage.animate().cancel();
|
||||
|
|
|
@ -23,6 +23,7 @@ import androidx.recyclerview.widget.ItemTouchHelper;
|
|||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.historyManager.historyEnums;
|
||||
import com.darkweb.genesissearchengine.databaseManager.databaseController;
|
||||
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.editTextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.homeController;
|
||||
|
@ -145,10 +146,11 @@ public class bookmarkController extends AppCompatActivity
|
|||
|
||||
mSearchInput.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
mSearchInput.clearFocus();
|
||||
// mSearchInput.clearFocus();
|
||||
}else {
|
||||
((bookmarkAdapter) Objects.requireNonNull(mRecycleView.getAdapter())).setFilter(mSearchInput.getText().toString());
|
||||
((bookmarkAdapter) mRecycleView.getAdapter()).invokeFilter(true);
|
||||
mbookmarkAdapter.setFilter(mSearchInput.getText().toString());
|
||||
mbookmarkAdapter.invokeFilter(true);
|
||||
mbookmarkAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -167,10 +169,12 @@ public class bookmarkController extends AppCompatActivity
|
|||
@Override
|
||||
public void afterTextChanged(Editable editable)
|
||||
{
|
||||
((bookmarkAdapter) Objects.requireNonNull(mRecycleView.getAdapter())).setFilter(mSearchInput.getText().toString());
|
||||
((bookmarkAdapter) mRecycleView.getAdapter()).invokeFilter(true);
|
||||
mbookmarkAdapter.setFilter(mSearchInput.getText().toString());
|
||||
mbookmarkAdapter.invokeFilter(true);
|
||||
mbookmarkAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -189,31 +193,14 @@ public class bookmarkController extends AppCompatActivity
|
|||
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
mbookmarkAdapter.onTrigger(bookmarkEnums.eBookmarkAdapterCommands.ON_CLOSE,Collections.singletonList(position));
|
||||
mbookmarkAdapter.invokeSwipeClose(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||
boolean mStatus = (boolean) mbookmarkAdapter.onTrigger(bookmarkEnums.eBookmarkAdapterCommands.GET_LONG_SELECTED_STATUS, null);
|
||||
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
|
||||
if(mStatus){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||
final int swipeFlags = 0;
|
||||
return makeMovementFlags(swipeFlags, dragFlags);
|
||||
}
|
||||
} else {
|
||||
if(mStatus){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||
final int swipeFlags = 0;
|
||||
return makeMovementFlags(swipeFlags, dragFlags);
|
||||
}
|
||||
}
|
||||
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||
final int swipeFlags = 0;
|
||||
return makeMovementFlags(swipeFlags, dragFlags);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -371,9 +358,6 @@ public class bookmarkController extends AppCompatActivity
|
|||
|
||||
else if(e_type.equals(enums.etype.url_clear)){
|
||||
mbookmarkModel.onManualClear((int)data.get(0));
|
||||
if(mbookmarkModel.getList().size()==0){
|
||||
mRecycleView.setAlpha(0);
|
||||
}
|
||||
}
|
||||
else if(e_type.equals(enums.etype.url_clear_at)){
|
||||
dataController.getInstance().invokeBookmark(dataEnums.eBookmarkCommands.M_DELETE_BOOKMARK ,data);
|
||||
|
|
|
@ -100,6 +100,7 @@ class bookmarkViewController
|
|||
mEmptyListNotification.animate().setDuration(pDuration).alpha(0f);
|
||||
mClearButton.setText(strings.HISTORY_CLEAR_HISTORY);
|
||||
mClearButton.setClickable(true);
|
||||
mRecycleView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else {
|
||||
mClearButton.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v3));
|
||||
|
@ -120,6 +121,7 @@ class bookmarkViewController
|
|||
|
||||
mClearButton.getLayoutParams().height = 0;
|
||||
mClearButton.requestLayout();
|
||||
mRecycleView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,16 +180,13 @@ class bookmarkViewController
|
|||
mSearchInput.setVisibility(View.GONE);
|
||||
mSearchInput.setText(strings.GENERIC_EMPTY_STR);
|
||||
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mTitle.setAlpha(0f);
|
||||
mTitle.setVisibility(View.VISIBLE);
|
||||
mTitle.animate().setDuration(150).alpha(1);
|
||||
mTitle.setAlpha(0f);
|
||||
mTitle.setVisibility(View.VISIBLE);
|
||||
mTitle.animate().setDuration(150).alpha(1);
|
||||
|
||||
mSearchButton.setAlpha(0f);
|
||||
mSearchButton.setVisibility(View.VISIBLE);
|
||||
mSearchButton.animate().setDuration(150).alpha(1);
|
||||
}, 500);
|
||||
mSearchButton.setAlpha(0f);
|
||||
mSearchButton.setVisibility(View.VISIBLE);
|
||||
mSearchButton.animate().setDuration(150).alpha(1);
|
||||
|
||||
mSearchInput.setText(strings.GENERIC_EMPTY_STR);
|
||||
mSearchInput.setClickable(false);
|
||||
|
|
|
@ -91,7 +91,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mRealIndex.clear();
|
||||
mCurrentList.clear();
|
||||
this.mModelList.clear();
|
||||
onVerifyLongSelectedURL();
|
||||
onVerifyLongSelectedURL(true);
|
||||
|
||||
ArrayList<historyRowModel> p_model_list = mPassedList;
|
||||
int m_date_state = -1;
|
||||
|
@ -117,7 +117,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
if(m_date_state!=1 && p_model_list.get(counter).getID()!=-2){
|
||||
this.mModelList.add(new historyRowModel("Today ",null,-1));
|
||||
mRealID.add(m_real_counter);
|
||||
mRealIndex.add(m_real_counter);
|
||||
mRealIndex.add(counter);
|
||||
m_date_state = 1;
|
||||
}
|
||||
}else if (diff>=1){
|
||||
|
@ -126,20 +126,20 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
m_last_day = (int)(Math.ceil(diff/7)*7);
|
||||
this.mModelList.add(new historyRowModel("Last " + m_last_day + " Days",null,-1));
|
||||
mRealID.add(m_real_counter);
|
||||
mRealIndex.add(m_real_counter);
|
||||
mRealIndex.add(counter);
|
||||
m_date_state = 2;
|
||||
}
|
||||
}else {
|
||||
if(m_date_state!=3){
|
||||
this.mModelList.add(new historyRowModel("Older ",null,-1));
|
||||
mRealID.add(m_real_counter);
|
||||
mRealIndex.add(m_real_counter);
|
||||
mRealIndex.add(counter);
|
||||
m_date_state = 3;
|
||||
}
|
||||
}
|
||||
|
||||
mRealID.add(p_model_list.get(counter).getID());
|
||||
mRealIndex.add(m_real_counter);
|
||||
mRealIndex.add(counter);
|
||||
this.mModelList.add(p_model_list.get(counter));
|
||||
m_real_counter+=1;
|
||||
}
|
||||
|
@ -251,16 +251,33 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mLongSelectedDate.add(pDate);
|
||||
mLongSelectedIndex.add(pUrl);
|
||||
mLongSelectedID.add(pId);
|
||||
|
||||
if(mLongSelectedIndex.size()<=1){
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
onVerifyLongSelectedURL();
|
||||
onVerifyLongSelectedURL(false);
|
||||
pItemView.clearFocus();
|
||||
pItemView.setPressed(false);
|
||||
pItemView.setVisibility(View.GONE);
|
||||
pItemView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
public void onVerifyLongSelectedURL(){
|
||||
public boolean isSwipable(int mIndex){
|
||||
if(mCurrentList.get(mIndex).getID() == -1){
|
||||
return false;
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void onVerifyLongSelectedURL(boolean pIsComputing){
|
||||
if(mLongSelectedIndex.size()>0){
|
||||
mEvent.invokeObserver(Collections.singletonList(false),enums.etype.on_verify_selected_url_menu);
|
||||
}else {
|
||||
if(!pIsComputing){
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
mEvent.invokeObserver(Collections.singletonList(true),enums.etype.on_verify_selected_url_menu);
|
||||
}
|
||||
}
|
||||
|
@ -272,7 +289,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mLongSelectedDate.remove(pDate);
|
||||
mLongSelectedIndex.remove(pUrl);
|
||||
mLongSelectedID.remove((Integer) pId);
|
||||
onVerifyLongSelectedURL();
|
||||
onVerifyLongSelectedURL(false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -282,6 +299,13 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mWebIcon.clear();
|
||||
}
|
||||
|
||||
public void notifyFilter(){
|
||||
if(mFilter.length()>0){
|
||||
initializeModelWithDate(true);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
public void onSwipe(View pItemView, String pUrl, View pMenuItem, ImageView pLogoImage, int pId, Date pDate){
|
||||
|
||||
|
@ -300,6 +324,11 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
pItemView.setPressed(false);
|
||||
pItemView.clearFocus();
|
||||
}
|
||||
|
||||
if(mFilter.length()>0){
|
||||
initializeModelWithDate(true);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
};
|
||||
|
||||
pItemView.setOnTouchListener((v, event) -> {
|
||||
|
@ -316,12 +345,15 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
historyAdapter.this.onSelectView(pItemView, pUrl, pMenuItem, pLogoImage, false, pId, pDate);
|
||||
}
|
||||
}
|
||||
|
||||
initializeModelWithDate(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
v.setPressed(false);
|
||||
handler.removeCallbacks(mLongPressed);
|
||||
mEvent.invokeObserver(Collections.singletonList(pUrl), enums.etype.url_triggered);
|
||||
initializeModelWithDate(true);
|
||||
return true;
|
||||
|
||||
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
|
@ -329,6 +361,7 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mLongPressedMenuActive = false;
|
||||
v.setPressed(true);
|
||||
handler.postDelayed(mLongPressed, ViewConfiguration.getLongPressTimeout());
|
||||
initializeModelWithDate(true);
|
||||
return true;
|
||||
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
|
||||
handler.removeCallbacks(mLongPressed);
|
||||
|
@ -338,11 +371,14 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
}
|
||||
handler.removeCallbacks(mLongPressed);
|
||||
|
||||
initializeModelWithDate(true);
|
||||
return true;
|
||||
}
|
||||
initializeModelWithDate(true);
|
||||
return false;
|
||||
|
||||
});
|
||||
initializeModelWithDate(false);
|
||||
//initializeModelWithDate(false);
|
||||
}
|
||||
|
||||
void onOpenMenu(View pView, String pUrl, int pPosition, String pTitle){
|
||||
|
@ -355,6 +391,20 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenCurrentTab), pUrl, pPosition, pTitle);
|
||||
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuOpenNewTab), pUrl, pPosition, pTitle);
|
||||
setPopupWindowEvents(mPopupView.findViewById(R.id.pMenuDelete), pUrl, pPosition, pTitle);
|
||||
|
||||
if(mFilter.length()>0){
|
||||
initializeModelWithDate(true);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public void invokeSwipeClose(int pPosition){
|
||||
onClose(pPosition);
|
||||
invokeFilter(true);
|
||||
|
||||
if(mPopupWindow!=null){
|
||||
mPopupWindow.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void setPopupWindowEvents(View pView, String pUrl, int pPosition, String pTitle){
|
||||
|
@ -393,27 +443,16 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mEvent.invokeObserver(Collections.singletonList(mRealIndex.get(pIndex)),enums.etype.url_clear);
|
||||
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.url_clear_at);
|
||||
mEvent.invokeObserver(Collections.singletonList(mRealID.get(pIndex)),enums.etype.is_empty);
|
||||
boolean mDateVerify = false;
|
||||
if(mPassedList.size()>0){
|
||||
if(mCurrentList.size()>0 && (mCurrentList.size()>pIndex+1 || mCurrentList.size()==pIndex+1)){
|
||||
mDateVerify = true;
|
||||
}
|
||||
}else {
|
||||
|
||||
if(mPassedList.size()<=0){
|
||||
mCurrentList.clear();
|
||||
return;
|
||||
}
|
||||
int size = mCurrentList.size();
|
||||
|
||||
if(mDateVerify){
|
||||
mCurrentList.remove(pIndex);
|
||||
notifyItemRemoved(pIndex);
|
||||
notifyItemRangeChanged(pIndex, mCurrentList.size());
|
||||
}else {
|
||||
mCurrentList.remove(pIndex);
|
||||
notifyItemRemoved(pIndex);
|
||||
notifyItemChanged(mCurrentList.size()-1);
|
||||
}
|
||||
initializeModelWithDate(false);
|
||||
mCurrentList.remove(pIndex);
|
||||
notifyItemRemoved(pIndex);
|
||||
notifyItemRangeChanged(0, mCurrentList.size());
|
||||
clearLongSelectedURL();
|
||||
}
|
||||
|
||||
/*View Holder Extensions*/
|
||||
|
@ -472,8 +511,14 @@ public class historyAdapter extends RecyclerView.Adapter<historyAdapter.listView
|
|||
mDateContainer.setVisibility(View.GONE);
|
||||
mLoadingContainer.setVisibility(View.GONE);
|
||||
mRowContainer.setVisibility(View.VISIBLE);
|
||||
mRowMenu.setVisibility(View.VISIBLE);
|
||||
mRowMenu.setClickable(true);
|
||||
if(mLongSelectedID.size()>0){
|
||||
mRowMenu.setVisibility(View.INVISIBLE);
|
||||
mRowMenu.setClickable(false);
|
||||
}else {
|
||||
mRowMenu.setVisibility(View.VISIBLE);
|
||||
mRowMenu.setClickable(true);
|
||||
}
|
||||
|
||||
mWebLogo.setVisibility(View.VISIBLE);
|
||||
mHeader.setText(model.getHeader());
|
||||
mWebLogo.setText((helperMethod.getDomainName(model.getHeader()).toUpperCase().charAt(0)+""));
|
||||
|
|
|
@ -164,6 +164,9 @@ public class historyController extends AppCompatActivity
|
|||
mSearchInput.setOnEditorActionListener((v, actionId, event) ->{
|
||||
if (actionId == EditorInfo.IME_ACTION_NEXT)
|
||||
{
|
||||
mHistoryAdapter.setFilter(mSearchInput.getText().toString());
|
||||
mHistoryAdapter.invokeFilter(true);
|
||||
mHistoryAdapter.notifyDataSetChanged();
|
||||
helperMethod.hideKeyboard(this);
|
||||
return true;
|
||||
}
|
||||
|
@ -172,14 +175,15 @@ public class historyController extends AppCompatActivity
|
|||
|
||||
mSearchInput.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
if (!hasFocus) {
|
||||
//mSearchInput.clearFocus();
|
||||
//onHideSearch(null);
|
||||
// mSearchInput.clearFocus();
|
||||
}else {
|
||||
//mHistoryAdapter.setFilter(mSearchInput.getText().toString());
|
||||
//mHistoryAdapter.invokeFilter(true);
|
||||
mHistoryAdapter.setFilter(mSearchInput.getText().toString());
|
||||
mHistoryAdapter.invokeFilter(true);
|
||||
mHistoryAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
mSearchInput.addTextChangedListener(new TextWatcher() {
|
||||
|
||||
@Override
|
||||
|
@ -197,6 +201,7 @@ public class historyController extends AppCompatActivity
|
|||
{
|
||||
mHistoryAdapter.setFilter(mSearchInput.getText().toString());
|
||||
mHistoryAdapter.invokeFilter(true);
|
||||
mHistoryAdapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -212,30 +217,18 @@ public class historyController extends AppCompatActivity
|
|||
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
mHistoryAdapter.onTrigger(historyEnums.eHistoryAdapterCommands.ON_CLOSE,Collections.singletonList(position));
|
||||
mHistoryAdapter.invokeSwipeClose(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
|
||||
boolean mStatus = (boolean) mHistoryAdapter.onTrigger(historyEnums.eHistoryAdapterCommands.GET_LONG_SELECTED_STATUS, null);
|
||||
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
|
||||
if(mStatus){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||
final int swipeFlags = 0;
|
||||
return makeMovementFlags(swipeFlags, dragFlags);
|
||||
}
|
||||
} else {
|
||||
if(mStatus){
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||
final int swipeFlags = 0;
|
||||
return makeMovementFlags(swipeFlags, dragFlags);
|
||||
}
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
if(mHistoryAdapter.isSwipable(position)){
|
||||
final int dragFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
|
||||
final int swipeFlags = 0;
|
||||
return makeMovementFlags(swipeFlags, dragFlags);
|
||||
}else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ class historyViewController
|
|||
mEmptyListNotification.animate().setDuration(pDuration).alpha(0f);
|
||||
mClearButton.setText(strings.HISTORY_CLEAR_HISTORY);
|
||||
mClearButton.setClickable(true);
|
||||
mRecycleView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
else {
|
||||
mClearButton.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v3));
|
||||
|
@ -111,6 +112,7 @@ class historyViewController
|
|||
|
||||
mClearButton.getLayoutParams().height = 0;
|
||||
mClearButton.requestLayout();
|
||||
mRecycleView.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,24 +4,24 @@ import android.content.Context;
|
|||
import androidx.core.view.NestedScrollingChildHelper;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import com.darkweb.genesissearchengine.constants.status;
|
||||
import com.darkweb.genesissearchengine.helperManager.eventObserver;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
import org.mozilla.geckoview.PanZoomController;
|
||||
|
||||
import java.util.Collections;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_CHANGED;
|
||||
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_DOWN;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_UP_ALWAYS;
|
||||
|
||||
public class NestedGeckoView extends GeckoView {
|
||||
private int mLastY = 0;
|
||||
private int deltaY = 0;
|
||||
private int mLastY;
|
||||
private final int[] mScrollOffset = new int[2];
|
||||
private final int[] mScrollConsumed = new int[2];
|
||||
private int mNestedOffsetY;
|
||||
private NestedScrollingChildHelper mChildHelper;
|
||||
private eventObserver.eventListener mEvent;
|
||||
private int mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
|
||||
|
||||
public void onSetHomeEvent(eventObserver.eventListener pEvent){
|
||||
mEvent = pEvent;
|
||||
|
@ -32,71 +32,76 @@ public class NestedGeckoView extends GeckoView {
|
|||
mChildHelper = null;
|
||||
}
|
||||
|
||||
public NestedGeckoView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
public NestedGeckoView(Context context, AttributeSet attrs) {
|
||||
super(context.getApplicationContext(), attrs);
|
||||
|
||||
public NestedGeckoView(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mChildHelper = new NestedScrollingChildHelper(this);
|
||||
setNestedScrollingEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent ev) {
|
||||
MotionEvent event = MotionEvent.obtain(ev);
|
||||
final int action = event.getActionMasked();
|
||||
int eventY = (int) event.getY();
|
||||
final MotionEvent event = MotionEvent.obtain(ev);
|
||||
final int action = ev.getActionMasked();
|
||||
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mNestedOffsetY = 0;
|
||||
}
|
||||
|
||||
final int eventY = (int) event.getY();
|
||||
event.offsetLocation(0, mNestedOffsetY);
|
||||
|
||||
if(event.getPointerCount() > 1 && !status.sSettingEnableZoom) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
final boolean allowScroll = !shouldPinOnScreen() &&
|
||||
mInputResult == PanZoomController.INPUT_RESULT_HANDLED;
|
||||
|
||||
if(!status.sSettingEnableZoom){
|
||||
mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
}
|
||||
// mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_FINISHED);
|
||||
final boolean allowScroll = status.sFullScreenBrowsing;
|
||||
int deltaY = mLastY - eventY;
|
||||
|
||||
|
||||
if (allowScroll && dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
|
||||
deltaY -= mScrollConsumed[1];
|
||||
event.offsetLocation(0f, -mScrollOffset[1]);
|
||||
event.offsetLocation(0, -mScrollOffset[1]);
|
||||
mNestedOffsetY += mScrollOffset[1];
|
||||
}
|
||||
|
||||
|
||||
mLastY = eventY - mScrollOffset[1];
|
||||
|
||||
if (allowScroll && dispatchNestedScroll(0, mScrollOffset[1], 0, deltaY, mScrollOffset)) {
|
||||
mLastY -= mScrollOffset[1];
|
||||
event.offsetLocation(0f, mScrollOffset[1]);
|
||||
event.offsetLocation(0, mScrollOffset[1]);
|
||||
mNestedOffsetY += mScrollOffset[1];
|
||||
}
|
||||
|
||||
if(status.sFullScreenBrowsing){
|
||||
Log.i("wow1", eventY + "");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
// A new gesture started. Reset handled status and ask GV if it can handle this.
|
||||
mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
|
||||
updateInputResult(event);
|
||||
|
||||
mNestedOffsetY = 0;
|
||||
mLastY = eventY;
|
||||
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
|
||||
mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_DOWN);
|
||||
break;
|
||||
|
||||
// The event should be handled either by onTouchEvent,
|
||||
// either by onTouchEventForResult, never by both.
|
||||
// Early return if we sent it to updateInputResult(..) which calls onTouchEventForResult.
|
||||
event.recycle();
|
||||
return true;
|
||||
|
||||
// We don't care about other touch events
|
||||
case MotionEvent.ACTION_UP:
|
||||
mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_UP_ALWAYS);
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
// mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_FINISHED);
|
||||
stopNestedScroll();
|
||||
break;
|
||||
|
||||
default:
|
||||
// mEvent.invokeObserver(Collections.singletonList(null), GECKO_SCROLL_FINISHED);
|
||||
}
|
||||
|
||||
// Execute event handler from parent class in all cases
|
||||
final boolean eventHandled = callSuperOnTouchEvent(event);
|
||||
boolean eventHandled = super.onTouchEvent(event);
|
||||
|
||||
// Recycle previously obtained event
|
||||
event.recycle();
|
||||
|
@ -104,25 +109,6 @@ public class NestedGeckoView extends GeckoView {
|
|||
return eventHandled;
|
||||
}
|
||||
|
||||
private boolean callSuperOnTouchEvent(MotionEvent event) {
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
private void updateInputResult(MotionEvent event) {
|
||||
if(status.sSettingEnableZoom){
|
||||
super.onTouchEventForResult(event).accept(inputResult -> {
|
||||
mInputResult = inputResult;
|
||||
mInputResult = PanZoomController.INPUT_RESULT_UNHANDLED;
|
||||
|
||||
startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int getInputResult() {
|
||||
return mInputResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNestedScrollingEnabled(boolean enabled) {
|
||||
mChildHelper.setNestedScrollingEnabled(enabled);
|
||||
|
@ -149,11 +135,7 @@ public class NestedGeckoView extends GeckoView {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedScroll(int dxConsumed,
|
||||
int dyConsumed,
|
||||
int dxUnconsumed,
|
||||
int dyUnconsumed,
|
||||
int[] offsetInWindow) {
|
||||
public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
|
||||
return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow);
|
||||
}
|
||||
|
||||
|
@ -167,8 +149,8 @@ public class NestedGeckoView extends GeckoView {
|
|||
return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
|
||||
return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
|
||||
public int getMaxY(){
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
|
@ -3,6 +3,7 @@ package com.darkweb.genesissearchengine.appManager.homeManager.geckoManager;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
@ -13,8 +14,12 @@ import com.darkweb.genesissearchengine.dataManager.dataController;
|
|||
import com.darkweb.genesissearchengine.dataManager.dataEnums;
|
||||
import com.darkweb.genesissearchengine.helperManager.eventObserver;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_REPORT_URL;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.on_handle_external_intent;
|
||||
import static org.mozilla.geckoview.GeckoSessionSettings.USER_AGENT_MODE_MOBILE;
|
||||
|
@ -71,15 +76,28 @@ public class geckoClients
|
|||
public void onValidateInitializeFromStartup(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
|
||||
boolean mStatus = mSession.onValidateInitializeFromStartup();
|
||||
if(mStatus){
|
||||
// loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
|
||||
mSession.onRestoreState();
|
||||
mSession.reload();
|
||||
boolean mState = mSession.onRestoreState();
|
||||
if(!mState){
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mSession.stop();
|
||||
mSession.loadUri(mSession.getCurrentURL());
|
||||
}, 500);
|
||||
}else {
|
||||
String mURL = mSession.getCurrentURL();
|
||||
if(mURL.equals("https://boogle.store") || mURL.startsWith(CONST_GENESIS_URL_CACHED) || mURL.startsWith(CONST_GENESIS_URL_CACHED_DARK)){
|
||||
if(!mSession.canGoBack()){
|
||||
mNestedGeckoView.releaseSession();
|
||||
mSession.close();
|
||||
mSession.open(mRuntime);
|
||||
mNestedGeckoView.setSession(mSession);
|
||||
}else {
|
||||
mSession.goBack();
|
||||
}
|
||||
loadURL("boogle.store", mNestedGeckoView, pcontext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean onGetInitializeFromStartup(){
|
||||
return mSession.onGetInitializeFromStartup();
|
||||
}
|
||||
|
||||
public geckoSession initFreeSession(GeckoView pGeckoView, AppCompatActivity pcontext, eventObserver.eventListener event){
|
||||
|
@ -223,6 +241,7 @@ public class geckoClients
|
|||
if(status.sTheme == enums.Theme.THEME_LIGHT || helperMethod.isDayMode(pcontext)){
|
||||
String mURL = constants.CONST_GENESIS_URL_CACHED + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
|
||||
mSession.getSettings().setAllowJavascript(true);
|
||||
mSession.initURL(mURL);
|
||||
mSession.loadUri(mURL);
|
||||
}else {
|
||||
String mURL = constants.CONST_GENESIS_URL_CACHED_DARK + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
|
||||
|
@ -258,6 +277,10 @@ public class geckoClients
|
|||
onLoadFavIcon(pcontext);
|
||||
}
|
||||
|
||||
public boolean isLoaded(){
|
||||
return mSession.isLoaded();
|
||||
}
|
||||
|
||||
public void onClearSiteData(){
|
||||
mRuntime.getStorageController().clearData(SITE_SETTINGS);
|
||||
mRuntime.getStorageController().clearData(SITE_DATA);
|
||||
|
@ -278,9 +301,10 @@ public class geckoClients
|
|||
mRuntime.getStorageController().clearData(COOKIES);
|
||||
}
|
||||
|
||||
public void onBackPressed(boolean isFinishAllowed, int mTabSize){
|
||||
public void onBackPressed(boolean isFinishAllowed, int mTabSize, NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
|
||||
if(mSession.canGoBack()){
|
||||
mSession.goBackSession();
|
||||
mSession.onUpdateBannerAdvert();
|
||||
}
|
||||
else if(isFinishAllowed){
|
||||
if(mSession.getRemovableFromBackPressed() && mTabSize>1){
|
||||
|
@ -321,6 +345,10 @@ public class geckoClients
|
|||
}
|
||||
}
|
||||
|
||||
public void onClose(){
|
||||
mSession.onClose();
|
||||
}
|
||||
|
||||
public void setRemovableFromBackPressed(boolean pStatus){
|
||||
mSession.setRemovableFromBackPressed(pStatus);
|
||||
}
|
||||
|
@ -331,9 +359,18 @@ public class geckoClients
|
|||
}
|
||||
|
||||
public void onReload(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
|
||||
mSession.stop();
|
||||
String url = mSession.getCurrentURL();
|
||||
if(url.startsWith("https://boogle.store/?pG") || url.startsWith("https://boogle.store?pG") || url.endsWith("boogle.store") || url.contains(constants.CONST_GENESIS_HELP_URL_SUB) || url.contains(constants.CONST_GENESIS_HELP_URL_CACHE) || url.contains(constants.CONST_GENESIS_HELP_URL_CACHE_DARK)){
|
||||
loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
|
||||
}else{
|
||||
mSession.reload();
|
||||
}
|
||||
}
|
||||
|
||||
public void onReloadStatic(NestedGeckoView mNestedGeckoView, AppCompatActivity pcontext){
|
||||
///mSession.stop();
|
||||
mSession.reload();
|
||||
//loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
|
||||
loadURL(mSession.getCurrentURL(), mNestedGeckoView, pcontext);
|
||||
}
|
||||
|
||||
public void manual_download(String url, AppCompatActivity context){
|
||||
|
@ -377,12 +414,53 @@ public class geckoClients
|
|||
mRuntime.getSettings().setFontSizeFactor(font/100);
|
||||
}
|
||||
|
||||
public void reinitHomeTheme(){
|
||||
String mURLFinal;
|
||||
mSession.initURL(constants.CONST_GENESIS_DOMAIN_URL);
|
||||
if(status.sTheme == enums.Theme.THEME_LIGHT || helperMethod.isDayMode(activityContextManager.getInstance().getHomeController())){
|
||||
String mURL = constants.CONST_GENESIS_URL_CACHED + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
|
||||
mSession.getSettings().setAllowJavascript(true);
|
||||
mSession.initURL(mURL);
|
||||
mURLFinal = mURL;
|
||||
}else {
|
||||
String mURL = constants.CONST_GENESIS_URL_CACHED_DARK + "?pData="+ dataController.getInstance().invokeReferenceWebsite(dataEnums.eReferenceWebsiteCommands.M_FETCH,null);
|
||||
mSession.getSettings().setAllowJavascript(true);
|
||||
mSession.initURL(mURL);
|
||||
mURLFinal = mURL;
|
||||
}
|
||||
|
||||
if(!mSession.canGoBack()){
|
||||
activityContextManager.getInstance().getHomeController().getGeckoView().releaseSession();
|
||||
mSession.close();
|
||||
mSession.open(mRuntime);
|
||||
activityContextManager.getInstance().getHomeController().getGeckoView().setSession(mSession);
|
||||
}else {
|
||||
mSession.goBack();
|
||||
}
|
||||
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
if(!mSession.canGoBack()){
|
||||
mSession.close();
|
||||
activityContextManager.getInstance().getHomeController().getGeckoView().releaseSession();
|
||||
mSession.open(mRuntime);
|
||||
activityContextManager.getInstance().getHomeController().getGeckoView().setSession(mSession);
|
||||
}
|
||||
|
||||
mSession.loadUri(mURLFinal);
|
||||
|
||||
}, 10);
|
||||
|
||||
}
|
||||
|
||||
public class geckoViewClientCallback implements eventObserver.eventListener{
|
||||
@Override
|
||||
public Object invokeObserver(List<Object> data, Object e_type)
|
||||
{
|
||||
if(mSession!=null && mSession.isClosed()){
|
||||
if(e_type.equals(enums.etype.M_CHANGE_HOME_THEME)){
|
||||
reinitHomeTheme();
|
||||
}
|
||||
else if(mSession!=null && mSession.isClosed()){
|
||||
return null;
|
||||
}else if(mSession!=null) {
|
||||
if(e_type.equals(enums.etype.SESSION_ID)){
|
||||
|
|
|
@ -28,6 +28,8 @@ import androidx.annotation.UiThread;
|
|||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.constants.constants;
|
||||
import com.darkweb.genesissearchengine.constants.enums;
|
||||
import com.darkweb.genesissearchengine.constants.status;
|
||||
|
@ -75,12 +77,14 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
{
|
||||
private eventObserver.eventListener event;
|
||||
|
||||
private boolean wasBackPressed = false;
|
||||
private String mSessionID;
|
||||
private boolean mCanGoBack = false;
|
||||
private boolean mCanGoForward = false;
|
||||
private boolean mFullScreen = false;
|
||||
private boolean isPageLoading = false;
|
||||
private int mProgress = 0;
|
||||
private String mPrevURL = "about:blank";
|
||||
private String mCurrentTitle = "loading";
|
||||
private String mCurrentURL = "about:blank";
|
||||
private Uri mUriPermission = null;
|
||||
|
@ -341,6 +345,10 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
event.invokeObserver(Arrays.asList("",mSessionID,mCurrentTitle, m_current_url_id, mTheme, false), dataEnums.eTabCommands.M_UPDATE_PIXEL);
|
||||
}
|
||||
|
||||
public boolean isLoaded(){
|
||||
return mProgress>=100;
|
||||
}
|
||||
|
||||
/*History Delegate*/
|
||||
@Override
|
||||
public GeckoResult<Boolean> onVisited(@NonNull GeckoSession var1, @NonNull String var2, @Nullable String var3, int var4) {
|
||||
|
@ -360,16 +368,19 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
@UiThread
|
||||
public void onSessionStateChange(@NonNull GeckoSession session, @NonNull SessionState sessionState) {
|
||||
mSessionState = sessionState;
|
||||
if(!status.sRestoreTabs){
|
||||
mSessionState = null;
|
||||
}
|
||||
if(mSessionState!=null)
|
||||
// if(!status.sRestoreTabs){
|
||||
// mSessionState = null;
|
||||
// }
|
||||
// if(mSessionState!=null)
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme, mSessionState.toString()), enums.etype.M_UPDATE_SESSION_STATE);
|
||||
}
|
||||
|
||||
public void onRestoreState(){
|
||||
public boolean onRestoreState(){
|
||||
if(mSessionState!=null){
|
||||
restoreState(mSessionState);
|
||||
return true;
|
||||
}else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -379,6 +390,21 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
if(!mIsLoaded){
|
||||
return;
|
||||
}
|
||||
if(wasBackPressed && mHistoryList.get(mHistoryList.getCurrentIndex()-1).getUri().equals(var2)){
|
||||
if(var2.equals("https://boogle.store") || var2.startsWith(CONST_GENESIS_URL_CACHED) || var2.startsWith(CONST_GENESIS_URL_CACHED_DARK)){
|
||||
if(var2.startsWith(CONST_GENESIS_URL_CACHED_DARK) && (status.sTheme == enums.Theme.THEME_LIGHT || helperMethod.isDayMode(mContext.get()))){
|
||||
isPageLoading = false;
|
||||
//stop();
|
||||
event.invokeObserver(null, enums.etype.M_CHANGE_HOME_THEME);
|
||||
}
|
||||
else if(var2.startsWith(CONST_GENESIS_URL_CACHED) && (status.sTheme != enums.Theme.THEME_LIGHT && !helperMethod.isDayMode(mContext.get()))){
|
||||
isPageLoading = false;
|
||||
//stop();
|
||||
event.invokeObserver(null, enums.etype.M_CHANGE_HOME_THEME);
|
||||
}
|
||||
}
|
||||
}
|
||||
wasBackPressed = false;
|
||||
|
||||
String newUrl = Objects.requireNonNull(var2).split("#")[0];
|
||||
if(!mCurrentTitle.equals("loading")){
|
||||
|
@ -441,6 +467,7 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
}
|
||||
else if(var1.target==2){
|
||||
event.invokeObserver(Arrays.asList(var1.uri,mSessionID), enums.etype.open_new_tab);
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), enums.etype.ON_EXPAND_TOP_BAR);
|
||||
return GeckoResult.fromValue(AllowOrDeny.DENY);
|
||||
}
|
||||
else if(!var1.uri.equals("about:blank")){
|
||||
|
@ -452,14 +479,13 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
}else {
|
||||
setURL(constants.CONST_GENESIS_HELP_URL_CACHE_DARK);
|
||||
}
|
||||
}else{
|
||||
}else if(!var1.uri.startsWith("resource://android/assets/homepage/")){
|
||||
setURL(var1.uri);
|
||||
}
|
||||
|
||||
event.invokeObserver(Arrays.asList(var1.uri,mSessionID), enums.etype.start_proxy);
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID), enums.etype.search_update);
|
||||
checkApplicationRate();
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), enums.etype.ON_EXPAND_TOP_BAR);
|
||||
|
||||
/* Its Absence causes delay on first launch*/
|
||||
if(!mCurrentURL.contains("boogle.store")){
|
||||
|
@ -473,6 +499,17 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
}
|
||||
}
|
||||
|
||||
public void onUpdateBannerAdvert(){
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, false), enums.etype.M_ON_BANNER_UPDATE);
|
||||
}
|
||||
|
||||
public void onClose(){
|
||||
stop();
|
||||
mCurrentURL = mPrevURL;
|
||||
//mIsLoaded = false;
|
||||
//isPageLoading = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCanGoBack(@NonNull GeckoSession session, boolean var2)
|
||||
{
|
||||
|
@ -537,6 +574,8 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
}
|
||||
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, m_current_url_id, mTheme), enums.etype.M_UPDATE_PIXEL_BACKGROUND);
|
||||
event.invokeObserver(Arrays.asList(mCurrentURL,mSessionID,mCurrentTitle, mTheme), enums.etype.ON_EXPAND_TOP_BAR);
|
||||
mPrevURL = mCurrentURL;
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
@ -826,8 +865,8 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
}
|
||||
|
||||
public String getCurrentURL(){
|
||||
if(mCurrentURL.equals("resource://android/assets/Homepage/homepage.html")){
|
||||
setURL("https://boogle.store");
|
||||
if(mCurrentURL.equals("resource://android/assets/Homepage/homepage.html") || mCurrentURL.equals("resource://android/assets/Homepage/homepage-dark.html")){
|
||||
//setURL("https://boogle.store");
|
||||
}
|
||||
return mCurrentURL;
|
||||
}
|
||||
|
@ -940,30 +979,8 @@ public class geckoSession extends GeckoSession implements GeckoSession.MediaDele
|
|||
}
|
||||
|
||||
void goBackSession(){
|
||||
|
||||
wasBackPressed = true;
|
||||
goBack();
|
||||
/*
|
||||
if(mHistoryList!=null){
|
||||
stop();
|
||||
int index = mHistoryList.getCurrentIndex()-1;
|
||||
initURL(mHistoryList.get(index).getUri());
|
||||
if(mHistoryList.size()>index && index>0){
|
||||
event.invokeObserver(Arrays.asList(mHistoryList.get(index).getUri(), mSessionID), enums.etype.start_proxy);
|
||||
}
|
||||
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(this::goBack, 100);
|
||||
mProgress = 5;
|
||||
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.progress_update_forced);
|
||||
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.M_ADMOB_BANNER_RECHECK);
|
||||
}
|
||||
else {
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(this::goBack, 100);
|
||||
mProgress = 5;
|
||||
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.progress_update_forced);
|
||||
event.invokeObserver(Arrays.asList(5, mSessionID, mCurrentURL), enums.etype.M_ADMOB_BANNER_RECHECK);
|
||||
}*/
|
||||
}
|
||||
|
||||
void goForwardSession(){
|
||||
|
|
|
@ -64,6 +64,11 @@ public class hintAdapter extends RecyclerView.Adapter<hintAdapter.listViewHolder
|
|||
|
||||
public void onUpdateAdapter(ArrayList<historyRowModel> pHintList, String pSearch){
|
||||
mHintList = pHintList;
|
||||
if(mHintList.size()==1 && mHintList.get(0).getHeader().equals("about:blank")) {
|
||||
mHintList.clear();
|
||||
mHintList.add( new historyRowModel("Genesis Search", "genesis.onion",-1));
|
||||
}
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
package com.darkweb.genesissearchengine.appManager.homeManager.homeController;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.DownloadManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentCallbacks2;
|
||||
|
@ -14,7 +17,6 @@ import android.database.Cursor;
|
|||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.net.VpnService;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
|
@ -29,6 +31,7 @@ import android.view.View;
|
|||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.webkit.URLUtil;
|
||||
import android.widget.*;
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -44,6 +47,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.bookmarkManager.bookmarkController;
|
||||
import com.darkweb.genesissearchengine.constants.sql;
|
||||
import com.darkweb.genesissearchengine.databaseManager.databaseController;
|
||||
import com.darkweb.genesissearchengine.appManager.historyManager.historyController;
|
||||
import com.darkweb.genesissearchengine.appManager.historyManager.historyRowModel;
|
||||
|
@ -81,10 +85,11 @@ import com.google.android.gms.ads.AdView;
|
|||
import org.mozilla.geckoview.ContentBlocking;
|
||||
import org.mozilla.geckoview.GeckoResult;
|
||||
import org.mozilla.geckoview.GeckoSession;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.proxy.wrapper.LocaleHelper;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.LocaleHelper;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
@ -95,15 +100,18 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_HELP_URL_CACHE;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_HELP_URL_CACHE_DARK;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED;
|
||||
import static com.darkweb.genesissearchengine.constants.constants.CONST_GENESIS_URL_CACHED_DARK;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_CHANGED;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.GECKO_SCROLL_DOWN;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.M_INITIALIZE_TAB_LINK;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.M_INITIALIZE_TAB_SINGLE;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.M_NEW_LINK_IN_NEW_TAB;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.open_new_tab;
|
||||
import static com.darkweb.genesissearchengine.constants.enums.etype.reload;
|
||||
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManager.*;
|
||||
import static com.darkweb.genesissearchengine.pluginManager.pluginEnums.eMessageManagerCallbacks.M_RATE_APPLICATION;
|
||||
import static java.lang.Character.isLetter;
|
||||
|
@ -210,6 +218,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
initAdmob();
|
||||
initWidget();
|
||||
initSuggestionView(new ArrayList<>(), strings.GENERIC_EMPTY_STR);
|
||||
status.sSettingIsAppRunning = true;
|
||||
org.torproject.android.service.util.Prefs.setContext(activityContextManager.getInstance().getHomeController());
|
||||
}
|
||||
|
||||
|
||||
|
@ -218,7 +228,6 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
if(!status.sSettingIsAppStarted){
|
||||
if(mSplashScreen.getAlpha()==1 && mConnectButton.isEnabled()){
|
||||
onStartApplication(null);
|
||||
status.sWidgetResponse = enums.WidgetResponse.NONE;
|
||||
}
|
||||
}else {
|
||||
mHomeViewController.initSearchBarFocus(false, isKeyboardOpened);
|
||||
|
@ -236,7 +245,6 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
if(!status.sSettingIsAppStarted){
|
||||
if(mSplashScreen.getAlpha()==1 && mConnectButton.isEnabled()){
|
||||
onStartApplication(null);
|
||||
status.sWidgetResponse = enums.WidgetResponse.NONE;
|
||||
}
|
||||
}else {
|
||||
if(mSearchEngineBar.getVisibility() != View.VISIBLE){
|
||||
|
@ -328,7 +336,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
onLoadTab(model.getSession(),false,true);
|
||||
//onLoadURL(model.getSession().getCurrentURL());
|
||||
mGeckoClient.onReload(mGeckoView, this);
|
||||
//mGeckoClient.onReload(mGeckoView, this);
|
||||
}else {
|
||||
onNewIntent(getIntent());
|
||||
onOpenLinkNewTab(helperMethod.getDomainName(mHomeModel.getSearchEngine()));
|
||||
|
@ -465,7 +473,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
public boolean dispatchTouchEvent(MotionEvent event) {
|
||||
if(inSignatureArea(event)){
|
||||
try{
|
||||
mSwipeDirectionDetector.onTouchEvent(event);
|
||||
//mSwipeDirectionDetector.onTouchEvent(event);
|
||||
}catch (Exception ignored){ }
|
||||
}
|
||||
return super.dispatchTouchEvent(event);
|
||||
|
@ -558,6 +566,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
|
||||
public void onLoadURL(String url){
|
||||
status.sUIInteracted = true;
|
||||
if(mGeckoView.getSession()!=null && !mGeckoView.getSession().isOpen()){
|
||||
mGeckoView.getSession().open(mGeckoClient.getmRuntime());
|
||||
}
|
||||
|
@ -608,7 +617,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}catch (Exception ignored){}
|
||||
|
||||
if(pExpandAppBar){
|
||||
mHomeViewController.expandTopBar();
|
||||
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
|
||||
}
|
||||
|
||||
if(mGeckoClient.getSession().getCurrentURL().equals("about:blank") || mGeckoClient.getSession().getCurrentURL().contains("boogle.store") || mGeckoClient.wasPreviousErrorPage() || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED) || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_URL_CACHED_DARK) || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE) || mGeckoClient.getSession().getCurrentURL().startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)){
|
||||
|
@ -704,15 +713,18 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
pluginController.getInstance().onOrbotInvoke(null, pluginEnums.eOrbotManager.M_DESTROY);
|
||||
mBackSplash.setImageDrawable(null);
|
||||
mBackSplash.setBackground(null);
|
||||
if(!status.sSettingIsAppStarted){
|
||||
Intent intent = new Intent(getApplicationContext(), OrbotService.class);
|
||||
stopService(intent);
|
||||
}else {
|
||||
NotificationManagerCompat.from(this).cancelAll();
|
||||
}
|
||||
|
||||
if(!status.mThemeApplying){
|
||||
if(!status.sSettingIsAppStarted){
|
||||
Intent intent = new Intent(getApplicationContext(), OrbotService.class);
|
||||
stopService(intent);
|
||||
}else {
|
||||
NotificationManagerCompat.from(this).cancelAll();
|
||||
}
|
||||
}
|
||||
|
||||
KeyboardUtils.removeAllKeyboardToggleListeners();
|
||||
mGatewaySplash.setOnTouchListener(null);
|
||||
|
@ -755,6 +767,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
|
||||
mNewTab.setOnTouchListener((v, event) -> {
|
||||
if(event.getAction() == MotionEvent.ACTION_DOWN){
|
||||
mTopBarContainer.getLayoutTransition().setDuration(200);
|
||||
onOpenTabViewBoundary(null);
|
||||
mNewTab.setPressed(true);
|
||||
}
|
||||
|
@ -811,17 +824,19 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
|
||||
mGeckoView.setOnTouchListener((v, event) -> {
|
||||
mHomeViewController.onClearSelections(true);
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN)
|
||||
if (event.getAction() == MotionEvent.ACTION_DOWN){
|
||||
mGatewaySplash.setElevation(9);
|
||||
status.sUIInteracted = true;
|
||||
}
|
||||
else if (event.getAction() == MotionEvent.ACTION_UP){
|
||||
int[] location = new int[2];
|
||||
mTopLayout.getLocationOnScreen(location);
|
||||
int y = location[1];
|
||||
if(status.sFullScreenBrowsing){
|
||||
if(y<=-helperMethod.pxFromDp(6)){
|
||||
mAppBar.setExpanded(false,true);
|
||||
//mAppBar.setExpanded(false,true);
|
||||
}else {
|
||||
mAppBar.setExpanded(true,true);
|
||||
//mAppBar.setExpanded(true,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -910,6 +925,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mSearchbar.setEventHandler(new edittextManagerCallback());
|
||||
|
||||
mSearchbar.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
status.sUIInteracted = true;
|
||||
if(!hasFocus)
|
||||
{
|
||||
mSearchBarWasBackButtonPressed = true;
|
||||
|
@ -986,9 +1002,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
public void onSearchBarInvoked(View view){
|
||||
String url = ((EditText)view).getText().toString();
|
||||
String validated_url = mHomeModel.urlComplete(url, mHomeModel.getSearchEngine());
|
||||
if(validated_url!=null){
|
||||
url = validated_url;
|
||||
}
|
||||
url = validated_url;
|
||||
|
||||
mHomeViewController.onUpdateSearchBar(url,false,true, false);
|
||||
onLoadURL(url);
|
||||
}
|
||||
|
@ -999,13 +1014,15 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mVal = ((TextView)view.findViewById(R.id.pHeaderSingle)).getText().toString();
|
||||
}
|
||||
String pURL = mHomeModel.urlComplete(mVal, status.sSettingSearchStatus);
|
||||
if(pURL==null){
|
||||
pURL = mVal;
|
||||
}
|
||||
|
||||
mHomeViewController.onClearSelections(true);
|
||||
onLoadURL(pURL);
|
||||
mHomeViewController.onUpdateSearchBar(pURL,false,true, true);
|
||||
|
||||
String finalPURL = pURL;
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
onLoadURL(finalPURL);
|
||||
}, 250);
|
||||
}
|
||||
|
||||
public void onSuggestionMove(View view){
|
||||
|
@ -1169,12 +1186,16 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mHomeViewController.onNewTabAnimation(Arrays.asList(isKeyboardOpenedTemp, isKeyboardOpened), M_INITIALIZE_TAB_SINGLE);
|
||||
}
|
||||
|
||||
public String completeURL(String pURL){
|
||||
return mHomeModel.urlComplete(pURL, mHomeModel.getSearchEngine());
|
||||
}
|
||||
|
||||
public void onOpenLinkNewTab(String url){
|
||||
mNewTab.setPressed(true);
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
onGetThumbnail(null, false);
|
||||
mHomeViewController.expandTopBar();
|
||||
mHomeViewController.expandTopBar(false,mGeckoView.getMaxY());
|
||||
if(status.sSettingSearchStatus.startsWith("https://boogle.store") || !status.sOpenURLInNewTab){
|
||||
mHomeViewController.updateBannerAdvertStatus(false, (boolean)pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED));
|
||||
}
|
||||
|
@ -1182,11 +1203,16 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}, 100);
|
||||
}
|
||||
|
||||
public void onClearSelectionTab(){
|
||||
mNewTab.setPressed(false);
|
||||
}
|
||||
|
||||
public void onOpenTabViewBoundary(View view){
|
||||
onInvokePixelGenerator();
|
||||
if(mScrollHandler!=null){
|
||||
mScrollHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
onInvokePixelGenerator();
|
||||
mNewTab.setPressed(true);
|
||||
onOpenTabReady();
|
||||
}
|
||||
|
@ -1218,7 +1244,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
initLocalLanguage();
|
||||
|
||||
helperMethod.hideKeyboard(this);
|
||||
mHomeViewController.onOpenMenu(view,mGeckoClient.canGoForward(),!(mProgressBar.getAlpha()<=0 || mProgressBar.getVisibility() ==View.INVISIBLE),mGeckoClient.getUserAgent(), mGeckoClient.getSession().getCurrentURL());
|
||||
mHomeViewController.onOpenMenu(view,mGeckoClient.canGoForward(),!(mProgressBar.getAlpha()<=0 || mProgressBar.getVisibility() == View.INVISIBLE || mGeckoClient.isLoaded()),mGeckoClient.getUserAgent(), mGeckoClient.getSession().getCurrentURL());
|
||||
|
||||
view.setClickable(false);
|
||||
new Handler().postDelayed(() ->
|
||||
|
@ -1271,14 +1297,18 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
else if(!mSearchBarWasBackButtonPressed){
|
||||
int mTabSize = (int)dataController.getInstance().invokeTab(dataEnums.eTabCommands.GET_TOTAL_TAB, null);
|
||||
mGeckoClient.onBackPressed(true, mTabSize);
|
||||
mGeckoClient.onBackPressed(true, mTabSize, mGeckoView, this);
|
||||
}
|
||||
}
|
||||
|
||||
/*Activity States*/
|
||||
|
||||
public NestedGeckoView getGeckoView(){
|
||||
return mGeckoView;
|
||||
}
|
||||
|
||||
public void onReload(View view){
|
||||
mHomeViewController.onUpdateLogo();
|
||||
onLoadURL(mSearchbar.getText().toString());
|
||||
}
|
||||
|
||||
public void onClearSession(){
|
||||
|
@ -1337,7 +1367,12 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
pluginController.getInstance().onLanguageInvoke(Collections.singletonList(this), pluginEnums.eLangManager.M_RESUME);
|
||||
mHomeViewController.onClearSelections(true);
|
||||
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, true);
|
||||
|
||||
mHomeViewController.initTopBarPadding();
|
||||
mHomeViewController.onSetBannerAdMargin(!mGeckoClient.isLoading(),(boolean)pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED)&&!!mGeckoClient.isLoading());
|
||||
|
||||
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
|
||||
status.sUIInteracted = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1362,6 +1397,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
pluginController.getInstance().onMessageManagerInvoke(null, M_RESET);
|
||||
pluginController.getInstance().onNotificationInvoke(Collections.singletonList(1296000000) , pluginEnums.eNotificationManager.M_CREATE_NOTIFICATION);
|
||||
mSearchBarWasBackButtonPressed = false;
|
||||
status.sUIInteracted = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1403,7 +1439,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
|
||||
if(mAppBar!=null){
|
||||
mHomeViewController.expandTopBar();
|
||||
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
|
||||
|
||||
mAppBar.refreshDrawableState();
|
||||
mAppBar.invalidate();
|
||||
|
@ -1473,7 +1509,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
|
||||
if(mAppBar!=null){
|
||||
mHomeViewController.expandTopBar();
|
||||
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
|
||||
|
||||
mAppBar.refreshDrawableState();
|
||||
mAppBar.invalidate();
|
||||
|
@ -1512,7 +1548,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
|
||||
public void onVoiceClick(View view) {
|
||||
if(status.sSettingEnableVoiceInput){
|
||||
if(status.sSettingEnableVoiceInput || status.sWidgetResponse == enums.WidgetResponse.VOICE){
|
||||
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
|
||||
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
|
||||
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
|
||||
|
@ -1523,7 +1559,11 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
|
||||
}
|
||||
}else {
|
||||
mHomeViewController.onClearSelections(true);
|
||||
mSearchbar.clearFocus();
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, false);
|
||||
}, 170);
|
||||
}
|
||||
}
|
||||
/*-------------------------------------------------------External Callback Methods-------------------------------------------------------*/
|
||||
|
@ -1706,20 +1746,25 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
}
|
||||
else if (menuId == R.id.pMenuQuit)
|
||||
{
|
||||
status.sSettingIsAppStarted = false;
|
||||
finishAndRemoveTask();
|
||||
pluginController.getInstance().onOrbotInvoke(null, pluginEnums.eOrbotManager.M_DESTROY);
|
||||
|
||||
new Thread(){
|
||||
public void run(){
|
||||
try {
|
||||
sleep(1000);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
status.sSettingIsAppStarted = false;
|
||||
finishAndRemoveTask();
|
||||
|
||||
new Thread(){
|
||||
public void run(){
|
||||
try {
|
||||
sleep(1000);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}.start();
|
||||
}, 100);
|
||||
}
|
||||
else if (menuId == R.id.pMenuFind)
|
||||
{
|
||||
|
@ -1727,8 +1772,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
mHomeViewController.onUpdateFindBar(true);
|
||||
}
|
||||
if (menuId == R.id.menu20) {
|
||||
mGeckoClient.onClose();
|
||||
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, true);
|
||||
helperMethod.hideKeyboard(this);
|
||||
mGeckoClient.onStop();
|
||||
}
|
||||
if (menuId == R.id.menu21) {
|
||||
helperMethod.hideKeyboard(this);
|
||||
|
@ -1815,6 +1861,8 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_HISTORY_CLEAR,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_GATEWAY,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_GATEWAY_MANUAL,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_IS_WELCOME_ENABLED,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.PROXY_IS_APP_RATED,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.VPN_ENABLED,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.BRIDGE_ENABLES,false));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_FONT_ADJUSTABLE,true));
|
||||
|
@ -1839,22 +1887,40 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_LIST_VIEW,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SHOW_TAB_GRID,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_OPEN_URL_IN_NEW_TAB,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_POPUP,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_STRING, Arrays.asList(keys.BRIDGE_CUSTOM_TYPE,strings.BRIDGE_CUSTOM_BRIDGE_OBFS4));
|
||||
|
||||
|
||||
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_CLEAR_TAB, null);
|
||||
databaseController.getInstance().execSQL(sql.SQL_CLEAR_HISTORY,null);
|
||||
dataController.getInstance().invokeHistory(dataEnums.eHistoryCommands.M_CLEAR_HISTORY ,null);
|
||||
activityContextManager.getInstance().getHomeController().onClearCache();
|
||||
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_CLEAR_TAB, null);
|
||||
activityContextManager.getInstance().getHomeController().onClearSiteData();
|
||||
activityContextManager.getInstance().getHomeController().onClearSession();
|
||||
activityContextManager.getInstance().getHomeController().onClearCookies();
|
||||
onClearSettings();
|
||||
status.initStatus(activityContextManager.getInstance().getHomeController());
|
||||
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_CLEAR_TAB, null);
|
||||
activityContextManager.getInstance().getHomeController().initRuntimeSettings();
|
||||
pluginController.getInstance().onMessageManagerInvoke(Collections.singletonList(this), M_DATA_CLEARED);
|
||||
activityContextManager.getInstance().getHomeController().onClearSettings();
|
||||
|
||||
|
||||
status.sSettingIsAppStarted = false;
|
||||
finishAndRemoveTask();
|
||||
|
||||
new Thread(){
|
||||
public void run(){
|
||||
try {
|
||||
sleep(1000);
|
||||
android.os.Process.killProcess(android.os.Process.myPid());
|
||||
System.exit(1);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
Intent intent = new Intent(this, homeController.class);
|
||||
intent.addFlags(FLAG_ACTIVITY_NEW_TASK);
|
||||
this.startActivity(intent);
|
||||
overridePendingTransition(R.anim.popup_anim_in, R.anim.popup_anim_out);
|
||||
if (this
|
||||
instanceof Activity) {
|
||||
((Activity) this).finish();
|
||||
}
|
||||
|
||||
Runtime.getRuntime().exit(0);
|
||||
|
||||
}
|
||||
|
||||
public class nestedGeckoViewCallback implements eventObserver.eventListener{
|
||||
|
@ -1862,9 +1928,24 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
@Override
|
||||
public Object invokeObserver(List<Object> data, Object e_type)
|
||||
{
|
||||
if(e_type.equals(GECKO_SCROLL_CHANGED)){
|
||||
mHomeViewController.onMoveTopBar((int)data.get(0));
|
||||
onInvokePixelGenerator();
|
||||
if(status.sFullScreenBrowsing){
|
||||
if(e_type.equals(GECKO_SCROLL_DOWN)){
|
||||
mTopBarContainer.getLayoutTransition().setDuration(0);
|
||||
mHomeViewController.onClearSelections(isKeyboardOpened);
|
||||
mSearchbar.clearFocus();
|
||||
}
|
||||
else {
|
||||
int[] locatiosn = new int[2];
|
||||
mSearchbar.getLocationOnScreen(locatiosn);
|
||||
int ys = locatiosn[1];
|
||||
if(ys!=0){
|
||||
if(ys<=50){
|
||||
mHomeViewController.shrinkTopBar(true, mGeckoView.getMaxY());
|
||||
}else {
|
||||
mHomeViewController.expandTopBar(true, mGeckoView.getMaxY());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -1929,11 +2010,23 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
{
|
||||
mHomeViewController.onSetBannerAdMargin((boolean)data.get(0),(boolean)pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED));
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_SPLASH_DISABLE))
|
||||
{
|
||||
initWidget();
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_WELCOME_MESSAGE)){
|
||||
if(status.sSettingIsWelcomeEnabled){
|
||||
final Handler handler = new Handler();
|
||||
Runnable runnable = () -> pluginController.getInstance().onMessageManagerInvoke(Arrays.asList(strings.GENERIC_EMPTY_STR, homeController.this), M_WELCOME);
|
||||
handler.postDelayed(runnable, 1300);
|
||||
Runnable runnable = () -> {
|
||||
if(!status.sUIInteracted){
|
||||
mHomeViewController.closeMenu();
|
||||
mHomeViewController.onUpdateSearchBar(mGeckoClient.getSession().getCurrentURL(),false,true, true);
|
||||
mSearchbar.clearFocus();
|
||||
pluginController.getInstance().onMessageManagerInvoke(Arrays.asList(strings.GENERIC_EMPTY_STR, homeController.this), M_WELCOME);
|
||||
status.sUIInteracted = true;
|
||||
}
|
||||
};
|
||||
handler.postDelayed(runnable, 2500);
|
||||
}
|
||||
}
|
||||
else if(e_type.equals(enums.etype.on_url_load)){
|
||||
|
@ -2091,7 +2184,7 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
{
|
||||
|
||||
if(e_type.equals(enums.etype.ON_EXPAND_TOP_BAR)){
|
||||
mHomeViewController.expandTopBar();
|
||||
mHomeViewController.expandTopBar(false, mGeckoView.getMaxY());
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_ON_BANNER_UPDATE)){
|
||||
Object mAdvertResponse = pluginController.getInstance().onAdsInvoke(null, pluginEnums.eAdManager.M_IS_ADVERT_LOADED);
|
||||
|
@ -2203,6 +2296,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
if(activityContextManager.getInstance().getTabController()!=null && mTabFragment.getVisibility()==View.VISIBLE)
|
||||
activityContextManager.getInstance().getTabController().onTabRowChanged((String) data.get(1));
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_RELOAD)){
|
||||
onReload(null);
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_UPDATE_SESSION_STATE)){
|
||||
dataController.getInstance().invokeTab(dataEnums.eTabCommands.M_UPDATE_SESSION_STATE, data);
|
||||
}
|
||||
|
@ -2222,6 +2318,9 @@ public class homeController extends AppCompatActivity implements ComponentCallba
|
|||
else if(e_type.equals(enums.etype.M_UPDATE_PIXEL_BACKGROUND)){
|
||||
onInvokePixelGenerator();
|
||||
}
|
||||
else if(e_type.equals(enums.etype.M_INIT_PADDING)){
|
||||
mHomeViewController.initTopBarPadding();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ class homeModel
|
|||
boolean isUrlValid = Patterns.WEB_URL.matcher(updateUrl).matches();
|
||||
if(isUrlValid && host.getHost().replace("www.","").contains("."))
|
||||
{
|
||||
return null;
|
||||
return pURL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.graphics.drawable.GradientDrawable;
|
|||
import android.graphics.drawable.InsetDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.text.method.MovementMethod;
|
||||
|
@ -49,7 +50,7 @@ import com.example.myapplication.R;
|
|||
import com.google.android.gms.ads.AdView;
|
||||
import com.google.android.material.appbar.AppBarLayout;
|
||||
import org.mozilla.geckoview.GeckoView;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -118,6 +119,7 @@ class homeViewController
|
|||
private MovementMethod mSearchBarMovementMethod = null;
|
||||
private Handler mTabDialogHandler = null;
|
||||
private Runnable mTabDialogRunnable = null;
|
||||
private boolean mIsTopBarExpanded = true;
|
||||
|
||||
void initialization(eventObserver.eventListener event, AppCompatActivity context, Button mNewTab, ConstraintLayout webviewContainer, TextView loadingText, AnimatedProgressBar progressBar, editTextManager searchbar, ConstraintLayout splashScreen, ImageView loading, AdView banner_ads, ImageButton gateway_splash, LinearLayout top_bar, GeckoView gecko_view, ImageView backsplash, Button connect_button, View pFindBar, EditText pFindText, TextView pFindCount, androidx.constraintlayout.widget.ConstraintLayout pTopLayout, ImageButton pVoiceInput, ImageButton pMenu, androidx.core.widget.NestedScrollView pNestedScroll, ImageView pBlocker, ImageView pBlockerFullSceen, View mSearchEngineBar, TextView pCopyright, RecyclerView pHistListView, com.google.android.material.appbar.AppBarLayout pAppBar, ImageButton pOrbotLogManager, ConstraintLayout pInfoLandscape, ConstraintLayout pInfoPortrait, ProgressBar pProgressBarIndeterminate, FragmentContainerView pTabFragment, LinearLayout pTopBarContainer, ImageView pSearchLock, View pPopupLoadNewTab, ImageView pTopBarHider, ImageView pNewTabBlocker, CoordinatorLayout mCoordinatorLayout, ImageView pImageDivider, ImageButton pPanicButton, ImageView pGenesisLogo,ImageButton pPanicButtonLandscape){
|
||||
this.mContext = context;
|
||||
|
@ -179,13 +181,10 @@ class homeViewController
|
|||
mTopBarContainer.getLayoutTransition().setDuration(200);
|
||||
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(() ->
|
||||
{
|
||||
mContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
|
||||
}, 1500);
|
||||
handler.postDelayed(() -> mContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER), 1500);
|
||||
|
||||
updateBannerAdvertStatus(false, false);
|
||||
expandTopBar();
|
||||
expandTopBar(false, 2000);
|
||||
mBlockerFullSceen.setVisibility(View.GONE);
|
||||
mNewTab.setPressed(true);
|
||||
mNewTab.setPressed(false);
|
||||
|
@ -194,6 +193,7 @@ class homeViewController
|
|||
View child = mAppBar.getChildAt(0);
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
|
||||
params.setScrollFlags(1);
|
||||
mIsTopBarExpanded = false;
|
||||
mAppBar.setExpanded(true,false);
|
||||
mAppBar.refreshDrawableState();
|
||||
mAppBar.invalidate();
|
||||
|
@ -274,7 +274,7 @@ class homeViewController
|
|||
mPopupLoadNewTab.animate().cancel();
|
||||
mPopupLoadNewTab.setAlpha(0);
|
||||
mPopupLoadNewTab.setVisibility(View.VISIBLE);
|
||||
mPopupLoadNewTab.animate().setDuration(350).alpha(1);
|
||||
mPopupLoadNewTab.animate().setStartDelay(400).setDuration(250).alpha(1);
|
||||
|
||||
if(mTabDialogHandler!=null){
|
||||
mTabDialogHandler.removeCallbacksAndMessages(null);
|
||||
|
@ -282,14 +282,14 @@ class homeViewController
|
|||
|
||||
mTabDialogHandler = new Handler();
|
||||
mTabDialogRunnable = this::onHideLoadTabDialog;
|
||||
mTabDialogHandler.postDelayed(mTabDialogRunnable, 7500);
|
||||
mTabDialogHandler.postDelayed(mTabDialogRunnable, 3500);
|
||||
}
|
||||
|
||||
public void onHideLoadTabDialog() {
|
||||
mPopupLoadNewTab.findViewById(R.id.pBlockerUndo).setVisibility(View.VISIBLE);
|
||||
mPopupLoadNewTab.animate().cancel();
|
||||
|
||||
mPopupLoadNewTab.animate().setDuration(350).alpha(0).withEndAction(() -> {
|
||||
mPopupLoadNewTab.animate().setDuration(250).alpha(0).withEndAction(() -> {
|
||||
mPopupLoadNewTab.setVisibility(View.GONE);
|
||||
});
|
||||
}
|
||||
|
@ -495,13 +495,13 @@ class homeViewController
|
|||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
animatedColor oneToTwo = new animatedColor(ContextCompat.getColor(mContext, R.color.landing_ease_blue), ContextCompat.getColor(mContext, R.color.green_dark_v2));
|
||||
|
||||
int mDelay = 800;
|
||||
int mDelay = 1150;
|
||||
if(status.mThemeApplying || mInstant){
|
||||
mDelay = 0;
|
||||
}
|
||||
|
||||
ValueAnimator animator = ObjectAnimator.ofFloat(0f, 1f);
|
||||
animator.setDuration(300).setStartDelay(mDelay);
|
||||
animator.setDuration(250).setStartDelay(mDelay);
|
||||
animator.addUpdateListener(animation ->
|
||||
{
|
||||
float v = (float) animation.getAnimatedValue();
|
||||
|
@ -647,29 +647,30 @@ class homeViewController
|
|||
if(mSplashScreen.getAlpha()==1){
|
||||
if(!mIsAnimating){
|
||||
mIsAnimating = true;
|
||||
triggerPostUI();
|
||||
triggerPostUI(2000);
|
||||
mProgressBar.setVisibility(View.GONE);
|
||||
mSplashScreen.animate().cancel();
|
||||
onClearSelections(false);
|
||||
mGeckoView.requestFocus();
|
||||
mProgressBarIndeterminate.animate().setStartDelay(300).setDuration(250).alpha(0).withEndAction(() -> mSplashScreen.animate().setDuration(350).setStartDelay(200).alpha(0).withEndAction(() -> {
|
||||
mProgressBarIndeterminate.setVisibility(View.GONE);
|
||||
mSplashScreen.setClickable(false);
|
||||
mSplashScreen.setFocusable(false);
|
||||
mProgressBarIndeterminate.setVisibility(View.GONE);
|
||||
mSearchbar.setEnabled(true);
|
||||
mBlocker.setEnabled(false);
|
||||
mProgressBarIndeterminate.animate().cancel();
|
||||
mProgressBarIndeterminate.animate().setStartDelay(750).setDuration(250).alpha(0).withEndAction(() -> {
|
||||
mSplashScreen.animate().setDuration(250).setStartDelay(100).alpha(0).withEndAction(() -> {
|
||||
mProgressBarIndeterminate.setVisibility(View.GONE);
|
||||
mSplashScreen.setClickable(false);
|
||||
mSplashScreen.setFocusable(false);
|
||||
mSearchbar.setEnabled(true);
|
||||
mBlocker.setEnabled(false);
|
||||
|
||||
mProgressBarIndeterminate.setVisibility(View.GONE);
|
||||
mBlocker.setVisibility(View.GONE);
|
||||
mGatewaySplash.setVisibility(View.GONE);
|
||||
mConnectButton.setVisibility(View.GONE);
|
||||
mPanicButton.setVisibility(View.GONE);
|
||||
mPanicButtonLandscape.setVisibility(View.GONE);
|
||||
mBlocker.setVisibility(View.GONE);
|
||||
mGatewaySplash.setVisibility(View.GONE);
|
||||
mConnectButton.setVisibility(View.GONE);
|
||||
mPanicButton.setVisibility(View.GONE);
|
||||
mPanicButtonLandscape.setVisibility(View.GONE);
|
||||
|
||||
mEvent.invokeObserver(null, enums.etype.M_CACHE_UPDATE_TAB);
|
||||
mEvent.invokeObserver(null, enums.etype.M_SPLASH_DISABLE);
|
||||
}));
|
||||
mEvent.invokeObserver(null, enums.etype.M_CACHE_UPDATE_TAB);
|
||||
mEvent.invokeObserver(null, enums.etype.M_SPLASH_DISABLE);
|
||||
});
|
||||
});
|
||||
mEvent.invokeObserver(null, enums.etype.M_WELCOME_MESSAGE);
|
||||
mOrbotLogManager.setClickable(false);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
|
@ -684,18 +685,79 @@ class homeViewController
|
|||
mContext.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_USER);
|
||||
}
|
||||
|
||||
private void triggerPostUI(){
|
||||
expandTopBar();
|
||||
private void triggerPostUI(int pOffsetY){
|
||||
expandTopBar(false, pOffsetY);
|
||||
if(mProgressBar.getProgress()>0 && mProgressBar.getProgress()<10000){
|
||||
mProgressBar.animate().setStartDelay(0).alpha(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void expandTopBar(){
|
||||
Object mTag = mAppBar.getTag(R.id.expandableBar);
|
||||
if(mTag!=null && (boolean) mTag){
|
||||
public void disableExpand(){
|
||||
|
||||
View child = mAppBar.getChildAt(0);
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
|
||||
params.setScrollFlags(0);
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
private void enableCollapsing() {
|
||||
View child = mAppBar.getChildAt(0);
|
||||
AppBarLayout.LayoutParams params = (AppBarLayout.LayoutParams) child.getLayoutParams();
|
||||
params.setScrollFlags(1);
|
||||
}
|
||||
public void expandTopBar(boolean pForced, int pOffsetY){
|
||||
|
||||
if(pOffsetY == -1){
|
||||
mAppBar.setExpanded(true,true);
|
||||
disableExpand();
|
||||
}else {
|
||||
enableCollapsing();
|
||||
}
|
||||
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mTopBarContainer.getLayoutTransition().setDuration(200);
|
||||
Object mTag = mAppBar.getTag(R.id.expandableBar);
|
||||
if(mIsTopBarExpanded && !pForced){
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if(mTag!=null && (boolean) mTag){
|
||||
mAppBar.setExpanded(true,true);
|
||||
mIsTopBarExpanded = true;
|
||||
Log.i("wwwwww1","wwwwww");
|
||||
}
|
||||
}, 100);
|
||||
|
||||
}
|
||||
|
||||
public void shrinkTopBar(boolean pForced, int pOffsetY){
|
||||
|
||||
if(pOffsetY == -1){
|
||||
mAppBar.setExpanded(true,true);
|
||||
disableExpand();
|
||||
}else {
|
||||
enableCollapsing();
|
||||
}
|
||||
|
||||
mTopBarContainer.getLayoutTransition().setDuration(0);
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
mTopBarContainer.getLayoutTransition().setDuration(200);
|
||||
Object mTag = mAppBar.getTag(R.id.expandableBar);
|
||||
|
||||
if(!mIsTopBarExpanded && !pForced){
|
||||
return;
|
||||
}
|
||||
|
||||
if(mTag!=null && (boolean) mTag){
|
||||
mIsTopBarExpanded = false;
|
||||
mAppBar.setExpanded(false,true);
|
||||
Log.i("wwwwww2","wwwwww");
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------Helper Methods-------------------------------------------------------*/
|
||||
|
@ -867,15 +929,8 @@ class homeViewController
|
|||
mSearchbar.setTag(R.id.msearchbarProcessing,true);
|
||||
url = CONST_GENESIS_DOMAIN_URL;
|
||||
}
|
||||
else if(url.startsWith(CONST_GENESIS_HELP_URL_CACHE) || url.startsWith(CONST_GENESIS_HELP_URL_CACHE_DARK)){
|
||||
mSearchbar.setTag(R.id.msearchbarProcessing,true);
|
||||
url = CONST_GENESIS_HELP_URL;
|
||||
}
|
||||
else if(helperMethod.getHost(helperMethod.completeURL(url)).contains("genesis") || helperMethod.getHost(helperMethod.completeURL(url)).contains("boogle")){
|
||||
mSearchbar.setTag(R.id.msearchbarProcessing,true);
|
||||
}else {
|
||||
mSearchbar.setTag(R.id.msearchbarProcessing,false);
|
||||
}
|
||||
|
||||
|
||||
Log.i("FUCK::5",url);
|
||||
if(!mSearchbar.hasFocus() || pClearText || pBypassFocus){
|
||||
if(mSearchEngineBar.getVisibility() == View.GONE || pBypassFocus){
|
||||
|
@ -1010,7 +1065,7 @@ class homeViewController
|
|||
|
||||
mNewTab.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v1));
|
||||
mMenu.setColorFilter(ContextCompat.getColor(mContext, R.color.c_navigation_tint));
|
||||
mVoiceInput.setColorFilter(ContextCompat.getColor(mContext, R.color.c_navigation_tint));
|
||||
mVoiceInput.setColorFilter(ContextCompat.getColor(mContext, R.color.c_text_v8));
|
||||
mSearchbar.setTextColor(ContextCompat.getColor(mContext, R.color.c_text_v1));
|
||||
mSearchbar.setHintTextColor(ContextCompat.getColor(mContext, R.color.c_text_v2));
|
||||
|
||||
|
@ -1352,6 +1407,8 @@ class homeViewController
|
|||
this.mBlockerFullSceen.animate().setStartDelay(0).setDuration(200).alpha(0).withEndAction(() -> mBlockerFullSceen.setVisibility(View.GONE));
|
||||
mContext.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
initTopBarPadding();
|
||||
|
||||
mIsTopBarExpanded = false;
|
||||
mAppBar.setExpanded(true,false);
|
||||
mAppBar.refreshDrawableState();
|
||||
mAppBar.invalidate();
|
||||
|
|
|
@ -15,7 +15,7 @@ import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
|||
import com.darkweb.genesissearchengine.appManager.tabManager.tabEnums;
|
||||
import com.darkweb.genesissearchengine.helperManager.eventObserver;
|
||||
import com.example.myapplication.R;
|
||||
import org.torproject.android.proxy.wrapper.logRowModel;
|
||||
import org.torproject.android.service.wrapper.logRowModel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ import com.darkweb.genesissearchengine.pluginManager.pluginController;
|
|||
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
||||
import com.example.myapplication.R;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ package com.darkweb.genesissearchengine.appManager.orbotLogManager;
|
|||
|
||||
import com.darkweb.genesissearchengine.constants.constants;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
import org.torproject.android.proxy.wrapper.logRowModel;
|
||||
import org.torproject.android.service.wrapper.logRowModel;
|
||||
import java.util.ArrayList;
|
||||
|
||||
class orbotLogModel
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.darkweb.genesissearchengine.appManager.settingManager.accessibilityM
|
|||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
@ -171,6 +172,12 @@ public class settingAccessibilityController extends AppCompatActivity {
|
|||
mSettingAccessibilityModel.onTrigger(settingAccessibilityEnums.eAccessibilityViewController.M_ZOOM_SETTING, Collections.singletonList(!mZoom.isChecked()));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_ZOOM,status.sSettingEnableZoom));
|
||||
mZoom.toggle();
|
||||
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
activityContextManager.getInstance().getHomeController().onReload(null);
|
||||
}, 300);
|
||||
|
||||
}
|
||||
|
||||
public void onVoiceInputSettingUpdate(View view){
|
||||
|
|
|
@ -8,8 +8,10 @@ import android.widget.CheckBox;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.app.AppCompatDelegate;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.settingManager.generalManager.settingGeneralController;
|
||||
import com.darkweb.genesissearchengine.databaseManager.databaseController;
|
||||
import com.darkweb.genesissearchengine.appManager.helpManager.helpController;
|
||||
import com.darkweb.genesissearchengine.constants.constants;
|
||||
|
@ -160,9 +162,25 @@ public class settingClearController extends AppCompatActivity {
|
|||
if(mHomeInvoked){
|
||||
activityContextManager.getInstance().getHomeController().onClearSettings();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private void onClearSettings(){
|
||||
|
||||
boolean mIsThemeChangable = false;
|
||||
if(!status.sDefaultNightMode){
|
||||
if(AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_NO){
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||
mIsThemeChangable = true;
|
||||
}
|
||||
}else {
|
||||
if(AppCompatDelegate.getDefaultNightMode() != AppCompatDelegate.MODE_NIGHT_YES){
|
||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
||||
mIsThemeChangable = true;
|
||||
}
|
||||
}
|
||||
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SEARCH_HISTORY,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_SEARCH_SUGGESTION,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_JAVA_SCRIPT,true));
|
||||
|
@ -197,6 +215,15 @@ public class settingClearController extends AppCompatActivity {
|
|||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_OPEN_URL_IN_NEW_TAB,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_BOOL, Arrays.asList(keys.SETTING_POPUP,true));
|
||||
dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_SET_STRING, Arrays.asList(keys.BRIDGE_CUSTOM_TYPE,strings.BRIDGE_CUSTOM_BRIDGE_OBFS4));
|
||||
|
||||
if(mIsThemeChangable) {
|
||||
status.mThemeApplying = true;
|
||||
onBackPressed();
|
||||
overridePendingTransition(R.anim.fade_in_lang, R.anim.fade_out_lang);
|
||||
activityContextManager.getInstance().getHomeController().onReInitTheme();
|
||||
activityContextManager.getInstance().getSettingController().onReInitTheme();
|
||||
helperMethod.openActivity(settingClearController.class, constants.CONST_LIST_HISTORY, settingClearController.this, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* LOCAL OVERRIDES */
|
||||
|
|
|
@ -356,7 +356,9 @@ public class tabController extends Fragment
|
|||
onClearSelection(null);
|
||||
}
|
||||
initTabCount(400);
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
new Handler().postDelayed(() -> {
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
}, 500);
|
||||
mTabAdapter.onTrigger(tabEnums.eTabAdapterCommands.INIT_FIRST_ROW, null);
|
||||
onSwipeBounce(0);
|
||||
}
|
||||
|
@ -375,19 +377,19 @@ public class tabController extends Fragment
|
|||
mTabAdapter.notifyDataSetChanged();
|
||||
onClearSelection(null);
|
||||
});
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
new Handler().postDelayed(() -> {
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
onSwipeBounce(0);
|
||||
}, 400);
|
||||
}, 500);
|
||||
return true;
|
||||
}else{
|
||||
onShowUndoDialog();
|
||||
mTabAdapter.notifyItemRangeChanged(pIndex, mTabAdapter.getItemCount() - pIndex);
|
||||
mTabAdapter.notifyItemChanged(0);
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
new Handler().postDelayed(() -> {
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
onSwipeBounce(0);
|
||||
}, 400);
|
||||
}, 500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -435,7 +437,10 @@ public class tabController extends Fragment
|
|||
mtabViewController.onTrigger(tabEnums.eTabViewCommands.ON_HIDE_UNDO_DIALOG, null);
|
||||
mTabAdapter.onTrigger(tabEnums.eTabAdapterCommands.REINIT_DATA, Collections.singletonList(mBackup));
|
||||
}
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
|
||||
new Handler().postDelayed(() -> {
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
}, 500);
|
||||
|
||||
}, 100);
|
||||
}
|
||||
|
@ -498,7 +503,9 @@ public class tabController extends Fragment
|
|||
|
||||
mtabViewController.onTrigger(tabEnums.eTabViewCommands.ON_SHOW_SELECTION_MENU, Arrays.asList(false,0));
|
||||
mtabViewController.onTrigger(tabEnums.eTabViewCommands.ON_HIDE_SELECTION, null);
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
new Handler().postDelayed(() -> {
|
||||
activityContextManager.getInstance().getHomeController().onLoadTabFromTabController();
|
||||
}, 500);
|
||||
|
||||
// mTabAdapter.notifyDataSetChanged();
|
||||
initTabCount(400);
|
||||
|
|
|
@ -4,7 +4,7 @@ public class enums
|
|||
{
|
||||
/*Settings Manager*/
|
||||
public enum etype{
|
||||
on_update_favicon,ON_UPDATE_TAB_TITLE, ON_OPEN_TAB_VIEW,ON_NEW_TAB_ANIMATION, M_UPDATE_SESSION_STATE,ON_LOAD_REQUEST,GECKO_SCROLL_CHANGED,ON_UPDATE_SEARCH_BAR,M_ON_MAIL,SESSION_ID,M_UPDATE_PIXEL_BACKGROUND,M_CACHE_UPDATE_TAB,
|
||||
M_CHANGE_HOME_THEME, on_update_favicon,M_RELOAD,ON_UPDATE_TAB_TITLE, ON_OPEN_TAB_VIEW,ON_NEW_TAB_ANIMATION, M_UPDATE_SESSION_STATE,ON_LOAD_REQUEST, GECKO_SCROLL_UP, GECKO_SCROLL_UP_ALWAYS, GECKO_SCROLL_DOWN, GECKO_SCROLL_DOWN_CALLER,ON_UPDATE_SEARCH_BAR,M_ON_MAIL,SESSION_ID,M_UPDATE_PIXEL_BACKGROUND, M_INIT_PADDING,M_CACHE_UPDATE_TAB,
|
||||
on_verify_selected_url_menu,FINDER_RESULT_CALLBACK,M_ADMOB_BANNER_RECHECK,M_OPEN_SESSION,M_DOWNLOAD_FAILURE,
|
||||
welcome, reload,download_folder, M_UPDATE_THEME,M_ON_BANNER_UPDATE, M_LOAD_HOMEPAGE_GENESIS,M_INIT_TAB_COUNT_FORCED,M_SPLASH_DISABLE,M_NEW_LINK_IN_NEW_TAB,M_RESET_SUGGESTION,
|
||||
url_triggered, url_triggered_new_tab,url_clear,fetch_favicon,url_clear_at,remove_from_database,is_empty,M_HOME_PAGE,M_PRELOAD_URL,ON_KEYBOARD_CLOSE,M_CLOSE_TAB,
|
||||
|
|
|
@ -33,6 +33,7 @@ public class status
|
|||
public static String sExternalWebsite = strings.GENERIC_EMPTY_STR;
|
||||
public static String sBridgesDefault = strings.BRIDGES_DEFAULT;
|
||||
|
||||
public static boolean sUIInteracted = false;
|
||||
public static boolean sSettingEnableZoom = true;
|
||||
public static boolean sSettingEnableVoiceInput = true;
|
||||
public static boolean sSettingSearchHistory = false;
|
||||
|
@ -43,6 +44,7 @@ public class status
|
|||
public static boolean sSettingIsAppPaused = false;
|
||||
public static boolean sSettingIsWelcomeEnabled = true;
|
||||
public static boolean sSettingIsAppStarted = false;
|
||||
public static boolean sSettingIsAppRunning = false;
|
||||
public static boolean sSettingIsAppRedirected = false;
|
||||
public static boolean sSettingIsAppRestarting = false;
|
||||
public static boolean sSettingIsAppRated = false;
|
||||
|
@ -88,6 +90,7 @@ public class status
|
|||
{
|
||||
versionVerifier(pContext);
|
||||
|
||||
status.sUIInteracted = false;
|
||||
status.sSettingSearchHistory = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_SEARCH_HISTORY,true));
|
||||
status.sSearchSuggestionStatus = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_SEARCH_SUGGESTION,true));
|
||||
status.sSettingJavaStatus = (boolean)dataController.getInstance().invokePrefs(dataEnums.ePreferencesCommands.M_GET_BOOL, Arrays.asList(keys.SETTING_JAVA_SCRIPT,true));
|
||||
|
|
|
@ -109,6 +109,10 @@ public class suggestionDataModel implements SpellCheckerSession.SpellCheckerSess
|
|||
}
|
||||
}
|
||||
|
||||
if(mCurrentList.size()<=0) {
|
||||
mCurrentList.add( mSize,new historyRowModel("Genesis Search", "genesis.onion",-1));
|
||||
}
|
||||
|
||||
return mCurrentList;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ public class databaseController
|
|||
/*Initializations*/
|
||||
|
||||
public void prepareDatabaseEnvironment(AppCompatActivity app_context) {
|
||||
File databaseFile = app_context.getDatabasePath(CONST_DATABASE_NAME);
|
||||
File databaseFile = app_context.getDatabasePath(CONST_DATABASE_NAME + "_SECURE");
|
||||
|
||||
if (!databaseFile.exists()) {
|
||||
databaseFile.getParentFile().mkdirs();
|
||||
|
@ -63,7 +63,7 @@ public class databaseController
|
|||
{
|
||||
SQLiteDatabase.loadLibs(app_context);
|
||||
prepareDatabaseEnvironment(app_context);
|
||||
mDatabaseInstance = mDatabaseInstance.openOrCreateDatabase(app_context.getDatabasePath(CONST_DATABASE_NAME), constants.CONST_ENCRYPTION_KEY_DATABASE,null, wrapHook(null));
|
||||
mDatabaseInstance = mDatabaseInstance.openOrCreateDatabase(app_context.getDatabasePath(CONST_DATABASE_NAME + "_SECURE"), constants.CONST_ENCRYPTION_KEY_DATABASE,null, wrapHook(null));
|
||||
|
||||
mDatabaseInstance.execSQL("CREATE TABLE IF NOT EXISTS " + "history" + " (id INT(4) PRIMARY KEY,date DATETIME,url VARCHAR,title VARCHAR);");
|
||||
mDatabaseInstance.execSQL("CREATE TABLE IF NOT EXISTS " + "bookmark" + " (id INT(4) PRIMARY KEY,title VARCHAR,url VARCHAR);");
|
||||
|
@ -159,22 +159,26 @@ public class databaseController
|
|||
public ArrayList<tabRowModel> selectTabs(){
|
||||
ArrayList<tabRowModel> mTempListModel = new ArrayList<>();
|
||||
|
||||
Cursor c = mDatabaseInstance.rawQuery("SELECT * FROM tab ORDER BY date DESC", null);
|
||||
Cursor c = mDatabaseInstance.rawQuery("SELECT * FROM tab ORDER BY date ASC", null);
|
||||
if (c.moveToFirst()){
|
||||
do {
|
||||
geckoSession mSession = activityContextManager.getInstance().getHomeController().onNewTabInit();
|
||||
tabRowModel model = new tabRowModel(c.getString(0), c.getString(1),c.getBlob(4));
|
||||
GeckoSession.SessionState session = null;
|
||||
try {
|
||||
if(status.sRestoreTabs){
|
||||
// if(status.sRestoreTabs){
|
||||
session = GeckoSession.SessionState.fromString(c.getString(6));
|
||||
}
|
||||
// }
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
model.setSession(mSession, c.getString(3),c.getString(2), c.getString(5), session);
|
||||
model.getSession().setSessionID(model.getmId());
|
||||
mTempListModel.add(model);
|
||||
if(session != null){
|
||||
mTempListModel.add(0, model);
|
||||
}else {
|
||||
mTempListModel.add(model);
|
||||
}
|
||||
} while(c.moveToNext());
|
||||
}
|
||||
c.close();
|
||||
|
|
|
@ -10,29 +10,46 @@ import com.darkweb.genesissearchengine.appManager.homeManager.homeController.hom
|
|||
import com.darkweb.genesissearchengine.constants.status;
|
||||
import com.example.myapplication.R;
|
||||
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
public class externalNavigationController extends AppCompatActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Uri data = externalNavigationController.this.getIntent().getData();
|
||||
if(data == null){
|
||||
finish();
|
||||
activityContextManager.getInstance().onClearStack();
|
||||
Intent bringToForegroundIntent = new Intent(activityContextManager.getInstance().getHomeController(), homeController.class);
|
||||
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(bringToForegroundIntent);
|
||||
return;
|
||||
}
|
||||
|
||||
if(status.sSettingIsAppStarted){
|
||||
finish();
|
||||
Uri data = externalNavigationController.this.getIntent().getData();
|
||||
activityContextManager.getInstance().getHomeController().onOpenLinkNewTab(data.toString());
|
||||
activityContextManager.getInstance().onClearStack();
|
||||
|
||||
|
||||
final Handler handler = new Handler();
|
||||
handler.postDelayed(() -> {
|
||||
Intent launchIntent = getPackageManager().getLaunchIntentForPackage("com.darkweb.genesissearchengine");
|
||||
startActivity(launchIntent);
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
activityContextManager.getInstance().getHomeController().onOpenLinkNewTab(activityContextManager.getInstance().getHomeController().completeURL(data.toString()));
|
||||
activityContextManager.getInstance().getHomeController().onClearSelectionTab();
|
||||
}, 500);
|
||||
|
||||
Intent bringToForegroundIntent = new Intent(activityContextManager.getInstance().getHomeController(), homeController.class);
|
||||
bringToForegroundIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(bringToForegroundIntent);
|
||||
|
||||
return;
|
||||
}else if(status.sSettingIsAppRunning){
|
||||
finish();
|
||||
status.sExternalWebsite = data.toString();
|
||||
return;
|
||||
}
|
||||
|
||||
Intent intent = new Intent(this.getIntent());
|
||||
intent.setClassName(this.getApplicationContext(), homeController.class.getName());
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
Uri data = this.getIntent().getData();
|
||||
if(data!=null){
|
||||
if(activityContextManager.getInstance().getHomeController()!=null){
|
||||
activityContextManager.getInstance().getHomeController().onOpenLinkNewTab(data.toString());
|
||||
|
|
|
@ -22,7 +22,11 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.FileProvider;
|
||||
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.netcipher.client.StrongHttpsClient;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginController;
|
||||
import com.darkweb.genesissearchengine.pluginManager.pluginEnums;
|
||||
import com.example.myapplication.R;
|
||||
import org.mozilla.thirdparty.com.google.android.exoplayer2.util.Log;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
|
@ -37,6 +41,7 @@ import java.net.URI;
|
|||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import ch.boye.httpclientandroidlib.HttpHost;
|
||||
|
@ -196,10 +201,7 @@ public class localFileDownloader extends AsyncTask<String, Integer, String> {
|
|||
|
||||
} catch (Exception ex) {
|
||||
Log.i("FIZZAHFUCK", ex.getMessage());
|
||||
if(mRequestCode>300){
|
||||
mEvent.invokeObserver(Collections.singletonList(mRequestCode), M_DOWNLOAD_FAILURE);
|
||||
//Toast.makeText(context,"Request Forbidden Error Code : ",mRequestCode).show();
|
||||
}
|
||||
mEvent.invokeObserver(Collections.singletonList(mRequestCode), M_DOWNLOAD_FAILURE);
|
||||
onCancel();
|
||||
}
|
||||
}else {
|
||||
|
@ -260,9 +262,7 @@ public class localFileDownloader extends AsyncTask<String, Integer, String> {
|
|||
output.close();
|
||||
mStream.close();
|
||||
}catch (Exception ex){
|
||||
if(mRequestCode>300){
|
||||
mEvent.invokeObserver(Collections.singletonList(mRequestCode), M_DOWNLOAD_FAILURE);
|
||||
}
|
||||
pluginController.getInstance().onMessageManagerInvoke(Arrays.asList(Collections.singletonList(mRequestCode), activityContextManager.getInstance().getHomeController()), pluginEnums.eMessageManager.M_DOWNLOAD_FAILURE);
|
||||
onCancel();
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ public class localFileDownloader extends AsyncTask<String, Integer, String> {
|
|||
build.addAction(0, null, null);
|
||||
build.setContentIntent(pendingIntent);
|
||||
build.setContentText("Download complete");
|
||||
build.setSmallIcon(R.xml.ic_check);
|
||||
build.setSmallIcon(R.drawable.ic_download_complete);
|
||||
build.setColor(Color.parseColor("#84989f"));
|
||||
build.setProgress(0, 0, false);
|
||||
build.setAutoCancel(true);
|
||||
|
|
|
@ -11,15 +11,12 @@ import android.content.pm.PackageManager;
|
|||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.constants.status;
|
||||
import com.darkweb.genesissearchengine.constants.strings;
|
||||
import com.example.myapplication.R;
|
||||
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class userEngagementNotification extends BroadcastReceiver {
|
||||
|
|
|
@ -441,7 +441,6 @@ class messageManager
|
|||
mDialog.dismiss();
|
||||
}
|
||||
});
|
||||
mDialog.setOnDismissListener(dialog -> onClearReference());
|
||||
}
|
||||
|
||||
private void downloadFileLongPress()
|
||||
|
@ -565,7 +564,6 @@ class messageManager
|
|||
};
|
||||
handler.postDelayed(runnable, 1000);
|
||||
});
|
||||
mDialog.setOnDismissListener(dialog -> onClearReference());
|
||||
}
|
||||
|
||||
void onReset(){
|
||||
|
|
|
@ -6,7 +6,7 @@ import androidx.appcompat.app.AppCompatActivity;
|
|||
import org.mozilla.gecko.PrefsHelper;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
|
@ -47,7 +47,7 @@ class orbotManager
|
|||
orbotLocalConstants.mIsManualBridge = status.sBridgeGatewayManual;
|
||||
orbotLocalConstants.mManualBridgeType = status.sBridgeCustomType;
|
||||
Prefs.putBridgesEnabled(status.sBridgeStatus);
|
||||
Intent mServiceIntent = new Intent(mAppContext.get(), OrbotService.class);
|
||||
Intent mServiceIntent = new Intent(mAppContext.get().getApplicationContext(), OrbotService.class);
|
||||
mServiceIntent.setAction(ACTION_START);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
mAppContext.get().getApplicationContext().startForegroundService(mServiceIntent);
|
||||
|
@ -200,6 +200,12 @@ class orbotManager
|
|||
return OrbotService.getServiceObject().getProxyStatus();
|
||||
}
|
||||
|
||||
private void onDestroy(){
|
||||
if(!status.mThemeApplying) {
|
||||
OrbotService.getServiceObject().onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
/*External Triggers*/
|
||||
|
||||
Object onTrigger(List<Object> pData, pluginEnums.eOrbotManager pEventType) {
|
||||
|
@ -263,6 +269,10 @@ class orbotManager
|
|||
{
|
||||
newCircuit();
|
||||
}
|
||||
else if(pEventType.equals(pluginEnums.eOrbotManager.M_DESTROY))
|
||||
{
|
||||
onDestroy();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.darkweb.genesissearchengine.pluginManager;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.appManager.homeManager.homeController.homeController;
|
||||
|
@ -203,7 +206,10 @@ public class pluginController
|
|||
((homeController)mHomeController.get()).onLoadURL(pData.get(0).toString());
|
||||
}
|
||||
else if(pEventType.equals(M_PANIC_RESET)){
|
||||
activityContextManager.getInstance().getHomeController().panicExitInvoked();
|
||||
new Handler().postDelayed(() ->
|
||||
{
|
||||
activityContextManager.getInstance().getHomeController().panicExitInvoked();
|
||||
}, 300);
|
||||
}
|
||||
else if(pEventType.equals(M_DOWNLOAD_SINGLE)){
|
||||
if(pData.size()<3){
|
||||
|
|
|
@ -46,6 +46,6 @@ public class pluginEnums
|
|||
|
||||
/*Orbot Manager*/
|
||||
public enum eOrbotManager{
|
||||
M_GET_NOTIFICATION_STATUS, M_NEW_CIRCUIT,M_ENABLE_NOTIFICATION, M_DISABLE_NOTIFICATION, M_DISABLE_NOTIFICATION_NO_BANDWIDTH, M_GET_LOGS, M_UPDATE_PRIVACY,M_START_ORBOT,M_IS_ORBOT_RUNNING, M_GET_ORBOT_STATUS, M_UPDATE_BRIDGES, M_UPDATE_VPN, M_SET_PROXY, M_SHOW_NOTIFICATION_STATUS, M_ORBOT_RUNNING
|
||||
M_GET_NOTIFICATION_STATUS, M_NEW_CIRCUIT, M_DESTROY,M_ENABLE_NOTIFICATION, M_DISABLE_NOTIFICATION, M_DISABLE_NOTIFICATION_NO_BANDWIDTH, M_GET_LOGS, M_UPDATE_PRIVACY,M_START_ORBOT,M_IS_ORBOT_RUNNING, M_GET_ORBOT_STATUS, M_UPDATE_BRIDGES, M_UPDATE_VPN, M_SET_PROXY, M_SHOW_NOTIFICATION_STATUS, M_ORBOT_RUNNING
|
||||
}
|
||||
}
|
|
@ -3,20 +3,27 @@ package com.widget.search;
|
|||
import android.app.PendingIntent;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProvider;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.widget.RemoteViews;
|
||||
|
||||
import com.darkweb.genesissearchengine.appManager.activityContextManager;
|
||||
import com.darkweb.genesissearchengine.constants.enums;
|
||||
import com.darkweb.genesissearchengine.constants.status;
|
||||
import com.darkweb.genesissearchengine.constants.strings;
|
||||
import com.darkweb.genesissearchengine.helperManager.helperMethod;
|
||||
import com.example.myapplication.R;
|
||||
|
||||
public class searchWidgetManager extends AppWidgetProvider {
|
||||
|
||||
private static final String SHARED_PREF_FILE = "com.example.android.appwidgetsample";
|
||||
private static final String COUNT_KEY = "count";
|
||||
private static int mCurrentWidth = -1;
|
||||
|
||||
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
|
||||
|
||||
|
@ -43,9 +50,10 @@ public class searchWidgetManager extends AppWidgetProvider {
|
|||
|
||||
views.setOnClickPendingIntent(R.id.pSearchLogo, pendingUpdate);
|
||||
views.setOnClickPendingIntent(R.id.pTopBarContainer, pendingUpdate);
|
||||
views.setOnClickPendingIntent(R.id.pSearchInput, pendingUpdate);
|
||||
views.setOnClickPendingIntent(R.id.pSearchInputWidget, pendingUpdate);
|
||||
views.setOnClickPendingIntent(R.id.pVoiceInput, mpintentUpdate);
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||
|
||||
}
|
||||
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
|
@ -103,10 +111,34 @@ public class searchWidgetManager extends AppWidgetProvider {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppWidgetOptionsChanged (Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle widgetInfo) {
|
||||
int width = widgetInfo.getInt (AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
|
||||
mCurrentWidth = width;
|
||||
int[] appWidgetIds = new int[1];
|
||||
appWidgetIds[0] = appWidgetId;
|
||||
onUpdate(context, appWidgetManager, appWidgetIds);
|
||||
}
|
||||
|
||||
private int getColsNum (int size) {
|
||||
return (int) Math.floor ((size - 30) / 70);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
|
||||
for (int appWidgetId : appWidgetIds) {
|
||||
updateAppWidget(context, appWidgetManager, appWidgetId);
|
||||
|
||||
int size = getColsNum(mCurrentWidth);
|
||||
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_search_controller);
|
||||
if(mCurrentWidth!=-1){
|
||||
if(size<=2){
|
||||
views.setTextColor(R.id.pSearchInputWidget, Color.WHITE);
|
||||
}else {
|
||||
views.setTextColor(R.id.pSearchInputWidget, Color.GRAY);
|
||||
}
|
||||
appWidgetManager.updateAppWidget(appWidgetIds, views);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<shape
|
||||
android:shape="rectangle" android:padding="10dp" >
|
||||
<solid android:color="@color/white"/>
|
||||
<corners android:radius="7dp"/>
|
||||
<corners android:radius="6dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_pressed="false"
|
||||
|
@ -14,7 +14,7 @@
|
|||
<shape
|
||||
android:shape="rectangle" android:padding="10dp">
|
||||
<solid android:color="@color/white"/>
|
||||
<corners android:radius="7dp"/>
|
||||
<corners android:radius="6dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
android:background="@color/c_background"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
android:translationZ="3dp">
|
||||
|
||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||
|
@ -32,9 +33,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/pTopLayout"
|
||||
|
@ -44,9 +44,8 @@
|
|||
android:clipToPadding="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
|
||||
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/pTopbar"
|
||||
|
@ -144,7 +143,7 @@
|
|||
android:scaleX="1.1"
|
||||
android:scaleY="1.1"
|
||||
android:src="@xml/ic_baseline_keyboard_voice"
|
||||
android:tint="@color/c_navigation_tint"
|
||||
android:tint="@color/c_text_v8"
|
||||
android:visibility="gone" />
|
||||
|
||||
<Button
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_marginStart="2.5dp"
|
||||
android:background="@xml/gx_ripple_default_round"
|
||||
android:contentDescription="@string/GENERAL_TODO"
|
||||
android:padding="6dp"
|
||||
|
@ -33,10 +33,10 @@
|
|||
android:translationZ="10dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pSearchInput"
|
||||
android:id="@+id/pSearchInputWidget"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="-56dp"
|
||||
android:layout_marginStart="-53dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:paddingTop="13dp"
|
||||
android:layout_marginEnd="1dp"
|
||||
|
@ -48,19 +48,18 @@
|
|||
android:ems="10"
|
||||
android:fadingEdgeLength="20dp"
|
||||
android:focusableInTouchMode="true"
|
||||
android:hint="@string/GENERAL_HIDDEN_WEB"
|
||||
android:text="@string/GENERAL_HIDDEN_WEB"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textNoSuggestions"
|
||||
android:maxLines="1"
|
||||
android:paddingStart="70dp"
|
||||
android:paddingStart="60dp"
|
||||
android:paddingEnd="15dp"
|
||||
android:popupElevation="0dp"
|
||||
android:privateImeOptions="nm"
|
||||
android:requiresFadingEdge="horizontal"
|
||||
android:selectAllOnFocus="true"
|
||||
android:textColor="@color/c_text_v1"
|
||||
android:textColor="#737373"
|
||||
android:textColorHighlight="@color/text_color_highlight_v3"
|
||||
android:textColorHint="#737373"
|
||||
android:textCursorDrawable="@xml/gx_search_cursor_state"
|
||||
android:textIsSelectable="false"
|
||||
android:textSize="15sp">
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:initialKeyguardLayout="@layout/widget_search_controller"
|
||||
android:initialLayout="@layout/widget_search_controller"
|
||||
android:minWidth="100dp"
|
||||
android:minWidth="1000dp"
|
||||
android:minResizeWidth="100.0dp"
|
||||
android:previewImage="@drawable/widget_ref"
|
||||
android:resizeMode="horizontal"
|
||||
android:updatePeriodMillis="86400000"
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
android:layout_marginEnd="-1dp"
|
||||
android:layout_height="48dp"
|
||||
android:visibility="visible"
|
||||
android:alpha="1"
|
||||
android:alpha="0"
|
||||
android:translationZ="3dp"
|
||||
android:src="@drawable/tick_recycler_view_green"
|
||||
android:gravity="center_vertical"
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
## For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
#
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx1024m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
#
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
#Wed Oct 07 12:31:34 PKT 2020
|
||||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
org.gradle.jvmargs=-Xms1g -Xmx4g
|
|
@ -1,9 +1,9 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
buildToolsVersion '30.0.3'
|
||||
ndkVersion '21.4.7075529'
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion '29.0.3'
|
||||
ndkVersion '21.3.6528147'
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
|
@ -12,8 +12,8 @@ android {
|
|||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 31
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -31,30 +31,31 @@ android {
|
|||
}
|
||||
|
||||
lintOptions {
|
||||
checkReleaseBuilds false
|
||||
abortOnError true
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
htmlReport true
|
||||
xmlReport false
|
||||
textReport false
|
||||
|
||||
lintConfig file("../lint.xml")
|
||||
packagingOptions {
|
||||
exclude 'assets/arm/obfs4proxy' //this is redundant
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
implementation fileTree(dir: 'libs', include: ['.so'])
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'org.torproject:tor-android-binary:0.4.4.6'
|
||||
implementation 'info.pluggabletransports.aptds:apt-dispatch-library:1.0.9'
|
||||
implementation 'info.pluggabletransports.aptds:apt-meek-obfs4-legacy:1.0.9'
|
||||
|
||||
implementation 'org.torproject:tor-android-binary:0.4.3.6-actual'
|
||||
|
||||
implementation 'info.pluggabletransports.aptds:apt-dispatch-library:1.0.9'
|
||||
implementation 'info.pluggabletransports.aptds:apt-meek-obfs4-legacy:1.0.9'
|
||||
implementation 'info.pluggabletransports.aptds:jsocksAndroid:1.0.4'
|
||||
|
||||
implementation 'com.jaredrummler:android-shell:1.0.0'
|
||||
implementation fileTree(dir: 'libs', include: ['.so'])
|
||||
implementation 'androidx.core:core:1.3.2'
|
||||
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
|
||||
testImplementation 'junit:junit:4.13'
|
||||
|
||||
implementation 'com.offbynull.portmapper:portmapper:2.0.5'
|
||||
|
||||
implementation 'info.guardianproject:jtorctl:0.4'
|
||||
implementation 'com.github.tladesignz:IPtProxy:0.5.0'
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.torproject.android.proxy">
|
||||
package="org.torproject.android.service">
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
</manifest>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,13 +2,12 @@ package org.torproject.android.proxy;
|
|||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.core.app.NotificationCompat;
|
||||
|
||||
import net.freehaven.tor.control.EventHandler;
|
||||
|
||||
import org.torproject.android.proxy.util.ExternalIPFetcher;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.R;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -103,7 +103,7 @@ public interface TorServiceConstants {
|
|||
// actions for internal command Intents
|
||||
String CMD_SIGNAL_HUP = "signal_hup";
|
||||
String CMD_NEWNYM = "newnym";
|
||||
String CMD_setting = "setting";
|
||||
String CMD_SETTING = "setting";
|
||||
String CMD_SET_EXIT = "setexit";
|
||||
String CMD_ACTIVE = "ACTIVE";
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import android.content.Context;
|
|||
import android.content.SharedPreferences;
|
||||
|
||||
import org.torproject.android.proxy.OrbotConstants;
|
||||
import org.torproject.android.proxy.wrapper.orbotLocalConstants;
|
||||
import org.torproject.android.service.wrapper.orbotLocalConstants;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
|
@ -98,7 +98,7 @@ public class Prefs {
|
|||
}
|
||||
|
||||
public static boolean useDebugLogging() {
|
||||
return prefs.getBoolean(PREF_ENABLE_LOGGING, false);
|
||||
return false;//prefs.getBoolean(PREF_ENABLE_LOGGING, false);
|
||||
}
|
||||
|
||||
public static boolean persistNotifications() {
|
||||
|
|
|
@ -35,10 +35,11 @@ import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
|
|||
|
||||
import org.torproject.android.proxy.OrbotConstants;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.R;
|
||||
import org.torproject.android.proxy.TorServiceConstants;
|
||||
import org.torproject.android.proxy.util.CustomNativeLoader;
|
||||
import org.torproject.android.proxy.util.Prefs;
|
||||
import org.torproject.android.service.R;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot/The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
package org.torproject.android.service;
|
||||
|
||||
public interface OrbotConstants {
|
||||
|
||||
String TAG = "Orbot";
|
||||
|
||||
String PREF_OR = "pref_or";
|
||||
String PREF_OR_PORT = "pref_or_port";
|
||||
String PREF_OR_NICKNAME = "pref_or_nickname";
|
||||
String PREF_REACHABLE_ADDRESSES = "pref_reachable_addresses";
|
||||
String PREF_REACHABLE_ADDRESSES_PORTS = "pref_reachable_addresses_ports";
|
||||
|
||||
String PREF_DISABLE_NETWORK = "pref_disable_network";
|
||||
|
||||
String PREF_TOR_SHARED_PREFS = "org.torproject.android_preferences";
|
||||
|
||||
String PREF_SOCKS = "pref_socks";
|
||||
|
||||
String PREF_HTTP = "pref_http";
|
||||
|
||||
String PREF_ISOLATE_DEST = "pref_isolate_dest";
|
||||
|
||||
String PREF_CONNECTION_PADDING = "pref_connection_padding";
|
||||
String PREF_REDUCED_CONNECTION_PADDING = "pref_reduced_connection_padding";
|
||||
String PREF_CIRCUIT_PADDING = "pref_circuit_padding";
|
||||
String PREF_REDUCED_CIRCUIT_PADDING = "pref_reduced_circuit_padding";
|
||||
|
||||
String PREF_PREFER_IPV6 = "pref_prefer_ipv6";
|
||||
String PREF_DISABLE_IPV4 = "pref_disable_ipv4";
|
||||
|
||||
|
||||
String APP_TOR_KEY = "_app_tor";
|
||||
String APP_DATA_KEY = "_app_data";
|
||||
String APP_WIFI_KEY = "_app_wifi";
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.torproject.android.service;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
|
||||
|
||||
public class StartTorReceiver extends BroadcastReceiver implements TorServiceConstants {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
/* sanitize the Intent before forwarding it to OrbotService */
|
||||
Prefs.setContext(context);
|
||||
String action = intent.getAction();
|
||||
if (TextUtils.equals(action, ACTION_START)) {
|
||||
String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
|
||||
if (Prefs.allowBackgroundStarts()) {
|
||||
Intent startTorIntent = new Intent(context, OrbotService.class);
|
||||
startTorIntent.setAction(action);
|
||||
if (packageName != null) {
|
||||
startTorIntent.putExtra(OrbotService.EXTRA_PACKAGE_NAME, packageName);
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && Prefs.persistNotifications()) {
|
||||
context.startForegroundService(startTorIntent);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/* 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 {
|
||||
|
||||
String DIRECTORY_TOR_DATA = "tordata";
|
||||
|
||||
String TOR_CONTROL_PORT_FILE = "control.txt";
|
||||
String TOR_PID_FILE = "torpid";
|
||||
|
||||
//torrc (tor config file)
|
||||
String TORRC_ASSET_KEY = "torrc";
|
||||
|
||||
String TOR_CONTROL_COOKIE = "control_auth_cookie";
|
||||
|
||||
//geoip data file asset key
|
||||
String GEOIP_ASSET_KEY = "geoip";
|
||||
String GEOIP6_ASSET_KEY = "geoip6";
|
||||
|
||||
String IP_LOCALHOST = "127.0.0.1";
|
||||
int TOR_TRANSPROXY_PORT_DEFAULT = 9040;
|
||||
|
||||
int TOR_DNS_PORT_DEFAULT = 5400;
|
||||
|
||||
String HTTP_PROXY_PORT_DEFAULT = "8118"; // like Privoxy!
|
||||
String SOCKS_PROXY_PORT_DEFAULT = "9050";
|
||||
|
||||
//control port
|
||||
String LOG_NOTICE_HEADER = "NOTICE";
|
||||
String LOG_NOTICE_BOOTSTRAPPED = "Bootstrapped";
|
||||
|
||||
/**
|
||||
* A request to Orbot to transparently start Tor services
|
||||
*/
|
||||
String ACTION_START = "org.torproject.android.intent.action.START";
|
||||
String ACTION_STOP = "org.torproject.android.intent.action.STOP";
|
||||
|
||||
String ACTION_START_VPN = "org.torproject.android.intent.action.START_VPN";
|
||||
String ACTION_STOP_VPN = "org.torproject.android.intent.action.STOP_VPN";
|
||||
|
||||
String ACTION_START_ON_BOOT = "org.torproject.android.intent.action.START_BOOT";
|
||||
|
||||
int REQUEST_VPN = 7777;
|
||||
|
||||
/**
|
||||
* {@link Intent} send by Orbot with {@code ON/OFF/STARTING/STOPPING} status
|
||||
*/
|
||||
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}
|
||||
*/
|
||||
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
|
||||
*/
|
||||
String EXTRA_PACKAGE_NAME = "org.torproject.android.intent.extra.PACKAGE_NAME";
|
||||
/**
|
||||
* The SOCKS proxy settings in URL form.
|
||||
*/
|
||||
String EXTRA_SOCKS_PROXY = "org.torproject.android.intent.extra.SOCKS_PROXY";
|
||||
String EXTRA_SOCKS_PROXY_HOST = "org.torproject.android.intent.extra.SOCKS_PROXY_HOST";
|
||||
String EXTRA_SOCKS_PROXY_PORT = "org.torproject.android.intent.extra.SOCKS_PROXY_PORT";
|
||||
/**
|
||||
* The HTTP proxy settings in URL form.
|
||||
*/
|
||||
String EXTRA_HTTP_PROXY = "org.torproject.android.intent.extra.HTTP_PROXY";
|
||||
String EXTRA_HTTP_PROXY_HOST = "org.torproject.android.intent.extra.HTTP_PROXY_HOST";
|
||||
String EXTRA_HTTP_PROXY_PORT = "org.torproject.android.intent.extra.HTTP_PROXY_PORT";
|
||||
|
||||
String EXTRA_DNS_PORT = "org.torproject.android.intent.extra.DNS_PORT";
|
||||
String EXTRA_TRANS_PORT = "org.torproject.android.intent.extra.TRANS_PORT";
|
||||
|
||||
String LOCAL_ACTION_LOG = "log";
|
||||
String LOCAL_ACTION_BANDWIDTH = "bandwidth";
|
||||
String LOCAL_EXTRA_LOG = "log";
|
||||
String LOCAL_ACTION_PORTS = "ports";
|
||||
|
||||
/**
|
||||
* All tor-related services and daemons are stopped
|
||||
*/
|
||||
String STATUS_OFF = "OFF";
|
||||
/**
|
||||
* All tor-related services and daemons have completed starting
|
||||
*/
|
||||
String STATUS_ON = "ON";
|
||||
String STATUS_STARTING = "STARTING";
|
||||
String STATUS_STOPPING = "STOPPING";
|
||||
|
||||
/**
|
||||
* The user has disabled the ability for background starts triggered by
|
||||
* apps. Fallback to the old {@link Intent} action that brings up Orbot:
|
||||
* {@link org.torproject.android.OrbotMainActivity#INTENT_ACTION_REQUEST_START_TOR}
|
||||
*/
|
||||
String STATUS_STARTS_DISABLED = "STARTS_DISABLED";
|
||||
|
||||
// actions for internal command Intents
|
||||
String CMD_SIGNAL_HUP = "signal_hup";
|
||||
String CMD_NEWNYM = "newnym";
|
||||
String CMD_SET_EXIT = "setexit";
|
||||
String CMD_ACTIVE = "ACTIVE";
|
||||
|
||||
String PREF_BINARY_TOR_VERSION_INSTALLED = "BINARY_TOR_VERSION_INSTALLED";
|
||||
|
||||
//obfsproxy
|
||||
String OBFSCLIENT_ASSET_KEY = "obfs4proxy";
|
||||
|
||||
String HIDDEN_SERVICES_DIR = "hidden_services";
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class CustomNativeLoader {
|
||||
|
||||
private final static String TAG = "CNL";
|
||||
|
||||
private static boolean loadFromZip(Context context, String libname, File destLocalFile, String arch) {
|
||||
|
||||
|
||||
ZipFile zipFile = null;
|
||||
InputStream stream = null;
|
||||
|
||||
try {
|
||||
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
|
||||
ZipEntry entry = zipFile.getEntry("lib/" + arch + "/" + libname + ".so");
|
||||
if (entry == null) {
|
||||
entry = zipFile.getEntry("jni/" + arch + "/" + libname + ".so");
|
||||
if (entry == null)
|
||||
throw new Exception("Unable to find file in apk:" + "lib/" + arch + "/" + libname);
|
||||
}
|
||||
|
||||
//how we wrap this in another stream because the native .so is zipped itself
|
||||
stream = zipFile.getInputStream(entry);
|
||||
|
||||
OutputStream out = new FileOutputStream(destLocalFile);
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = stream.read(buf)) > 0) {
|
||||
Thread.yield();
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
|
||||
destLocalFile.setReadable(true, false);
|
||||
destLocalFile.setExecutable(true, false);
|
||||
destLocalFile.setWritable(true);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
if (zipFile != null) {
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static File loadNativeBinary(Context context, String libname, File destLocalFile) {
|
||||
|
||||
try {
|
||||
|
||||
|
||||
File fileNativeBin = new File(getNativeLibraryDir(context), libname + ".so");
|
||||
if (!fileNativeBin.exists())
|
||||
fileNativeBin = new File(getNativeLibraryDir(context), "lib" + libname + ".so");
|
||||
|
||||
if (fileNativeBin.exists()) {
|
||||
if (fileNativeBin.canExecute())
|
||||
return fileNativeBin;
|
||||
else {
|
||||
setExecutable(fileNativeBin);
|
||||
|
||||
if (fileNativeBin.canExecute())
|
||||
return fileNativeBin;
|
||||
}
|
||||
}
|
||||
|
||||
String folder = Build.CPU_ABI;
|
||||
|
||||
|
||||
String javaArch = System.getProperty("os.arch");
|
||||
if (javaArch != null && javaArch.contains("686")) {
|
||||
folder = "x86";
|
||||
}
|
||||
|
||||
if (loadFromZip(context, libname, destLocalFile, folder)) {
|
||||
return destLocalFile;
|
||||
}
|
||||
|
||||
} catch (Throwable e) {
|
||||
Log.e(TAG, e.getMessage(), e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void setExecutable(File fileBin) {
|
||||
fileBin.setReadable(true);
|
||||
fileBin.setExecutable(true);
|
||||
fileBin.setWritable(false);
|
||||
fileBin.setWritable(true, true);
|
||||
}
|
||||
|
||||
// Return Full path to the directory where native JNI libraries are stored.
|
||||
private static String getNativeLibraryDir(Context context) {
|
||||
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||
return appInfo.nativeLibraryDir;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.jaredrummler.android.shell.CommandResult;
|
||||
import com.jaredrummler.android.shell.Shell;
|
||||
import com.jaredrummler.android.shell.ShellExitCode;
|
||||
import com.jaredrummler.android.shell.StreamGobbler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CustomShell extends Shell {
|
||||
|
||||
|
||||
@WorkerThread
|
||||
public static CommandResult run(@NonNull String shell, boolean waitFor, @Nullable Map<String, String> env, @NonNull String command) {
|
||||
List<String> stdout = Collections.synchronizedList(new ArrayList<>());
|
||||
List<String> stderr = Collections.synchronizedList(new ArrayList<>());
|
||||
int exitCode = -1;
|
||||
|
||||
try {
|
||||
|
||||
// setup our process, retrieve stdin stream, and stdout/stderr gobblers
|
||||
//Process process = runWithEnv(command, env);
|
||||
ProcessBuilder builder = new ProcessBuilder();
|
||||
|
||||
if (env != null && (!env.isEmpty()))
|
||||
builder.environment().putAll(env);
|
||||
|
||||
builder.command("/system/bin/" + shell, "-c", command);
|
||||
Process process = builder.start();
|
||||
|
||||
StreamGobbler stdoutGobbler = null;
|
||||
StreamGobbler stderrGobbler = null;
|
||||
|
||||
if (waitFor) {
|
||||
stdoutGobbler = new StreamGobbler(process.getInputStream(), stdout);
|
||||
stderrGobbler = new StreamGobbler(process.getErrorStream(), stderr);
|
||||
|
||||
// start gobbling and write our commands to the shell
|
||||
stdoutGobbler.start();
|
||||
stderrGobbler.start();
|
||||
}
|
||||
|
||||
// wait for our process to finish, while we gobble away in the background
|
||||
if (waitFor)
|
||||
exitCode = process.waitFor();
|
||||
else
|
||||
exitCode = 0;
|
||||
|
||||
// make sure our threads are done gobbling, our streams are closed, and the process is destroyed - while the
|
||||
// latter two shouldn't be needed in theory, and may even produce warnings, in "normal" Java they are required
|
||||
// for guaranteed cleanup of resources, so lets be safe and do this on Android as well
|
||||
/**
|
||||
try {
|
||||
stdin.close();
|
||||
} catch (IOException e) {
|
||||
// might be closed already
|
||||
}**/
|
||||
|
||||
if (waitFor) {
|
||||
stdoutGobbler.join();
|
||||
stderrGobbler.join();
|
||||
}
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
exitCode = ShellExitCode.WATCHDOG_EXIT;
|
||||
} catch (IOException e) {
|
||||
exitCode = ShellExitCode.SHELL_WRONG_UID;
|
||||
}
|
||||
|
||||
return new CommandResult(stdout, stderr, exitCode);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import org.torproject.android.binary.TorServiceConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class CustomTorResourceInstaller implements TorServiceConstants {
|
||||
|
||||
|
||||
private File installFolder;
|
||||
private Context context;
|
||||
|
||||
private File fileTorrc;
|
||||
private File fileTor;
|
||||
|
||||
public CustomTorResourceInstaller(Context context, File installFolder) {
|
||||
this.installFolder = installFolder;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// Return Full path to the directory where native JNI libraries are stored.
|
||||
private static String getNativeLibraryDir(Context context) {
|
||||
ApplicationInfo appInfo = context.getApplicationInfo();
|
||||
return appInfo.nativeLibraryDir;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the inputstream contents to the file
|
||||
*/
|
||||
private static boolean streamToFile(InputStream stm, File outFile, boolean append, boolean zip) throws IOException {
|
||||
byte[] buffer = new byte[FILE_WRITE_BUFFER_SIZE];
|
||||
|
||||
int bytecount;
|
||||
|
||||
OutputStream stmOut = new FileOutputStream(outFile.getAbsolutePath(), append);
|
||||
ZipInputStream zis = null;
|
||||
|
||||
if (zip) {
|
||||
zis = new ZipInputStream(stm);
|
||||
ZipEntry ze = zis.getNextEntry();
|
||||
stm = zis;
|
||||
|
||||
}
|
||||
|
||||
while ((bytecount = stm.read(buffer)) > 0) {
|
||||
|
||||
stmOut.write(buffer, 0, bytecount);
|
||||
|
||||
}
|
||||
|
||||
stmOut.close();
|
||||
stm.close();
|
||||
|
||||
if (zis != null)
|
||||
zis.close();
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Extract the Tor binary from the APK file using ZIP
|
||||
*/
|
||||
|
||||
private static File[] listf(String directoryName) {
|
||||
|
||||
// .............list file
|
||||
File directory = new File(directoryName);
|
||||
|
||||
// get all the files from a directory
|
||||
File[] fList = directory.listFiles();
|
||||
|
||||
if (fList != null)
|
||||
for (File file : fList) {
|
||||
if (file.isFile()) {
|
||||
Log.d(TAG, file.getAbsolutePath());
|
||||
} else if (file.isDirectory()) {
|
||||
listf(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
return fList;
|
||||
}
|
||||
|
||||
//
|
||||
/*
|
||||
* Extract the Tor resources from the APK file using ZIP
|
||||
*
|
||||
* @File path to the Tor executable
|
||||
*/
|
||||
public File installResources() throws IOException, TimeoutException {
|
||||
|
||||
fileTor = new File(installFolder, TOR_ASSET_KEY);
|
||||
|
||||
if (!installFolder.exists())
|
||||
installFolder.mkdirs();
|
||||
|
||||
installGeoIP();
|
||||
fileTorrc = assetToFile(COMMON_ASSET_KEY + TORRC_ASSET_KEY, TORRC_ASSET_KEY, false, false);
|
||||
|
||||
File fileNativeDir = new File(getNativeLibraryDir(context));
|
||||
fileTor = new File(fileNativeDir, TOR_ASSET_KEY + ".so");
|
||||
|
||||
if (fileTor.exists()) {
|
||||
if (fileTor.canExecute())
|
||||
return fileTor;
|
||||
else {
|
||||
setExecutable(fileTor);
|
||||
|
||||
if (fileTor.canExecute())
|
||||
return fileTor;
|
||||
}
|
||||
}
|
||||
|
||||
File fileTorBin = new File(installFolder, TOR_BINARY_KEY);
|
||||
|
||||
//it exists but we can't execute it, so copy it to a new path
|
||||
if (fileTor.exists()) {
|
||||
InputStream is = new FileInputStream(fileTor);
|
||||
streamToFile(is, fileTorBin, false, true);
|
||||
setExecutable(fileTorBin);
|
||||
|
||||
if (fileTorBin.exists() && fileTorBin.canExecute())
|
||||
return fileTorBin;
|
||||
}
|
||||
|
||||
//let's try another approach
|
||||
fileTor = CustomNativeLoader.loadNativeBinary(context, TOR_ASSET_KEY, fileTorBin);
|
||||
|
||||
if (fileTor != null && fileTor.exists())
|
||||
setExecutable(fileTor);
|
||||
|
||||
if (fileTor != null && fileTor.exists() && fileTor.canExecute())
|
||||
return fileTor;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean installGeoIP() throws IOException {
|
||||
|
||||
assetToFile(COMMON_ASSET_KEY + GEOIP_ASSET_KEY, GEOIP_ASSET_KEY, false, false);
|
||||
|
||||
assetToFile(COMMON_ASSET_KEY + GEOIP6_ASSET_KEY, GEOIP6_ASSET_KEY, false, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads file from assetPath/assetKey writes it to the install folder
|
||||
*/
|
||||
private File assetToFile(String assetPath, String assetKey, boolean isZipped, boolean isExecutable) throws IOException {
|
||||
InputStream is = context.getAssets().open(assetPath);
|
||||
File outFile = new File(installFolder, assetKey);
|
||||
streamToFile(is, outFile, false, isZipped);
|
||||
if (isExecutable) {
|
||||
setExecutable(outFile);
|
||||
}
|
||||
return outFile;
|
||||
}
|
||||
|
||||
private void setExecutable(File fileBin) {
|
||||
fileBin.setReadable(true);
|
||||
fileBin.setExecutable(true);
|
||||
fileBin.setWritable(false);
|
||||
fileBin.setWritable(true, true);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
|
||||
/*
|
||||
* To combat background service being stopped/swiped
|
||||
*/
|
||||
public class DummyActivity extends Activity {
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
finish();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.proxy.TorEventHandler;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
public class ExternalIPFetcher implements Runnable {
|
||||
|
||||
private final static String ONIONOO_BASE_URL = "https://onionoo.torproject.org/details?fields=country_name,as_name,or_addresses&lookup=";
|
||||
private OrbotService mService;
|
||||
private TorEventHandler.Node mNode;
|
||||
private int mLocalHttpProxyPort = 8118;
|
||||
|
||||
public ExternalIPFetcher(OrbotService service, TorEventHandler.Node node, int localProxyPort) {
|
||||
mService = service;
|
||||
mNode = node;
|
||||
mLocalHttpProxyPort = localProxyPort;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
URLConnection conn;
|
||||
|
||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", mLocalHttpProxyPort));
|
||||
conn = new URL(ONIONOO_BASE_URL + mNode.id).openConnection(proxy);
|
||||
|
||||
conn.setRequestProperty("Connection", "Close");
|
||||
conn.setConnectTimeout(60000);
|
||||
conn.setReadTimeout(60000);
|
||||
|
||||
InputStream is = conn.getInputStream();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
// getting JSON string from URL
|
||||
|
||||
StringBuffer json = new StringBuffer();
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null)
|
||||
json.append(line);
|
||||
|
||||
JSONObject jsonNodeInfo = new org.json.JSONObject(json.toString());
|
||||
|
||||
JSONArray jsonRelays = jsonNodeInfo.getJSONArray("relays");
|
||||
|
||||
if (jsonRelays.length() > 0) {
|
||||
mNode.ipAddress = jsonRelays.getJSONObject(0).getJSONArray("or_addresses").getString(0).split(":")[0];
|
||||
mNode.country = jsonRelays.getJSONObject(0).getString("country_name");
|
||||
mNode.organization = jsonRelays.getJSONObject(0).getString("as_name");
|
||||
|
||||
StringBuffer sbInfo = new StringBuffer();
|
||||
sbInfo.append(mNode.name).append("(");
|
||||
sbInfo.append(mNode.ipAddress).append(")");
|
||||
|
||||
if (mNode.country != null)
|
||||
sbInfo.append(' ').append(mNode.country);
|
||||
|
||||
if (mNode.organization != null)
|
||||
sbInfo.append(" (").append(mNode.organization).append(')');
|
||||
|
||||
mService.debug(sbInfo.toString());
|
||||
|
||||
}
|
||||
|
||||
reader.close();
|
||||
is.close();
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
// mService.debug ("Error getting node details from onionoo: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
public class NativeLoader {
|
||||
|
||||
private final static String TAG = "TorNativeLoader";
|
||||
|
||||
private static boolean loadFromZip(Context context, String libName, File destLocalFile, String folder) {
|
||||
|
||||
|
||||
ZipFile zipFile = null;
|
||||
InputStream stream = null;
|
||||
try {
|
||||
zipFile = new ZipFile(context.getApplicationInfo().sourceDir);
|
||||
|
||||
/**
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements())
|
||||
{
|
||||
ZipEntry entry = entries.nextElement();
|
||||
Log.d("Zip","entry: " + entry.getName());
|
||||
}
|
||||
**/
|
||||
|
||||
ZipEntry entry = zipFile.getEntry("lib/" + folder + "/" + libName + ".so");
|
||||
if (entry == null) {
|
||||
entry = zipFile.getEntry("lib/" + folder + "/" + libName);
|
||||
if (entry == null)
|
||||
throw new Exception("Unable to find file in apk:" + "lib/" + folder + "/" + libName);
|
||||
}
|
||||
stream = zipFile.getInputStream(entry);
|
||||
|
||||
OutputStream out = new FileOutputStream(destLocalFile);
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
while ((len = stream.read(buf)) > 0) {
|
||||
Thread.yield();
|
||||
out.write(buf, 0, len);
|
||||
}
|
||||
out.close();
|
||||
|
||||
destLocalFile.setReadable(true, false);
|
||||
destLocalFile.setExecutable(true, false);
|
||||
destLocalFile.setWritable(true);
|
||||
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
if (zipFile != null) {
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static synchronized boolean initNativeLibs(Context context, String binaryName, File destLocalFile) {
|
||||
|
||||
try {
|
||||
String folder = Build.CPU_ABI;
|
||||
|
||||
String javaArch = System.getProperty("os.arch");
|
||||
if (javaArch != null && javaArch.contains("686")) {
|
||||
folder = "x86";
|
||||
}
|
||||
|
||||
return loadFromZip(context, binaryName, destLocalFile, folder);
|
||||
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.offbynull.portmapper.PortMapperFactory;
|
||||
import com.offbynull.portmapper.gateway.Bus;
|
||||
import com.offbynull.portmapper.gateway.Gateway;
|
||||
import com.offbynull.portmapper.gateways.network.NetworkGateway;
|
||||
import com.offbynull.portmapper.gateways.network.internalmessages.KillNetworkRequest;
|
||||
import com.offbynull.portmapper.gateways.process.ProcessGateway;
|
||||
import com.offbynull.portmapper.gateways.process.internalmessages.KillProcessRequest;
|
||||
import com.offbynull.portmapper.mapper.MappedPort;
|
||||
import com.offbynull.portmapper.mapper.PortMapper;
|
||||
import com.offbynull.portmapper.mapper.PortType;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PortForwarder {
|
||||
|
||||
private boolean shutdown = false;
|
||||
private Thread mThread = null;
|
||||
|
||||
public void shutdown() {
|
||||
shutdown = true;
|
||||
}
|
||||
|
||||
public void forward(final int internalPort, final int externalPort, final long lifetime) throws InterruptedException {
|
||||
|
||||
mThread = new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
forwardSync(internalPort, externalPort, lifetime);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mThread.start();
|
||||
}
|
||||
|
||||
|
||||
public void forwardSync(int internalPort, int externalPort, long lifetime) throws InterruptedException {
|
||||
// Start gateways
|
||||
Gateway network = NetworkGateway.create();
|
||||
Gateway process = ProcessGateway.create();
|
||||
Bus networkBus = network.getBus();
|
||||
Bus processBus = process.getBus();
|
||||
|
||||
// Discover port forwarding devices and take the first one found
|
||||
List<PortMapper> mappers = PortMapperFactory.discover(networkBus, processBus);
|
||||
PortMapper mapper = mappers.get(0);
|
||||
|
||||
// Map internal port 12345 to some external port (55555 preferred)
|
||||
//
|
||||
// IMPORTANT NOTE: Many devices prevent you from mapping ports that are <= 1024
|
||||
// (both internal and external ports). Be mindful of this when choosing which
|
||||
// ports you want to map.
|
||||
MappedPort mappedPort = mapper.mapPort(PortType.TCP, internalPort, externalPort, lifetime);
|
||||
Log.d(getClass().getName(), "Port mapping added: " + mappedPort);
|
||||
|
||||
// Refresh mapping half-way through the lifetime of the mapping (for example,
|
||||
// if the mapping is available for 40 seconds, refresh it every 20 seconds)
|
||||
while (!shutdown) {
|
||||
mappedPort = mapper.refreshPort(mappedPort, mappedPort.getLifetime() / 2L);
|
||||
Log.d(getClass().getName(), "Port mapping refreshed: " + mappedPort);
|
||||
Thread.sleep(mappedPort.getLifetime() * 1000L);
|
||||
}
|
||||
|
||||
// Unmap port 12345
|
||||
mapper.unmapPort(mappedPort);
|
||||
|
||||
// Stop gateways
|
||||
networkBus.send(new KillNetworkRequest());
|
||||
processBus.send(new KillProcessRequest()); // can kill this after discovery
|
||||
}
|
||||
}
|
|
@ -0,0 +1,118 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.torproject.android.service.OrbotConstants;
|
||||
|
||||
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_PERSIST_NOTIFICATIONS = "pref_persistent_notifications";
|
||||
private final static String PREF_START_ON_BOOT = "pref_start_boot";
|
||||
private final static String PREF_ALLOW_BACKGROUND_STARTS = "pref_allow_background_starts";
|
||||
private final static String PREF_OPEN_PROXY_ON_ALL_INTERFACES = "pref_open_proxy_on_all_interfaces";
|
||||
private final static String PREF_USE_VPN = "pref_vpn";
|
||||
private final static String PREF_EXIT_NODES = "pref_exit_nodes";
|
||||
|
||||
private static SharedPreferences prefs;
|
||||
|
||||
public static void setContext(Context context) {
|
||||
if (prefs == null)
|
||||
prefs = 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() {
|
||||
//if phone is in Farsi, enable bridges by default
|
||||
boolean bridgesEnabledDefault = Locale.getDefault().getLanguage().equals("fa");
|
||||
return prefs.getBoolean(PREF_BRIDGES_ENABLED, bridgesEnabledDefault);
|
||||
}
|
||||
|
||||
public static void putBridgesEnabled(boolean value) {
|
||||
putBoolean(PREF_BRIDGES_ENABLED, value);
|
||||
}
|
||||
|
||||
public static String getBridgesList() {
|
||||
String defaultBridgeType = "obfs4";
|
||||
if (Locale.getDefault().getLanguage().equals("fa"))
|
||||
defaultBridgeType = "meek"; //if Farsi, use meek as the default bridge type
|
||||
return prefs.getString(PREF_BRIDGES_LIST, defaultBridgeType);
|
||||
}
|
||||
|
||||
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 expandedNotifications() {
|
||||
return prefs.getBoolean(PREF_EXPANDED_NOTIFICATIONS, true);
|
||||
}
|
||||
|
||||
public static boolean useDebugLogging() {
|
||||
if(prefs == null){
|
||||
return false;
|
||||
}
|
||||
return prefs.getBoolean(PREF_ENABLE_LOGGING, false);
|
||||
}
|
||||
|
||||
public static boolean persistNotifications() {
|
||||
return prefs.getBoolean(PREF_PERSIST_NOTIFICATIONS, true);
|
||||
}
|
||||
|
||||
public static boolean allowBackgroundStarts() {
|
||||
return prefs.getBoolean(PREF_ALLOW_BACKGROUND_STARTS, true);
|
||||
}
|
||||
|
||||
public static boolean openProxyOnAllInterfaces() {
|
||||
return prefs.getBoolean(PREF_OPEN_PROXY_ON_ALL_INTERFACES, false);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public static String getExitNodes() {
|
||||
return prefs.getString(PREF_EXIT_NODES, "");
|
||||
}
|
||||
|
||||
public static void setExitNodes(String exits) {
|
||||
putString(PREF_EXIT_NODES, exits);
|
||||
}
|
||||
|
||||
public static SharedPreferences getSharedPrefs(Context context) {
|
||||
return context.getSharedPreferences(OrbotConstants.PREF_TOR_SHARED_PREFS, Context.MODE_MULTI_PROCESS);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
package org.torproject.android.service.util;
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Copyright (c) 2013, Sebastiano Gottardo
|
||||
* All rights reserved.
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the MegaDevs nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL SEBASTIANO GOTTARDO BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Main class for the TCPSourceApp library.
|
||||
*
|
||||
* @author Sebastiano Gottardo
|
||||
*/
|
||||
public class TCPSourceApp {
|
||||
|
||||
/*
|
||||
* In a Linux-based OS, each active TCP socket is mapped in the following
|
||||
* two files. A socket may be mapped in the '/proc/net/tcp' file in case
|
||||
* of a simple IPv4 address, or in the '/proc/net/tcp6' if an IPv6 address
|
||||
* is available.
|
||||
*/
|
||||
private static final String TCP_4_FILE_PATH = "/proc/net/tcp";
|
||||
private static final String TCP_6_FILE_PATH = "/proc/net/tcp6";
|
||||
/*
|
||||
* Two regular expressions that are able to extract valuable informations
|
||||
* from the two /proc/net/tcp* files. More specifically, there are three
|
||||
* fields that are extracted:
|
||||
* - address
|
||||
* - port
|
||||
* - PID
|
||||
*/
|
||||
private static final String TCP_6_PATTERN = "\\d+:\\s([0-9A-F]{32}):([0-9A-F]{4})\\s[0-9A-F]{32}:[0-9A-F]{4}\\s[0-9A-F]{2}\\s[0-9]{8}:[0-9]{8}\\s[0-9]{2}:[0-9]{8}\\s[0-9]{8}\\s+([0-9]+)";
|
||||
private static final String TCP_4_PATTERN = "\\d+:\\s([0-9A-F]{8}):([0-9A-F]{4})\\s[0-9A-F]{8}:[0-9A-F]{4}\\s[0-9A-F]{2}\\s[0-9A-F]{8}:[0-9A-F]{8}\\s[0-9]{2}:[0-9]{8}\\s[0-9A-F]{8}\\s+([0-9]+)";
|
||||
//sargo:/ $ cat /proc/net/tcp6
|
||||
// sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
// 0: 00000000000000000000000000000000:C36A 00000000000000000000000000000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 35059 1 0000000000000000 99 0 0 10 0
|
||||
// 1: 00000000000000000000000000000000:A64B 00000000000000000000000000000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 910009 1 0000000000000000 99 0 0 10 0
|
||||
/*
|
||||
* Optimises the socket lookup by checking if the connected network
|
||||
* interface has a 'valid' IPv6 address (a global address, not a link-local
|
||||
* one).
|
||||
*/
|
||||
private static boolean checkConnectedIfaces = true;
|
||||
// sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
// 0: 00000000:C368 00000000:0000 8A 00000000:00000000 00:00000000 00000000 1001 0 34999 1 0000000000000000 99 0 0 10 0
|
||||
|
||||
/**
|
||||
* The main method of the TCPSourceApp library. This method receives an
|
||||
* Android Context instance, which is used to access the PackageManager.
|
||||
* It parses the /proc/net/tcp* files, looking for a socket entry that
|
||||
* matches the given port. If it finds an entry, this method extracts the
|
||||
* PID value and it uses the PackageManager.getPackagesFromPid() method to
|
||||
* find the originating application.
|
||||
*
|
||||
* @param context a valid Android Context instance
|
||||
* @param daddr the (logical) address of the destination
|
||||
* @param dport the (logical) port of the destination
|
||||
* @return an AppDescriptor object, representing the found application; null
|
||||
* if no application could be found
|
||||
*/
|
||||
public static AppDescriptor getApplicationInfo(Context context, String saddr, int sport, String daddr, int dport) {
|
||||
|
||||
File tcp;
|
||||
BufferedReader reader;
|
||||
String line;
|
||||
StringBuilder builder;
|
||||
String content;
|
||||
|
||||
try {
|
||||
boolean hasIPv6 = true;
|
||||
|
||||
// if true, checks for a connected network interface with a valid
|
||||
// IPv4 / IPv6 address
|
||||
if (checkConnectedIfaces) {
|
||||
String ipv4Address = getIPAddress(true);
|
||||
String ipv6Address = getIPAddress(false);
|
||||
|
||||
hasIPv6 = (ipv6Address.length() > 0);
|
||||
}
|
||||
|
||||
tcp = new File(TCP_6_FILE_PATH);
|
||||
reader = new BufferedReader(new FileReader(tcp));
|
||||
builder = new StringBuilder();
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
|
||||
content = builder.toString();
|
||||
|
||||
Matcher m6 = Pattern.compile(TCP_6_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.UNIX_LINES | Pattern.DOTALL).matcher(content);
|
||||
|
||||
if (hasIPv6)
|
||||
while (m6.find()) {
|
||||
String addressEntry = m6.group(1);
|
||||
String portEntry = m6.group(2);
|
||||
int pidEntry = Integer.valueOf(m6.group(3));
|
||||
|
||||
if (Integer.parseInt(portEntry, 16) == dport) {
|
||||
PackageManager manager = context.getPackageManager();
|
||||
String[] packagesForUid = manager.getPackagesForUid(pidEntry);
|
||||
|
||||
if (packagesForUid != null) {
|
||||
String packageName = packagesForUid[0];
|
||||
PackageInfo pInfo = manager.getPackageInfo(packageName, 0);
|
||||
String version = pInfo.versionName;
|
||||
|
||||
return new AppDescriptor(pidEntry, packageName, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// From here, no connection with the given port could be found in the tcp6 file
|
||||
// So let's try the tcp (IPv4) one
|
||||
|
||||
try {
|
||||
tcp = new File(TCP_4_FILE_PATH);
|
||||
reader = new BufferedReader(new FileReader(tcp));
|
||||
builder = new StringBuilder();
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
builder.append(line);
|
||||
}
|
||||
|
||||
content = builder.toString();
|
||||
|
||||
Matcher m4 = Pattern.compile(TCP_4_PATTERN, Pattern.CASE_INSENSITIVE | Pattern.UNIX_LINES | Pattern.DOTALL).matcher(content);
|
||||
|
||||
while (m4.find()) {
|
||||
String addressEntry = m4.group(1);
|
||||
String portEntry = m4.group(2);
|
||||
int pidEntry = Integer.valueOf(m4.group(3));
|
||||
|
||||
if (Integer.parseInt(portEntry, 16) == dport) {
|
||||
PackageManager manager = context.getPackageManager();
|
||||
String[] packagesForUid = manager.getPackagesForUid(pidEntry);
|
||||
|
||||
if (packagesForUid != null) {
|
||||
String packageName = packagesForUid[0];
|
||||
PackageInfo pInfo = manager.getPackageInfo(packageName, 0);
|
||||
String version = pInfo.versionName;
|
||||
|
||||
return new AppDescriptor(pidEntry, packageName, version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NameNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressLint("DefaultLocale")
|
||||
public static String getIPAddress(boolean useIPv4) throws SocketException {
|
||||
|
||||
List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
|
||||
|
||||
for (NetworkInterface intf : interfaces) {
|
||||
List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
|
||||
|
||||
for (InetAddress addr : addrs) {
|
||||
if (!addr.isLoopbackAddress()) {
|
||||
String sAddr = addr.getHostAddress().toUpperCase();
|
||||
|
||||
boolean isIPv4 = addr instanceof Inet4Address;
|
||||
|
||||
if (useIPv4) {
|
||||
if (isIPv4)
|
||||
return sAddr;
|
||||
} else {
|
||||
if (!isIPv4) {
|
||||
if (sAddr.startsWith("fe80") || sAddr.startsWith("FE80")) // skipping link-local addresses
|
||||
continue;
|
||||
|
||||
int delim = sAddr.indexOf('%'); // drop ip6 port suffix
|
||||
return delim < 0 ? sAddr : sAddr.substring(0, delim);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the connected interfaces optimisation.
|
||||
*/
|
||||
public static void setCheckConnectedIfaces(boolean value) {
|
||||
checkConnectedIfaces = value;
|
||||
}
|
||||
|
||||
/*
|
||||
* This class represents an Android application. Each application is
|
||||
* uniquely identified by its package name (e.g. com.megadevs.tcpsourceapp)
|
||||
* and its version (e.g. 1.0).
|
||||
*/
|
||||
public static class AppDescriptor {
|
||||
|
||||
private String packageName;
|
||||
private String version;
|
||||
private int uid;
|
||||
|
||||
public AppDescriptor(int uid, String pName, String ver) {
|
||||
this.uid = uid;
|
||||
packageName = pName;
|
||||
version = ver;
|
||||
}
|
||||
|
||||
public int getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override of the 'equals' method, in order to have a proper
|
||||
* comparison between two AppDescriptor objects.
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
||||
if (o instanceof AppDescriptor) {
|
||||
boolean c1 = ((AppDescriptor) o).packageName.compareTo(this.packageName) == 0;
|
||||
boolean c2 = ((AppDescriptor) o).version.compareTo(this.version) == 0;
|
||||
|
||||
return c1 && c2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
package org.torproject.android.service.util;
|
||||
|
||||
import org.torproject.android.service.TorServiceConstants;
|
||||
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
public class TorServiceUtils implements TorServiceConstants {
|
||||
|
||||
public static boolean isPortOpen(final String ip, final int port, final int timeout) {
|
||||
try {
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(ip, port), timeout);
|
||||
socket.close();
|
||||
return true;
|
||||
} catch (ConnectException ce) {
|
||||
//ce.printStackTrace();
|
||||
return false;
|
||||
} catch (Exception ex) {
|
||||
//ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
|
||||
package org.torproject.android.service.util;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class Utils {
|
||||
|
||||
|
||||
public static String readString(InputStream stream) {
|
||||
String line;
|
||||
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the log file text
|
||||
*/
|
||||
public static String loadTextFile(String path) {
|
||||
String line;
|
||||
|
||||
StringBuffer out = new StringBuffer();
|
||||
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader((new FileReader(new File(path))));
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
out.append(line);
|
||||
out.append('\n');
|
||||
|
||||
}
|
||||
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Load the log file text
|
||||
*/
|
||||
public static boolean saveTextFile(String path, String contents) {
|
||||
|
||||
try {
|
||||
|
||||
FileWriter writer = new FileWriter(path, false);
|
||||
writer.write(contents);
|
||||
|
||||
writer.close();
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
} catch (IOException e) {
|
||||
// Log.d(TAG, "error writing file: " + path, e);
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Zips a file at a location and places the resulting zip file at the toLocation
|
||||
* Example: zipFileAtPath("downloads/myfolder", "downloads/myFolder.zip");
|
||||
*/
|
||||
|
||||
public static boolean zipFileAtPath(String sourcePath, String toLocation) {
|
||||
final int BUFFER = 2048;
|
||||
|
||||
File sourceFile = new File(sourcePath);
|
||||
try {
|
||||
BufferedInputStream origin;
|
||||
FileOutputStream dest = new FileOutputStream(toLocation);
|
||||
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
|
||||
dest));
|
||||
if (sourceFile.isDirectory()) {
|
||||
zipSubFolder(out, sourceFile, sourceFile.getParent().length());
|
||||
} else {
|
||||
byte[] data = new byte[BUFFER];
|
||||
FileInputStream fi = new FileInputStream(sourcePath);
|
||||
origin = new BufferedInputStream(fi, BUFFER);
|
||||
ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
|
||||
entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
|
||||
out.putNextEntry(entry);
|
||||
int count;
|
||||
while ((count = origin.read(data, 0, BUFFER)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
}
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Zips a subfolder
|
||||
*
|
||||
*/
|
||||
|
||||
private static void zipSubFolder(ZipOutputStream out, File folder,
|
||||
int basePathLength) throws IOException {
|
||||
|
||||
final int BUFFER = 2048;
|
||||
|
||||
File[] fileList = folder.listFiles();
|
||||
BufferedInputStream origin;
|
||||
for (File file : fileList) {
|
||||
if (file.isDirectory()) {
|
||||
zipSubFolder(out, file, basePathLength);
|
||||
} else {
|
||||
byte[] data = new byte[BUFFER];
|
||||
String unmodifiedFilePath = file.getPath();
|
||||
String relativePath = unmodifiedFilePath
|
||||
.substring(basePathLength);
|
||||
FileInputStream fi = new FileInputStream(unmodifiedFilePath);
|
||||
origin = new BufferedInputStream(fi, BUFFER);
|
||||
ZipEntry entry = new ZipEntry(relativePath);
|
||||
entry.setTime(file.lastModified()); // to keep modification time after unzipping
|
||||
out.putNextEntry(entry);
|
||||
int count;
|
||||
while ((count = origin.read(data, 0, BUFFER)) != -1) {
|
||||
out.write(data, 0, count);
|
||||
}
|
||||
origin.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gets the last path component
|
||||
*
|
||||
* Example: getLastPathComponent("downloads/example/fileToZip");
|
||||
* Result: "fileToZip"
|
||||
*/
|
||||
public static String getLastPathComponent(String filePath) {
|
||||
String[] segments = filePath.split("/");
|
||||
if (segments.length == 0)
|
||||
return "";
|
||||
return segments[segments.length - 1];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.torproject.android.service.vpn;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.net.VpnService;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.runjva.sourceforge.jsocks.protocol.ProxyServer;
|
||||
import com.runjva.sourceforge.jsocks.server.ServerAuthenticatorNone;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.torproject.android.proxy.OrbotService;
|
||||
import org.torproject.android.service.OrbotConstants;
|
||||
import org.torproject.android.service.R;
|
||||
import org.torproject.android.service.TorServiceConstants;
|
||||
import org.torproject.android.service.util.CustomNativeLoader;
|
||||
import org.torproject.android.service.util.Prefs;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static org.torproject.android.service.TorServiceConstants.ACTION_START;
|
||||
import static org.torproject.android.service.TorServiceConstants.ACTION_START_VPN;
|
||||
import static org.torproject.android.service.TorServiceConstants.ACTION_STOP_VPN;
|
||||
|
||||
public class OrbotVpnManager implements Handler.Callback {
|
||||
private static final String TAG = "OrbotVpnService";
|
||||
private final static int VPN_MTU = 1500;
|
||||
private final static boolean mIsLollipop = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
|
||||
private final static String PDNSD_BIN = "pdnsd";
|
||||
public static int sSocksProxyServerPort = -1;
|
||||
public static String sSocksProxyLocalhost = null;
|
||||
boolean isStarted = false;
|
||||
File filePdnsPid;
|
||||
private Thread mThreadVPN;
|
||||
private String mSessionName = "OrbotVPN";
|
||||
private ParcelFileDescriptor mInterface;
|
||||
private int mTorSocks = -1;
|
||||
private int mTorDns = -1;
|
||||
private int pdnsdPort = 8091;
|
||||
private ProxyServer mSocksProxyServer;
|
||||
private File filePdnsd;
|
||||
private boolean isRestart = false;
|
||||
private VpnService mService;
|
||||
|
||||
public OrbotVpnManager(VpnService service) throws IOException, TimeoutException {
|
||||
mService = service;
|
||||
filePdnsd = CustomNativeLoader.loadNativeBinary(service.getApplicationContext(), PDNSD_BIN, new File(service.getFilesDir(), PDNSD_BIN));
|
||||
Tun2Socks.init();
|
||||
}
|
||||
|
||||
public static File makePdnsdConf(Context context, File fileDir, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws IOException {
|
||||
String conf = String.format(context.getString(R.string.pdnsd_conf), torDnsHost, torDnsPort, fileDir.getCanonicalPath(), pdnsdHost, pdnsdPort);
|
||||
|
||||
Log.d(TAG, "pdsnd conf:" + conf);
|
||||
|
||||
File fPid = new File(fileDir, pdnsdPort + "pdnsd.conf");
|
||||
|
||||
if (fPid.exists()) {
|
||||
fPid.delete();
|
||||
}
|
||||
|
||||
FileOutputStream fos = new FileOutputStream(fPid, false);
|
||||
PrintStream ps = new PrintStream(fos);
|
||||
ps.print(conf);
|
||||
ps.close();
|
||||
|
||||
File cache = new File(fileDir, "pdnsd.cache");
|
||||
|
||||
if (!cache.exists()) {
|
||||
try {
|
||||
cache.createNewFile();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return fPid;
|
||||
}
|
||||
|
||||
public int handleIntent(VpnService.Builder builder, Intent intent) {
|
||||
if (intent != null) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (!TextUtils.isEmpty(action)) {
|
||||
if (action.equals(ACTION_START_VPN) || action.equals(ACTION_START)) {
|
||||
Log.d(TAG, "starting VPN");
|
||||
|
||||
isStarted = true;
|
||||
|
||||
// Stop the previous session by interrupting the thread.
|
||||
if (mThreadVPN != null && mThreadVPN.isAlive())
|
||||
stopVPN();
|
||||
|
||||
if (mTorSocks != -1) {
|
||||
if (!mIsLollipop) {
|
||||
startSocksBypass();
|
||||
}
|
||||
|
||||
setupTun2Socks(builder);
|
||||
}
|
||||
|
||||
} else if (action.equals(ACTION_STOP_VPN)) {
|
||||
isStarted = false;
|
||||
|
||||
Log.d(TAG, "stopping VPN");
|
||||
|
||||
stopVPN();
|
||||
} else if (action.equals(TorServiceConstants.LOCAL_ACTION_PORTS)) {
|
||||
Log.d(TAG, "setting VPN ports");
|
||||
|
||||
int torSocks = intent.getIntExtra(OrbotService.EXTRA_SOCKS_PROXY_PORT, -1);
|
||||
int torDns = intent.getIntExtra(OrbotService.EXTRA_DNS_PORT, -1);
|
||||
|
||||
//if running, we need to restart
|
||||
if ((torSocks != mTorSocks || torDns != mTorDns)) {
|
||||
|
||||
mTorSocks = torSocks;
|
||||
mTorDns = torDns;
|
||||
|
||||
if (!mIsLollipop) {
|
||||
stopSocksBypass();
|
||||
startSocksBypass();
|
||||
}
|
||||
|
||||
setupTun2Socks(builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return Service.START_STICKY;
|
||||
}
|
||||
|
||||
private void startSocksBypass() {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
|
||||
//generate the proxy port that the
|
||||
if (sSocksProxyServerPort == -1) {
|
||||
try {
|
||||
|
||||
sSocksProxyLocalhost = "127.0.0.1";// InetAddress.getLocalHost().getHostAddress();
|
||||
sSocksProxyServerPort = (int) ((Math.random() * 1000) + 10000);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Unable to access localhost", e);
|
||||
throw new RuntimeException("Unable to access localhost: " + e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (mSocksProxyServer != null) {
|
||||
stopSocksBypass();
|
||||
}
|
||||
|
||||
try {
|
||||
mSocksProxyServer = new ProxyServer(new ServerAuthenticatorNone(null, null));
|
||||
ProxyServer.setVpnService(mService);
|
||||
mSocksProxyServer.start(sSocksProxyServerPort, 5, InetAddress.getLocalHost());
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "error getting host", e);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
private synchronized void stopSocksBypass() {
|
||||
if (mSocksProxyServer != null) {
|
||||
mSocksProxyServer.stop();
|
||||
mSocksProxyServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void stopVPN() {
|
||||
if (mIsLollipop)
|
||||
stopSocksBypass();
|
||||
|
||||
Tun2Socks.Stop();
|
||||
|
||||
if (mInterface != null) {
|
||||
try {
|
||||
Log.d(TAG, "closing interface, destroying VPN interface");
|
||||
|
||||
mInterface.close();
|
||||
mInterface = null;
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "error stopping tun2socks", e);
|
||||
} catch (Error e) {
|
||||
Log.d(TAG, "error stopping tun2socks", e);
|
||||
}
|
||||
}
|
||||
stopDns();
|
||||
mThreadVPN = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message message) {
|
||||
if (message != null) {
|
||||
Toast.makeText(mService, message.what, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private synchronized void setupTun2Socks(final VpnService.Builder builder) {
|
||||
if (mInterface != null) //stop tun2socks now to give it time to clean up
|
||||
{
|
||||
isRestart = true;
|
||||
Tun2Socks.Stop();
|
||||
|
||||
stopDns();
|
||||
|
||||
}
|
||||
|
||||
mThreadVPN = new Thread() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
if (isRestart) {
|
||||
Log.d(TAG, "is a restart... let's wait for a few seconds");
|
||||
Thread.sleep(3000);
|
||||
}
|
||||
|
||||
final String vpnName = "OrbotVPN";
|
||||
final String localhost = "127.0.0.1";
|
||||
|
||||
final String virtualGateway = "192.168.200.1";
|
||||
final String virtualIP = "192.168.200.2";
|
||||
final String virtualNetMask = "255.255.255.0";
|
||||
final String dummyDNS = "1.1.1.1"; //this is intercepted by the tun2socks library, but we must put in a valid DNS to start
|
||||
final String defaultRoute = "0.0.0.0";
|
||||
|
||||
final String localSocks = localhost + ':' + mTorSocks;
|
||||
|
||||
builder.setMtu(VPN_MTU);
|
||||
builder.addAddress(virtualGateway, 32);
|
||||
|
||||
builder.setSession(vpnName);
|
||||
|
||||
//route all traffic through VPN (we might offer country specific exclude lists in the future)
|
||||
builder.addRoute(defaultRoute, 0);
|
||||
|
||||
builder.addDnsServer(dummyDNS);
|
||||
builder.addRoute(dummyDNS, 32);
|
||||
|
||||
//handle ipv6
|
||||
//builder.addAddress("fdfe:dcba:9876::1", 126);
|
||||
//builder.addRoute("::", 0);
|
||||
|
||||
if (mIsLollipop)
|
||||
doLollipopAppRouting(builder);
|
||||
|
||||
// Create a new interface using the builder and save the parameters.
|
||||
ParcelFileDescriptor newInterface = builder.setSession(mSessionName)
|
||||
.setConfigureIntent(null) // previously this was set to a null member variable
|
||||
.establish();
|
||||
|
||||
if (mInterface != null) {
|
||||
Log.d(TAG, "Stopping existing VPN interface");
|
||||
mInterface.close();
|
||||
mInterface = null;
|
||||
}
|
||||
|
||||
mInterface = newInterface;
|
||||
|
||||
isRestart = false;
|
||||
|
||||
//start PDNSD daemon pointing to actual DNS
|
||||
if (filePdnsd != null) {
|
||||
|
||||
pdnsdPort++;
|
||||
startDNS(filePdnsd.getCanonicalPath(), localhost, mTorDns, virtualGateway, pdnsdPort);
|
||||
final boolean localDnsTransparentProxy = true;
|
||||
|
||||
Tun2Socks.Start(mService, mInterface, VPN_MTU, virtualIP, virtualNetMask, localSocks, virtualGateway + ":" + pdnsdPort, localDnsTransparentProxy);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.d(TAG, "tun2Socks has stopped", e);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
mThreadVPN.start();
|
||||
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void doLollipopAppRouting(VpnService.Builder builder) throws NameNotFoundException {
|
||||
SharedPreferences prefs = Prefs.getSharedPrefs(mService.getApplicationContext());
|
||||
ArrayList<TorifiedApp> apps = TorifiedApp.getApps(mService, prefs);
|
||||
|
||||
|
||||
boolean perAppEnabled = false;
|
||||
|
||||
for (TorifiedApp app : apps) {
|
||||
if (app.isTorified() && (!app.getPackageName().equals(mService.getPackageName()))) {
|
||||
if (prefs.getBoolean(app.getPackageName() + OrbotConstants.APP_TOR_KEY, true)) {
|
||||
|
||||
builder.addAllowedApplication(app.getPackageName());
|
||||
|
||||
}
|
||||
|
||||
perAppEnabled = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!perAppEnabled)
|
||||
builder.addDisallowedApplication(mService.getPackageName());
|
||||
|
||||
}
|
||||
|
||||
private void startDNS(String pdnsPath, String torDnsHost, int torDnsPort, String pdnsdHost, int pdnsdPort) throws IOException, TimeoutException {
|
||||
|
||||
File fileConf = makePdnsdConf(mService, mService.getFilesDir(), torDnsHost, torDnsPort, pdnsdHost, pdnsdPort);
|
||||
|
||||
String[] cmdString = {pdnsPath, "-c", fileConf.toString(), "-g", "-v2"};
|
||||
ProcessBuilder pb = new ProcessBuilder(cmdString);
|
||||
pb.redirectErrorStream(true);
|
||||
Process proc = pb.start();
|
||||
try {
|
||||
proc.waitFor();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
|
||||
Log.i(TAG, "PDNSD: " + proc.exitValue());
|
||||
|
||||
if (proc.exitValue() != 0) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
Log.d(TAG, "pdnsd: " + line);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private boolean stopDns() {
|
||||
if (filePdnsPid != null && filePdnsPid.exists()) {
|
||||
List<String> lines;
|
||||
try {
|
||||
lines = IOUtils.readLines(new FileReader(filePdnsPid));
|
||||
String dnsPid = lines.get(0);
|
||||
VpnUtils.killProcess(dnsPid, "");
|
||||
filePdnsPid.delete();
|
||||
filePdnsPid = null;
|
||||
} catch (Exception e) {
|
||||
Log.e("OrbotVPN", "error killing dns process", e);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return isStarted;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,260 @@
|
|||
package org.torproject.android.service.vpn;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import static org.torproject.android.service.vpn.VpnPrefs.PREFS_KEY_TORIFIED;
|
||||
|
||||
public class TorifiedApp implements Comparable {
|
||||
|
||||
private boolean enabled;
|
||||
private int uid;
|
||||
private String username;
|
||||
private String procname;
|
||||
private String name;
|
||||
private Drawable icon;
|
||||
private String packageName;
|
||||
|
||||
private boolean torified = false;
|
||||
private boolean usesInternet = false;
|
||||
private int[] enabledPorts;
|
||||
|
||||
public static ArrayList<TorifiedApp> getApps(Context context, SharedPreferences prefs) {
|
||||
|
||||
String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
|
||||
String[] tordApps;
|
||||
|
||||
StringTokenizer st = new StringTokenizer(tordAppString, "|");
|
||||
tordApps = new String[st.countTokens()];
|
||||
int tordIdx = 0;
|
||||
while (st.hasMoreTokens()) {
|
||||
tordApps[tordIdx++] = st.nextToken();
|
||||
}
|
||||
|
||||
Arrays.sort(tordApps);
|
||||
|
||||
//else load the apps up
|
||||
PackageManager pMgr = context.getPackageManager();
|
||||
|
||||
List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
|
||||
|
||||
Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
|
||||
|
||||
ArrayList<TorifiedApp> apps = new ArrayList<>();
|
||||
|
||||
ApplicationInfo aInfo;
|
||||
|
||||
int appIdx = 0;
|
||||
TorifiedApp app;
|
||||
|
||||
while (itAppInfo.hasNext()) {
|
||||
aInfo = itAppInfo.next();
|
||||
|
||||
app = new TorifiedApp();
|
||||
|
||||
try {
|
||||
PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS);
|
||||
|
||||
if (pInfo != null && pInfo.requestedPermissions != null) {
|
||||
for (String permInfo : pInfo.requestedPermissions) {
|
||||
if (permInfo.equals(Manifest.permission.INTERNET)) {
|
||||
app.setUsesInternet(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1) {
|
||||
//System app
|
||||
app.setUsesInternet(true);
|
||||
}
|
||||
|
||||
|
||||
if (!app.usesInternet())
|
||||
continue;
|
||||
else {
|
||||
apps.add(app);
|
||||
}
|
||||
|
||||
|
||||
app.setEnabled(aInfo.enabled);
|
||||
app.setUid(aInfo.uid);
|
||||
app.setUsername(pMgr.getNameForUid(app.getUid()));
|
||||
app.setProcname(aInfo.processName);
|
||||
app.setPackageName(aInfo.packageName);
|
||||
|
||||
try {
|
||||
app.setName(pMgr.getApplicationLabel(aInfo).toString());
|
||||
} catch (Exception e) {
|
||||
app.setName(aInfo.packageName);
|
||||
}
|
||||
|
||||
|
||||
//app.setIcon(pMgr.getApplicationIcon(aInfo));
|
||||
|
||||
// check if this application is allowed
|
||||
if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) {
|
||||
app.setTorified(true);
|
||||
} else {
|
||||
app.setTorified(false);
|
||||
}
|
||||
|
||||
appIdx++;
|
||||
}
|
||||
|
||||
Collections.sort(apps);
|
||||
|
||||
return apps;
|
||||
}
|
||||
|
||||
public boolean usesInternet() {
|
||||
return usesInternet;
|
||||
}
|
||||
|
||||
public void setUsesInternet(boolean usesInternet) {
|
||||
this.usesInternet = usesInternet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the torified
|
||||
*/
|
||||
public boolean isTorified() {
|
||||
return torified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param torified the torified to set
|
||||
*/
|
||||
public void setTorified(boolean torified) {
|
||||
this.torified = torified;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabledPorts
|
||||
*/
|
||||
public int[] getEnabledPorts() {
|
||||
return enabledPorts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enabledPorts the enabledPorts to set
|
||||
*/
|
||||
public void setEnabledPorts(int[] enabledPorts) {
|
||||
this.enabledPorts = enabledPorts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param enabled the enabled to set
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the uid
|
||||
*/
|
||||
public int getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param uid the uid to set
|
||||
*/
|
||||
public void setUid(int uid) {
|
||||
this.uid = uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the username
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param username the username to set
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the procname
|
||||
*/
|
||||
public String getProcname() {
|
||||
return procname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param procname the procname to set
|
||||
*/
|
||||
public void setProcname(String procname) {
|
||||
this.procname = procname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Drawable getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(Drawable icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object another) {
|
||||
return this.toString().compareToIgnoreCase(another.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package org.torproject.android.service.vpn;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013, Psiphon Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.util.Log;
|
||||
|
||||
import org.torproject.android.service.util.TCPSourceApp;
|
||||
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static android.content.Context.CONNECTIVITY_SERVICE;
|
||||
|
||||
public class Tun2Socks {
|
||||
|
||||
private static final String TAG = Tun2Socks.class.getSimpleName();
|
||||
private static final boolean LOGD = true;
|
||||
|
||||
private static ParcelFileDescriptor mVpnInterfaceFileDescriptor;
|
||||
private static int mVpnInterfaceMTU;
|
||||
private static String mVpnIpAddress;
|
||||
private static String mVpnNetMask;
|
||||
private static String mSocksServerAddress;
|
||||
private static String mUdpgwServerAddress;
|
||||
private static boolean mUdpgwTransparentDNS;
|
||||
private static HashMap<Integer, String> mAppUidBlacklist = new HashMap<>();
|
||||
|
||||
static {
|
||||
System.loadLibrary("tun2socks");
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
}
|
||||
// Note: this class isn't a singleton, but you can't run more
|
||||
// than one instance due to the use of global state (the lwip
|
||||
// module, etc.) in the native code.
|
||||
|
||||
public static void Start(
|
||||
Context context,
|
||||
ParcelFileDescriptor vpnInterfaceFileDescriptor,
|
||||
int vpnInterfaceMTU,
|
||||
String vpnIpAddress,
|
||||
String vpnNetMask,
|
||||
String socksServerAddress,
|
||||
String udpgwServerAddress,
|
||||
boolean udpgwTransparentDNS) {
|
||||
|
||||
mVpnInterfaceFileDescriptor = vpnInterfaceFileDescriptor;
|
||||
mVpnInterfaceMTU = vpnInterfaceMTU;
|
||||
mVpnIpAddress = vpnIpAddress;
|
||||
mVpnNetMask = vpnNetMask;
|
||||
mSocksServerAddress = socksServerAddress;
|
||||
mUdpgwServerAddress = udpgwServerAddress;
|
||||
mUdpgwTransparentDNS = udpgwTransparentDNS;
|
||||
|
||||
if (mVpnInterfaceFileDescriptor != null)
|
||||
runTun2Socks(
|
||||
mVpnInterfaceFileDescriptor.detachFd(),
|
||||
mVpnInterfaceMTU,
|
||||
mVpnIpAddress,
|
||||
mVpnNetMask,
|
||||
mSocksServerAddress,
|
||||
mUdpgwServerAddress,
|
||||
mUdpgwTransparentDNS ? 1 : 0);
|
||||
}
|
||||
|
||||
public static void Stop() {
|
||||
|
||||
terminateTun2Socks();
|
||||
|
||||
}
|
||||
|
||||
public static void logTun2Socks(
|
||||
String level,
|
||||
String channel,
|
||||
String msg) {
|
||||
String logMsg = level + "(" + channel + "): " + msg;
|
||||
if (0 == level.compareTo("ERROR")) {
|
||||
Log.e(TAG, logMsg);
|
||||
} else {
|
||||
if (LOGD) Log.d(TAG, logMsg);
|
||||
}
|
||||
}
|
||||
|
||||
private native static int runTun2Socks(
|
||||
int vpnInterfaceFileDescriptor,
|
||||
int vpnInterfaceMTU,
|
||||
String vpnIpAddress,
|
||||
String vpnNetMask,
|
||||
String socksServerAddress,
|
||||
String udpgwServerAddress,
|
||||
int udpgwTransparentDNS);
|
||||
|
||||
private native static void terminateTun2Socks();
|
||||
|
||||
public static boolean checkIsAllowed(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
return isAllowedQ(context, protocol, sourceAddr, sourcePort, destAddr, destPort);
|
||||
} else
|
||||
return isAllowed(context, protocol, sourceAddr, sourcePort, destAddr, destPort);
|
||||
}
|
||||
|
||||
public static boolean isAllowed(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
|
||||
|
||||
TCPSourceApp.AppDescriptor aInfo = TCPSourceApp.getApplicationInfo(context, sourceAddr, sourcePort, destAddr, destPort);
|
||||
|
||||
if (aInfo != null) {
|
||||
int uid = aInfo.getUid();
|
||||
return mAppUidBlacklist.containsKey(uid);
|
||||
} else
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.Q)
|
||||
public static boolean isAllowedQ(Context context, int protocol, String sourceAddr, int sourcePort, String destAddr, int destPort) {
|
||||
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
|
||||
if (cm == null)
|
||||
return false;
|
||||
|
||||
InetSocketAddress local = new InetSocketAddress(sourceAddr, sourcePort);
|
||||
InetSocketAddress remote = new InetSocketAddress(destAddr, destPort);
|
||||
|
||||
int uid = cm.getConnectionOwnerUid(protocol, local, remote);
|
||||
return mAppUidBlacklist.containsKey(uid);
|
||||
}
|
||||
|
||||
public static void setBlacklist(HashMap<Integer, String> appUidBlacklist) {
|
||||
mAppUidBlacklist = appUidBlacklist;
|
||||
}
|
||||
|
||||
public static void clearBlacklist() {
|
||||
mAppUidBlacklist.clear();
|
||||
}
|
||||
|
||||
public static void addToBlacklist(int uid, String pkgId) {
|
||||
mAppUidBlacklist.put(uid, pkgId);
|
||||
}
|
||||
|
||||
public static void removeFromBlacklist(int uid) {
|
||||
mAppUidBlacklist.remove(uid);
|
||||
}
|
||||
|
||||
public interface IProtectSocket {
|
||||
boolean doVpnProtect(Socket socket);
|
||||
|
||||
boolean doVpnProtect(DatagramSocket socket);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package org.torproject.android.service.vpn;
|
||||
|
||||
public interface VpnPrefs {
|
||||
|
||||
String PREFS_DNS_PORT = "PREFS_DNS_PORT";
|
||||
|
||||
String PREFS_KEY_TORIFIED = "PrefTord";
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package org.torproject.android.service.vpn;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.List;
|
||||
|
||||
import static java.lang.Runtime.getRuntime;
|
||||
|
||||
public class VpnUtils {
|
||||
|
||||
public static int findProcessId(String command) throws IOException {
|
||||
|
||||
String[] cmds = {"ps -ef", "ps -A", "toolbox ps"};
|
||||
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
Process procPs = getRuntime().exec(cmds[i]);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(procPs.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (!line.contains("PID") && line.contains(command)) {
|
||||
String[] lineParts = line.split("\\s+");
|
||||
try {
|
||||
return Integer.parseInt(lineParts[1]); //for most devices it is the second
|
||||
} catch (NumberFormatException e) {
|
||||
return Integer.parseInt(lineParts[0]); //but for samsungs it is the first
|
||||
} finally {
|
||||
try {
|
||||
procPs.destroy();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void killProcess(File fileProcBin) throws Exception {
|
||||
killProcess(fileProcBin, "-9"); // this is -KILL
|
||||
}
|
||||
|
||||
public static int killProcess(File fileProcBin, String signal) throws Exception {
|
||||
|
||||
int procId = -1;
|
||||
int killAttempts = 0;
|
||||
|
||||
while ((procId = findProcessId(fileProcBin.getName())) != -1) {
|
||||
killAttempts++;
|
||||
String pidString = String.valueOf(procId);
|
||||
boolean itBeDead = killProcess(pidString, signal);
|
||||
|
||||
if (!itBeDead) {
|
||||
|
||||
String[] cmds = {"", "busybox ", "toolbox "};
|
||||
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
|
||||
Process proc;
|
||||
|
||||
try {
|
||||
proc = getRuntime().exec(cmds[i] + "killall " + signal + " " + fileProcBin.getName
|
||||
());
|
||||
int exitValue = proc.waitFor();
|
||||
if (exitValue == 0)
|
||||
break;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
try {
|
||||
proc = getRuntime().exec(cmds[i] + "killall " + signal + " " + fileProcBin.getCanonicalPath());
|
||||
int exitValue = proc.waitFor();
|
||||
if (exitValue == 0)
|
||||
break;
|
||||
|
||||
} catch (IOException ioe) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
// ignored
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (killAttempts > 4)
|
||||
throw new Exception("Cannot kill: " + fileProcBin.getAbsolutePath());
|
||||
}
|
||||
|
||||
return procId;
|
||||
}
|
||||
|
||||
public static boolean killProcess(String pidString, String signal) throws Exception {
|
||||
|
||||
String[] cmds = {"", "toolbox ", "busybox "};
|
||||
|
||||
for (int i = 0; i < cmds.length; i++) {
|
||||
try {
|
||||
Process proc = getRuntime().exec(cmds[i] + "kill " + signal + " " + pidString);
|
||||
int exitVal = proc.waitFor();
|
||||
List<String> lineErrors = IOUtils.readLines(proc.getErrorStream());
|
||||
List<String> lineInputs = IOUtils.readLines(proc.getInputStream());
|
||||
|
||||
if (exitVal != 0) {
|
||||
Log.d("Orbot.killProcess", "exit=" + exitVal);
|
||||
for (String line : lineErrors)
|
||||
Log.d("Orbot.killProcess", line);
|
||||
|
||||
for (String line : lineInputs)
|
||||
Log.d("Orbot.killProcess", line);
|
||||
|
||||
} else {
|
||||
//it worked, let's exit
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} catch (IOException ioe) {
|
||||
Log.e("Orbot.killprcess", "error killing process: " + pidString, ioe);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
public class logRowModel {
|
||||
/*Private Variables*/
|
|
@ -1,4 +1,4 @@
|
|||
package org.torproject.android.proxy.wrapper;
|
||||
package org.torproject.android.service.wrapper;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
|
@ -5,4 +5,3 @@ obfs4 37.218.240.34:40035 88CD36D45A35271963EF82E511C8827A24730913 cert=eGXYfWOD
|
|||
obfs4 37.218.245.14:38224 D9A82D2F9C2F65A18407B1D2B764F130847F8B5D cert=bjRaMrr1BRiAW8IE9U5z27fQaYgOhX1UCmOpg2pFpoMvo6ZgQMzLsaTzzQNTlm7hNcb+Sg iat-mode=0
|
||||
obfs4 85.31.186.98:443 011F2599C0E9B27EE74B353155E244813763C3E5 cert=ayq0XzCwhpdysn5o0EyDUbmSOx3X/oTEbzDMvczHOdBJKlvIdHHLJGkZARtT4dcBFArPPg iat-mode=0
|
||||
meek_lite 0.0.2.0:2 97700DFE9F483596DDA6264C4D7DF7641E1E39CE url=https://meek.azureedge.net/ front=ajax.aspnetcdn.com
|
||||
snowflake 192.0.2.3:1
|
|
@ -14,13 +14,10 @@
|
|||
<string name="something_bad_happened">Something bad happened. Check the log</string>
|
||||
<string name="unable_to_read_hidden_service_name">unable to read onion service name</string>
|
||||
<string name="unable_to_start_tor">Unable to start Tor:</string>
|
||||
<string name="waiting_for_control_port">Waiting for control port...</string>
|
||||
<string name="connecting_to_control_port">Connecting to control port:</string>
|
||||
|
||||
<string name="newnym">You\'ve switched to a new Tor identity!</string>
|
||||
|
||||
<string name="updating_settings_in_tor_service">updating settings in Tor service</string>
|
||||
|
||||
<string name="menu_new_identity">New Identity</string>
|
||||
<string name="no_network_connectivity_putting_tor_to_sleep_">No network connectivity. Putting Tor to sleep…</string>
|
||||
<string name="network_connectivity_is_good_waking_tor_up_">Network connectivity is good. Waking Tor up…</string>
|
||||
</resources>
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package org.torproject.android.service;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* To work on unit tests, switch the Test Artifact in the Build Variants view.
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue