summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortreib <treib@chromium.org>2014-09-05 01:43:55 -0700
committerCommit bot <commit-bot@chromium.org>2014-09-05 08:45:41 +0000
commit4edbded7edb6d07dea0e5ccb339142ddb3ad121b (patch)
tree2af70dafab277b58d7e7599dd0c826462203ed2c
parent767d8801ac2b97a991caf3e269b0433cd2f0148d (diff)
downloadchromium_src-4edbded7edb6d07dea0e5ccb339142ddb3ad121b.zip
chromium_src-4edbded7edb6d07dea0e5ccb339142ddb3ad121b.tar.gz
chromium_src-4edbded7edb6d07dea0e5ccb339142ddb3ad121b.tar.bz2
Supervised users: Prototype of static client-side host blacklist.
BUG=410824 Review URL: https://codereview.chromium.org/537993002 Cr-Commit-Position: refs/heads/master@{#293483}
-rw-r--r--chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc94
-rw-r--r--chrome/browser/supervised_user/experimental/supervised_user_blacklist.h59
-rw-r--r--chrome/browser/supervised_user/supervised_user_service.cc25
-rw-r--r--chrome/browser/supervised_user/supervised_user_service.h10
-rw-r--r--chrome/browser/supervised_user/supervised_user_url_filter.cc12
-rw-r--r--chrome/browser/supervised_user/supervised_user_url_filter.h10
-rw-r--r--chrome/chrome_browser.gypi2
7 files changed, 209 insertions, 3 deletions
diff --git a/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc b/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc
new file mode 100644
index 0000000..14843ff
--- /dev/null
+++ b/chrome/browser/supervised_user/experimental/supervised_user_blacklist.cc
@@ -0,0 +1,94 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/supervised_user/experimental/supervised_user_blacklist.h"
+
+#include <algorithm>
+#include <cstring>
+#include <fstream>
+
+#include "base/files/file_path.h"
+#include "base/files/memory_mapped_file.h"
+#include "content/public/browser/browser_thread.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+
+namespace {
+
+scoped_ptr<std::vector<SupervisedUserBlacklist::Hash> >
+ReadFromBinaryFileOnFileThread(const base::FilePath& path) {
+ DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+
+ scoped_ptr<std::vector<SupervisedUserBlacklist::Hash> > host_hashes(
+ new std::vector<SupervisedUserBlacklist::Hash>);
+
+ base::MemoryMappedFile file;
+ file.Initialize(path);
+ if (!file.IsValid())
+ return host_hashes.Pass();
+
+ size_t size = file.length();
+ if (size <= 0 || size % base::kSHA1Length != 0)
+ return host_hashes.Pass();
+
+ size_t hash_count = size / base::kSHA1Length;
+ host_hashes->resize(hash_count);
+
+ for (size_t i = 0; i < hash_count; i++) {
+ memcpy((*host_hashes.get())[i].data,
+ file.data() + i * base::kSHA1Length,
+ base::kSHA1Length);
+ }
+
+ std::sort(host_hashes->begin(), host_hashes->end());
+
+ return host_hashes.Pass();
+}
+
+} // namespace
+
+SupervisedUserBlacklist::Hash::Hash(const std::string& host) {
+ const unsigned char* host_bytes =
+ reinterpret_cast<const unsigned char*>(host.c_str());
+ base::SHA1HashBytes(host_bytes, host.length(), data);
+}
+
+bool SupervisedUserBlacklist::Hash::operator<(const Hash& rhs) const {
+ return memcmp(data, rhs.data, base::kSHA1Length) < 0;
+}
+
+SupervisedUserBlacklist::SupervisedUserBlacklist() : weak_ptr_factory_(this) {}
+
+SupervisedUserBlacklist::~SupervisedUserBlacklist() {}
+
+bool SupervisedUserBlacklist::HasURL(const GURL& url) const {
+ Hash hash(url.host());
+ return std::binary_search(host_hashes_.begin(), host_hashes_.end(), hash);
+}
+
+size_t SupervisedUserBlacklist::GetEntryCount() const {
+ return host_hashes_.size();
+}
+
+void SupervisedUserBlacklist::ReadFromFile(const base::FilePath& path,
+ const base::Closure& done_callback) {
+ base::PostTaskAndReplyWithResult(
+ BrowserThread::GetBlockingPool(),
+ FROM_HERE,
+ base::Bind(&ReadFromBinaryFileOnFileThread, path),
+ base::Bind(&SupervisedUserBlacklist::OnReadFromFileCompleted,
+ weak_ptr_factory_.GetWeakPtr(),
+ done_callback));
+}
+
+void SupervisedUserBlacklist::OnReadFromFileCompleted(
+ const base::Closure& done_callback,
+ scoped_ptr<std::vector<Hash> > host_hashes) {
+ host_hashes_.swap(*host_hashes);
+ LOG_IF(WARNING, host_hashes_.empty()) << "Got empty blacklist";
+
+ if (!done_callback.is_null())
+ done_callback.Run();
+}
diff --git a/chrome/browser/supervised_user/experimental/supervised_user_blacklist.h b/chrome/browser/supervised_user/experimental/supervised_user_blacklist.h
new file mode 100644
index 0000000..2e93d7d
--- /dev/null
+++ b/chrome/browser/supervised_user/experimental/supervised_user_blacklist.h
@@ -0,0 +1,59 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SUPERVISED_USER_EXPERIMENTAL_SUPERVISED_USER_BLACKLIST_H_
+#define CHROME_BROWSER_SUPERVISED_USER_EXPERIMENTAL_SUPERVISED_USER_BLACKLIST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sha1.h"
+
+namespace base {
+class FilePath;
+}
+
+class GURL;
+
+// Compact list of (SHA1 hashes of) blocked hosts.
+// Checking for URLs is thread-safe, loading is not.
+class SupervisedUserBlacklist {
+ public:
+ struct Hash {
+ Hash() {}
+ explicit Hash(const std::string& host);
+ bool operator<(const Hash& rhs) const;
+
+ unsigned char data[base::kSHA1Length];
+ };
+
+ SupervisedUserBlacklist();
+ ~SupervisedUserBlacklist();
+
+ // Asynchronously read a blacklist from the given file, replacing any previous
+ // entries. |done_callback| will be run after reading finishes (successfully
+ // or not), but not if the SupervisedUserBlacklist is destroyed before that.
+ void ReadFromFile(const base::FilePath& path,
+ const base::Closure& done_callback);
+
+ bool HasURL(const GURL& url) const;
+
+ size_t GetEntryCount() const;
+
+ private:
+ void OnReadFromFileCompleted(const base::Closure& done_callback,
+ scoped_ptr<std::vector<Hash> > host_hashes);
+
+ std::vector<Hash> host_hashes_;
+
+ base::WeakPtrFactory<SupervisedUserBlacklist> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SupervisedUserBlacklist);
+};
+
+#endif // CHROME_BROWSER_SUPERVISED_USER_EXPERIMENTAL_SUPERVISED_USER_BLACKLIST_H_
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc
index 8f0a559..9816eb0 100644
--- a/chrome/browser/supervised_user/supervised_user_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -111,6 +111,17 @@ void SupervisedUserService::URLFilterContext::LoadWhitelists(
io_url_filter_, base::Passed(&site_lists_copy)));
}
+void SupervisedUserService::URLFilterContext::LoadBlacklist(
+ const base::FilePath& path) {
+ // For now, support loading only once. If we want to support re-load, we'll
+ // have to clear the blacklist pointer in the url filters first.
+ DCHECK_EQ(0u, blacklist_.GetEntryCount());
+ blacklist_.ReadFromFile(
+ path,
+ base::Bind(&SupervisedUserService::URLFilterContext::OnBlacklistLoaded,
+ base::Unretained(this)));
+}
+
void SupervisedUserService::URLFilterContext::SetManualHosts(
scoped_ptr<std::map<std::string, bool> > host_map) {
ui_url_filter_->SetManualHosts(host_map.get());
@@ -131,6 +142,16 @@ void SupervisedUserService::URLFilterContext::SetManualURLs(
io_url_filter_, base::Owned(url_map.release())));
}
+void SupervisedUserService::URLFilterContext::OnBlacklistLoaded() {
+ ui_url_filter_->SetBlacklist(&blacklist_);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&SupervisedUserURLFilter::SetBlacklist,
+ io_url_filter_,
+ &blacklist_));
+}
+
SupervisedUserService::SupervisedUserService(Profile* profile)
: profile_(profile),
active_(false),
@@ -519,6 +540,10 @@ void SupervisedUserService::UpdateSiteLists() {
#endif
}
+void SupervisedUserService::LoadBlacklist(const base::FilePath& path) {
+ url_filter_context_.LoadBlacklist(path);
+}
+
bool SupervisedUserService::AccessRequestsEnabled() {
if (waiting_for_permissions_)
return false;
diff --git a/chrome/browser/supervised_user/supervised_user_service.h b/chrome/browser/supervised_user/supervised_user_service.h
index 7bbdfed..f373947 100644
--- a/chrome/browser/supervised_user/supervised_user_service.h
+++ b/chrome/browser/supervised_user/supervised_user_service.h
@@ -14,6 +14,7 @@
#include "base/prefs/pref_change_registrar.h"
#include "base/scoped_observer.h"
#include "base/strings/string16.h"
+#include "chrome/browser/supervised_user/experimental/supervised_user_blacklist.h"
#include "chrome/browser/supervised_user/supervised_user_url_filter.h"
#include "chrome/browser/supervised_user/supervised_users.h"
#include "chrome/browser/sync/profile_sync_service_observer.h"
@@ -202,10 +203,13 @@ class SupervisedUserService : public KeyedService,
void SetDefaultFilteringBehavior(
SupervisedUserURLFilter::FilteringBehavior behavior);
void LoadWhitelists(ScopedVector<SupervisedUserSiteList> site_lists);
+ void LoadBlacklist(const base::FilePath& path);
void SetManualHosts(scoped_ptr<std::map<std::string, bool> > host_map);
void SetManualURLs(scoped_ptr<std::map<GURL, bool> > url_map);
private:
+ void OnBlacklistLoaded();
+
// SupervisedUserURLFilter is refcounted because the IO thread filter is
// used both by ProfileImplIOData and OffTheRecordProfileIOData (to filter
// network requests), so they both keep a reference to it.
@@ -215,6 +219,8 @@ class SupervisedUserService : public KeyedService,
scoped_refptr<SupervisedUserURLFilter> ui_url_filter_;
scoped_refptr<SupervisedUserURLFilter> io_url_filter_;
+ SupervisedUserBlacklist blacklist_;
+
DISALLOW_COPY_AND_ASSIGN(URLFilterContext);
};
@@ -261,6 +267,10 @@ class SupervisedUserService : public KeyedService,
void UpdateSiteLists();
+ // Asynchronously loads a static blacklist from a binary file at |path| and
+ // applies it to the URL filters.
+ void LoadBlacklist(const base::FilePath& path);
+
// Updates the manual overrides for hosts in the URL filters when the
// corresponding preference is changed.
void UpdateManualHosts();
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.cc b/chrome/browser/supervised_user/supervised_user_url_filter.cc
index b1a98f1..6f0fb76 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.cc
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_util.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/supervised_user/experimental/supervised_user_blacklist.h"
#include "components/policy/core/browser/url_blacklist_manager.h"
#include "components/url_fixer/url_fixer.h"
#include "components/url_matcher/url_matcher.h"
@@ -177,7 +178,8 @@ LoadWhitelistsOnBlockingPoolThread(
SupervisedUserURLFilter::SupervisedUserURLFilter()
: default_behavior_(ALLOW),
- contents_(new Contents()) {
+ contents_(new Contents()),
+ blacklist_(NULL) {
// Detach from the current thread so we can be constructed on a different
// thread than the one where we're used.
DetachFromThread();
@@ -288,6 +290,9 @@ SupervisedUserURLFilter::GetFilteringBehaviorForURL(const GURL& url) const {
}
}
+ if (blacklist_ && blacklist_->HasURL(url))
+ return BLOCK;
+
// If the default behavior is to allow, we don't need to check anything else.
if (default_behavior_ == ALLOW)
return ALLOW;
@@ -350,6 +355,11 @@ void SupervisedUserURLFilter::LoadWhitelists(
base::Bind(&SupervisedUserURLFilter::SetContents, this));
}
+void SupervisedUserURLFilter::SetBlacklist(
+ SupervisedUserBlacklist* blacklist) {
+ blacklist_ = blacklist;
+}
+
void SupervisedUserURLFilter::SetFromPatterns(
const std::vector<std::string>& patterns) {
DCHECK(CalledOnValidThread());
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.h b/chrome/browser/supervised_user/supervised_user_url_filter.h
index 64ef42b..ceaf9ea 100644
--- a/chrome/browser/supervised_user/supervised_user_url_filter.h
+++ b/chrome/browser/supervised_user/supervised_user_url_filter.h
@@ -16,6 +16,7 @@
#include "chrome/browser/supervised_user/supervised_users.h"
class GURL;
+class SupervisedUserBlacklist;
// This class manages the filtering behavior for a given URL, i.e. it tells
// callers if a given URL should be allowed, blocked or warned about. It uses
@@ -84,11 +85,13 @@ class SupervisedUserURLFilter
// Sets the filtering behavior for pages not on a list (default is ALLOW).
void SetDefaultFilteringBehavior(FilteringBehavior behavior);
- // Asynchronously loads the specified site lists from disk and updates the
+ // Asynchronously loads the specified site lists and updates the
// filter to recognize each site on them.
- // Calls |continuation| when the filter has been updated.
void LoadWhitelists(ScopedVector<SupervisedUserSiteList> site_lists);
+ // Sets the static blacklist of blocked hosts.
+ void SetBlacklist(SupervisedUserBlacklist* blacklist);
+
// Set the list of matched patterns to the passed in list.
// This method is only used for testing.
void SetFromPatterns(const std::vector<std::string>& patterns);
@@ -121,6 +124,9 @@ class SupervisedUserURLFilter
// (false).
std::map<std::string, bool> host_map_;
+ // Not owned.
+ SupervisedUserBlacklist* blacklist_;
+
DISALLOW_COPY_AND_ASSIGN(SupervisedUserURLFilter);
};
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index b3a27ec..ef926a3 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2285,6 +2285,8 @@
'browser/supervised_user/custodian_profile_downloader_service.h',
'browser/supervised_user/custodian_profile_downloader_service_factory.cc',
'browser/supervised_user/custodian_profile_downloader_service_factory.h',
+ 'browser/supervised_user/experimental/supervised_user_blacklist.cc',
+ 'browser/supervised_user/experimental/supervised_user_blacklist.h',
'browser/supervised_user/permission_request_creator.h',
'browser/supervised_user/permission_request_creator_apiary.cc',
'browser/supervised_user/permission_request_creator_apiary.h',