Skip to content

Commit

Permalink
Add DappBrowser Whitelists (#3412)
Browse files Browse the repository at this point in the history
- Add DappBrowser protection for browsing non-whitelisted sites.
- Lock DeveloperOverride with warning page.
  • Loading branch information
JamesSmartCell authored Dec 1, 2024
1 parent aa109b9 commit 095038f
Show file tree
Hide file tree
Showing 21 changed files with 209 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import static com.alphawallet.app.util.Helper.waitUntilLoaded;
import static junit.framework.TestCase.assertTrue;

import static org.hamcrest.core.IsNot.not;

import android.view.KeyEvent;

import androidx.annotation.NonNull;
Expand All @@ -35,8 +33,8 @@

public class DappBrowserTest extends BaseE2ETest
{
private static final String DEFAULT_HOME_PAGE = "https://courses.cs.washington.edu/courses/cse373/99sp/assignments/hw2/test1.html";
private static final String URL_DAPP = "http://web.simmons.edu/~grovesd/comm244/notes/week3/html-test-page.html";
private static final String DEFAULT_HOME_PAGE = "https://tlink.store/tapp?chain=84532&contract=0xb02082b18f74ab3853b6a11e5f487be4322167db&tokenId=6";
private static final String URL_DAPP = "https://rarible.com/explore/all/collections";

@Override
@Before
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,22 @@
android:usesCleartextTraffic="true"
tools:replace="android:name, android:theme, android:allowBackup">


<receiver android:name=".entity.HomeReceiver"
android:exported="false">
<intent-filter>
<action android:name="C.REQUEST_NOTIFICATION_ACCESS" />
<action android:name="C.BACKUP_WALLET_SUCCESS" />
</intent-filter>
</receiver>

<receiver android:name=".entity.FinishReceiver"
android:exported="false">
<intent-filter>
<action android:name="C.PRUNE_ACTIVITY" />
</intent-filter>
</receiver>

<activity
android:name=".ui.HomeActivity"
android:exported="true"
Expand Down
12 changes: 5 additions & 7 deletions app/src/main/assets/dapps_list.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
[
{"name": "TokenScript", "description": "Smart Token Labs TokenScript Viewer", "url": "https://viewer.tokenscript.org/", "category": "Infrastructure"},
{"name": "SmartLayer", "description": "Smart Token Labs Smart Layer Network", "url": "https://smartlayer.network", "category": "Infrastructure"},
{"name": "TLink", "description": "Smart Token Labs TLink", "url": "https://tlink.store/", "category": "Infrastructure"},
{"name": "X", "description": "Social Media", "url": "https://x.com", "category": "Social Media"},
{"name": "Aave", "description": "A decentralized non-custodial liquidity protocol where users can participate as depositors or borrowers", "url": "https://app.aave.com/", "category": "Finance"},
{"name": "Tbull", "description": "A Utility Token on Binance Smart Chain for Payments for Services", "url": "tbull.live", "category": "Utility"},
{"name": "Rare Coin", "description": "Free Crypto Faucet & Yield Farming", "url": "make.rare.claims", "category": "Tool"},
{"name": "Tbull", "description": "A Utility Token on Binance Smart Chain for Payments for Services", "url": "https://tbull.live", "category": "Utility"},
{"name": "Rare Coin", "description": "Free Crypto Faucet & Yield Farming", "url": "https://make.rare.claims", "category": "Tool"},
{"name": "DeFiBox", "description": "one-stop DeFi asset, data and protocols aggregation platform", "url": "https://www.defibox.com/index?utm_source=2189969", "category": "Tool"},
{"name": "Rarible", "description": "Peer-to-peer marketplace for scarce digital goods", "url": "https://rarible.com/", "category": "Marketplace"},
{"name": "TokenSets", "description": "Enhance your portfolio with automated asset management strategies.", "url": "https://www.tokensets.com/", "category": "Finance"},
{"name": "State of the ÐApps", "description": "Directory of Decentralized Applications", "url": "https://www.stateofthedapps.com/", "category": "Directory"},
{"name": "BulkSender", "description": "Batch sending of tokens", "url": "https://bulksender.app/", "category": "Finance"},
Expand All @@ -19,12 +21,9 @@
{"name": "Last Trip", "description": "A RPG game", "url": "http://lasttrip.matrixdapp.com/", "category": "Game"},
{"name": "LORDLESS", "description": "Be a bounty hunter in my tavern", "url": "https://game.lordless.io/home", "category": "Game"},
{"name": "MLB Crypto Baseball", "description": "Baseball collectible game", "url": "https://mlbcryptobaseball.com", "category": "Game"},
{"name": "Radi.Cards", "description": "Creative, unique art pieces from from all around the interwebs.", "url": "https://radi.cards/cardshop", "category": "Game"},
{"name": "Augur", "description": "Decentralized prediction market", "url": "https://www.augur.net/ipfs-redirect.html", "category": "Marketplace"},
{"name": "Name Bazaar", "description": "A peer-to-peer marketplace for the exchange of names registered via the ENS", "url": "https://namebazaar.io/", "category": "Marketplace"},
{"name": "OpenSea", "description": "Peer-to-peer marketplace for scarce digital goods", "url": "https://opensea.io", "category": "Marketplace"},
{"name": "SuperRare", "description": "Collect art or submit your art as a creator", "url": "https://superrare.co/", "category": "Marketplace"},
{"name": "Veil", "description": "A peer-to-peer trading platform for prediction markets and derivatives", "url": "https://app.veil.co/", "category": "Marketplace"},
{"name": "Veil", "description": "A peer-to-peer trading platform for prediction markets and derivatives", "url": "https://app.veil.co/", "category": "Marketplace"},
{"name": "Gravity", "description": "Create your gravatar.", "url": "https://gravity.cool/", "category": "Property"},
{"name": "Mokens", "description": "Create your own collectibles", "url": "https://mokens.io/", "category": "Property"},
{"name": "TENZ-ID", "description": "TENZ-ID is a Decentralized Blockchain naming system", "url": "https://tenzorum.org/tenz_id/", "category": "Property"},
Expand All @@ -40,7 +39,6 @@
{"name": "SmartDrops", "description": "A platform that lets people earn crypto by joining new token projects.", "url": "https://www.smartdrops.io/", "category": "Tool"},
{"name": "xDai Bridge", "description": "xDai/Ethereum bridge for self transfers of Dai to xDai", "url": "https://dai-bridge.poa.network/", "category": "Tool"},
{"name": "Alfacash", "description": "Trade crypto instantly. ETH, BTC, XRP and 30+ other coins and tokens", "url": "https://www.alfa.cash/", "category": "Exchange"},
{"name": "0x Instant", "description": "A free and flexible way to offer simple crypto purchasing", "url": "http://0x-instant-staging.s3-website-us-east-1.amazonaws.com/", "category": "Exchange"},
{"name": "KyberSwap", "description": "Instant and Secure Token to Token Swaps", "url": "https://kyber.network/swap/eth_knc", "category": "Exchange"},
{"name": "Kyber Migration Portal", "description": "Migration portal to upgrade legacy KNC to ERC-20 KNC tokens", "url": "https://kyber.org/migrate", "category": "Token Migration"},
{"name": "localethereum", "description": "Peer-to-peer marketplace allowing to trade eth to fiat", "url": "https://localethereum.com/", "category": "Exchange"},
Expand Down
32 changes: 28 additions & 4 deletions app/src/main/java/com/alphawallet/app/entity/FinishReceiver.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package com.alphawallet.app.entity;

import static androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED;
import static androidx.core.content.ContextCompat.registerReceiver;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;

import androidx.localbroadcastmanager.content.LocalBroadcastManager;

Expand All @@ -19,12 +23,25 @@ public FinishReceiver(Activity ctx)
{
activity = ctx;
broadcastManager = LocalBroadcastManager.getInstance(ctx);
register();
register(ctx);
}

public FinishReceiver()
{
activity = null;
broadcastManager = null;
}

private void register()
private void register(Activity ctx)
{
broadcastManager.registerReceiver(this, new IntentFilter(C.PRUNE_ACTIVITY));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
registerReceiver(ctx, this, new IntentFilter(C.WALLET_CONNECT_COUNT_CHANGE), RECEIVER_NOT_EXPORTED);
}
else
{
broadcastManager.registerReceiver(this, new IntentFilter(C.PRUNE_ACTIVITY));
}
}

@Override
Expand All @@ -35,6 +52,13 @@ public void onReceive(Context context, Intent intent)

public void unregister()
{
broadcastManager.unregisterReceiver(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
activity.unregisterReceiver(this);
}
else
{
broadcastManager.unregisterReceiver(this);
}
}
}
33 changes: 29 additions & 4 deletions app/src/main/java/com/alphawallet/app/entity/HomeReceiver.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package com.alphawallet.app.entity;

import static androidx.core.content.ContextCompat.registerReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;

import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;

import com.alphawallet.app.C;
Expand All @@ -21,6 +25,12 @@ public HomeReceiver(Context context, HomeCommsInterface homeCommsInterface)
this.homeCommsInterface = homeCommsInterface;
}

