| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/prefs/profile_pref_store_manager.h" | 5 #include "chrome/browser/prefs/profile_pref_store_manager.h" |
| 6 | 6 |
| 7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/json/json_file_value_serializer.h" | 8 #include "base/json/json_file_value_serializer.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/prefs/json_pref_store.h" | 11 #include "base/prefs/json_pref_store.h" |
| 12 #include "base/prefs/persistent_pref_store.h" | 12 #include "base/prefs/persistent_pref_store.h" |
| 13 #include "base/prefs/pref_registry_simple.h" | 13 #include "base/prefs/pref_registry_simple.h" |
| 14 #include "chrome/browser/prefs/pref_hash_store_impl.h" | 14 #include "chrome/browser/prefs/pref_hash_store_impl.h" |
| 15 #include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h" | 15 #include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h" |
| 16 #include "chrome/browser/prefs/tracked/segregated_pref_store.h" | 16 #include "chrome/browser/prefs/tracked/segregated_pref_store.h" |
| 17 #include "chrome/browser/prefs/tracked/tracked_preference_validation_observer.h" |
| 17 #include "chrome/common/chrome_constants.h" | 18 #include "chrome/common/chrome_constants.h" |
| 18 #include "chrome/common/pref_names.h" | 19 #include "chrome/common/pref_names.h" |
| 19 #include "components/user_prefs/pref_registry_syncable.h" | 20 #include "components/user_prefs/pref_registry_syncable.h" |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // An adaptor that allows a PrefHashStoreImpl to access a preference store | 24 // An adaptor that allows a PrefHashStoreImpl to access a preference store |
| 24 // directly as a dictionary. Uses an equivalent layout to | 25 // directly as a dictionary. Uses an equivalent layout to |
| 25 // PrefStoreHashStoreContents. | 26 // PrefStoreHashStoreContents. |
| 26 class DictionaryHashStoreContents : public HashStoreContents { | 27 class DictionaryHashStoreContents : public HashStoreContents { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 void InitializeHashStoreObserver::OnPrefValueChanged(const std::string& key) {} | 174 void InitializeHashStoreObserver::OnPrefValueChanged(const std::string& key) {} |
| 174 | 175 |
| 175 void InitializeHashStoreObserver::OnInitializationCompleted(bool succeeded) { | 176 void InitializeHashStoreObserver::OnInitializationCompleted(bool succeeded) { |
| 176 // If we successfully loaded the preferences _and_ the PrefHashStoreImpl | 177 // If we successfully loaded the preferences _and_ the PrefHashStoreImpl |
| 177 // hasn't been initialized by someone else in the meantime, initialize it now. | 178 // hasn't been initialized by someone else in the meantime, initialize it now. |
| 178 const PrefHashStoreImpl::StoreVersion pre_update_version = | 179 const PrefHashStoreImpl::StoreVersion pre_update_version = |
| 179 pref_hash_store_impl_->GetCurrentVersion(); | 180 pref_hash_store_impl_->GetCurrentVersion(); |
| 180 if (succeeded && pre_update_version < PrefHashStoreImpl::VERSION_LATEST) { | 181 if (succeeded && pre_update_version < PrefHashStoreImpl::VERSION_LATEST) { |
| 181 PrefHashFilter(pref_hash_store_impl_.PassAs<PrefHashStore>(), | 182 PrefHashFilter(pref_hash_store_impl_.PassAs<PrefHashStore>(), |
| 182 tracking_configuration_, | 183 tracking_configuration_, |
| 184 scoped_ptr<TrackedPreferenceValidationObserver>(), |
| 183 reporting_ids_count_).Initialize(*pref_store_); | 185 reporting_ids_count_).Initialize(*pref_store_); |
| 184 UMA_HISTOGRAM_ENUMERATION( | 186 UMA_HISTOGRAM_ENUMERATION( |
| 185 "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom", | 187 "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom", |
| 186 pre_update_version, | 188 pre_update_version, |
| 187 PrefHashStoreImpl::VERSION_LATEST + 1); | 189 PrefHashStoreImpl::VERSION_LATEST + 1); |
| 188 } | 190 } |
| 189 pref_store_->RemoveObserver(this); | 191 pref_store_->RemoveObserver(this); |
| 190 delete this; | 192 delete this; |
| 191 } | 193 } |
| 192 | 194 |
| 195 // A TrackedPreferenceValidationObserver that delegates to another shared |
| 196 // observer instance. |
| 197 class DelegatingValidationObserver |
| 198 : public TrackedPreferenceValidationObserver { |
| 199 public: |
| 200 // A reference-counted holder of a TrackedPreferenceValidationObserver. |
| 201 class RefCountedObserver : public base::RefCounted<RefCountedObserver> { |
| 202 public: |
| 203 explicit RefCountedObserver( |
| 204 scoped_ptr<TrackedPreferenceValidationObserver> observer); |
| 205 TrackedPreferenceValidationObserver* get(); |
| 206 |
| 207 private: |
| 208 friend class base::RefCounted<RefCountedObserver>; |
| 209 ~RefCountedObserver(); |
| 210 |
| 211 scoped_ptr<TrackedPreferenceValidationObserver> observer_; |
| 212 }; |
| 213 |
| 214 explicit DelegatingValidationObserver( |
| 215 const scoped_refptr<RefCountedObserver>& observer); |
| 216 virtual ~DelegatingValidationObserver(); |
| 217 |
| 218 // TrackedPreferenceValidationObserver methods. |
| 219 virtual void OnAtomicPreferenceValidation( |
| 220 const std::string& pref_path, |
| 221 const base::Value* value, |
| 222 PrefHashStoreTransaction::ValueState value_state, |
| 223 TrackedPreferenceHelper::ResetAction reset_action) OVERRIDE; |
| 224 virtual void OnSplitPreferenceValidation( |
| 225 const std::string& pref_path, |
| 226 const base::DictionaryValue* dict_value, |
| 227 const std::vector<std::string>& invalid_keys, |
| 228 PrefHashStoreTransaction::ValueState value_state, |
| 229 TrackedPreferenceHelper::ResetAction reset_action) OVERRIDE; |
| 230 |
| 231 private: |
| 232 scoped_refptr<RefCountedObserver> observer_; |
| 233 DISALLOW_COPY_AND_ASSIGN(DelegatingValidationObserver); |
| 234 }; |
| 235 |
| 236 DelegatingValidationObserver::RefCountedObserver::RefCountedObserver( |
| 237 scoped_ptr<TrackedPreferenceValidationObserver> observer) |
| 238 : observer_(observer.Pass()) { |
| 239 } |
| 240 |
| 241 DelegatingValidationObserver::RefCountedObserver::~RefCountedObserver() { |
| 242 } |
| 243 |
| 244 TrackedPreferenceValidationObserver* |
| 245 DelegatingValidationObserver::RefCountedObserver::get() { |
| 246 return observer_.get(); |
| 247 } |
| 248 |
| 249 DelegatingValidationObserver::DelegatingValidationObserver( |
| 250 const scoped_refptr<RefCountedObserver>& observer) |
| 251 : observer_(observer) { |
| 252 } |
| 253 |
| 254 DelegatingValidationObserver::~DelegatingValidationObserver() { |
| 255 } |
| 256 |
| 257 void DelegatingValidationObserver::OnAtomicPreferenceValidation( |
| 258 const std::string& pref_path, |
| 259 const base::Value* value, |
| 260 PrefHashStoreTransaction::ValueState value_state, |
| 261 TrackedPreferenceHelper::ResetAction reset_action) { |
| 262 observer_->get()->OnAtomicPreferenceValidation( |
| 263 pref_path, value, value_state, reset_action); |
| 264 } |
| 265 |
| 266 void DelegatingValidationObserver::OnSplitPreferenceValidation( |
| 267 const std::string& pref_path, |
| 268 const base::DictionaryValue* dict_value, |
| 269 const std::vector<std::string>& invalid_keys, |
| 270 PrefHashStoreTransaction::ValueState value_state, |
| 271 TrackedPreferenceHelper::ResetAction reset_action) { |
| 272 observer_->get()->OnSplitPreferenceValidation( |
| 273 pref_path, dict_value, invalid_keys, value_state, reset_action); |
| 274 } |
| 275 |
| 193 } // namespace | 276 } // namespace |
| 194 | 277 |
| 195 // TODO(erikwright): Enable this on Chrome OS and Android once MACs are moved | 278 // TODO(erikwright): Enable this on Chrome OS and Android once MACs are moved |
| 196 // out of Local State. This will resolve a race condition on Android and a | 279 // out of Local State. This will resolve a race condition on Android and a |
| 197 // privacy issue on ChromeOS. http://crbug.com/349158 | 280 // privacy issue on ChromeOS. http://crbug.com/349158 |
| 198 const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking = | 281 const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking = |
| 199 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) | 282 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) |
| 200 false; | 283 false; |
| 201 #else | 284 #else |
| 202 true; | 285 true; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 // pref store before being deleted from the latter. | 346 // pref store before being deleted from the latter. |
| 264 PrefHashFilter::ClearResetTime(pref_service); | 347 PrefHashFilter::ClearResetTime(pref_service); |
| 265 } | 348 } |
| 266 | 349 |
| 267 void ProfilePrefStoreManager::ResetPrefHashStore() { | 350 void ProfilePrefStoreManager::ResetPrefHashStore() { |
| 268 if (kPlatformSupportsPreferenceTracking) | 351 if (kPlatformSupportsPreferenceTracking) |
| 269 GetPrefHashStoreImpl()->Reset(); | 352 GetPrefHashStoreImpl()->Reset(); |
| 270 } | 353 } |
| 271 | 354 |
| 272 PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore( | 355 PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore( |
| 273 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) { | 356 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner, |
| 357 scoped_ptr<TrackedPreferenceValidationObserver> verification_observer) { |
| 274 scoped_ptr<PrefFilter> pref_filter; | 358 scoped_ptr<PrefFilter> pref_filter; |
| 275 if (!kPlatformSupportsPreferenceTracking) { | 359 if (!kPlatformSupportsPreferenceTracking) { |
| 276 return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_), | 360 return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_), |
| 277 io_task_runner, | 361 io_task_runner, |
| 278 scoped_ptr<PrefFilter>()); | 362 scoped_ptr<PrefFilter>()); |
| 279 } | 363 } |
| 280 | 364 |
| 281 std::vector<PrefHashFilter::TrackedPreferenceMetadata> | 365 std::vector<PrefHashFilter::TrackedPreferenceMetadata> |
| 282 unprotected_configuration; | 366 unprotected_configuration; |
| 283 std::vector<PrefHashFilter::TrackedPreferenceMetadata> | 367 std::vector<PrefHashFilter::TrackedPreferenceMetadata> |
| 284 protected_configuration; | 368 protected_configuration; |
| 285 std::set<std::string> protected_pref_names; | 369 std::set<std::string> protected_pref_names; |
| 286 for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::const_iterator | 370 for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::const_iterator |
| 287 it = tracking_configuration_.begin(); | 371 it = tracking_configuration_.begin(); |
| 288 it != tracking_configuration_.end(); | 372 it != tracking_configuration_.end(); |
| 289 ++it) { | 373 ++it) { |
| 290 if (it->enforcement_level > PrefHashFilter::NO_ENFORCEMENT) { | 374 if (it->enforcement_level > PrefHashFilter::NO_ENFORCEMENT) { |
| 291 protected_configuration.push_back(*it); | 375 protected_configuration.push_back(*it); |
| 292 protected_pref_names.insert(it->name); | 376 protected_pref_names.insert(it->name); |
| 293 } else { | 377 } else { |
| 294 unprotected_configuration.push_back(*it); | 378 unprotected_configuration.push_back(*it); |
| 295 } | 379 } |
| 296 } | 380 } |
| 297 | 381 |
| 298 scoped_ptr<PrefFilter> unprotected_pref_hash_filter( | 382 scoped_refptr<DelegatingValidationObserver::RefCountedObserver> observer; |
| 299 new PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(), | 383 if (verification_observer) { |
| 300 unprotected_configuration, | 384 observer = new DelegatingValidationObserver::RefCountedObserver( |
| 301 reporting_ids_count_)); | 385 verification_observer.Pass()); |
| 302 scoped_ptr<PrefFilter> protected_pref_hash_filter( | 386 } |
| 303 new PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(), | 387 |
| 304 protected_configuration, | 388 scoped_ptr<PrefFilter> unprotected_pref_hash_filter(new PrefHashFilter( |
| 305 reporting_ids_count_)); | 389 GetPrefHashStoreImpl().PassAs<PrefHashStore>(), |
| 390 unprotected_configuration, |
| 391 observer ? |
| 392 scoped_ptr<TrackedPreferenceValidationObserver>( |
| 393 new DelegatingValidationObserver(observer)) : |
| 394 scoped_ptr<TrackedPreferenceValidationObserver>(), |
| 395 reporting_ids_count_)); |
| 396 scoped_ptr<PrefFilter> protected_pref_hash_filter(new PrefHashFilter( |
| 397 GetPrefHashStoreImpl().PassAs<PrefHashStore>(), |
| 398 protected_configuration, |
| 399 observer ? |
| 400 scoped_ptr<TrackedPreferenceValidationObserver>( |
| 401 new DelegatingValidationObserver(observer)) : |
| 402 scoped_ptr<TrackedPreferenceValidationObserver>(), |
| 403 reporting_ids_count_)); |
| 306 | 404 |
| 307 scoped_refptr<PersistentPrefStore> unprotected_pref_store( | 405 scoped_refptr<PersistentPrefStore> unprotected_pref_store( |
| 308 new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_), | 406 new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_), |
| 309 io_task_runner, | 407 io_task_runner, |
| 310 unprotected_pref_hash_filter.Pass())); | 408 unprotected_pref_hash_filter.Pass())); |
| 311 scoped_refptr<PersistentPrefStore> protected_pref_store(new JsonPrefStore( | 409 scoped_refptr<PersistentPrefStore> protected_pref_store(new JsonPrefStore( |
| 312 profile_path_.Append(chrome::kProtectedPreferencesFilename), | 410 profile_path_.Append(chrome::kProtectedPreferencesFilename), |
| 313 io_task_runner, | 411 io_task_runner, |
| 314 protected_pref_hash_filter.Pass())); | 412 protected_pref_hash_filter.Pass())); |
| 315 | 413 |
| 316 // The on_initialized callback is used to migrate newly protected values from | 414 // The on_initialized callback is used to migrate newly protected values from |
| 317 // the main Preferences store to the Protected Preferences store. It is also | 415 // the main Preferences store to the Protected Preferences store. It is also |
| 318 // responsible for the initial migration to a two-store model. | 416 // responsible for the initial migration to a two-store model. |
| 319 return new SegregatedPrefStore( | 417 return new SegregatedPrefStore( |
| 320 unprotected_pref_store, | 418 unprotected_pref_store, |
| 321 protected_pref_store, | 419 protected_pref_store, |
| 322 protected_pref_names, | 420 protected_pref_names, |
| 323 base::Bind(&PrefHashFilter::MigrateValues, | 421 base::Bind( |
| 324 base::Owned(new PrefHashFilter( | 422 &PrefHashFilter::MigrateValues, |
| 325 CopyPrefHashStore(), | 423 base::Owned(new PrefHashFilter( |
| 326 protected_configuration, | 424 CopyPrefHashStore(), |
| 327 reporting_ids_count_)), | 425 protected_configuration, |
| 328 unprotected_pref_store, | 426 observer ? |
| 329 protected_pref_store)); | 427 scoped_ptr<TrackedPreferenceValidationObserver>( |
| 428 new DelegatingValidationObserver(observer)) : |
| 429 scoped_ptr<TrackedPreferenceValidationObserver>(), |
| 430 reporting_ids_count_)), |
| 431 unprotected_pref_store, |
| 432 protected_pref_store)); |
| 330 } | 433 } |
| 331 | 434 |
| 332 void ProfilePrefStoreManager::UpdateProfileHashStoreIfRequired( | 435 void ProfilePrefStoreManager::UpdateProfileHashStoreIfRequired( |
| 333 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) { | 436 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) { |
| 334 if (!kPlatformSupportsPreferenceTracking) | 437 if (!kPlatformSupportsPreferenceTracking) |
| 335 return; | 438 return; |
| 336 scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl(GetPrefHashStoreImpl()); | 439 scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl(GetPrefHashStoreImpl()); |
| 337 const PrefHashStoreImpl::StoreVersion current_version = | 440 const PrefHashStoreImpl::StoreVersion current_version = |
| 338 pref_hash_store_impl->GetCurrentVersion(); | 441 pref_hash_store_impl->GetCurrentVersion(); |
| 339 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferencesAlternateStoreVersion", | 442 UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferencesAlternateStoreVersion", |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 372 // complete before Chrome can start (as master preferences seed the Local | 475 // complete before Chrome can start (as master preferences seed the Local |
| 373 // State and Preferences files). This won't trip ThreadIORestrictions as they | 476 // State and Preferences files). This won't trip ThreadIORestrictions as they |
| 374 // won't have kicked in yet on the main thread. | 477 // won't have kicked in yet on the main thread. |
| 375 bool success = serializer.Serialize(master_prefs); | 478 bool success = serializer.Serialize(master_prefs); |
| 376 | 479 |
| 377 if (success && kPlatformSupportsPreferenceTracking) { | 480 if (success && kPlatformSupportsPreferenceTracking) { |
| 378 scoped_refptr<const PrefStore> pref_store( | 481 scoped_refptr<const PrefStore> pref_store( |
| 379 new DictionaryPrefStore(&master_prefs)); | 482 new DictionaryPrefStore(&master_prefs)); |
| 380 PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(), | 483 PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(), |
| 381 tracking_configuration_, | 484 tracking_configuration_, |
| 485 scoped_ptr<TrackedPreferenceValidationObserver>(), |
| 382 reporting_ids_count_).Initialize(*pref_store); | 486 reporting_ids_count_).Initialize(*pref_store); |
| 383 } | 487 } |
| 384 | 488 |
| 385 UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success); | 489 UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success); |
| 386 return success; | 490 return success; |
| 387 } | 491 } |
| 388 | 492 |
| 389 PersistentPrefStore* | 493 PersistentPrefStore* |
| 390 ProfilePrefStoreManager::CreateDeprecatedCombinedProfilePrefStore( | 494 ProfilePrefStoreManager::CreateDeprecatedCombinedProfilePrefStore( |
| 391 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) { | 495 const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) { |
| 392 scoped_ptr<PrefFilter> pref_filter; | 496 scoped_ptr<PrefFilter> pref_filter; |
| 393 if (kPlatformSupportsPreferenceTracking) { | 497 if (kPlatformSupportsPreferenceTracking) { |
| 394 pref_filter.reset( | 498 pref_filter.reset( |
| 395 new PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(), | 499 new PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(), |
| 396 tracking_configuration_, | 500 tracking_configuration_, |
| 501 scoped_ptr<TrackedPreferenceValidationObserver>(), |
| 397 reporting_ids_count_)); | 502 reporting_ids_count_)); |
| 398 } | 503 } |
| 399 return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_), | 504 return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_), |
| 400 io_task_runner, | 505 io_task_runner, |
| 401 pref_filter.Pass()); | 506 pref_filter.Pass()); |
| 402 } | 507 } |
| 403 | 508 |
| 404 scoped_ptr<PrefHashStoreImpl> ProfilePrefStoreManager::GetPrefHashStoreImpl() { | 509 scoped_ptr<PrefHashStoreImpl> ProfilePrefStoreManager::GetPrefHashStoreImpl() { |
| 405 DCHECK(kPlatformSupportsPreferenceTracking); | 510 DCHECK(kPlatformSupportsPreferenceTracking); |
| 406 | 511 |
| 407 return make_scoped_ptr(new PrefHashStoreImpl( | 512 return make_scoped_ptr(new PrefHashStoreImpl( |
| 408 seed_, | 513 seed_, |
| 409 device_id_, | 514 device_id_, |
| 410 scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents( | 515 scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents( |
| 411 profile_path_.AsUTF8Unsafe(), local_state_)))); | 516 profile_path_.AsUTF8Unsafe(), local_state_)))); |
| 412 } | 517 } |
| 413 | 518 |
| 414 scoped_ptr<PrefHashStore> ProfilePrefStoreManager::CopyPrefHashStore() { | 519 scoped_ptr<PrefHashStore> ProfilePrefStoreManager::CopyPrefHashStore() { |
| 415 DCHECK(kPlatformSupportsPreferenceTracking); | 520 DCHECK(kPlatformSupportsPreferenceTracking); |
| 416 | 521 |
| 417 PrefServiceHashStoreContents real_contents(profile_path_.AsUTF8Unsafe(), | 522 PrefServiceHashStoreContents real_contents(profile_path_.AsUTF8Unsafe(), |
| 418 local_state_); | 523 local_state_); |
| 419 return scoped_ptr<PrefHashStore>(new PrefHashStoreImpl( | 524 return scoped_ptr<PrefHashStore>(new PrefHashStoreImpl( |
| 420 seed_, | 525 seed_, |
| 421 device_id_, | 526 device_id_, |
| 422 scoped_ptr<HashStoreContents>( | 527 scoped_ptr<HashStoreContents>( |
| 423 new DictionaryHashStoreContents(real_contents)))); | 528 new DictionaryHashStoreContents(real_contents)))); |
| 424 } | 529 } |
| OLD | NEW |