summaryrefslogtreecommitdiffstats
path: root/chrome/browser/managed_mode
diff options
context:
space:
mode:
authorbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-19 03:44:31 +0000
committerbauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-01-19 03:44:31 +0000
commit0850e849eee0cc95c9b5c0fc8cbfd6cd8e30f3ff (patch)
treefc5b0875748b34c79c90e55552b0aea63393d416 /chrome/browser/managed_mode
parentd99126aca23d5a2e977deefc46511e105ade8241 (diff)
downloadchromium_src-0850e849eee0cc95c9b5c0fc8cbfd6cd8e30f3ff.zip
chromium_src-0850e849eee0cc95c9b5c0fc8cbfd6cd8e30f3ff.tar.gz
chromium_src-0850e849eee0cc95c9b5c0fc8cbfd6cd8e30f3ff.tar.bz2
Add ManagedUserService for profile-specific managed user data.
Because ManagedModeURLFilter is now owned by ProfileIOData, make it refcounted, so ProfileImplIOData and OffTheRecordProfileIOData can share the same filter. TBR=ben@chromium.org,evan@chromium.org BUG=169819 Review URL: https://chromiumcodereview.appspot.com/11826059 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@177813 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/managed_mode')
-rw-r--r--chrome/browser/managed_mode/managed_mode.cc353
-rw-r--r--chrome/browser/managed_mode/managed_mode.h101
-rw-r--r--chrome/browser/managed_mode/managed_mode_browsertest.cc188
-rw-r--r--chrome/browser/managed_mode/managed_mode_navigation_observer.cc12
-rw-r--r--chrome/browser/managed_mode/managed_mode_navigation_observer.h6
-rw-r--r--chrome/browser/managed_mode/managed_mode_resource_throttle.cc5
-rw-r--r--chrome/browser/managed_mode/managed_mode_resource_throttle.h3
-rw-r--r--chrome/browser/managed_mode/managed_mode_site_list.cc4
-rw-r--r--chrome/browser/managed_mode/managed_mode_site_list.h4
-rw-r--r--chrome/browser/managed_mode/managed_mode_unittest.cc31
-rw-r--r--chrome/browser/managed_mode/managed_mode_url_filter.cc27
-rw-r--r--chrome/browser/managed_mode/managed_mode_url_filter.h21
-rw-r--r--chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc30
-rw-r--r--chrome/browser/managed_mode/managed_user_service.cc353
-rw-r--r--chrome/browser/managed_mode/managed_user_service.h171
-rw-r--r--chrome/browser/managed_mode/managed_user_service_factory.cc43
-rw-r--r--chrome/browser/managed_mode/managed_user_service_factory.h34
-rw-r--r--chrome/browser/managed_mode/managed_user_service_unittest.cc220
18 files changed, 927 insertions, 679 deletions
diff --git a/chrome/browser/managed_mode/managed_mode.cc b/chrome/browser/managed_mode/managed_mode.cc
index 5eead29..5a6e1cc 100644
--- a/chrome/browser/managed_mode/managed_mode.cc
+++ b/chrome/browser/managed_mode/managed_mode.cc
@@ -8,98 +8,23 @@
#include "base/prefs/public/pref_change_registrar.h"
#include "base/sequenced_task_runner.h"
#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/managed_mode/managed_mode_site_list.h"
#include "chrome/browser/managed_mode/managed_mode_url_filter.h"
#include "chrome/browser/policy/url_blacklist_manager.h"
#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension_set.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
-// A bridge from ManagedMode (which lives on the UI thread) to
-// ManagedModeURLFilter (which might live on a different thread).
-class ManagedMode::URLFilterContext {
- public:
- explicit URLFilterContext(
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : task_runner_(task_runner) {}
- ~URLFilterContext() {}
-
- ManagedModeURLFilter* url_filter() {
- DCHECK(task_runner_->RunsTasksOnCurrentThread());
- return &url_filter_;
- }
-
- void SetDefaultFilteringBehavior(
- ManagedModeURLFilter::FilteringBehavior behavior) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // Because ManagedMode is a singleton, we can pass the pointer to
- // |url_filter_| unretained.
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&ManagedModeURLFilter::SetDefaultFilteringBehavior,
- base::Unretained(&url_filter_),
- behavior));
- }
-
- void LoadWhitelists(ScopedVector<ManagedModeSiteList> site_lists) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&ManagedModeURLFilter::LoadWhitelists,
- base::Unretained(&url_filter_),
- base::Passed(&site_lists)));
- }
-
- void SetManualLists(scoped_ptr<ListValue> whitelist,
- scoped_ptr<ListValue> blacklist) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&ManagedModeURLFilter::SetManualLists,
- base::Unretained(&url_filter_),
- base::Passed(&whitelist),
- base::Passed(&blacklist)));
- }
-
- void AddURLPatternToManualList(bool is_whitelist,
- const std::string& url) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&ManagedModeURLFilter::AddURLPatternToManualList,
- base::Unretained(&url_filter_),
- is_whitelist,
- url));
- }
-
- void ShutdownOnUIThread() {
- if (task_runner_->RunsTasksOnCurrentThread()) {
- delete this;
- return;
- }
- bool result = task_runner_->DeleteSoon(FROM_HERE, this);
- DCHECK(result);
- }
-
- private:
- ManagedModeURLFilter url_filter_;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(URLFilterContext);
-};
-
// static
ManagedMode* ManagedMode::GetInstance() {
return Singleton<ManagedMode, LeakySingletonTraits<ManagedMode> >::get();
@@ -111,17 +36,6 @@ void ManagedMode::RegisterPrefs(PrefServiceSimple* prefs) {
}
// static
-void ManagedMode::RegisterUserPrefs(PrefServiceSyncable* prefs) {
- prefs->RegisterIntegerPref(prefs::kDefaultManagedModeFilteringBehavior,
- 2,
- PrefServiceSyncable::UNSYNCABLE_PREF);
- prefs->RegisterListPref(prefs::kManagedModeWhitelist,
- PrefServiceSyncable::UNSYNCABLE_PREF);
- prefs->RegisterListPref(prefs::kManagedModeBlacklist,
- PrefServiceSyncable::UNSYNCABLE_PREF);
-}
-
-// static
void ManagedMode::Init(Profile* profile) {
GetInstance()->InitImpl(profile);
}
@@ -223,141 +137,6 @@ void ManagedMode::LeaveManagedModeImpl() {
SetInManagedMode(NULL);
}
-// static
-const ManagedModeURLFilter* ManagedMode::GetURLFilterForIOThread() {
- return GetInstance()->GetURLFilterForIOThreadImpl();
-}
-
-// static
-const ManagedModeURLFilter* ManagedMode::GetURLFilterForUIThread() {
- return GetInstance()->GetURLFilterForUIThreadImpl();
-}
-
-ManagedModeURLFilter* ManagedMode::GetURLFilterForIOThreadImpl() {
- return io_url_filter_context_->url_filter();
-}
-
-ManagedModeURLFilter* ManagedMode::GetURLFilterForUIThreadImpl() {
- return ui_url_filter_context_->url_filter();
-}
-
-// static
-void ManagedMode::AddToManualList(bool is_whitelist,
- const base::ListValue& list) {
- GetInstance()->AddToManualListImpl(is_whitelist, list);
-}
-
-void ManagedMode::AddToManualListImpl(bool is_whitelist,
- const base::ListValue& list) {
- if (!managed_profile_)
- return;
-
- ListPrefUpdate pref_update(managed_profile_->GetPrefs(),
- is_whitelist ? prefs::kManagedModeWhitelist :
- prefs::kManagedModeBlacklist);
- ListValue* pref_list = pref_update.Get();
-
- for (size_t i = 0; i < list.GetSize(); ++i) {
- std::string url_pattern;
- list.GetString(i, &url_pattern);
-
- if (!IsInManualList(is_whitelist, url_pattern)) {
- pref_list->AppendString(url_pattern);
- AddURLPatternToManualList(is_whitelist, url_pattern);
- }
- }
-}
-
-// static
-void ManagedMode::RemoveFromManualList(bool is_whitelist,
- const base::ListValue& list) {
- GetInstance()->RemoveFromManualListImpl(is_whitelist, list);
-}
-
-void ManagedMode::RemoveFromManualListImpl(bool is_whitelist,
- const base::ListValue& list) {
- ListPrefUpdate pref_update(managed_profile_->GetPrefs(),
- is_whitelist ? prefs::kManagedModeWhitelist :
- prefs::kManagedModeBlacklist);
- ListValue* pref_list = pref_update.Get();
-
- for (size_t i = 0; i < list.GetSize(); ++i) {
- std::string pattern;
- size_t out_index;
- list.GetString(i, &pattern);
- StringValue value_to_remove(pattern);
-
- pref_list->Remove(value_to_remove, &out_index);
- }
-}
-
-// static
-bool ManagedMode::IsInManualList(bool is_whitelist,
- const std::string& url_pattern) {
- return GetInstance()->IsInManualListImpl(is_whitelist, url_pattern);
-}
-
-bool ManagedMode::IsInManualListImpl(bool is_whitelist,
- const std::string& url_pattern) {
- StringValue pattern(url_pattern);
- const ListValue* list = managed_profile_->GetPrefs()->GetList(
- is_whitelist ? prefs::kManagedModeWhitelist :
- prefs::kManagedModeBlacklist);
- return list->Find(pattern) != list->end();
-}
-
-// static
-scoped_ptr<base::ListValue> ManagedMode::GetBlacklist() {
- return scoped_ptr<base::ListValue>(
- GetInstance()->managed_profile_->GetPrefs()->GetList(
- prefs::kManagedModeBlacklist)->DeepCopy()).Pass();
-}
-
-std::string ManagedMode::GetDebugPolicyProviderName() const {
- // Save the string space in official builds.
-#ifdef NDEBUG
- NOTREACHED();
- return std::string();
-#else
- return "Managed Mode";
-#endif
-}
-
-bool ManagedMode::UserMayLoad(const extensions::Extension* extension,
- string16* error) const {
- string16 tmp_error;
- if (ExtensionManagementPolicyImpl(&tmp_error))
- return true;
-
- // If the extension is already loaded, we allow it, otherwise we'd unload
- // all existing extensions.
- ExtensionService* extension_service =
- extensions::ExtensionSystem::Get(managed_profile_)->extension_service();
-
- // |extension_service| can be NULL in a unit test.
- if (extension_service &&
- extension_service->GetInstalledExtension(extension->id()))
- return true;
-
- if (error)
- *error = tmp_error;
- return false;
-}
-
-bool ManagedMode::UserMayModifySettings(const extensions::Extension* extension,
- string16* error) const {
- return ExtensionManagementPolicyImpl(error);
-}
-
-bool ManagedMode::ExtensionManagementPolicyImpl(string16* error) const {
- if (!IsInManagedModeImpl())
- return true;
-
- if (error)
- *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE);
- return false;
-}
-
void ManagedMode::OnBrowserAdded(Browser* browser) {
// Return early if we don't have any queued callbacks.
if (callbacks_.empty())
@@ -384,14 +163,7 @@ void ManagedMode::OnBrowserRemoved(Browser* browser) {
FinalizeEnter(true);
}
-ManagedMode::ManagedMode()
- : managed_profile_(NULL),
- io_url_filter_context_(
- new URLFilterContext(
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO))),
- ui_url_filter_context_(
- new URLFilterContext(
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI))) {
+ManagedMode::ManagedMode() : managed_profile_(NULL) {
BrowserList::AddObserver(this);
}
@@ -401,38 +173,26 @@ ManagedMode::~ManagedMode() {
BrowserList::RemoveObserver(this);
DCHECK_EQ(0u, callbacks_.size());
DCHECK_EQ(0u, browsers_to_close_.size());
- io_url_filter_context_.release()->ShutdownOnUIThread();
- ui_url_filter_context_.release()->ShutdownOnUIThread();
}
void ManagedMode::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
+ // Return early if we don't have any queued callbacks.
+ if (callbacks_.empty())
+ return;
+
switch (type) {
case chrome::NOTIFICATION_CLOSE_ALL_BROWSERS_REQUEST: {
- if (!callbacks_.empty())
- FinalizeEnter(false);
+ FinalizeEnter(false);
return;
}
case chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED: {
Browser* browser = content::Source<Browser>(source).ptr();
- if (!callbacks_.empty() && browsers_to_close_.find(browser) !=
- browsers_to_close_.end())
+ if (browsers_to_close_.find(browser) != browsers_to_close_.end())
FinalizeEnter(false);
return;
}
- case chrome::NOTIFICATION_EXTENSION_LOADED:
- case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
- if (!managed_profile_)
- break;
-
- const extensions::Extension* extension =
- content::Details<const extensions::Extension>(details).ptr();
- if (!extension->GetContentPackSiteList().empty())
- UpdateManualListsImpl();
-
- break;
- }
default:
NOTREACHED();
}
@@ -441,6 +201,7 @@ void ManagedMode::Observe(int type,
void ManagedMode::FinalizeEnter(bool result) {
if (result)
SetInManagedMode(managed_profile_);
+
for (std::vector<EnterCallback>::iterator it = callbacks_.begin();
it != callbacks_.end(); ++it) {
it->Run(result);
@@ -461,49 +222,9 @@ bool ManagedMode::PlatformConfirmLeave() {
}
void ManagedMode::SetInManagedMode(Profile* newly_managed_profile) {
- // Register the ManagementPolicy::Provider before changing the pref when
- // setting it, and unregister it after changing the pref when clearing it,
- // so pref observers see the correct ManagedMode state.
- bool in_managed_mode = !!newly_managed_profile;
- if (in_managed_mode) {
- DCHECK(!managed_profile_ || managed_profile_ == newly_managed_profile);
- extensions::ExtensionSystem::Get(
- newly_managed_profile)->management_policy()->RegisterProvider(this);
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(newly_managed_profile));
- registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(newly_managed_profile));
- pref_change_registrar_.reset(new PrefChangeRegistrar());
- pref_change_registrar_->Init(newly_managed_profile->GetPrefs());
- pref_change_registrar_->Add(
- prefs::kDefaultManagedModeFilteringBehavior,
- base::Bind(
- &ManagedMode::OnDefaultFilteringBehaviorChanged,
- base::Unretained(this)));
- } else {
- extensions::ExtensionSystem::Get(
- managed_profile_)->management_policy()->UnregisterProvider(this);
- registrar_.Remove(this, chrome::NOTIFICATION_EXTENSION_LOADED,
- content::Source<Profile>(managed_profile_));
- registrar_.Remove(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
- content::Source<Profile>(managed_profile_));
- pref_change_registrar_.reset();
- }
-
managed_profile_ = newly_managed_profile;
- ManagedModeURLFilter::FilteringBehavior behavior =
- ManagedModeURLFilter::ALLOW;
- if (in_managed_mode) {
- int behavior_value = managed_profile_->GetPrefs()->GetInteger(
- prefs::kDefaultManagedModeFilteringBehavior);
- behavior = ManagedModeURLFilter::BehaviorFromInt(behavior_value);
- }
- io_url_filter_context_->SetDefaultFilteringBehavior(behavior);
- ui_url_filter_context_->SetDefaultFilteringBehavior(behavior);
g_browser_process->local_state()->SetBoolean(prefs::kInManagedMode,
- in_managed_mode);
- if (in_managed_mode)
- UpdateManualListsImpl();
+ !!newly_managed_profile);
// This causes the avatar and the profile menu to get updated.
content::NotificationService::current()->Notify(
@@ -511,59 +232,3 @@ void ManagedMode::SetInManagedMode(Profile* newly_managed_profile) {
content::NotificationService::AllBrowserContextsAndSources(),
content::NotificationService::NoDetails());
}
-
-ScopedVector<ManagedModeSiteList> ManagedMode::GetActiveSiteLists() {
- DCHECK(managed_profile_);
- ExtensionService* extension_service =
- extensions::ExtensionSystem::Get(managed_profile_)->extension_service();
- const ExtensionSet* extensions = extension_service->extensions();
- ScopedVector<ManagedModeSiteList> site_lists;
- for (ExtensionSet::const_iterator it = extensions->begin();
- it != extensions->end(); ++it) {
- const extensions::Extension* extension = *it;
- if (!extension_service->IsExtensionEnabled(extension->id()))
- continue;
-
- ExtensionResource site_list = extension->GetContentPackSiteList();
- if (!site_list.empty())
- site_lists.push_back(new ManagedModeSiteList(extension->id(), site_list));
- }
-
- return site_lists.Pass();
-}
-
-void ManagedMode::OnDefaultFilteringBehaviorChanged() {
- DCHECK(IsInManagedModeImpl());
-
- int behavior_value = managed_profile_->GetPrefs()->GetInteger(
- prefs::kDefaultManagedModeFilteringBehavior);
- ManagedModeURLFilter::FilteringBehavior behavior =
- ManagedModeURLFilter::BehaviorFromInt(behavior_value);
- io_url_filter_context_->SetDefaultFilteringBehavior(behavior);
- ui_url_filter_context_->SetDefaultFilteringBehavior(behavior);
-}
-
-// Static
-void ManagedMode::UpdateManualLists() {
- GetInstance()->UpdateManualListsImpl();
-}
-
-void ManagedMode::UpdateManualListsImpl() {
- io_url_filter_context_->LoadWhitelists(GetActiveSiteLists());
- ui_url_filter_context_->LoadWhitelists(GetActiveSiteLists());
- io_url_filter_context_->SetManualLists(GetWhitelist(), GetBlacklist());
- ui_url_filter_context_->SetManualLists(GetWhitelist(), GetBlacklist());
-}
-
-scoped_ptr<base::ListValue> ManagedMode::GetWhitelist() {
- return make_scoped_ptr(
- managed_profile_->GetPrefs()->GetList(
- prefs::kManagedModeWhitelist)->DeepCopy());
-}
-
-void ManagedMode::AddURLPatternToManualList(
- bool is_whitelist,
- const std::string& url_pattern) {
- io_url_filter_context_->AddURLPatternToManualList(true, url_pattern);
- ui_url_filter_context_->AddURLPatternToManualList(true, url_pattern);
-}
diff --git a/chrome/browser/managed_mode/managed_mode.h b/chrome/browser/managed_mode/managed_mode.h
index f7d998a..a079128 100644
--- a/chrome/browser/managed_mode/managed_mode.h
+++ b/chrome/browser/managed_mode/managed_mode.h
@@ -11,9 +11,9 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
-#include "chrome/browser/extensions/management_policy.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -28,23 +28,21 @@ class PrefServiceSimple;
class PrefServiceSyncable;
class Profile;
-namespace policy{
+namespace policy {
class URLBlacklist;
}
-// Managed mode allows one person to manage the Chrome experience for another
-// person by pre-configuring and then locking a managed User profile.
+// Managed mode locks the UI to a certain managed user profile, preventing the
+// user from accessing other profiles.
// The ManagedMode class provides methods to check whether the browser is in
// managed mode, and to attempt to enter or leave managed mode.
// Except where otherwise noted, this class should be used on the UI thread.
class ManagedMode : public chrome::BrowserListObserver,
- public extensions::ManagementPolicy::Provider,
public content::NotificationObserver {
public:
typedef base::Callback<void(bool)> EnterCallback;
static void RegisterPrefs(PrefServiceSimple* prefs);
- static void RegisterUserPrefs(PrefServiceSyncable* prefs);
// Initializes the singleton, setting the managed_profile_. Must be called
// after g_browser_process and the LocalState have been created.
@@ -56,51 +54,6 @@ class ManagedMode : public chrome::BrowserListObserver,
static void EnterManagedMode(Profile* profile, const EnterCallback& callback);
static void LeaveManagedMode();
- // Returns the URL filter for the IO thread, for filtering network requests
- // (in ChromeNetworkDelegate).
- // This method should only be called on the IO thread.
- static const ManagedModeURLFilter* GetURLFilterForIOThread();
-
- // Returns the URL filter for the UI thread, for filtering navigations and
- // classifying sites in the history view.
- // This method should only be called on the UI thread.
- static const ManagedModeURLFilter* GetURLFilterForUIThread();
-
- // The functions that handle manual whitelists use |url_pattern| or lists
- // of "url patterns". An "url pattern" is a pattern in the format used by the
- // policy::URLBlacklist filter. A description of the format used can be found
- // here: http://dev.chromium.org/administrators/url-blacklist-filter-format.
- // They all receive the |is_whitelist| parameter which dictates whether they
- // act on the whitelist (for |is_whitelist| == true) or on the blacklist (for
- // |is_whitelist| == false).
-
- // Checks if the |url_pattern| is in the manual whitelist.
- static bool IsInManualList(const bool is_whitelist,
- const std::string& url_pattern);
-
- // Appends |list| to the manual white/black list (according to |is_whitelist|)
- // both in URL filter and in preferences.
- static void AddToManualList(const bool is_whitelist,
- const base::ListValue& list);
-
- // Removes |list| from the manual white/black list (according to
- // |is_whitelist|) both in URL filter and in preferences.
- static void RemoveFromManualList(const bool is_whitelist,
- const base::ListValue& list);
-
- // Updates the whitelist and the blacklist from the prefs.
- static void UpdateManualLists();
-
- // Returns the profile blacklist.
- static scoped_ptr<base::ListValue> GetBlacklist();
-
- // ExtensionManagementPolicy::Provider implementation:
- virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
- virtual bool UserMayLoad(const extensions::Extension* extension,
- string16* error) const OVERRIDE;
- virtual bool UserMayModifySettings(const extensions::Extension* extension,
- string16* error) const OVERRIDE;
-
// chrome::BrowserListObserver implementation:
virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
@@ -119,8 +72,6 @@ class ManagedMode : public chrome::BrowserListObserver,
Profile* managed_profile_;
private:
- class URLFilterContext;
-
friend class Singleton<ManagedMode, LeakySingletonTraits<ManagedMode> >;
friend struct DefaultSingletonTraits<ManagedMode>;
FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest, ManagedModeOnChange);
@@ -132,16 +83,8 @@ class ManagedMode : public chrome::BrowserListObserver,
virtual void InitImpl(Profile* profile);
- // Internal implementation for ExtensionManagementPolicy::Delegate methods.
- // If |error| is not NULL, it will be filled with an error message if the
- // requested extension action (install, modify status, etc.) is not permitted.
- bool ExtensionManagementPolicyImpl(string16* error) const;
-
void LeaveManagedModeImpl();
- ManagedModeURLFilter* GetURLFilterForIOThreadImpl();
- ManagedModeURLFilter* GetURLFilterForUIThreadImpl();
-
void FinalizeEnter(bool result);
// Platform-specific methods that confirm whether we can enter or leave
@@ -158,43 +101,7 @@ class ManagedMode : public chrome::BrowserListObserver,
// testing).
virtual void SetInManagedMode(Profile* newly_managed_profile);
- // Returns a list of all installed and enabled site lists in the current
- // managed profile.
- // This method should only be called if managed mode is active.
- ScopedVector<ManagedModeSiteList> GetActiveSiteLists();
-
- void OnDefaultFilteringBehaviorChanged();
-
- void UpdateManualListsImpl();
-
- // Returns a copy of the manual whitelist which is stored in each profile.
- scoped_ptr<base::ListValue> GetWhitelist();
-
- // The following functions use |is_whitelist| to select between the whitelist
- // and the blacklist as the target of the function. If |is_whitelist| is true
- // |url_pattern| is added to the whitelist, otherwise it is added to the
- // blacklist.
-
- void RemoveFromManualListImpl(const bool is_whitelist,
- const base::ListValue& whitelist);
-
- // Adds the |url_pattern| to the manual lists in the URL filter. This is used
- // by AddToManualListImpl().
- void AddURLPatternToManualList(const bool is_whitelist,
- const std::string& url_pattern);
-
- void AddToManualListImpl(const bool is_whitelist,
- const base::ListValue& whitelist);
-
- bool IsInManualListImpl(const bool is_whitelist,
- const std::string& url_pattern);
-
content::NotificationRegistrar registrar_;
- scoped_ptr<PrefChangeRegistrar> pref_change_registrar_;
-
- scoped_ptr<URLFilterContext> io_url_filter_context_;
- scoped_ptr<URLFilterContext> ui_url_filter_context_;
-
std::set<Browser*> browsers_to_close_;
std::vector<EnterCallback> callbacks_;
diff --git a/chrome/browser/managed_mode/managed_mode_browsertest.cc b/chrome/browser/managed_mode/managed_mode_browsertest.cc
index 1aef679..9b0db77 100644
--- a/chrome/browser/managed_mode/managed_mode_browsertest.cc
+++ b/chrome/browser/managed_mode/managed_mode_browsertest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -6,13 +6,14 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
-#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/managed_mode/managed_mode.h"
-#include "chrome/browser/managed_mode/managed_mode_url_filter.h"
-#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
+#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/common/chrome_notification_types.h"
@@ -26,129 +27,12 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
-#include "content/public/test/test_utils.h"
-#include "googleurl/src/gurl.h"
using content::InterstitialPage;
-using content::MessageLoopRunner;
using content::NavigationController;
using content::NavigationEntry;
using content::WebContents;
-namespace {
-
-class ManagedModeURLFilterObserver : public ManagedModeURLFilter::Observer {
- public:
- explicit ManagedModeURLFilterObserver(ManagedModeURLFilter* url_filter)
- : url_filter_(url_filter) {
- Reset();
- url_filter_->AddObserver(this);
- }
-
- ~ManagedModeURLFilterObserver() {
- url_filter_->RemoveObserver(this);
- }
-
- void Wait() {
- message_loop_runner_->Run();
- Reset();
- }
-
- // ManagedModeURLFilter::Observer
- virtual void OnSiteListUpdated() OVERRIDE {
- message_loop_runner_->Quit();
- }
-
- private:
- void Reset() {
- message_loop_runner_ = new MessageLoopRunner;
- }
-
- ManagedModeURLFilter* url_filter_;
- scoped_refptr<MessageLoopRunner> message_loop_runner_;
-};
-
-} // namespace
-
-class ManagedModeContentPackTest : public ExtensionBrowserTest {
- public:
- ManagedModeContentPackTest() {}
- virtual ~ManagedModeContentPackTest() {}
-
- virtual void SetUpOnMainThread() OVERRIDE {
- PrefService* prefs = browser()->profile()->GetPrefs();
- prefs->SetInteger(prefs::kDefaultManagedModeFilteringBehavior,
- ManagedModeURLFilter::WARN);
- }
-};
-
-IN_PROC_BROWSER_TEST_F(ManagedModeContentPackTest, InstallContentPacks) {
- ManagedMode* managed_mode = ManagedMode::GetInstance();
- ManagedModeURLFilter* url_filter =
- managed_mode->GetURLFilterForUIThreadImpl();
- ManagedModeURLFilterObserver observer(url_filter);
-
- GURL example_url("http://example.com");
- GURL moose_url("http://moose.org");
- EXPECT_EQ(ManagedModeURLFilter::ALLOW,
- url_filter->GetFilteringBehaviorForURL(example_url));
-
- managed_mode->SetInManagedMode(browser()->profile());
- observer.Wait();
-
- EXPECT_EQ(ManagedModeURLFilter::WARN,
- url_filter->GetFilteringBehaviorForURL(example_url));
-
- // Load a content pack.
- const extensions::Extension* extension = LoadExtension(
- test_data_dir_.AppendASCII("managed_mode/content_pack"));
- ASSERT_TRUE(extension) << "Failed to load extension.";
- observer.Wait();
-
- ScopedVector<ManagedModeSiteList> site_lists =
- managed_mode->GetActiveSiteLists();
- ASSERT_EQ(1u, site_lists.size());
- std::vector<ManagedModeSiteList::Site> sites;
- site_lists[0]->GetSites(&sites);
- ASSERT_EQ(3u, sites.size());
- EXPECT_EQ(ASCIIToUTF16("YouTube"), sites[0].name);
- EXPECT_EQ(ASCIIToUTF16("Homestar Runner"), sites[1].name);
- EXPECT_EQ(string16(), sites[2].name);
-
- EXPECT_EQ(ManagedModeURLFilter::ALLOW,
- url_filter->GetFilteringBehaviorForURL(example_url));
- EXPECT_EQ(ManagedModeURLFilter::WARN,
- url_filter->GetFilteringBehaviorForURL(moose_url));
-
- // Load a second content pack.
- extension = LoadExtension(
- test_data_dir_.AppendASCII("managed_mode/content_pack_2"));
- ASSERT_TRUE(extension) << "Failed to load extension.";
- observer.Wait();
-
- site_lists = managed_mode->GetActiveSiteLists();
- ASSERT_EQ(2u, site_lists.size());
- sites.clear();
- site_lists[0]->GetSites(&sites);
- site_lists[1]->GetSites(&sites);
- ASSERT_EQ(4u, sites.size());
- // The site lists might be returned in any order, so we put them into a set.
- std::set<std::string> site_names;
- for (std::vector<ManagedModeSiteList::Site>::const_iterator it =
- sites.begin(); it != sites.end(); ++it) {
- site_names.insert(UTF16ToUTF8(it->name));
- }
- EXPECT_TRUE(site_names.count("YouTube") == 1u);
- EXPECT_TRUE(site_names.count("Homestar Runner") == 1u);
- EXPECT_TRUE(site_names.count(std::string()) == 1u);
- EXPECT_TRUE(site_names.count("Moose") == 1u);
-
- EXPECT_EQ(ManagedModeURLFilter::ALLOW,
- url_filter->GetFilteringBehaviorForURL(example_url));
- EXPECT_EQ(ManagedModeURLFilter::ALLOW,
- url_filter->GetFilteringBehaviorForURL(moose_url));
-}
-
// TODO(sergiu): Make the webkit error message disappear when navigating to an
// interstitial page. The message states: "Not allowed to load local resource:
// chrome://resources/css/widgets.css" followed by the compiled page.
@@ -172,7 +56,8 @@ class ManagedModeBlockModeTest : public InProcessBrowserTest {
INFOBAR_NOT_USED,
};
- ManagedModeBlockModeTest() {}
+ ManagedModeBlockModeTest() : managed_user_service_(NULL) {}
+ virtual ~ManagedModeBlockModeTest() {}
// Builds the redirect URL for the testserver from the hostnames and the
// final URL and returns it as a string.
@@ -274,7 +159,14 @@ class ManagedModeBlockModeTest : public InProcessBrowserTest {
}
protected:
- virtual void SetUpCommandLine(CommandLine* command_line) {
+ virtual void SetUpOnMainThread() OVERRIDE {
+ Profile* profile = browser()->profile();
+ managed_user_service_ = ManagedUserServiceFactory::GetForProfile(profile);
+ profile->GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true);
+ managed_user_service_->Init();
+ }
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
// Enable the test server and remap all URLs to it.
ASSERT_TRUE(test_server()->Start());
std::string host_port = test_server()->host_port_pair().ToString();
@@ -285,8 +177,7 @@ class ManagedModeBlockModeTest : public InProcessBrowserTest {
"MAP *.a.com " + host_port);
}
- private:
- DISALLOW_COPY_AND_ASSIGN(ManagedModeBlockModeTest);
+ ManagedUserService* managed_user_service_;
};
// Navigates to a URL which is not in a manual list, clicks preview on the
@@ -301,7 +192,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest, SimpleURLNotInAnyLists) {
CheckShownPageIsInterstitial(tab);
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// Same as above just that the URL redirects to a second URL first. The initial
@@ -319,9 +210,9 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest, RedirectedURLsNotInAnyLists) {
CheckShownPageIsInterstitial(tab);
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
- EXPECT_TRUE(ManagedMode::IsInManualList(true,
- "http://.www.a.com/server-redirect"));
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(
+ true, "http://.www.a.com/server-redirect"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// Navigates to a URL in the whitelist. No interstitial should be shown and
@@ -330,7 +221,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest, SimpleURLInWhitelist) {
GURL test_url("http://www.example.com/files/simple.html");
ListValue whitelist;
whitelist.AppendString(test_url.host());
- ManagedMode::AddToManualList(true, whitelist);
+ managed_user_service_->AddToManualList(true, whitelist);
ui_test_utils::NavigateToURL(browser(), test_url);
@@ -338,7 +229,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest, SimpleURLInWhitelist) {
CheckShownPageIsNotInterstitial(tab);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// Navigates to a URL which redirects to another URL, both in the whitelist.
@@ -354,7 +245,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
ListValue whitelist;
whitelist.AppendString("www.a.com");
whitelist.AppendString("www.example.com");
- ManagedMode::AddToManualList(true, whitelist);
+ managed_user_service_->AddToManualList(true, whitelist);
ui_test_utils::NavigateToURL(browser(), test_url);
@@ -362,8 +253,8 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
CheckShownPageIsNotInterstitial(tab);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.a.com"));
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.a.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// Only one URL is in the whitelist and the second not, so it should redirect,
@@ -379,7 +270,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
// Add the first URL to the whitelist.
ListValue whitelist;
whitelist.AppendString("www.a.com");
- ManagedMode::AddToManualList(true, whitelist);
+ managed_user_service_->AddToManualList(true, whitelist);
ui_test_utils::NavigateToURL(browser(), test_url);
@@ -389,8 +280,8 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
CheckShownPageIsInterstitial(tab);
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.a.com"));
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.a.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// This test navigates to a URL which is not in the whitelist but redirects to
@@ -407,7 +298,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
// Add the last URL to the whitelist.
ListValue whitelist;
whitelist.AppendString("www.example.com");
- ManagedMode::AddToManualList(true, whitelist);
+ managed_user_service_->AddToManualList(true, whitelist);
ui_test_utils::NavigateToURL(browser(), test_url);
@@ -418,9 +309,9 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED,
INFOBAR_ALREADY_ADDED);
- EXPECT_TRUE(ManagedMode::IsInManualList(true,
- "http://.www.a.com/server-redirect"));
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(
+ true, "http://.www.a.com/server-redirect"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// Tests whether going back after being shown an interstitial works. No
@@ -438,7 +329,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
EXPECT_EQ(tab->GetURL().spec(), "about:blank");
- EXPECT_FALSE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_FALSE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// Like SimpleURLNotInAnyLists just that it navigates to a page on the allowed
@@ -454,7 +345,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
CheckShownPageIsInterstitial(tab);
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
// Navigate to a different page on the same host.
test_url = GURL("http://www.example.com/files/english_page.html");
@@ -477,7 +368,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
CheckShownPageIsInterstitial(tab);
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
// Reload the page
tab->GetController().Reload(false);
@@ -504,7 +395,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
// Check that the https:// version is added in the whitelist.
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "https://www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "https://www.example.com"));
}
// The test navigates to a page, the interstitial is shown and preview is
@@ -569,7 +460,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
CheckNumberOfInfobars(0);
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true, "www.example.com"));
}
// The test navigates to a page, the interstitial is shown and preview is
@@ -614,6 +505,7 @@ IN_PROC_BROWSER_TEST_F(ManagedModeBlockModeTest,
ActOnInterstitialAndInfobar(tab, INTERSTITIAL_PROCEED, INFOBAR_ACCEPT);
- EXPECT_FALSE(ManagedMode::IsInManualList(true, "www.example.com"));
- EXPECT_TRUE(ManagedMode::IsInManualList(true, "www.new-example.com"));
+ EXPECT_FALSE(managed_user_service_->IsInManualList(true, "www.example.com"));
+ EXPECT_TRUE(managed_user_service_->IsInManualList(true,
+ "www.new-example.com"));
}
diff --git a/chrome/browser/managed_mode/managed_mode_navigation_observer.cc b/chrome/browser/managed_mode/managed_mode_navigation_observer.cc
index 7faf56a..f935b0e 100644
--- a/chrome/browser/managed_mode/managed_mode_navigation_observer.cc
+++ b/chrome/browser/managed_mode/managed_mode_navigation_observer.cc
@@ -14,6 +14,8 @@
#include "chrome/browser/managed_mode/managed_mode_interstitial.h"
#include "chrome/browser/managed_mode/managed_mode_resource_throttle.h"
#include "chrome/browser/managed_mode/managed_mode_url_filter.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/managed_mode/managed_user_service_factory.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
@@ -231,11 +233,15 @@ ManagedModeNavigationObserver::~ManagedModeNavigationObserver() {
ManagedModeNavigationObserver::ManagedModeNavigationObserver(
content::WebContents* web_contents)
: WebContentsObserver(web_contents),
- url_filter_(ManagedMode::GetURLFilterForUIThread()),
warn_infobar_delegate_(NULL),
preview_infobar_delegate_(NULL),
state_(RECORDING_URLS_BEFORE_PREVIEW),
- last_allowed_page_(-1) {}
+ last_allowed_page_(-1) {
+ Profile* profile =
+ Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ managed_user_service_ = ManagedUserServiceFactory::GetForProfile(profile);
+ url_filter_ = managed_user_service_->GetURLFilterForUIThread();
+}
void ManagedModeNavigationObserver::AddTemporaryException() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -289,7 +295,7 @@ void ManagedModeNavigationObserver::AddSavedURLsToWhitelistAndClearState() {
whitelist.AppendString(last_url_.host());
}
}
- ManagedMode::AddToManualList(true, whitelist);
+ managed_user_service_->AddToManualList(true, whitelist);
ClearObserverState();
}
diff --git a/chrome/browser/managed_mode/managed_mode_navigation_observer.h b/chrome/browser/managed_mode/managed_mode_navigation_observer.h
index 53ab1c9..3fb4bd3 100644
--- a/chrome/browser/managed_mode/managed_mode_navigation_observer.h
+++ b/chrome/browser/managed_mode/managed_mode_navigation_observer.h
@@ -13,6 +13,7 @@
class InfoBarDelegate;
class ManagedModeURLFilter;
+class ManagedUserService;
class ManagedModeNavigationObserver
: public content::WebContentsObserver,
@@ -106,7 +107,10 @@ class ManagedModeNavigationObserver
content::PageTransition transition_type,
content::RenderViewHost* render_view_host) OVERRIDE;
- // Owned by ManagedMode (which is a singleton and outlives us).
+ // Owned by the profile, so outlives us.
+ ManagedUserService* managed_user_service_;
+
+ // Owned by ManagedUserService.
const ManagedModeURLFilter* url_filter_;
// Owned by the InfoBarService, which has the same lifetime as this object.
diff --git a/chrome/browser/managed_mode/managed_mode_resource_throttle.cc b/chrome/browser/managed_mode/managed_mode_resource_throttle.cc
index a8f60eea..a7208a3 100644
--- a/chrome/browser/managed_mode/managed_mode_resource_throttle.cc
+++ b/chrome/browser/managed_mode/managed_mode_resource_throttle.cc
@@ -26,14 +26,15 @@ ManagedModeResourceThrottle::ManagedModeResourceThrottle(
const net::URLRequest* request,
int render_process_host_id,
int render_view_id,
- bool is_main_frame)
+ bool is_main_frame,
+ const ManagedModeURLFilter* url_filter)
: ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
request_(request),
render_process_host_id_(render_process_host_id),
render_view_id_(render_view_id),
is_main_frame_(is_main_frame),
temporarily_allowed_(false),
- url_filter_(ManagedMode::GetURLFilterForIOThread()) {}
+ url_filter_(url_filter) {}
ManagedModeResourceThrottle::~ManagedModeResourceThrottle() {}
diff --git a/chrome/browser/managed_mode/managed_mode_resource_throttle.h b/chrome/browser/managed_mode/managed_mode_resource_throttle.h
index 1a33e66..f49f006 100644
--- a/chrome/browser/managed_mode/managed_mode_resource_throttle.h
+++ b/chrome/browser/managed_mode/managed_mode_resource_throttle.h
@@ -20,7 +20,8 @@ class ManagedModeResourceThrottle : public content::ResourceThrottle {
ManagedModeResourceThrottle(const net::URLRequest* request,
int render_process_host_id,
int render_view_id,
- bool is_main_frame);
+ bool is_main_frame,
+ const ManagedModeURLFilter* url_filter);
virtual ~ManagedModeResourceThrottle();
// Adds/removes a temporary exception to filtering for a
diff --git a/chrome/browser/managed_mode/managed_mode_site_list.cc b/chrome/browser/managed_mode/managed_mode_site_list.cc
index 872524d..ceb1e29 100644
--- a/chrome/browser/managed_mode/managed_mode_site_list.cc
+++ b/chrome/browser/managed_mode/managed_mode_site_list.cc
@@ -142,6 +142,10 @@ ManagedModeSiteList::ManagedModeSiteList(const std::string& extension_id,
ManagedModeSiteList::~ManagedModeSiteList() {
}
+ManagedModeSiteList* ManagedModeSiteList::Clone() {
+ return new ManagedModeSiteList(extension_id_, path_);
+}
+
// static
void ManagedModeSiteList::GetCategoryNames(std::vector<string16>* categories) {
// TODO(bauerb): Collect custom categories from extensions.
diff --git a/chrome/browser/managed_mode/managed_mode_site_list.h b/chrome/browser/managed_mode/managed_mode_site_list.h
index 4757764..015b005 100644
--- a/chrome/browser/managed_mode/managed_mode_site_list.h
+++ b/chrome/browser/managed_mode/managed_mode_site_list.h
@@ -62,6 +62,10 @@ class ManagedModeSiteList {
const ExtensionResource& path);
~ManagedModeSiteList();
+ // Creates a copy of the site list.
+ // Caller takes ownership of the returned value.
+ ManagedModeSiteList* Clone();
+
// Returns a list of all categories.
// TODO(bauerb): The list is hardcoded for now, but if we allow custom
// categories, this should live in some registry.
diff --git a/chrome/browser/managed_mode/managed_mode_unittest.cc b/chrome/browser/managed_mode/managed_mode_unittest.cc
index 1e2e192..3b128ef 100644
--- a/chrome/browser/managed_mode/managed_mode_unittest.cc
+++ b/chrome/browser/managed_mode/managed_mode_unittest.cc
@@ -232,34 +232,3 @@ TEST_F(ManagedModeTest, Cancelled) {
managed_mode_.EnterManagedModeForTesting(&managed_mode_profile_,
CreateExpectedCallback(false));
}
-
-TEST_F(ManagedModeTest, ExtensionManagementPolicyProvider) {
- BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_);
-
- {
- string16 error;
- EXPECT_TRUE(managed_mode_.UserMayLoad(NULL, &error));
- EXPECT_EQ(string16(), error);
- }
- {
- string16 error;
- EXPECT_TRUE(managed_mode_.UserMayModifySettings(NULL, &error));
- EXPECT_EQ(string16(), error);
- }
-
- managed_mode_.SetInManagedMode(&managed_mode_profile_);
- {
- string16 error;
- EXPECT_FALSE(managed_mode_.UserMayLoad(NULL, &error));
- EXPECT_FALSE(error.empty());
- }
- {
- string16 error;
- EXPECT_FALSE(managed_mode_.UserMayModifySettings(NULL, &error));
- EXPECT_FALSE(error.empty());
- }
-
-#ifndef NDEBUG
- EXPECT_FALSE(managed_mode_.GetDebugPolicyProviderName().empty());
-#endif
-}
diff --git a/chrome/browser/managed_mode/managed_mode_url_filter.cc b/chrome/browser/managed_mode/managed_mode_url_filter.cc
index 4534321..ff131f6 100644
--- a/chrome/browser/managed_mode/managed_mode_url_filter.cc
+++ b/chrome/browser/managed_mode/managed_mode_url_filter.cc
@@ -157,15 +157,14 @@ scoped_ptr<ManagedModeURLFilter::Contents> LoadWhitelistsOnBlockingPoolThread(
} // namespace
ManagedModeURLFilter::ManagedModeURLFilter()
- : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
- default_behavior_(ALLOW),
+ : default_behavior_(ALLOW),
contents_(new Contents()),
url_manual_list_allow_(new policy::URLBlacklist()),
url_manual_list_block_(new policy::URLBlacklist()) {
// Set empty manual lists in the begining.
- scoped_ptr<base::ListValue> whitelist(new base::ListValue());
- scoped_ptr<base::ListValue> blacklist(new base::ListValue());
- SetManualLists(whitelist.Pass(), blacklist.Pass());
+ base::ListValue whitelist;
+ base::ListValue blacklist;
+ SetManualLists(&whitelist, &blacklist);
// Detach from the current thread so we can be constructed on a different
// thread than the one where we're used.
DetachFromThread();
@@ -262,8 +261,7 @@ void ManagedModeURLFilter::LoadWhitelists(
FROM_HERE,
base::Bind(&LoadWhitelistsOnBlockingPoolThread,
base::Passed(&site_lists)),
- base::Bind(&ManagedModeURLFilter::SetContents,
- weak_ptr_factory_.GetWeakPtr()));
+ base::Bind(&ManagedModeURLFilter::SetContents, this));
}
void ManagedModeURLFilter::SetFromPatterns(
@@ -274,31 +272,30 @@ void ManagedModeURLFilter::SetFromPatterns(
BrowserThread::GetBlockingPool(),
FROM_HERE,
base::Bind(&CreateWhitelistFromPatterns, patterns),
- base::Bind(&ManagedModeURLFilter::SetContents,
- weak_ptr_factory_.GetWeakPtr()));
+ base::Bind(&ManagedModeURLFilter::SetContents, this));
}
-void ManagedModeURLFilter::SetManualLists(scoped_ptr<ListValue> whitelist,
- scoped_ptr<ListValue> blacklist){
+void ManagedModeURLFilter::SetManualLists(const ListValue* whitelist,
+ const ListValue* blacklist) {
DCHECK(CalledOnValidThread());
url_manual_list_block_.reset(new policy::URLBlacklist);
url_manual_list_allow_.reset(new policy::URLBlacklist);
- url_manual_list_block_->Block(blacklist.get());
+ url_manual_list_block_->Block(blacklist);
ListValue all_sites;
all_sites.Append(new base::StringValue("*"));
- url_manual_list_allow_->Allow(whitelist.get());
+ url_manual_list_allow_->Allow(whitelist);
url_manual_list_allow_->Block(&all_sites);
// Debug
DVLOG(1) << "Loaded whitelist: ";
- for (ListValue::iterator it = whitelist->begin();
+ for (ListValue::const_iterator it = whitelist->begin();
it != whitelist->end(); ++it){
std::string item;
(*it)->GetAsString(&item);
DVLOG(1) << item;
}
DVLOG(1) << "Loaded blacklist: ";
- for (ListValue::iterator it = blacklist->begin();
+ for (ListValue::const_iterator it = blacklist->begin();
it != blacklist->end(); ++it){
std::string item;
(*it)->GetAsString(&item);
diff --git a/chrome/browser/managed_mode/managed_mode_url_filter.h b/chrome/browser/managed_mode/managed_mode_url_filter.h
index 53a53ea..cb2020b 100644
--- a/chrome/browser/managed_mode/managed_mode_url_filter.h
+++ b/chrome/browser/managed_mode/managed_mode_url_filter.h
@@ -6,13 +6,14 @@
#define CHROME_BROWSER_MANAGED_MODE_MANAGED_MODE_URL_FILTER_H_
#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
-#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "base/values.h"
#include "chrome/browser/managed_mode/managed_mode_site_list.h"
+#include "chrome/browser/policy/url_blacklist_manager.h"
namespace policy {
class URLBlacklist;
@@ -23,9 +24,12 @@ class GURL;
// 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 is not thread-safe, so it can only be used on one thread, but that can be
-// any thread.
-class ManagedModeURLFilter : public base::NonThreadSafe {
+// References to it can be passed around on different threads (the refcounting
+// is thread-safe), but the object itself should always be accessed on the same
+// thread (member access isn't thread-safe).
+class ManagedModeURLFilter
+ : public base::RefCountedThreadSafe<ManagedModeURLFilter>,
+ public base::NonThreadSafe {
public:
enum FilteringBehavior {
ALLOW,
@@ -41,7 +45,6 @@ class ManagedModeURLFilter : public base::NonThreadSafe {
struct Contents;
ManagedModeURLFilter();
- ~ManagedModeURLFilter();
static FilteringBehavior BehaviorFromInt(int behavior_value);
@@ -65,8 +68,8 @@ class ManagedModeURLFilter : public base::NonThreadSafe {
void SetFromPatterns(const std::vector<std::string>& patterns);
// Sets the manual lists.
- void SetManualLists(scoped_ptr<ListValue> whitelist,
- scoped_ptr<ListValue> blacklist);
+ void SetManualLists(const ListValue* whitelist,
+ const ListValue* blacklist);
// Adds a pattern to a manual list. If |is_whitelist| is true it gets added
// to the whitelist, else to the blacklist.
@@ -77,11 +80,13 @@ class ManagedModeURLFilter : public base::NonThreadSafe {
void RemoveObserver(Observer* observer);
private:
+ friend class base::RefCountedThreadSafe<ManagedModeURLFilter>;
+ ~ManagedModeURLFilter();
+
void SetContents(scoped_ptr<Contents> url_matcher);
ObserverList<Observer> observers_;
- base::WeakPtrFactory<ManagedModeURLFilter> weak_ptr_factory_;
FilteringBehavior default_behavior_;
scoped_ptr<Contents> contents_;
diff --git a/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc b/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc
index c8f7ee6..21df1f4 100644
--- a/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc
+++ b/chrome/browser/managed_mode/managed_mode_url_filter_unittest.cc
@@ -10,34 +10,6 @@
#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
-namespace {
-
-class FailClosureHelper : public base::RefCountedThreadSafe<FailClosureHelper> {
- public:
- explicit FailClosureHelper(const base::Closure& cb) : closure_runner_(cb) {}
-
- void Fail() {
- FAIL();
- }
-
- private:
- friend class base::RefCountedThreadSafe<FailClosureHelper>;
-
- virtual ~FailClosureHelper() {}
-
- base::ScopedClosureRunner closure_runner_;
-};
-
-// Returns a closure that FAILs when it is called. As soon as the closure is
-// destroyed (because the last reference to it is dropped), |continuation| is
-// called.
-base::Closure FailClosure(const base::Closure& continuation) {
- scoped_refptr<FailClosureHelper> helper = new FailClosureHelper(continuation);
- return base::Bind(&FailClosureHelper::Fail, helper);
-}
-
-} // namespace
-
class ManagedModeURLFilterTest : public ::testing::Test,
public ManagedModeURLFilter::Observer {
public:
@@ -63,7 +35,7 @@ class ManagedModeURLFilterTest : public ::testing::Test,
MessageLoop message_loop_;
base::RunLoop run_loop_;
- scoped_ptr<ManagedModeURLFilter> filter_;
+ scoped_refptr<ManagedModeURLFilter> filter_;
};
TEST_F(ManagedModeURLFilterTest, Basic) {
diff --git a/chrome/browser/managed_mode/managed_user_service.cc b/chrome/browser/managed_mode/managed_user_service.cc
new file mode 100644
index 0000000..8fbc39a
--- /dev/null
+++ b/chrome/browser/managed_mode/managed_user_service.cc
@@ -0,0 +1,353 @@
+// Copyright (c) 2013 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/managed_mode/managed_user_service.h"
+
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_system.h"
+#include "chrome/browser/managed_mode/managed_mode_site_list.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/extensions/extension_set.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/browser_thread.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using content::BrowserThread;
+
+ManagedUserService::URLFilterContext::URLFilterContext()
+ : ui_url_filter_(new ManagedModeURLFilter),
+ io_url_filter_(new ManagedModeURLFilter) {}
+ManagedUserService::URLFilterContext::~URLFilterContext() {}
+
+ManagedModeURLFilter*
+ManagedUserService::URLFilterContext::ui_url_filter() const {
+ return ui_url_filter_.get();
+}
+
+ManagedModeURLFilter*
+ManagedUserService::URLFilterContext::io_url_filter() const {
+ return io_url_filter_.get();
+}
+
+void ManagedUserService::URLFilterContext::SetDefaultFilteringBehavior(
+ ManagedModeURLFilter::FilteringBehavior behavior) {
+ ui_url_filter_->SetDefaultFilteringBehavior(behavior);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ManagedModeURLFilter::SetDefaultFilteringBehavior,
+ io_url_filter_.get(),
+ behavior));
+}
+
+void ManagedUserService::URLFilterContext::LoadWhitelists(
+ ScopedVector<ManagedModeSiteList> site_lists) {
+ // ManagedModeURLFilter::LoadWhitelists takes ownership of |site_lists|,
+ // so we make an additional copy of it.
+ /// TODO(bauerb): This is kinda ugly.
+ ScopedVector<ManagedModeSiteList> site_lists_copy;
+ for (ScopedVector<ManagedModeSiteList>::iterator it = site_lists.begin();
+ it != site_lists.end(); ++it) {
+ site_lists_copy.push_back((*it)->Clone());
+ }
+ ui_url_filter_->LoadWhitelists(site_lists.Pass());
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ManagedModeURLFilter::LoadWhitelists,
+ io_url_filter_,
+ base::Passed(&site_lists_copy)));
+}
+
+void ManagedUserService::URLFilterContext::SetManualLists(
+ scoped_ptr<ListValue> whitelist,
+ scoped_ptr<ListValue> blacklist) {
+ ui_url_filter_->SetManualLists(whitelist.get(), blacklist.get());
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ManagedModeURLFilter::SetManualLists,
+ io_url_filter_,
+ base::Owned(whitelist.release()),
+ base::Owned(blacklist.release())));
+}
+
+void ManagedUserService::URLFilterContext::AddURLPatternToManualList(
+ const bool is_whitelist,
+ const std::string& url) {
+ ui_url_filter_->AddURLPatternToManualList(is_whitelist, url);
+ BrowserThread::PostTask(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&ManagedModeURLFilter::AddURLPatternToManualList,
+ io_url_filter_,
+ is_whitelist,
+ url));
+}
+
+ManagedUserService::ManagedUserService(Profile* profile)
+ : profile_(profile),
+ is_elevated_(false) {
+ Init();
+}
+
+ManagedUserService::~ManagedUserService() {
+}
+
+bool ManagedUserService::ProfileIsManaged() const {
+ return profile_->GetPrefs()->GetBoolean(prefs::kProfileIsManaged);
+}
+
+// static
+void ManagedUserService::RegisterUserPrefs(PrefServiceSyncable* prefs) {
+ prefs->RegisterListPref(prefs::kManagedModeWhitelist,
+ PrefServiceSyncable::UNSYNCABLE_PREF);
+ prefs->RegisterListPref(prefs::kManagedModeBlacklist,
+ PrefServiceSyncable::UNSYNCABLE_PREF);
+ prefs->RegisterIntegerPref(prefs::kDefaultManagedModeFilteringBehavior,
+ ManagedModeURLFilter::BLOCK,
+ PrefServiceSyncable::UNSYNCABLE_PREF);
+}
+
+scoped_refptr<const ManagedModeURLFilter>
+ManagedUserService::GetURLFilterForIOThread() {
+ return url_filter_context_.io_url_filter();
+}
+
+ManagedModeURLFilter* ManagedUserService::GetURLFilterForUIThread() {
+ return url_filter_context_.ui_url_filter();
+}
+
+// Items not on any list must return -1 (CATEGORY_NOT_ON_LIST in history.js).
+// Items on a list, but with no category, must return 0 (CATEGORY_OTHER).
+#define CATEGORY_NOT_ON_LIST -1;
+#define CATEGORY_OTHER 0;
+
+int ManagedUserService::GetCategory(const GURL& url) {
+ std::vector<ManagedModeSiteList::Site*> sites;
+ GetURLFilterForUIThread()->GetSites(url, &sites);
+ if (sites.empty())
+ return CATEGORY_NOT_ON_LIST;
+
+ return (*sites.begin())->category_id;
+}
+
+// static
+void ManagedUserService::GetCategoryNames(CategoryList* list) {
+ ManagedModeSiteList::GetCategoryNames(list);
+};
+
+void ManagedUserService::AddToManualList(bool is_whitelist,
+ const base::ListValue& list) {
+ ListPrefUpdate pref_update(profile_->GetPrefs(),
+ is_whitelist ? prefs::kManagedModeWhitelist :
+ prefs::kManagedModeBlacklist);
+ ListValue* pref_list = pref_update.Get();
+
+ for (size_t i = 0; i < list.GetSize(); ++i) {
+ std::string url_pattern;
+ list.GetString(i, &url_pattern);
+
+ if (!IsInManualList(is_whitelist, url_pattern)) {
+ pref_list->AppendString(url_pattern);
+ AddURLPatternToManualList(is_whitelist, url_pattern);
+ }
+ }
+}
+
+void ManagedUserService::RemoveFromManualList(bool is_whitelist,
+ const base::ListValue& list) {
+ ListPrefUpdate pref_update(profile_->GetPrefs(),
+ is_whitelist ? prefs::kManagedModeWhitelist :
+ prefs::kManagedModeBlacklist);
+ ListValue* pref_list = pref_update.Get();
+
+ for (size_t i = 0; i < list.GetSize(); ++i) {
+ std::string pattern;
+ size_t out_index;
+ list.GetString(i, &pattern);
+ StringValue value_to_remove(pattern);
+
+ pref_list->Remove(value_to_remove, &out_index);
+ }
+}
+
+bool ManagedUserService::IsInManualList(bool is_whitelist,
+ const std::string& url_pattern) {
+ StringValue pattern(url_pattern);
+ const ListValue* list = profile_->GetPrefs()->GetList(
+ is_whitelist ? prefs::kManagedModeWhitelist :
+ prefs::kManagedModeBlacklist);
+ return list->Find(pattern) != list->end();
+}
+
+// static
+scoped_ptr<base::ListValue> ManagedUserService::GetBlacklist() {
+ return make_scoped_ptr(
+ profile_->GetPrefs()->GetList(prefs::kManagedModeBlacklist)->DeepCopy());
+}
+
+std::string ManagedUserService::GetDebugPolicyProviderName() const {
+ // Save the string space in official builds.
+#ifdef NDEBUG
+ NOTREACHED();
+ return std::string();
+#else
+ return "Managed User Service";
+#endif
+}
+
+bool ManagedUserService::UserMayLoad(const extensions::Extension* extension,
+ string16* error) const {
+ string16 tmp_error;
+ if (ExtensionManagementPolicyImpl(&tmp_error))
+ return true;
+
+ // If the extension is already loaded, we allow it, otherwise we'd unload
+ // all existing extensions.
+ ExtensionService* extension_service =
+ extensions::ExtensionSystem::Get(profile_)->extension_service();
+
+ // |extension_service| can be NULL in a unit test.
+ if (extension_service &&
+ extension_service->GetInstalledExtension(extension->id()))
+ return true;
+
+ if (error)
+ *error = tmp_error;
+ return false;
+}
+
+bool ManagedUserService::UserMayModifySettings(
+ const extensions::Extension* extension,
+ string16* error) const {
+ return ExtensionManagementPolicyImpl(error);
+}
+
+void ManagedUserService::Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ switch (type) {
+ case chrome::NOTIFICATION_EXTENSION_LOADED: {
+ const extensions::Extension* extension =
+ content::Details<extensions::Extension>(details).ptr();
+ if (!extension->GetContentPackSiteList().empty())
+ UpdateSiteLists();
+
+ break;
+ }
+ case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
+ const extensions::UnloadedExtensionInfo* extension_info =
+ content::Details<extensions::UnloadedExtensionInfo>(details).ptr();
+ if (!extension_info->extension->GetContentPackSiteList().empty())
+ UpdateSiteLists();
+
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+bool ManagedUserService::ExtensionManagementPolicyImpl(string16* error) const {
+ if (!ProfileIsManaged())
+ return true;
+
+ if (is_elevated_)
+ return true;
+
+ if (error)
+ *error = l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE);
+ return false;
+}
+
+ScopedVector<ManagedModeSiteList> ManagedUserService::GetActiveSiteLists() {
+ ScopedVector<ManagedModeSiteList> site_lists;
+ ExtensionService* extension_service =
+ extensions::ExtensionSystem::Get(profile_)->extension_service();
+ // Can be NULL in unit tests.
+ if (!extension_service)
+ return site_lists.Pass();
+
+ const ExtensionSet* extensions = extension_service->extensions();
+ for (ExtensionSet::const_iterator it = extensions->begin();
+ it != extensions->end(); ++it) {
+ const extensions::Extension* extension = *it;
+ if (!extension_service->IsExtensionEnabled(extension->id()))
+ continue;
+
+ ExtensionResource site_list = extension->GetContentPackSiteList();
+ if (!site_list.empty())
+ site_lists.push_back(new ManagedModeSiteList(extension->id(), site_list));
+ }
+
+ return site_lists.Pass();
+}
+
+void ManagedUserService::OnDefaultFilteringBehaviorChanged() {
+ DCHECK(ProfileIsManaged());
+
+ int behavior_value = profile_->GetPrefs()->GetInteger(
+ prefs::kDefaultManagedModeFilteringBehavior);
+ ManagedModeURLFilter::FilteringBehavior behavior =
+ ManagedModeURLFilter::BehaviorFromInt(behavior_value);
+ url_filter_context_.SetDefaultFilteringBehavior(behavior);
+}
+
+void ManagedUserService::UpdateSiteLists() {
+ url_filter_context_.LoadWhitelists(GetActiveSiteLists());
+}
+
+void ManagedUserService::UpdateManualLists() {
+ url_filter_context_.SetManualLists(GetWhitelist(), GetBlacklist());
+}
+
+void ManagedUserService::SetElevatedForTesting(bool is_elevated) {
+ is_elevated_ = is_elevated;
+}
+
+void ManagedUserService::Init() {
+ if (!ProfileIsManaged())
+ return;
+
+ extensions::ExtensionSystem* extension_system =
+ extensions::ExtensionSystem::Get(profile_);
+ extensions::ManagementPolicy* management_policy =
+ extension_system->management_policy();
+ if (management_policy)
+ extension_system->management_policy()->RegisterProvider(this);
+
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile_));
+ registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
+ content::Source<Profile>(profile_));
+ pref_change_registrar_.Init(profile_->GetPrefs());
+ pref_change_registrar_.Add(
+ prefs::kDefaultManagedModeFilteringBehavior,
+ base::Bind(
+ &ManagedUserService::OnDefaultFilteringBehaviorChanged,
+ base::Unretained(this)));
+
+ // Initialize the filter.
+ OnDefaultFilteringBehaviorChanged();
+ UpdateSiteLists();
+ UpdateManualLists();
+}
+
+scoped_ptr<base::ListValue> ManagedUserService::GetWhitelist() {
+ return make_scoped_ptr(
+ profile_->GetPrefs()->GetList(prefs::kManagedModeWhitelist)->DeepCopy());
+}
+
+void ManagedUserService::AddURLPatternToManualList(
+ bool is_whitelist,
+ const std::string& url_pattern) {
+ url_filter_context_.AddURLPatternToManualList(true, url_pattern);
+}
diff --git a/chrome/browser/managed_mode/managed_user_service.h b/chrome/browser/managed_mode/managed_user_service.h
new file mode 100644
index 0000000..8f2f7db
--- /dev/null
+++ b/chrome/browser/managed_mode/managed_user_service.h
@@ -0,0 +1,171 @@
+// Copyright (c) 2013 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_MANAGED_MODE_MANAGED_USER_SERVICE_H_
+#define CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SERVICE_H_
+
+#include <vector>
+
+#include "base/prefs/public/pref_change_registrar.h"
+#include "base/string16.h"
+#include "chrome/browser/extensions/management_policy.h"
+#include "chrome/browser/managed_mode/managed_mode_url_filter.h"
+#include "chrome/browser/profiles/profile_keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class ManagedModeURLFilter;
+class ManagedModeSiteList;
+class PrefServiceSyncable;
+class Profile;
+
+// This class handles all the information related to a given managed profile
+// (e.g. the installed content packs, the default URL filtering behavior, or
+// manual whitelist/blacklist overrides).
+class ManagedUserService : public ProfileKeyedService,
+ public extensions::ManagementPolicy::Provider,
+ public content::NotificationObserver {
+ public:
+ typedef std::vector<string16> CategoryList;
+
+ explicit ManagedUserService(Profile* profile);
+ virtual ~ManagedUserService();
+
+ bool ProfileIsManaged() const;
+
+ static void RegisterUserPrefs(PrefServiceSyncable* prefs);
+
+ // Returns the URL filter for the IO thread, for filtering network requests
+ // (in ManagedModeResourceThrottle).
+ scoped_refptr<const ManagedModeURLFilter> GetURLFilterForIOThread();
+
+ // Returns the URL filter for the UI thread, for filtering navigations and
+ // classifying sites in the history view.
+ ManagedModeURLFilter* GetURLFilterForUIThread();
+
+ // Returns the URL's category, obtained from the installed content packs.
+ int GetCategory(const GURL& url);
+
+ // Returns the list of all known human-readable category names, sorted by ID
+ // number. Called in the critical path of drawing the history UI, so needs to
+ // be fast.
+ void GetCategoryNames(CategoryList* list);
+
+ // The functions that handle manual whitelists use |url_pattern| or lists
+ // of "url patterns". An "url pattern" is a pattern in the format used by the
+ // policy::URLBlacklist filter. A description of the format used can be found
+ // here: http://dev.chromium.org/administrators/url-blacklist-filter-format.
+ // They all receive the |is_whitelist| parameter which dictates whether they
+ // act on the whitelist (for |is_whitelist| == true) or on the blacklist (for
+ // |is_whitelist| == false).
+
+ // Checks if the |url_pattern| is in the manual whitelist.
+ bool IsInManualList(const bool is_whitelist, const std::string& url_pattern);
+
+ // Appends |list| to the manual white/black list (according to |is_whitelist|)
+ // both in URL filter and in preferences.
+ void AddToManualList(const bool is_whitelist, const base::ListValue& list);
+
+ // Removes |list| from the manual white/black list (according to
+ // |is_whitelist|) both in URL filter and in preferences.
+ void RemoveFromManualList(const bool is_whitelist,
+ const base::ListValue& list);
+
+ // Updates the whitelist and the blacklist from the prefs.
+ void UpdateManualLists();
+
+ void SetElevatedForTesting(bool is_elevated);
+
+ // Initializes this object. This method does nothing if the profile is not
+ // managed. This method should only be called for testing, to do
+ // initialization after the profile has been manually set to managed,
+ // otherwise it is called automatically,
+ void Init();
+
+ // ExtensionManagementPolicy::Provider implementation:
+ virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
+ virtual bool UserMayLoad(const extensions::Extension* extension,
+ string16* error) const OVERRIDE;
+ virtual bool UserMayModifySettings(const extensions::Extension* extension,
+ string16* error) const OVERRIDE;
+
+ // content::NotificationObserver implementation:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ friend class ManagedUserServiceExtensionTest;
+
+ // A bridge from ManagedMode (which lives on the UI thread) to the
+ // ManagedModeURLFilters, one of which lives on the IO thread. This class
+ // mediates access to them and makes sure they are kept in sync.
+ class URLFilterContext {
+ public:
+ URLFilterContext();
+ ~URLFilterContext();
+
+ ManagedModeURLFilter* ui_url_filter() const;
+ ManagedModeURLFilter* io_url_filter() const;
+
+ void SetDefaultFilteringBehavior(
+ ManagedModeURLFilter::FilteringBehavior behavior);
+ void LoadWhitelists(ScopedVector<ManagedModeSiteList> site_lists);
+ void SetManualLists(scoped_ptr<base::ListValue> whitelist,
+ scoped_ptr<base::ListValue> blacklist);
+ void AddURLPatternToManualList(const bool isWhitelist,
+ const std::string& url);
+
+ private:
+ // ManagedModeURLFilter 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.
+ // Clients should not keep references to the UI thread filter, however
+ // (the filter will live as long as the profile lives, and afterwards it
+ // should not be used anymore either).
+ scoped_refptr<ManagedModeURLFilter> ui_url_filter_;
+ scoped_refptr<ManagedModeURLFilter> io_url_filter_;
+
+ DISALLOW_COPY_AND_ASSIGN(URLFilterContext);
+ };
+
+ // Internal implementation for ExtensionManagementPolicy::Delegate methods.
+ // If |error| is not NULL, it will be filled with an error message if the
+ // requested extension action (install, modify status, etc.) is not permitted.
+ bool ExtensionManagementPolicyImpl(string16* error) const;
+
+ // Returns a list of all installed and enabled site lists in the current
+ // managed profile.
+ ScopedVector<ManagedModeSiteList> GetActiveSiteLists();
+
+ void OnDefaultFilteringBehaviorChanged();
+
+ void UpdateSiteLists();
+
+ // Adds the |url_pattern| to the manual lists in the URL filter. This is used
+ // by AddToManualListImpl().
+ void AddURLPatternToManualList(const bool is_whitelist,
+ const std::string& url_pattern);
+
+ // Returns a copy of the manual whitelist which is stored in each profile.
+ scoped_ptr<base::ListValue> GetWhitelist();
+
+ // Returns a copy of the manual blacklist which is stored in each profile.
+ scoped_ptr<base::ListValue> GetBlacklist();
+
+ // Owns us via the ProfileKeyedService mechanism.
+ Profile* profile_;
+
+ // If ManagedUserService is in an elevated state, a custodian user has
+ // authorized making changes (to install additional content packs, for
+ // example).
+ bool is_elevated_;
+
+ content::NotificationRegistrar registrar_;
+ PrefChangeRegistrar pref_change_registrar_;
+
+ URLFilterContext url_filter_context_;
+};
+
+#endif // CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SERVICE_H_
diff --git a/chrome/browser/managed_mode/managed_user_service_factory.cc b/chrome/browser/managed_mode/managed_user_service_factory.cc
new file mode 100644
index 0000000..6215b23
--- /dev/null
+++ b/chrome/browser/managed_mode/managed_user_service_factory.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2013 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/managed_mode/managed_user_service_factory.h"
+
+#include "chrome/browser/extensions/extension_system_factory.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/profiles/profile_dependency_manager.h"
+
+// static
+ManagedUserService* ManagedUserServiceFactory::GetForProfile(Profile* profile) {
+ return static_cast<ManagedUserService*>(
+ GetInstance()->GetServiceForProfile(profile, true));
+}
+
+// static
+ManagedUserServiceFactory* ManagedUserServiceFactory::GetInstance() {
+ return Singleton<ManagedUserServiceFactory>::get();
+}
+
+// static
+ProfileKeyedService* ManagedUserServiceFactory::BuildInstanceFor(
+ Profile* profile) {
+ return new ManagedUserService(profile);
+}
+
+ManagedUserServiceFactory::ManagedUserServiceFactory()
+ : ProfileKeyedServiceFactory("ManagedUserService",
+ ProfileDependencyManager::GetInstance()) {
+ DependsOn(extensions::ExtensionSystemFactory::GetInstance());
+}
+
+ManagedUserServiceFactory::~ManagedUserServiceFactory() {}
+
+bool ManagedUserServiceFactory::ServiceRedirectedInIncognito() const {
+ return true;
+}
+
+ProfileKeyedService* ManagedUserServiceFactory::BuildServiceInstanceFor(
+ Profile* profile) const {
+ return BuildInstanceFor(profile);
+}
diff --git a/chrome/browser/managed_mode/managed_user_service_factory.h b/chrome/browser/managed_mode/managed_user_service_factory.h
new file mode 100644
index 0000000..e43ea02
--- /dev/null
+++ b/chrome/browser/managed_mode/managed_user_service_factory.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2013 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_MANAGED_MODE_MANAGED_USER_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SERVICE_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "chrome/browser/profiles/profile_keyed_service_factory.h"
+
+class ManagedUserService;
+
+class ManagedUserServiceFactory : public ProfileKeyedServiceFactory {
+ public:
+ static ManagedUserService* GetForProfile(Profile* profile);
+
+ static ManagedUserServiceFactory* GetInstance();
+
+ // Used to create instances for testing.
+ static ProfileKeyedService* BuildInstanceFor(Profile* profile);
+
+ private:
+ friend struct DefaultSingletonTraits<ManagedUserServiceFactory>;
+
+ ManagedUserServiceFactory();
+ virtual ~ManagedUserServiceFactory();
+
+ // ProfileKeyedServiceFactory:
+ virtual bool ServiceRedirectedInIncognito() const OVERRIDE;
+ virtual ProfileKeyedService* BuildServiceInstanceFor(
+ Profile* profile) const OVERRIDE;
+};
+
+#endif // CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SERVICE_FACTORY_H_
diff --git a/chrome/browser/managed_mode/managed_user_service_unittest.cc b/chrome/browser/managed_mode/managed_user_service_unittest.cc
new file mode 100644
index 0000000..cd336d9
--- /dev/null
+++ b/chrome/browser/managed_mode/managed_user_service_unittest.cc
@@ -0,0 +1,220 @@
+// Copyright (c) 2013 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 "base/path_service.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_service_unittest.h"
+#include "chrome/browser/extensions/unpacked_installer.h"
+#include "chrome/browser/managed_mode/managed_user_service.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::MessageLoopRunner;
+
+namespace {
+
+class ManagedModeURLFilterObserver : public ManagedModeURLFilter::Observer {
+ public:
+ explicit ManagedModeURLFilterObserver(ManagedModeURLFilter* url_filter)
+ : url_filter_(url_filter) {
+ Reset();
+ url_filter_->AddObserver(this);
+ }
+
+ ~ManagedModeURLFilterObserver() {
+ url_filter_->RemoveObserver(this);
+ }
+
+ void Wait() {
+ message_loop_runner_->Run();
+ Reset();
+ }
+
+ // ManagedModeURLFilter::Observer
+ virtual void OnSiteListUpdated() OVERRIDE {
+ message_loop_runner_->Quit();
+ }
+
+ private:
+ void Reset() {
+ message_loop_runner_ = new MessageLoopRunner;
+ }
+
+ ManagedModeURLFilter* url_filter_;
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+};
+
+} // namespace
+
+TEST(ManagedUserServiceTest, ExtensionManagementPolicyProvider) {
+ MessageLoop message_loop;
+ TestingProfile profile;
+ {
+ ManagedUserService managed_user_service(&profile);
+ EXPECT_FALSE(managed_user_service.ProfileIsManaged());
+
+ string16 error_1;
+ EXPECT_TRUE(managed_user_service.UserMayLoad(NULL, &error_1));
+ EXPECT_EQ(string16(), error_1);
+
+ string16 error_2;
+ EXPECT_TRUE(managed_user_service.UserMayModifySettings(NULL, &error_2));
+ EXPECT_EQ(string16(), error_2);
+ }
+
+ profile.GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true);
+ {
+ ManagedUserService managed_user_service(&profile);
+ EXPECT_TRUE(managed_user_service.ProfileIsManaged());
+
+ string16 error_1;
+ EXPECT_FALSE(managed_user_service.UserMayLoad(NULL, &error_1));
+ EXPECT_FALSE(error_1.empty());
+
+ string16 error_2;
+ EXPECT_FALSE(managed_user_service.UserMayModifySettings(NULL, &error_2));
+ EXPECT_FALSE(error_2.empty());
+
+#ifndef NDEBUG
+ EXPECT_FALSE(managed_user_service.GetDebugPolicyProviderName().empty());
+#endif
+ }
+}
+
+class ManagedUserServiceExtensionTest : public ExtensionServiceTestBase {
+ public:
+ ManagedUserServiceExtensionTest() {}
+ virtual ~ManagedUserServiceExtensionTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ ExtensionServiceTestBase::SetUp();
+ InitializeEmptyExtensionService();
+ }
+
+ protected:
+ ScopedVector<ManagedModeSiteList> GetActiveSiteLists(
+ ManagedUserService* managed_user_service) {
+ return managed_user_service->GetActiveSiteLists();
+ }
+};
+
+TEST_F(ManagedUserServiceExtensionTest, NoContentPacks) {
+ ManagedUserService managed_user_service(profile_.get());
+ ManagedModeURLFilter* url_filter =
+ managed_user_service.GetURLFilterForUIThread();
+
+ GURL url("http://youtube.com");
+ ScopedVector<ManagedModeSiteList> site_lists =
+ GetActiveSiteLists(&managed_user_service);
+ ASSERT_EQ(0u, site_lists.size());
+ EXPECT_EQ(ManagedModeURLFilter::ALLOW,
+ url_filter->GetFilteringBehaviorForURL(url));
+}
+
+TEST_F(ManagedUserServiceExtensionTest, InstallContentPacks) {
+ profile_->GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true);
+ ManagedUserService managed_user_service(profile_.get());
+ managed_user_service.SetElevatedForTesting(true);
+ ManagedModeURLFilter* url_filter =
+ managed_user_service.GetURLFilterForUIThread();
+ ManagedModeURLFilterObserver observer(url_filter);
+ observer.Wait();
+
+ GURL example_url("http://example.com");
+ GURL moose_url("http://moose.org");
+ EXPECT_EQ(ManagedModeURLFilter::BLOCK,
+ url_filter->GetFilteringBehaviorForURL(example_url));
+
+ profile_->GetPrefs()->SetInteger(prefs::kDefaultManagedModeFilteringBehavior,
+ ManagedModeURLFilter::WARN);
+ EXPECT_EQ(ManagedModeURLFilter::WARN,
+ url_filter->GetFilteringBehaviorForURL(example_url));
+
+ // Load a content pack.
+ scoped_refptr<extensions::UnpackedInstaller> installer(
+ extensions::UnpackedInstaller::Create(service_));
+ installer->set_prompt_for_plugins(false);
+ FilePath test_data_dir;
+ ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
+ FilePath extension_path =
+ test_data_dir.AppendASCII("extensions/managed_mode/content_pack");
+ content::WindowedNotificationObserver extension_load_observer(
+ chrome::NOTIFICATION_EXTENSION_LOADED,
+ content::Source<Profile>(profile_.get()));
+ installer->Load(extension_path);
+ extension_load_observer.Wait();
+ observer.Wait();
+ content::Details<extensions::Extension> details =
+ extension_load_observer.details();
+ scoped_refptr<extensions::Extension> extension =
+ make_scoped_refptr(details.ptr());
+ ASSERT_TRUE(extension);
+
+ ScopedVector<ManagedModeSiteList> site_lists =
+ GetActiveSiteLists(&managed_user_service);
+ ASSERT_EQ(1u, site_lists.size());
+ std::vector<ManagedModeSiteList::Site> sites;
+ site_lists[0]->GetSites(&sites);
+ ASSERT_EQ(3u, sites.size());
+ EXPECT_EQ(ASCIIToUTF16("YouTube"), sites[0].name);
+ EXPECT_EQ(ASCIIToUTF16("Homestar Runner"), sites[1].name);
+ EXPECT_EQ(string16(), sites[2].name);
+
+ EXPECT_EQ(ManagedModeURLFilter::ALLOW,
+ url_filter->GetFilteringBehaviorForURL(example_url));
+ EXPECT_EQ(ManagedModeURLFilter::WARN,
+ url_filter->GetFilteringBehaviorForURL(moose_url));
+
+ // Load a second content pack.
+ installer = extensions::UnpackedInstaller::Create(service_);
+ extension_path =
+ test_data_dir.AppendASCII("extensions/managed_mode/content_pack_2");
+ installer->Load(extension_path);
+ observer.Wait();
+
+ site_lists = GetActiveSiteLists(&managed_user_service);
+ ASSERT_EQ(2u, site_lists.size());
+ sites.clear();
+ site_lists[0]->GetSites(&sites);
+ site_lists[1]->GetSites(&sites);
+ ASSERT_EQ(4u, sites.size());
+ // The site lists might be returned in any order, so we put them into a set.
+ std::set<std::string> site_names;
+ for (std::vector<ManagedModeSiteList::Site>::const_iterator it =
+ sites.begin(); it != sites.end(); ++it) {
+ site_names.insert(UTF16ToUTF8(it->name));
+ }
+ EXPECT_TRUE(site_names.count("YouTube") == 1u);
+ EXPECT_TRUE(site_names.count("Homestar Runner") == 1u);
+ EXPECT_TRUE(site_names.count(std::string()) == 1u);
+ EXPECT_TRUE(site_names.count("Moose") == 1u);
+
+ EXPECT_EQ(ManagedModeURLFilter::ALLOW,
+ url_filter->GetFilteringBehaviorForURL(example_url));
+ EXPECT_EQ(ManagedModeURLFilter::ALLOW,
+ url_filter->GetFilteringBehaviorForURL(moose_url));
+
+ // Disable the first content pack.
+ service_->DisableExtension(extension->id(),
+ extensions::Extension::DISABLE_USER_ACTION);
+ observer.Wait();
+
+ site_lists = GetActiveSiteLists(&managed_user_service);
+ ASSERT_EQ(1u, site_lists.size());
+ sites.clear();
+ site_lists[0]->GetSites(&sites);
+ ASSERT_EQ(1u, sites.size());
+ EXPECT_EQ(ASCIIToUTF16("Moose"), sites[0].name);
+
+ EXPECT_EQ(ManagedModeURLFilter::WARN,
+ url_filter->GetFilteringBehaviorForURL(example_url));
+ EXPECT_EQ(ManagedModeURLFilter::ALLOW,
+ url_filter->GetFilteringBehaviorForURL(moose_url));
+}