summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 07:45:59 +0000
committermnissler@chromium.org <mnissler@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-07-14 07:45:59 +0000
commitd3b98c88fa50c3b6bf4644570220cf93f8ca9bea (patch)
treee2fdf54cee2d8546526ed9aca724e9f957d0fb2b
parent9473a8d2db6780ecac153c65ba8200cdb0eeb1bd (diff)
downloadchromium_src-d3b98c88fa50c3b6bf4644570220cf93f8ca9bea.zip
chromium_src-d3b98c88fa50c3b6bf4644570220cf93f8ca9bea.tar.gz
chromium_src-d3b98c88fa50c3b6bf4644570220cf93f8ca9bea.tar.bz2
Implement support for disabling sync through configuration management.
BUG=45316 TEST=Configure SyncDisabled policy and check the UI. Review URL: http://codereview.chromium.org/2905003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@52288 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/app_controller_mac.mm7
-rw-r--r--chrome/browser/browser.cc25
-rw-r--r--chrome/browser/browser.h7
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm2
-rw-r--r--chrome/browser/cocoa/preferences_window_controller.mm18
-rw-r--r--chrome/browser/configuration_policy_pref_store.cc17
-rw-r--r--chrome/browser/configuration_policy_pref_store.h5
-rw-r--r--chrome/browser/configuration_policy_provider.cc4
-rw-r--r--chrome/browser/configuration_policy_store.h2
-rw-r--r--chrome/browser/dom_ui/new_tab_page_sync_handler.cc9
-rw-r--r--chrome/browser/dom_ui/new_tab_ui.cc5
-rw-r--r--chrome/browser/gtk/bookmark_bar_gtk.cc2
-rw-r--r--chrome/browser/gtk/options/content_page_gtk.cc22
-rw-r--r--chrome/browser/gtk/options/content_page_gtk.h4
-rw-r--r--chrome/browser/managed_prefs_banner_base.cc14
-rw-r--r--chrome/browser/managed_prefs_banner_base.h2
-rw-r--r--chrome/browser/profile.cc8
-rw-r--r--chrome/browser/profile.h4
-rw-r--r--chrome/browser/sync/profile_sync_service.cc29
-rw-r--r--chrome/browser/sync/profile_sync_service.h25
-rw-r--r--chrome/browser/sync/profile_sync_service_observer.h23
-rw-r--r--chrome/browser/sync/profile_sync_service_startup_unittest.cc34
-rw-r--r--chrome/browser/sync/sync_ui_util.cc6
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc2
-rw-r--r--chrome/browser/views/options/content_page_view.cc22
-rw-r--r--chrome/common/pref_names.cc4
-rw-r--r--chrome/common/pref_names.h1
27 files changed, 245 insertions, 58 deletions
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 0ed8a0d..e06cc60 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -634,8 +634,8 @@ void RecordLastRunAppBundlePath() {
<< "NULL defaultProfile detected -- not doing anything";
break;
}
- enable = ProfileSyncService::IsSyncEnabled() &&
- [self keyWindowIsNotModal];
+ enable = defaultProfile->IsSyncAccessible() &&
+ [self keyWindowIsNotModal];
sync_ui_util::UpdateSyncItem(item, enable, defaultProfile);
break;
}
@@ -848,8 +848,7 @@ void RecordLastRunAppBundlePath() {
menuState_->UpdateCommandEnabled(IDC_HELP_PAGE, true);
menuState_->UpdateCommandEnabled(IDC_IMPORT_SETTINGS, true);
menuState_->UpdateCommandEnabled(IDC_REPORT_BUG, true);
- menuState_->UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
- ProfileSyncService::IsSyncEnabled());
+ menuState_->UpdateCommandEnabled(IDC_SYNC_BOOKMARKS, true);
menuState_->UpdateCommandEnabled(IDC_TASK_MANAGER, true);
}
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 24918de..e0d797d 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -236,6 +236,9 @@ Browser::Browser(Type type, Profile* profile)
tab_restore_service_->AddObserver(this);
TabRestoreServiceChanged(tab_restore_service_);
}
+
+ if (profile_->GetProfileSyncService())
+ profile_->GetProfileSyncService()->AddObserver(this);
}
Browser::~Browser() {
@@ -243,6 +246,9 @@ Browser::~Browser() {
DCHECK(!tabstrip_model_.HasNonPhantomTabs());
tabstrip_model_.RemoveObserver(this);
+ if (profile_->GetProfileSyncService())
+ profile_->GetProfileSyncService()->RemoveObserver(this);
+
BrowserList::RemoveBrowser(this);
#if defined(OS_WIN) || defined(OS_LINUX)
@@ -1059,8 +1065,8 @@ void Browser::UpdateCommandsForFullscreenMode(bool is_fullscreen) {
command_updater_.UpdateCommandEnabled(IDC_REPORT_BUG, show_main_ui);
command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR, show_main_ui);
command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, show_main_ui);
- command_updater_.UpdateCommandEnabled(
- IDC_SYNC_BOOKMARKS, show_main_ui && ProfileSyncService::IsSyncEnabled());
+ command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
+ show_main_ui && profile_->IsSyncAccessible());
command_updater_.UpdateCommandEnabled(IDC_OPTIONS, show_main_ui);
command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui);
command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui);
@@ -3037,6 +3043,21 @@ void Browser::Observe(NotificationType type,
}
}
+///////////////////////////////////////////////////////////////////////////////
+// Browser, ProfileSyncServiceObserver implementation:
+
+void Browser::OnStateChanged() {
+ DCHECK(profile_->GetProfileSyncService());
+
+#if !defined(OS_MACOSX)
+ const bool show_main_ui = (type() == TYPE_NORMAL) && !window_->IsFullscreen();
+#else
+ const bool show_main_ui = (type() == TYPE_NORMAL);
+#endif
+
+ command_updater_.UpdateCommandEnabled(IDC_SYNC_BOOKMARKS,
+ show_main_ui && profile_->IsSyncAccessible());
+}
///////////////////////////////////////////////////////////////////////////////
// Browser, Command and state updating (private):
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 2577eb4..1c0283d 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -17,6 +17,7 @@
#include "chrome/browser/sessions/session_id.h"
#include "chrome/browser/sessions/tab_restore_service.h"
#include "chrome/browser/shell_dialogs.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/tab_contents/page_navigator.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
@@ -50,7 +51,8 @@ class Browser : public TabStripModelDelegate,
public CommandUpdater::CommandUpdaterDelegate,
public NotificationObserver,
public SelectFileDialog::Listener,
- public TabRestoreService::Observer {
+ public TabRestoreService::Observer,
+ public ProfileSyncServiceObserver {
public:
// If you change the values in this enum you'll need to update browser_proxy.
// TODO(sky): move into a common place that is referenced by both ui_tests
@@ -737,6 +739,9 @@ class Browser : public TabStripModelDelegate,
const NotificationSource& source,
const NotificationDetails& details);
+ // Overridden from ProfileSyncServiceObserver:
+ virtual void OnStateChanged();
+
// Command and state updating ///////////////////////////////////////////////
// Initialize state for all browser commands.
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index aa7b325..b4d2af8 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -878,7 +878,7 @@
break;
}
case IDC_SYNC_BOOKMARKS:
- enable &= ProfileSyncService::IsSyncEnabled();
+ enable &= browser_->profile()->IsSyncAccessible();
sync_ui_util::UpdateSyncItem(item, enable, browser_->profile());
break;
default:
diff --git a/chrome/browser/cocoa/preferences_window_controller.mm b/chrome/browser/cocoa/preferences_window_controller.mm
index 4065f0b..5a075cf 100644
--- a/chrome/browser/cocoa/preferences_window_controller.mm
+++ b/chrome/browser/cocoa/preferences_window_controller.mm
@@ -76,6 +76,11 @@ static const wchar_t* kGeneralPolicyConstrainedPrefs[] = {
prefs::kHomePageIsNewTabPage
};
+// Content page preferences that are potentially constrained by policy.
+static const wchar_t* kContentPolicyConstrainedPrefs[] = {
+ prefs::kSyncManaged
+};
+
std::string GetNewTabUIURLString() {
return URLFixerUpper::FixupURL(chrome::kChromeUINewTabURL,
std::string()).possibly_invalid_spec();
@@ -412,6 +417,9 @@ class ManagedPrefsBannerState : public ManagedPrefsBannerBase {
kGeneralPolicyConstrainedPrefs,
arraysize(kGeneralPolicyConstrainedPrefs));
case OPTIONS_PAGE_CONTENT:
+ return new ManagedPrefsBannerState(controller, page, prefs,
+ kContentPolicyConstrainedPrefs,
+ arraysize(kContentPolicyConstrainedPrefs));
break;
case OPTIONS_PAGE_ADVANCED:
break;
@@ -1235,7 +1243,7 @@ const int kDisabledIndex = 1;
- (void)stopSyncAlertDidEnd:(NSAlert*)alert
returnCode:(int)returnCode
contextInfo:(void*)contextInfo {
- DCHECK(syncService_);
+ DCHECK(syncService_ && !syncService_->IsManaged());
if (returnCode == NSAlertFirstButtonReturn) {
syncService_->DisableForUser();
ProfileSyncService::SyncEvent(ProfileSyncService::STOP_FROM_OPTIONS);
@@ -1245,7 +1253,7 @@ const int kDisabledIndex = 1;
// Called when the user clicks the multi-purpose sync button in the
// "Personal Stuff" pane.
- (IBAction)doSyncAction:(id)sender {
- DCHECK(syncService_);
+ DCHECK(syncService_ && !syncService_->IsManaged());
if (syncService_->HasSyncSetupCompleted()) {
// If sync setup has completed that means the sync button was a
// "stop syncing" button. Bring up a confirmation dialog before
@@ -1292,7 +1300,7 @@ const int kDisabledIndex = 1;
}
- (IBAction)doSyncReauthentication:(id)sender {
- DCHECK(syncService_);
+ DCHECK(syncService_ && !syncService_->IsManaged());
syncService_->ShowLoginDialog();
}
@@ -1720,6 +1728,7 @@ const int kDisabledIndex = 1;
string16 statusLabel, linkLabel;
sync_ui_util::MessageType status =
sync_ui_util::GetStatusLabels(syncService_, &statusLabel, &linkLabel);
+ bool managed = syncService_->IsManaged();
[syncButton_ setEnabled:!syncService_->WizardIsVisible()];
NSString* buttonLabel;
@@ -1736,11 +1745,14 @@ const int kDisabledIndex = 1;
IDS_SYNC_START_SYNC_BUTTON_LABEL);
[syncCustomizeButton_ setHidden:true];
}
+ [syncCustomizeButton_ setEnabled:!managed];
[syncButton_ setTitle:buttonLabel];
+ [syncButton_ setEnabled:!managed];
[syncStatus_ setStringValue:base::SysUTF16ToNSString(statusLabel)];
[syncLink_ setHidden:linkLabel.empty()];
[syncLink_ setTitle:base::SysUTF16ToNSString(linkLabel)];
+ [syncLink_ setEnabled:!managed];
NSButtonCell* syncLinkCell = static_cast<NSButtonCell*>([syncLink_ cell]);
if (!syncStatusNoErrorBackgroundColor_) {
diff --git a/chrome/browser/configuration_policy_pref_store.cc b/chrome/browser/configuration_policy_pref_store.cc
index d2ada7c..43c9caa 100644
--- a/chrome/browser/configuration_policy_pref_store.cc
+++ b/chrome/browser/configuration_policy_pref_store.cc
@@ -224,6 +224,19 @@ bool ConfigurationPolicyPrefStore::ApplyProxyPolicy(PolicyType policy,
return result;
}
+bool ConfigurationPolicyPrefStore::ApplySyncPolicy(PolicyType policy,
+ Value* value) {
+ if (policy == ConfigurationPolicyStore::kPolicySyncDisabled) {
+ bool disable_sync;
+ if (value->GetAsBoolean(&disable_sync) && disable_sync)
+ prefs_->Set(prefs::kSyncManaged, value);
+ else
+ delete value;
+ return true;
+ }
+ return false;
+}
+
bool ConfigurationPolicyPrefStore::ApplyPolicyFromMap(PolicyType policy,
Value* value, const PolicyToPreferenceMapEntry map[], int size) {
const PolicyToPreferenceMapEntry* end = map + size;
@@ -242,6 +255,9 @@ void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) {
if (ApplyProxyPolicy(policy, value))
return;
+ if (ApplySyncPolicy(policy, value))
+ return;
+
if (ApplyPolicyFromMap(policy, value, simple_policy_map_,
arraysize(simple_policy_map_)))
return;
@@ -249,4 +265,3 @@ void ConfigurationPolicyPrefStore::Apply(PolicyType policy, Value* value) {
// Other policy implementations go here.
NOTIMPLEMENTED();
}
-
diff --git a/chrome/browser/configuration_policy_pref_store.h b/chrome/browser/configuration_policy_pref_store.h
index b87f42176..5035cba 100644
--- a/chrome/browser/configuration_policy_pref_store.h
+++ b/chrome/browser/configuration_policy_pref_store.h
@@ -85,8 +85,11 @@ class ConfigurationPolicyPrefStore : public PrefStore,
// of |value| in the case that the policy is proxy-specific.
bool ApplyProxyPolicy(PolicyType policy, Value* value);
+ // Handles sync-related policies. Returns true if the policy was handled.
+ // Assumes ownership of |value| in that case.
+ bool ApplySyncPolicy(PolicyType policy, Value* value);
+
DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyPrefStore);
};
#endif // CHROME_BROWSER_CONFIGURATION_POLICY_PREF_STORE_H_
-
diff --git a/chrome/browser/configuration_policy_provider.cc b/chrome/browser/configuration_policy_provider.cc
index a6d2f52..3156c59 100644
--- a/chrome/browser/configuration_policy_provider.cc
+++ b/chrome/browser/configuration_policy_provider.cc
@@ -39,7 +39,9 @@ const InternalPolicyValueMapEntry kPolicyValueMap[] = {
{ ConfigurationPolicyStore::kPolicySafeBrowsingEnabled,
Value::TYPE_BOOLEAN, "SafeBrowsingEnabled" },
{ ConfigurationPolicyStore::kPolicyMetricsReportingEnabled,
- Value::TYPE_BOOLEAN, "MetricsReportingEnabled" }
+ Value::TYPE_BOOLEAN, "MetricsReportingEnabled" },
+ { ConfigurationPolicyStore::kPolicySyncDisabled,
+ Value::TYPE_BOOLEAN, "SyncDisabled" }
};
} // namespace
diff --git a/chrome/browser/configuration_policy_store.h b/chrome/browser/configuration_policy_store.h
index 20d0b36..8cdbe77 100644
--- a/chrome/browser/configuration_policy_store.h
+++ b/chrome/browser/configuration_policy_store.h
@@ -26,6 +26,7 @@ class ConfigurationPolicyStore {
kPolicyDnsPrefetchingEnabled,
kPolicySafeBrowsingEnabled,
kPolicyMetricsReportingEnabled,
+ kPolicySyncDisabled
};
static const int kPolicyNoProxyServerMode = 0;
@@ -43,4 +44,3 @@ class ConfigurationPolicyStore {
};
#endif // CHROME_BROWSER_CONFIGURATION_POLICY_STORE_H_
-
diff --git a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
index f711709..b7349fd 100644
--- a/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
+++ b/chrome/browser/dom_ui/new_tab_page_sync_handler.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -98,6 +98,7 @@ NewTabPageSyncHandler::MessageType
DOMMessageHandler* NewTabPageSyncHandler::Attach(DOMUI* dom_ui) {
sync_service_ = dom_ui->GetProfile()->GetProfileSyncService();
DCHECK(sync_service_); // This shouldn't get called by an incognito NTP.
+ DCHECK(!sync_service_->IsManaged()); // And neither if sync is managed.
sync_service_->AddObserver(this);
return DOMMessageHandler::Attach(dom_ui);
}
@@ -121,8 +122,8 @@ void NewTabPageSyncHandler::HideSyncStatusSection() {
void NewTabPageSyncHandler::BuildAndSendSyncStatus() {
DCHECK(!waiting_for_initial_page_load_);
- // Hide the sync status section if sync is disabled entirely.
- if (!sync_service_) {
+ // Hide the sync status section if sync is managed or disabled entirely.
+ if (!sync_service_ || sync_service_->IsManaged()) {
HideSyncStatusSection();
return;
}
@@ -149,6 +150,8 @@ void NewTabPageSyncHandler::BuildAndSendSyncStatus() {
void NewTabPageSyncHandler::HandleSyncLinkClicked(const Value* value) {
DCHECK(!waiting_for_initial_page_load_);
DCHECK(sync_service_);
+ if (!sync_service_->IsSyncEnabled())
+ return;
if (sync_service_->HasSyncSetupCompleted()) {
if (sync_service_->GetAuthError().state() ==
GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
diff --git a/chrome/browser/dom_ui/new_tab_ui.cc b/chrome/browser/dom_ui/new_tab_ui.cc
index 8bcb449..6d2bdde 100644
--- a/chrome/browser/dom_ui/new_tab_ui.cc
+++ b/chrome/browser/dom_ui/new_tab_ui.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -465,9 +465,8 @@ NewTabUI::NewTabUI(TabContents* contents)
AddMessageHandler((new MetricsHandler())->Attach(this));
if (WebResourcesEnabled())
AddMessageHandler((new TipsHandler())->Attach(this));
- if (ProfileSyncService::IsSyncEnabled()) {
+ if (GetProfile()->IsSyncAccessible())
AddMessageHandler((new NewTabPageSyncHandler())->Attach(this));
- }
if (Extension::AppsAreEnabled()) {
ExtensionsService* service = GetProfile()->GetExtensionsService();
// We might not have an ExtensionsService (on ChromeOS when not logged in
diff --git a/chrome/browser/gtk/bookmark_bar_gtk.cc b/chrome/browser/gtk/bookmark_bar_gtk.cc
index 16bf8a4..7712196 100644
--- a/chrome/browser/gtk/bookmark_bar_gtk.cc
+++ b/chrome/browser/gtk/bookmark_bar_gtk.cc
@@ -998,7 +998,7 @@ gboolean BookmarkBarGtk::OnButtonPressed(GtkWidget* sender,
gboolean BookmarkBarGtk::OnSyncErrorButtonPressed(GtkWidget* sender,
GdkEventButton* event) {
if (sender == sync_error_button_) {
- DCHECK(sync_service_);
+ DCHECK(sync_service_ && !sync_service_->IsManaged());
sync_service_->ShowLoginDialog();
}
diff --git a/chrome/browser/gtk/options/content_page_gtk.cc b/chrome/browser/gtk/options/content_page_gtk.cc
index 540766c..4cc89ed 100644
--- a/chrome/browser/gtk/options/content_page_gtk.cc
+++ b/chrome/browser/gtk/options/content_page_gtk.cc
@@ -42,6 +42,11 @@ namespace {
// Background color for the status label when it's showing an error.
static const GdkColor kSyncLabelErrorBgColor = GDK_COLOR_RGB(0xff, 0x9a, 0x9a);
+// Set of preferences which might be unavailable for editing when managed.
+const wchar_t* kContentManagablePrefs[] = {
+ prefs::kSyncManaged
+};
+
// Helper for WrapLabelAtAllocationHack.
void OnLabelAllocate(GtkWidget* label, GtkAllocation* allocation) {
gtk_widget_set_size_request(label, allocation->width, -1);
@@ -80,7 +85,9 @@ ContentPageGtk::ContentPageGtk(Profile* profile)
sync_customize_button_(NULL),
privacy_dashboard_link_(NULL),
initializing_(true),
- sync_service_(NULL) {
+ sync_service_(NULL),
+ managed_prefs_banner_(profile->GetPrefs(), kContentManagablePrefs,
+ arraysize(kContentManagablePrefs)) {
if (profile->GetProfileSyncService()) {
sync_service_ = profile->GetProfileSyncService();
sync_service_->AddObserver(this);
@@ -89,6 +96,7 @@ ContentPageGtk::ContentPageGtk(Profile* profile)
// Prepare the group options layout.
scoped_ptr<OptionsLayoutBuilderGtk>
options_builder(OptionsLayoutBuilderGtk::CreateOptionallyCompactLayout());
+ options_builder->AddWidget(managed_prefs_banner_.banner_widget(), false);
if (sync_service_) {
options_builder->AddOptionGroup(
l10n_util::GetStringUTF8(IDS_SYNC_OPTIONS_GROUP_NAME),
@@ -391,6 +399,7 @@ void ContentPageGtk::UpdateSyncControls() {
string16 link_label;
std::string customize_button_label;
std::string button_label;
+ bool managed = sync_service_->IsManaged();
bool sync_setup_completed = sync_service_->HasSyncSetupCompleted();
bool status_has_error = sync_ui_util::GetStatusLabels(sync_service_,
&status_label, &link_label) == sync_ui_util::SYNC_ERROR;
@@ -408,7 +417,7 @@ void ContentPageGtk::UpdateSyncControls() {
UTF16ToUTF8(status_label).c_str());
#if !defined(OS_CHROMEOS)
gtk_widget_set_sensitive(sync_start_stop_button_,
- !sync_service_->WizardIsVisible());
+ !sync_service_->WizardIsVisible() && !managed);
gtk_button_set_label(GTK_BUTTON(sync_start_stop_button_),
button_label.c_str());
#endif
@@ -417,6 +426,7 @@ void ContentPageGtk::UpdateSyncControls() {
sync_setup_completed && !status_has_error);
gtk_button_set_label(GTK_BUTTON(sync_customize_button_),
customize_button_label.c_str());
+ gtk_widget_set_sensitive(sync_customize_button_, !managed);
#if !defined(OS_CHROMEOS)
gtk_chrome_link_button_set_label(GTK_CHROME_LINK_BUTTON(sync_action_link_),
UTF16ToUTF8(link_label).c_str());
@@ -427,6 +437,7 @@ void ContentPageGtk::UpdateSyncControls() {
gtk_widget_set_no_show_all(sync_action_link_background_, FALSE);
gtk_widget_show(sync_action_link_background_);
}
+ gtk_widget_set_sensitive(sync_action_link_, !managed);
#endif
if (status_has_error) {
gtk_widget_modify_bg(sync_status_label_background_, GTK_STATE_NORMAL,
@@ -529,7 +540,7 @@ void ContentPageGtk::OnPasswordRadioToggled(GtkWidget* widget) {
}
void ContentPageGtk::OnSyncStartStopButtonClicked(GtkWidget* widget) {
- DCHECK(sync_service_);
+ DCHECK(sync_service_ && !sync_service_->IsManaged());
if (sync_service_->HasSyncSetupCompleted()) {
GtkWidget* dialog = gtk_message_dialog_new(
@@ -567,12 +578,13 @@ void ContentPageGtk::OnSyncStartStopButtonClicked(GtkWidget* widget) {
void ContentPageGtk::OnSyncCustomizeButtonClicked(GtkWidget* widget) {
// sync_customize_button_ should be invisible if sync is not yet set up.
- DCHECK(sync_service_->HasSyncSetupCompleted());
+ DCHECK(sync_service_ && !sync_service_->IsManaged() &&
+ sync_service_->HasSyncSetupCompleted());
sync_service_->ShowChooseDataTypes();
}
void ContentPageGtk::OnSyncActionLinkClicked(GtkWidget* widget) {
- DCHECK(sync_service_);
+ DCHECK(sync_service_ && !sync_service_->IsManaged());
sync_service_->ShowLoginDialog();
}
diff --git a/chrome/browser/gtk/options/content_page_gtk.h b/chrome/browser/gtk/options/content_page_gtk.h
index 024eec8..f7239e0 100644
--- a/chrome/browser/gtk/options/content_page_gtk.h
+++ b/chrome/browser/gtk/options/content_page_gtk.h
@@ -9,6 +9,7 @@
#include "app/gtk_signal.h"
#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/gtk/options/managed_prefs_banner_gtk.h"
#include "chrome/browser/options_page_base.h"
#include "chrome/browser/pref_member.h"
#include "chrome/browser/profile.h"
@@ -103,6 +104,9 @@ class ContentPageGtk : public OptionsPageBase,
// and NULL-ed out on destruction.
ProfileSyncService* sync_service_;
+ // Tracks managed preference warning banner state.
+ ManagedPrefsBannerGtk managed_prefs_banner_;
+
DISALLOW_COPY_AND_ASSIGN(ContentPageGtk);
};
diff --git a/chrome/browser/managed_prefs_banner_base.cc b/chrome/browser/managed_prefs_banner_base.cc
index 5251d7f..09dcde6 100644
--- a/chrome/browser/managed_prefs_banner_base.cc
+++ b/chrome/browser/managed_prefs_banner_base.cc
@@ -12,11 +12,15 @@
ManagedPrefsBannerBase::ManagedPrefsBannerBase(PrefService* prefs,
const wchar_t** relevant_prefs,
size_t count)
- : prefs_(prefs),
- relevant_prefs_(relevant_prefs, relevant_prefs + count) {
- for (PrefSet::const_iterator pref(relevant_prefs_.begin());
- pref != relevant_prefs_.end(); ++pref)
- prefs_->AddPrefObserver(pref->c_str(), this);
+ : prefs_(prefs) {
+ for (size_t i = 0; i < count; ++i) {
+ // Ignore prefs that are not registered.
+ const wchar_t* pref = relevant_prefs[i];
+ if (prefs->FindPreference(pref)) {
+ prefs_->AddPrefObserver(pref, this);
+ relevant_prefs_.insert(pref);
+ }
+ }
}
ManagedPrefsBannerBase::~ManagedPrefsBannerBase() {
diff --git a/chrome/browser/managed_prefs_banner_base.h b/chrome/browser/managed_prefs_banner_base.h
index f0013ca..b06d0c8 100644
--- a/chrome/browser/managed_prefs_banner_base.h
+++ b/chrome/browser/managed_prefs_banner_base.h
@@ -40,7 +40,7 @@ class ManagedPrefsBannerBase : public NotificationObserver {
private:
PrefService* prefs_;
typedef std::set<std::wstring> PrefSet;
- const PrefSet relevant_prefs_;
+ PrefSet relevant_prefs_;
DISALLOW_COPY_AND_ASSIGN(ManagedPrefsBannerBase);
};
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 89c50f4..570371b 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -277,6 +277,11 @@ URLRequestContextGetter* Profile::GetDefaultRequestContext() {
return default_request_context_;
}
+bool Profile::IsSyncAccessible() {
+ ProfileSyncService* syncService = GetProfileSyncService();
+ return syncService && !syncService->IsManaged();
+}
+
#if defined(OS_WIN)
#include "chrome/browser/password_manager/password_store_win.h"
#elif defined(OS_MACOSX)
@@ -1642,9 +1647,6 @@ TokenService* ProfileImpl::GetTokenService() {
}
ProfileSyncService* ProfileImpl::GetProfileSyncService() {
- if (!ProfileSyncService::IsSyncEnabled()) {
- return NULL;
- }
if (!sync_service_.get())
InitSyncService();
return sync_service_.get();
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 59019cb..16bea36 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -452,6 +452,10 @@ class Profile {
return 0 == accessibility_pause_level_;
}
+ // Checks whether sync is configurable by the user. Returns false if sync is
+ // disabled or controlled by configuration management.
+ bool IsSyncAccessible();
+
protected:
static URLRequestContextGetter* default_request_context_;
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 055f039..7ee7bf2 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -126,6 +126,16 @@ void ProfileSyncService::Initialize() {
InitSettings();
RegisterPreferences();
+ // Watch the preference that indicates sync is managed so we can take
+ // appropriate action.
+ pref_sync_managed_.Init(prefs::kSyncManaged, profile_->GetPrefs(), this);
+
+ // For now, the only thing we can do through policy is to turn sync off.
+ if (IsManaged()) {
+ DisableForUser();
+ return;
+ }
+
if (!profile()->GetPrefs()->GetBoolean(prefs::kSyncHasSetupCompleted)) {
DisableForUser(); // Clean up in case of previous crash / setup abort.
@@ -218,6 +228,8 @@ void ProfileSyncService::RegisterPreferences() {
pref_service->RegisterBooleanPref(prefs::kKeepEverythingSynced,
enable_by_default);
+
+ pref_service->RegisterBooleanPref(prefs::kSyncManaged, false);
}
void ProfileSyncService::ClearPreferences() {
@@ -732,6 +744,17 @@ void ProfileSyncService::Observe(NotificationType type,
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
break;
}
+ case NotificationType::PREF_CHANGED: {
+ std::wstring* pref_name = Details<std::wstring>(details).ptr();
+ if (*pref_name == prefs::kSyncManaged) {
+ FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
+ if (*pref_sync_managed_)
+ DisableForUser();
+ else if (HasSyncSetupCompleted())
+ StartUp();
+ }
+ break;
+ }
default: {
NOTREACHED();
}
@@ -750,12 +773,18 @@ void ProfileSyncService::SyncEvent(SyncEventCodes code) {
UMA_HISTOGRAM_ENUMERATION("Sync.EventCodes", code, MAX_SYNC_EVENT_CODE);
}
+// static
bool ProfileSyncService::IsSyncEnabled() {
// We have switches::kEnableSync just in case we need to change back to
// sync-disabled-by-default on a platform.
return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableSync);
}
+bool ProfileSyncService::IsManaged() {
+ // Some tests use ProfileSyncServiceMock which doesn't have a profile.
+ return profile_ && profile_->GetPrefs()->GetBoolean(prefs::kSyncManaged);
+}
+
bool ProfileSyncService::ShouldPushChanges() {
// True only after all bootstrapping has succeeded: the sync backend
// is initialized, all enabled data types are consistent with one
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 5b36e0b..e88d852 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -14,10 +14,12 @@
#include "base/scoped_ptr.h"
#include "base/time.h"
#include "chrome/browser/google_service_auth_error.h"
+#include "chrome/browser/pref_member.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/glue/data_type_manager.h"
#include "chrome/browser/sync/glue/sync_backend_host.h"
#include "chrome/browser/sync/notification_method.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
#include "chrome/browser/sync/sync_setup_wizard.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/unrecoverable_error_handler.h"
@@ -31,21 +33,6 @@ class NotificationType;
class Profile;
class ProfileSyncFactory;
-// Various UI components such as the New Tab page can be driven by observing
-// the ProfileSyncService through this interface.
-class ProfileSyncServiceObserver {
- public:
- // When one of the following events occurs, OnStateChanged() is called.
- // Observers should query the service to determine what happened.
- // - We initialized successfully.
- // - There was an authentication error and the user needs to reauthenticate.
- // - The sync servers are unavailable at this time.
- // - Credentials are now in flight for authentication.
- virtual void OnStateChanged() = 0;
- protected:
- virtual ~ProfileSyncServiceObserver() { }
-};
-
// ProfileSyncService is the layer between browser subsystems like bookmarks,
// and the sync backend. Each subsystem is logically thought of as being
// a sync datatype.
@@ -258,6 +245,10 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// command-line switches).
static bool IsSyncEnabled();
+ // Retuns whether sync is managed, i.e. controlled by configuration
+ // management. If so, the user is not allowed to configure sync.
+ bool IsManaged();
+
// UnrecoverableErrorHandler implementation.
virtual void OnUnrecoverableError(
const tracked_objects::Location& from_here,
@@ -442,6 +433,10 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
ScopedRunnableMethodFactory<ProfileSyncService>
scoped_runnable_method_factory_;
+ // The preference that controls whether sync is under control by configuration
+ // management.
+ BooleanPrefMember pref_sync_managed_;
+
DISALLOW_COPY_AND_ASSIGN(ProfileSyncService);
};
diff --git a/chrome/browser/sync/profile_sync_service_observer.h b/chrome/browser/sync/profile_sync_service_observer.h
new file mode 100644
index 0000000..2bd967c
--- /dev/null
+++ b/chrome/browser/sync/profile_sync_service_observer.h
@@ -0,0 +1,23 @@
+// Copyright (c) 2010 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_SYNC_PROFILE_SYNC_SERVICE_OBSERVER_H_
+#define CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_OBSERVER_H_
+
+// Various UI components such as the New Tab page can be driven by observing
+// the ProfileSyncService through this interface.
+class ProfileSyncServiceObserver {
+ public:
+ // When one of the following events occurs, OnStateChanged() is called.
+ // Observers should query the service to determine what happened.
+ // - We initialized successfully.
+ // - There was an authentication error and the user needs to reauthenticate.
+ // - The sync servers are unavailable at this time.
+ // - Credentials are now in flight for authentication.
+ virtual void OnStateChanged() = 0;
+ protected:
+ virtual ~ProfileSyncServiceObserver() { }
+};
+
+#endif // CHROME_BROWSER_SYNC_PROFILE_SYNC_SERVICE_OBSERVER_H_
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index 21e6648..63df954 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -121,6 +121,40 @@ TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartNormal)) {
service_->Initialize();
}
+TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(ManagedStartup)) {
+ // Disable sync through policy.
+ profile_.GetPrefs()->SetBoolean(prefs::kSyncManaged, true);
+
+ EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).Times(0);
+ EXPECT_CALL(observer_, OnStateChanged()).Times(1);
+
+ // Service should not be started by Initialize() since it's managed.
+ service_->Initialize();
+}
+
+TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(SwitchManaged)) {
+ DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
+ EXPECT_CALL(*data_type_manager, Configure(_)).Times(1);
+ EXPECT_CALL(observer_, OnStateChanged()).Times(3);
+
+ service_->Initialize();
+
+ // The service should stop when switching to managed mode.
+ Mock::VerifyAndClearExpectations(data_type_manager);
+ EXPECT_CALL(*data_type_manager, state()).
+ WillOnce(Return(DataTypeManager::CONFIGURED));
+ EXPECT_CALL(*data_type_manager, Stop()).Times(1);
+ EXPECT_CALL(observer_, OnStateChanged()).Times(2);
+ profile_.GetPrefs()->SetBoolean(prefs::kSyncManaged, true);
+
+ // When switching back to unmanaged, the state should change, but the service
+ // should not start up automatically (kSyncSetupCompleted will be false).
+ Mock::VerifyAndClearExpectations(data_type_manager);
+ EXPECT_CALL(factory_, CreateDataTypeManager(_, _)).Times(0);
+ EXPECT_CALL(observer_, OnStateChanged()).Times(1);
+ profile_.GetPrefs()->ClearPref(prefs::kSyncManaged);
+}
+
TEST_F(ProfileSyncServiceStartupTest, SKIP_MACOSX(StartFailure)) {
DataTypeManagerMock* data_type_manager = SetUpDataTypeManager();
DataTypeManager::ConfigureResult result =
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index df28f40..ce8e4f9 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -163,7 +163,7 @@ MessageType GetStatus(ProfileSyncService* service) {
}
bool ShouldShowSyncErrorButton(ProfileSyncService* service) {
- return service && service->HasSyncSetupCompleted() &&
+ return service && !service->IsManaged() && service->HasSyncSetupCompleted() &&
(GetStatus(service) == sync_ui_util::SYNC_ERROR);
}
@@ -182,7 +182,7 @@ void OpenSyncMyBookmarksDialog(
Profile* profile, ProfileSyncService::SyncEventCodes code) {
ProfileSyncService* service =
profile->GetOriginalProfile()->GetProfileSyncService();
- if (!service) {
+ if (!service || !service->IsSyncEnabled()) {
LOG(DFATAL) << "OpenSyncMyBookmarksDialog called with sync disabled";
return;
}
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index a4de470..984744c 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -1187,7 +1187,7 @@ void BookmarkBarView::ButtonPressed(views::Button* sender,
// Show the login wizard if the user clicked the re-login button.
if (sender->tag() == kSyncErrorButtonTag) {
DCHECK(sender == sync_error_button_);
- DCHECK(sync_service_);
+ DCHECK(sync_service_ && !sync_service_->IsManaged());
sync_service_->ShowLoginDialog();
return;
}
diff --git a/chrome/browser/views/options/content_page_view.cc b/chrome/browser/views/options/content_page_view.cc
index 1d25651..093c90d 100644
--- a/chrome/browser/views/options/content_page_view.cc
+++ b/chrome/browser/views/options/content_page_view.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/sync/sync_setup_wizard.h"
#include "chrome/browser/views/importer_view.h"
+#include "chrome/browser/views/options/managed_prefs_banner_view.h"
#include "chrome/browser/views/options/options_group_view.h"
#include "chrome/browser/views/options/passwords_exceptions_window_view.h"
#include "chrome/common/chrome_switches.h"
@@ -49,6 +50,12 @@ const int kFormAutofillRadioGroup = 202;
// Background color for the status label when it's showing an error.
static const SkColor kSyncLabelErrorBgColor = SkColorSetRGB(0xff, 0x9a, 0x9a);
+// All content related preferences that are potentially managed by policy. We'll
+// display the warning banner if one of these have the managed bit set.
+const wchar_t* kContentPolicyConstrainedPrefs[] = {
+ prefs::kSyncManaged
+};
+
static views::Background* CreateErrorBackground() {
return views::Background::CreateSolidBackground(kSyncLabelErrorBgColor);
}
@@ -136,7 +143,7 @@ void ContentPageView::ButtonPressed(
gfx::Rect(),
new ImporterView(profile(), importer::ALL))->Show();
} else if (sender == sync_start_stop_button_) {
- DCHECK(sync_service_);
+ DCHECK(sync_service_ && !sync_service_->IsManaged());
if (sync_service_->HasSyncSetupCompleted()) {
ConfirmMessageBoxDialog::RunWithCustomConfiguration(
@@ -170,7 +177,7 @@ void ContentPageView::LinkActivated(views::Link* source, int event_flags) {
return;
}
if (source == sync_action_link_) {
- DCHECK(sync_service_);
+ DCHECK(sync_service_ && !sync_service_->IsManaged());
sync_service_->ShowLoginDialog();
return;
}
@@ -197,6 +204,11 @@ void ContentPageView::InitControlLayout() {
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
GridLayout::USE_PREF, 0, 0);
+ layout->StartRow(0, single_column_view_set_id);
+ layout->AddView(
+ new ManagedPrefsBannerView(profile()->GetPrefs(),
+ kContentPolicyConstrainedPrefs,
+ arraysize(kContentPolicyConstrainedPrefs)));
if (sync_service_) {
layout->StartRow(0, single_column_view_set_id);
InitSyncGroup();
@@ -489,6 +501,7 @@ void ContentPageView::UpdateSyncControls() {
std::wstring link_label;
std::wstring customize_button_label;
std::wstring button_label;
+ bool managed = sync_service_->IsManaged();
bool sync_setup_completed = sync_service_->HasSyncSetupCompleted();
bool status_has_error = sync_ui_util::GetStatusLabels(sync_service_,
&status_label, &link_label) == sync_ui_util::SYNC_ERROR;
@@ -503,12 +516,15 @@ void ContentPageView::UpdateSyncControls() {
}
sync_status_label_->SetText(status_label);
- sync_start_stop_button_->SetEnabled(!sync_service_->WizardIsVisible());
+ sync_start_stop_button_->SetEnabled(
+ !sync_service_->WizardIsVisible() && !managed);
sync_start_stop_button_->SetLabel(button_label);
sync_customize_button_->SetLabel(customize_button_label);
sync_customize_button_->SetVisible(sync_setup_completed && !status_has_error);
+ sync_customize_button_->SetEnabled(!managed);
sync_action_link_->SetText(link_label);
sync_action_link_->SetVisible(!link_label.empty());
+ sync_action_link_->SetEnabled(!managed);
if (status_has_error) {
sync_status_label_->set_background(CreateErrorBackground());
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 9e098d5..424b011 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -874,6 +874,10 @@ const wchar_t kSyncThemes[] = L"sync.themes";
const wchar_t kSyncTypedUrls[] = L"sync.typed_urls";
const wchar_t kSyncExtensions[] = L"sync.extensions";
+// Boolean used by enterprise configuration management in order to lock down
+// sync.
+const wchar_t kSyncManaged[] = L"sync.managed";
+
// Create web application shortcut dialog preferences.
const wchar_t kWebAppCreateOnDesktop[] = L"browser.web_app.create_on_desktop";
const wchar_t kWebAppCreateInAppsMenu[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 360b655..4a00675 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -319,6 +319,7 @@ extern const wchar_t kSyncAutofill[];
extern const wchar_t kSyncThemes[];
extern const wchar_t kSyncTypedUrls[];
extern const wchar_t kSyncExtensions[];
+extern const wchar_t kSyncManaged[];
extern const wchar_t kWebAppCreateOnDesktop[];
extern const wchar_t kWebAppCreateInAppsMenu[];