summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/generated_resources.grd3
-rw-r--r--chrome/browser/chrome_browser_main.cc6
-rw-r--r--chrome/browser/extensions/extension_managed_mode_apitest.cc5
-rw-r--r--chrome/browser/extensions/extension_prefs.cc7
-rw-r--r--chrome/browser/extensions/extension_prefs.h2
-rw-r--r--chrome/browser/extensions/management_policy.cc20
-rw-r--r--chrome/browser/extensions/management_policy.h4
-rw-r--r--chrome/browser/extensions/test_management_policy.cc2
-rw-r--r--chrome/browser/extensions/test_management_policy.h2
-rw-r--r--chrome/browser/managed_mode.cc97
-rw-r--r--chrome/browser/managed_mode.h41
-rw-r--r--chrome/browser/managed_mode_unittest.cc33
-rw-r--r--chrome/browser/resources/extensions/extensions.css14
-rw-r--r--chrome/browser/resources/extensions/extensions.html13
-rw-r--r--chrome/browser/resources/extensions/extensions.js18
-rw-r--r--chrome/browser/resources/options2/chromeos/internet_detail.html4
-rw-r--r--chrome/browser/resources/options2/options.html6
-rw-r--r--chrome/browser/resources/options2/options_page.css44
-rw-r--r--chrome/browser/resources/options2/options_page.js2
-rw-r--r--chrome/browser/resources/uber/uber_shared.css45
-rw-r--r--chrome/browser/ui/webui/extensions/extension_settings_handler.cc23
-rw-r--r--chrome/browser/ui/webui/extensions/extension_settings_handler.h1
-rwxr-xr-xchrome/test/functional/policy_prefs_ui.py5
23 files changed, 288 insertions, 109 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 9c689fb..e6218a3 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4704,6 +4704,9 @@ Update checks have repeatedly failed for the extension "<ph name="EXTENSION_NAME
<message name="IDS_EXTENSIONS_POLICY_CONTROLLED" desc="The text in the extensions UI informing the user that an extension is policy controlled">
(This extension is managed and cannot be removed or disabled.)
</message>
+ <message name="IDS_EXTENSIONS_LOCKED_MANAGED_MODE" desc="The error message (either shown in the extensions UI or logged) informing the user that extensions are controlled by managed mode">
+ Extensions cannot be modified in managed mode.
+ </message>
<message name="IDS_GET_MORE_EXTENSIONS_DEPRECATED" desc="The link for getting more extensions. Displayed at bottom of extension management page when there is at least one extension installed.">
<ph name="BEGIN_LINK">&lt;a target="blank_" href="$1"&gt;</ph>Get more extensions<ph name="END_LINK">&lt;/a&gt;<ex>&lt;/a&gt;</ex></ph>
</message>
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 928ab28..7ab2892 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -49,6 +49,7 @@
#include "chrome/browser/gpu_util.h"
#include "chrome/browser/jankometer.h"
#include "chrome/browser/language_usage_metrics.h"
+#include "chrome/browser/managed_mode.h"
#include "chrome/browser/metrics/field_trial_synchronizer.h"
#include "chrome/browser/metrics/histogram_synchronizer.h"
#include "chrome/browser/metrics/metrics_log.h"
@@ -1603,7 +1604,10 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
translate_manager_ = TranslateManager::GetInstance();
DCHECK(translate_manager_ != NULL);
- // TODO(stevenjb): Move WIN and MACOSX specific code to apprpriate Parts.
+ // Initialize Managed Mode.
+ ManagedMode::Init(profile_);
+
+ // TODO(stevenjb): Move WIN and MACOSX specific code to appropriate Parts.
// (requires supporting early exit).
PostProfileInit();
diff --git a/chrome/browser/extensions/extension_managed_mode_apitest.cc b/chrome/browser/extensions/extension_managed_mode_apitest.cc
index d8d1c07..4c19cfb 100644
--- a/chrome/browser/extensions/extension_managed_mode_apitest.cc
+++ b/chrome/browser/extensions/extension_managed_mode_apitest.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/managed_mode.h"
#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/test/base/ui_test_utils.h"
@@ -37,10 +38,10 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ManagedModeOnChange) {
// Fire the extension event when entering managed mode. We directly call
// SetInManagedMode() to bypass any confirmation dialogs etc.
- ManagedMode::GetInstance()->SetInManagedMode(true);
+ ManagedMode::GetInstance()->SetInManagedMode(browser()->profile());
// Fire the extension event when leaving managed mode.
- ManagedMode::GetInstance()->SetInManagedMode(false);
+ ManagedMode::GetInstance()->SetInManagedMode(NULL);
ASSERT_TRUE(catcher.GetNextResult()) << catcher.message();
}
diff --git a/chrome/browser/extensions/extension_prefs.cc b/chrome/browser/extensions/extension_prefs.cc
index fc523325..fed7aec 100644
--- a/chrome/browser/extensions/extension_prefs.cc
+++ b/chrome/browser/extensions/extension_prefs.cc
@@ -657,8 +657,13 @@ void ExtensionPrefs::SetAppNotificationDisabled(
Value::CreateBooleanValue(value));
}
-std::string ExtensionPrefs::GetPolicyProviderName() const {
+std::string ExtensionPrefs::GetDebugPolicyProviderName() const {
+#ifdef NDEBUG
+ NOTREACHED();
+ return std::string();
+#else
return "admin policy black/white/forcelist, via the ExtensionPrefs";
+#endif
}
bool ExtensionPrefs::UserMayLoad(const extensions::Extension* extension,
diff --git a/chrome/browser/extensions/extension_prefs.h b/chrome/browser/extensions/extension_prefs.h
index 0efe0b4..8b906cd 100644
--- a/chrome/browser/extensions/extension_prefs.h
+++ b/chrome/browser/extensions/extension_prefs.h
@@ -211,7 +211,7 @@ class ExtensionPrefs : public extensions::ContentSettingsStore::Observer,
// ManagementPolicy::Provider
// These methods apply admin policy to extensions.
- virtual std::string GetPolicyProviderName() const OVERRIDE;
+ virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
virtual bool UserMayLoad(const extensions::Extension* extension,
string16* error) const OVERRIDE;
virtual bool UserMayModifySettings(const extensions::Extension* extension,
diff --git a/chrome/browser/extensions/management_policy.cc b/chrome/browser/extensions/management_policy.cc
index 2524116..ce28faa 100644
--- a/chrome/browser/extensions/management_policy.cc
+++ b/chrome/browser/extensions/management_policy.cc
@@ -41,8 +41,10 @@ bool ManagementPolicy::UserMayLoad(const Extension* extension,
if (!(*it)->UserMayLoad(extension, error)) {
// The extension may be NULL in testing.
std::string id = extension ? extension->id() : "[test]";
- DLOG(WARNING) << "Installation of extension " << id
- << " prohibited by " << (*it)->GetPolicyProviderName();
+ std::string name = extension ? extension->name() : "test";
+ DLOG(WARNING) << "Installation of extension " << name
+ << "( " << id << ")"
+ << " prohibited by " << (*it)->GetDebugPolicyProviderName();
return false;
}
}
@@ -56,8 +58,10 @@ bool ManagementPolicy::UserMayModifySettings(const Extension* extension,
if (!(*it)->UserMayModifySettings(extension, error)) {
// The extension may be NULL in testing.
std::string id = extension ? extension->id() : "[test]";
- DLOG(WARNING) << "Modification of extension " << id
- << " prohibited by " << (*it)->GetPolicyProviderName();
+ std::string name = extension ? extension->name() : "test";
+ DLOG(WARNING) << "Modification of extension " << name
+ << "( " << id << ")"
+ << " prohibited by " << (*it)->GetDebugPolicyProviderName();
return false;
}
}
@@ -68,12 +72,14 @@ bool ManagementPolicy::MustRemainEnabled(const Extension* extension,
string16* error) const {
for (ProviderList::const_iterator it = providers_.begin();
it != providers_.end(); ++it) {
+ if ((*it)->MustRemainEnabled(extension, error)) {
// The extension may be NULL in testing.
std::string id = extension ? extension->id() : "[test]";
- if ((*it)->MustRemainEnabled(extension, error)) {
- DLOG(WARNING) << "Extension " << id
+ std::string name = extension ? extension->name() : "test";
+ DLOG(WARNING) << "Extension " << name
+ << "( " << id << ")"
<< " required to remain enabled by "
- << (*it)->GetPolicyProviderName();
+ << (*it)->GetDebugPolicyProviderName();
return true;
}
}
diff --git a/chrome/browser/extensions/management_policy.h b/chrome/browser/extensions/management_policy.h
index f2d16f5..47f499f 100644
--- a/chrome/browser/extensions/management_policy.h
+++ b/chrome/browser/extensions/management_policy.h
@@ -46,7 +46,9 @@ class ManagementPolicy {
virtual ~Provider() {}
// A human-readable name for this provider, for use in debug messages.
- virtual std::string GetPolicyProviderName() const = 0;
+ // Implementers should return an empty string in non-debug builds, to save
+ // executable size.
+ virtual std::string GetDebugPolicyProviderName() const = 0;
// Providers should return false if a user may not install the |extension|,
// or load or run it if it has already been installed.
diff --git a/chrome/browser/extensions/test_management_policy.cc b/chrome/browser/extensions/test_management_policy.cc
index 16d317e..2296fc8 100644
--- a/chrome/browser/extensions/test_management_policy.cc
+++ b/chrome/browser/extensions/test_management_policy.cc
@@ -27,7 +27,7 @@ void TestManagementPolicyProvider::SetProhibitedActions(
must_remain_enabled_ = (prohibited_actions & MUST_REMAIN_ENABLED) != 0;
}
-std::string TestManagementPolicyProvider::GetPolicyProviderName() const {
+std::string TestManagementPolicyProvider::GetDebugPolicyProviderName() const {
return "the test management policy provider";
}
diff --git a/chrome/browser/extensions/test_management_policy.h b/chrome/browser/extensions/test_management_policy.h
index bcb300d..649ea91 100644
--- a/chrome/browser/extensions/test_management_policy.h
+++ b/chrome/browser/extensions/test_management_policy.h
@@ -32,7 +32,7 @@ class TestManagementPolicyProvider : public ManagementPolicy::Provider {
void SetProhibitedActions(int prohibited_actions);
- virtual std::string GetPolicyProviderName() const OVERRIDE;
+ virtual std::string GetDebugPolicyProviderName() const OVERRIDE;
virtual bool UserMayLoad(const Extension* extension,
string16* error) const OVERRIDE;
diff --git a/chrome/browser/managed_mode.cc b/chrome/browser/managed_mode.cc
index 480bf4c..259882f 100644
--- a/chrome/browser/managed_mode.cc
+++ b/chrome/browser/managed_mode.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
@@ -16,6 +17,8 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/notification_service.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
// static
ManagedMode* ManagedMode::GetInstance() {
@@ -25,12 +28,26 @@ ManagedMode* ManagedMode::GetInstance() {
// static
void ManagedMode::RegisterPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kInManagedMode, false);
+}
+
+// static
+void ManagedMode::Init(Profile* profile) {
+ GetInstance()->InitImpl(profile);
+}
+
+void ManagedMode::InitImpl(Profile* profile) {
+ DCHECK(g_browser_process);
+ DCHECK(g_browser_process->local_state());
+
+ Profile* original_profile = profile->GetOriginalProfile();
// Set the value directly in the PrefService instead of using
// CommandLinePrefStore so we can change it at runtime.
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoManaged))
- GetInstance()->SetInManagedMode(false);
- else if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kManaged))
- GetInstance()->SetInManagedMode(true);
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoManaged)) {
+ SetInManagedMode(NULL);
+ } else if (IsInManagedModeImpl() ||
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kManaged)) {
+ SetInManagedMode(original_profile);
+ }
}
// static
@@ -38,7 +55,7 @@ bool ManagedMode::IsInManagedMode() {
return GetInstance()->IsInManagedModeImpl();
}
-bool ManagedMode::IsInManagedModeImpl() {
+bool ManagedMode::IsInManagedModeImpl() const {
// |g_browser_process| can be NULL during startup.
if (!g_browser_process)
return false;
@@ -56,11 +73,11 @@ void ManagedMode::EnterManagedMode(Profile* profile,
void ManagedMode::EnterManagedModeImpl(Profile* profile,
const EnterCallback& callback) {
+ Profile* original_profile = profile->GetOriginalProfile();
if (IsInManagedModeImpl()) {
- callback.Run(true);
+ callback.Run(original_profile == managed_profile_);
return;
}
- Profile* original_profile = profile->GetOriginalProfile();
if (!callbacks_.empty()) {
// We are already in the process of entering managed mode, waiting for
// browsers to close. Don't allow entering managed mode again for a
@@ -76,22 +93,23 @@ void ManagedMode::EnterManagedModeImpl(Profile* profile,
callback.Run(false);
return;
}
- managed_profile_ = original_profile;
// Close all other profiles.
// At this point, we shouldn't be waiting for other browsers to close (yet).
DCHECK_EQ(0u, browsers_to_close_.size());
for (BrowserList::const_iterator i = BrowserList::begin();
i != BrowserList::end(); ++i) {
- if ((*i)->profile()->GetOriginalProfile() != managed_profile_)
+ if ((*i)->profile()->GetOriginalProfile() != original_profile)
browsers_to_close_.insert(*i);
}
if (browsers_to_close_.empty()) {
- SetInManagedMode(true);
- managed_profile_ = NULL;
+ SetInManagedMode(original_profile);
callback.Run(true);
return;
}
+ // Remember the profile we're trying to manage while we wait for other
+ // browsers to close.
+ managed_profile_ = original_profile;
callbacks_.push_back(callback);
registrar_.Add(this, content::NOTIFICATION_APP_EXITING,
content::NotificationService::AllSources());
@@ -111,7 +129,36 @@ void ManagedMode::LeaveManagedMode() {
void ManagedMode::LeaveManagedModeImpl() {
bool confirmed = PlatformConfirmLeave();
if (confirmed)
- SetInManagedMode(false);
+ SetInManagedMode(NULL);
+}
+
+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 {
+ return ExtensionManagementPolicyImpl(error);
+}
+
+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) {
@@ -119,6 +166,7 @@ void ManagedMode::OnBrowserAdded(Browser* browser) {
if (callbacks_.empty())
return;
+ DCHECK(managed_profile_);
if (browser->profile()->GetOriginalProfile() != managed_profile_)
FinalizeEnter(false);
}
@@ -128,6 +176,7 @@ void ManagedMode::OnBrowserRemoved(Browser* browser) {
if (callbacks_.empty())
return;
+ DCHECK(managed_profile_);
if (browser->profile()->GetOriginalProfile() == managed_profile_) {
// Ignore closing browser windows that are in managed mode.
return;
@@ -144,7 +193,6 @@ ManagedMode::ManagedMode() : managed_profile_(NULL) {
ManagedMode::~ManagedMode() {
BrowserList::RemoveObserver(this);
- DCHECK(!managed_profile_);
DCHECK_EQ(0u, callbacks_.size());
DCHECK_EQ(0u, browsers_to_close_.size());
}
@@ -176,12 +224,11 @@ void ManagedMode::Observe(int type,
void ManagedMode::FinalizeEnter(bool result) {
if (result)
- SetInManagedMode(true);
+ SetInManagedMode(managed_profile_);
for (std::vector<EnterCallback>::iterator it = callbacks_.begin();
it != callbacks_.end(); ++it) {
it->Run(result);
}
- managed_profile_ = NULL;
callbacks_.clear();
browsers_to_close_.clear();
registrar_.RemoveAll();
@@ -197,13 +244,25 @@ bool ManagedMode::PlatformConfirmLeave() {
return true;
}
-void ManagedMode::SetInManagedMode(bool in_managed_mode) {
- g_browser_process->local_state()->SetBoolean(prefs::kInManagedMode,
- in_managed_mode);
+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.
+ if (newly_managed_profile) {
+ DCHECK(!managed_profile_ || managed_profile_ == newly_managed_profile);
+ ExtensionSystem::Get(
+ newly_managed_profile)->management_policy()->RegisterProvider(this);
+ g_browser_process->local_state()->SetBoolean(prefs::kInManagedMode, true);
+ } else {
+ ExtensionSystem::Get(
+ managed_profile_)->management_policy()->UnregisterProvider(this);
+ g_browser_process->local_state()->SetBoolean(prefs::kInManagedMode, false);
+ }
+ managed_profile_ = newly_managed_profile;
+
// This causes the avatar and the profile menu to get updated.
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
content::NotificationService::AllBrowserContextsAndSources(),
content::NotificationService::NoDetails());
}
-
diff --git a/chrome/browser/managed_mode.h b/chrome/browser/managed_mode.h
index d3779ca..76f0b32 100644
--- a/chrome/browser/managed_mode.h
+++ b/chrome/browser/managed_mode.h
@@ -6,11 +6,13 @@
#define CHROME_BROWSER_MANAGED_MODE_H_
#include <set>
+#include <string>
#include <vector>
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/singleton.h"
+#include "chrome/browser/extensions/management_policy.h"
#include "chrome/browser/ui/browser_list.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
@@ -26,11 +28,16 @@ class Profile;
// The ManagedMode class provides methods to check whether the browser is in
// managed mode, and to attempt to enter or leave managed mode.
class ManagedMode : public BrowserList::Observer,
+ public extensions::ManagementPolicy::Provider,
public content::NotificationObserver {
public:
typedef base::Callback<void(bool)> EnterCallback;
static void RegisterPrefs(PrefService* prefs);
+
+ // Initializes the singleton, setting the managed_profile_. Must be called
+ // after g_browser_process and the LocalState have been created.
+ static void Init(Profile* profile);
static bool IsInManagedMode();
// Calls |callback| with the argument true iff managed mode was entered
@@ -38,6 +45,13 @@ class ManagedMode : public BrowserList::Observer,
static void EnterManagedMode(Profile* profile, const EnterCallback& callback);
static void LeaveManagedMode();
+ // 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;
+
// BrowserList::Observer implementation:
virtual void OnBrowserAdded(Browser* browser) OVERRIDE;
virtual void OnBrowserRemoved(Browser* browser) OVERRIDE;
@@ -52,13 +66,25 @@ class ManagedMode : public BrowserList::Observer,
virtual ~ManagedMode();
void EnterManagedModeImpl(Profile* profile, const EnterCallback& callback);
+ // The managed profile. This is NULL iff we are not in managed mode.
+ Profile* managed_profile_;
+
private:
friend struct DefaultSingletonTraits<ManagedMode>;
friend class Singleton<ManagedMode>;
FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest, ManagedModeOnChange);
+ FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
+ ManagedModeProhibitsModification);
static ManagedMode* GetInstance();
+ 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();
void FinalizeEnter(bool result);
@@ -68,16 +94,21 @@ class ManagedMode : public BrowserList::Observer,
virtual bool PlatformConfirmEnter();
virtual bool PlatformConfirmLeave();
- virtual bool IsInManagedModeImpl();
- virtual void SetInManagedMode(bool in_managed_mode);
+ virtual bool IsInManagedModeImpl() const;
+
+ // Enables or disables managed mode and registers or unregisters it with the
+ // ManagementPolicy. If |newly_managed_profile| is NULL, managed mode will
+ // be disabled. Otherwise, managed mode will be enabled for that profile
+ // (typically |managed_profile_|, but other values are possible during
+ // testing).
+ virtual void SetInManagedMode(Profile* newly_managed_profile);
content::NotificationRegistrar registrar_;
- // The managed profile. This is non-NULL only while we're entering
- // managed mode.
- const Profile* managed_profile_;
std::set<Browser*> browsers_to_close_;
std::vector<EnterCallback> callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(ManagedMode);
};
#endif // CHROME_BROWSER_MANAGED_MODE_H_
diff --git a/chrome/browser/managed_mode_unittest.cc b/chrome/browser/managed_mode_unittest.cc
index 5f35d5d..881ba4e 100644
--- a/chrome/browser/managed_mode_unittest.cc
+++ b/chrome/browser/managed_mode_unittest.cc
@@ -37,12 +37,17 @@ class FakeManagedMode : public ManagedMode {
}
// ManagedMode overrides:
- virtual bool IsInManagedModeImpl() OVERRIDE {
+ virtual bool IsInManagedModeImpl() const OVERRIDE {
return in_managed_mode_;
}
- virtual void SetInManagedMode(bool in_managed_mode) OVERRIDE {
- in_managed_mode_ = in_managed_mode;
+ virtual void SetInManagedMode(Profile* newly_managed_profile) OVERRIDE {
+ if (newly_managed_profile) {
+ ASSERT_TRUE(!managed_profile_ ||
+ managed_profile_ == newly_managed_profile);
+ }
+ managed_profile_ = newly_managed_profile;
+ in_managed_mode_ = (newly_managed_profile != NULL);
}
virtual bool PlatformConfirmEnter() OVERRIDE {
@@ -96,7 +101,7 @@ class MockCallback : public base::RefCountedThreadSafe<MockCallback> {
}
void CheckManagedMode(bool success) {
- EXPECT_EQ(managed_mode_->IsInManagedModeImpl(), success);
+ EXPECT_EQ(success, managed_mode_->IsInManagedModeImpl());
DidEnterManagedMode(success);
}
@@ -151,8 +156,9 @@ TEST_F(ManagedModeTest, AlreadyInManagedMode) {
BrowserFixture managed_mode_browser(&managed_mode_, &managed_mode_profile_);
BrowserFixture other_browser(&managed_mode_, &other_profile_);
- // If we're already in managed mode, entering should immediately succeed.
- managed_mode_.SetInManagedMode(true);
+ // If we're already in managed mode in this profile, entering should
+ // immediately succeed.
+ managed_mode_.SetInManagedMode(&managed_mode_profile_);
managed_mode_.EnterManagedModeForTesting(&managed_mode_profile_,
CreateExpectedCallback(true));
}
@@ -228,3 +234,18 @@ 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_);
+
+ EXPECT_TRUE(managed_mode_.UserMayLoad(NULL, NULL));
+ EXPECT_TRUE(managed_mode_.UserMayModifySettings(NULL, NULL));
+
+ managed_mode_.SetInManagedMode(&managed_mode_profile_);
+ EXPECT_FALSE(managed_mode_.UserMayLoad(NULL, NULL));
+ EXPECT_FALSE(managed_mode_.UserMayModifySettings(NULL, NULL));
+
+#ifndef NDEBUG
+ EXPECT_FALSE(managed_mode_.GetDebugPolicyProviderName().empty());
+#endif
+}
diff --git a/chrome/browser/resources/extensions/extensions.css b/chrome/browser/resources/extensions/extensions.css
index 213fbb0..02c2160 100644
--- a/chrome/browser/resources/extensions/extensions.css
+++ b/chrome/browser/resources/extensions/extensions.css
@@ -253,3 +253,17 @@ html[dir='rtl'] #extension-settings .trash {
.may-not-disable .optional-controls {
display: none;
}
+
+.page:not(.dev-mode) #dev-controls {
+ display: none;
+}
+
+/* Managed mode */
+
+.page:not(.managed-mode) #managed-mode-banner {
+ display: none;
+}
+
+.managed-mode .more-extensions-link {
+ display: none;
+}
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html
index cd2babd..4f6b1c7 100644
--- a/chrome/browser/resources/extensions/extensions.html
+++ b/chrome/browser/resources/extensions/extensions.html
@@ -42,8 +42,15 @@
<input id="toggle-dev-on" type="checkbox">
<span i18n-content="extensionSettingsDeveloperMode">
</label></div>
+ <div id="managed-mode-banner"
+ class="page-banner managed-mode-banner">
+ <div class="page-banner-gradient">
+ <span id="managed-prefs-text" class="page-banner-text"
+ i18n-content="extensionSettingsManagedMode"></span>
+ </div>
+ </div>
</header>
- <div id="dev-controls" hidden>
+ <div id="dev-controls">
<button id="load-unpacked"
i18n-content="extensionSettingsLoadUnpackedButton"></button>
<button id="pack-extension"
@@ -56,12 +63,12 @@
<div id="no-extensions">
<span id="no-extensions-message"
i18n-content="extensionSettingsNoExtensions"></span>
- <span id="suggest-gallery"
+ <span id="suggest-gallery" class="more-extensions-link"
i18n-values=".innerHTML:extensionSettingsSuggestGallery">
</span>
</div>
<div id="footer-section">
- <a target="blank_"
+ <a target="blank_" class="more-extensions-link"
i18n-values="href:extensionSettingsGetMoreExtensionsUrl"
i18n-content="extensionSettingsGetMoreExtensions"></a>
<a target="blank_" hidden
diff --git a/chrome/browser/resources/extensions/extensions.js b/chrome/browser/resources/extensions/extensions.js
index bfcf3e8..1fe0c19 100644
--- a/chrome/browser/resources/extensions/extensions.js
+++ b/chrome/browser/resources/extensions/extensions.js
@@ -223,13 +223,23 @@ cr.define('extensions', function() {
});
}
- if (extensionsData.developerMode) {
+ var pageDiv = $('extension-settings');
+ if (extensionsData.managedMode) {
+ pageDiv.classList.add('showing-banner');
+ pageDiv.classList.add('managed-mode');
+ $('toggle-dev-on').disabled = true;
+ } else {
+ pageDiv.classList.remove('showing-banner');
+ pageDiv.classList.remove('managed-mode');
+ $('toggle-dev-on').disabled = false;
+ }
+
+ if (extensionsData.developerMode && !extensionsData.managedMode) {
+ pageDiv.classList.add('dev-mode');
$('toggle-dev-on').checked = true;
- $('extension-settings').classList.add('dev-mode');
- $('dev-controls').hidden = false;
} else {
+ pageDiv.classList.remove('dev-mode');
$('toggle-dev-on').checked = false;
- $('extension-settings').classList.remove('dev-mode');
}
$('load-unpacked').disabled = extensionsData.loadUnpackedDisabled;
diff --git a/chrome/browser/resources/options2/chromeos/internet_detail.html b/chrome/browser/resources/options2/chromeos/internet_detail.html
index 0e3da70..19a5757e 100644
--- a/chrome/browser/resources/options2/chromeos/internet_detail.html
+++ b/chrome/browser/resources/options2/chromeos/internet_detail.html
@@ -453,8 +453,8 @@
<div id="network-proxy-tab" class="subpages-tab-contents">
<section>
<div id="info-banner" hidden>
- <span id="banner-icon" class="managed-prefs-icon"></span>
- <span id="banner-text" class="managed-prefs-text"></span>
+ <span id="banner-icon" class="page-banner-icon"></span>
+ <span id="banner-text" class="page-banner-text"></span>
</div>
<div class="radio">
<label>
diff --git a/chrome/browser/resources/options2/options.html b/chrome/browser/resources/options2/options.html
index e28a48d..ab9ec85 100644
--- a/chrome/browser/resources/options2/options.html
+++ b/chrome/browser/resources/options2/options.html
@@ -150,9 +150,9 @@
</div>
<div id="templates" hidden>
- <div id="managed-prefs-banner" class="managed-prefs-banner">
- <div class="managed-prefs-gradient">
- <span id="managed-prefs-text" class="managed-prefs-text"></span>
+ <div id="managed-prefs-banner" class="page-banner managed-prefs-banner">
+ <div class="page-banner-gradient">
+ <span id="managed-prefs-text" class="page-banner-text"></span>
</div>
</div>
</div>
diff --git a/chrome/browser/resources/options2/options_page.css b/chrome/browser/resources/options2/options_page.css
index e6273ff..b65aa53 100644
--- a/chrome/browser/resources/options2/options_page.css
+++ b/chrome/browser/resources/options2/options_page.css
@@ -109,50 +109,6 @@ div.disabled {
padding-top: 0;
}
-.managed-prefs-banner {
- background-color: white;
- width: 100%;
- z-index: 2;
-}
-
-.page:not(.showing-banner) .managed-prefs-banner {
- display: none;
-}
-
-.managed-prefs-gradient {
- background: -webkit-linear-gradient(rgb(255, 242, 183),
- rgb(250, 230, 145));
- border: 1px solid rgb(201, 189, 141);
- border-radius: 3px;
- height: 25px;
- margin: 9px 9px 0 9px;
-}
-
-.main-page-banner .managed-prefs-gradient {
- -webkit-margin-end: 20px;
- -webkit-margin-start: 0;
- margin-bottom: 9px;
-}
-
-.managed-prefs-text {
- background-image: url('chrome://theme/IDR_MANAGED');
- background-position: 5px center;
- background-repeat: no-repeat;
- background-size: 16px;
- display: block;
- line-height: 24px;
- padding-left: 26px;
-}
-
-.managed-prefs-banner.clickable:active .managed-prefs-text {
- background: -webkit-linear-gradient(rgb(250, 230, 145),
- rgb(255, 242, 183));
-}
-
-#page-container .page.showing-banner {
- margin-top: 45px;
-}
-
.page list {
/* Min height is a multiple of the list item height (32) */
min-height: 192px;
diff --git a/chrome/browser/resources/options2/options_page.js b/chrome/browser/resources/options2/options_page.js
index 7bb67f0..c42cac4 100644
--- a/chrome/browser/resources/options2/options_page.js
+++ b/chrome/browser/resources/options2/options_page.js
@@ -708,7 +708,7 @@ cr.define('options', function() {
} else {
this.pageDiv.classList.add('showing-banner');
- var text = bannerDiv.querySelector('.managed-prefs-text');
+ var text = bannerDiv.querySelector('#managed-prefs-text');
if (controlledByPolicy && !controlledByExtension) {
text.textContent =
loadTimeData.getString('policyManagedPrefsBannerText');
diff --git a/chrome/browser/resources/uber/uber_shared.css b/chrome/browser/resources/uber/uber_shared.css
index 2a8f9bc..0fb3209 100644
--- a/chrome/browser/resources/uber/uber_shared.css
+++ b/chrome/browser/resources/uber/uber_shared.css
@@ -116,3 +116,48 @@ body.uber-frame section > h3 {
body.uber-frame section > div:only-of-type {
-webkit-box-flex: 1;
}
+
+/* Styles for a hideable notification banner at the top of a page.
+ * See the Options page .managed-prefs-banner for a usage example. */
+.page.showing-banner {
+ margin-top: 45px;
+}
+
+.page-banner {
+ background-color: white;
+ width: 100%;
+ z-index: 2;
+}
+
+.page:not(.showing-banner) .page-banner {
+ display: none;
+}
+
+.page-banner-gradient {
+ background: -webkit-linear-gradient(rgb(255, 242, 183),
+ rgb(250, 230, 145));
+ border: 1px solid rgb(201, 189, 141);
+ border-radius: 3px;
+ height: 25px;
+ margin: 9px 9px 0 9px;
+}
+
+.page-banner .page-banner-gradient {
+ -webkit-margin-end: 20px;
+ -webkit-margin-start: 0;
+ margin-bottom: 9px;
+}
+
+.page-banner-text {
+ background-image: url('chrome://theme/IDR_MANAGED');
+ background-position: 5px center;
+ background-repeat: no-repeat;
+ display: block;
+ line-height: 24px;
+ padding-left: 26px;
+}
+
+.page-banner.clickable:active .page-banner-text {
+ background: -webkit-linear-gradient(rgb(250, 230, 145),
+ rgb(255, 242, 183));
+}
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index 1605be8..a379835 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -14,6 +14,7 @@
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_disabled_ui.h"
@@ -25,6 +26,7 @@
#include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/extensions/updater/extension_updater.h"
#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/managed_mode.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/background_contents.h"
@@ -267,6 +269,8 @@ void ExtensionSettingsHandler::GetLocalizedValues(
l10n_util::GetStringUTF16(IDS_EXTENSIONS_VISIT_WEBSTORE));
localized_strings->SetString("extensionSettingsPolicyControlled",
l10n_util::GetStringUTF16(IDS_EXTENSIONS_POLICY_CONTROLLED));
+ localized_strings->SetString("extensionSettingsManagedMode",
+ l10n_util::GetStringUTF16(IDS_EXTENSIONS_LOCKED_MANAGED_MODE));
localized_strings->SetString("extensionSettingsShowButton",
l10n_util::GetStringUTF16(IDS_EXTENSIONS_SHOW_BUTTON));
localized_strings->SetString("extensionSettingsLoadUnpackedButton",
@@ -501,10 +505,16 @@ void ExtensionSettingsHandler::HandleRequestExtensionsData(
}
results.Set("extensions", extensions_list);
- Profile* profile = Profile::FromWebUI(web_ui());
- bool developer_mode =
- profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
- results.SetBoolean("developerMode", developer_mode);
+ if (ManagedMode::IsInManagedMode()) {
+ results.SetBoolean("managedMode", true);
+ results.SetBoolean("developerMode", false);
+ } else {
+ results.SetBoolean("managedMode", false);
+ Profile* profile = Profile::FromWebUI(web_ui());
+ bool developer_mode =
+ profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
+ results.SetBoolean("developerMode", developer_mode);
+ }
bool load_unpacked_disabled =
extension_service_->extension_prefs()->ExtensionsBlacklistedByDefault();
@@ -519,6 +529,9 @@ void ExtensionSettingsHandler::HandleRequestExtensionsData(
void ExtensionSettingsHandler::HandleToggleDeveloperMode(
const ListValue* args) {
+ if (ManagedMode::IsInManagedMode())
+ return;
+
Profile* profile = Profile::FromWebUI(web_ui());
bool developer_mode =
profile->GetPrefs()->GetBoolean(prefs::kExtensionsUIDeveloperMode);
@@ -782,6 +795,8 @@ void ExtensionSettingsHandler::MaybeRegisterForNotifications() {
pref_registrar_.Init(profile->GetPrefs());
pref_registrar_.Add(prefs::kExtensionInstallDenyList, this);
+ local_state_pref_registrar_.Init(g_browser_process->local_state());
+ local_state_pref_registrar_.Add(prefs::kInManagedMode, this);
}
std::vector<ExtensionPage>
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.h b/chrome/browser/ui/webui/extensions/extension_settings_handler.h
index 3c6da67..7dd6610 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.h
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.h
@@ -216,6 +216,7 @@ class ExtensionSettingsHandler : public content::WebUIMessageHandler,
content::NotificationRegistrar registrar_;
PrefChangeRegistrar pref_registrar_;
+ PrefChangeRegistrar local_state_pref_registrar_;
DISALLOW_COPY_AND_ASSIGN(ExtensionSettingsHandler);
};
diff --git a/chrome/test/functional/policy_prefs_ui.py b/chrome/test/functional/policy_prefs_ui.py
index 9785127..415042d 100755
--- a/chrome/test/functional/policy_prefs_ui.py
+++ b/chrome/test/functional/policy_prefs_ui.py
@@ -50,11 +50,10 @@ class PolicyPrefsUITest(policy_base.PolicyTestBase):
self.LoginWithTestAccount()
def IsAnyBannerVisible(self):
- """Returns true if any managed prefs banner is visible in the current page.
- """
+ """Returns true if any banner (e.g. for managed prefs) is visible."""
ret = self.ExecuteJavascript("""
var visible = false;
- var banners = document.querySelectorAll('.managed-prefs-banner');
+ var banners = document.querySelectorAll('.page-banner');
for (var i=0; i<banners.length; i++) {
if (banners[i].parentElement.id == 'templates')
continue;