123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// found in the LICENSE file.
423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h"
623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/prefs/pref_registry_simple.h"
823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/prefs/pref_service.h"
923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/prefs/scoped_user_pref_update.h"
1023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "base/values.h"
1123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)namespace {
1323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
1423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Implements get-or-create of a dictionary value and holds a
1523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// DictionaryPrefUpdate.
1623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)class PrefServiceMutableDictionary
1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    : public HashStoreContents::MutableDictionary {
1823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) public:
1923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Creates an instance that provides mutable access to a dictionary value
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // named |key| that is a child of |kProfilePreferenceHashes| in
2123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // |prefs|.
2223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  PrefServiceMutableDictionary(const std::string& key,
2323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                               PrefService* pref_service);
2423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // HashStoreContents::MutableDictionary implementation
2623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  virtual base::DictionaryValue* operator->() OVERRIDE;
2723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) private:
2923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const std::string key_;
3023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DictionaryPrefUpdate update_;
3123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)};
3223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)PrefServiceMutableDictionary::PrefServiceMutableDictionary(
3423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const std::string& key,
3523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    PrefService* pref_service)
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : key_(key),
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      update_(pref_service,
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              PrefServiceHashStoreContents::kProfilePreferenceHashes) {
3923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(!key_.empty());
4023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
4123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)base::DictionaryValue* PrefServiceMutableDictionary::operator->() {
4323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::DictionaryValue* dictionary = NULL;
4423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!update_->GetDictionaryWithoutPathExpansion(key_, &dictionary)) {
4523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    dictionary = new base::DictionaryValue;
4623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    update_->SetWithoutPathExpansion(key_, dictionary);
4723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
4823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return dictionary;
4923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
5123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}  // namespace
5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)const char PrefServiceHashStoreContents::kProfilePreferenceHashes[] =
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    "profile.preference_hashes";
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// static
5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const char PrefServiceHashStoreContents::kHashOfHashesDict[] = "hash_of_hashes";
5923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const char PrefServiceHashStoreContents::kStoreVersionsDict[] =
6223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    "store_versions";
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)PrefServiceHashStoreContents::PrefServiceHashStoreContents(
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const std::string& hash_store_id,
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    PrefService* pref_service)
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    : hash_store_id_(hash_store_id), pref_service_(pref_service) {
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // TODO(erikwright): Remove in M40+.
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DictionaryPrefUpdate update(pref_service_, kProfilePreferenceHashes);
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  update->RemovePath(kStoreVersionsDict, NULL);
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
7223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
7323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
7423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void PrefServiceHashStoreContents::RegisterPrefs(PrefRegistrySimple* registry) {
7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Register the top level dictionary to map profile names to dictionaries of
7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // tracked preferences.
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  registry->RegisterDictionaryPref(kProfilePreferenceHashes);
7823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
7923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
8123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void PrefServiceHashStoreContents::ResetAllPrefHashStores(
8223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    PrefService* pref_service) {
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  pref_service->ClearPref(kProfilePreferenceHashes);
8423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
8523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
8623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)std::string PrefServiceHashStoreContents::hash_store_id() const {
8723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return hash_store_id_;
8823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
8923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void PrefServiceHashStoreContents::Reset() {
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DictionaryPrefUpdate update(pref_service_, kProfilePreferenceHashes);
9223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  update->RemoveWithoutPathExpansion(hash_store_id_, NULL);
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
9523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Remove this store's entry in the kHashOfHashesDict.
9623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  base::DictionaryValue* hash_of_hashes_dict;
9723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (update->GetDictionaryWithoutPathExpansion(kHashOfHashesDict,
9823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                &hash_of_hashes_dict)) {
9923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    hash_of_hashes_dict->RemoveWithoutPathExpansion(hash_store_id_, NULL);
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (hash_of_hashes_dict->empty())
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      update->RemovePath(kHashOfHashesDict, NULL);
10223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (update->empty())
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    pref_service_->ClearPref(kProfilePreferenceHashes);
10623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
10723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
10823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool PrefServiceHashStoreContents::IsInitialized() const {
10923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const base::DictionaryValue* pref_hash_dicts =
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pref_service_->GetDictionary(kProfilePreferenceHashes);
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return pref_hash_dicts->GetDictionaryWithoutPathExpansion(hash_store_id_,
11223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                            NULL);
11323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const base::DictionaryValue* PrefServiceHashStoreContents::GetContents() const {
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const base::DictionaryValue* pref_hash_dicts =
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pref_service_->GetDictionary(kProfilePreferenceHashes);
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const base::DictionaryValue* hashes_dict = NULL;
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  pref_hash_dicts->GetDictionaryWithoutPathExpansion(hash_store_id_,
12023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                     &hashes_dict);
12123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return hashes_dict;
12223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)scoped_ptr<HashStoreContents::MutableDictionary>
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)PrefServiceHashStoreContents::GetMutableContents() {
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return scoped_ptr<HashStoreContents::MutableDictionary>(
12723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      new PrefServiceMutableDictionary(hash_store_id_, pref_service_));
12823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
12923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)std::string PrefServiceHashStoreContents::GetSuperMac() const {
13123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const base::DictionaryValue* pref_hash_dicts =
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      pref_service_->GetDictionary(kProfilePreferenceHashes);
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const base::DictionaryValue* hash_of_hashes_dict = NULL;
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  std::string hash_of_hashes;
13523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (pref_hash_dicts->GetDictionaryWithoutPathExpansion(
13623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)          kHashOfHashesDict, &hash_of_hashes_dict)) {
13723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    hash_of_hashes_dict->GetStringWithoutPathExpansion(hash_store_id_,
13823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                                       &hash_of_hashes);
13923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
14023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return hash_of_hashes;
14123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
14223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
14323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void PrefServiceHashStoreContents::SetSuperMac(const std::string& super_mac) {
14423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  PrefServiceMutableDictionary(kHashOfHashesDict, pref_service_)
14523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      ->SetStringWithoutPathExpansion(hash_store_id_, super_mac);
14623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
147