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