diff options
author | treib <treib@chromium.org> | 2014-09-05 01:43:55 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-05 08:45:41 +0000 |
commit | 4edbded7edb6d07dea0e5ccb339142ddb3ad121b (patch) | |
tree | 2af70dafab277b58d7e7599dd0c826462203ed2c | |
parent | 767d8801ac2b97a991caf3e269b0433cd2f0148d (diff) | |
download | chromium_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}
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', |