You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
6.7 KiB
182 lines
6.7 KiB
package acr.browser.lightning.utils; |
|
|
|
import android.content.Context; |
|
import android.content.res.AssetManager; |
|
import android.support.annotation.NonNull; |
|
import android.support.annotation.Nullable; |
|
import android.util.Log; |
|
|
|
import java.io.BufferedReader; |
|
import java.io.IOException; |
|
import java.io.InputStreamReader; |
|
import java.net.URI; |
|
import java.net.URISyntaxException; |
|
import java.util.HashSet; |
|
import java.util.Set; |
|
|
|
import javax.inject.Inject; |
|
import javax.inject.Singleton; |
|
|
|
import acr.browser.lightning.app.BrowserApp; |
|
import acr.browser.lightning.constant.Constants; |
|
import acr.browser.lightning.preference.PreferenceManager; |
|
|
|
@Singleton |
|
public class AdBlock { |
|
|
|
private static final String TAG = "AdBlock"; |
|
private static final String BLOCKED_DOMAINS_LIST_FILE_NAME = "hosts.txt"; |
|
private static final String LOCAL_IP_V4 = "127.0.0.1"; |
|
private static final String LOCAL_IP_V4_ALT = "0.0.0.0"; |
|
private static final String LOCAL_IP_V6 = "::1"; |
|
private static final String LOCALHOST = "localhost"; |
|
private static final String COMMENT = "#"; |
|
private static final String TAB = "\t"; |
|
private static final String SPACE = " "; |
|
private static final String EMPTY = ""; |
|
private final Set<String> mBlockedDomainsList = new HashSet<>(); |
|
private boolean mBlockAds; |
|
|
|
@Inject PreferenceManager mPreferenceManager; |
|
|
|
@Inject |
|
public AdBlock(@NonNull Context context) { |
|
BrowserApp.getAppComponent().inject(this); |
|
if (mBlockedDomainsList.isEmpty() && Constants.FULL_VERSION) { |
|
loadHostsFile(context); |
|
} |
|
mBlockAds = mPreferenceManager.getAdBlockEnabled(); |
|
} |
|
|
|
public void updatePreference() { |
|
mBlockAds = mPreferenceManager.getAdBlockEnabled(); |
|
} |
|
|
|
private void loadBlockedDomainsList(@NonNull final Context context) { |
|
BrowserApp.getTaskThread().execute(new Runnable() { |
|
|
|
@Override |
|
public void run() { |
|
AssetManager asset = context.getAssets(); |
|
BufferedReader reader = null; |
|
try { |
|
//noinspection IOResourceOpenedButNotSafelyClosed |
|
reader = new BufferedReader(new InputStreamReader( |
|
asset.open(BLOCKED_DOMAINS_LIST_FILE_NAME))); |
|
String line; |
|
while ((line = reader.readLine()) != null) { |
|
mBlockedDomainsList.add(line.trim()); |
|
} |
|
} catch (IOException e) { |
|
Log.wtf(TAG, "Reading blocked domains list from file '" |
|
+ BLOCKED_DOMAINS_LIST_FILE_NAME + "' failed.", e); |
|
} finally { |
|
Utils.close(reader); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
/** |
|
* a method that determines if the given URL is an ad or not. It performs |
|
* a search of the URL's domain on the blocked domain hash set. |
|
* |
|
* @param url the URL to check for being an ad |
|
* @return true if it is an ad, false if it is not an ad |
|
*/ |
|
public boolean isAd(@Nullable String url) { |
|
if (!mBlockAds || url == null) { |
|
return false; |
|
} |
|
|
|
String domain; |
|
try { |
|
domain = getDomainName(url); |
|
} catch (URISyntaxException e) { |
|
Log.d(TAG, "URL '" + url + "' is invalid", e); |
|
return false; |
|
} |
|
|
|
boolean isOnBlacklist = mBlockedDomainsList.contains(domain); |
|
if (isOnBlacklist) { |
|
Log.d(TAG, "URL '" + url + "' is an ad"); |
|
} |
|
return isOnBlacklist; |
|
} |
|
|
|
/** |
|
* Returns the probable domain name for a given URL |
|
* |
|
* @param url the url to parse |
|
* @return returns the domain |
|
* @throws URISyntaxException throws an exception if the string cannot form a URI |
|
*/ |
|
@NonNull |
|
private static String getDomainName(@NonNull String url) throws URISyntaxException { |
|
int index = url.indexOf('/', 8); |
|
if (index != -1) { |
|
url = url.substring(0, index); |
|
} |
|
|
|
URI uri = new URI(url); |
|
String domain = uri.getHost(); |
|
if (domain == null) { |
|
return url; |
|
} |
|
|
|
return domain.startsWith("www.") ? domain.substring(4) : domain; |
|
} |
|
|
|
/** |
|
* This method reads through a hosts file and extracts the domains that should |
|
* be redirected to localhost (a.k.a. IP address 127.0.0.1). It can handle files that |
|
* simply have a list of hostnames to block, or it can handle a full blown hosts file. |
|
* It will strip out comments, references to the base IP address and just extract the |
|
* domains to be used |
|
* |
|
* @param context the context needed to read the file |
|
*/ |
|
private void loadHostsFile(@NonNull final Context context) { |
|
BrowserApp.getTaskThread().execute(new Runnable() { |
|
|
|
@Override |
|
public void run() { |
|
AssetManager asset = context.getAssets(); |
|
BufferedReader reader = null; |
|
try { |
|
//noinspection IOResourceOpenedButNotSafelyClosed |
|
reader = new BufferedReader(new InputStreamReader( |
|
asset.open(BLOCKED_DOMAINS_LIST_FILE_NAME))); |
|
String line; |
|
while ((line = reader.readLine()) != null) { |
|
if (!line.isEmpty() && !line.startsWith(COMMENT)) { |
|
line = line.replace(LOCAL_IP_V4, EMPTY) |
|
.replace(LOCAL_IP_V4_ALT, EMPTY) |
|
.replace(LOCAL_IP_V6, EMPTY) |
|
.replace(TAB, EMPTY); |
|
int comment = line.indexOf(COMMENT); |
|
if (comment >= 0) { |
|
line = line.substring(0, comment); |
|
} |
|
line = line.trim(); |
|
if (!line.isEmpty() && !line.equals(LOCALHOST)) { |
|
while (line.contains(SPACE)) { |
|
int space = line.indexOf(SPACE); |
|
String host = line.substring(0, space); |
|
mBlockedDomainsList.add(host.trim()); |
|
line = line.substring(space, line.length()).trim(); |
|
} |
|
mBlockedDomainsList.add(line.trim()); |
|
} |
|
} |
|
} |
|
} catch (IOException e) { |
|
Log.wtf(TAG, "Reading blocked domains list from file '" |
|
+ BLOCKED_DOMAINS_LIST_FILE_NAME + "' failed.", e); |
|
} finally { |
|
Utils.close(reader); |
|
} |
|
} |
|
}); |
|
} |
|
}
|
|
|