diff options
author | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-19 03:44:31 +0000 |
---|---|---|
committer | bauerb@chromium.org <bauerb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-01-19 03:44:31 +0000 |
commit | 0850e849eee0cc95c9b5c0fc8cbfd6cd8e30f3ff (patch) | |
tree | fc5b0875748b34c79c90e55552b0aea63393d416 /chrome/browser/managed_mode | |
parent | d99126aca23d5a2e977deefc46511e105ade8241 (diff) | |
download | chromium_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')
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)); +} |