1// Copyright 2013 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//
5// A helper class that assists preferences in firing notifications when lists
6// or dictionaries are changed.
7
8#ifndef BASE_PREFS_SCOPED_USER_PREF_UPDATE_H_
9#define BASE_PREFS_SCOPED_USER_PREF_UPDATE_H_
10
11#include <string>
12
13#include "base/basictypes.h"
14#include "base/prefs/base_prefs_export.h"
15#include "base/prefs/pref_service.h"
16#include "base/threading/non_thread_safe.h"
17#include "base/values.h"
18
19class PrefService;
20
21namespace base {
22class DictionaryValue;
23class ListValue;
24}
25
26namespace subtle {
27
28// Base class for ScopedUserPrefUpdateTemplate that contains the parts
29// that do not depend on ScopedUserPrefUpdateTemplate's template parameter.
30//
31// We need this base class mostly for making it a friend of PrefService
32// and getting access to PrefService::GetMutableUserPref and
33// PrefService::ReportUserPrefChanged.
34class BASE_PREFS_EXPORT ScopedUserPrefUpdateBase : public base::NonThreadSafe {
35 protected:
36  ScopedUserPrefUpdateBase(PrefService* service, const char* path);
37
38  // Calls Notify().
39  ~ScopedUserPrefUpdateBase();
40
41  // Sets |value_| to |service_|->GetMutableUserPref and returns it.
42  base::Value* GetValueOfType(base::Value::Type type);
43
44 private:
45  // If |value_| is not null, triggers a notification of PrefObservers and
46  // resets |value_|.
47  void Notify();
48
49  // Weak pointer.
50  PrefService* service_;
51  // Path of the preference being updated.
52  std::string path_;
53  // Cache of value from user pref store (set between Get() and Notify() calls).
54  base::Value* value_;
55
56  DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdateBase);
57};
58
59}  // namespace subtle
60
61// Class to support modifications to DictionaryValues and ListValues while
62// guaranteeing that PrefObservers are notified of changed values.
63//
64// This class may only be used on the UI thread as it requires access to the
65// PrefService.
66template <typename T, base::Value::Type type_enum_value>
67class ScopedUserPrefUpdate : public subtle::ScopedUserPrefUpdateBase {
68 public:
69  ScopedUserPrefUpdate(PrefService* service, const char* path)
70      : ScopedUserPrefUpdateBase(service, path) {}
71
72  // Triggers an update notification if Get() was called.
73  virtual ~ScopedUserPrefUpdate() {}
74
75  // Returns a mutable |T| instance that
76  // - is already in the user pref store, or
77  // - is (silently) created and written to the user pref store if none existed
78  //   before.
79  //
80  // Calling Get() implies that an update notification is necessary at
81  // destruction time.
82  //
83  // The ownership of the return value remains with the user pref store.
84  // Virtual so it can be overriden in subclasses that transform the value
85  // before returning it (for example to return a subelement of a dictionary).
86  virtual T* Get() {
87    return static_cast<T*>(GetValueOfType(type_enum_value));
88  }
89
90  T& operator*() {
91    return *Get();
92  }
93
94  T* operator->() {
95    return Get();
96  }
97
98 private:
99  DISALLOW_COPY_AND_ASSIGN(ScopedUserPrefUpdate);
100};
101
102typedef ScopedUserPrefUpdate<base::DictionaryValue,
103                             base::Value::TYPE_DICTIONARY>
104    DictionaryPrefUpdate;
105typedef ScopedUserPrefUpdate<base::ListValue, base::Value::TYPE_LIST>
106    ListPrefUpdate;
107
108#endif  // BASE_PREFS_SCOPED_USER_PREF_UPDATE_H_
109