summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormichaelpg@chromium.org <michaelpg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-14 14:07:28 +0000
committermichaelpg@chromium.org <michaelpg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-14 14:07:28 +0000
commitc0bbb533cb570ee90c93b131cf3762baf4b8d535 (patch)
tree0008147f60837f9914490b8989172cd06e505f2c
parentb09aeb1e9f832a4f02047adc024370fb38d7d6a6 (diff)
downloadchromium_src-c0bbb533cb570ee90c93b131cf3762baf4b8d535.zip
chromium_src-c0bbb533cb570ee90c93b131cf3762baf4b8d535.tar.gz
chromium_src-c0bbb533cb570ee90c93b131cf3762baf4b8d535.tar.bz2
Clarify settings UI in multi-profiles mode
Adds bubble buttons to indicate which settings are shared. When signed in as a secondary user (i.e., added to a multi-profile session), a banner should be display. The "Internet connection" header should show a shared icon. Owner-controlled settings should show the owner icon. "Require password to wake from sleep" is a special case. This also fixes a bug where controlled settings on managed devices should say they are controlled by policy, but instead say the (non-existent) owner controls them. For details, see PRD with additional links at bottom: https://docs.google.com/a/google.com/document/d/1G09Mql1TtVFA4qhb7hlt4u2crBv6_fhrZMf40Yo--lc BUG=326354 R=dbeam@chromium.org, stevenjb@chromium.org, oshima@chromium.org Review URL: https://codereview.chromium.org/152143009 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251302 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/chromeos_strings.grdp19
-rw-r--r--chrome/app/theme/theme_resources.grd7
-rw-r--r--chrome/browser/profiles/profile_impl.cc3
-rw-r--r--chrome/browser/resources/options/browser_options.html10
-rw-r--r--chrome/browser/resources/options/browser_options.js20
-rw-r--r--chrome/browser/resources/options/content_settings.css9
-rw-r--r--chrome/browser/resources/options/controlled_setting.css11
-rw-r--r--chrome/browser/resources/options/controlled_setting.js10
-rw-r--r--chrome/browser/resources/options/language_options.css3
-rw-r--r--chrome/browser/resources/options/language_options.html1
-rw-r--r--chrome/browser/resources/options/language_options.js17
-rw-r--r--chrome/browser/resources/options/secondary_user_banner.html11
-rw-r--r--chrome/browser/resources/options/settings_banner.css7
-rw-r--r--chrome/browser/resources/uber/uber_shared.css24
-rw-r--r--chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc115
-rw-r--r--chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h3
-rw-r--r--chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc12
-rw-r--r--chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc116
-rw-r--r--chrome/browser/ui/webui/options/core_options_handler.h5
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--ui/webui/resources/css/bubble_button.css3
21 files changed, 340 insertions, 67 deletions
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index dc076e9..1676f66 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1584,6 +1584,9 @@ Press any key to continue exploring.
<message name="IDS_LOGIN_CAPTCHA_INSTRUCTIONS" desc="Explanatory message shown when the user must type letters shown in a captcha image to reauthenticate.">
Type the characters you see in the picture below.
</message>
+ <message name="IDS_OPTIONS_SETTINGS_SECONDARY_USER_BANNER" desc="Banner displayed in settings page when the user is secondary in a multi-profile session.">
+ Some settings belonging to <ph name="PRIMARY_EMAIL">$1<ex>john@google.com</ex></ph> are being shared with you. These settings only affect your account when using multiple sign-in.
+ </message>
<message name="IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME">
Date and time
</message>
@@ -2685,13 +2688,21 @@ Press any key to continue exploring.
<message name="IDS_TERMS_OF_SERVICE_SCREEN_ACCEPT_BUTTON" desc="Text of the accept button on the Terms of Service screen.">
Accept and continue
</message>
-
- <message name="IDS_OPTIONS_CONTROLLED_SETTING_OWNER" desc="Tooltip for options which can be edited only by the owner">
- This setting is enforced by the owner of the device.
+ <message name="IDS_OPTIONS_CONTROLLED_SETTING_OWNER" desc="Text displayed in the controlled settings bubble when a setting's value can be edited only by the owner.">
+ This setting is managed by the device owner, <ph name="OWNER_EMAIL">$1<ex>john@google.com</ex></ph>.
</message>
- <message name="IDS_OPTION_DISABLED_BY_POLICY" desc="Tooltip for options managed by enterprise policy">
+ <message name="IDS_OPTION_DISABLED_BY_POLICY" desc="Text displayed in the controlled settings bubble when a setting's value is enforced by enterprise policy.">
This option is controlled by enterprise policy. Please contact your administrator for more information.
</message>
+ <message name="IDS_OPTIONS_CONTROLLED_SETTING_SHARED" desc="Text displayed in the controlled settings bubble when a setting's value belongs to the primary user but can be edited.">
+ This setting belongs to <ph name="OWNER_EMAIL">$1<ex>john@google.com</ex></ph>.
+ </message>
+ <message name="IDS_OPTIONS_CONTROLLED_SETTINGS_SHARED" desc="Text displayed in the controlled settings bubble when it is shown for a group of settings which belong to the primary user but can be edited.">
+ These settings belong to <ph name="OWNER_EMAIL">$1<ex>john@google.com</ex></ph>.
+ </message>
+ <message name="IDS_OPTIONS_CONTROLLED_SETTING_SHARED_SCREEN_LOCK" desc="Text displayed in the controlled settings bubble for the screen lock option, indicating screen lock is enabled if it's set for any profile in a session.">
+ Passwords are required for signed-in users, as one or more users has this setting turned on.
+ </message>
<message name="IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_SETTINGS_TITLE"
desc="The title for the Chewing input settings dialog. Please note that 'Chewing' here is name of an input method and not 'an act of biting and grinding with the teeth'.">
Chewing input settings
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 8dbec6c..8a21b6b 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -154,6 +154,10 @@
<structure type="chrome_scaled_image" name="IDR_CONTENT_TOP_RIGHT_CORNER_MASK" file="content_top_right_corner_mask.png" />
<structure type="chrome_scaled_image" name="IDR_CONTROLLED_SETTING_EXTENSION" file="common/controlled_setting_extension.png" />
<structure type="chrome_scaled_image" name="IDR_CONTROLLED_SETTING_MANDATORY" file="common/controlled_setting_mandatory.png" />
+ <structure type="chrome_scaled_image" name="IDR_CONTROLLED_SETTING_OWNER" file="common/controlled_setting_owner.png" />
+ <if expr="pp_ifdef('chromeos')">
+ <structure type="chrome_scaled_image" name="IDR_CONTROLLED_SETTING_SHARED" file="cros/controlled_setting_shared.png" />
+ </if>
<structure type="chrome_scaled_image" name="IDR_COOKIE_ICON" file="cookie.png" />
<structure type="chrome_scaled_image" name="IDR_COOKIE_STORAGE_ICON" file="cookie_storage.png" />
<structure type="chrome_scaled_image" name="IDR_CREDIT_CARD_CVC_HINT" file="common/credit_card_cvc_hint.png" />
@@ -869,6 +873,9 @@
<structure type="chrome_scaled_image" name="IDR_SAFEBROWSING_WARNING" file="safebrowsing_warning.png" />
<structure type="chrome_scaled_image" name="IDR_SCREEN_CAPTURE_NOTIFICATION_GRIP" file="screen_capture_notification_grip.png" />
<structure type="chrome_scaled_image" name="IDR_SCREENSHOT_NOTIFICATION_ICON" file="common/notification_screenshot_icon.png" />
+ <if expr="pp_ifdef('chromeos')">
+ <structure type="chrome_scaled_image" name="IDR_SECONDARY_USER_SETTINGS" file="cros/secondary_user_settings.png" />
+ </if>
<if expr="pp_ifdef('enable_settings_app')">
<structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_128" file="settings_app_icon_128.png" />
<structure type="chrome_scaled_image" name="IDR_SETTINGS_APP_ICON_16" file="settings_app_icon_16.png" />
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index be6d07a..a7ab71b 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1143,7 +1143,8 @@ void ProfileImpl::ChangeAppLocale(
GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
local_state->SetString(prefs::kApplicationLocale, new_locale);
- if (chromeos::UserManager::Get()->IsCurrentUserOwner())
+ if (chromeos::UserManager::Get()->GetOwnerEmail() ==
+ chromeos::UserManager::Get()->GetUserByProfile(this)->email())
local_state->SetString(prefs::kOwnerLocale, new_locale);
}
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index 036876a..c98f60b 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -4,12 +4,13 @@
</header>
<include src="reset_profile_settings_banner.html">
<include src="automatic_settings_reset_banner.html">
-<if expr="not pp_ifdef('chromeos')">
- <include src="sync_section.html">
-</if>
<if expr="pp_ifdef('chromeos')">
+ <include src="secondary_user_banner.html">
<section>
- <h3 i18n-content="sectionTitleInternet"></h3>
+ <div id="network-section-header" class="section-header">
+ <h3 i18n-content="sectionTitleInternet"></h3>
+ <span class="controlled-setting-indicator" plural></span>
+ </div>
<div id="network-settings">
<list id="network-list"></list>
<div id="shared-proxies" class="checkbox">
@@ -24,6 +25,7 @@
</section>
</if>
<if expr="not pp_ifdef('chromeos')">
+ <include src="sync_section.html">
<include src="startup_section.html">
</if>
<section>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index dfa6bc8..1485936 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -77,8 +77,11 @@ cr.define('options', function() {
$('advanced-settings').addEventListener('webkitTransitionEnd',
this.updateAdvancedSettingsExpander_.bind(this));
- if (cr.isChromeOS)
+ if (cr.isChromeOS) {
UIAccountTweaks.applyGuestModeVisibility(document);
+ if (loadTimeData.getBoolean('secondaryUser'))
+ $('secondary-user-banner').hidden = false;
+ }
// Sync (Sign in) section.
this.updateSyncState_(loadTimeData.getValue('syncData'));
@@ -98,6 +101,14 @@ cr.define('options', function() {
// Internet connection section (ChromeOS only).
if (cr.isChromeOS) {
options.network.NetworkList.decorate($('network-list'));
+ // Show that the network settings are shared if this is a secondary user
+ // in a multi-profile session.
+ if (loadTimeData.getBoolean('secondaryUser')) {
+ var networkIndicator = document.querySelector(
+ '#network-section-header > .controlled-setting-indicator');
+ networkIndicator.setAttribute('controlled-by', 'shared');
+ networkIndicator.location = cr.ui.ArrowLocation.TOP_START;
+ }
options.network.NetworkList.refreshNetworkData(
loadTimeData.getValue('networkData'));
}
@@ -230,8 +241,15 @@ cr.define('options', function() {
chrome.send('coreOptionsUserMetricsAction',
['Options_ManageAccounts']);
};
+
+ document.querySelector(
+ '#enable-screen-lock + span > .controlled-setting-indicator').
+ setAttribute('textshared',
+ loadTimeData.getString('screenLockShared'));
+
$('hotword-app-list').hidden =
!loadTimeData.getBoolean('shouldShowAppListHotword');
+
} else {
$('import-data').onclick = function(event) {
ImportDataOverlay.show();
diff --git a/chrome/browser/resources/options/content_settings.css b/chrome/browser/resources/options/content_settings.css
index 30e01d1..1d5084e 100644
--- a/chrome/browser/resources/options/content_settings.css
+++ b/chrome/browser/resources/options/content_settings.css
@@ -68,15 +68,6 @@ div[role='listitem'][controlled-by] {
position: relative;
}
-.section-header {
- -webkit-margin-start: -18px;
- margin-bottom: 0.8em;
-}
-
-.section-header > h3 {
- display: inline;
-}
-
.settings-list div[role='listitem'][controlled-by='policy'],
.settings-list div[role='listitem'][controlled-by='extension'] {
background: rgb(250, 230, 146);
diff --git a/chrome/browser/resources/options/controlled_setting.css b/chrome/browser/resources/options/controlled_setting.css
index 496336e..488e907 100644
--- a/chrome/browser/resources/options/controlled_setting.css
+++ b/chrome/browser/resources/options/controlled_setting.css
@@ -27,11 +27,6 @@
padding: 0;
}
-input:-webkit-any([type='text'],[type='url'],:not([type])) +
- .controlled-setting-indicator {
- -webkit-margin-start: 5px;
-}
-
.controlled-setting-indicator:not([controlled-by]) {
display: none;
}
@@ -41,13 +36,17 @@ input:-webkit-any([type='text'],[type='url'],:not([type])) +
}
.controlled-setting-indicator[controlled-by='owner'] > div {
- background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY');
+ background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_OWNER');
}
.controlled-setting-indicator[controlled-by='extension'] > div {
background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_EXTENSION');
}
+.controlled-setting-indicator[controlled-by='shared'] > div {
+ background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_SHARED');
+}
+
.controlled-setting-indicator:-webkit-any([controlled-by='recommended'],
[controlled-by='hasRecommendation']) > div {
background-image: url('chrome://theme/IDR_CONTROLLED_SETTING_MANDATORY');
diff --git a/chrome/browser/resources/options/controlled_setting.js b/chrome/browser/resources/options/controlled_setting.js
index bbf1de8..17048d4 100644
--- a/chrome/browser/resources/options/controlled_setting.js
+++ b/chrome/browser/resources/options/controlled_setting.js
@@ -105,6 +105,10 @@ cr.define('options', function() {
'extensionWithName': loadTimeData.getString(
'controlledSettingsExtensionWithName'),
};
+ if (cr.isChromeOS) {
+ defaultStrings.shared =
+ loadTimeData.getString('controlledSettingsShared');
+ }
} else {
var defaultStrings = {
'policy': loadTimeData.getString('controlledSettingPolicy'),
@@ -119,6 +123,8 @@ cr.define('options', function() {
if (cr.isChromeOS) {
defaultStrings.owner =
loadTimeData.getString('controlledSettingOwner');
+ defaultStrings.shared =
+ loadTimeData.getString('controlledSettingShared');
}
}
@@ -221,6 +227,10 @@ cr.define('options', function() {
* override this recommendation but has not done so.
* - 'hasRecommendation': A value is recommended by policy. The user has
* overridden this recommendation.
+ * - 'owner': A value is controlled by the owner of the device
+ * (Chrome OS only).
+ * - 'shared': A value belongs to the primary user but can be
+ * modified (Chrome OS only).
* - unset: The value is controlled by the user alone.
* @type {string}
*/
diff --git a/chrome/browser/resources/options/language_options.css b/chrome/browser/resources/options/language_options.css
index 7bb4e95..8683cfd 100644
--- a/chrome/browser/resources/options/language_options.css
+++ b/chrome/browser/resources/options/language_options.css
@@ -29,7 +29,8 @@
padding: 0 12px 4px;
}
-.language-options-contents > span:not(.input-method-label) {
+.language-options-contents >
+ span:not(.input-method-label):not(.controlled-setting-indicator) {
display: inline-block;
margin: 1px;
padding: 0.42em 10px;
diff --git a/chrome/browser/resources/options/language_options.html b/chrome/browser/resources/options/language_options.html
index ce41bc9..595365e 100644
--- a/chrome/browser/resources/options/language_options.html
+++ b/chrome/browser/resources/options/language_options.html
@@ -32,6 +32,7 @@
<button id="language-options-ui-language-button"
i18n-content="displayInThisLanguage">
</button>
+ <span class="controlled-setting-indicator"></span>
<span id="language-options-ui-language-message" hidden></span>
</div>
</if>
diff --git a/chrome/browser/resources/options/language_options.js b/chrome/browser/resources/options/language_options.js
index 3ebf7d2..4792e1c 100644
--- a/chrome/browser/resources/options/language_options.js
+++ b/chrome/browser/resources/options/language_options.js
@@ -557,6 +557,11 @@ cr.define('options', function() {
// hidden by a language change.
uiLanguageButton.hidden = false;
+ // Hide the controlled setting indicator.
+ var uiLanguageIndicator = document.querySelector(
+ '.language-options-contents .controlled-setting-indicator');
+ uiLanguageIndicator.removeAttribute('controlled-by');
+
if (languageCode == this.prospectiveUiLanguageCode_) {
uiLanguageMessage.textContent =
loadTimeData.getString('isDisplayedInThisLanguage');
@@ -571,11 +576,17 @@ cr.define('options', function() {
} else {
uiLanguageButton.textContent =
loadTimeData.getString('displayInThisLanguage');
+
+ if (loadTimeData.getBoolean('secondaryUser')) {
+ uiLanguageButton.disabled = true;
+ uiLanguageIndicator.setAttribute('controlled-by', 'shared');
+ } else {
+ uiLanguageButton.onclick = function(e) {
+ chrome.send('uiLanguageChange', [languageCode]);
+ };
+ }
showMutuallyExclusiveNodes(
[uiLanguageButton, uiLanguageMessage, uiLanguageNotification], 0);
- uiLanguageButton.onclick = function(e) {
- chrome.send('uiLanguageChange', [languageCode]);
- };
}
} else {
uiLanguageMessage.textContent =
diff --git a/chrome/browser/resources/options/secondary_user_banner.html b/chrome/browser/resources/options/secondary_user_banner.html
new file mode 100644
index 0000000..84da427
--- /dev/null
+++ b/chrome/browser/resources/options/secondary_user_banner.html
@@ -0,0 +1,11 @@
+<div id="secondary-user-banner" class="settings-banner" hidden>
+ <div class="content-area">
+ <div class="badge"></div>
+ <div class="text">
+ <p>
+ <span i18n-values=".innerHTML:secondaryUserBannerText">
+ </span>
+ </p>
+ </div>
+ </div>
+</div>
diff --git a/chrome/browser/resources/options/settings_banner.css b/chrome/browser/resources/options/settings_banner.css
index 9086427..44add99 100644
--- a/chrome/browser/resources/options/settings_banner.css
+++ b/chrome/browser/resources/options/settings_banner.css
@@ -13,8 +13,8 @@
border-width: 1px;
margin-bottom: 24px;
margin-top: 20px;
+ max-width: 716px;
position: relative;
- width: 716px;
}
.settings-banner > .close-button {
@@ -78,3 +78,8 @@ html[dir='rtl'] .settings-banner > .close-button {
margin-bottom: 1px;
margin-right: 0;
}
+
+#secondary-user-banner .content-area .badge {
+ background-color: rgb(210, 210, 212);
+ background-image: url(chrome://theme/IDR_SECONDARY_USER_SETTINGS);
+}
diff --git a/chrome/browser/resources/uber/uber_shared.css b/chrome/browser/resources/uber/uber_shared.css
index a981ad6..7bd22b2 100644
--- a/chrome/browser/resources/uber/uber_shared.css
+++ b/chrome/browser/resources/uber/uber_shared.css
@@ -115,24 +115,20 @@ body.uber-frame section > h3 {
-webkit-margin-start: -18px;
}
-@media(pointer:coarse) {
- /* TODO(kevers): Remove the extra padding once the following bug is fixed:
- * https://bugs.webkit.org/show_bug.cgi?id=95204
- * In the interim, the added padding makes it less likely that a touch will
- * span the boundary of the navigation bar, which results in poor touch
- * adjustments. */
- body.uber-frame section {
- -webkit-padding-start: 28px;
- }
- body.uber-frame section > h3 {
- -webkit-margin-start: -28px;
- }
-}
-
body.uber-frame section > div:only-of-type {
-webkit-box-flex: 1;
}
+body.uber-frame .section-header {
+ -webkit-margin-start: -18px;
+ margin-bottom: 0.8em;
+ margin-top: 1.2em;
+}
+
+body.uber-frame .section-header > h3 {
+ display: inline;
+}
+
/* Styles for a hideable notification banner at the top of a page. */
.page.showing-banner {
margin-top: 45px;
diff --git a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
index 0dc8c61..73d9c77 100644
--- a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.cc
@@ -6,11 +6,14 @@
#include <string>
+#include "ash/session_state_delegate.h"
+#include "ash/shell.h"
#include "base/bind.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/sys_info.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
@@ -42,13 +45,6 @@ bool IsSettingOwnerOnly(const std::string& pref) {
return std::find(kNonOwnerSettings, end, pref) == end;
}
-// Returns true if |username| is the logged-in owner.
-bool IsLoggedInOwner(const std::string& username) {
- UserManager* user_manager = UserManager::Get();
- return user_manager->IsCurrentUserOwner() &&
- user_manager->GetLoggedInUser()->email() == username;
-}
-
// Creates a user info dictionary to be stored in the |ListValue| that is
// passed to Javascript for the |kAccountsPrefUsers| preference.
base::DictionaryValue* CreateUserInfo(const std::string& username,
@@ -58,7 +54,9 @@ base::DictionaryValue* CreateUserInfo(const std::string& username,
user_dict->SetString("username", username);
user_dict->SetString("name", display_email);
user_dict->SetString("email", display_name);
- user_dict->SetBoolean("owner", IsLoggedInOwner(username));
+
+ bool is_owner = UserManager::Get()->GetOwnerEmail() == username;
+ user_dict->SetBoolean("owner", is_owner);
return user_dict;
}
@@ -133,6 +131,7 @@ base::Value* CoreChromeOSOptionsHandler::FetchPref(
return value;
}
+
if (!CrosSettings::IsCrosSettings(pref_name)) {
std::string controlling_pref =
pref_name == prefs::kUseSharedProxies ? prefs::kProxy : std::string();
@@ -152,13 +151,16 @@ base::Value* CoreChromeOSOptionsHandler::FetchPref(
dict->Set("value", pref_value->DeepCopy());
policy::BrowserPolicyConnectorChromeOS* connector =
g_browser_process->platform_part()->browser_policy_connector_chromeos();
- if (connector->IsEnterpriseManaged())
+ if (connector->IsEnterpriseManaged()) {
+ dict->SetBoolean("disabled", true);
dict->SetString("controlledBy", "policy");
- bool disabled_by_owner = IsSettingOwnerOnly(pref_name) &&
- !ProfileHelper::IsOwnerProfile(Profile::FromWebUI(web_ui()));
- dict->SetBoolean("disabled", disabled_by_owner);
- if (disabled_by_owner)
- dict->SetString("controlledBy", "owner");
+ } else {
+ bool controlled_by_owner = IsSettingOwnerOnly(pref_name) &&
+ !ProfileHelper::IsOwnerProfile(Profile::FromWebUI(web_ui()));
+ dict->SetBoolean("disabled", controlled_by_owner);
+ if (controlled_by_owner)
+ dict->SetString("controlledBy", "owner");
+ }
return dict;
}
@@ -209,15 +211,92 @@ void CoreChromeOSOptionsHandler::StopObservingPref(const std::string& path) {
::options::CoreOptionsHandler::StopObservingPref(path);
}
+base::Value* CoreChromeOSOptionsHandler::CreateValueForPref(
+ const std::string& pref_name,
+ const std::string& controlling_pref_name) {
+ // The screen lock setting is shared if multiple users are logged in and at
+ // least one has chosen to require passwords.
+ if (pref_name == prefs::kEnableAutoScreenLock &&
+ UserManager::Get()->GetLoggedInUsers().size() > 1 &&
+ controlling_pref_name.empty()) {
+ PrefService* user_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+ const PrefService::Preference* pref =
+ user_prefs->FindPreference(prefs::kEnableAutoScreenLock);
+
+ ash::SessionStateDelegate* delegate =
+ ash::Shell::GetInstance()->session_state_delegate();
+ if (pref && pref->IsUserModifiable() &&
+ delegate->ShouldLockScreenBeforeSuspending()) {
+ bool screen_lock = false;
+ bool success = pref->GetValue()->GetAsBoolean(&screen_lock);
+ DCHECK(success);
+ if (!screen_lock) {
+ // Screen lock is enabled for the session, but not in the user's
+ // preferences. Show the user's value in the checkbox, but indicate
+ // that the password requirement is enabled by some other user.
+ base::DictionaryValue* dict = new base::DictionaryValue;
+ dict->Set("value", pref->GetValue()->DeepCopy());
+ dict->SetString("controlledBy", "shared");
+ return dict;
+ }
+ }
+ }
+
+ return CoreOptionsHandler::CreateValueForPref(pref_name,
+ controlling_pref_name);
+}
+
void CoreChromeOSOptionsHandler::GetLocalizedValues(
base::DictionaryValue* localized_strings) {
DCHECK(localized_strings);
CoreOptionsHandler::GetLocalizedValues(localized_strings);
- AddAccountUITweaksLocalizedValues(localized_strings,
- Profile::FromWebUI(web_ui()));
- localized_strings->SetString("controlledSettingOwner",
- l10n_util::GetStringUTF16(IDS_OPTIONS_CONTROLLED_SETTING_OWNER));
+ Profile* profile = Profile::FromWebUI(web_ui());
+ AddAccountUITweaksLocalizedValues(localized_strings, profile);
+
+ UserManager* user_manager = UserManager::Get();
+ const std::string& primary_email = user_manager->GetPrimaryUser()->email();
+
+ // Check at load time whether this is a secondary user in a multi-profile
+ // session.
+ if (user_manager->GetUserByProfile(profile)->email() != primary_email) {
+ // Set secondaryUser to show the shared icon by the network section header.
+ localized_strings->SetBoolean("secondaryUser", true);
+ localized_strings->SetString("secondaryUserBannerText",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_SETTINGS_SECONDARY_USER_BANNER,
+ base::ASCIIToUTF16(primary_email)));
+ localized_strings->SetString("controlledSettingShared",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_CONTROLLED_SETTING_SHARED,
+ base::ASCIIToUTF16(primary_email)));
+ localized_strings->SetString("controlledSettingsShared",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_CONTROLLED_SETTINGS_SHARED,
+ base::ASCIIToUTF16(primary_email)));
+ } else {
+ localized_strings->SetBoolean("secondaryUser", false);
+ localized_strings->SetString("secondaryUserBannerText", base::string16());
+ localized_strings->SetString("controlledSettingShared", base::string16());
+ localized_strings->SetString("controlledSettingsShared", base::string16());
+ }
+
+ // Screen lock icon can show up as primary or secondary user.
+ localized_strings->SetString("screenLockShared",
+ l10n_util::GetStringUTF16(
+ IDS_OPTIONS_CONTROLLED_SETTING_SHARED_SCREEN_LOCK));
+
+ policy::BrowserPolicyConnectorChromeOS* connector =
+ g_browser_process->platform_part()->browser_policy_connector_chromeos();
+ if (connector->IsEnterpriseManaged()) {
+ // Managed machines have no "owner".
+ localized_strings->SetString("controlledSettingOwner", base::string16());
+ } else {
+ localized_strings->SetString("controlledSettingOwner",
+ l10n_util::GetStringFUTF16(
+ IDS_OPTIONS_CONTROLLED_SETTING_OWNER,
+ base::ASCIIToUTF16(user_manager->GetOwnerEmail())));
+ }
}
void CoreChromeOSOptionsHandler::SelectNetworkCallback(
diff --git a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h
index 4b823b4..76c3fff 100644
--- a/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h
+++ b/chrome/browser/ui/webui/options/chromeos/core_chromeos_options_handler.h
@@ -31,6 +31,9 @@ class CoreChromeOSOptionsHandler : public ::options::CoreOptionsHandler {
const base::Value* value,
const std::string& metric) OVERRIDE;
virtual void StopObservingPref(const std::string& path) OVERRIDE;
+ virtual base::Value* CreateValueForPref(
+ const std::string& pref_name,
+ const std::string& controlling_pref_name) OVERRIDE;
// OptionsPageUIHandler implementation.
virtual void GetLocalizedValues(
diff --git a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc
index 192cbe8..372ba6f 100644
--- a/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/cros_language_options_handler.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/customization_document.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/lifetime/application_lifetime.h"
@@ -389,8 +390,15 @@ base::string16 CrosLanguageOptionsHandler::GetProductName() {
void CrosLanguageOptionsHandler::SetApplicationLocale(
const std::string& language_code) {
- Profile::FromWebUI(web_ui())->ChangeAppLocale(
- language_code, Profile::APP_LOCALE_CHANGED_VIA_SETTINGS);
+ Profile* profile = Profile::FromWebUI(web_ui());
+ UserManager* user_manager = UserManager::Get();
+
+ // Only the primary user can change the locale.
+ if (user_manager->GetUserByProfile(profile)->email() ==
+ user_manager->GetPrimaryUser()->email()) {
+ profile->ChangeAppLocale(language_code,
+ Profile::APP_LOCALE_CHANGED_VIA_SETTINGS);
+ }
}
void CrosLanguageOptionsHandler::RestartCallback(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc b/chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc
new file mode 100644
index 0000000..47e2f04
--- /dev/null
+++ b/chrome/browser/ui/webui/options/chromeos/shared_options_browsertest.cc
@@ -0,0 +1,116 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/user_adding_screen.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/settings/cros_settings_names.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+
+namespace chromeos {
+
+namespace {
+
+const char* kTestUsers[] = { "test-user1@gmail.com", "test-user2@gmail.com" };
+
+} // namespace
+
+class SharedOptionsTest : public LoginManagerTest {
+ public:
+ SharedOptionsTest()
+ : LoginManagerTest(false),
+ device_settings_provider_(NULL) {
+ stub_settings_provider_.Set(kDeviceOwner, base::StringValue(kTestUsers[0]));
+ }
+
+ virtual ~SharedOptionsTest() {
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ LoginManagerTest::SetUpOnMainThread();
+ CrosSettings* settings = CrosSettings::Get();
+ device_settings_provider_ = settings->GetProvider(kDeviceOwner);
+ settings->RemoveSettingsProvider(device_settings_provider_);
+ settings->AddSettingsProvider(&stub_settings_provider_);
+ }
+
+ virtual void CleanUpOnMainThread() OVERRIDE {
+ CrosSettings* settings = CrosSettings::Get();
+ settings->RemoveSettingsProvider(&stub_settings_provider_);
+ settings->AddSettingsProvider(device_settings_provider_);
+ LoginManagerTest::CleanUpOnMainThread();
+ }
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+ LoginManagerTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(::switches::kMultiProfiles);
+ command_line->AppendSwitch(switches::kForceMultiProfileInTests);
+ }
+
+ protected:
+ void CheckOptionsUI(const User* user, bool is_primary) {
+ Profile* profile = UserManager::Get()->GetProfileByUser(user);
+ profile->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+ user->email());
+
+ ui_test_utils::BrowserAddedObserver observer;
+ Browser* browser = CreateBrowser(profile);
+ observer.WaitForSingleNewBrowser();
+
+ ui_test_utils::NavigateToURL(browser,
+ GURL("chrome://settings-frame"));
+ content::WebContents* contents =
+ browser->tab_strip_model()->GetActiveWebContents();
+
+ bool banner_visible;
+ ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
+ contents,
+ "var e = document.getElementById('secondary-user-banner');"
+ "var visible = e.offsetWidth > 0 && e.offsetHeight > 0;"
+ "window.domAutomationController.send(visible);",
+ &banner_visible));
+ EXPECT_EQ(is_primary, !banner_visible);
+ }
+
+ StubCrosSettingsProvider stub_settings_provider_;
+ CrosSettingsProvider* device_settings_provider_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SharedOptionsTest);
+};
+
+IN_PROC_BROWSER_TEST_F(SharedOptionsTest, PRE_SharedOptions) {
+ RegisterUser(kTestUsers[0]);
+ RegisterUser(kTestUsers[1]);
+ StartupUtils::MarkOobeCompleted();
+}
+
+IN_PROC_BROWSER_TEST_F(SharedOptionsTest, SharedOptions) {
+ LoginUser(kTestUsers[0]);
+ UserAddingScreen::Get()->Start();
+ content::RunAllPendingInMessageLoop();
+ AddUser(kTestUsers[1]);
+
+ UserManager* manager = UserManager::Get();
+ ASSERT_EQ(2u, manager->GetLoggedInUsers().size());
+
+ CheckOptionsUI(manager->FindUser(kTestUsers[0]), true /* is_primary */);
+ CheckOptionsUI(manager->FindUser(kTestUsers[1]), false /* is_primary */);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/ui/webui/options/core_options_handler.h b/chrome/browser/ui/webui/options/core_options_handler.h
index 2804590..369be28 100644
--- a/chrome/browser/ui/webui/options/core_options_handler.h
+++ b/chrome/browser/ui/webui/options/core_options_handler.h
@@ -88,8 +88,9 @@ class CoreOptionsHandler : public OptionsPageUIHandler {
// Creates dictionary value for the pref described by |pref_name|.
// If |controlling_pref| is not empty, it describes the pref that manages
// |pref| via policy or extension.
- base::Value* CreateValueForPref(const std::string& pref_name,
- const std::string& controlling_pref_name);
+ virtual base::Value* CreateValueForPref(
+ const std::string& pref_name,
+ const std::string& controlling_pref_name);
typedef std::multimap<std::string, std::string> PreferenceCallbackMap;
PreferenceCallbackMap pref_callback_map_;
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 189ea9e..e0abb0a 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1551,6 +1551,7 @@
'browser/ui/webui/options/chromeos/accounts_options_browsertest.js',
'browser/ui/webui/options/chromeos/bluetooth_options_browsertest.js',
'browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc',
+ 'browser/ui/webui/options/chromeos/shared_options_browsertest.cc',
'browser/ui/webui/options/content_options_browsertest.js',
'browser/ui/webui/options/content_settings_exception_area_browsertest.js',
'browser/ui/webui/options/cookies_view_browsertest.js',
diff --git a/ui/webui/resources/css/bubble_button.css b/ui/webui/resources/css/bubble_button.css
index 5f37ed2..7d6d5d7 100644
--- a/ui/webui/resources/css/bubble_button.css
+++ b/ui/webui/resources/css/bubble_button.css
@@ -7,6 +7,7 @@
display: inline-block;
height: 0;
line-height: 1;
+ margin-left: 4px;
vertical-align: middle;
width: 16px;
}
@@ -15,6 +16,6 @@
background-size: 16px;
height: 16px;
position: relative;
- top: -8px;
+ top: -9px;
width: 16px;
}