public HomeReceiver()
{
homeCommsInterface = null;
broadcastManager = null;
}

@Override
public void onReceive(Context context, Intent intent)
{
Expand All @@ -42,17 +52,32 @@ public void onReceive(Context context, Intent intent)
}
}

public void register()
public void register(Context ctx)
{
IntentFilter filter = new IntentFilter();
filter.addAction(C.REQUEST_NOTIFICATION_ACCESS);
filter.addAction(C.BACKUP_WALLET_SUCCESS);
filter.addAction(C.WALLET_CONNECT_REQUEST);
broadcastManager.registerReceiver(this, filter);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
registerReceiver(ctx, this, new IntentFilter(C.WALLET_CONNECT_COUNT_CHANGE), ContextCompat.RECEIVER_NOT_EXPORTED);
}
else
{
broadcastManager.registerReceiver(this, filter);
}
}

public void unregister()
public void unregister(Context ctx)
{
broadcastManager.unregisterReceiver(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
ctx.unregisterReceiver(this);
}
else
{
broadcastManager.unregisterReceiver(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.alphawallet.app.C;
import com.alphawallet.app.R;
import com.alphawallet.app.entity.HomeReceiver;
import com.alphawallet.app.ui.HomeActivity;

/**
Expand Down Expand Up @@ -148,6 +149,7 @@ private void checkNotificationPermission()
!= PackageManager.PERMISSION_DENIED))
{
Intent intent = new Intent(C.REQUEST_NOTIFICATION_ACCESS);
intent.setPackage("com.alphawallet.app.entity.HomeReceiver");
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,46 @@ private void initializeSettings()
tokenScriptViewer.setToggleState(viewModel.getTokenScriptViewerState());
}

@FunctionalInterface
public interface Callback
{
void onResult(boolean choice);
}

private void onDeveloperOverride()
{
viewModel.toggleDeveloperOverride(developerOverride.getToggleState());
boolean developerOverrideState = developerOverride.getToggleState();
if (developerOverrideState)
{
//display warning popup
showWarningPopup(R.string.developer_override_warning, result -> {
viewModel.toggleDeveloperOverride(result);
developerOverride.setToggleState(result);
});
}
else
{
viewModel.toggleDeveloperOverride(developerOverride.getToggleState());
}
}

private void showWarningPopup(int message, Callback callback)
{
AWalletAlertDialog dialog = new AWalletAlertDialog(this);
dialog.setIcon(AWalletAlertDialog.WARNING);
dialog.setTitle(R.string.warning);
dialog.setMessage(message);
dialog.setButtonText(R.string.i_accept);
dialog.setButtonListener(v -> {
callback.onResult(true);
dialog.dismiss();
});
dialog.setSecondaryButtonText(R.string.action_cancel);
dialog.setSecondaryButtonListener(v -> {
callback.onResult(false);
dialog.dismiss();
});
dialog.show();
}

private void onFullScreenClicked()
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/java/com/alphawallet/app/ui/DappBrowserFragment.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.alphawallet.app.ui;

import static com.alphawallet.app.C.ALPHAWALLET_WEB;
import static com.alphawallet.app.C.ETHER_DECIMALS;
import static com.alphawallet.app.C.RESET_TOOLBAR;
import static com.alphawallet.app.entity.tokens.Token.TOKEN_BALANCE_PRECISION;
Expand Down Expand Up @@ -1485,10 +1486,22 @@ public void onWebpageLoadComplete()

private boolean loadUrl(String urlText)
{
requireContext();
AnalyticsProperties props = new AnalyticsProperties();
props.put(Analytics.PROPS_URL, urlText);
viewModel.track(Analytics.Action.LOAD_URL, props);

// ensure the URL is whitelisted, that is it is featured in the dapp list, and check if the app is in developer override mode
if (!viewModel.getDeveloperOverrideState(getContext()) && !DappBrowserUtils.isInDappsList(this.getContext(), urlText))
{
//reset url string back to AlphaWallet
setUrlText(ALPHAWALLET_WEB);

//display a warning dialog
displayError(R.string.title_dialog_error, R.string.not_recommended_to_visit);
return false;
}

detachFragments();
addToBackStack(DAPP_BROWSER);
cancelSearchSession();
Expand All @@ -1500,6 +1513,7 @@ else if (handlePrefix(urlText))
{
return true;
}

web3.resetView();
web3.loadUrl(Utils.formatUrl(urlText));
setUrlText(Utils.formatUrl(urlText));
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/alphawallet/app/ui/HomeActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ protected void onResume()
if (homeReceiver == null)
{
homeReceiver = new HomeReceiver(this, this);
homeReceiver.register();
homeReceiver.register(this);
}
initViews();
}
Expand Down Expand Up @@ -669,7 +669,7 @@ public void onDestroy()
viewModel.onClean();
if (homeReceiver != null)
{
homeReceiver.unregister();
homeReceiver.unregister(this);
homeReceiver = null;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ private void onBurned(Boolean burn)
dialog.setTitle(R.string.ticket_redeemed);
dialog.setIcon(AWalletAlertDialog.SUCCESS);
dialog.setOnDismissListener(v -> {
Intent pruneIntent = new Intent(PRUNE_ACTIVITY);
pruneIntent.setPackage("com.alphawallet.app.entity.FinishReceiver");
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(PRUNE_ACTIVITY));
});
dialog.show();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@

import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;

import static androidx.core.content.ContentProviderCompat.requireContext;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
Expand All @@ -24,7 +23,6 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
Expand Down Expand Up @@ -60,6 +58,7 @@ public class WalletConnectSessionActivity extends BaseActivity
{
private final Handler handler = new Handler(Looper.getMainLooper());
private LocalBroadcastManager broadcastManager;
private
WalletConnectViewModel viewModel;
private RecyclerView recyclerView;
private Button btnConnectWallet;
Expand Down Expand Up @@ -246,12 +245,26 @@ public void onSessionDisconnected()

private void startConnectionCheck()
{
broadcastManager.registerReceiver(walletConnectChangeReceiver, new IntentFilter(C.WALLET_CONNECT_COUNT_CHANGE));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
registerReceiver(walletConnectChangeReceiver, new IntentFilter(C.WALLET_CONNECT_COUNT_CHANGE), RECEIVER_NOT_EXPORTED);
}
else
{
broadcastManager.registerReceiver(walletConnectChangeReceiver, new IntentFilter(C.WALLET_CONNECT_COUNT_CHANGE));
}
}

private void stopConnectionCheck()
{
broadcastManager.unregisterReceiver(walletConnectChangeReceiver);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
{
unregisterReceiver(walletConnectChangeReceiver);
}
else
{
broadcastManager.unregisterReceiver(walletConnectChangeReceiver);
}
}

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomViewHolder>
Expand Down
Loading

0 comments on commit 095038f

Please sign in to comment.