Commit f5285289 authored by Selim Gurun's avatar Selim Gurun Committed by Commit Bot

Add Plumbing for Calling Whitelisting

Safebrowsing checks can be prevented for certain domains by passing
these domains via a whitelisting API. This code lands the plumbing for
using that whitelisting code.

Bug: 726770
Change-Id: I3e6278afb4900929bef6d05e81fae34529fe920e
Reviewed-on: https://chromium-review.googlesource.com/577921Reviewed-by: default avatarNate Fischer <ntfschr@chromium.org>
Commit-Queue: Selim Gurun <sgurun@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488029}
parent 0b3e7a5f
...@@ -44,6 +44,13 @@ void NotifyClientCertificatesChanged() { ...@@ -44,6 +44,13 @@ void NotifyClientCertificatesChanged() {
net::CertDatabase::GetInstance()->OnAndroidKeyStoreChanged(); net::CertDatabase::GetInstance()->OnAndroidKeyStoreChanged();
} }
void SafeBrowsingWhitelistAssigned(const JavaRef<jobject>& callback,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
JNIEnv* env = AttachCurrentThread();
Java_AwContentsStatics_safeBrowsingWhitelistAssigned(env, callback, success);
}
} // namespace } // namespace
// static // static
...@@ -93,14 +100,18 @@ void SetSafeBrowsingEnabledByManifest(JNIEnv* env, ...@@ -93,14 +100,18 @@ void SetSafeBrowsingEnabledByManifest(JNIEnv* env,
} }
// static // static
void SetSafeBrowsingWhiteList(JNIEnv* env, void SetSafeBrowsingWhitelist(JNIEnv* env,
const JavaParamRef<jclass>&, const JavaParamRef<jclass>&,
const JavaParamRef<jobjectArray>& jrules) { const JavaParamRef<jobjectArray>& jrules,
const JavaParamRef<jobject>& callback) {
std::vector<std::string> rules; std::vector<std::string> rules;
base::android::AppendJavaStringArrayToStringVector(env, jrules, &rules); base::android::AppendJavaStringArrayToStringVector(env, jrules, &rules);
AwSafeBrowsingWhitelistManager* whitelist_manager = AwSafeBrowsingWhitelistManager* whitelist_manager =
AwBrowserContext::GetDefault()->GetSafeBrowsingWhitelistManager(); AwBrowserContext::GetDefault()->GetSafeBrowsingWhitelistManager();
whitelist_manager->SetWhitelistOnUIThread(std::move(rules)); whitelist_manager->SetWhitelistOnUIThread(
std::move(rules),
base::Bind(&SafeBrowsingWhitelistAssigned,
ScopedJavaGlobalRef<jobject>(env, callback)));
} }
// static // static
......
...@@ -143,12 +143,14 @@ bool AddRuleToWhitelist(base::StringPiece rule, TrieNode* root) { ...@@ -143,12 +143,14 @@ bool AddRuleToWhitelist(base::StringPiece rule, TrieNode* root) {
return true; return true;
} }
void AddRules(const std::vector<std::string>& rules, TrieNode* root) { bool AddRules(const std::vector<std::string>& rules, TrieNode* root) {
for (auto rule : rules) { for (auto rule : rules) {
if (!AddRuleToWhitelist(rule, root)) { if (!AddRuleToWhitelist(rule, root)) {
LOG(ERROR) << " Dropping invalid whitelist rule " << rule; LOG(ERROR) << " invalid whitelist rule " << rule;
return false;
} }
} }
return true;
} }
bool IsWhitelisted(const GURL& url, const TrieNode* node) { bool IsWhitelisted(const GURL& url, const TrieNode* node) {
...@@ -193,30 +195,37 @@ void AwSafeBrowsingWhitelistManager::SetWhitelist( ...@@ -193,30 +195,37 @@ void AwSafeBrowsingWhitelistManager::SetWhitelist(
// A task that builds the whitelist on a background thread. // A task that builds the whitelist on a background thread.
void AwSafeBrowsingWhitelistManager::BuildWhitelist( void AwSafeBrowsingWhitelistManager::BuildWhitelist(
const std::vector<std::string>& rules) { const std::vector<std::string>& rules,
const base::Callback<void(bool)>& callback) {
DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); DCHECK(background_task_runner_->RunsTasksInCurrentSequence());
std::unique_ptr<TrieNode> whitelist(base::MakeUnique<TrieNode>()); std::unique_ptr<TrieNode> whitelist(base::MakeUnique<TrieNode>());
AddRules(rules, whitelist.get()); bool success = AddRules(rules, whitelist.get());
DCHECK(!whitelist->is_terminal); DCHECK(!whitelist->is_terminal);
DCHECK(!whitelist->match_prefix); DCHECK(!whitelist->match_prefix);
// use base::Unretained as AwSafeBrowsingWhitelistManager is a singleton and
// not cleaned. ui_task_runner_->PostTask(FROM_HERE, base::Bind(callback, success));
io_task_runner_->PostTask(
FROM_HERE, if (success) {
base::Bind(&AwSafeBrowsingWhitelistManager::SetWhitelist, // use base::Unretained as AwSafeBrowsingWhitelistManager is a singleton and
base::Unretained(this), base::Passed(std::move(whitelist)))); // not cleaned.
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&AwSafeBrowsingWhitelistManager::SetWhitelist,
base::Unretained(this), base::Passed(std::move(whitelist))));
}
} }
void AwSafeBrowsingWhitelistManager::SetWhitelistOnUIThread( void AwSafeBrowsingWhitelistManager::SetWhitelistOnUIThread(
std::vector<std::string>&& rules) { std::vector<std::string>&& rules,
const base::Callback<void(bool)>& callback) {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence()); DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
// use base::Unretained as AwSafeBrowsingWhitelistManager is a singleton and // use base::Unretained as AwSafeBrowsingWhitelistManager is a singleton and
// not cleaned. // not cleaned.
background_task_runner_->PostTask( background_task_runner_->PostTask(
FROM_HERE, FROM_HERE, base::Bind(&AwSafeBrowsingWhitelistManager::BuildWhitelist,
base::Bind(&AwSafeBrowsingWhitelistManager::BuildWhitelist, base::Unretained(this),
base::Unretained(this), base::Passed(std::move(rules)))); base::Passed(std::move(rules)), callback));
} }
bool AwSafeBrowsingWhitelistManager::IsURLWhitelisted(const GURL& url) const { bool AwSafeBrowsingWhitelistManager::IsURLWhitelisted(const GURL& url) const {
......
...@@ -65,11 +65,13 @@ class AwSafeBrowsingWhitelistManager { ...@@ -65,11 +65,13 @@ class AwSafeBrowsingWhitelistManager {
bool IsURLWhitelisted(const GURL& url) const; bool IsURLWhitelisted(const GURL& url) const;
// Replace the current host whitelist with a new one. // Replace the current host whitelist with a new one.
void SetWhitelistOnUIThread(std::vector<std::string>&& rules); void SetWhitelistOnUIThread(std::vector<std::string>&& rules,
const base::Callback<void(bool)>& callback);
private: private:
// Builds whitelist on background thread. // Builds whitelist on background thread.
void BuildWhitelist(const std::vector<std::string>& rules); void BuildWhitelist(const std::vector<std::string>& rules,
const base::Callback<void(bool)>& callback);
// Replaces the current whitelist. Must be called on the IO thread. // Replaces the current whitelist. Must be called on the IO thread.
void SetWhitelist(std::unique_ptr<TrieNode> whitelist); void SetWhitelist(std::unique_ptr<TrieNode> whitelist);
......
...@@ -68,6 +68,7 @@ import org.chromium.content.browser.input.LGEmailActionModeWorkaround; ...@@ -68,6 +68,7 @@ import org.chromium.content.browser.input.LGEmailActionModeWorkaround;
import org.chromium.net.NetworkChangeNotifier; import org.chromium.net.NetworkChangeNotifier;
import java.io.File; import java.io.File;
import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
...@@ -576,6 +577,12 @@ public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider { ...@@ -576,6 +577,12 @@ public class WebViewChromiumFactoryProvider implements WebViewFactoryProvider {
AwContentsStatics.shutdownSafeBrowsing(); AwContentsStatics.shutdownSafeBrowsing();
} }
// TODO(ntfschr): add @Override once next android SDK rolls
public void setSafeBrowsingWhitelist(
List<String> urls, ValueCallback<Boolean> callback) {
AwContentsStatics.setSafeBrowsingWhitelist(urls, callback);
}
}; };
} }
} }
......
...@@ -13,6 +13,7 @@ import org.chromium.base.annotations.CalledByNative; ...@@ -13,6 +13,7 @@ import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.JNINamespace;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.List;
/** /**
* Implementations of various static methods, and also a home for static * Implementations of various static methods, and also a home for static
...@@ -107,8 +108,23 @@ public class AwContentsStatics { ...@@ -107,8 +108,23 @@ public class AwContentsStatics {
setSafeBrowsingEnabledByManifest(enable); setSafeBrowsingEnabledByManifest(enable);
} }
public static void setSafeBrowsingWhiteList(String[] urls) { @CalledByNative
nativeSetSafeBrowsingWhiteList(urls); private static void safeBrowsingWhitelistAssigned(
ValueCallback<Boolean> callback, boolean success) {
if (callback == null) return;
callback.onReceiveValue(success);
}
public static void setSafeBrowsingWhitelist(
List<String> urls, ValueCallback<Boolean> callback) {
String[] urlArray = urls.toArray(new String[urls.size()]);
if (callback == null) {
callback = new ValueCallback<Boolean>() {
@Override
public void onReceiveValue(Boolean b) {}
};
}
nativeSetSafeBrowsingWhitelist(urlArray, callback);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
...@@ -173,7 +189,8 @@ public class AwContentsStatics { ...@@ -173,7 +189,8 @@ public class AwContentsStatics {
AwContentsIoThreadClient ioThreadClient, AwBrowserContext browserContext); AwContentsIoThreadClient ioThreadClient, AwBrowserContext browserContext);
private static native boolean nativeGetSafeBrowsingEnabledByManifest(); private static native boolean nativeGetSafeBrowsingEnabledByManifest();
private static native void nativeSetSafeBrowsingEnabledByManifest(boolean enable); private static native void nativeSetSafeBrowsingEnabledByManifest(boolean enable);
private static native void nativeSetSafeBrowsingWhiteList(String[] urls); private static native void nativeSetSafeBrowsingWhitelist(
String[] urls, ValueCallback<Boolean> callback);
private static native void nativeSetCheckClearTextPermitted(boolean permitted); private static native void nativeSetCheckClearTextPermitted(boolean permitted);
private static native String nativeFindAddress(String addr); private static native String nativeFindAddress(String addr);
} }
...@@ -44,6 +44,7 @@ import org.chromium.content.browser.test.util.CriteriaHelper; ...@@ -44,6 +44,7 @@ import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
import org.chromium.net.test.EmbeddedTestServer; import org.chromium.net.test.EmbeddedTestServer;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
...@@ -261,6 +262,15 @@ public class SafeBrowsingTest extends AwTestBase { ...@@ -261,6 +262,15 @@ public class SafeBrowsingTest extends AwTestBase {
} }
} }
private static class WhitelistHelper extends CallbackHelper implements ValueCallback<Boolean> {
public boolean success;
public void onReceiveValue(Boolean success) {
this.success = success;
notifyCalled();
}
}
@Override @Override
public void setUp() throws Exception { public void setUp() throws Exception {
super.setUp(); super.setUp();
...@@ -446,14 +456,44 @@ public class SafeBrowsingTest extends AwTestBase { ...@@ -446,14 +456,44 @@ public class SafeBrowsingTest extends AwTestBase {
@Override @Override
public void run() { public void run() {
String host = Uri.parse(responseUrl).getHost(); String host = Uri.parse(responseUrl).getHost();
String[] s = new String[] {host}; ArrayList<String> s = new ArrayList<String>();
AwContentsStatics.setSafeBrowsingWhiteList(s); s.add(host);
AwContentsStatics.setSafeBrowsingWhitelist(s, null);
} }
}); });
loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), responseUrl); loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), responseUrl);
assertTargetPageHasLoaded(MALWARE_PAGE_BACKGROUND_COLOR); assertTargetPageHasLoaded(MALWARE_PAGE_BACKGROUND_COLOR);
} }
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT)
public void testCallbackCalledOnSafeBrowsingBadWhitelistRule() throws Throwable {
verifyWhiteListRule("http://www.google.com", false);
}
@SmallTest
@Feature({"AndroidWebView"})
@CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT)
public void testCallbackCalledOnSafeBrowsingGoodWhitelistRule() throws Throwable {
verifyWhiteListRule("www.google.com", true);
}
private void verifyWhiteListRule(final String rule, boolean expected) throws Throwable {
final WhitelistHelper helper = new WhitelistHelper();
final int count = helper.getCallCount();
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
ArrayList<String> s = new ArrayList<String>();
s.add(rule);
AwContentsStatics.setSafeBrowsingWhitelist(s, helper);
}
});
helper.waitForCallback(count);
assertEquals(expected, helper.success);
}
@SmallTest @SmallTest
@Feature({"AndroidWebView"}) @Feature({"AndroidWebView"})
@CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT) @CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment