shelf_prefs.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/public/cpp/shelf_prefs.h"
  5. #include <memory>
  6. #include "ash/constants/ash_pref_names.h"
  7. #include "base/strings/string_number_conversions.h"
  8. #include "base/values.h"
  9. #include "components/prefs/pref_service.h"
  10. #include "components/prefs/scoped_user_pref_update.h"
  11. #include "ui/display/display.h"
  12. #include "ui/display/screen.h"
  13. #include "ui/display/types/display_constants.h"
  14. namespace ash {
  15. const char kShelfAutoHideBehaviorAlways[] = "Always";
  16. const char kShelfAutoHideBehaviorNever[] = "Never";
  17. // If any of the following ShelfAlignment values changed, the ShelfAlignment
  18. // policy should be updated.
  19. const char kShelfAlignmentBottom[] = "Bottom";
  20. const char kShelfAlignmentLeft[] = "Left";
  21. const char kShelfAlignmentRight[] = "Right";
  22. namespace {
  23. // Returns the preference value for the display with the given |display_id|.
  24. // The pref value is stored in |local_path| and |path|, but the pref service may
  25. // have per-display preferences and the value can be specified by policy.
  26. // Here is the priority:
  27. // * A value managed by policy. This is a single value that applies to all
  28. // displays.
  29. // * A user-set value for the specified display.
  30. // * A user-set value in |local_path| or |path|, if no per-display settings are
  31. // ever specified (see http://crbug.com/173719 for why), |local_path| is
  32. // preferred. See comment in |kShelfAlignment| as to why we consider two
  33. // prefs and why |local_path| is preferred.
  34. // * A value recommended by policy. This is a single value that applies to all
  35. // root windows.
  36. // * The default value for |local_path| if the value is not recommended by
  37. // policy.
  38. std::string GetPerDisplayPref(PrefService* prefs,
  39. int64_t display_id,
  40. const char* local_path,
  41. const char* path) {
  42. const PrefService::Preference* local_pref = prefs->FindPreference(local_path);
  43. const std::string value(prefs->GetString(local_path));
  44. if (local_pref->IsManaged())
  45. return value;
  46. std::string pref_key = base::NumberToString(display_id);
  47. bool has_per_display_prefs = false;
  48. if (!pref_key.empty()) {
  49. const base::Value::Dict& shelf_prefs =
  50. prefs->GetValueDict(prefs::kShelfPreferences);
  51. const base::Value::Dict* display_pref = shelf_prefs.FindDict(pref_key);
  52. if (display_pref) {
  53. const std::string* per_display_value =
  54. display_pref->FindStringByDottedPath(path);
  55. if (per_display_value)
  56. return *per_display_value;
  57. }
  58. // If the pref for the specified display is not found, scan the whole prefs
  59. // and check if the prefs for other display is already specified.
  60. std::string unused_value;
  61. for (const auto iter : shelf_prefs) {
  62. if (iter.second.is_dict() && iter.second.FindStringPath(path)) {
  63. has_per_display_prefs = true;
  64. break;
  65. }
  66. }
  67. }
  68. if (local_pref->IsRecommended() || !has_per_display_prefs)
  69. return value;
  70. const std::string* default_string =
  71. prefs->GetDefaultPrefValue(local_path)->GetIfString();
  72. return default_string ? *default_string : std::string();
  73. }
  74. // Sets the preference value for the display with the given |display_id|.
  75. void SetPerDisplayPref(PrefService* prefs,
  76. int64_t display_id,
  77. const char* pref_key,
  78. const std::string& value) {
  79. if (display_id == display::kInvalidDisplayId)
  80. return;
  81. // Avoid DictionaryPrefUpdate's notifications for read but unmodified prefs.
  82. const base::Value::Dict& current_shelf_prefs =
  83. prefs->GetValueDict(prefs::kShelfPreferences);
  84. std::string display_key = base::NumberToString(display_id);
  85. const base::Value::Dict* current_display_prefs =
  86. current_shelf_prefs.FindDict(display_key);
  87. if (current_display_prefs) {
  88. const std::string* current_value =
  89. current_display_prefs->FindStringByDottedPath(pref_key);
  90. if (current_value && *current_value == value)
  91. return;
  92. }
  93. DictionaryPrefUpdate update(prefs, prefs::kShelfPreferences);
  94. base::Value* shelf_prefs = update.Get();
  95. base::Value* display_prefs_weak = shelf_prefs->FindDictKey(display_key);
  96. if (!display_prefs_weak) {
  97. display_prefs_weak = shelf_prefs->SetKey(
  98. display_key, base::Value(base::Value::Type::DICTIONARY));
  99. }
  100. display_prefs_weak->SetKey(pref_key, base::Value(value));
  101. }
  102. ShelfAlignment AlignmentFromPref(const std::string& value) {
  103. if (value == kShelfAlignmentLeft)
  104. return ShelfAlignment::kLeft;
  105. if (value == kShelfAlignmentRight)
  106. return ShelfAlignment::kRight;
  107. // Default to bottom.
  108. return ShelfAlignment::kBottom;
  109. }
  110. const char* AlignmentToPref(ShelfAlignment alignment) {
  111. switch (alignment) {
  112. case ShelfAlignment::kBottom:
  113. return kShelfAlignmentBottom;
  114. case ShelfAlignment::kLeft:
  115. return kShelfAlignmentLeft;
  116. case ShelfAlignment::kRight:
  117. return kShelfAlignmentRight;
  118. case ShelfAlignment::kBottomLocked:
  119. // This should not be a valid preference option for now. We only want to
  120. // lock the shelf during login or when adding a user.
  121. return nullptr;
  122. }
  123. NOTREACHED();
  124. return nullptr;
  125. }
  126. ShelfAutoHideBehavior AutoHideBehaviorFromPref(const std::string& value) {
  127. // Note: To maintain sync compatibility with old images of chrome/chromeos
  128. // the set of values that may be encountered includes the now-extinct
  129. // "Default" as well as "Never" and "Always", "Default" should now
  130. // be treated as "Never" (http://crbug.com/146773).
  131. if (value == kShelfAutoHideBehaviorAlways)
  132. return ShelfAutoHideBehavior::kAlways;
  133. return ShelfAutoHideBehavior::kNever;
  134. }
  135. const char* AutoHideBehaviorToPref(ShelfAutoHideBehavior behavior) {
  136. switch (behavior) {
  137. case ShelfAutoHideBehavior::kAlways:
  138. return kShelfAutoHideBehaviorAlways;
  139. case ShelfAutoHideBehavior::kNever:
  140. return kShelfAutoHideBehaviorNever;
  141. case ShelfAutoHideBehavior::kAlwaysHidden:
  142. // This should not be a valid preference option for now. We only want to
  143. // completely hide it when we run in app mode - or while we temporarily
  144. // hide the shelf (e.g. SessionAbortedDialog).
  145. return nullptr;
  146. }
  147. NOTREACHED();
  148. return nullptr;
  149. }
  150. } // namespace
  151. ShelfAutoHideBehavior GetShelfAutoHideBehaviorPref(PrefService* prefs,
  152. int64_t display_id) {
  153. DCHECK_NE(display_id, display::kInvalidDisplayId);
  154. // See comment in |kShelfAlignment| as to why we consider two prefs.
  155. return AutoHideBehaviorFromPref(
  156. GetPerDisplayPref(prefs, display_id, prefs::kShelfAutoHideBehaviorLocal,
  157. prefs::kShelfAutoHideBehavior));
  158. }
  159. void SetShelfAutoHideBehaviorPref(PrefService* prefs,
  160. int64_t display_id,
  161. ShelfAutoHideBehavior behavior) {
  162. DCHECK_NE(display_id, display::kInvalidDisplayId);
  163. const char* value = AutoHideBehaviorToPref(behavior);
  164. if (!value)
  165. return;
  166. SetPerDisplayPref(prefs, display_id, prefs::kShelfAutoHideBehavior, value);
  167. if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) {
  168. // See comment in |kShelfAlignment| about why we have two prefs here.
  169. prefs->SetString(prefs::kShelfAutoHideBehaviorLocal, value);
  170. prefs->SetString(prefs::kShelfAutoHideBehavior, value);
  171. }
  172. }
  173. ShelfAlignment GetShelfAlignmentPref(PrefService* prefs, int64_t display_id) {
  174. DCHECK_NE(display_id, display::kInvalidDisplayId);
  175. // See comment in |kShelfAlignment| as to why we consider two prefs.
  176. return AlignmentFromPref(GetPerDisplayPref(
  177. prefs, display_id, prefs::kShelfAlignmentLocal, prefs::kShelfAlignment));
  178. }
  179. void SetShelfAlignmentPref(PrefService* prefs,
  180. int64_t display_id,
  181. ShelfAlignment alignment) {
  182. DCHECK_NE(display_id, display::kInvalidDisplayId);
  183. const char* value = AlignmentToPref(alignment);
  184. if (!value)
  185. return;
  186. SetPerDisplayPref(prefs, display_id, prefs::kShelfAlignment, value);
  187. if (display_id == display::Screen::GetScreen()->GetPrimaryDisplay().id()) {
  188. // See comment in |kShelfAlignment| as to why we consider two prefs.
  189. prefs->SetString(prefs::kShelfAlignmentLocal, value);
  190. prefs->SetString(prefs::kShelfAlignment, value);
  191. }
  192. }
  193. } // namespace ash