summaryrefslogtreecommitdiff
path: root/chromium/chrome/browser/prefs
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-02-13 10:55:42 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-03-05 13:33:38 +0000
commit248b70b82a40964d5594eb04feca0fa36716185d (patch)
tree44e31d9dd0ac2cb79f48633eefbc5496e013c347 /chromium/chrome/browser/prefs
parentcabfcdd1db482729ded525feae56911a99792773 (diff)
downloadqtwebengine-chromium-248b70b82a40964d5594eb04feca0fa36716185d.tar.gz
BASELINE: Update Chromium to 79.0.3945.147
And new simplified snapshot filter Change-Id: I7c692bedd5b3833f05565bd6f6939115350b233a Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser/prefs')
-rw-r--r--chromium/chrome/browser/prefs/DEPS9
-rw-r--r--chromium/chrome/browser/prefs/OWNERS7
-rw-r--r--chromium/chrome/browser/prefs/browser_prefs.cc1223
-rw-r--r--chromium/chrome/browser/prefs/browser_prefs.h53
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc177
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store.h53
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc198
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc71
-rw-r--r--chromium/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc222
-rw-r--r--chromium/chrome/browser/prefs/chrome_pref_model_associator_client.cc57
-rw-r--r--chromium/chrome/browser/prefs/chrome_pref_model_associator_client.h42
-rw-r--r--chromium/chrome/browser/prefs/chrome_pref_service_factory.cc540
-rw-r--r--chromium/chrome/browser/prefs/chrome_pref_service_factory.h130
-rw-r--r--chromium/chrome/browser/prefs/chrome_pref_service_unittest.cc109
-rw-r--r--chromium/chrome/browser/prefs/in_process_service_factory_factory.cc41
-rw-r--r--chromium/chrome/browser/prefs/in_process_service_factory_factory.h43
-rw-r--r--chromium/chrome/browser/prefs/incognito_mode_prefs.cc236
-rw-r--r--chromium/chrome/browser/prefs/incognito_mode_prefs.h98
-rw-r--r--chromium/chrome/browser/prefs/incognito_mode_prefs_unittest.cc69
-rw-r--r--chromium/chrome/browser/prefs/origin_trial_prefs.cc15
-rw-r--r--chromium/chrome/browser/prefs/origin_trial_prefs.h15
-rw-r--r--chromium/chrome/browser/prefs/pref_functional_browsertest.cc246
-rw-r--r--chromium/chrome/browser/prefs/pref_metrics_service.cc189
-rw-r--r--chromium/chrome/browser/prefs/pref_metrics_service.h60
-rw-r--r--chromium/chrome/browser/prefs/pref_service_browsertest.cc135
-rw-r--r--chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc229
-rw-r--r--chromium/chrome/browser/prefs/pref_service_incognito_whitelist.h19
-rw-r--r--chromium/chrome/browser/prefs/pref_service_syncable_util.cc29
-rw-r--r--chromium/chrome/browser/prefs/pref_service_syncable_util.h41
-rw-r--r--chromium/chrome/browser/prefs/profile_pref_store_manager.cc161
-rw-r--r--chromium/chrome/browser/prefs/profile_pref_store_manager.h132
-rw-r--r--chromium/chrome/browser/prefs/profile_pref_store_manager_unittest.cc562
-rw-r--r--chromium/chrome/browser/prefs/proxy_policy_unittest.cc254
-rw-r--r--chromium/chrome/browser/prefs/session_startup_pref.cc175
-rw-r--r--chromium/chrome/browser/prefs/session_startup_pref.h85
-rw-r--r--chromium/chrome/browser/prefs/session_startup_pref_unittest.cc66
-rw-r--r--chromium/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc205
-rw-r--r--chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc1284
38 files changed, 7280 insertions, 0 deletions
diff --git a/chromium/chrome/browser/prefs/DEPS b/chromium/chrome/browser/prefs/DEPS
new file mode 100644
index 00000000000..d5dd4a0bf76
--- /dev/null
+++ b/chromium/chrome/browser/prefs/DEPS
@@ -0,0 +1,9 @@
+include_rules = [
+ "+services/preferences/public/mojom",
+]
+# TODO(crbug.com/654988): Remove once the pref service is always used.
+specific_include_rules = {
+ "profile_pref_store_manager\.cc": [
+ "+services/preferences/tracked",
+ ],
+}
diff --git a/chromium/chrome/browser/prefs/OWNERS b/chromium/chrome/browser/prefs/OWNERS
new file mode 100644
index 00000000000..538512cd888
--- /dev/null
+++ b/chromium/chrome/browser/prefs/OWNERS
@@ -0,0 +1,7 @@
+battre@chromium.org
+gab@chromium.org
+
+per-file pref_service_incognito_whitelist.cc=rhalavati@chromium.org
+
+# COMPONENT: UI>Browser>Preferences
+# TEAM: chromium-dev@chromium.org
diff --git a/chromium/chrome/browser/prefs/browser_prefs.cc b/chromium/chrome/browser/prefs/browser_prefs.cc
new file mode 100644
index 00000000000..a960db92420
--- /dev/null
+++ b/chromium/chrome/browser/prefs/browser_prefs.cc
@@ -0,0 +1,1223 @@
+// Copyright 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/browser_prefs.h"
+
+#include <string>
+
+#include "base/trace_event/trace_event.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
+#include "chrome/browser/about_flags.h"
+#include "chrome/browser/accessibility/accessibility_labels_service.h"
+#include "chrome/browser/accessibility/accessibility_ui.h"
+#include "chrome/browser/accessibility/invert_bubble_prefs.h"
+#include "chrome/browser/availability/availability_prober.h"
+#include "chrome/browser/browser_process_impl.h"
+#include "chrome/browser/chrome_content_browser_client.h"
+#include "chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h"
+#include "chrome/browser/chromeos/scheduler_configuration_manager.h"
+#include "chrome/browser/component_updater/component_updater_prefs.h"
+#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
+#include "chrome/browser/devtools/devtools_window.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/engagement/important_sites_util.h"
+#include "chrome/browser/external_protocol/external_protocol_handler.h"
+#include "chrome/browser/first_run/first_run.h"
+#include "chrome/browser/gpu/gpu_mode_manager.h"
+#include "chrome/browser/intranet_redirect_detector.h"
+#include "chrome/browser/lifetime/browser_shutdown.h"
+#include "chrome/browser/media/media_device_id_salt.h"
+#include "chrome/browser/media/media_engagement_service.h"
+#include "chrome/browser/media/media_storage_id_salt.h"
+#include "chrome/browser/media/router/media_router_feature.h"
+#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
+#include "chrome/browser/media/webrtc/media_stream_devices_controller.h"
+#include "chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.h"
+#include "chrome/browser/memory/enterprise_memory_limit_pref_observer.h"
+#include "chrome/browser/metrics/chrome_metrics_service_client.h"
+#include "chrome/browser/net/net_error_tab_helper.h"
+#include "chrome/browser/net/prediction_options.h"
+#include "chrome/browser/net/profile_network_context_service.h"
+#include "chrome/browser/net/system_network_context_manager.h"
+#include "chrome/browser/notifications/notification_channels_provider_android.h"
+#include "chrome/browser/notifications/notifier_state_tracker.h"
+#include "chrome/browser/notifications/platform_notification_service_impl.h"
+#include "chrome/browser/pepper_flash_settings_manager.h"
+#include "chrome/browser/policy/developer_tools_policy_handler.h"
+#include "chrome/browser/policy/webusb_allow_devices_for_urls_policy_handler.h"
+#include "chrome/browser/prefs/chrome_pref_service_factory.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
+#include "chrome/browser/prefs/origin_trial_prefs.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/previews/previews_lite_page_redirect_decider.h"
+#include "chrome/browser/previews/previews_offline_helper.h"
+#include "chrome/browser/profiles/chrome_version_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_attributes_entry.h"
+#include "chrome/browser/profiles/profile_impl.h"
+#include "chrome/browser/profiles/profile_info_cache.h"
+#include "chrome/browser/profiles/profiles_state.h"
+#include "chrome/browser/push_messaging/push_messaging_app_identifier.h"
+#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h"
+#include "chrome/browser/rlz/chrome_rlz_tracker_delegate.h"
+#include "chrome/browser/search/search.h"
+#include "chrome/browser/sharing/sharing_sync_preference.h"
+#include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
+#include "chrome/browser/ssl/ssl_config_service_manager.h"
+#include "chrome/browser/task_manager/task_manager_interface.h"
+#include "chrome/browser/tracing/chrome_tracing_delegate.h"
+#include "chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker.h"
+#include "chrome/browser/ui/browser_ui_prefs.h"
+#include "chrome/browser/ui/hats/hats_service.h"
+#include "chrome/browser/ui/navigation_correction_tab_observer.h"
+#include "chrome/browser/ui/network_profile_bubble.h"
+#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
+#include "chrome/browser/ui/search_engines/keyword_editor_controller.h"
+#include "chrome/browser/ui/tabs/pinned_tab_codec.h"
+#include "chrome/browser/ui/webui/flags_ui.h"
+#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
+#include "chrome/browser/ui/webui/print_preview/policy_settings.h"
+#include "chrome/browser/ui/webui/print_preview/sticky_settings.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/webauthn/chrome_authenticator_request_delegate.h"
+#include "chrome/common/buildflags.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/secure_origin_whitelist.h"
+#include "components/autofill/core/common/autofill_prefs.h"
+#include "components/browsing_data/core/pref_names.h"
+#include "components/certificate_transparency/pref_names.h"
+#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_prefs.h"
+#include "components/dom_distiller/core/distilled_page_prefs.h"
+#include "components/feature_engagement/buildflags.h"
+#include "components/flags_ui/pref_service_flags_storage.h"
+#include "components/gcm_driver/gcm_channel_status_syncer.h"
+#include "components/image_fetcher/core/cache/image_cache.h"
+#include "components/invalidation/impl/invalidator_registrar_with_memory.h"
+#include "components/invalidation/impl/per_user_topic_registration_manager.h"
+#include "components/language/content/browser/geo_language_provider.h"
+#include "components/language/content/browser/ulp_language_code_locator/ulp_language_code_locator.h"
+#include "components/language/core/browser/language_prefs.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/network_time/network_time_tracker.h"
+#include "components/ntp_snippets/content_suggestions_service.h"
+#include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h"
+#include "components/ntp_snippets/remote/remote_suggestions_scheduler_impl.h"
+#include "components/ntp_snippets/remote/request_throttler.h"
+#include "components/ntp_snippets/user_classifier.h"
+#include "components/ntp_tiles/most_visited_sites.h"
+#include "components/offline_pages/buildflags/buildflags.h"
+#include "components/omnibox/browser/document_provider.h"
+#include "components/omnibox/browser/zero_suggest_provider.h"
+#include "components/optimization_guide/optimization_guide_prefs.h"
+#include "components/password_manager/core/browser/password_bubble_experiment.h"
+#include "components/password_manager/core/browser/password_manager.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/payments/core/payment_prefs.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/browser/url_blacklist_manager.h"
+#include "components/policy/core/common/policy_statistics_collector.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
+#include "components/rappor/rappor_service_impl.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/search_engines/template_url_prepopulate_data.h"
+#include "components/sessions/core/session_id_generator.h"
+#include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/subresource_filter/content/browser/ruleset_service.h"
+#include "components/sync/base/sync_prefs.h"
+#include "components/sync_device_info/device_info_prefs.h"
+#include "components/sync_preferences/pref_service_syncable.h"
+#include "components/sync_sessions/session_sync_prefs.h"
+#include "components/translate/core/browser/translate_prefs.h"
+#include "components/update_client/update_client.h"
+#include "components/variations/service/variations_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "extensions/buildflags/buildflags.h"
+#include "net/http/http_server_properties_manager.h"
+#include "ppapi/buildflags/buildflags.h"
+#include "printing/buildflags/buildflags.h"
+#include "rlz/buildflags/buildflags.h"
+
+#if BUILDFLAG(ENABLE_APP_LIST)
+#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
+#endif
+
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+#include "chrome/browser/background/background_mode_manager.h"
+#endif
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "chrome/browser/accessibility/animation_policy_prefs.h"
+#include "chrome/browser/apps/platform_apps/shortcut_manager.h"
+#include "chrome/browser/extensions/activity_log/activity_log.h"
+#include "chrome/browser/extensions/api/commands/command_service.h"
+#include "chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.h"
+#include "chrome/browser/extensions/api/tabs/tabs_api.h"
+#include "chrome/browser/extensions/extension_web_ui.h"
+#include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h"
+#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
+#include "chrome/browser/ui/webui/extensions/extensions_ui.h"
+#include "extensions/browser/api/audio/audio_api.h"
+#include "extensions/browser/api/runtime/runtime_api.h"
+#include "extensions/browser/extension_prefs.h"
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/guest_os/guest_os_share_path.h"
+#include "chrome/browser/chromeos/kerberos/kerberos_credentials_manager.h"
+#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.h"
+#include "chrome/browser/chromeos/settings/stats_reporting_controller.h"
+#include "chrome/browser/component_updater/metadata_table_chromeos.h"
+#else
+#include "chrome/browser/extensions/api/enterprise_reporting_private/prefs.h"
+#endif
+#endif // BUILDFLAG(ENABLE_EXTENSIONS)
+
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+#include "chrome/browser/offline_pages/prefetch/offline_metrics_collector_impl.h"
+#include "chrome/browser/offline_pages/prefetch/prefetch_background_task_handler_impl.h"
+#include "components/offline_pages/core/prefetch/prefetch_prefs.h"
+#endif
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+#include "chrome/browser/plugins/plugin_info_host_impl.h"
+#include "chrome/browser/plugins/plugins_resource_service.h"
+#endif
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/browser/supervised_user/child_accounts/child_account_service.h"
+#include "chrome/browser/supervised_user/supervised_user_service.h"
+#include "chrome/browser/supervised_user/supervised_user_whitelist_service.h"
+#endif
+
+#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
+#include "chrome/browser/ui/webui/local_discovery/local_discovery_ui.h"
+#endif
+
+#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
+#include "chrome/browser/feature_engagement/session_duration_updater.h"
+#endif
+
+#if defined(OS_ANDROID)
+#include "chrome/browser/android/bookmarks/partner_bookmarks_shim.h"
+#include "chrome/browser/android/explore_sites/history_statistics_reporter.h"
+#include "chrome/browser/android/ntp/recent_tabs_page_prefs.h"
+#include "chrome/browser/android/oom_intervention/oom_intervention_decider.h"
+#include "chrome/browser/android/preferences/browser_prefs_android.h"
+#include "chrome/browser/android/usage_stats/usage_stats_bridge.h"
+#include "chrome/browser/geolocation/geolocation_permission_context_android.h"
+#include "chrome/browser/media/android/cdm/media_drm_origin_id_manager.h"
+#include "components/cdm/browser/media_drm_storage_impl.h"
+#include "components/feed/buildflags.h"
+#include "components/ntp_snippets/category_rankers/click_based_category_ranker.h"
+#include "components/ntp_tiles/popular_sites_impl.h"
+#if BUILDFLAG(ENABLE_FEED_IN_CHROME)
+#include "components/feed/core/feed_scheduler_host.h"
+#include "components/feed/core/refresh_throttler.h"
+#include "components/feed/core/user_classifier.h"
+#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME)
+#else // defined(OS_ANDROID)
+#include "chrome/browser/enterprise_reporting/prefs.h"
+#include "chrome/browser/gcm/gcm_product_util.h"
+#include "chrome/browser/metrics/tab_stats_tracker.h"
+#include "chrome/browser/search/instant_service.h"
+#include "chrome/browser/search/promos/promo_service.h"
+#include "chrome/browser/search/search_suggest/search_suggest_service.h"
+#include "chrome/browser/signin/signin_promo.h"
+#include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/browser/ui/webui/foreign_session_handler.h"
+#include "chrome/browser/ui/webui/history_ui.h"
+#include "chrome/browser/ui/webui/settings/settings_ui.h"
+#include "chrome/browser/upgrade_detector/upgrade_detector.h"
+#endif // defined(OS_ANDROID)
+
+#if defined(OS_CHROMEOS)
+#include "ash/public/cpp/ash_pref_names.h"
+#include "ash/public/cpp/ash_prefs.h"
+#include "chrome/browser/chromeos/app_mode/arc/arc_kiosk_app_manager.h"
+#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
+#include "chrome/browser/chromeos/app_mode/kiosk_cryptohome_remover.h"
+#include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
+#include "chrome/browser/chromeos/arc/session/arc_session_manager.h"
+#include "chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service.h"
+#include "chrome/browser/chromeos/child_accounts/screen_time_controller.h"
+#include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
+#include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
+#include "chrome/browser/chromeos/cryptauth/cryptauth_device_id_provider_impl.h"
+#include "chrome/browser/chromeos/customization/customization_document.h"
+#include "chrome/browser/chromeos/extensions/echo_private_api.h"
+#include "chrome/browser/chromeos/extensions/login_screen/login/login_api.h"
+#include "chrome/browser/chromeos/file_system_provider/registry.h"
+#include "chrome/browser/chromeos/first_run/first_run.h"
+#include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h"
+#include "chrome/browser/chromeos/lock_screen_apps/state_controller.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_session.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h"
+#include "chrome/browser/chromeos/login/quick_unlock/fingerprint_storage.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_prefs.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+#include "chrome/browser/chromeos/login/saml/saml_profile_prefs.h"
+#include "chrome/browser/chromeos/login/screens/reset_screen.h"
+#include "chrome/browser/chromeos/login/session/user_session_manager.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h"
+#include "chrome/browser/chromeos/login/users/avatar/user_image_sync_observer.h"
+#include "chrome/browser/chromeos/login/users/chrome_user_manager_impl.h"
+#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
+#include "chrome/browser/chromeos/net/network_throttling_observer.h"
+#include "chrome/browser/chromeos/platform_keys/key_permissions.h"
+#include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h"
+#include "chrome/browser/chromeos/policy/app_install_event_log_manager_wrapper.h"
+#include "chrome/browser/chromeos/policy/app_install_event_logger.h"
+#include "chrome/browser/chromeos/policy/auto_enrollment_client_impl.h"
+#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
+#include "chrome/browser/chromeos/policy/dm_token_storage.h"
+#include "chrome/browser/chromeos/policy/external_data_handlers/device_wallpaper_image_external_data_handler.h"
+#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
+#include "chrome/browser/chromeos/policy/status_collector/device_status_collector.h"
+#include "chrome/browser/chromeos/policy/status_collector/status_collector.h"
+#include "chrome/browser/chromeos/power/auto_screen_brightness/metrics_reporter.h"
+#include "chrome/browser/chromeos/power/power_metrics_reporter.h"
+#include "chrome/browser/chromeos/preferences.h"
+#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
+#include "chrome/browser/chromeos/printing/history/print_job_history_service.h"
+#include "chrome/browser/chromeos/printing/synced_printers_manager.h"
+#include "chrome/browser/chromeos/release_notes/release_notes_storage.h"
+#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h"
+#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
+#include "chrome/browser/chromeos/settings/device_settings_cache.h"
+#include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
+#include "chrome/browser/chromeos/system/input_device_settings.h"
+#include "chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h"
+#include "chrome/browser/extensions/extension_assets_manager_chromeos.h"
+#include "chrome/browser/media/protected_media_identifier_permission_context.h"
+#include "chrome/browser/metrics/chromeos_metrics_provider.h"
+#include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
+#include "chrome/browser/ui/webui/certificates_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h"
+#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
+#include "chrome/browser/upgrade_detector/upgrade_detector_chromeos.h"
+#include "chromeos/audio/audio_devices_pref_handler_impl.h"
+#include "chromeos/components/account_manager/account_manager.h"
+#include "chromeos/constants/chromeos_switches.h"
+#include "chromeos/network/fast_transition_observer.h"
+#include "chromeos/network/proxy/proxy_config_handler.h"
+#include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
+#include "chromeos/services/multidevice_setup/multidevice_setup_service.h"
+#include "chromeos/timezone/timezone_resolver.h"
+#include "components/arc/arc_prefs.h"
+#include "components/invalidation/impl/fcm_invalidation_service.h"
+#include "components/invalidation/impl/invalidator_storage.h"
+#include "components/onc/onc_pref_names.h"
+#include "components/quirks/quirks_manager.h"
+#include "extensions/browser/api/lock_screen_data/lock_screen_item_storage.h"
+#else
+#include "chrome/browser/extensions/default_apps.h"
+#endif
+
+#if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_APP_LIST)
+#include "chrome/browser/chromeos/apps/apk_web_app_service.h"
+#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
+#include "chrome/browser/ui/app_list/search/arc/arc_app_reinstall_search_provider.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.h"
+#include "chrome/browser/ui/cocoa/confirm_quit.h"
+#include "components/os_crypt/os_crypt.h"
+#endif
+
+#if defined(OS_WIN)
+#include "chrome/browser/component_updater/sw_reporter_installer_win.h"
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#include "chrome/browser/win/conflicts/incompatible_applications_updater.h"
+#include "chrome/browser/win/conflicts/module_database.h"
+#include "chrome/browser/win/conflicts/third_party_conflicts_manager.h"
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
+#include "chrome/browser/safe_browsing/chrome_cleaner/settings_resetter_win.h"
+#include "chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_prefs_manager.h"
+#endif
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+ (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+#include "chrome/browser/browser_switcher/browser_switcher_prefs.h"
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+#include "chrome/browser/ui/startup/default_browser_prompt.h"
+#endif
+
+#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/ui/browser_view_prefs.h"
+#endif
+
+#if !defined(OS_ANDROID)
+#include "chrome/browser/media/unified_autoplay_config.h"
+#include "components/ntp_tiles/custom_links_manager_impl.h"
+#endif
+
+namespace {
+
+// Deprecated 8/2018.
+const char kDnsPrefetchingStartupList[] = "dns_prefetching.startup_list";
+const char kDnsPrefetchingHostReferralList[] =
+ "dns_prefetching.host_referral_list";
+
+// Deprecated 9/2018
+const char kGeolocationAccessToken[] = "geolocation.access_token";
+const char kGoogleServicesPasswordHash[] = "google.services.password_hash";
+const char kModuleConflictBubbleShown[] = "module_conflict.bubble_shown";
+const char kOptionsWindowLastTabIndex[] = "options_window.last_tab_index";
+const char kTrustedDownloadSources[] = "trusted_download_sources";
+#if defined(OS_WIN)
+const char kLastWelcomedOSVersion[] = "browser.last_welcomed_os_version";
+#endif
+const char kSupervisedUserCreationAllowed[] =
+ "profile.managed_user_creation_allowed";
+
+// Deprecated 10/2018
+const char kReverseAutologinEnabled[] = "reverse_autologin.enabled";
+
+// Deprecated 11/2018.
+const char kNetworkQualities[] = "net.network_qualities";
+const char kForceSessionSync[] = "settings.history_recorded";
+const char kOnboardDuringNUX[] = "browser.onboard_during_nux";
+const char kNuxOnboardGroup[] = "browser.onboard_group";
+// This pref is particularly large, taking up 15+% of the prefs file, so should
+// perhaps be kept around longer than the others.
+const char kHttpServerProperties[] = "net.http_server_properties";
+
+// Deprecated 1/2019.
+const char kNextUpdateCheck[] = "extensions.autoupdate.next_check";
+const char kLastUpdateCheck[] = "extensions.autoupdate.last_check";
+
+// Deprecated 3/2019.
+const char kCurrentThemeImages[] = "extensions.theme.images";
+const char kCurrentThemeColors[] = "extensions.theme.colors";
+const char kCurrentThemeTints[] = "extensions.theme.tints";
+const char kCurrentThemeDisplayProperties[] = "extensions.theme.properties";
+
+#if defined(OS_ANDROID)
+// Deprecated 4/2019.
+const char kDismissedAssetDownloadSuggestions[] =
+ "ntp_suggestions.downloads.assets.dismissed_ids";
+const char kDismissedOfflinePageDownloadSuggestions[] =
+ "ntp_suggestions.downloads.offline_pages.dismissed_ids";
+
+// Deprecated 4/2019.
+const char kBreakingNewsSubscriptionDataToken[] =
+ "ntp_suggestions.breaking_news_subscription_data.token";
+const char kBreakingNewsSubscriptionDataIsAuthenticated[] =
+ "ntp_suggestions.breaking_news_subscription_data.is_authenticated";
+const char kBreakingNewsGCMSubscriptionTokenCache[] =
+ "ntp_suggestions.breaking_news_gcm_subscription_token_cache";
+const char kBreakingNewsGCMLastTokenValidationTime[] =
+ "ntp_suggestions.breaking_news_gcm_last_token_validation_time";
+const char kBreakingNewsGCMLastForcedSubscriptionTime[] =
+ "ntp_suggestions.breaking_news_gcm_last_forced_subscription_time";
+
+// Deprecated 4/2019.
+const char kContentSuggestionsConsecutiveIgnoredPrefName[] =
+ "ntp.content_suggestions.notifications.consecutive_ignored";
+const char kContentSuggestionsNotificationsSentDay[] =
+ "ntp.content_suggestions.notifications.sent_day";
+const char kContentSuggestionsNotificationsSentCount[] =
+ "ntp.content_suggestions.notifications.sent_count";
+const char kNotificationIDWithinCategory[] =
+ "ContentSuggestionsNotificationIDWithinCategory";
+
+// Deprecated 5/2019.
+const char kContentSuggestionsNotificationsEnabled[] =
+ "ntp.content_suggestions.notifications.enabled";
+
+#endif // defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+// Deprecated 5/2019
+const char kSignInPromoShowOnFirstRunAllowed[] =
+ "sync_promo.show_on_first_run_allowed";
+const char kSignInPromoShowNTPBubble[] = "sync_promo.show_ntp_bubble";
+#endif // !defined(OS_ANDROID)
+
+// Deprecated 5/2019
+const char kBookmarkAppCreationLaunchType[] =
+ "extensions.bookmark_app_creation_launch_type";
+
+// Deprecated 6/2019
+const char kMediaCacheSize[] = "browser.media_cache_size";
+
+#if defined(OS_WIN)
+// Deprecated 6/2019
+const char kHasSeenWin10PromoPage[] = "browser.has_seen_win10_promo_page";
+#endif // defined(OS_WIN)
+
+// Deprecated 7/2019
+const char kSignedInTime[] = "signin.signedin_time";
+
+#if !defined(OS_ANDROID)
+// Deprecated 7/2019
+const char kNtpActivateHideShortcutsFieldTrial[] =
+ "ntp.activate_hide_shortcuts_field_trial";
+#endif // !defined(OS_ANDROID)
+
+#if defined(OS_ANDROID)
+// Deprecated 7/2019
+// WebAuthn prefs were being erroneously stored on Android. They are registered
+// on other platforms.
+const char kWebAuthnLastTransportUsedPrefName[] =
+ "webauthn.last_transport_used";
+const char kWebAuthnBlePairedMacAddressesPrefName[] =
+ "webauthn.ble.paired_mac_addresses";
+#endif // defined(OS_ANDROID)
+
+// Deprecated 7/2019
+const char kLastKnownGoogleURL[] = "browser.last_known_google_url";
+const char kLastPromptedGoogleURL[] = "browser.last_prompted_google_url";
+#if defined(USE_X11)
+constexpr char kLocalProfileId[] = "profile.local_profile_id";
+#endif
+
+// Deprecated 8/2019
+const char kInsecureExtensionUpdatesEnabled[] =
+ "extension_updates.insecure_extension_updates_enabled";
+
+const char kLastStartupTimestamp[] = "startup_metric.last_startup_timestamp";
+const char kLastStartupVersion[] = "startup_metric.last_startup_version";
+const char kSameVersionStartupCount[] =
+ "startup_metric.same_version_startup_count";
+
+// Deprecated 8/2019
+const char kHintLoadedCounts[] = "optimization_guide.hint_loaded_counts";
+
+// Deprecated 9/2019
+const char kGoogleServicesUsername[] = "google.services.username";
+const char kGoogleServicesUserAccountId[] = "google.services.user_account_id";
+const char kDataReductionProxySavingsClearedNegativeSystemClock[] =
+ "data_reduction.savings_cleared_negative_system_clock";
+
+#if defined(OS_CHROMEOS)
+// Deprecated 10/2019
+const char kDisplayRotationAcceleratorDialogHasBeenAccepted[] =
+ "settings.a11y.display_rotation_accelerator_dialog_has_been_accepted";
+#endif // defined(OS_CHROMEOS)
+
+// Register prefs used only for migration (clearing or moving to a new key).
+void RegisterProfilePrefsForMigration(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterListPref(kDnsPrefetchingStartupList);
+ registry->RegisterListPref(kDnsPrefetchingHostReferralList);
+
+ registry->RegisterStringPref(kGeolocationAccessToken, std::string());
+ registry->RegisterStringPref(kGoogleServicesPasswordHash, std::string());
+ registry->RegisterIntegerPref(kModuleConflictBubbleShown, 0);
+ registry->RegisterIntegerPref(kOptionsWindowLastTabIndex, 0);
+ registry->RegisterStringPref(kTrustedDownloadSources, std::string());
+ registry->RegisterBooleanPref(kSupervisedUserCreationAllowed, true);
+
+ registry->RegisterBooleanPref(kReverseAutologinEnabled, true);
+
+ registry->RegisterDictionaryPref(kNetworkQualities, PrefRegistry::LOSSY_PREF);
+ registry->RegisterBooleanPref(kForceSessionSync, false);
+ registry->RegisterBooleanPref(kOnboardDuringNUX, false);
+ registry->RegisterIntegerPref(kNuxOnboardGroup, 0);
+ registry->RegisterDictionaryPref(kHttpServerProperties,
+ PrefRegistry::LOSSY_PREF);
+ registry->RegisterIntegerPref(kLastUpdateCheck, 0);
+ registry->RegisterIntegerPref(kNextUpdateCheck, 0);
+
+ registry->RegisterDictionaryPref(kCurrentThemeImages);
+ registry->RegisterDictionaryPref(kCurrentThemeColors);
+ registry->RegisterDictionaryPref(kCurrentThemeTints);
+ registry->RegisterDictionaryPref(kCurrentThemeDisplayProperties);
+
+#if defined(OS_ANDROID)
+ registry->RegisterListPref(kDismissedAssetDownloadSuggestions);
+ registry->RegisterListPref(kDismissedOfflinePageDownloadSuggestions);
+
+ registry->RegisterStringPref(kBreakingNewsSubscriptionDataToken,
+ std::string());
+ registry->RegisterBooleanPref(kBreakingNewsSubscriptionDataIsAuthenticated,
+ false);
+ registry->RegisterStringPref(kBreakingNewsGCMSubscriptionTokenCache,
+ std::string());
+ registry->RegisterInt64Pref(kBreakingNewsGCMLastTokenValidationTime, 0);
+ registry->RegisterInt64Pref(kBreakingNewsGCMLastForcedSubscriptionTime, 0);
+
+ registry->RegisterIntegerPref(kContentSuggestionsConsecutiveIgnoredPrefName,
+ 0);
+ registry->RegisterIntegerPref(kContentSuggestionsNotificationsSentDay, 0);
+ registry->RegisterIntegerPref(kContentSuggestionsNotificationsSentCount, 0);
+ registry->RegisterStringPref(kNotificationIDWithinCategory, std::string());
+ registry->RegisterBooleanPref(kContentSuggestionsNotificationsEnabled, true);
+#endif // defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+ registry->RegisterBooleanPref(kSignInPromoShowOnFirstRunAllowed, true);
+ registry->RegisterBooleanPref(kSignInPromoShowNTPBubble, false);
+#endif // !defined(OS_ANDROID)
+
+ registry->RegisterIntegerPref(kBookmarkAppCreationLaunchType, 0);
+
+ registry->RegisterIntegerPref(kMediaCacheSize, 0);
+
+ registry->RegisterInt64Pref(kSignedInTime, 0);
+
+#if defined(OS_ANDROID)
+ registry->RegisterStringPref(kWebAuthnLastTransportUsedPrefName,
+ std::string());
+ registry->RegisterListPref(kWebAuthnBlePairedMacAddressesPrefName);
+#endif // defined(OS_ANDROID)
+
+ registry->RegisterStringPref(kLastKnownGoogleURL, std::string());
+ registry->RegisterStringPref(kLastPromptedGoogleURL, std::string());
+#if defined(USE_X11)
+ registry->RegisterIntegerPref(kLocalProfileId, 0);
+#endif
+
+ registry->RegisterBooleanPref(kInsecureExtensionUpdatesEnabled, false);
+
+ registry->RegisterDictionaryPref(kHintLoadedCounts);
+ registry->RegisterStringPref(kGoogleServicesUsername, std::string());
+ registry->RegisterStringPref(kGoogleServicesUserAccountId, std::string());
+ registry->RegisterInt64Pref(
+ kDataReductionProxySavingsClearedNegativeSystemClock, 0);
+
+#if defined(OS_CHROMEOS)
+ registry->RegisterBooleanPref(
+ kDisplayRotationAcceleratorDialogHasBeenAccepted, false);
+#endif // defined(OS_CHROMEOS)
+}
+
+} // namespace
+
+void RegisterLocalState(PrefRegistrySimple* registry) {
+ // Please keep this list alphabetized.
+ browser_shutdown::RegisterPrefs(registry);
+ data_reduction_proxy::RegisterPrefs(registry);
+ BrowserProcessImpl::RegisterPrefs(registry);
+ ChromeContentBrowserClient::RegisterLocalStatePrefs(registry);
+ ChromeMetricsServiceClient::RegisterPrefs(registry);
+ ChromeTracingDelegate::RegisterPrefs(registry);
+ component_updater::RegisterPrefs(registry);
+ ExternalProtocolHandler::RegisterPrefs(registry);
+ flags_ui::PrefServiceFlagsStorage::RegisterPrefs(registry);
+ GpuModeManager::RegisterPrefs(registry);
+ signin::IdentityManager::RegisterLocalStatePrefs(registry);
+ IntranetRedirectDetector::RegisterPrefs(registry);
+ language::GeoLanguageProvider::RegisterLocalStatePrefs(registry);
+ language::UlpLanguageCodeLocator::RegisterLocalStatePrefs(registry);
+ memory::EnterpriseMemoryLimitPrefObserver::RegisterPrefs(registry);
+ network_time::NetworkTimeTracker::RegisterPrefs(registry);
+ OriginTrialPrefs::RegisterPrefs(registry);
+ password_manager::PasswordManager::RegisterLocalPrefs(registry);
+ PrefProxyConfigTrackerImpl::RegisterPrefs(registry);
+ ProfileAttributesEntry::RegisterLocalStatePrefs(registry);
+ ProfileInfoCache::RegisterPrefs(registry);
+ ProfileNetworkContextService::RegisterLocalStatePrefs(registry);
+ profiles::RegisterPrefs(registry);
+ rappor::RapporServiceImpl::RegisterPrefs(registry);
+ RegisterScreenshotPrefs(registry);
+ safe_browsing::RegisterLocalStatePrefs(registry);
+ secure_origin_whitelist::RegisterPrefs(registry);
+ sessions::SessionIdGenerator::RegisterPrefs(registry);
+ SSLConfigServiceManager::RegisterPrefs(registry);
+ subresource_filter::IndexedRulesetVersion::RegisterPrefs(registry);
+ SystemNetworkContextManager::RegisterPrefs(registry);
+ update_client::RegisterPrefs(registry);
+ variations::VariationsService::RegisterPrefs(registry);
+
+ policy::BrowserPolicyConnector::RegisterPrefs(registry);
+ policy::PolicyStatisticsCollector::RegisterPrefs(registry);
+
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE)
+ BackgroundModeManager::RegisterPrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_EXTENSIONS) and defined(OS_CHROMEOS)
+ chromeos::EasyUnlockService::RegisterPrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ PluginsResourceService::RegisterPrefs(registry);
+#endif
+
+#if defined(OS_ANDROID)
+ ::android::RegisterPrefs(registry);
+#else
+ media_router::RegisterLocalStatePrefs(registry);
+ // The native GCM is used on Android instead.
+ gcm::GCMChannelStatusSyncer::RegisterPrefs(registry);
+ gcm::RegisterPrefs(registry);
+ metrics::TabStatsTracker::RegisterPrefs(registry);
+ RegisterBrowserPrefs(registry);
+ StartupBrowserCreator::RegisterLocalStatePrefs(registry);
+ task_manager::TaskManagerInterface::RegisterPrefs(registry);
+ UpgradeDetector::RegisterPrefs(registry);
+ enterprise_reporting::RegisterLocalStatePrefs(registry);
+#if !defined(OS_CHROMEOS)
+ RegisterDefaultBrowserPromptPrefs(registry);
+#endif // !defined(OS_CHROMEOS)
+#endif // !defined(OS_ANDROID)
+
+#if defined(OS_CHROMEOS)
+ arc::prefs::RegisterLocalStatePrefs(registry);
+ ChromeOSMetricsProvider::RegisterPrefs(registry);
+ chromeos::ArcKioskAppManager::RegisterPrefs(registry);
+ chromeos::AudioDevicesPrefHandlerImpl::RegisterPrefs(registry);
+ chromeos::ChromeUserManagerImpl::RegisterPrefs(registry);
+ chromeos::DemoModeDetector::RegisterPrefs(registry);
+ chromeos::DemoModeResourcesRemover::RegisterLocalStatePrefs(registry);
+ chromeos::DemoSession::RegisterLocalStatePrefs(registry);
+ chromeos::DemoSetupController::RegisterLocalStatePrefs(registry);
+ chromeos::DeviceOAuth2TokenService::RegisterPrefs(registry);
+ chromeos::device_settings_cache::RegisterPrefs(registry);
+ chromeos::echo_offer::RegisterPrefs(registry);
+ chromeos::EnableDebuggingScreenHandler::RegisterPrefs(registry);
+ chromeos::FastTransitionObserver::RegisterPrefs(registry);
+ chromeos::HIDDetectionScreenHandler::RegisterPrefs(registry);
+ chromeos::KerberosCredentialsManager::RegisterLocalStatePrefs(registry);
+ chromeos::KioskAppManager::RegisterPrefs(registry);
+ chromeos::KioskCryptohomeRemover::RegisterPrefs(registry);
+ chromeos::language_prefs::RegisterPrefs(registry);
+ chromeos::MultiProfileUserController::RegisterPrefs(registry);
+ chromeos::NetworkThrottlingObserver::RegisterPrefs(registry);
+ chromeos::PowerMetricsReporter::RegisterLocalStatePrefs(registry);
+ chromeos::power::auto_screen_brightness::MetricsReporter::
+ RegisterLocalStatePrefs(registry);
+ chromeos::Preferences::RegisterPrefs(registry);
+ chromeos::ResetScreen::RegisterPrefs(registry);
+ chromeos::ResourceReporter::RegisterPrefs(registry);
+ chromeos::SchedulerConfigurationManager::RegisterLocalStatePrefs(registry);
+ chromeos::ServicesCustomizationDocument::RegisterPrefs(registry);
+ chromeos::SigninScreenHandler::RegisterPrefs(registry);
+ chromeos::StartupUtils::RegisterPrefs(registry);
+ chromeos::StatsReportingController::RegisterLocalStatePrefs(registry);
+ chromeos::system::AutomaticRebootManager::RegisterPrefs(registry);
+ chromeos::TimeZoneResolver::RegisterPrefs(registry);
+ chromeos::UserImageManager::RegisterPrefs(registry);
+ chromeos::UserSessionManager::RegisterPrefs(registry);
+ component_updater::MetadataTable::RegisterPrefs(registry);
+ cryptauth::CryptAuthDeviceIdProviderImpl::RegisterLocalPrefs(registry);
+ extensions::ExtensionAssetsManagerChromeOS::RegisterPrefs(registry);
+ extensions::lock_screen_data::LockScreenItemStorage::RegisterLocalState(
+ registry);
+ extensions::login_api::RegisterLocalStatePrefs(registry);
+ invalidation::FCMInvalidationService::RegisterPrefs(registry);
+ invalidation::InvalidatorStorage::RegisterPrefs(registry);
+ ::onc::RegisterPrefs(registry);
+ policy::AutoEnrollmentClientImpl::RegisterPrefs(registry);
+ policy::BrowserPolicyConnectorChromeOS::RegisterPrefs(registry);
+ policy::DeviceCloudPolicyManagerChromeOS::RegisterPrefs(registry);
+ policy::DeviceStatusCollector::RegisterPrefs(registry);
+ policy::DeviceWallpaperImageExternalDataHandler::RegisterPrefs(registry);
+ policy::DMTokenStorage::RegisterPrefs(registry);
+ policy::PolicyCertServiceFactory::RegisterPrefs(registry);
+ policy::TPMAutoUpdateModePolicyHandler::RegisterPrefs(registry);
+ policy::WebUsbAllowDevicesForUrlsPolicyHandler::RegisterPrefs(registry);
+ quirks::QuirksManager::RegisterPrefs(registry);
+ UpgradeDetectorChromeos::RegisterPrefs(registry);
+ syncer::PerUserTopicRegistrationManager::RegisterPrefs(registry);
+ syncer::InvalidatorRegistrarWithMemory::RegisterPrefs(registry);
+#endif
+
+#if defined(OS_MACOSX)
+ confirm_quit::RegisterLocalState(registry);
+ OSCrypt::RegisterLocalPrefs(registry);
+ QuitWithAppsController::RegisterPrefs(registry);
+ system_media_permissions::RegisterSystemMediaPermissionStatesPrefs(registry);
+#endif
+
+#if defined(OS_WIN)
+ registry->RegisterBooleanPref(prefs::kRendererCodeIntegrityEnabled, true);
+ component_updater::RegisterPrefsForSwReporter(registry);
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ IncompatibleApplicationsUpdater::RegisterLocalStatePrefs(registry);
+ ModuleDatabase::RegisterLocalStatePrefs(registry);
+ ThirdPartyConflictsManager::RegisterLocalStatePrefs(registry);
+#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
+
+ registry->RegisterBooleanPref(kHasSeenWin10PromoPage, false); // DEPRECATED
+ registry->RegisterStringPref(kLastWelcomedOSVersion, std::string());
+#endif // defined(OS_WIN)
+
+ // Obsolete. See MigrateObsoleteBrowserPrefs().
+ registry->RegisterIntegerPref(metrics::prefs::kStabilityExecutionPhase, 0);
+#if !defined(OS_ANDROID)
+ registry->RegisterBooleanPref(kNtpActivateHideShortcutsFieldTrial, false);
+#endif // !defined(OS_ANDROID)
+ registry->RegisterInt64Pref(kLastStartupTimestamp, 0);
+ registry->RegisterStringPref(kLastStartupVersion, std::string());
+ registry->RegisterIntegerPref(kSameVersionStartupCount, 0);
+
+#if defined(TOOLKIT_VIEWS)
+ RegisterBrowserViewLocalPrefs(registry);
+#endif
+}
+
+// Register prefs applicable to all profiles.
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
+ const std::string& locale) {
+ TRACE_EVENT0("browser", "chrome::RegisterProfilePrefs");
+ // User prefs. Please keep this list alphabetized.
+ AccessibilityLabelsService::RegisterProfilePrefs(registry);
+ AccessibilityUIMessageHandler::RegisterProfilePrefs(registry);
+ AvailabilityProber::RegisterProfilePrefs(registry);
+ autofill::prefs::RegisterProfilePrefs(registry);
+ browsing_data::prefs::RegisterBrowserUserPrefs(registry);
+ certificate_transparency::prefs::RegisterPrefs(registry);
+ ChromeContentBrowserClient::RegisterProfilePrefs(registry);
+ ChromeSSLHostStateDelegate::RegisterProfilePrefs(registry);
+ ChromeVersionService::RegisterProfilePrefs(registry);
+ chrome_browser_net::NetErrorTabHelper::RegisterProfilePrefs(registry);
+ chrome_browser_net::RegisterPredictionOptionsProfilePrefs(registry);
+ chrome_prefs::RegisterProfilePrefs(registry);
+ dom_distiller::DistilledPagePrefs::RegisterProfilePrefs(registry);
+ DocumentProvider::RegisterProfilePrefs(registry);
+ DownloadPrefs::RegisterProfilePrefs(registry);
+ HostContentSettingsMap::RegisterProfilePrefs(registry);
+ image_fetcher::ImageCache::RegisterProfilePrefs(registry);
+ ImportantSitesUtil::RegisterProfilePrefs(registry);
+ IncognitoModePrefs::RegisterProfilePrefs(registry);
+ language::LanguagePrefs::RegisterProfilePrefs(registry);
+ MediaCaptureDevicesDispatcher::RegisterProfilePrefs(registry);
+ MediaDeviceIDSalt::RegisterProfilePrefs(registry);
+ MediaEngagementService::RegisterProfilePrefs(registry);
+ MediaStorageIdSalt::RegisterProfilePrefs(registry);
+ MediaStreamDevicesController::RegisterProfilePrefs(registry);
+ NavigationCorrectionTabObserver::RegisterProfilePrefs(registry);
+ NotifierStateTracker::RegisterProfilePrefs(registry);
+ ntp_snippets::ContentSuggestionsService::RegisterProfilePrefs(registry);
+ ntp_snippets::RemoteSuggestionsProviderImpl::RegisterProfilePrefs(registry);
+ ntp_snippets::RemoteSuggestionsSchedulerImpl::RegisterProfilePrefs(registry);
+ ntp_snippets::RequestThrottler::RegisterProfilePrefs(registry);
+ ntp_snippets::UserClassifier::RegisterProfilePrefs(registry);
+ ntp_tiles::MostVisitedSites::RegisterProfilePrefs(registry);
+ optimization_guide::prefs::RegisterProfilePrefs(registry);
+ password_bubble_experiment::RegisterPrefs(registry);
+ password_manager::PasswordManager::RegisterProfilePrefs(registry);
+ payments::RegisterProfilePrefs(registry);
+ PlatformNotificationServiceImpl::RegisterProfilePrefs(registry);
+ policy::DeveloperToolsPolicyHandler::RegisterProfilePrefs(registry);
+ policy::URLBlacklistManager::RegisterProfilePrefs(registry);
+ PrefProxyConfigTrackerImpl::RegisterProfilePrefs(registry);
+ PrefsTabHelper::RegisterProfilePrefs(registry, locale);
+ PreviewsLitePageRedirectDecider::RegisterProfilePrefs(registry);
+ PreviewsOfflineHelper::RegisterProfilePrefs(registry);
+ Profile::RegisterProfilePrefs(registry);
+ ProfileImpl::RegisterProfilePrefs(registry);
+ ProfileNetworkContextService::RegisterProfilePrefs(registry);
+ ProtocolHandlerRegistry::RegisterProfilePrefs(registry);
+ PushMessagingAppIdentifier::RegisterProfilePrefs(registry);
+ RegisterBrowserUserPrefs(registry);
+ safe_browsing::RegisterProfilePrefs(registry);
+ SafeBrowsingTriggeredPopupBlocker::RegisterProfilePrefs(registry);
+ SessionStartupPref::RegisterProfilePrefs(registry);
+ SharingSyncPreference::RegisterProfilePrefs(registry);
+ sync_sessions::SessionSyncPrefs::RegisterProfilePrefs(registry);
+ syncer::DeviceInfoPrefs::RegisterProfilePrefs(registry);
+ syncer::SyncPrefs::RegisterProfilePrefs(registry);
+ syncer::PerUserTopicRegistrationManager::RegisterProfilePrefs(registry);
+ syncer::InvalidatorRegistrarWithMemory::RegisterProfilePrefs(registry);
+ TemplateURLPrepopulateData::RegisterProfilePrefs(registry);
+ translate::TranslatePrefs::RegisterProfilePrefs(registry);
+ ZeroSuggestProvider::RegisterProfilePrefs(registry);
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+ ExtensionWebUI::RegisterProfilePrefs(registry);
+ RegisterAnimationPolicyPrefs(registry);
+ ToolbarActionsBar::RegisterProfilePrefs(registry);
+ extensions::api::CryptotokenRegisterProfilePrefs(registry);
+ extensions::ActivityLog::RegisterProfilePrefs(registry);
+ extensions::AudioAPI::RegisterUserPrefs(registry);
+ extensions::ExtensionPrefs::RegisterProfilePrefs(registry);
+ extensions::ExtensionsUI::RegisterProfilePrefs(registry);
+ extensions::NtpOverriddenBubbleDelegate::RegisterPrefs(registry);
+ extensions::RuntimeAPI::RegisterPrefs(registry);
+ update_client::RegisterProfilePrefs(registry);
+ web_app::WebAppProvider::RegisterProfilePrefs(registry);
+#endif // BUILDFLAG(ENABLE_EXTENSIONS)
+
+#if BUILDFLAG(ENABLE_LEGACY_DESKTOP_IN_PRODUCT_HELP)
+ feature_engagement::SessionDurationUpdater::RegisterProfilePrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_PLUGINS)
+ PluginInfoHostImpl::RegisterUserPrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
+ printing::PolicySettings::RegisterProfilePrefs(registry);
+ printing::StickySettings::RegisterProfilePrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY)
+ LocalDiscoveryUI::RegisterProfilePrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ ChildAccountService::RegisterProfilePrefs(registry);
+ SupervisedUserService::RegisterProfilePrefs(registry);
+ SupervisedUserWhitelistService::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(OS_ANDROID)
+ ntp_tiles::PopularSitesImpl::RegisterProfilePrefs(registry);
+ variations::VariationsService::RegisterProfilePrefs(registry);
+ GeolocationPermissionContextAndroid::RegisterProfilePrefs(registry);
+ PartnerBookmarksShim::RegisterProfilePrefs(registry);
+ RecentTabsPagePrefs::RegisterProfilePrefs(registry);
+ usage_stats::UsageStatsBridge::RegisterProfilePrefs(registry);
+#if BUILDFLAG(ENABLE_FEED_IN_CHROME)
+ feed::FeedSchedulerHost::RegisterProfilePrefs(registry);
+ feed::RefreshThrottler::RegisterProfilePrefs(registry);
+ feed::UserClassifier::RegisterProfilePrefs(registry);
+#endif // BUILDFLAG(ENABLE_FEED_IN_CHROME)
+#else
+ AppShortcutManager::RegisterProfilePrefs(registry);
+ DeviceIDFetcher::RegisterProfilePrefs(registry);
+ DevToolsWindow::RegisterProfilePrefs(registry);
+#if BUILDFLAG(ENABLE_APP_LIST)
+ app_list::AppListSyncableService::RegisterProfilePrefs(registry);
+#endif // BUILDFLAG(ENABLE_APP_LIST)
+ extensions::CommandService::RegisterProfilePrefs(registry);
+ extensions::TabsCaptureVisibleTabFunction::RegisterProfilePrefs(registry);
+ NewTabUI::RegisterProfilePrefs(registry);
+ PepperFlashSettingsManager::RegisterProfilePrefs(registry);
+ PinnedTabCodec::RegisterProfilePrefs(registry);
+ signin::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(OS_ANDROID)
+ cdm::MediaDrmStorageImpl::RegisterProfilePrefs(registry);
+ MediaDrmOriginIdManager::RegisterProfilePrefs(registry);
+ explore_sites::HistoryStatisticsReporter::RegisterPrefs(registry);
+ ntp_snippets::ClickBasedCategoryRanker::RegisterProfilePrefs(registry);
+ OomInterventionDecider::RegisterProfilePrefs(registry);
+#endif // defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+ browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry);
+ ChromeAuthenticatorRequestDelegate::RegisterProfilePrefs(registry);
+ first_run::RegisterProfilePrefs(registry);
+ HatsService::RegisterProfilePrefs(registry);
+ InstantService::RegisterProfilePrefs(registry);
+ PromoService::RegisterProfilePrefs(registry);
+ SearchSuggestService::RegisterProfilePrefs(registry);
+ gcm::GCMChannelStatusSyncer::RegisterProfilePrefs(registry);
+ gcm::RegisterProfilePrefs(registry);
+ media_router::RegisterProfilePrefs(registry);
+ ntp_tiles::CustomLinksManagerImpl::RegisterProfilePrefs(registry);
+ StartupBrowserCreator::RegisterProfilePrefs(registry);
+#endif
+
+#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
+ default_apps::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(OS_CHROMEOS)
+ arc::prefs::RegisterProfilePrefs(registry);
+ certificate_manager::CertificatesHandler::RegisterProfilePrefs(registry);
+ chromeos::AccountManager::RegisterPrefs(registry);
+ chromeos::assistant::prefs::RegisterProfilePrefsForBrowser(registry);
+ chromeos::CupsPrintersManager::RegisterProfilePrefs(registry);
+ chromeos::first_run::RegisterProfilePrefs(registry);
+ chromeos::file_system_provider::RegisterProfilePrefs(registry);
+ chromeos::KerberosCredentialsManager::RegisterProfilePrefs(registry);
+ chromeos::KeyPermissions::RegisterProfilePrefs(registry);
+ chromeos::multidevice_setup::MultiDeviceSetupService::RegisterProfilePrefs(
+ registry);
+ chromeos::MultiProfileUserController::RegisterProfilePrefs(registry);
+ chromeos::ReleaseNotesStorage::RegisterProfilePrefs(registry);
+ chromeos::quick_unlock::FingerprintStorage::RegisterProfilePrefs(registry);
+ chromeos::quick_unlock::PinStoragePrefs::RegisterProfilePrefs(registry);
+ chromeos::Preferences::RegisterProfilePrefs(registry);
+ chromeos::PrintJobHistoryService::RegisterProfilePrefs(registry);
+ chromeos::SyncedPrintersManager::RegisterProfilePrefs(registry);
+ chromeos::parent_access::ParentAccessService::RegisterProfilePrefs(registry);
+ chromeos::quick_unlock::RegisterProfilePrefs(registry);
+ chromeos::RegisterSamlProfilePrefs(registry);
+ chromeos::ScreenTimeController::RegisterProfilePrefs(registry);
+ chromeos::ServicesCustomizationDocument::RegisterProfilePrefs(registry);
+ chromeos::UserImageSyncObserver::RegisterProfilePrefs(registry);
+ crostini::prefs::RegisterProfilePrefs(registry);
+ chromeos::attestation::TpmChallengeKey::RegisterProfilePrefs(registry);
+ extensions::EPKPChallengeKey::RegisterProfilePrefs(registry);
+ flags_ui::PrefServiceFlagsStorage::RegisterProfilePrefs(registry);
+ guest_os::prefs::RegisterProfilePrefs(registry);
+ lock_screen_apps::StateController::RegisterProfilePrefs(registry);
+ plugin_vm::prefs::RegisterProfilePrefs(registry);
+ policy::AppInstallEventLogger::RegisterProfilePrefs(registry);
+ policy::AppInstallEventLogManagerWrapper::RegisterProfilePrefs(registry);
+ policy::StatusCollector::RegisterProfilePrefs(registry);
+ ::onc::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_APP_LIST)
+ app_list::ArcAppReinstallSearchProvider::RegisterProfilePrefs(registry);
+ ArcAppListPrefs::RegisterProfilePrefs(registry);
+ chromeos::ApkWebAppService::RegisterProfilePrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_RLZ)
+ ChromeRLZTrackerDelegate::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(OS_WIN)
+ component_updater::RegisterProfilePrefsForSwReporter(registry);
+ NetworkProfileBubble::RegisterProfilePrefs(registry);
+ safe_browsing::SettingsResetPromptPrefsManager::RegisterProfilePrefs(
+ registry);
+ safe_browsing::PostCleanupSettingsResetter::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || \
+ (defined(OS_LINUX) && !defined(OS_CHROMEOS))
+ browser_switcher::BrowserSwitcherPrefs::RegisterProfilePrefs(registry);
+#endif
+
+#if defined(TOOLKIT_VIEWS)
+ accessibility_prefs::RegisterInvertBubbleUserPrefs(registry);
+ RegisterBrowserViewProfilePrefs(registry);
+#endif
+
+#if defined(OS_CHROMEOS)
+ RegisterChromeLauncherUserPrefs(registry);
+#endif
+
+#if !defined(OS_ANDROID)
+ HistoryUI::RegisterProfilePrefs(registry);
+ settings::SettingsUI::RegisterProfilePrefs(registry);
+#endif
+
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+ offline_pages::OfflineMetricsCollectorImpl::RegisterPrefs(registry);
+ offline_pages::prefetch_prefs::RegisterPrefs(registry);
+#endif
+
+#if defined(OS_ANDROID)
+ NotificationChannelsProviderAndroid::RegisterProfilePrefs(registry);
+#endif
+
+#if !defined(OS_ANDROID)
+ UnifiedAutoplayConfig::RegisterProfilePrefs(registry);
+#endif
+
+#if !defined(OS_CHROMEOS) && BUILDFLAG(ENABLE_EXTENSIONS)
+ extensions::enterprise_reporting::RegisterProfilePrefs(registry);
+#endif
+
+#if !defined(OS_ANDROID)
+ enterprise_reporting::RegisterProfilePrefs(registry);
+#endif
+
+ RegisterProfilePrefsForMigration(registry);
+}
+
+void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+ RegisterUserProfilePrefs(registry, g_browser_process->GetApplicationLocale());
+}
+
+void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
+ const std::string& locale) {
+ RegisterProfilePrefs(registry, locale);
+
+#if defined(OS_ANDROID)
+ ::android::RegisterUserProfilePrefs(registry);
+#endif
+#if defined(OS_CHROMEOS)
+ ash::RegisterUserProfilePrefs(registry);
+#endif
+}
+
+void RegisterScreenshotPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterBooleanPref(prefs::kDisableScreenshots, false);
+}
+
+#if defined(OS_CHROMEOS)
+void RegisterSigninProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+ RegisterProfilePrefs(registry, g_browser_process->GetApplicationLocale());
+ ash::RegisterSigninProfilePrefs(registry);
+}
+
+#endif
+
+// This method should be periodically pruned of year+ old migrations.
+void MigrateObsoleteBrowserPrefs(Profile* profile, PrefService* local_state) {
+ // Added 12/2018.
+ local_state->ClearPref(metrics::prefs::kStabilityExecutionPhase);
+
+#if defined(OS_ANDROID)
+ // Added 9/2018
+ local_state->ClearPref(
+ metrics::prefs::kStabilityCrashCountWithoutGmsCoreUpdateObsolete);
+#endif // defined(OS_ANDROID)
+
+#if defined(OS_WIN)
+ // Added 9/2018
+ local_state->ClearPref(kLastWelcomedOSVersion);
+#endif
+#if defined(OS_CHROMEOS)
+ // Added 12/2018
+ local_state->ClearPref(prefs::kCarrierDealPromoShown);
+#endif
+
+#if defined(OS_WIN)
+ // Added 6/2019.
+ local_state->ClearPref(kHasSeenWin10PromoPage);
+#endif // defined(OS_WIN)
+
+#if !defined(OS_ANDROID)
+ // Added 7/2019.
+ local_state->ClearPref(kNtpActivateHideShortcutsFieldTrial);
+#endif // !defined(OS_ANDROID)
+
+ // Added 8/2019.
+ local_state->ClearPref(kLastStartupTimestamp);
+ local_state->ClearPref(kLastStartupVersion);
+ local_state->ClearPref(kSameVersionStartupCount);
+}
+
+// This method should be periodically pruned of year+ old migrations.
+void MigrateObsoleteProfilePrefs(Profile* profile) {
+ PrefService* profile_prefs = profile->GetPrefs();
+
+ // Added 8/2018.
+ autofill::prefs::MigrateDeprecatedAutofillPrefs(profile_prefs);
+
+ // Added 8/2018
+ profile_prefs->ClearPref(kDnsPrefetchingStartupList);
+ profile_prefs->ClearPref(kDnsPrefetchingHostReferralList);
+
+ // Added 9/2018
+ profile_prefs->ClearPref(kGeolocationAccessToken);
+ profile_prefs->ClearPref(kGoogleServicesPasswordHash);
+ profile_prefs->ClearPref(kModuleConflictBubbleShown);
+ profile_prefs->ClearPref(kOptionsWindowLastTabIndex);
+ profile_prefs->ClearPref(kTrustedDownloadSources);
+ profile_prefs->ClearPref(kSupervisedUserCreationAllowed);
+
+ // Added 10/2018
+ profile_prefs->ClearPref(kReverseAutologinEnabled);
+
+ // Added 11/2018.
+ profile_prefs->ClearPref(kNetworkQualities);
+ profile_prefs->ClearPref(kForceSessionSync);
+ profile_prefs->ClearPref(kOnboardDuringNUX);
+ profile_prefs->ClearPref(kNuxOnboardGroup);
+ profile_prefs->ClearPref(kHttpServerProperties);
+
+#if defined(OS_CHROMEOS)
+ // Added 12/2018.
+ profile_prefs->ClearPref(prefs::kDataSaverPromptsShown);
+
+ // Added 4/2019
+ guest_os::GuestOsSharePath::MigratePersistedPathsToMultiVM(profile_prefs);
+#endif
+
+ // Added 1/2019.
+ profile_prefs->ClearPref(kLastUpdateCheck);
+ profile_prefs->ClearPref(kNextUpdateCheck);
+
+ syncer::MigrateSessionsToProxyTabsPrefs(profile_prefs);
+ syncer::ClearObsoleteUserTypePrefs(profile_prefs);
+
+ // Added 2/2019.
+ syncer::ClearObsoleteClearServerDataPrefs(profile_prefs);
+ syncer::ClearObsoleteAuthErrorPrefs(profile_prefs);
+
+ // Added 3/2019.
+ syncer::ClearObsoleteFirstSyncTime(profile_prefs);
+ syncer::ClearObsoleteSyncLongPollIntervalSeconds(profile_prefs);
+
+ // Added 3/2019.
+ profile_prefs->ClearPref(kCurrentThemeImages);
+ profile_prefs->ClearPref(kCurrentThemeColors);
+ profile_prefs->ClearPref(kCurrentThemeTints);
+ profile_prefs->ClearPref(kCurrentThemeDisplayProperties);
+
+#if defined(OS_ANDROID)
+ // Added 4/2019.
+ profile_prefs->ClearPref(kDismissedAssetDownloadSuggestions);
+ profile_prefs->ClearPref(kDismissedOfflinePageDownloadSuggestions);
+
+ // Added 4/2019.
+ profile_prefs->ClearPref(kBreakingNewsSubscriptionDataToken);
+ profile_prefs->ClearPref(kBreakingNewsSubscriptionDataIsAuthenticated);
+ profile_prefs->ClearPref(kBreakingNewsGCMSubscriptionTokenCache);
+ profile_prefs->ClearPref(kBreakingNewsGCMLastTokenValidationTime);
+ profile_prefs->ClearPref(kBreakingNewsGCMLastForcedSubscriptionTime);
+#endif // defined(OS_ANDROID)
+
+#if defined(OS_CHROMEOS)
+ // Added 4/2019.
+ syncer::ClearObsoleteSyncSpareBootstrapToken(profile_prefs);
+#endif // defined(OS_CHROMEOS)
+
+#if defined(OS_ANDROID)
+ // Added 4/2019.
+ profile_prefs->ClearPref(kContentSuggestionsConsecutiveIgnoredPrefName);
+ profile_prefs->ClearPref(kContentSuggestionsNotificationsSentDay);
+ profile_prefs->ClearPref(kContentSuggestionsNotificationsSentCount);
+ profile_prefs->ClearPref(kNotificationIDWithinCategory);
+
+ // Added 5/2019.
+ profile_prefs->ClearPref(kContentSuggestionsNotificationsEnabled);
+#endif // defined(OS_ANDROID)
+
+#if !defined(OS_ANDROID)
+ // Deprecated 5/2019
+ profile_prefs->ClearPref(kSignInPromoShowOnFirstRunAllowed);
+ profile_prefs->ClearPref(kSignInPromoShowNTPBubble);
+#endif // !defined(OS_ANDROID)
+
+ // Added 5/2019.
+ profile_prefs->ClearPref(kBookmarkAppCreationLaunchType);
+
+ // Added 6/2019.
+ profile_prefs->ClearPref(kMediaCacheSize);
+#if defined(OS_MACOSX)
+ profile_prefs->ClearPref(password_manager::prefs::kKeychainMigrationStatus);
+#endif // defined(OS_MACOSX)
+
+ // Added 7/2019.
+ syncer::MigrateSyncSuppressedPref(profile_prefs);
+ profile_prefs->ClearPref(kSignedInTime);
+ syncer::ClearObsoleteMemoryPressurePrefs(profile_prefs);
+ profile_prefs->ClearPref(kLastKnownGoogleURL);
+ profile_prefs->ClearPref(kLastPromptedGoogleURL);
+
+#if defined(OS_ANDROID)
+ // Added 7/2019.
+ profile_prefs->ClearPref(kWebAuthnLastTransportUsedPrefName);
+ profile_prefs->ClearPref(kWebAuthnBlePairedMacAddressesPrefName);
+#endif // defined(OS_ANDROID)
+
+ // Added 7/2019.
+#if defined(USE_X11)
+ profile_prefs->ClearPref(kLocalProfileId);
+#endif
+
+ // Added 8/2019
+ profile_prefs->ClearPref(kInsecureExtensionUpdatesEnabled);
+ profile_prefs->ClearPref(kHintLoadedCounts);
+
+ // Added 9/2019
+ profile_prefs->ClearPref(kGoogleServicesUsername);
+ profile_prefs->ClearPref(kGoogleServicesUserAccountId);
+ profile_prefs->ClearPref(
+ kDataReductionProxySavingsClearedNegativeSystemClock);
+
+ // Added 10/2019.
+ syncer::DeviceInfoPrefs::MigrateRecentLocalCacheGuidsPref(profile_prefs);
+#if defined(OS_CHROMEOS)
+ // Added 10/2019.
+ profile_prefs->ClearPref(kDisplayRotationAcceleratorDialogHasBeenAccepted);
+#endif // defined(OS_CHROMEOS)
+}
diff --git a/chromium/chrome/browser/prefs/browser_prefs.h b/chromium/chrome/browser/prefs/browser_prefs.h
new file mode 100644
index 00000000000..05f6c207446
--- /dev/null
+++ b/chromium/chrome/browser/prefs/browser_prefs.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_BROWSER_PREFS_H_
+#define CHROME_BROWSER_PREFS_BROWSER_PREFS_H_
+
+#include <set>
+
+#include "build/build_config.h"
+#include "components/prefs/pref_value_store.h"
+
+class PrefRegistrySimple;
+class PrefService;
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+// Register all prefs that will be used via the local state PrefService.
+void RegisterLocalState(PrefRegistrySimple* registry);
+
+void RegisterScreenshotPrefs(PrefRegistrySimple* registry);
+
+// Register all prefs that will be used via a PrefService attached to a user
+// Profile using the locale of |g_browser_process|.
+void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+// Register all prefs that will be used via a PrefService attached to a user
+// Profile with the given |locale|.
+void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
+ const std::string& locale);
+
+#if defined(OS_CHROMEOS)
+// Register all prefs that will be used via a PrefService attached to the
+// sign-in profile using the locale of |g_browser_process|.
+void RegisterSigninProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+#endif
+
+// Migrate/cleanup deprecated prefs in |local_state|. Over time, long deprecated
+// prefs should be removed as new ones are added, but this call should never go
+// away (even if it becomes an empty call for some time) as it should remain
+// *the* place to drop deprecated browser prefs at.
+void MigrateObsoleteBrowserPrefs(Profile* profile, PrefService* local_state);
+
+// Migrate/cleanup deprecated prefs in |profile|'s pref store. Over time, long
+// deprecated prefs should be removed as new ones are added, but this call
+// should never go away (even if it becomes an empty call for some time) as it
+// should remain *the* place to drop deprecated profile prefs at.
+void MigrateObsoleteProfilePrefs(Profile* profile);
+
+#endif // CHROME_BROWSER_PREFS_BROWSER_PREFS_H_
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc
new file mode 100644
index 00000000000..60cd72cedbb
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store.cc
@@ -0,0 +1,177 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "ash/public/cpp/ash_switches.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/browser_sync/browser_sync_switches.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
+#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
+#include "components/language/core/browser/pref_names.h"
+#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
+#include "components/sync/base/pref_names.h"
+#include "content/public/common/content_switches.h"
+#include "services/network/public/cpp/network_switches.h"
+#include "ui/base/ui_base_switches.h"
+#include "ui/display/display_switches.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/constants/chromeos_switches.h"
+#endif
+
+const CommandLinePrefStore::SwitchToPreferenceMapEntry
+ ChromeCommandLinePrefStore::string_switch_map_[] = {
+ {switches::kLang, language::prefs::kApplicationLocale},
+ {data_reduction_proxy::switches::kDataReductionProxy,
+ data_reduction_proxy::prefs::kDataReductionProxy},
+ {switches::kAuthServerWhitelist, prefs::kAuthServerWhitelist},
+ {switches::kSSLVersionMin, prefs::kSSLVersionMin},
+ {switches::kSSLVersionMax, prefs::kSSLVersionMax},
+#if defined(OS_ANDROID)
+ {switches::kAuthAndroidNegotiateAccountType,
+ prefs::kAuthAndroidNegotiateAccountType},
+#endif
+#if defined(OS_CHROMEOS)
+ {switches::kSchedulerConfiguration, prefs::kSchedulerConfiguration},
+#endif
+};
+
+const CommandLinePrefStore::SwitchToPreferenceMapEntry
+ ChromeCommandLinePrefStore::path_switch_map_[] = {
+ { switches::kDiskCacheDir, prefs::kDiskCacheDir },
+ { switches::kLocalSyncBackendDir, syncer::prefs::kLocalSyncBackendDir },
+};
+
+const CommandLinePrefStore::BooleanSwitchToPreferenceMapEntry
+ ChromeCommandLinePrefStore::boolean_switch_map_[] = {
+ {switches::kDisable3DAPIs, prefs::kDisable3DAPIs, true},
+ {switches::kEnableCloudPrintProxy, prefs::kCloudPrintProxyEnabled,
+ true},
+ {switches::kAllowOutdatedPlugins, prefs::kPluginsAllowOutdated, true},
+ {switches::kNoPings, prefs::kEnableHyperlinkAuditing, false},
+ {switches::kAllowRunningInsecureContent,
+ prefs::kWebKitAllowRunningInsecureContent, true},
+ {switches::kAllowCrossOriginAuthPrompt,
+ prefs::kAllowCrossOriginAuthPrompt, true},
+ {switches::kDisablePrintPreview, prefs::kPrintPreviewDisabled, true},
+#if defined(OS_CHROMEOS)
+ {chromeos::switches::kEnableTouchpadThreeFingerClick,
+ prefs::kEnableTouchpadThreeFingerClick, true},
+ {switches::kEnableUnifiedDesktop,
+ prefs::kUnifiedDesktopEnabledByDefault, true},
+ {chromeos::switches::kEnableCastReceiver, prefs::kCastReceiverEnabled,
+ true},
+#endif
+ {switches::kEnableLocalSyncBackend,
+ syncer::prefs::kEnableLocalSyncBackend, true},
+#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
+ {switches::kUseSystemDefaultPrinter,
+ prefs::kPrintPreviewUseSystemDefaultPrinter, true},
+#endif
+ {switches::kSitePerProcess, prefs::kSitePerProcess, true},
+};
+
+const CommandLinePrefStore::SwitchToPreferenceMapEntry
+ ChromeCommandLinePrefStore::integer_switch_map_[] = {
+ {switches::kDiskCacheSize, prefs::kDiskCacheSize}};
+
+ChromeCommandLinePrefStore::ChromeCommandLinePrefStore(
+ const base::CommandLine* command_line)
+ : CommandLinePrefStore(command_line) {
+ ApplySimpleSwitches();
+ ApplyProxyMode();
+ ValidateProxySwitches();
+ ApplySSLSwitches();
+ ApplyBackgroundModeSwitches();
+}
+
+ChromeCommandLinePrefStore::~ChromeCommandLinePrefStore() {}
+
+bool ChromeCommandLinePrefStore::ValidateProxySwitches() {
+ if (command_line()->HasSwitch(switches::kNoProxyServer) &&
+ (command_line()->HasSwitch(switches::kProxyAutoDetect) ||
+ command_line()->HasSwitch(switches::kProxyServer) ||
+ command_line()->HasSwitch(switches::kProxyPacUrl) ||
+ command_line()->HasSwitch(switches::kProxyBypassList))) {
+ LOG(WARNING) << "Additional command-line proxy switches specified when --"
+ << switches::kNoProxyServer << " was also specified.";
+ return false;
+ }
+ return true;
+}
+
+void ChromeCommandLinePrefStore::ApplySimpleSwitches() {
+ // Look for each switch we know about and set its preference accordingly.
+ ApplyStringSwitches(string_switch_map_, base::size(string_switch_map_));
+ ApplyPathSwitches(path_switch_map_, base::size(path_switch_map_));
+ ApplyIntegerSwitches(integer_switch_map_, base::size(integer_switch_map_));
+ ApplyBooleanSwitches(boolean_switch_map_, base::size(boolean_switch_map_));
+}
+
+void ChromeCommandLinePrefStore::ApplyProxyMode() {
+ if (command_line()->HasSwitch(switches::kNoProxyServer)) {
+ SetValue(
+ proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(ProxyConfigDictionary::CreateDirect()),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ } else if (command_line()->HasSwitch(switches::kProxyPacUrl)) {
+ std::string pac_script_url =
+ command_line()->GetSwitchValueASCII(switches::kProxyPacUrl);
+ SetValue(proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreatePacScript(pac_script_url, false)),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ } else if (command_line()->HasSwitch(switches::kProxyAutoDetect)) {
+ SetValue(proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreateAutoDetect()),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ } else if (command_line()->HasSwitch(switches::kProxyServer)) {
+ std::string proxy_server =
+ command_line()->GetSwitchValueASCII(switches::kProxyServer);
+ std::string bypass_list =
+ command_line()->GetSwitchValueASCII(switches::kProxyBypassList);
+ SetValue(
+ proxy_config::prefs::kProxy,
+ std::make_unique<base::Value>(ProxyConfigDictionary::CreateFixedServers(
+ proxy_server, bypass_list)),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ }
+}
+
+void ChromeCommandLinePrefStore::ApplySSLSwitches() {
+ if (command_line()->HasSwitch(switches::kCipherSuiteBlacklist)) {
+ std::unique_ptr<base::ListValue> list_value(new base::ListValue());
+ list_value->AppendStrings(base::SplitString(
+ command_line()->GetSwitchValueASCII(switches::kCipherSuiteBlacklist),
+ ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
+ SetValue(prefs::kCipherSuiteBlacklist, std::move(list_value),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ }
+}
+
+void ChromeCommandLinePrefStore::ApplyBackgroundModeSwitches() {
+ if (command_line()->HasSwitch(switches::kDisableExtensions)) {
+ SetValue(prefs::kBackgroundModeEnabled,
+ std::make_unique<base::Value>(false),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ }
+}
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store.h b/chromium/chrome/browser/prefs/chrome_command_line_pref_store.h
new file mode 100644
index 00000000000..a37280f137d
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_CHROME_COMMAND_LINE_PREF_STORE_H_
+#define CHROME_BROWSER_PREFS_CHROME_COMMAND_LINE_PREF_STORE_H_
+
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/values.h"
+#include "components/prefs/command_line_pref_store.h"
+
+// This PrefStore keeps track of preferences set by command-line switches,
+// such as proxy settings.
+class ChromeCommandLinePrefStore : public CommandLinePrefStore {
+ public:
+ explicit ChromeCommandLinePrefStore(const base::CommandLine* command_line);
+
+ protected:
+ ~ChromeCommandLinePrefStore() override;
+
+ // Logs a message and returns false if the proxy switches are
+ // self-contradictory. Protected so it can be used in unit testing.
+ // TODO(bauerb): make this method public and remove the subclass, which calls
+ // this method, from the test.
+ bool ValidateProxySwitches();
+
+ private:
+ friend class TestCommandLinePrefStore;
+
+ // Using the string and boolean maps, apply command-line switches to their
+ // corresponding preferences in this pref store.
+ void ApplySimpleSwitches();
+
+ // Determines the proxy mode preference from the given proxy switches.
+ void ApplyProxyMode();
+
+ // Apply the SSL/TLS preferences from the given switches.
+ void ApplySSLSwitches();
+
+ // Determines whether the background mode is force-disabled.
+ void ApplyBackgroundModeSwitches();
+
+ // Mappings of command line switches to prefs.
+ static const BooleanSwitchToPreferenceMapEntry boolean_switch_map_[];
+ static const SwitchToPreferenceMapEntry string_switch_map_[];
+ static const SwitchToPreferenceMapEntry path_switch_map_[];
+ static const SwitchToPreferenceMapEntry integer_switch_map_[];
+
+ DISALLOW_COPY_AND_ASSIGN(ChromeCommandLinePrefStore);
+};
+
+#endif // CHROME_BROWSER_PREFS_CHROME_COMMAND_LINE_PREF_STORE_H_
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc
new file mode 100644
index 00000000000..62e885a16b5
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_proxy_unittest.cc
@@ -0,0 +1,198 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+
+#include <gtest/gtest.h>
+#include <stddef.h>
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/stl_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/proxy_config/pref_proxy_config_tracker_impl.h"
+#include "components/sync_preferences/pref_service_mock_factory.h"
+#include "content/public/common/content_switches.h"
+#include "net/proxy_resolution/proxy_config_service_common_unittest.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Test parameter object for testing command line proxy configuration.
+struct CommandLineTestParams {
+ // Short description to identify the test.
+ const char* description;
+
+ // The command line to build a ProxyConfig from.
+ struct SwitchValue {
+ const char* name;
+ const char* value;
+ } switches[2];
+
+ // Expected outputs (fields of the ProxyConfig).
+ bool is_null;
+ bool auto_detect;
+ GURL pac_url;
+ net::ProxyRulesExpectation proxy_rules;
+};
+
+void PrintTo(const CommandLineTestParams& params, std::ostream* os) {
+ *os << params.description;
+}
+
+static const CommandLineTestParams kCommandLineTestParams[] = {
+ {
+ "Empty command line",
+ // Input
+ {},
+ // Expected result
+ true, // is_null
+ false, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::Empty(),
+ },
+ {
+ "No proxy",
+ // Input
+ {
+ {switches::kNoProxyServer, NULL},
+ },
+ // Expected result
+ false, // is_null
+ false, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::Empty(),
+ },
+ {
+ "No proxy with extra parameters.",
+ // Input
+ {
+ {switches::kNoProxyServer, NULL},
+ {switches::kProxyServer, "http://proxy:8888"},
+ },
+ // Expected result
+ false, // is_null
+ false, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::Empty(),
+ },
+ {
+ "Single proxy.",
+ // Input
+ {
+ {switches::kProxyServer, "http://proxy:8888"},
+ },
+ // Expected result
+ false, // is_null
+ false, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::Single("proxy:8888", // single proxy
+ ""), // bypass rules
+ },
+ {
+ "Per scheme proxy.",
+ // Input
+ {
+ {switches::kProxyServer, "http=httpproxy:8888;ftp=ftpproxy:8889"},
+ },
+ // Expected result
+ false, // is_null
+ false, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::PerScheme("httpproxy:8888", // http
+ "", // https
+ "ftpproxy:8889", // ftp
+ ""), // bypass rules
+ },
+ {
+ "Per scheme proxy with bypass URLs.",
+ // Input
+ {
+ {switches::kProxyServer, "http=httpproxy:8888;ftp=ftpproxy:8889"},
+ {switches::kProxyBypassList,
+ ".google.com, foo.com:99, 1.2.3.4:22, 127.0.0.1/8"},
+ },
+ // Expected result
+ false, // is_null
+ false, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::PerScheme(
+ "httpproxy:8888", // http
+ "", // https
+ "ftpproxy:8889", // ftp
+ "*.google.com,foo.com:99,1.2.3.4:22,127.0.0.1/8"),
+ },
+ {
+ "Pac URL",
+ // Input
+ {
+ {switches::kProxyPacUrl, "http://wpad/wpad.dat"},
+ },
+ // Expected result
+ false, // is_null
+ false, // auto_detect
+ GURL("http://wpad/wpad.dat"), // pac_url
+ net::ProxyRulesExpectation::Empty(),
+ },
+ {
+ "Autodetect",
+ // Input
+ {
+ {switches::kProxyAutoDetect, NULL},
+ },
+ // Expected result
+ false, // is_null
+ true, // auto_detect
+ GURL(), // pac_url
+ net::ProxyRulesExpectation::Empty(),
+ },
+};
+
+} // namespace
+
+class ChromeCommandLinePrefStoreProxyTest
+ : public testing::TestWithParam<CommandLineTestParams> {
+ protected:
+ ChromeCommandLinePrefStoreProxyTest()
+ : command_line_(base::CommandLine::NO_PROGRAM) {}
+
+ net::ProxyConfigWithAnnotation* proxy_config() { return &proxy_config_; }
+
+ void SetUp() override {
+ for (size_t i = 0; i < base::size(GetParam().switches); i++) {
+ const char* name = GetParam().switches[i].name;
+ const char* value = GetParam().switches[i].value;
+ if (name && value)
+ command_line_.AppendSwitchASCII(name, value);
+ else if (name)
+ command_line_.AppendSwitch(name);
+ }
+ scoped_refptr<PrefRegistrySimple> registry = new PrefRegistrySimple;
+ PrefProxyConfigTrackerImpl::RegisterPrefs(registry.get());
+ sync_preferences::PrefServiceMockFactory factory;
+ factory.set_command_line_prefs(
+ new ChromeCommandLinePrefStore(&command_line_));
+ pref_service_ = factory.Create(registry.get());
+ PrefProxyConfigTrackerImpl::ReadPrefConfig(pref_service_.get(),
+ &proxy_config_);
+ }
+
+ private:
+ base::CommandLine command_line_;
+ std::unique_ptr<PrefService> pref_service_;
+ net::ProxyConfigWithAnnotation proxy_config_;
+};
+
+TEST_P(ChromeCommandLinePrefStoreProxyTest, CommandLine) {
+ EXPECT_EQ(GetParam().auto_detect, proxy_config()->value().auto_detect());
+ EXPECT_EQ(GetParam().pac_url, proxy_config()->value().pac_url());
+ EXPECT_TRUE(
+ GetParam().proxy_rules.Matches(proxy_config()->value().proxy_rules()));
+}
+
+INSTANTIATE_TEST_SUITE_P(ChromeCommandLinePrefStoreProxyTestInstance,
+ ChromeCommandLinePrefStoreProxyTest,
+ testing::ValuesIn(kCommandLineTestParams));
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc
new file mode 100644
index 00000000000..ba08fd05151
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_ssl_manager_unittest.cc
@@ -0,0 +1,71 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/test/task_environment.h"
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "chrome/browser/ssl/ssl_config_service_manager.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/testing_pref_store.h"
+#include "components/sync_preferences/pref_service_mock_factory.h"
+#include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/public/mojom/ssl_config.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class CommandLinePrefStoreSSLManagerTest : public testing::Test {
+ public:
+ CommandLinePrefStoreSSLManagerTest() {}
+
+ protected:
+ base::test::SingleThreadTaskEnvironment task_environment_;
+};
+
+// Test that command-line settings for SSL versions are respected and that they
+// do not persist to the preferences files.
+TEST_F(CommandLinePrefStoreSSLManagerTest, CommandLinePrefs) {
+ scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
+
+ base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
+ command_line.AppendSwitchASCII(switches::kSSLVersionMin, "tls1.1");
+ command_line.AppendSwitchASCII(switches::kSSLVersionMax, "tls1.2");
+
+ sync_preferences::PrefServiceMockFactory factory;
+ factory.set_user_prefs(local_state_store);
+ factory.set_command_line_prefs(new ChromeCommandLinePrefStore(&command_line));
+ scoped_refptr<PrefRegistrySimple> registry = new PrefRegistrySimple;
+ std::unique_ptr<PrefService> local_state(factory.Create(registry.get()));
+
+ SSLConfigServiceManager::RegisterPrefs(registry.get());
+ network::mojom::NetworkContextParamsPtr context_params =
+ network::mojom::NetworkContextParams::New();
+ std::unique_ptr<SSLConfigServiceManager> config_manager(
+ SSLConfigServiceManager::CreateDefaultManager(local_state.get()));
+ config_manager->AddToNetworkContextParams(context_params.get());
+
+ // Command-line flags should be respected.
+ EXPECT_EQ(network::mojom::SSLVersion::kTLS11,
+ context_params->initial_ssl_config->version_min);
+ EXPECT_EQ(network::mojom::SSLVersion::kTLS12,
+ context_params->initial_ssl_config->version_max);
+
+ // Explicitly double-check the settings are not in the preference store.
+ const PrefService::Preference* version_min_pref =
+ local_state->FindPreference(prefs::kSSLVersionMin);
+ EXPECT_FALSE(version_min_pref->IsUserModifiable());
+
+ const PrefService::Preference* version_max_pref =
+ local_state->FindPreference(prefs::kSSLVersionMax);
+ EXPECT_FALSE(version_max_pref->IsUserModifiable());
+
+ std::string version_min_str;
+ std::string version_max_str;
+ EXPECT_FALSE(
+ local_state_store->GetString(prefs::kSSLVersionMin, &version_min_str));
+ EXPECT_FALSE(
+ local_state_store->GetString(prefs::kSSLVersionMax, &version_max_str));
+}
diff --git a/chromium/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc
new file mode 100644
index 00000000000..8753173ce1a
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc
@@ -0,0 +1,222 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <gtest/gtest.h>
+#include <stddef.h>
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/language/core/browser/pref_names.h"
+#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
+#include "content/public/common/content_switches.h"
+#include "ui/base/ui_base_switches.h"
+
+namespace {
+
+const char unknown_bool[] = "unknown_switch";
+const char unknown_string[] = "unknown_other_switch";
+
+} // namespace
+
+class TestCommandLinePrefStore : public ChromeCommandLinePrefStore {
+ public:
+ explicit TestCommandLinePrefStore(base::CommandLine* cl)
+ : ChromeCommandLinePrefStore(cl) {}
+
+ bool ProxySwitchesAreValid() {
+ return ValidateProxySwitches();
+ }
+
+ void VerifyProxyMode(ProxyPrefs::ProxyMode expected_mode) {
+ const base::Value* value = nullptr;
+ ASSERT_TRUE(GetValue(proxy_config::prefs::kProxy, &value));
+ ASSERT_TRUE(value->is_dict());
+ ProxyConfigDictionary dict(value->Clone());
+ ProxyPrefs::ProxyMode actual_mode;
+ ASSERT_TRUE(dict.GetMode(&actual_mode));
+ EXPECT_EQ(expected_mode, actual_mode);
+ }
+
+ void VerifySSLCipherSuites(const char* const* ciphers,
+ size_t cipher_count) {
+ const base::Value* value = nullptr;
+ ASSERT_TRUE(GetValue(prefs::kCipherSuiteBlacklist, &value));
+ ASSERT_TRUE(value->is_list());
+ ASSERT_EQ(cipher_count, value->GetList().size());
+
+ std::string cipher_string;
+ for (const base::Value& cipher_string : value->GetList()) {
+ ASSERT_TRUE(cipher_string.is_string());
+ EXPECT_EQ(*ciphers++, cipher_string.GetString());
+ }
+ }
+
+ private:
+ ~TestCommandLinePrefStore() override {}
+};
+
+// Tests a simple string pref on the command line.
+TEST(ChromeCommandLinePrefStoreTest, SimpleStringPref) {
+ base::CommandLine cl(base::CommandLine::NO_PROGRAM);
+ cl.AppendSwitchASCII(switches::kLang, "hi-MOM");
+ scoped_refptr<ChromeCommandLinePrefStore> store =
+ new ChromeCommandLinePrefStore(&cl);
+
+ const base::Value* actual = nullptr;
+ EXPECT_TRUE(store->GetValue(language::prefs::kApplicationLocale, &actual));
+ std::string result;
+ EXPECT_TRUE(actual->GetAsString(&result));
+ EXPECT_EQ("hi-MOM", result);
+}
+
+// Tests a simple boolean pref on the command line.
+TEST(ChromeCommandLinePrefStoreTest, SimpleBooleanPref) {
+ base::CommandLine cl(base::CommandLine::NO_PROGRAM);
+ cl.AppendSwitch(switches::kNoProxyServer);
+ scoped_refptr<TestCommandLinePrefStore> store =
+ new TestCommandLinePrefStore(&cl);
+
+ store->VerifyProxyMode(ProxyPrefs::MODE_DIRECT);
+}
+
+// Tests a command line with no recognized prefs.
+TEST(ChromeCommandLinePrefStoreTest, NoPrefs) {
+ base::CommandLine cl(base::CommandLine::NO_PROGRAM);
+ cl.AppendSwitch(unknown_string);
+ cl.AppendSwitchASCII(unknown_bool, "a value");
+ scoped_refptr<ChromeCommandLinePrefStore> store =
+ new ChromeCommandLinePrefStore(&cl);
+
+ const base::Value* actual = nullptr;
+ EXPECT_FALSE(store->GetValue(unknown_bool, &actual));
+ EXPECT_FALSE(store->GetValue(unknown_string, &actual));
+}
+
+// Tests a complex command line with multiple known and unknown switches.
+TEST(ChromeCommandLinePrefStoreTest, MultipleSwitches) {
+ base::CommandLine cl(base::CommandLine::NO_PROGRAM);
+ cl.AppendSwitch(unknown_string);
+ cl.AppendSwitchASCII(switches::kProxyServer, "proxy");
+ cl.AppendSwitchASCII(switches::kProxyBypassList, "list");
+ cl.AppendSwitchASCII(unknown_bool, "a value");
+ scoped_refptr<TestCommandLinePrefStore> store =
+ new TestCommandLinePrefStore(&cl);
+
+ const base::Value* actual = nullptr;
+ EXPECT_FALSE(store->GetValue(unknown_bool, &actual));
+ EXPECT_FALSE(store->GetValue(unknown_string, &actual));
+
+ store->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS);
+
+ const base::Value* value = nullptr;
+ ASSERT_TRUE(store->GetValue(proxy_config::prefs::kProxy, &value));
+ ASSERT_TRUE(value->is_dict());
+ ProxyConfigDictionary dict(value->Clone());
+
+ std::string string_result;
+
+ ASSERT_TRUE(dict.GetProxyServer(&string_result));
+ EXPECT_EQ("proxy", string_result);
+
+ ASSERT_TRUE(dict.GetBypassList(&string_result));
+ EXPECT_EQ("list", string_result);
+}
+
+// Tests proxy switch validation.
+TEST(ChromeCommandLinePrefStoreTest, ProxySwitchValidation) {
+ base::CommandLine cl(base::CommandLine::NO_PROGRAM);
+
+ // No switches.
+ scoped_refptr<TestCommandLinePrefStore> store =
+ new TestCommandLinePrefStore(&cl);
+ EXPECT_TRUE(store->ProxySwitchesAreValid());
+
+ // Only no-proxy.
+ cl.AppendSwitch(switches::kNoProxyServer);
+ scoped_refptr<TestCommandLinePrefStore> store2 =
+ new TestCommandLinePrefStore(&cl);
+ EXPECT_TRUE(store2->ProxySwitchesAreValid());
+
+ // Another proxy switch too.
+ cl.AppendSwitch(switches::kProxyAutoDetect);
+ scoped_refptr<TestCommandLinePrefStore> store3 =
+ new TestCommandLinePrefStore(&cl);
+ EXPECT_FALSE(store3->ProxySwitchesAreValid());
+
+ // All proxy switches except no-proxy.
+ base::CommandLine cl2(base::CommandLine::NO_PROGRAM);
+ cl2.AppendSwitch(switches::kProxyAutoDetect);
+ cl2.AppendSwitchASCII(switches::kProxyServer, "server");
+ cl2.AppendSwitchASCII(switches::kProxyPacUrl, "url");
+ cl2.AppendSwitchASCII(switches::kProxyBypassList, "list");
+ scoped_refptr<TestCommandLinePrefStore> store4 =
+ new TestCommandLinePrefStore(&cl2);
+ EXPECT_TRUE(store4->ProxySwitchesAreValid());
+}
+
+TEST(ChromeCommandLinePrefStoreTest, ManualProxyModeInference) {
+ base::CommandLine cl1(base::CommandLine::NO_PROGRAM);
+ cl1.AppendSwitch(unknown_string);
+ cl1.AppendSwitchASCII(switches::kProxyServer, "proxy");
+ scoped_refptr<TestCommandLinePrefStore> store1 =
+ new TestCommandLinePrefStore(&cl1);
+ store1->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS);
+
+ base::CommandLine cl2(base::CommandLine::NO_PROGRAM);
+ cl2.AppendSwitchASCII(switches::kProxyPacUrl, "proxy");
+ scoped_refptr<TestCommandLinePrefStore> store2 =
+ new TestCommandLinePrefStore(&cl2);
+ store2->VerifyProxyMode(ProxyPrefs::MODE_PAC_SCRIPT);
+
+ base::CommandLine cl3(base::CommandLine::NO_PROGRAM);
+ cl3.AppendSwitchASCII(switches::kProxyServer, std::string());
+ scoped_refptr<TestCommandLinePrefStore> store3 =
+ new TestCommandLinePrefStore(&cl3);
+ store3->VerifyProxyMode(ProxyPrefs::MODE_DIRECT);
+}
+
+TEST(ChromeCommandLinePrefStoreTest, DisableSSLCipherSuites) {
+ base::CommandLine cl1(base::CommandLine::NO_PROGRAM);
+ cl1.AppendSwitchASCII(switches::kCipherSuiteBlacklist,
+ "0x0004,0x0005");
+ scoped_refptr<TestCommandLinePrefStore> store1 =
+ new TestCommandLinePrefStore(&cl1);
+ const char* const expected_ciphers1[] = {
+ "0x0004",
+ "0x0005",
+ };
+ store1->VerifySSLCipherSuites(expected_ciphers1,
+ base::size(expected_ciphers1));
+
+ base::CommandLine cl2(base::CommandLine::NO_PROGRAM);
+ cl2.AppendSwitchASCII(switches::kCipherSuiteBlacklist,
+ "0x0004, WHITESPACE_IGNORED TEST , 0x0005");
+ scoped_refptr<TestCommandLinePrefStore> store2 =
+ new TestCommandLinePrefStore(&cl2);
+ const char* const expected_ciphers2[] = {
+ "0x0004",
+ "WHITESPACE_IGNORED TEST",
+ "0x0005",
+ };
+ store2->VerifySSLCipherSuites(expected_ciphers2,
+ base::size(expected_ciphers2));
+
+ base::CommandLine cl3(base::CommandLine::NO_PROGRAM);
+ cl3.AppendSwitchASCII(switches::kCipherSuiteBlacklist,
+ "0x0004;MOAR;0x0005");
+ scoped_refptr<TestCommandLinePrefStore> store3 =
+ new TestCommandLinePrefStore(&cl3);
+ const char* const expected_ciphers3[] = {
+ "0x0004;MOAR;0x0005"
+ };
+ store3->VerifySSLCipherSuites(expected_ciphers3,
+ base::size(expected_ciphers3));
+}
diff --git a/chromium/chrome/browser/prefs/chrome_pref_model_associator_client.cc b/chromium/chrome/browser/prefs/chrome_pref_model_associator_client.cc
new file mode 100644
index 00000000000..a628aa6a4fd
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_pref_model_associator_client.cc
@@ -0,0 +1,57 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/chrome_pref_model_associator_client.h"
+
+#include <cstdint>
+
+#include "base/memory/singleton.h"
+#include "chrome/common/pref_names.h"
+#include "components/content_settings/core/browser/website_settings_info.h"
+#include "components/content_settings/core/browser/website_settings_registry.h"
+
+// static
+ChromePrefModelAssociatorClient*
+ChromePrefModelAssociatorClient::GetInstance() {
+ return base::Singleton<ChromePrefModelAssociatorClient>::get();
+}
+
+ChromePrefModelAssociatorClient::ChromePrefModelAssociatorClient() {}
+
+ChromePrefModelAssociatorClient::~ChromePrefModelAssociatorClient() {}
+
+bool ChromePrefModelAssociatorClient::IsMergeableListPreference(
+ const std::string& pref_name) const {
+ return pref_name == prefs::kURLsToRestoreOnStartup;
+}
+
+bool ChromePrefModelAssociatorClient::IsMergeableDictionaryPreference(
+ const std::string& pref_name) const {
+ const content_settings::WebsiteSettingsRegistry& registry =
+ *content_settings::WebsiteSettingsRegistry::GetInstance();
+ for (const content_settings::WebsiteSettingsInfo* info : registry) {
+ if (info->pref_name() == pref_name)
+ return true;
+ }
+ return false;
+}
+
+std::unique_ptr<base::Value>
+ChromePrefModelAssociatorClient::MaybeMergePreferenceValues(
+ const std::string& pref_name,
+ const base::Value& local_value,
+ const base::Value& server_value) const {
+ if (pref_name == prefs::kNetworkEasterEggHighScore) {
+ uint32_t local_high_score;
+ if (!local_value.GetAsInteger(reinterpret_cast<int*>(&local_high_score)))
+ return nullptr;
+ uint32_t server_high_score;
+ if (!server_value.GetAsInteger(reinterpret_cast<int*>(&server_high_score)))
+ return nullptr;
+ return std::make_unique<base::Value>(
+ static_cast<int>(std::max(local_high_score, server_high_score)));
+ }
+
+ return nullptr;
+}
diff --git a/chromium/chrome/browser/prefs/chrome_pref_model_associator_client.h b/chromium/chrome/browser/prefs/chrome_pref_model_associator_client.h
new file mode 100644
index 00000000000..d11606a688d
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_pref_model_associator_client.h
@@ -0,0 +1,42 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_CHROME_PREF_MODEL_ASSOCIATOR_CLIENT_H_
+#define CHROME_BROWSER_PREFS_CHROME_PREF_MODEL_ASSOCIATOR_CLIENT_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "components/sync_preferences/pref_model_associator_client.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+class ChromePrefModelAssociatorClient
+ : public sync_preferences::PrefModelAssociatorClient {
+ public:
+ // Returns the global instance.
+ static ChromePrefModelAssociatorClient* GetInstance();
+
+ private:
+ friend struct base::DefaultSingletonTraits<ChromePrefModelAssociatorClient>;
+
+ ChromePrefModelAssociatorClient();
+ ~ChromePrefModelAssociatorClient() override;
+
+ // sync_preferences::PrefModelAssociatorClient implementation.
+ bool IsMergeableListPreference(const std::string& pref_name) const override;
+ bool IsMergeableDictionaryPreference(
+ const std::string& pref_name) const override;
+ std::unique_ptr<base::Value> MaybeMergePreferenceValues(
+ const std::string& pref_name,
+ const base::Value& local_value,
+ const base::Value& server_value) const override;
+
+ DISALLOW_COPY_AND_ASSIGN(ChromePrefModelAssociatorClient);
+};
+
+#endif // CHROME_BROWSER_PREFS_CHROME_PREF_MODEL_ASSOCIATOR_CLIENT_H_
diff --git a/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc b/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc
new file mode 100644
index 00000000000..6b6e1fe677f
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -0,0 +1,540 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/chrome_pref_service_factory.h"
+
+#include <stddef.h>
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
+#include "build/branding_buildflags.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "chrome/browser/prefs/chrome_pref_model_associator_client.h"
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/glue/sync_start_util.h"
+#include "chrome/browser/ui/profile_error_dialog.h"
+#include "chrome/common/buildflags.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/chromium_strings.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/component_updater/pref_names.h"
+#include "components/policy/core/browser/configuration_policy_pref_store.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/default_pref_store.h"
+#include "components/prefs/json_pref_store.h"
+#include "components/prefs/pref_filter.h"
+#include "components/prefs/pref_notifier_impl.h"
+#include "components/prefs/pref_registry.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_store.h"
+#include "components/prefs/pref_value_store.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/search_engines/default_search_manager.h"
+#include "components/search_engines/search_engines_pref_names.h"
+#include "components/signin/public/base/signin_pref_names.h"
+#include "components/sync/base/model_type.h"
+#include "components/sync/base/pref_names.h"
+#include "components/sync_preferences/pref_model_associator.h"
+#include "components/sync_preferences/pref_service_syncable.h"
+#include "components/sync_preferences/pref_service_syncable_factory.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "extensions/buildflags/buildflags.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "rlz/buildflags/buildflags.h"
+#include "services/preferences/public/cpp/tracked/configuration.h"
+#include "services/preferences/public/cpp/tracked/pref_names.h"
+#include "sql/error_delegate_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "extensions/browser/pref_names.h"
+#endif
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+#include "chrome/browser/supervised_user/supervised_user_pref_store.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/enterprise_util.h"
+#if BUILDFLAG(ENABLE_RLZ)
+#include "rlz/lib/machine_id.h"
+#endif // BUILDFLAG(ENABLE_RLZ)
+#endif // defined(OS_WIN)
+
+using content::BrowserContext;
+using content::BrowserThread;
+
+using EnforcementLevel =
+ prefs::mojom::TrackedPreferenceMetadata::EnforcementLevel;
+using PrefTrackingStrategy =
+ prefs::mojom::TrackedPreferenceMetadata::PrefTrackingStrategy;
+using ValueType = prefs::mojom::TrackedPreferenceMetadata::ValueType;
+
+namespace {
+
+#if defined(OS_WIN)
+// Whether we are in testing mode; can be enabled via
+// DisableDomainCheckForTesting(). Forces startup checks to ignore the presence
+// of a domain when determining the active SettingsEnforcement group.
+bool g_disable_domain_check_for_testing = false;
+#endif // OS_WIN
+
+// These preferences must be kept in sync with the TrackedPreference enum in
+// tools/metrics/histograms/enums.xml. To add a new preference, append it to the
+// array and add a corresponding value to the histogram enum. Each tracked
+// preference must be given a unique reporting ID.
+// See CleanupDeprecatedTrackedPreferences() in pref_hash_filter.cc to remove a
+// deprecated tracked preference.
+const prefs::TrackedPreferenceMetadata kTrackedPrefs[] = {
+ {0, prefs::kShowHomeButton, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+ {1, prefs::kHomePageIsNewTabPage, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+ {2, prefs::kHomePage, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+ {3, prefs::kRestoreOnStartup, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+ {4, prefs::kURLsToRestoreOnStartup, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+ {5, extensions::pref_names::kExtensions, EnforcementLevel::NO_ENFORCEMENT,
+ PrefTrackingStrategy::SPLIT, ValueType::IMPERSONAL},
+#endif
+ {6, prefs::kGoogleServicesLastUsername, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::PERSONAL},
+ {7, prefs::kSearchProviderOverrides, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#if !defined(OS_ANDROID)
+ {11, prefs::kPinnedTabs, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#endif
+ {14, DefaultSearchManager::kDefaultSearchProviderDataPrefName,
+ EnforcementLevel::NO_ENFORCEMENT, PrefTrackingStrategy::ATOMIC,
+ ValueType::IMPERSONAL},
+ {// Protecting kPreferenceResetTime does two things:
+ // 1) It ensures this isn't accidently set by someone stomping the pref
+ // file.
+ // 2) More importantly, it declares kPreferenceResetTime as a protected
+ // pref which is required for it to be visible when queried via the
+ // SegregatedPrefStore. This is because it's written directly in the
+ // protected JsonPrefStore by that store's PrefHashFilter if there was
+ // a reset in FilterOnLoad and SegregatedPrefStore will not look for it
+ // in the protected JsonPrefStore unless it's declared as a protected
+ // preference here.
+ 15, user_prefs::kPreferenceResetTime, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+ // kSyncRemainingRollbackTries is deprecated and will be removed a few
+ // releases after M50.
+ {18, prefs::kSafeBrowsingIncidentsSent, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#if defined(OS_WIN)
+ {19, prefs::kSwReporterPromptVersion, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#endif
+#if defined(OS_WIN)
+ {22, prefs::kSwReporterPromptSeed, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#endif
+ {23, prefs::kGoogleServicesAccountId, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::PERSONAL},
+ {24, prefs::kGoogleServicesLastAccountId, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::PERSONAL},
+#if defined(OS_WIN)
+ {25, prefs::kSettingsResetPromptPromptWave,
+ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
+ ValueType::IMPERSONAL},
+ {26, prefs::kSettingsResetPromptLastTriggeredForDefaultSearch,
+ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
+ ValueType::IMPERSONAL},
+ {27, prefs::kSettingsResetPromptLastTriggeredForStartupUrls,
+ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
+ ValueType::IMPERSONAL},
+ {28, prefs::kSettingsResetPromptLastTriggeredForHomepage,
+ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
+ ValueType::IMPERSONAL},
+#endif // defined(OS_WIN)
+ {29, prefs::kMediaStorageIdSalt, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ {30, prefs::kModuleBlacklistCacheMD5Digest,
+ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC,
+ ValueType::IMPERSONAL},
+#endif
+#if defined(OS_WIN)
+ {31, prefs::kSwReporterReportingEnabled, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL},
+#endif // defined(OS_WIN)
+
+ // See note at top, new items added here also need to be added to
+ // histograms.xml's TrackedPreference enum.
+};
+
+// One more than the last tracked preferences ID above.
+const size_t kTrackedPrefsReportingIDsCount =
+ kTrackedPrefs[base::size(kTrackedPrefs) - 1].reporting_id + 1;
+
+// Each group enforces a superset of the protection provided by the previous
+// one.
+enum SettingsEnforcementGroup {
+ GROUP_NO_ENFORCEMENT,
+ // Enforce protected settings on profile loads.
+ GROUP_ENFORCE_ALWAYS,
+ // Also enforce extension default search.
+ GROUP_ENFORCE_ALWAYS_WITH_DSE,
+ // Also enforce extension settings and default search.
+ GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE,
+ // The default enforcement group contains all protection features.
+ GROUP_ENFORCE_DEFAULT
+};
+
+SettingsEnforcementGroup GetSettingsEnforcementGroup() {
+# if defined(OS_WIN)
+ if (!g_disable_domain_check_for_testing) {
+ static bool first_call = true;
+ static const bool is_managed = base::IsMachineExternallyManaged();
+ if (first_call) {
+ UMA_HISTOGRAM_BOOLEAN("Settings.TrackedPreferencesNoEnforcementOnDomain",
+ is_managed);
+ first_call = false;
+ }
+ if (is_managed)
+ return GROUP_NO_ENFORCEMENT;
+ }
+#endif
+
+ struct {
+ const char* group_name;
+ SettingsEnforcementGroup group;
+ } static const kEnforcementLevelMap[] = {
+ { chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement,
+ GROUP_NO_ENFORCEMENT },
+ { chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways,
+ GROUP_ENFORCE_ALWAYS },
+ { chrome_prefs::internals::
+ kSettingsEnforcementGroupEnforceAlwaysWithDSE,
+ GROUP_ENFORCE_ALWAYS_WITH_DSE },
+ { chrome_prefs::internals::
+ kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE,
+ GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE },
+ };
+
+ // Use the strongest enforcement setting in the absence of a field trial
+ // config on Windows and MacOS. Remember to update the OFFICIAL_BUILD section
+ // of extension_startup_browsertest.cc and pref_hash_browsertest.cc when
+ // updating the default value below.
+ // TODO(gab): Enforce this on all platforms.
+ SettingsEnforcementGroup enforcement_group =
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ GROUP_ENFORCE_DEFAULT;
+#else
+ GROUP_NO_ENFORCEMENT;
+#endif
+ bool group_determined_from_trial = false;
+ base::FieldTrial* trial =
+ base::FieldTrialList::Find(
+ chrome_prefs::internals::kSettingsEnforcementTrialName);
+ if (trial) {
+ const std::string& group_name = trial->group_name();
+ for (size_t i = 0; i < base::size(kEnforcementLevelMap); ++i) {
+ if (kEnforcementLevelMap[i].group_name == group_name) {
+ enforcement_group = kEnforcementLevelMap[i].group;
+ group_determined_from_trial = true;
+ break;
+ }
+ }
+ }
+ UMA_HISTOGRAM_BOOLEAN("Settings.EnforcementGroupDeterminedFromTrial",
+ group_determined_from_trial);
+ return enforcement_group;
+}
+
+// Returns the effective preference tracking configuration.
+std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+GetTrackingConfiguration() {
+ const SettingsEnforcementGroup enforcement_group =
+ GetSettingsEnforcementGroup();
+
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr> result;
+ for (size_t i = 0; i < base::size(kTrackedPrefs); ++i) {
+ prefs::mojom::TrackedPreferenceMetadataPtr data =
+ prefs::ConstructTrackedMetadata(kTrackedPrefs[i]);
+
+ if (GROUP_NO_ENFORCEMENT == enforcement_group) {
+ // Remove enforcement for all tracked preferences.
+ data->enforcement_level = EnforcementLevel::NO_ENFORCEMENT;
+ }
+
+ if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_DSE &&
+ data->name ==
+ DefaultSearchManager::kDefaultSearchProviderDataPrefName) {
+ // Specifically enable default search settings enforcement.
+ data->enforcement_level = EnforcementLevel::ENFORCE_ON_LOAD;
+ }
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+ if (enforcement_group >= GROUP_ENFORCE_ALWAYS_WITH_EXTENSIONS_AND_DSE &&
+ data->name == extensions::pref_names::kExtensions) {
+ // Specifically enable extension settings enforcement.
+ data->enforcement_level = EnforcementLevel::ENFORCE_ON_LOAD;
+ }
+#endif
+
+ result.push_back(std::move(data));
+ }
+ return result;
+}
+
+std::unique_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
+ const base::FilePath& profile_path) {
+ std::string legacy_device_id;
+#if defined(OS_WIN) && BUILDFLAG(ENABLE_RLZ)
+ // This is used by
+ // chrome/browser/apps/platform_apps/api/music_manager_private/device_id_win.cc
+ // but that API is private (http://crbug.com/276485) and other platforms are
+ // not available synchronously.
+ // As part of improving pref metrics on other platforms we may want to find
+ // ways to defer preference loading until the device ID can be used.
+ rlz_lib::GetMachineId(&legacy_device_id);
+#endif
+ std::string seed;
+ CHECK(ui::ResourceBundle::HasSharedInstance());
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+ seed = ui::ResourceBundle::GetSharedInstance()
+ .GetRawDataResource(IDR_PREF_HASH_SEED_BIN)
+ .as_string();
+#endif
+ return std::make_unique<ProfilePrefStoreManager>(profile_path, seed,
+ legacy_device_id);
+}
+
+void PrepareFactory(sync_preferences::PrefServiceSyncableFactory* factory,
+ const base::FilePath& pref_filename,
+ policy::PolicyService* policy_service,
+ SupervisedUserSettingsService* supervised_user_settings,
+ scoped_refptr<PersistentPrefStore> user_pref_store,
+ scoped_refptr<PrefStore> extension_prefs,
+ bool async,
+ policy::BrowserPolicyConnector* policy_connector) {
+ factory->SetManagedPolicies(policy_service, policy_connector);
+ factory->SetRecommendedPolicies(policy_service, policy_connector);
+
+#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
+ if (supervised_user_settings) {
+ scoped_refptr<PrefStore> supervised_user_prefs =
+ base::MakeRefCounted<SupervisedUserPrefStore>(supervised_user_settings);
+ DCHECK(async || supervised_user_prefs->IsInitializationComplete());
+ factory->set_supervised_user_prefs(supervised_user_prefs);
+ }
+#endif
+
+ factory->set_async(async);
+ factory->set_extension_prefs(std::move(extension_prefs));
+ factory->set_command_line_prefs(
+ base::MakeRefCounted<ChromeCommandLinePrefStore>(
+ base::CommandLine::ForCurrentProcess()));
+ factory->set_read_error_callback(base::BindRepeating(
+ &chrome_prefs::HandlePersistentPrefStoreReadError, pref_filename));
+ factory->set_user_prefs(std::move(user_pref_store));
+ factory->SetPrefModelAssociatorClient(
+ ChromePrefModelAssociatorClient::GetInstance());
+}
+
+class ResetOnLoadObserverImpl : public prefs::mojom::ResetOnLoadObserver {
+ public:
+ explicit ResetOnLoadObserverImpl(const base::FilePath& profile_path)
+ : profile_path_(profile_path) {}
+
+ void OnResetOnLoad() override {
+ // A StartSyncFlare used to kick sync early in case of a reset event. This
+ // is done since sync may bring back the user's server value post-reset
+ // which could potentially cause a "settings flash" between the factory
+ // default and the re-instantiated server value. Starting sync ASAP
+ // minimizes the window before the server value is re-instantiated (this
+ // window can otherwise be as long as 10 seconds by default).
+ sync_start_util::GetFlareForSyncableService(profile_path_)
+ .Run(syncer::PREFERENCES);
+ }
+
+ private:
+ const base::FilePath profile_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResetOnLoadObserverImpl);
+};
+
+} // namespace
+
+namespace chrome_prefs {
+
+namespace internals {
+
+// Group modifications should be reflected in first_run_browsertest.cc and
+// pref_hash_browsertest.cc.
+const char kSettingsEnforcementTrialName[] = "SettingsEnforcement";
+const char kSettingsEnforcementGroupNoEnforcement[] = "no_enforcement";
+const char kSettingsEnforcementGroupEnforceAlways[] = "enforce_always";
+const char kSettingsEnforcementGroupEnforceAlwaysWithDSE[] =
+ "enforce_always_with_dse";
+const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE[] =
+ "enforce_always_with_extensions_and_dse";
+
+} // namespace internals
+
+std::unique_ptr<PrefService> CreateLocalState(
+ const base::FilePath& pref_filename,
+ policy::PolicyService* policy_service,
+ scoped_refptr<PrefRegistry> pref_registry,
+ bool async,
+ std::unique_ptr<PrefValueStore::Delegate> delegate,
+ policy::BrowserPolicyConnector* policy_connector) {
+ sync_preferences::PrefServiceSyncableFactory factory;
+ PrepareFactory(&factory, pref_filename, policy_service,
+ nullptr, // supervised_user_settings
+ base::MakeRefCounted<JsonPrefStore>(
+ pref_filename, std::unique_ptr<PrefFilter>()),
+ nullptr, // extension_prefs
+ async, policy_connector);
+
+ return factory.Create(std::move(pref_registry), std::move(delegate));
+}
+
+std::unique_ptr<sync_preferences::PrefServiceSyncable> CreateProfilePrefs(
+ const base::FilePath& profile_path,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate,
+ policy::PolicyService* policy_service,
+ SupervisedUserSettingsService* supervised_user_settings,
+ scoped_refptr<PrefStore> extension_prefs,
+ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
+ policy::BrowserPolicyConnector* connector,
+ bool async,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner,
+ std::unique_ptr<PrefValueStore::Delegate> delegate) {
+ TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
+
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver> reset_on_load_observer;
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<ResetOnLoadObserverImpl>(profile_path),
+ reset_on_load_observer.InitWithNewPipeAndPassReceiver());
+ sync_preferences::PrefServiceSyncableFactory factory;
+ scoped_refptr<PersistentPrefStore> user_pref_store =
+ CreateProfilePrefStoreManager(profile_path)
+ ->CreateProfilePrefStore(
+ GetTrackingConfiguration(), kTrackedPrefsReportingIDsCount,
+ std::move(io_task_runner), std::move(reset_on_load_observer),
+ std::move(validation_delegate));
+ PrepareFactory(&factory, profile_path, policy_service,
+ supervised_user_settings, std::move(user_pref_store),
+ std::move(extension_prefs), async, connector);
+ return factory.CreateSyncable(std::move(pref_registry), std::move(delegate));
+}
+
+void InstallPoliciesOnLocalState(
+ PrefService* preexisting_local_state,
+ policy::PolicyService* policy_service,
+ std::unique_ptr<PrefValueStore::Delegate> delegate) {
+ sync_preferences::PrefServiceSyncableFactory factory;
+ policy::BrowserPolicyConnector* policy_connector =
+ g_browser_process->browser_policy_connector();
+ factory.SetManagedPolicies(policy_service, policy_connector);
+ factory.SetRecommendedPolicies(policy_service, policy_connector);
+ factory.ChangePrefValueStore(preexisting_local_state, std::move(delegate));
+}
+
+void DisableDomainCheckForTesting() {
+#if defined(OS_WIN)
+ g_disable_domain_check_for_testing = true;
+#endif // OS_WIN
+}
+
+bool InitializePrefsFromMasterPrefs(
+ const base::FilePath& profile_path,
+ std::unique_ptr<base::DictionaryValue> master_prefs) {
+ return CreateProfilePrefStoreManager(profile_path)
+ ->InitializePrefsFromMasterPrefs(GetTrackingConfiguration(),
+ kTrackedPrefsReportingIDsCount,
+ std::move(master_prefs));
+}
+
+base::Time GetResetTime(Profile* profile) {
+ return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
+}
+
+void ClearResetTime(Profile* profile) {
+ ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
+}
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+ ProfilePrefStoreManager::RegisterProfilePrefs(registry);
+}
+
+void HandlePersistentPrefStoreReadError(
+ const base::FilePath& pref_filename,
+ PersistentPrefStore::PrefReadError error) {
+ // The error callback is always invoked back on the main thread (which is
+ // BrowserThread::UI unless called during early initialization before the main
+ // thread is promoted to BrowserThread::UI).
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
+ !BrowserThread::IsThreadInitialized(BrowserThread::UI));
+
+ // Sample the histogram also for the successful case in order to get a
+ // baseline on the success rate in addition to the error distribution.
+ UMA_HISTOGRAM_ENUMERATION("PrefService.ReadError", error,
+ PersistentPrefStore::PREF_READ_ERROR_MAX_ENUM);
+
+ if (error != PersistentPrefStore::PREF_READ_ERROR_NONE) {
+#if !defined(OS_CHROMEOS)
+ // Failing to load prefs on startup is a bad thing(TM). See bug 38352 for
+ // an example problem that this can cause.
+ // Do some diagnosis and try to avoid losing data.
+ int message_id = 0;
+ if (error <= PersistentPrefStore::PREF_READ_ERROR_JSON_TYPE) {
+ message_id = IDS_PREFERENCES_CORRUPT_ERROR;
+ } else if (error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
+ message_id = IDS_PREFERENCES_UNREADABLE_ERROR;
+ }
+
+ if (message_id) {
+ // Note: ThreadTaskRunnerHandle() is usually BrowserThread::UI but during
+ // early startup it can be ChromeBrowserMainParts::DeferringTaskRunner
+ // which will forward to BrowserThread::UI when it's initialized.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&ShowProfileErrorDialog, ProfileErrorType::PREFERENCES,
+ message_id,
+ sql::GetCorruptFileDiagnosticsInfo(pref_filename)));
+ }
+#else
+ // On ChromeOS error screen with message about broken local state
+ // will be displayed.
+
+ // A supplementary error message about broken local state - is included
+ // in logs and user feedbacks.
+ if (error != PersistentPrefStore::PREF_READ_ERROR_NONE &&
+ error != PersistentPrefStore::PREF_READ_ERROR_NO_FILE) {
+ LOG(ERROR) << "An error happened during prefs loading: " << error;
+ }
+#endif
+ }
+}
+
+} // namespace chrome_prefs
diff --git a/chromium/chrome/browser/prefs/chrome_pref_service_factory.h b/chromium/chrome/browser/prefs/chrome_pref_service_factory.h
new file mode 100644
index 00000000000..c86c0643f13
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_pref_service_factory.h
@@ -0,0 +1,130 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_CHROME_PREF_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_PREFS_CHROME_PREF_SERVICE_FACTORY_H_
+
+#include <memory>
+
+#include "base/memory/ref_counted.h"
+#include "components/prefs/persistent_pref_store.h"
+#include "components/prefs/pref_value_store.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom-forward.h"
+
+namespace base {
+class DictionaryValue;
+class FilePath;
+class SequencedTaskRunner;
+class Time;
+}
+
+namespace policy {
+class PolicyService;
+class BrowserPolicyConnector;
+}
+
+namespace sync_preferences {
+class PrefServiceSyncable;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+class PrefRegistry;
+class PrefService;
+
+class PrefStore;
+class Profile;
+class SupervisedUserSettingsService;
+
+namespace chrome_prefs {
+
+namespace internals {
+
+extern const char kSettingsEnforcementTrialName[];
+extern const char kSettingsEnforcementGroupNoEnforcement[];
+extern const char kSettingsEnforcementGroupEnforceAlways[];
+extern const char kSettingsEnforcementGroupEnforceAlwaysWithDSE[];
+extern const char kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE[];
+
+} // namespace internals
+
+// Factory methods that create and initialize a new instance of a
+// PrefService for Chrome with the applicable PrefStores. The
+// |pref_filename| points to the user preference file. This is the
+// usual way to create a new PrefService.
+// |extension_pref_store| is used as the source for extension-controlled
+// preferences and may be NULL.
+// |policy_service| is used as the source for mandatory or recommended
+// policies.
+// |pref_registry| keeps the list of registered prefs and their default values.
+// If |async| is true, asynchronous version is used.
+// Notifies using PREF_INITIALIZATION_COMPLETED in the end. Details is set to
+// the created PrefService or NULL if creation has failed. Note, it is
+// guaranteed that in asynchronous version initialization happens after this
+// function returned.
+std::unique_ptr<PrefService> CreateLocalState(
+ const base::FilePath& pref_filename,
+ policy::PolicyService* policy_service,
+ scoped_refptr<PrefRegistry> pref_registry,
+ bool async,
+ std::unique_ptr<PrefValueStore::Delegate> delegate,
+ policy::BrowserPolicyConnector* policy_connector);
+
+std::unique_ptr<sync_preferences::PrefServiceSyncable> CreateProfilePrefs(
+ const base::FilePath& pref_filename,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate,
+ policy::PolicyService* policy_service,
+ SupervisedUserSettingsService* supervised_user_settings,
+ scoped_refptr<PrefStore> extension_prefs,
+ scoped_refptr<user_prefs::PrefRegistrySyncable> pref_registry,
+ policy::BrowserPolicyConnector* connector,
+ bool async,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner,
+ std::unique_ptr<PrefValueStore::Delegate> delegate);
+
+// Installs policy related PrefStores on |preexisting_local_state|.
+// |preexisting_local_state| instance is a local state that has user PrefStore
+// and commandline PrefStore initialized. It is missing the mandatory and
+// recommended PrefStores and this method will add them to it.
+// |policy_service| is used as the source for mandatory or recommended
+// policies.
+// |delegate| is passed to listen to PrefStore initialization events.
+void InstallPoliciesOnLocalState(
+ PrefService* preexisting_local_state,
+ policy::PolicyService* policy_service,
+ std::unique_ptr<PrefValueStore::Delegate> delegate);
+
+// Call before startup tasks kick in to ignore the presence of a domain when
+// determining the active SettingsEnforcement group. For testing only.
+void DisableDomainCheckForTesting();
+
+// Initializes the preferences for the profile at |profile_path| with the
+// preference values in |master_prefs|. Returns true on success.
+bool InitializePrefsFromMasterPrefs(
+ const base::FilePath& profile_path,
+ std::unique_ptr<base::DictionaryValue> master_prefs);
+
+// Retrieves the time of the last preference reset event, if any, for the
+// provided profile. If no reset has occurred, returns a null |Time|.
+base::Time GetResetTime(Profile* profile);
+
+// Clears the time of the last preference reset event, if any, for the provided
+// profile.
+void ClearResetTime(Profile* profile);
+
+// Register user prefs used by chrome preference system.
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+// Shows notifications which correspond to PersistentPrefStore's reading errors.
+void HandlePersistentPrefStoreReadError(
+ const base::FilePath& pref_filename,
+ PersistentPrefStore::PrefReadError error);
+
+} // namespace chrome_prefs
+
+#endif // CHROME_BROWSER_PREFS_CHROME_PREF_SERVICE_FACTORY_H_
diff --git a/chromium/chrome/browser/prefs/chrome_pref_service_unittest.cc b/chromium/chrome/browser/prefs/chrome_pref_service_unittest.cc
new file mode 100644
index 00000000000..5e31462ccdd
--- /dev/null
+++ b/chromium/chrome/browser/prefs/chrome_pref_service_unittest.cc
@@ -0,0 +1,109 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/common/web_preferences.h"
+#include "content/public/test/test_renderer_host.h"
+
+using content::RenderViewHostTester;
+using content::WebPreferences;
+
+TEST(ChromePrefServiceTest, UpdateCommandLinePrefStore) {
+ TestingPrefServiceSimple prefs;
+ prefs.registry()->RegisterBooleanPref(prefs::kCloudPrintProxyEnabled, false);
+
+ // Check to make sure the value is as expected.
+ const PrefService::Preference* pref =
+ prefs.FindPreference(prefs::kCloudPrintProxyEnabled);
+ ASSERT_TRUE(pref);
+ const base::Value* value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(base::Value::Type::BOOLEAN, value->type());
+ bool actual_bool_value = true;
+ EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
+ EXPECT_FALSE(actual_bool_value);
+
+ // Change the command line.
+ base::CommandLine cmd_line(base::CommandLine::NO_PROGRAM);
+ cmd_line.AppendSwitch(switches::kEnableCloudPrintProxy);
+
+ // Call UpdateCommandLinePrefStore and check to see if the value has changed.
+ prefs.UpdateCommandLinePrefStore(new ChromeCommandLinePrefStore(&cmd_line));
+ pref = prefs.FindPreference(prefs::kCloudPrintProxyEnabled);
+ ASSERT_TRUE(pref);
+ value = pref->GetValue();
+ ASSERT_TRUE(value);
+ EXPECT_EQ(base::Value::Type::BOOLEAN, value->type());
+ actual_bool_value = false;
+ EXPECT_TRUE(value->GetAsBoolean(&actual_bool_value));
+ EXPECT_TRUE(actual_bool_value);
+}
+
+class ChromePrefServiceWebKitPrefs : public ChromeRenderViewHostTestHarness {
+ protected:
+ void SetUp() override {
+ ChromeRenderViewHostTestHarness::SetUp();
+
+ // Supply our own profile so we use the correct profile data. The test
+ // harness is not supposed to overwrite a profile if it's already created.
+
+ // Set some (WebKit) user preferences.
+ sync_preferences::TestingPrefServiceSyncable* pref_services =
+ profile()->GetTestingPrefService();
+ pref_services->SetUserPref(prefs::kDefaultCharset,
+ std::make_unique<base::Value>("utf8"));
+ pref_services->SetUserPref(prefs::kWebKitDefaultFontSize,
+ std::make_unique<base::Value>(20));
+ pref_services->SetUserPref(prefs::kWebKitTextAreasAreResizable,
+ std::make_unique<base::Value>(false));
+ pref_services->SetUserPref("webkit.webprefs.foo",
+ std::make_unique<base::Value>("bar"));
+ }
+};
+
+// Tests to see that webkit preferences are properly loaded and copied over
+// to a WebPreferences object.
+TEST_F(ChromePrefServiceWebKitPrefs, PrefsCopied) {
+ WebPreferences webkit_prefs =
+ RenderViewHostTester::For(rvh())->TestComputeWebPreferences();
+
+ // These values have been overridden by the profile preferences.
+ EXPECT_EQ("UTF-8", webkit_prefs.default_encoding);
+#if !defined(OS_ANDROID)
+ EXPECT_EQ(20, webkit_prefs.default_font_size);
+#else
+ // This pref is not configurable on Android so the default of 16 is always
+ // used.
+ EXPECT_EQ(16, webkit_prefs.default_font_size);
+#endif
+ EXPECT_FALSE(webkit_prefs.text_areas_are_resizable);
+
+ // These should still be the default values.
+#if defined(OS_MACOSX)
+ const char kDefaultFont[] = "Times";
+#elif defined(OS_CHROMEOS)
+ const char kDefaultFont[] = "Tinos";
+#else
+ const char kDefaultFont[] = "Times New Roman";
+#endif
+ EXPECT_EQ(base::ASCIIToUTF16(kDefaultFont),
+ webkit_prefs.standard_font_family_map[prefs::kWebKitCommonScript]);
+ EXPECT_TRUE(webkit_prefs.javascript_enabled);
+
+#if defined(OS_ANDROID)
+ // Touch event enabled only on Android.
+ EXPECT_TRUE(webkit_prefs.touch_event_feature_detection_enabled);
+#else
+ EXPECT_FALSE(webkit_prefs.touch_event_feature_detection_enabled);
+#endif
+}
diff --git a/chromium/chrome/browser/prefs/in_process_service_factory_factory.cc b/chromium/chrome/browser/prefs/in_process_service_factory_factory.cc
new file mode 100644
index 00000000000..326f1466915
--- /dev/null
+++ b/chromium/chrome/browser/prefs/in_process_service_factory_factory.cc
@@ -0,0 +1,41 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/in_process_service_factory_factory.h"
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/core/simple_dependency_manager.h"
+#include "services/preferences/public/cpp/in_process_service_factory.h"
+#include "services/service_manager/public/cpp/service.h"
+
+// static
+InProcessPrefServiceFactoryFactory*
+InProcessPrefServiceFactoryFactory::GetInstance() {
+ return base::Singleton<InProcessPrefServiceFactoryFactory>::get();
+}
+
+// static
+prefs::InProcessPrefServiceFactory*
+InProcessPrefServiceFactoryFactory::GetInstanceForKey(SimpleFactoryKey* key) {
+ return static_cast<prefs::InProcessPrefServiceFactory*>(
+ GetInstance()->GetServiceForKey(key, true));
+}
+
+InProcessPrefServiceFactoryFactory::InProcessPrefServiceFactoryFactory()
+ : SimpleKeyedServiceFactory("InProcessPrefServiceFactory",
+ SimpleDependencyManager::GetInstance()) {}
+
+InProcessPrefServiceFactoryFactory::~InProcessPrefServiceFactoryFactory() =
+ default;
+
+std::unique_ptr<KeyedService>
+InProcessPrefServiceFactoryFactory::BuildServiceInstanceFor(
+ SimpleFactoryKey* key) const {
+ return std::make_unique<prefs::InProcessPrefServiceFactory>();
+}
+
+SimpleFactoryKey* InProcessPrefServiceFactoryFactory::GetKeyToUse(
+ SimpleFactoryKey* key) const {
+ return key;
+}
diff --git a/chromium/chrome/browser/prefs/in_process_service_factory_factory.h b/chromium/chrome/browser/prefs/in_process_service_factory_factory.h
new file mode 100644
index 00000000000..5c9e7b3899d
--- /dev/null
+++ b/chromium/chrome/browser/prefs/in_process_service_factory_factory.h
@@ -0,0 +1,43 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_IN_PROCESS_SERVICE_FACTORY_FACTORY_H_
+#define CHROME_BROWSER_PREFS_IN_PROCESS_SERVICE_FACTORY_FACTORY_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "components/keyed_service/core/simple_keyed_service_factory.h"
+
+namespace base {
+template <typename T>
+struct DefaultSingletonTraits;
+}
+
+namespace prefs {
+class InProcessPrefServiceFactory;
+}
+
+class InProcessPrefServiceFactoryFactory : public SimpleKeyedServiceFactory {
+ public:
+ static InProcessPrefServiceFactoryFactory* GetInstance();
+
+ static prefs::InProcessPrefServiceFactory* GetInstanceForKey(
+ SimpleFactoryKey* key);
+
+ private:
+ friend struct base::DefaultSingletonTraits<
+ InProcessPrefServiceFactoryFactory>;
+
+ InProcessPrefServiceFactoryFactory();
+ ~InProcessPrefServiceFactoryFactory() override;
+
+ std::unique_ptr<KeyedService> BuildServiceInstanceFor(
+ SimpleFactoryKey* key) const override;
+ SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override;
+
+ DISALLOW_COPY_AND_ASSIGN(InProcessPrefServiceFactoryFactory);
+};
+
+#endif // CHROME_BROWSER_PREFS_IN_PROCESS_SERVICE_FACTORY_FACTORY_H_
diff --git a/chromium/chrome/browser/prefs/incognito_mode_prefs.cc b/chromium/chrome/browser/prefs/incognito_mode_prefs.cc
new file mode 100644
index 00000000000..881d7e6934a
--- /dev/null
+++ b/chromium/chrome/browser/prefs/incognito_mode_prefs.cc
@@ -0,0 +1,236 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
+
+#include <stdint.h>
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/task/post_task.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "base/time/time.h"
+#include "build/build_config.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "content/public/browser/browser_thread.h"
+
+#if defined(OS_WIN)
+#include <windows.h>
+#include <objbase.h>
+#include <wpcapi.h>
+#include <wrl/client.h>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/singleton.h"
+#endif // OS_WIN
+
+#if defined(OS_ANDROID)
+#include "chrome/browser/android/partner_browser_customizations.h"
+#endif // defined(OS_ANDROID)
+
+using content::BrowserThread;
+
+#if defined(OS_WIN)
+namespace {
+
+// This singleton allows us to attempt to calculate the Platform Parental
+// Controls enabled value on a worker thread before the UI thread needs the
+// value. If the UI thread finishes sooner than we expect, that's no worse than
+// today where we block.
+class PlatformParentalControlsValue {
+ public:
+ static PlatformParentalControlsValue* GetInstance() {
+ return base::Singleton<PlatformParentalControlsValue>::get();
+ }
+
+ bool is_enabled() const {
+ return is_enabled_;
+ }
+
+ private:
+ friend struct base::DefaultSingletonTraits<PlatformParentalControlsValue>;
+
+ // Histogram enum for tracking the thread that checked parental controls.
+ enum class ThreadType {
+ UI = 0,
+ BLOCKING,
+ COUNT,
+ };
+
+ PlatformParentalControlsValue()
+ : is_enabled_(IsParentalControlActivityLoggingOn()) {}
+
+ ~PlatformParentalControlsValue() = default;
+
+ // Returns true if Windows Parental control activity logging is enabled. This
+ // feature is available on Windows 7 and beyond. This function should be
+ // called on a COM Initialized thread and is potentially blocking.
+ static bool IsParentalControlActivityLoggingOn() {
+ ThreadType thread_type = ThreadType::BLOCKING;
+ if (BrowserThread::IsThreadInitialized(BrowserThread::UI) &&
+ content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
+ thread_type = ThreadType::UI;
+ }
+
+ UMA_HISTOGRAM_ENUMERATION(
+ "IncognitoModePrefs.WindowsParentalControlsInitThread",
+ static_cast<int32_t>(thread_type),
+ static_cast<int32_t>(ThreadType::COUNT));
+
+ base::Time begin_time = base::Time::Now();
+ bool result = IsParentalControlActivityLoggingOnImpl();
+ UMA_HISTOGRAM_TIMES("IncognitoModePrefs.WindowsParentalControlsInitTime",
+ base::Time::Now() - begin_time);
+ return result;
+ }
+
+ // Does the work of determining if Windows Parental control activity logging
+ // is enabled.
+ static bool IsParentalControlActivityLoggingOnImpl() {
+ // Since we can potentially block, make sure the thread is okay with this.
+ base::ScopedBlockingCall scoped_blocking_call(
+ FROM_HERE, base::BlockingType::MAY_BLOCK);
+ Microsoft::WRL::ComPtr<IWindowsParentalControlsCore> parent_controls;
+ HRESULT hr = ::CoCreateInstance(__uuidof(WindowsParentalControls), nullptr,
+ CLSCTX_ALL, IID_PPV_ARGS(&parent_controls));
+ if (FAILED(hr))
+ return false;
+
+ Microsoft::WRL::ComPtr<IWPCSettings> settings;
+ hr = parent_controls->GetUserSettings(nullptr, settings.GetAddressOf());
+ if (FAILED(hr))
+ return false;
+
+ unsigned long restrictions = 0;
+ settings->GetRestrictions(&restrictions);
+
+ return (restrictions & WPCFLAG_LOGGING_REQUIRED) ==
+ WPCFLAG_LOGGING_REQUIRED;
+ }
+
+ const bool is_enabled_;
+
+ DISALLOW_COPY_AND_ASSIGN(PlatformParentalControlsValue);
+};
+
+} // namespace
+#endif // OS_WIN
+
+// static
+// Sadly, this is required until c++17.
+constexpr IncognitoModePrefs::Availability
+ IncognitoModePrefs::kDefaultAvailability;
+
+// static
+bool IncognitoModePrefs::IntToAvailability(int in_value,
+ Availability* out_value) {
+ if (in_value < 0 || in_value >= AVAILABILITY_NUM_TYPES) {
+ *out_value = kDefaultAvailability;
+ return false;
+ }
+ *out_value = static_cast<Availability>(in_value);
+ return true;
+}
+
+// static
+IncognitoModePrefs::Availability IncognitoModePrefs::GetAvailability(
+ const PrefService* pref_service) {
+ return GetAvailabilityInternal(pref_service, CHECK_PARENTAL_CONTROLS);
+}
+
+// static
+void IncognitoModePrefs::SetAvailability(PrefService* prefs,
+ const Availability availability) {
+ prefs->SetInteger(prefs::kIncognitoModeAvailability, availability);
+}
+
+// static
+void IncognitoModePrefs::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterIntegerPref(prefs::kIncognitoModeAvailability,
+ kDefaultAvailability);
+}
+
+// static
+bool IncognitoModePrefs::ShouldLaunchIncognito(
+ const base::CommandLine& command_line,
+ const PrefService* prefs) {
+ // Note: This code only checks parental controls if the user requested
+ // to launch in incognito mode or if it was forced via prefs. This way,
+ // the parental controls check (which can be quite slow) can be avoided
+ // most of the time.
+ const bool should_use_incognito =
+ command_line.HasSwitch(switches::kIncognito) ||
+ GetAvailabilityInternal(prefs, DONT_CHECK_PARENTAL_CONTROLS) ==
+ IncognitoModePrefs::FORCED;
+ return should_use_incognito &&
+ GetAvailabilityInternal(prefs, CHECK_PARENTAL_CONTROLS) !=
+ IncognitoModePrefs::DISABLED;
+}
+
+// static
+bool IncognitoModePrefs::CanOpenBrowser(Profile* profile) {
+ if (profile->IsGuestSession())
+ return true;
+
+ switch (GetAvailability(profile->GetPrefs())) {
+ case IncognitoModePrefs::ENABLED:
+ return true;
+
+ case IncognitoModePrefs::DISABLED:
+ return !profile->IsOffTheRecord();
+
+ case IncognitoModePrefs::FORCED:
+ return profile->IsOffTheRecord();
+
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
+#if defined(OS_WIN)
+// static
+void IncognitoModePrefs::InitializePlatformParentalControls() {
+ base::CreateCOMSTATaskRunner(
+ {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE})
+ ->PostTask(FROM_HERE, base::BindOnce(base::IgnoreResult(
+ &PlatformParentalControlsValue::GetInstance)));
+}
+#endif
+
+// static
+bool IncognitoModePrefs::ArePlatformParentalControlsEnabled() {
+#if defined(OS_WIN)
+ return PlatformParentalControlsValue::GetInstance()->is_enabled();
+#elif defined(OS_ANDROID)
+ return chrome::android::PartnerBrowserCustomizations::IsIncognitoDisabled();
+#else
+ return false;
+#endif
+}
+
+// static
+IncognitoModePrefs::Availability IncognitoModePrefs::GetAvailabilityInternal(
+ const PrefService* pref_service,
+ GetAvailabilityMode mode) {
+ DCHECK(pref_service);
+ int pref_value = pref_service->GetInteger(prefs::kIncognitoModeAvailability);
+ Availability result = kDefaultAvailability;
+ bool valid = IntToAvailability(pref_value, &result);
+ DCHECK(valid);
+ if (result != IncognitoModePrefs::DISABLED &&
+ mode == CHECK_PARENTAL_CONTROLS && ArePlatformParentalControlsEnabled()) {
+ if (result == IncognitoModePrefs::FORCED)
+ LOG(ERROR) << "Ignoring FORCED incognito. Parental control logging on";
+ return IncognitoModePrefs::DISABLED;
+ }
+ return result;
+}
diff --git a/chromium/chrome/browser/prefs/incognito_mode_prefs.h b/chromium/chrome/browser/prefs/incognito_mode_prefs.h
new file mode 100644
index 00000000000..03ad9282af7
--- /dev/null
+++ b/chromium/chrome/browser/prefs/incognito_mode_prefs.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_INCOGNITO_MODE_PREFS_H_
+#define CHROME_BROWSER_PREFS_INCOGNITO_MODE_PREFS_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+
+class PrefService;
+class Profile;
+
+namespace base {
+class CommandLine;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+// Specifies Incognito mode availability preferences.
+class IncognitoModePrefs {
+ public:
+ // Possible values for Incognito mode availability. Please, do not change
+ // the order of entries since numeric values are exposed to users.
+ enum Availability {
+ // Incognito mode enabled. Users may open pages in both Incognito mode and
+ // normal mode (usually the default behaviour).
+ ENABLED = 0,
+ // Incognito mode disabled. Users may not open pages in Incognito mode.
+ // Only normal mode is available for browsing.
+ DISABLED,
+ // Incognito mode forced. Users may open pages *ONLY* in Incognito mode.
+ // Normal mode is not available for browsing.
+ FORCED,
+
+ AVAILABILITY_NUM_TYPES
+ };
+
+ static constexpr Availability kDefaultAvailability = ENABLED;
+
+ // Register incognito related preferences.
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Returns kIncognitoModeAvailability preference value stored
+ // in the given pref service.
+ static Availability GetAvailability(const PrefService* prefs);
+
+ // Sets kIncognitoModeAvailability preference to the specified availability
+ // value.
+ static void SetAvailability(PrefService* prefs,
+ const Availability availability);
+
+ // Converts in_value into the corresponding Availability value. Returns true
+ // if conversion is successful (in_value is valid). Otherwise, returns false
+ // and *out_value is set to ENABLED.
+ static bool IntToAvailability(int in_value, Availability* out_value);
+
+ // Returns true if the browser should start in incognito mode.
+ static bool ShouldLaunchIncognito(const base::CommandLine& command_line,
+ const PrefService* prefs);
+
+ // Returns true if |profile| can open a new Browser. This checks the incognito
+ // availability policies and verifies if the |profile| type is allowed to
+ // open new windows.
+ static bool CanOpenBrowser(Profile* profile);
+
+#if defined(OS_WIN)
+ // Calculates and caches the platform parental controls enable value on a
+ // worker thread.
+ static void InitializePlatformParentalControls();
+#endif
+
+ // Returns whether parental controls have been enabled on the platform. This
+ // method evaluates and caches if the platform controls have been enabled on
+ // the first call, which must be on the UI thread when IO and blocking are
+ // allowed. Subsequent calls may be from any thread.
+ static bool ArePlatformParentalControlsEnabled() WARN_UNUSED_RESULT;
+
+ private:
+ // Specifies whether parental controls should be checked. See comment below.
+ enum GetAvailabilityMode {
+ CHECK_PARENTAL_CONTROLS,
+ DONT_CHECK_PARENTAL_CONTROLS,
+ };
+
+ // Internal version of GetAvailability() that specifies whether parental
+ // controls should be checked (which is expensive and not always necessary
+ // to do - such as when checking for FORCED state).
+ static Availability GetAvailabilityInternal(const PrefService* pref_service,
+ GetAvailabilityMode mode);
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(IncognitoModePrefs);
+};
+
+#endif // CHROME_BROWSER_PREFS_INCOGNITO_MODE_PREFS_H_
diff --git a/chromium/chrome/browser/prefs/incognito_mode_prefs_unittest.cc b/chromium/chrome/browser/prefs/incognito_mode_prefs_unittest.cc
new file mode 100644
index 00000000000..0fe41caa0e1
--- /dev/null
+++ b/chromium/chrome/browser/prefs/incognito_mode_prefs_unittest.cc
@@ -0,0 +1,69 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
+
+#include "base/test/gtest_util.h"
+#include "chrome/common/pref_names.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class IncognitoModePrefsTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ IncognitoModePrefs::RegisterProfilePrefs(prefs_.registry());
+ }
+
+ sync_preferences::TestingPrefServiceSyncable prefs_;
+};
+
+TEST_F(IncognitoModePrefsTest, IntToAvailability) {
+ ASSERT_EQ(0, IncognitoModePrefs::ENABLED);
+ ASSERT_EQ(1, IncognitoModePrefs::DISABLED);
+ ASSERT_EQ(2, IncognitoModePrefs::FORCED);
+
+ IncognitoModePrefs::Availability incognito;
+ EXPECT_TRUE(IncognitoModePrefs::IntToAvailability(0, &incognito));
+ EXPECT_EQ(IncognitoModePrefs::ENABLED, incognito);
+ EXPECT_TRUE(IncognitoModePrefs::IntToAvailability(1, &incognito));
+ EXPECT_EQ(IncognitoModePrefs::DISABLED, incognito);
+ EXPECT_TRUE(IncognitoModePrefs::IntToAvailability(2, &incognito));
+ EXPECT_EQ(IncognitoModePrefs::FORCED, incognito);
+
+ EXPECT_FALSE(IncognitoModePrefs::IntToAvailability(10, &incognito));
+ EXPECT_EQ(IncognitoModePrefs::kDefaultAvailability, incognito);
+ EXPECT_FALSE(IncognitoModePrefs::IntToAvailability(-1, &incognito));
+ EXPECT_EQ(IncognitoModePrefs::kDefaultAvailability, incognito);
+}
+
+TEST_F(IncognitoModePrefsTest, GetAvailability) {
+ prefs_.SetUserPref(
+ prefs::kIncognitoModeAvailability,
+ std::make_unique<base::Value>(IncognitoModePrefs::ENABLED));
+ EXPECT_EQ(IncognitoModePrefs::ENABLED,
+ IncognitoModePrefs::GetAvailability(&prefs_));
+
+ prefs_.SetUserPref(
+ prefs::kIncognitoModeAvailability,
+ std::make_unique<base::Value>(IncognitoModePrefs::DISABLED));
+ EXPECT_EQ(IncognitoModePrefs::DISABLED,
+ IncognitoModePrefs::GetAvailability(&prefs_));
+
+ prefs_.SetUserPref(prefs::kIncognitoModeAvailability,
+ std::make_unique<base::Value>(IncognitoModePrefs::FORCED));
+ EXPECT_EQ(IncognitoModePrefs::FORCED,
+ IncognitoModePrefs::GetAvailability(&prefs_));
+}
+
+typedef IncognitoModePrefsTest IncognitoModePrefsDeathTest;
+
+TEST_F(IncognitoModePrefsDeathTest, GetAvailabilityBadValue) {
+ prefs_.SetUserPref(prefs::kIncognitoModeAvailability,
+ std::make_unique<base::Value>(-1));
+ EXPECT_DCHECK_DEATH({
+ IncognitoModePrefs::Availability availability =
+ IncognitoModePrefs::GetAvailability(&prefs_);
+ EXPECT_EQ(IncognitoModePrefs::ENABLED, availability);
+ });
+}
diff --git a/chromium/chrome/browser/prefs/origin_trial_prefs.cc b/chromium/chrome/browser/prefs/origin_trial_prefs.cc
new file mode 100644
index 00000000000..65e2407d31f
--- /dev/null
+++ b/chromium/chrome/browser/prefs/origin_trial_prefs.cc
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/origin_trial_prefs.h"
+
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+
+// static
+void OriginTrialPrefs::RegisterPrefs(PrefRegistrySimple* registry) {
+ registry->RegisterStringPref(prefs::kOriginTrialPublicKey, "");
+ registry->RegisterListPref(prefs::kOriginTrialDisabledFeatures);
+ registry->RegisterListPref(prefs::kOriginTrialDisabledTokens);
+}
diff --git a/chromium/chrome/browser/prefs/origin_trial_prefs.h b/chromium/chrome/browser/prefs/origin_trial_prefs.h
new file mode 100644
index 00000000000..3e8baafb666
--- /dev/null
+++ b/chromium/chrome/browser/prefs/origin_trial_prefs.h
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_ORIGIN_TRIAL_PREFS_H_
+#define CHROME_BROWSER_PREFS_ORIGIN_TRIAL_PREFS_H_
+
+class PrefRegistrySimple;
+
+class OriginTrialPrefs {
+ public:
+ static void RegisterPrefs(PrefRegistrySimple* registry);
+};
+
+#endif // CHROME_BROWSER_PREFS_ORIGIN_TRIAL_PREFS_H_
diff --git a/chromium/chrome/browser/prefs/pref_functional_browsertest.cc b/chromium/chrome/browser/prefs/pref_functional_browsertest.cc
new file mode 100644
index 00000000000..00fac2797cb
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_functional_browsertest.cc
@@ -0,0 +1,246 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+#include "chrome/browser/download/download_prefs.h"
+#include "chrome/browser/net/prediction_options.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/content_settings/core/browser/website_settings_info.h"
+#include "components/content_settings/core/browser/website_settings_registry.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/safe_browsing/common/safe_browsing_prefs.h"
+#include "components/sync_preferences/pref_service_syncable.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/download_test_observer.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+using content::BrowserContext;
+using content::DownloadManager;
+
+class PrefsFunctionalTest : public InProcessBrowserTest {
+ protected:
+ // Create a DownloadTestObserverTerminal that will wait for the
+ // specified number of downloads to finish.
+ std::unique_ptr<content::DownloadTestObserver> CreateWaiter(
+ Browser* browser,
+ int num_downloads) {
+ DownloadManager* download_manager =
+ BrowserContext::GetDownloadManager(browser->profile());
+
+ content::DownloadTestObserver* downloads_observer =
+ new content::DownloadTestObserverTerminal(
+ download_manager,
+ num_downloads,
+ content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL);
+ return base::WrapUnique(downloads_observer);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestDownloadDirPref) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ base::FilePath new_download_dir =
+ DownloadPrefs(browser()->profile()).DownloadPath().AppendASCII("subdir");
+ base::FilePath downloaded_pkg =
+ new_download_dir.AppendASCII("a_zip_file.zip");
+
+ // Set pref to download in new_download_dir.
+ browser()->profile()->GetPrefs()->SetFilePath(
+ prefs::kDownloadDefaultDirectory, new_download_dir);
+
+ // Create a downloads observer.
+ std::unique_ptr<content::DownloadTestObserver> downloads_observer(
+ CreateWaiter(browser(), 1));
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/downloads/a_zip_file.zip"));
+ // Waits for the download to complete.
+ downloads_observer->WaitForFinished();
+
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ EXPECT_TRUE(base::PathExists(downloaded_pkg));
+}
+
+// Verify image content settings show or hide images.
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestImageContentSettings) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/settings/image_page.html"));
+
+ bool result = false;
+ std::string script =
+ "for (i=0; i < document.images.length; i++) {"
+ " if ((document.images[i].naturalWidth != 0) &&"
+ " (document.images[i].naturalHeight != 0)) {"
+ " window.domAutomationController.send(true);"
+ " }"
+ "}"
+ "window.domAutomationController.send(false);";
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ script,
+ &result));
+ EXPECT_TRUE(result);
+
+ browser()->profile()->GetPrefs()->SetInteger(
+ content_settings::WebsiteSettingsRegistry::GetInstance()
+ ->Get(CONTENT_SETTINGS_TYPE_IMAGES)
+ ->default_value_pref_name(),
+ CONTENT_SETTING_BLOCK);
+
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/settings/image_page.html"));
+
+ result = false;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+ browser()->tab_strip_model()->GetActiveWebContents(),
+ script,
+ &result));
+ EXPECT_FALSE(result);
+}
+
+// Verify that enabling/disabling Javascript in prefs works.
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestJavascriptEnableDisable) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
+ prefs::kWebKitJavascriptEnabled));
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/javaScriptTitle.html"));
+ EXPECT_EQ(base::ASCIIToUTF16("Title from script javascript enabled"),
+ browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
+ browser()->profile()->GetPrefs()->SetBoolean(prefs::kWebKitJavascriptEnabled,
+ false);
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL("/javaScriptTitle.html"));
+ EXPECT_EQ(base::ASCIIToUTF16("This is html title"),
+ browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
+}
+
+// Verify restore for bookmark bar visibility.
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest,
+ TestSessionRestoreShowBookmarkBar) {
+ EXPECT_FALSE(browser()->profile()->GetPrefs()->GetBoolean(
+ bookmarks::prefs::kShowBookmarkBar));
+ browser()->profile()->GetPrefs()->SetBoolean(
+ bookmarks::prefs::kShowBookmarkBar, true);
+ EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
+ bookmarks::prefs::kShowBookmarkBar));
+
+ EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
+ bookmarks::prefs::kShowBookmarkBar));
+ EXPECT_EQ(BookmarkBar::SHOW, browser()->bookmark_bar_state());
+}
+
+// Verify images are not blocked in incognito mode.
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestImagesNotBlockedInIncognito) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL url = embedded_test_server()->GetURL("/settings/image_page.html");
+ Browser* incognito_browser = CreateIncognitoBrowser();
+ ui_test_utils::NavigateToURL(incognito_browser, url);
+
+ bool result = false;
+ std::string script =
+ "for (i=0; i < document.images.length; i++) {"
+ " if ((document.images[i].naturalWidth != 0) &&"
+ " (document.images[i].naturalHeight != 0)) {"
+ " window.domAutomationController.send(true);"
+ " }"
+ "}"
+ "window.domAutomationController.send(false);";
+ EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+ incognito_browser->tab_strip_model()->GetActiveWebContents(),
+ script,
+ &result));
+ EXPECT_TRUE(result);
+}
+
+// Verify setting homepage preference to newtabpage across restarts. Part1
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, PRE_TestHomepageNewTabpagePrefs) {
+ browser()->profile()->GetPrefs()->SetBoolean(prefs::kHomePageIsNewTabPage,
+ true);
+}
+
+// Verify setting homepage preference to newtabpage across restarts. Part2
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestHomepageNewTabpagePrefs) {
+ EXPECT_TRUE(browser()->profile()->GetPrefs()->GetBoolean(
+ prefs::kHomePageIsNewTabPage));
+}
+
+// Verify setting homepage preference to specific url. Part1
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, PRE_TestHomepagePrefs) {
+ GURL home_page_url("http://www.google.com");
+
+ PrefService* prefs = browser()->profile()->GetPrefs();
+ prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
+ const PrefService::Preference* pref =
+ prefs->FindPreference(prefs::kHomePage);
+ if (pref && !pref->IsManaged()) {
+ prefs->SetString(prefs::kHomePage, home_page_url.spec());
+ }
+}
+
+// Verify setting homepage preference to specific url. Part2
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestHomepagePrefs) {
+ GURL home_page_url("http://www.google.com");
+
+ PrefService* prefs = browser()->profile()->GetPrefs();
+ EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
+ EXPECT_EQ(home_page_url.spec(), prefs->GetString(prefs::kHomePage));
+}
+
+// Verify the security preference under privacy across restarts. Part1
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, PRE_TestPrivacySecurityPrefs) {
+ PrefService* prefs = browser()->profile()->GetPrefs();
+
+ static_assert(chrome_browser_net::NETWORK_PREDICTION_DEFAULT !=
+ chrome_browser_net::NETWORK_PREDICTION_NEVER,
+ "PrefsFunctionalTest.TestPrivacySecurityPrefs relies on "
+ "predictive network actions being enabled by default.");
+ EXPECT_EQ(chrome_browser_net::NETWORK_PREDICTION_DEFAULT,
+ prefs->GetInteger(prefs::kNetworkPredictionOptions));
+ prefs->SetInteger(prefs::kNetworkPredictionOptions,
+ chrome_browser_net::NETWORK_PREDICTION_NEVER);
+
+ EXPECT_TRUE(prefs->GetBoolean(prefs::kSafeBrowsingEnabled));
+ prefs->SetBoolean(prefs::kSafeBrowsingEnabled, false);
+
+ EXPECT_TRUE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
+ prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false);
+
+ EXPECT_TRUE(prefs->GetBoolean(prefs::kSearchSuggestEnabled));
+ prefs->SetBoolean(prefs::kSearchSuggestEnabled, false);
+}
+
+// Verify the security preference under privacy across restarts. Part2
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestPrivacySecurityPrefs) {
+ PrefService* prefs = browser()->profile()->GetPrefs();
+
+ EXPECT_EQ(chrome_browser_net::NETWORK_PREDICTION_NEVER,
+ prefs->GetInteger(prefs::kNetworkPredictionOptions));
+ EXPECT_FALSE(prefs->GetBoolean(prefs::kSafeBrowsingEnabled));
+ EXPECT_FALSE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
+ EXPECT_FALSE(prefs->GetBoolean(prefs::kSearchSuggestEnabled));
+}
+
+// Verify that we have some Local State prefs.
+IN_PROC_BROWSER_TEST_F(PrefsFunctionalTest, TestHaveLocalStatePrefs) {
+ EXPECT_TRUE(g_browser_process->local_state()
+ ->GetPreferenceValues(PrefService::INCLUDE_DEFAULTS)
+ .get());
+}
diff --git a/chromium/chrome/browser/prefs/pref_metrics_service.cc b/chromium/chrome/browser/prefs/pref_metrics_service.cc
new file mode 100644
index 00000000000..f321fa5c75d
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_metrics_service.cc
@@ -0,0 +1,189 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/pref_metrics_service.h"
+
+#include <string>
+
+#include "base/metrics/histogram_macros.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/ui/tabs/pinned_tab_codec.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/prefs/pref_service.h"
+#include "components/rappor/public/rappor_utils.h"
+#include "components/rappor/rappor_service_impl.h"
+#include "components/search_engines/template_url_prepopulate_data.h"
+#include "content/public/browser/browser_url_handler.h"
+#include "url/gurl.h"
+
+namespace {
+
+#if !defined(OS_ANDROID)
+// Record a sample for the Settings.NewTabPage rappor metric.
+void SampleNewTabPageURL(Profile* profile) {
+ GURL ntp_url(chrome::kChromeUINewTabURL);
+ bool reverse_on_redirect = false;
+ content::BrowserURLHandler::GetInstance()->RewriteURLIfNecessary(
+ &ntp_url,
+ profile,
+ &reverse_on_redirect);
+ if (ntp_url.is_valid()) {
+ rappor::SampleDomainAndRegistryFromGURL(g_browser_process->rappor_service(),
+ "Settings.NewTabPage", ntp_url);
+ }
+}
+#endif
+
+} // namespace
+
+PrefMetricsService::PrefMetricsService(Profile* profile)
+ : profile_(profile), prefs_(profile_->GetPrefs()) {
+ RecordLaunchPrefs();
+}
+
+PrefMetricsService::~PrefMetricsService() {
+}
+
+// static
+void PrefMetricsService::RecordHomePageLaunchMetrics(bool show_home_button,
+ bool homepage_is_ntp,
+ const GURL& homepage_url) {
+ UMA_HISTOGRAM_BOOLEAN("Settings.ShowHomeButton", show_home_button);
+ if (show_home_button) {
+ UMA_HISTOGRAM_BOOLEAN("Settings.GivenShowHomeButton_HomePageIsNewTabPage",
+ homepage_is_ntp);
+ }
+
+ // For non-NTP homepages, see if the URL comes from the same TLD+1 as a known
+ // search engine. Note that this is only an approximation of search engine
+ // use, due to both false negatives (pages that come from unknown TLD+1 X but
+ // consist of a search box that sends to known TLD+1 Y) and false positives
+ // (pages that share a TLD+1 with a known engine but aren't actually search
+ // pages, e.g. plus.google.com). Additionally, record the TLD+1 of non-NTP
+ // homepages through the privacy-preserving Rappor service.
+ if (!homepage_is_ntp) {
+ if (homepage_url.is_valid()) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Settings.HomePageEngineType",
+ TemplateURLPrepopulateData::GetEngineType(homepage_url),
+ SEARCH_ENGINE_MAX);
+ rappor::SampleDomainAndRegistryFromGURL(
+ g_browser_process->rappor_service(), "Settings.HomePage2",
+ homepage_url);
+ }
+ }
+}
+
+void PrefMetricsService::RecordLaunchPrefs() {
+ // On Android, determining whether the homepage is enabled requires waiting
+ // for a response from a third party provider installed on the device. So,
+ // it will be logged later once all the dependent information is available.
+ // See DeferredStartupHandler.java.
+#if !defined(OS_ANDROID)
+ GURL homepage_url(prefs_->GetString(prefs::kHomePage));
+ RecordHomePageLaunchMetrics(prefs_->GetBoolean(prefs::kShowHomeButton),
+ prefs_->GetBoolean(prefs::kHomePageIsNewTabPage),
+ homepage_url);
+#endif
+
+ // Android does not support overriding the NTP URL.
+#if !defined(OS_ANDROID)
+ SampleNewTabPageURL(profile_);
+#endif
+
+ // Tab restoring is always done on Android, so these metrics are not
+ // applicable. Also, startup pages are not supported on Android
+#if !defined(OS_ANDROID)
+ int restore_on_startup = prefs_->GetInteger(prefs::kRestoreOnStartup);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Settings.StartupPageLoadSettings", restore_on_startup,
+ static_cast<int>(SessionStartupPref::kPrefValueMax));
+ if (restore_on_startup == SessionStartupPref::kPrefValueURLs) {
+ const base::ListValue* url_list =
+ prefs_->GetList(prefs::kURLsToRestoreOnStartup);
+ // Similarly, check startup pages for known search engine TLD+1s.
+ std::string url_text;
+ for (size_t i = 0; i < url_list->GetSize(); ++i) {
+ if (url_list->GetString(i, &url_text)) {
+ GURL start_url(url_text);
+ if (start_url.is_valid()) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Settings.StartupPageEngineTypes",
+ TemplateURLPrepopulateData::GetEngineType(start_url),
+ SEARCH_ENGINE_MAX);
+ if (i == 0) {
+ rappor::SampleDomainAndRegistryFromGURL(
+ g_browser_process->rappor_service(),
+ "Settings.FirstStartupPage", start_url);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ // Android does not support pinned tabs.
+#if !defined(OS_ANDROID)
+ StartupTabs startup_tabs = PinnedTabCodec::ReadPinnedTabs(profile_);
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Settings.PinnedTabs",
+ startup_tabs.size(), 1, 50, 20);
+ for (size_t i = 0; i < startup_tabs.size(); ++i) {
+ GURL start_url(startup_tabs.at(i).url);
+ if (start_url.is_valid()) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Settings.PinnedTabEngineTypes",
+ TemplateURLPrepopulateData::GetEngineType(start_url),
+ SEARCH_ENGINE_MAX);
+ }
+ }
+#endif
+}
+
+// static
+PrefMetricsService::Factory* PrefMetricsService::Factory::GetInstance() {
+ return base::Singleton<PrefMetricsService::Factory>::get();
+}
+
+// static
+PrefMetricsService* PrefMetricsService::Factory::GetForProfile(
+ Profile* profile) {
+ return static_cast<PrefMetricsService*>(
+ GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+PrefMetricsService::Factory::Factory()
+ : BrowserContextKeyedServiceFactory(
+ "PrefMetricsService",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(TemplateURLServiceFactory::GetInstance());
+}
+
+PrefMetricsService::Factory::~Factory() {
+}
+
+KeyedService* PrefMetricsService::Factory::BuildServiceInstanceFor(
+ content::BrowserContext* profile) const {
+ return new PrefMetricsService(static_cast<Profile*>(profile));
+}
+
+bool PrefMetricsService::Factory::ServiceIsCreatedWithBrowserContext() const {
+ return true;
+}
+
+bool PrefMetricsService::Factory::ServiceIsNULLWhileTesting() const {
+ return false;
+}
+
+content::BrowserContext* PrefMetricsService::Factory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
diff --git a/chromium/chrome/browser/prefs/pref_metrics_service.h b/chromium/chrome/browser/prefs/pref_metrics_service.h
new file mode 100644
index 00000000000..a1864def73f
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_metrics_service.h
@@ -0,0 +1,60 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
+#define CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "url/gurl.h"
+
+class PrefService;
+class Profile;
+
+// PrefMetricsService is responsible for recording prefs-related UMA stats.
+class PrefMetricsService : public KeyedService {
+ public:
+ explicit PrefMetricsService(Profile* profile);
+ ~PrefMetricsService() override;
+
+ // Records metrics about the state of the homepage on launch.
+ static void RecordHomePageLaunchMetrics(bool show_home_button,
+ bool homepage_is_ntp,
+ const GURL& homepage_url);
+
+ class Factory : public BrowserContextKeyedServiceFactory {
+ public:
+ static Factory* GetInstance();
+ static PrefMetricsService* GetForProfile(Profile* profile);
+ private:
+ friend struct base::DefaultSingletonTraits<Factory>;
+
+ Factory();
+ ~Factory() override;
+
+ // BrowserContextKeyedServiceFactory implementation
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* profile) const override;
+ bool ServiceIsCreatedWithBrowserContext() const override;
+ bool ServiceIsNULLWhileTesting() const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+ };
+
+ private:
+ // Record prefs state on browser context creation.
+ void RecordLaunchPrefs();
+
+ Profile* profile_;
+ PrefService* prefs_;
+
+ base::WeakPtrFactory<PrefMetricsService> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(PrefMetricsService);
+};
+
+#endif // CHROME_BROWSER_PREFS_PREF_METRICS_SERVICE_H_
diff --git a/chromium/chrome/browser/prefs/pref_service_browsertest.cc b/chromium/chrome/browser/prefs/pref_service_browsertest.cc
new file mode 100644
index 00000000000..ccfd545b870
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_service_browsertest.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/path_service.h"
+#include "base/test/test_file_util.h"
+#include "base/threading/thread_restrictions.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/browser_window_state.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "ui/gfx/geometry/rect.h"
+
+typedef InProcessBrowserTest PreservedWindowPlacement;
+
+IN_PROC_BROWSER_TEST_F(PreservedWindowPlacement, PRE_Test) {
+ browser()->window()->SetBounds(gfx::Rect(20, 30, 600, 600));
+}
+
+// Fails on Chrome OS as the browser thinks it is restarting after a crash, see
+// http://crbug.com/168044
+#if defined(OS_CHROMEOS)
+#define MAYBE_Test DISABLED_Test
+#else
+#define MAYBE_Test Test
+#endif
+IN_PROC_BROWSER_TEST_F(PreservedWindowPlacement, MAYBE_Test) {
+ gfx::Rect bounds = browser()->window()->GetBounds();
+ gfx::Rect expected_bounds(gfx::Rect(20, 30, 600, 600));
+ ASSERT_EQ(expected_bounds.ToString(), bounds.ToString());
+}
+
+class PreferenceServiceTest : public InProcessBrowserTest {
+ public:
+ bool SetUpUserDataDirectory() override {
+ base::FilePath user_data_directory;
+ base::PathService::Get(chrome::DIR_USER_DATA, &user_data_directory);
+
+ original_pref_file_ = ui_test_utils::GetTestFilePath(
+ base::FilePath()
+ .AppendASCII("profiles")
+ .AppendASCII("window_placement")
+ .AppendASCII("Default"),
+ base::FilePath().Append(chrome::kPreferencesFilename));
+ tmp_pref_file_ =
+ user_data_directory.AppendASCII(TestingProfile::kTestUserProfileDir);
+ EXPECT_TRUE(base::CreateDirectory(tmp_pref_file_));
+ tmp_pref_file_ = tmp_pref_file_.Append(chrome::kPreferencesFilename);
+
+ EXPECT_TRUE(base::PathExists(original_pref_file_));
+ EXPECT_TRUE(base::CopyFile(original_pref_file_, tmp_pref_file_));
+
+#if defined(OS_WIN)
+ // Make the copy writable. On POSIX we assume the umask allows files
+ // we create to be writable.
+ EXPECT_TRUE(::SetFileAttributesW(tmp_pref_file_.value().c_str(),
+ FILE_ATTRIBUTE_NORMAL));
+#endif
+ return true;
+ }
+
+ protected:
+ base::FilePath original_pref_file_;
+ base::FilePath tmp_pref_file_;
+};
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+// This test verifies that the window position from the prefs file is restored
+// when the app restores. This doesn't really make sense on Linux, where
+// the window manager might fight with you over positioning. However, we
+// might be able to make this work on buildbots.
+// TODO(port): revisit this.
+
+IN_PROC_BROWSER_TEST_F(PreferenceServiceTest, Test) {
+ // The window should open with the new reference profile, with window
+ // placement values stored in the user data directory.
+ JSONFileValueDeserializer deserializer(original_pref_file_);
+ std::unique_ptr<base::Value> root;
+ {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ root = deserializer.Deserialize(NULL, NULL);
+ }
+
+ ASSERT_TRUE(root.get());
+ ASSERT_TRUE(root->is_dict());
+
+ base::DictionaryValue* root_dict =
+ static_cast<base::DictionaryValue*>(root.get());
+
+ // Retrieve the screen rect for the launched window
+ gfx::Rect bounds = browser()->window()->GetRestoredBounds();
+
+ // Retrieve the expected rect values from "Preferences"
+ int bottom = 0;
+ std::string kBrowserWindowPlacement(prefs::kBrowserWindowPlacement);
+ EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".bottom",
+ &bottom));
+ EXPECT_EQ(bottom, bounds.y() + bounds.height());
+
+ int top = 0;
+ EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".top",
+ &top));
+ EXPECT_EQ(top, bounds.y());
+
+ int left = 0;
+ EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".left",
+ &left));
+ EXPECT_EQ(left, bounds.x());
+
+ int right = 0;
+ EXPECT_TRUE(root_dict->GetInteger(kBrowserWindowPlacement + ".right",
+ &right));
+ EXPECT_EQ(right, bounds.x() + bounds.width());
+
+ // Find if launched window is maximized.
+ bool is_window_maximized = browser()->window()->IsMaximized();
+ bool is_maximized = false;
+ EXPECT_TRUE(root_dict->GetBoolean(kBrowserWindowPlacement + ".maximized",
+ &is_maximized));
+ EXPECT_EQ(is_maximized, is_window_maximized);
+}
+#endif
diff --git a/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc
new file mode 100644
index 00000000000..0206ea78562
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -0,0 +1,229 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/pref_service_incognito_whitelist.h"
+
+#include <vector>
+
+#include "base/stl_util.h"
+#include "build/build_config.h"
+#include "chrome/common/pref_names.h"
+#include "components/bookmarks/common/bookmark_pref_names.h"
+#include "components/content_settings/core/common/pref_names.h"
+#include "components/metrics/metrics_pref_names.h"
+#include "components/rappor/rappor_pref_names.h"
+#include "components/reading_list/core/reading_list_pref_names.h"
+#include "components/ukm/ukm_pref_names.h"
+
+#if !defined(OS_ANDROID)
+#include "chrome/browser/accessibility/animation_policy_prefs.h"
+#endif // !defined(OS_ANDROID)
+
+#if defined(OS_CHROMEOS)
+#include "ash/public/cpp/ash_pref_names.h"
+#endif // defined(OS_CHROMEOS)
+
+namespace {
+
+// List of keys that can be changed in the user prefs file by the incognito
+// profile.
+const char* const kPersistentPrefNames[] = {
+#if defined(OS_CHROMEOS)
+ // Accessibility preferences should be persisted if they are changed in
+ // incognito mode.
+ ash::prefs::kAccessibilityLargeCursorEnabled,
+ ash::prefs::kAccessibilityLargeCursorDipSize,
+ ash::prefs::kAccessibilityStickyKeysEnabled,
+ ash::prefs::kAccessibilitySpokenFeedbackEnabled,
+ ash::prefs::kAccessibilityHighContrastEnabled,
+ ash::prefs::kAccessibilityScreenMagnifierCenterFocus,
+ ash::prefs::kAccessibilityScreenMagnifierEnabled,
+ ash::prefs::kAccessibilityScreenMagnifierScale,
+ ash::prefs::kAccessibilityVirtualKeyboardEnabled,
+ ash::prefs::kAccessibilityMonoAudioEnabled,
+ ash::prefs::kAccessibilityAutoclickEnabled,
+ ash::prefs::kAccessibilityAutoclickDelayMs,
+ ash::prefs::kAccessibilityAutoclickEventType,
+ ash::prefs::kAccessibilityAutoclickRevertToLeftClick,
+ ash::prefs::kAccessibilityAutoclickStabilizePosition,
+ ash::prefs::kAccessibilityAutoclickMovementThreshold,
+ ash::prefs::kAccessibilityCaretHighlightEnabled,
+ ash::prefs::kAccessibilityCursorHighlightEnabled,
+ ash::prefs::kAccessibilityFocusHighlightEnabled,
+ ash::prefs::kAccessibilitySelectToSpeakEnabled,
+ ash::prefs::kAccessibilitySwitchAccessEnabled,
+ ash::prefs::kAccessibilitySwitchAccessSelectKeyCodes,
+ ash::prefs::kAccessibilitySwitchAccessSelectSetting,
+ ash::prefs::kAccessibilitySwitchAccessNextKeyCodes,
+ ash::prefs::kAccessibilitySwitchAccessNextSetting,
+ ash::prefs::kAccessibilitySwitchAccessPreviousKeyCodes,
+ ash::prefs::kAccessibilitySwitchAccessPreviousSetting,
+ ash::prefs::kAccessibilitySwitchAccessAutoScanEnabled,
+ ash::prefs::kAccessibilitySwitchAccessAutoScanSpeedMs,
+ ash::prefs::kAccessibilitySwitchAccessAutoScanKeyboardSpeedMs,
+ ash::prefs::kAccessibilityDictationEnabled,
+ ash::prefs::kDockedMagnifierEnabled,
+ ash::prefs::kDockedMagnifierScale,
+ ash::prefs::kDockedMagnifierAcceleratorDialogHasBeenAccepted,
+ ash::prefs::kHighContrastAcceleratorDialogHasBeenAccepted,
+ ash::prefs::kScreenMagnifierAcceleratorDialogHasBeenAccepted,
+ ash::prefs::kShouldAlwaysShowAccessibilityMenu,
+#endif // defined(OS_CHROMEOS)
+#if !defined(OS_ANDROID)
+ kAnimationPolicyAllowed,
+ kAnimationPolicyOnce,
+ kAnimationPolicyNone,
+#endif // !defined(OS_ANDROID)
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+ prefs::kAnimationPolicy,
+#endif
+
+ // Bookmark preferences are common between incognito and regular mode.
+ bookmarks::prefs::kBookmarkEditorExpandedNodes,
+ bookmarks::prefs::kEditBookmarksEnabled,
+ bookmarks::prefs::kManagedBookmarks,
+ bookmarks::prefs::kManagedBookmarksFolderName,
+ bookmarks::prefs::kShowAppsShortcutInBookmarkBar,
+ bookmarks::prefs::kShowManagedBookmarksInBookmarkBar,
+ bookmarks::prefs::kShowBookmarkBar,
+#if defined(OS_ANDROID)
+ prefs::kPartnerBookmarkMappings,
+#endif // defined(OS_ANDROID)
+
+ // Metrics preferences are out of profile scope and are merged between
+ // incognito and regular modes.
+ metrics::prefs::kInstallDate,
+ metrics::prefs::kMetricsClientID,
+ metrics::prefs::kMetricsDefaultOptIn,
+ metrics::prefs::kMetricsInitialLogs,
+ metrics::prefs::kMetricsLowEntropySource,
+ metrics::prefs::kMetricsMachineId,
+ metrics::prefs::kMetricsOngoingLogs,
+ metrics::prefs::kMetricsResetIds,
+
+ metrics::prefs::kMetricsReportingEnabled,
+ metrics::prefs::kMetricsReportingEnabledTimestamp,
+ metrics::prefs::kMetricsSessionID,
+ metrics::prefs::kMetricsLastSeenPrefix,
+ metrics::prefs::kStabilityBreakpadRegistrationFail,
+ metrics::prefs::kStabilityBreakpadRegistrationSuccess,
+ metrics::prefs::kStabilityBrowserLastLiveTimeStamp,
+ metrics::prefs::kStabilityChildProcessCrashCount,
+ metrics::prefs::kStabilityCrashCount,
+ metrics::prefs::kStabilityCrashCountDueToGmsCoreUpdate,
+ metrics::prefs::kStabilityCrashCountWithoutGmsCoreUpdateObsolete,
+ metrics::prefs::kStabilityDebuggerNotPresent,
+ metrics::prefs::kStabilityDebuggerPresent,
+ metrics::prefs::kStabilityDeferredCount,
+ metrics::prefs::kStabilityDiscardCount,
+ metrics::prefs::kStabilityExecutionPhase,
+ metrics::prefs::kStabilityExitedCleanly,
+ metrics::prefs::kStabilityExtensionRendererCrashCount,
+ metrics::prefs::kStabilityExtensionRendererFailedLaunchCount,
+ metrics::prefs::kStabilityExtensionRendererLaunchCount,
+ metrics::prefs::kStabilityGmsCoreVersion,
+ metrics::prefs::kStabilityGpuCrashCount,
+ metrics::prefs::kStabilityIncompleteSessionEndCount,
+ metrics::prefs::kStabilityLaunchCount,
+ metrics::prefs::kStabilityPageLoadCount,
+ metrics::prefs::kStabilityRendererCrashCount,
+ metrics::prefs::kStabilityRendererFailedLaunchCount,
+ metrics::prefs::kStabilityRendererHangCount,
+ metrics::prefs::kStabilityRendererLaunchCount,
+ metrics::prefs::kStabilitySavedSystemProfile,
+ metrics::prefs::kStabilitySavedSystemProfileHash,
+ metrics::prefs::kStabilitySessionEndCompleted,
+ metrics::prefs::kStabilityStatsBuildTime,
+ metrics::prefs::kStabilityStatsVersion,
+ metrics::prefs::kStabilitySystemCrashCount,
+ metrics::prefs::kStabilityVersionMismatchCount,
+ metrics::prefs::kUninstallLaunchCount,
+ metrics::prefs::kUninstallMetricsPageLoadCount,
+ metrics::prefs::kUninstallMetricsUptimeSec,
+ metrics::prefs::kUkmCellDataUse,
+ metrics::prefs::kUmaCellDataUse,
+ metrics::prefs::kUserCellDataUse,
+
+#if defined(OS_ANDROID)
+ // Clipboard modification state is updated over all profiles.
+ prefs::kClipboardLastModifiedTime,
+#endif
+
+ // Default browser bar's status is aggregated between regular and incognito
+ // modes.
+ prefs::kBrowserSuppressDefaultBrowserPrompt,
+ prefs::kDefaultBrowserLastDeclined,
+ prefs::kDefaultBrowserSettingEnabled,
+ prefs::kResetCheckDefaultBrowser,
+
+ // Devtools preferences are stored cross profiles as they are not storing
+ // user data and just keep debugging environment settings.
+ prefs::kDevToolsAdbKey,
+ prefs::kDevToolsAvailability,
+ prefs::kDevToolsDiscoverUsbDevicesEnabled,
+ prefs::kDevToolsEditedFiles,
+ prefs::kDevToolsFileSystemPaths,
+ prefs::kDevToolsPortForwardingEnabled,
+ prefs::kDevToolsPortForwardingDefaultSet,
+ prefs::kDevToolsPortForwardingConfig,
+ prefs::kDevToolsPreferences,
+ prefs::kDevToolsDiscoverTCPTargetsEnabled,
+ prefs::kDevToolsTCPDiscoveryConfig,
+
+#if defined(OS_WIN)
+ // The total number of times that network profile warning is shown is
+ // aggregated between regular and incognito modes.
+ prefs::kNetworkProfileWarningsLeft,
+#endif
+
+ // Tab stats metrics are aggregated between regular and incognio mode.
+ prefs::kTabStatsTotalTabCountMax,
+ prefs::kTabStatsMaxTabsPerWindow,
+ prefs::kTabStatsWindowCountMax,
+ prefs::kTabStatsDailySample,
+
+#if defined(OS_MACOSX)
+ prefs::kShowFullscreenToolbar,
+#endif
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+ // Toggleing custom frames affects all open windows in the profile, hence
+ // should be written to the regular profile when changed in incognito mode.
+ prefs::kUseCustomChromeFrame,
+#endif
+
+ // Rappor preferences are not used in incognito mode, but they are written
+ // in startup if they don't exist. So if the startup would be in incognito,
+ // they need to be persisted.
+ rappor::prefs::kRapporCohortSeed,
+ rappor::prefs::kRapporSecret,
+
+ // Reading list preferences are common between incognito and regular mode.
+ reading_list::prefs::kReadingListHasUnseenEntries,
+
+ // Although UKMs are not collected in incognito, theses preferences may be
+ // changed by UMA/Sync/Unity consent, and need to be the same between
+ // incognito and regular modes.
+ ukm::prefs::kUkmClientId,
+ ukm::prefs::kUkmUnsentLogStore,
+ ukm::prefs::kUkmSessionId,
+
+ // Cookie controls preference is, as in an initial release, surfaced only in
+ // the incognito mode and therefore should be persisted between incognito
+ // sessions.
+ prefs::kCookieControlsMode,
+};
+
+} // namespace
+
+namespace prefs {
+
+std::vector<const char*> GetIncognitoPersistentPrefsWhitelist() {
+ std::vector<const char*> whitelist;
+ whitelist.insert(whitelist.end(), kPersistentPrefNames,
+ kPersistentPrefNames + base::size(kPersistentPrefNames));
+ return whitelist;
+}
+
+} // namespace prefs
diff --git a/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.h b/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.h
new file mode 100644
index 00000000000..78123f6c04a
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_service_incognito_whitelist.h
@@ -0,0 +1,19 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_PREF_SERVICE_INCOGNITO_WHITELIST_H_
+#define CHROME_BROWSER_PREFS_PREF_SERVICE_INCOGNITO_WHITELIST_H_
+
+#include <vector>
+
+namespace prefs {
+
+// Populate a list of all preferences that are stored in user profile in
+// incognito mode.
+// Please refer to the comments in .cc file.
+std::vector<const char*> GetIncognitoPersistentPrefsWhitelist();
+
+} // namespace prefs
+
+#endif // CHROME_BROWSER_PREFS_PREF_SERVICE_INCOGNITO_WHITELIST_H_
diff --git a/chromium/chrome/browser/prefs/pref_service_syncable_util.cc b/chromium/chrome/browser/prefs/pref_service_syncable_util.cc
new file mode 100644
index 00000000000..befeafcd1dc
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_service_syncable_util.cc
@@ -0,0 +1,29 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/pref_service_syncable_util.h"
+
+#include <utility>
+
+#include "chrome/browser/prefs/pref_service_incognito_whitelist.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/sync_preferences/pref_service_syncable.h"
+
+
+sync_preferences::PrefServiceSyncable* PrefServiceSyncableFromProfile(
+ Profile* profile) {
+ return static_cast<sync_preferences::PrefServiceSyncable*>(
+ profile->GetPrefs());
+}
+
+std::unique_ptr<sync_preferences::PrefServiceSyncable>
+CreateIncognitoPrefServiceSyncable(
+ sync_preferences::PrefServiceSyncable* pref_service,
+ PrefStore* incognito_extension_pref_store,
+ std::unique_ptr<PrefValueStore::Delegate> delegate) {
+
+ return pref_service->CreateIncognitoPrefService(
+ incognito_extension_pref_store,
+ prefs::GetIncognitoPersistentPrefsWhitelist(), std::move(delegate));
+}
diff --git a/chromium/chrome/browser/prefs/pref_service_syncable_util.h b/chromium/chrome/browser/prefs/pref_service_syncable_util.h
new file mode 100644
index 00000000000..6c000ce461c
--- /dev/null
+++ b/chromium/chrome/browser/prefs/pref_service_syncable_util.h
@@ -0,0 +1,41 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_PREF_SERVICE_SYNCABLE_UTIL_H_
+#define CHROME_BROWSER_PREFS_PREF_SERVICE_SYNCABLE_UTIL_H_
+
+#include <memory>
+
+#include "components/prefs/pref_value_store.h"
+
+class PrefStore;
+class Profile;
+
+namespace sync_preferences {
+class PrefServiceSyncable;
+}
+
+// sync_preferences::PrefServiceSyncable is a PrefService with added integration
+// for sync, and knowledge of how to create an incognito PrefService. For code
+// that does not need to know about the sync integration, you should use only
+// the plain PrefService type.
+//
+// For this reason, Profile does not expose an accessor for the
+// sync_preferences::PrefServiceSyncable type. Instead, you can use the
+// utilities below to retrieve the sync_preferences::PrefServiceSyncable from a
+// Profile.
+sync_preferences::PrefServiceSyncable* PrefServiceSyncableFromProfile(
+ Profile* profile);
+
+// Creates an incognito copy of |pref_service| that shares most prefs but uses
+// a fresh non-persistent overlay for the user pref store and an individual
+// extension pref store (to cache the effective extension prefs for incognito
+// windows).
+std::unique_ptr<sync_preferences::PrefServiceSyncable>
+CreateIncognitoPrefServiceSyncable(
+ sync_preferences::PrefServiceSyncable* pref_service,
+ PrefStore* incognito_extension_pref_store,
+ std::unique_ptr<PrefValueStore::Delegate> delegate);
+
+#endif // CHROME_BROWSER_PREFS_PREF_SERVICE_SYNCABLE_UTIL_H_
diff --git a/chromium/chrome/browser/prefs/profile_pref_store_manager.cc b/chromium/chrome/browser/prefs/profile_pref_store_manager.cc
new file mode 100644
index 00000000000..73245053297
--- /dev/null
+++ b/chromium/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -0,0 +1,161 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
+
+#include <utility>
+
+#include "base/files/file_util.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/sequenced_task_runner.h"
+#include "build/build_config.h"
+#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_features.h"
+#include "components/prefs/json_pref_store.h"
+#include "components/prefs/persistent_pref_store.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "services/preferences/public/cpp/persistent_pref_store_client.h"
+#include "services/preferences/public/mojom/preferences.mojom.h"
+#include "services/preferences/tracked/pref_hash_filter.h"
+#include "services/preferences/tracked/tracked_persistent_pref_store_factory.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+#if defined(OS_WIN)
+#include "chrome/install_static/install_util.h"
+#endif
+
+namespace {
+
+#if defined(OS_WIN)
+// Forces a different registry key to be used for storing preference validation
+// MACs. See |SetPreferenceValidationRegistryPathForTesting|.
+const base::string16* g_preference_validation_registry_path_for_testing =
+ nullptr;
+#endif // OS_WIN
+
+} // namespace
+
+// Preference tracking and protection is not required on platforms where other
+// apps do not have access to chrome's persistent storage.
+const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking =
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ false;
+#else
+ true;
+#endif
+
+ProfilePrefStoreManager::ProfilePrefStoreManager(
+ const base::FilePath& profile_path,
+ const std::string& seed,
+ const std::string& legacy_device_id)
+ : profile_path_(profile_path),
+ seed_(seed),
+ legacy_device_id_(legacy_device_id) {}
+
+ProfilePrefStoreManager::~ProfilePrefStoreManager() {}
+
+// static
+void ProfilePrefStoreManager::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ PrefHashFilter::RegisterProfilePrefs(registry);
+}
+
+// static
+base::Time ProfilePrefStoreManager::GetResetTime(PrefService* pref_service) {
+ return PrefHashFilter::GetResetTime(pref_service);
+}
+
+// static
+void ProfilePrefStoreManager::ClearResetTime(PrefService* pref_service) {
+ PrefHashFilter::ClearResetTime(pref_service);
+}
+
+#if defined(OS_WIN)
+// static
+void ProfilePrefStoreManager::SetPreferenceValidationRegistryPathForTesting(
+ const base::string16* path) {
+ DCHECK(!path->empty());
+ g_preference_validation_registry_path_for_testing = path;
+}
+#endif // OS_WIN
+
+PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner,
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver>
+ reset_on_load_observer,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate) {
+ if (!kPlatformSupportsPreferenceTracking) {
+ return new JsonPrefStore(profile_path_.Append(chrome::kPreferencesFilename),
+ nullptr, io_task_runner);
+ }
+ return CreateTrackedPersistentPrefStore(
+ CreateTrackedPrefStoreConfiguration(
+ std::move(tracking_configuration), reporting_ids_count,
+ std::move(reset_on_load_observer), std::move(validation_delegate)),
+ io_task_runner);
+}
+
+bool ProfilePrefStoreManager::InitializePrefsFromMasterPrefs(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ std::unique_ptr<base::DictionaryValue> master_prefs) {
+ // Create the profile directory if it doesn't exist yet (very possible on
+ // first run).
+ if (!base::CreateDirectory(profile_path_))
+ return false;
+
+ if (kPlatformSupportsPreferenceTracking) {
+ InitializeMasterPrefsTracking(
+ CreateTrackedPrefStoreConfiguration(std::move(tracking_configuration),
+ reporting_ids_count, {},
+ mojo::NullRemote()),
+ master_prefs.get());
+ }
+
+ // This will write out to a single combined file which will be immediately
+ // migrated to two files on load.
+ JSONFileValueSerializer serializer(
+ profile_path_.Append(chrome::kPreferencesFilename));
+
+ // Call Serialize (which does IO) on the main thread, which would _normally_
+ // be verboten. In this case however, we require this IO to synchronously
+ // complete before Chrome can start (as master preferences seed the Local
+ // State and Preferences files). This won't trip ThreadIORestrictions as they
+ // won't have kicked in yet on the main thread.
+ bool success = serializer.Serialize(*master_prefs);
+
+ return success;
+}
+
+prefs::mojom::TrackedPersistentPrefStoreConfigurationPtr
+ProfilePrefStoreManager::CreateTrackedPrefStoreConfiguration(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver>
+ reset_on_load_observer,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate) {
+ return prefs::mojom::TrackedPersistentPrefStoreConfiguration::New(
+ profile_path_.Append(chrome::kPreferencesFilename),
+ profile_path_.Append(chrome::kSecurePreferencesFilename),
+ std::move(tracking_configuration), reporting_ids_count, seed_,
+ legacy_device_id_, "ChromeRegistryHashStoreValidationSeed",
+#if defined(OS_WIN)
+ g_preference_validation_registry_path_for_testing
+ ? *g_preference_validation_registry_path_for_testing
+ : install_static::GetRegistryPath(),
+#else
+ base::string16(),
+#endif
+ std::move(validation_delegate), std::move(reset_on_load_observer));
+}
diff --git a/chromium/chrome/browser/prefs/profile_pref_store_manager.h b/chromium/chrome/browser/prefs/profile_pref_store_manager.h
new file mode 100644
index 00000000000..94dadd4953d
--- /dev/null
+++ b/chromium/chrome/browser/prefs/profile_pref_store_manager.h
@@ -0,0 +1,132 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_PROFILE_PREF_STORE_MANAGER_H_
+#define CHROME_BROWSER_PREFS_PROFILE_PREF_STORE_MANAGER_H_
+
+#include <stddef.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "services/preferences/public/mojom/preferences.mojom.h"
+#include "services/preferences/public/mojom/tracked_preference_validation_delegate.mojom.h"
+
+class PersistentPrefStore;
+class PrefService;
+
+namespace base {
+class DictionaryValue;
+} // namespace base
+
+namespace service_manager {
+class Connector;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+} // namespace user_prefs
+
+// Provides a facade through which the user preference store may be accessed and
+// managed.
+class ProfilePrefStoreManager {
+ public:
+ // Instantiates a ProfilePrefStoreManager with the configuration required to
+ // manage the user preferences of the profile at |profile_path|.
+ // |seed| and |legacy_device_id| are used to track preference value changes
+ // and must be the same on each launch in order to verify loaded preference
+ // values.
+ ProfilePrefStoreManager(const base::FilePath& profile_path,
+ const std::string& seed,
+ const std::string& legacy_device_id);
+
+ ~ProfilePrefStoreManager();
+
+ static const bool kPlatformSupportsPreferenceTracking;
+
+ // Register user prefs used by the profile preferences system.
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Retrieves the time of the last preference reset event, if any, for
+ // |pref_service|. Assumes that |pref_service| is backed by a PrefStore that
+ // was built by ProfilePrefStoreManager.
+ // If no reset has occurred, returns a null |Time|.
+ static base::Time GetResetTime(PrefService* pref_service);
+
+ // Clears the time of the last preference reset event, if any, for
+ // |pref_service|. Assumes that |pref_service| is backed by a PrefStore that
+ // was built by ProfilePrefStoreManager.
+ static void ClearResetTime(PrefService* pref_service);
+
+#if defined(OS_WIN)
+ // Call before startup tasks kick in to use a different registry path for
+ // storing and validating tracked preference MACs. Callers are responsible
+ // for ensuring that the key is deleted on shutdown. For testing only.
+ static void SetPreferenceValidationRegistryPathForTesting(
+ const base::string16* path);
+#endif
+
+ // Creates a PersistentPrefStore providing access to the user preferences of
+ // the managed profile. If |reset_on_load_observer| is provided, it will be
+ // notified if a reset occurs as a result of loading the profile's prefs. An
+ // optional |validation_delegate| will be notified of the status of each
+ // tracked preference as they are checked.
+ // |tracking_configuration| is used for preference tracking.
+ // |reporting_ids_count| is the count of all possible tracked preference IDs
+ // (possibly greater than |tracking_configuration.size()|).
+ PersistentPrefStore* CreateProfilePrefStore(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ scoped_refptr<base::SequencedTaskRunner> io_task_runner,
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver>
+ reset_on_load_observer,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate);
+
+ // Initializes the preferences for the managed profile with the preference
+ // values in |master_prefs|. Acts synchronously, including blocking IO.
+ // Returns true on success.
+ bool InitializePrefsFromMasterPrefs(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ std::unique_ptr<base::DictionaryValue> master_prefs);
+
+ private:
+ // Connects to the pref service over mojo and configures it.
+ void ConfigurePrefService(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver>
+ reset_on_load_observer,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate,
+ service_manager::Connector* connector);
+
+ prefs::mojom::TrackedPersistentPrefStoreConfigurationPtr
+ CreateTrackedPrefStoreConfiguration(
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ tracking_configuration,
+ size_t reporting_ids_count,
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver>
+ reset_on_load_observer,
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate);
+
+ const base::FilePath profile_path_;
+ const std::string seed_;
+ const std::string legacy_device_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(ProfilePrefStoreManager);
+};
+
+#endif // CHROME_BROWSER_PREFS_PROFILE_PREF_STORE_MANAGER_H_
diff --git a/chromium/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chromium/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
new file mode 100644
index 00000000000..716061b4809
--- /dev/null
+++ b/chromium/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -0,0 +1,562 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
+
+#include <stddef.h>
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
+#include "base/run_loop.h"
+#include "base/stl_util.h"
+#include "base/strings/string_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "base/values.h"
+#include "chrome/common/chrome_features.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/json_pref_store.h"
+#include "components/prefs/persistent_pref_store.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/pref_service_factory.h"
+#include "components/prefs/pref_store.h"
+#include "components/prefs/testing_pref_service.h"
+#include "content/public/common/service_names.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/preferences/public/cpp/pref_service_main.h"
+#include "services/preferences/public/cpp/tracked/configuration.h"
+#include "services/preferences/public/cpp/tracked/mock_validation_delegate.h"
+#include "services/preferences/public/cpp/tracked/pref_names.h"
+#include "services/preferences/public/mojom/preferences.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/service_manager/public/cpp/constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+using EnforcementLevel =
+ prefs::mojom::TrackedPreferenceMetadata::EnforcementLevel;
+using PrefTrackingStrategy =
+ prefs::mojom::TrackedPreferenceMetadata::PrefTrackingStrategy;
+using ValueType = prefs::mojom::TrackedPreferenceMetadata::ValueType;
+
+class FirstEqualsPredicate {
+ public:
+ explicit FirstEqualsPredicate(const std::string& expected)
+ : expected_(expected) {}
+ bool operator()(const PrefValueMap::Map::value_type& pair) {
+ return pair.first == expected_;
+ }
+
+ private:
+ const std::string expected_;
+};
+
+// Observes changes to the PrefStore and verifies that only registered prefs are
+// written.
+class RegistryVerifier : public PrefStore::Observer {
+ public:
+ explicit RegistryVerifier(PrefRegistry* pref_registry)
+ : pref_registry_(pref_registry) {}
+
+ // PrefStore::Observer implementation
+ void OnPrefValueChanged(const std::string& key) override {
+ EXPECT_TRUE(pref_registry_->end() !=
+ std::find_if(pref_registry_->begin(),
+ pref_registry_->end(),
+ FirstEqualsPredicate(key)))
+ << "Unregistered key " << key << " was changed.";
+ }
+
+ void OnInitializationCompleted(bool succeeded) override {}
+
+ private:
+ scoped_refptr<PrefRegistry> pref_registry_;
+};
+
+class PrefStoreReadObserver : public PrefStore::Observer {
+ public:
+ explicit PrefStoreReadObserver(scoped_refptr<PersistentPrefStore> pref_store)
+ : pref_store_(std::move(pref_store)) {
+ pref_store_->AddObserver(this);
+ }
+
+ ~PrefStoreReadObserver() override { pref_store_->RemoveObserver(this); }
+
+ PersistentPrefStore::PrefReadError Read() {
+ base::RunLoop run_loop;
+ stop_waiting_ = run_loop.QuitClosure();
+ pref_store_->ReadPrefsAsync(nullptr);
+ run_loop.Run();
+ return pref_store_->GetReadError();
+ }
+
+ // PrefStore::Observer implementation
+ void OnPrefValueChanged(const std::string& key) override {}
+
+ void OnInitializationCompleted(bool succeeded) override {
+ if (!stop_waiting_.is_null()) {
+ std::move(stop_waiting_).Run();
+ }
+ }
+
+ private:
+ scoped_refptr<PersistentPrefStore> pref_store_;
+ base::Closure stop_waiting_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrefStoreReadObserver);
+};
+
+const char kUnprotectedPref[] = "unprotected_pref";
+const char kTrackedAtomic[] = "tracked_atomic";
+const char kProtectedAtomic[] = "protected_atomic";
+
+const char kFoobar[] = "FOOBAR";
+const char kBarfoo[] = "BARFOO";
+const char kHelloWorld[] = "HELLOWORLD";
+const char kGoodbyeWorld[] = "GOODBYEWORLD";
+
+const prefs::TrackedPreferenceMetadata kConfiguration[] = {
+ {0u, kTrackedAtomic, EnforcementLevel::NO_ENFORCEMENT,
+ PrefTrackingStrategy::ATOMIC},
+ {1u, kProtectedAtomic, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC}};
+
+const size_t kExtraReportingId = 2u;
+const size_t kReportingIdCount = 3u;
+
+} // namespace
+
+class ProfilePrefStoreManagerTest : public testing::Test,
+ public prefs::mojom::ResetOnLoadObserver {
+ public:
+ ProfilePrefStoreManagerTest()
+ : configuration_(prefs::ConstructTrackedConfiguration(kConfiguration)),
+ profile_pref_registry_(new user_prefs::PrefRegistrySyncable),
+ registry_verifier_(profile_pref_registry_.get()),
+ seed_("seed"),
+ reset_recorded_(false) {}
+
+ void SetUp() override {
+ mock_validation_delegate_record_ = new MockValidationDelegateRecord;
+ mock_validation_delegate_ = std::make_unique<MockValidationDelegate>(
+ mock_validation_delegate_record_);
+
+ ProfilePrefStoreManager::RegisterProfilePrefs(profile_pref_registry_.get());
+ for (const prefs::TrackedPreferenceMetadata* it = kConfiguration;
+ it != kConfiguration + base::size(kConfiguration); ++it) {
+ if (it->strategy == PrefTrackingStrategy::ATOMIC) {
+ profile_pref_registry_->RegisterStringPref(it->name, std::string());
+ } else {
+ profile_pref_registry_->RegisterDictionaryPref(it->name);
+ }
+ }
+ profile_pref_registry_->RegisterStringPref(kUnprotectedPref, std::string());
+
+ // As in chrome_pref_service_factory.cc, kPreferencesResetTime needs to be
+ // declared as protected in order to be read from the proper store by the
+ // SegregatedPrefStore. Only declare it after configured prefs have been
+ // registered above for this test as kPreferenceResetTime is already
+ // registered in ProfilePrefStoreManager::RegisterProfilePrefs.
+ prefs::TrackedPreferenceMetadata pref_reset_time_config = {
+ (*configuration_.rbegin())->reporting_id + 1,
+ user_prefs::kPreferenceResetTime, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC};
+ configuration_.push_back(
+ prefs::ConstructTrackedMetadata(pref_reset_time_config));
+
+ ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
+ ReloadConfiguration();
+ }
+
+ void ReloadConfiguration() {
+ manager_.reset(new ProfilePrefStoreManager(profile_dir_.GetPath(), seed_,
+ "device_id"));
+ }
+
+ void TearDown() override {
+ DestroyPrefStore();
+ }
+
+ protected:
+ // Verifies whether a reset was reported via the OnResetOnLoad() hook. Also
+ // verifies that GetResetTime() was set (or not) accordingly.
+ void VerifyResetRecorded(bool reset_expected) {
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(reset_expected, reset_recorded_);
+
+ PrefServiceFactory pref_service_factory;
+ pref_service_factory.set_user_prefs(pref_store_);
+
+ std::unique_ptr<PrefService> pref_service(
+ pref_service_factory.Create(profile_pref_registry_.get()));
+
+ EXPECT_EQ(
+ reset_expected,
+ !ProfilePrefStoreManager::GetResetTime(pref_service.get()).is_null());
+ }
+
+ void ClearResetRecorded() {
+ reset_recorded_ = false;
+
+ PrefServiceFactory pref_service_factory;
+ pref_service_factory.set_user_prefs(pref_store_);
+
+ std::unique_ptr<PrefService> pref_service(
+ pref_service_factory.Create(profile_pref_registry_.get()));
+
+ ProfilePrefStoreManager::ClearResetTime(pref_service.get());
+ }
+
+ void InitializePrefs() {
+ // According to the implementation of ProfilePrefStoreManager, this is
+ // actually a SegregatedPrefStore backed by two underlying pref stores.
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver> observer;
+ reset_on_load_observer_receivers_.Add(
+ this, observer.InitWithNewPipeAndPassReceiver());
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate;
+ mock_validation_delegate_receivers_.Add(
+ mock_validation_delegate_.get(),
+ validation_delegate.InitWithNewPipeAndPassReceiver());
+ scoped_refptr<PersistentPrefStore> pref_store =
+ manager_->CreateProfilePrefStore(
+ prefs::CloneTrackedConfiguration(configuration_), kReportingIdCount,
+ base::ThreadTaskRunnerHandle::Get(), std::move(observer),
+ std::move(validation_delegate));
+ InitializePrefStore(pref_store.get());
+ pref_store = nullptr;
+ }
+
+ void DestroyPrefStore() {
+ if (pref_store_.get()) {
+ ClearResetRecorded();
+ // Force everything to be written to disk, triggering the PrefHashFilter
+ // while our RegistryVerifier is watching.
+ base::RunLoop run_loop;
+ pref_store_->CommitPendingWrite(run_loop.QuitClosure());
+ run_loop.Run();
+
+ pref_store_->RemoveObserver(&registry_verifier_);
+ pref_store_ = NULL;
+ // Nothing should have to happen on the background threads, but just in
+ // case...
+ base::RunLoop().RunUntilIdle();
+ }
+ }
+
+ void InitializePrefStore(PersistentPrefStore* pref_store) {
+ pref_store->AddObserver(&registry_verifier_);
+ PrefStoreReadObserver read_observer(pref_store);
+ PersistentPrefStore::PrefReadError error = read_observer.Read();
+ EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error);
+ pref_store->SetValue(kTrackedAtomic, std::make_unique<base::Value>(kFoobar),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ pref_store->SetValue(kProtectedAtomic,
+ std::make_unique<base::Value>(kHelloWorld),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ pref_store->SetValue(kUnprotectedPref,
+ std::make_unique<base::Value>(kFoobar),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ pref_store->RemoveObserver(&registry_verifier_);
+ base::RunLoop run_loop;
+ pref_store->CommitPendingWrite(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ void LoadExistingPrefs() {
+ DestroyPrefStore();
+ mojo::PendingRemote<prefs::mojom::ResetOnLoadObserver> observer;
+ reset_on_load_observer_receivers_.Add(
+ this, observer.InitWithNewPipeAndPassReceiver());
+ mojo::PendingRemote<prefs::mojom::TrackedPreferenceValidationDelegate>
+ validation_delegate;
+ mock_validation_delegate_receivers_.Add(
+ mock_validation_delegate_.get(),
+ validation_delegate.InitWithNewPipeAndPassReceiver());
+ pref_store_ = manager_->CreateProfilePrefStore(
+ prefs::CloneTrackedConfiguration(configuration_), kReportingIdCount,
+ base::ThreadTaskRunnerHandle::Get(), std::move(observer),
+ std::move(validation_delegate));
+ pref_store_->AddObserver(&registry_verifier_);
+ PrefStoreReadObserver read_observer(pref_store_);
+ read_observer.Read();
+ }
+
+ void ReplaceStringInPrefs(const std::string& find,
+ const std::string& replace) {
+ base::FileEnumerator file_enum(profile_dir_.GetPath(), true,
+ base::FileEnumerator::FILES);
+
+ for (base::FilePath path = file_enum.Next(); !path.empty();
+ path = file_enum.Next()) {
+ // Tamper with the file's contents
+ std::string contents;
+ EXPECT_TRUE(base::ReadFileToString(path, &contents));
+ base::ReplaceSubstringsAfterOffset(&contents, 0u, find, replace);
+ EXPECT_EQ(static_cast<int>(contents.length()),
+ base::WriteFile(path, contents.c_str(), contents.length()));
+ }
+ }
+
+ void ExpectStringValueEquals(const std::string& name,
+ const std::string& expected) {
+ const base::Value* value = NULL;
+ std::string as_string;
+ if (!pref_store_->GetValue(name, &value)) {
+ ADD_FAILURE() << name << " is not a defined value.";
+ } else if (!value->GetAsString(&as_string)) {
+ ADD_FAILURE() << name << " could not be coerced to a string.";
+ } else {
+ EXPECT_EQ(expected, as_string);
+ }
+ }
+
+ void ExpectValidationObserved(const std::string& pref_path) {
+ // No validations are expected for platforms that do not support tracking.
+ if (!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking)
+ return;
+ if (!mock_validation_delegate_record_->GetEventForPath(pref_path))
+ ADD_FAILURE() << "No validation observed for preference: " << pref_path;
+ }
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr> configuration_;
+ base::ScopedTempDir profile_dir_;
+ scoped_refptr<user_prefs::PrefRegistrySyncable> profile_pref_registry_;
+ RegistryVerifier registry_verifier_;
+ scoped_refptr<MockValidationDelegateRecord> mock_validation_delegate_record_;
+ std::unique_ptr<MockValidationDelegate> mock_validation_delegate_;
+ mojo::ReceiverSet<prefs::mojom::TrackedPreferenceValidationDelegate>
+ mock_validation_delegate_receivers_;
+ std::unique_ptr<ProfilePrefStoreManager> manager_;
+ scoped_refptr<PersistentPrefStore> pref_store_;
+
+ std::string seed_;
+
+ private:
+ void OnResetOnLoad() override {
+ // As-is |reset_recorded_| is only designed to remember a single reset, make
+ // sure none was previously recorded (or that ClearResetRecorded() was
+ // called).
+ EXPECT_FALSE(reset_recorded_);
+ reset_recorded_ = true;
+ }
+
+ base::test::ScopedFeatureList feature_list_;
+ bool reset_recorded_;
+ service_manager::mojom::ConnectorRequest connector_request_;
+ mojo::ReceiverSet<prefs::mojom::ResetOnLoadObserver>
+ reset_on_load_observer_receivers_;
+};
+
+TEST_F(ProfilePrefStoreManagerTest, StoreValues) {
+ InitializePrefs();
+
+ LoadExistingPrefs();
+
+ ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+ ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+ VerifyResetRecorded(false);
+ ExpectValidationObserved(kTrackedAtomic);
+ ExpectValidationObserved(kProtectedAtomic);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, ProtectValues) {
+ InitializePrefs();
+
+ ReplaceStringInPrefs(kFoobar, kBarfoo);
+ ReplaceStringInPrefs(kHelloWorld, kGoodbyeWorld);
+
+ LoadExistingPrefs();
+
+ // kTrackedAtomic is unprotected and thus will be loaded as it appears on
+ // disk.
+ ExpectStringValueEquals(kTrackedAtomic, kBarfoo);
+
+ // If preference tracking is supported, the tampered value of kProtectedAtomic
+ // will be discarded at load time, leaving this preference undefined.
+ EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
+ pref_store_->GetValue(kProtectedAtomic, NULL));
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
+
+ ExpectValidationObserved(kTrackedAtomic);
+ ExpectValidationObserved(kProtectedAtomic);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, InitializePrefsFromMasterPrefs) {
+ auto master_prefs = std::make_unique<base::DictionaryValue>();
+ master_prefs->Set(kTrackedAtomic, std::make_unique<base::Value>(kFoobar));
+ master_prefs->Set(kProtectedAtomic,
+ std::make_unique<base::Value>(kHelloWorld));
+ EXPECT_TRUE(manager_->InitializePrefsFromMasterPrefs(
+ prefs::CloneTrackedConfiguration(configuration_), kReportingIdCount,
+ std::move(master_prefs)));
+
+ LoadExistingPrefs();
+
+ // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs
+ // necessary to authenticate these values.
+ ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+ ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+ VerifyResetRecorded(false);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtected) {
+ InitializePrefs();
+
+ ExpectValidationObserved(kTrackedAtomic);
+ ExpectValidationObserved(kProtectedAtomic);
+
+ LoadExistingPrefs();
+ ExpectStringValueEquals(kUnprotectedPref, kFoobar);
+
+ // Ensure everything is written out to disk.
+ DestroyPrefStore();
+
+ ReplaceStringInPrefs(kFoobar, kBarfoo);
+
+ // It's unprotected, so we can load the modified value.
+ LoadExistingPrefs();
+ ExpectStringValueEquals(kUnprotectedPref, kBarfoo);
+
+ // Now update the configuration to protect it.
+ prefs::TrackedPreferenceMetadata new_protected = {
+ kExtraReportingId, kUnprotectedPref, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC};
+ configuration_.push_back(prefs::ConstructTrackedMetadata(new_protected));
+ ReloadConfiguration();
+
+ // And try loading with the new configuration.
+ LoadExistingPrefs();
+
+ // Since there was a valid super MAC we were able to extend the existing trust
+ // to the newly protected preference.
+ ExpectStringValueEquals(kUnprotectedPref, kBarfoo);
+ VerifyResetRecorded(false);
+
+ // Ensure everything is written out to disk.
+ DestroyPrefStore();
+
+ // It's protected now, so (if the platform supports it) any tampering should
+ // lead to a reset.
+ ReplaceStringInPrefs(kBarfoo, kFoobar);
+ LoadExistingPrefs();
+ EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
+ pref_store_->GetValue(kUnprotectedPref, NULL));
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, NewPrefWhenFirstProtecting) {
+ std::vector<prefs::mojom::TrackedPreferenceMetadataPtr>
+ original_configuration = prefs::CloneTrackedConfiguration(configuration_);
+ for (const auto& metadata : configuration_) {
+ metadata->enforcement_level = EnforcementLevel::NO_ENFORCEMENT;
+ }
+ ReloadConfiguration();
+
+ InitializePrefs();
+
+ ExpectValidationObserved(kTrackedAtomic);
+ ExpectValidationObserved(kProtectedAtomic);
+
+ LoadExistingPrefs();
+ ExpectStringValueEquals(kUnprotectedPref, kFoobar);
+
+ // Ensure everything is written out to disk.
+ DestroyPrefStore();
+
+ // Now introduce protection, including the never-before tracked "new_pref".
+ configuration_ = std::move(original_configuration);
+ prefs::TrackedPreferenceMetadata new_protected = {
+ kExtraReportingId, kUnprotectedPref, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC};
+ configuration_.push_back(prefs::ConstructTrackedMetadata(new_protected));
+ ReloadConfiguration();
+
+ // And try loading with the new configuration.
+ LoadExistingPrefs();
+
+ // Since there was a valid super MAC we were able to extend the existing trust
+ // to the newly tracked & protected preference.
+ ExpectStringValueEquals(kUnprotectedPref, kFoobar);
+ VerifyResetRecorded(false);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, UnprotectedToProtectedWithoutTrust) {
+ InitializePrefs();
+
+ ExpectValidationObserved(kTrackedAtomic);
+ ExpectValidationObserved(kProtectedAtomic);
+
+ // Now update the configuration to protect it.
+ prefs::TrackedPreferenceMetadata new_protected = {
+ kExtraReportingId, kUnprotectedPref, EnforcementLevel::ENFORCE_ON_LOAD,
+ PrefTrackingStrategy::ATOMIC};
+ configuration_.push_back(prefs::ConstructTrackedMetadata(new_protected));
+ seed_ = "new-seed-to-break-trust";
+ ReloadConfiguration();
+
+ // And try loading with the new configuration.
+ LoadExistingPrefs();
+
+ // If preference tracking is supported, kUnprotectedPref will have been
+ // discarded because new values are not accepted without a valid super MAC.
+ EXPECT_NE(ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
+ pref_store_->GetValue(kUnprotectedPref, NULL));
+ VerifyResetRecorded(
+ ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking);
+}
+
+// This test verifies that preference values are correctly maintained when a
+// preference's protection state changes from protected to unprotected.
+TEST_F(ProfilePrefStoreManagerTest, ProtectedToUnprotected) {
+ InitializePrefs();
+
+ ExpectValidationObserved(kTrackedAtomic);
+ ExpectValidationObserved(kProtectedAtomic);
+
+ DestroyPrefStore();
+
+ // Unconfigure protection for kProtectedAtomic
+ for (const auto& metadata : configuration_) {
+ if (metadata->name == kProtectedAtomic) {
+ metadata->enforcement_level = EnforcementLevel::NO_ENFORCEMENT;
+ break;
+ }
+ }
+
+ seed_ = "new-seed-to-break-trust";
+ ReloadConfiguration();
+ LoadExistingPrefs();
+
+ // Verify that the value was not reset.
+ ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+ VerifyResetRecorded(false);
+
+ // Accessing the value of the previously protected pref didn't trigger its
+ // move to the unprotected preferences file, though the loading of the pref
+ // store should still have caused the MAC store to be recalculated.
+ LoadExistingPrefs();
+ ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+
+ // Trigger the logic that migrates it back to the unprotected preferences
+ // file.
+ pref_store_->SetValue(kProtectedAtomic,
+ std::make_unique<base::Value>(kGoodbyeWorld),
+ WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
+ LoadExistingPrefs();
+ ExpectStringValueEquals(kProtectedAtomic, kGoodbyeWorld);
+ VerifyResetRecorded(false);
+}
diff --git a/chromium/chrome/browser/prefs/proxy_policy_unittest.cc b/chromium/chrome/browser/prefs/proxy_policy_unittest.cc
new file mode 100644
index 00000000000..efa4b31cf82
--- /dev/null
+++ b/chromium/chrome/browser/prefs/proxy_policy_unittest.cc
@@ -0,0 +1,254 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/policy/chrome_browser_policy_connector.h"
+#include "chrome/browser/prefs/browser_prefs.h"
+#include "chrome/browser/prefs/chrome_command_line_pref_store.h"
+#include "chrome/common/chrome_switches.h"
+#include "components/policy/core/common/external_data_fetcher.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_service_impl.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/policy_constants.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/proxy_config/proxy_config_dictionary.h"
+#include "components/proxy_config/proxy_config_pref_names.h"
+#include "components/sync_preferences/pref_service_mock_factory.h"
+#include "components/sync_preferences/pref_service_syncable.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/tpm/stub_install_attributes.h"
+#endif
+
+using ::testing::Return;
+using ::testing::_;
+
+namespace policy {
+
+namespace {
+
+void assertProxyMode(const ProxyConfigDictionary& dict,
+ ProxyPrefs::ProxyMode expected_mode) {
+ ProxyPrefs::ProxyMode actual_mode;
+ ASSERT_TRUE(dict.GetMode(&actual_mode));
+ EXPECT_EQ(expected_mode, actual_mode);
+}
+
+void assertProxyServer(const ProxyConfigDictionary& dict,
+ const std::string& expected) {
+ std::string actual;
+ if (!expected.empty()) {
+ ASSERT_TRUE(dict.GetProxyServer(&actual));
+ EXPECT_EQ(expected, actual);
+ } else {
+ EXPECT_FALSE(dict.GetProxyServer(&actual));
+ }
+}
+
+void assertPacUrl(const ProxyConfigDictionary& dict,
+ const std::string& expected) {
+ std::string actual;
+ if (!expected.empty()) {
+ ASSERT_TRUE(dict.GetPacUrl(&actual));
+ EXPECT_EQ(expected, actual);
+ } else {
+ EXPECT_FALSE(dict.GetPacUrl(&actual));
+ }
+}
+
+void assertBypassList(const ProxyConfigDictionary& dict,
+ const std::string& expected) {
+ std::string actual;
+ if (!expected.empty()) {
+ ASSERT_TRUE(dict.GetBypassList(&actual));
+ EXPECT_EQ(expected, actual);
+ } else {
+ EXPECT_FALSE(dict.GetBypassList(&actual));
+ }
+}
+
+void assertProxyModeWithoutParams(const ProxyConfigDictionary& dict,
+ ProxyPrefs::ProxyMode proxy_mode) {
+ assertProxyMode(dict, proxy_mode);
+ assertProxyServer(dict, std::string());
+ assertPacUrl(dict, std::string());
+ assertBypassList(dict, std::string());
+}
+
+} // namespace
+
+class ProxyPolicyTest : public testing::Test {
+ protected:
+ ProxyPolicyTest() : command_line_(base::CommandLine::NO_PROGRAM) {}
+
+ void SetUp() override {
+ EXPECT_CALL(provider_, IsInitializationComplete(_))
+ .WillRepeatedly(Return(true));
+
+ PolicyServiceImpl::Providers providers;
+ providers.push_back(&provider_);
+ policy_service_ = std::make_unique<PolicyServiceImpl>(std::move(providers));
+ provider_.Init();
+ }
+
+ void TearDown() override { provider_.Shutdown(); }
+
+ std::unique_ptr<PrefService> CreatePrefService(bool with_managed_policies) {
+ sync_preferences::PrefServiceMockFactory factory;
+ factory.set_command_line_prefs(
+ new ChromeCommandLinePrefStore(&command_line_));
+ if (with_managed_policies) {
+ factory.SetManagedPolicies(policy_service_.get(),
+ g_browser_process->browser_policy_connector());
+ }
+
+ scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
+ new user_prefs::PrefRegistrySyncable);
+ std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs =
+ factory.CreateSyncable(registry.get());
+ RegisterUserProfilePrefs(registry.get());
+ return std::move(prefs);
+ }
+
+ content::BrowserTaskEnvironment task_environment_;
+ base::CommandLine command_line_;
+ MockConfigurationPolicyProvider provider_;
+ std::unique_ptr<PolicyServiceImpl> policy_service_;
+
+#if defined(OS_CHROMEOS)
+ chromeos::ScopedStubInstallAttributes test_install_attributes_;
+#endif
+};
+
+TEST_F(ProxyPolicyTest, OverridesCommandLineOptions) {
+ command_line_.AppendSwitchASCII(switches::kProxyBypassList, "123");
+ command_line_.AppendSwitchASCII(switches::kProxyServer, "789");
+ std::unique_ptr<base::Value> mode_name(
+ new base::Value(ProxyPrefs::kFixedServersProxyModeName));
+ PolicyMap policy;
+ policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_CLOUD, std::move(mode_name), nullptr);
+ policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("abc"),
+ nullptr);
+ policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_CLOUD, std::make_unique<base::Value>("ghi"),
+ nullptr);
+ provider_.UpdateChromePolicy(policy);
+
+ // First verify that command-line options are set correctly when
+ // there is no policy in effect.
+ std::unique_ptr<PrefService> prefs(CreatePrefService(false));
+ ProxyConfigDictionary dict(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyMode(dict, ProxyPrefs::MODE_FIXED_SERVERS);
+ assertProxyServer(dict, "789");
+ assertPacUrl(dict, std::string());
+ assertBypassList(dict, "123");
+
+ // Try a second time time with the managed PrefStore in place, the
+ // manual proxy policy should have removed all traces of the command
+ // line and replaced them with the policy versions.
+ prefs = CreatePrefService(true);
+ ProxyConfigDictionary dict2(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyMode(dict2, ProxyPrefs::MODE_FIXED_SERVERS);
+ assertProxyServer(dict2, "ghi");
+ assertPacUrl(dict2, std::string());
+ assertBypassList(dict2, "abc");
+}
+
+TEST_F(ProxyPolicyTest, OverridesUnrelatedCommandLineOptions) {
+ command_line_.AppendSwitchASCII(switches::kProxyBypassList, "123");
+ command_line_.AppendSwitchASCII(switches::kProxyServer, "789");
+ std::unique_ptr<base::Value> mode_name(
+ new base::Value(ProxyPrefs::kAutoDetectProxyModeName));
+ PolicyMap policy;
+ policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_CLOUD, std::move(mode_name), nullptr);
+ provider_.UpdateChromePolicy(policy);
+
+ // First verify that command-line options are set correctly when
+ // there is no policy in effect.
+ std::unique_ptr<PrefService> prefs = CreatePrefService(false);
+ ProxyConfigDictionary dict(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyMode(dict, ProxyPrefs::MODE_FIXED_SERVERS);
+ assertProxyServer(dict, "789");
+ assertPacUrl(dict, std::string());
+ assertBypassList(dict, "123");
+
+ // Try a second time time with the managed PrefStore in place, the
+ // no proxy policy should have removed all traces of the command
+ // line proxy settings, even though they were not the specific one
+ // set in policy.
+ prefs = CreatePrefService(true);
+ ProxyConfigDictionary dict2(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_AUTO_DETECT);
+}
+
+TEST_F(ProxyPolicyTest, OverridesCommandLineNoProxy) {
+ command_line_.AppendSwitch(switches::kNoProxyServer);
+ std::unique_ptr<base::Value> mode_name(
+ new base::Value(ProxyPrefs::kAutoDetectProxyModeName));
+ PolicyMap policy;
+ policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_CLOUD, std::move(mode_name), nullptr);
+ provider_.UpdateChromePolicy(policy);
+
+ // First verify that command-line options are set correctly when
+ // there is no policy in effect.
+ std::unique_ptr<PrefService> prefs = CreatePrefService(false);
+ ProxyConfigDictionary dict(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyModeWithoutParams(dict, ProxyPrefs::MODE_DIRECT);
+
+ // Try a second time time with the managed PrefStore in place, the
+ // auto-detect should be overridden. The default pref store must be
+ // in place with the appropriate default value for this to work.
+ prefs = CreatePrefService(true);
+ ProxyConfigDictionary dict2(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_AUTO_DETECT);
+}
+
+TEST_F(ProxyPolicyTest, OverridesCommandLineAutoDetect) {
+ command_line_.AppendSwitch(switches::kProxyAutoDetect);
+ std::unique_ptr<base::Value> mode_name(
+ new base::Value(ProxyPrefs::kDirectProxyModeName));
+ PolicyMap policy;
+ policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
+ POLICY_SOURCE_CLOUD, std::move(mode_name), nullptr);
+ provider_.UpdateChromePolicy(policy);
+
+ // First verify that the auto-detect is set if there is no managed
+ // PrefStore.
+ std::unique_ptr<PrefService> prefs = CreatePrefService(false);
+ ProxyConfigDictionary dict(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyModeWithoutParams(dict, ProxyPrefs::MODE_AUTO_DETECT);
+
+ // Try a second time time with the managed PrefStore in place, the
+ // auto-detect should be overridden. The default pref store must be
+ // in place with the appropriate default value for this to work.
+ prefs = CreatePrefService(true);
+ ProxyConfigDictionary dict2(
+ prefs->GetDictionary(proxy_config::prefs::kProxy)->Clone());
+ assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_DIRECT);
+}
+
+} // namespace policy
diff --git a/chromium/chrome/browser/prefs/session_startup_pref.cc b/chromium/chrome/browser/prefs/session_startup_pref.cc
new file mode 100644
index 00000000000..216ea4a2a2e
--- /dev/null
+++ b/chromium/chrome/browser/prefs/session_startup_pref.cc
@@ -0,0 +1,175 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/session_startup_pref.h"
+
+#include <stddef.h>
+
+#include <string>
+
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/url_formatter/url_fixer.h"
+
+namespace {
+
+// Converts a SessionStartupPref::Type to an integer written to prefs.
+int TypeToPrefValue(SessionStartupPref::Type type) {
+ switch (type) {
+ case SessionStartupPref::LAST: return SessionStartupPref::kPrefValueLast;
+ case SessionStartupPref::URLS: return SessionStartupPref::kPrefValueURLs;
+ default: return SessionStartupPref::kPrefValueNewTab;
+ }
+}
+
+void URLListToPref(const base::ListValue* url_list, SessionStartupPref* pref) {
+ pref->urls.clear();
+ for (size_t i = 0; i < url_list->GetSize(); ++i) {
+ std::string url_text;
+ if (url_list->GetString(i, &url_text)) {
+ GURL fixed_url = url_formatter::FixupURL(url_text, std::string());
+ pref->urls.push_back(fixed_url);
+ }
+ }
+}
+
+} // namespace
+
+// static
+void SessionStartupPref::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+#if defined(OS_ANDROID)
+ uint32_t flags = PrefRegistry::NO_REGISTRATION_FLAGS;
+#else
+ uint32_t flags = user_prefs::PrefRegistrySyncable::SYNCABLE_PREF;
+#endif
+ registry->RegisterIntegerPref(prefs::kRestoreOnStartup,
+ TypeToPrefValue(GetDefaultStartupType()),
+ flags);
+ registry->RegisterListPref(prefs::kURLsToRestoreOnStartup, flags);
+}
+
+// static
+SessionStartupPref::Type SessionStartupPref::GetDefaultStartupType() {
+#if defined(OS_CHROMEOS)
+ return SessionStartupPref::LAST;
+#else
+ return SessionStartupPref::DEFAULT;
+#endif
+}
+
+// static
+void SessionStartupPref::SetStartupPref(
+ Profile* profile,
+ const SessionStartupPref& pref) {
+ DCHECK(profile);
+ SetStartupPref(profile->GetPrefs(), pref);
+}
+
+// static
+void SessionStartupPref::SetStartupPref(PrefService* prefs,
+ const SessionStartupPref& pref) {
+ DCHECK(prefs);
+
+ if (!SessionStartupPref::TypeIsManaged(prefs))
+ prefs->SetInteger(prefs::kRestoreOnStartup, TypeToPrefValue(pref.type));
+
+ if (!SessionStartupPref::URLsAreManaged(prefs)) {
+ // Always save the URLs, that way the UI can remain consistent even if the
+ // user changes the startup type pref.
+ // Ownership of the ListValue retains with the pref service.
+ ListPrefUpdate update(prefs, prefs::kURLsToRestoreOnStartup);
+ base::ListValue* url_pref_list = update.Get();
+ DCHECK(url_pref_list);
+ url_pref_list->Clear();
+ for (size_t i = 0; i < pref.urls.size(); ++i) {
+ url_pref_list->Set(static_cast<int>(i),
+ std::make_unique<base::Value>(pref.urls[i].spec()));
+ }
+ }
+}
+
+// static
+SessionStartupPref SessionStartupPref::GetStartupPref(Profile* profile) {
+ DCHECK(profile);
+
+ // Guest sessions should not store any state, therefore they should never
+ // trigger a restore during startup.
+ return profile->IsGuestSession()
+ ? SessionStartupPref(SessionStartupPref::DEFAULT)
+ : GetStartupPref(profile->GetPrefs());
+}
+
+// static
+SessionStartupPref SessionStartupPref::GetStartupPref(PrefService* prefs) {
+ DCHECK(prefs);
+
+ SessionStartupPref pref(
+ PrefValueToType(prefs->GetInteger(prefs::kRestoreOnStartup)));
+
+ // Always load the urls, even if the pref type isn't URLS. This way the
+ // preferences panels can show the user their last choice.
+ const base::ListValue* url_list =
+ prefs->GetList(prefs::kURLsToRestoreOnStartup);
+ URLListToPref(url_list, &pref);
+
+ return pref;
+}
+
+// static
+bool SessionStartupPref::TypeIsManaged(PrefService* prefs) {
+ DCHECK(prefs);
+ const PrefService::Preference* pref_restore =
+ prefs->FindPreference(prefs::kRestoreOnStartup);
+ DCHECK(pref_restore);
+ return pref_restore->IsManaged();
+}
+
+// static
+bool SessionStartupPref::URLsAreManaged(PrefService* prefs) {
+ DCHECK(prefs);
+ const PrefService::Preference* pref_urls =
+ prefs->FindPreference(prefs::kURLsToRestoreOnStartup);
+ DCHECK(pref_urls);
+ return pref_urls->IsManaged();
+}
+
+// static
+bool SessionStartupPref::TypeHasRecommendedValue(PrefService* prefs) {
+ DCHECK(prefs);
+ const PrefService::Preference* pref_restore =
+ prefs->FindPreference(prefs::kRestoreOnStartup);
+ DCHECK(pref_restore);
+ return pref_restore->GetRecommendedValue() != nullptr;
+}
+
+// static
+bool SessionStartupPref::TypeIsDefault(PrefService* prefs) {
+ DCHECK(prefs);
+ const PrefService::Preference* pref_restore =
+ prefs->FindPreference(prefs::kRestoreOnStartup);
+ DCHECK(pref_restore);
+ return pref_restore->IsDefaultValue();
+}
+
+// static
+SessionStartupPref::Type SessionStartupPref::PrefValueToType(int pref_value) {
+ switch (pref_value) {
+ case kPrefValueLast: return SessionStartupPref::LAST;
+ case kPrefValueURLs: return SessionStartupPref::URLS;
+ default: return SessionStartupPref::DEFAULT;
+ }
+}
+
+SessionStartupPref::SessionStartupPref(Type type) : type(type) {}
+
+SessionStartupPref::SessionStartupPref(const SessionStartupPref& other) =
+ default;
+
+SessionStartupPref::~SessionStartupPref() {}
diff --git a/chromium/chrome/browser/prefs/session_startup_pref.h b/chromium/chrome/browser/prefs/session_startup_pref.h
new file mode 100644
index 00000000000..ebcb6e9850a
--- /dev/null
+++ b/chromium/chrome/browser/prefs/session_startup_pref.h
@@ -0,0 +1,85 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_SESSION_STARTUP_PREF_H__
+#define CHROME_BROWSER_PREFS_SESSION_STARTUP_PREF_H__
+
+#include <vector>
+
+#include "url/gurl.h"
+
+class PrefService;
+class Profile;
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+// StartupPref specifies what should happen at startup for a specified profile.
+// StartupPref is stored in the preferences for a particular profile.
+struct SessionStartupPref {
+ // Integer values should not be changed because reset reports depend on these.
+ enum Type {
+ // Indicates the user wants to open the New Tab page.
+ DEFAULT = 0,
+
+ // Indicates the user wants to restore the last session.
+ LAST = 2,
+
+ // Indicates the user wants to restore a specific set of URLs. The URLs
+ // are contained in urls.
+ URLS = 3,
+ };
+
+ // For historical reasons the enum and value registered in the prefs don't
+ // line up. These are the values registered in prefs.
+ // The values are also recorded in Settings.StartupPageLoadSettings histogram,
+ // so make sure to update histograms.xml if you change these.
+ enum PrefValue {
+ kPrefValueLast = 1,
+ kPrefValueURLs = 4,
+ kPrefValueNewTab = 5,
+ kPrefValueMax = 6,
+ };
+
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ // Returns the default value for |type|.
+ static Type GetDefaultStartupType();
+
+ // What should happen on startup for the specified profile.
+ static void SetStartupPref(Profile* profile, const SessionStartupPref& pref);
+ static void SetStartupPref(PrefService* prefs,
+ const SessionStartupPref& pref);
+ static SessionStartupPref GetStartupPref(Profile* profile);
+ static SessionStartupPref GetStartupPref(PrefService* prefs);
+
+ // Whether the startup type and URLs are managed via mandatory policy.
+ static bool TypeIsManaged(PrefService* prefs);
+ static bool URLsAreManaged(PrefService* prefs);
+
+ // Whether the startup type has a recommended value (regardless of whether or
+ // not that value is in use).
+ static bool TypeHasRecommendedValue(PrefService* prefs);
+
+ // Whether the startup type has not been overridden from its default.
+ static bool TypeIsDefault(PrefService* prefs);
+
+ // Converts an integer pref value to a SessionStartupPref::Type.
+ static SessionStartupPref::Type PrefValueToType(int pref_value);
+
+ explicit SessionStartupPref(Type type);
+
+ SessionStartupPref(const SessionStartupPref& other);
+
+ ~SessionStartupPref();
+
+ // What to do on startup.
+ Type type;
+
+ // The URLs to restore. Only used if type == URLS.
+ std::vector<GURL> urls;
+};
+
+#endif // CHROME_BROWSER_PREFS_SESSION_STARTUP_PREF_H__
diff --git a/chromium/chrome/browser/prefs/session_startup_pref_unittest.cc b/chromium/chrome/browser/prefs/session_startup_pref_unittest.cc
new file mode 100644
index 00000000000..69a77f997a5
--- /dev/null
+++ b/chromium/chrome/browser/prefs/session_startup_pref_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/common/pref_names.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// Unit tests for SessionStartupPref.
+class SessionStartupPrefTest : public testing::Test {
+ public:
+ void SetUp() override {
+ pref_service_.reset(new sync_preferences::TestingPrefServiceSyncable);
+ SessionStartupPref::RegisterProfilePrefs(registry());
+ registry()->RegisterBooleanPref(prefs::kHomePageIsNewTabPage, true);
+ }
+
+ user_prefs::PrefRegistrySyncable* registry() {
+ return pref_service_->registry();
+ }
+
+ std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_;
+};
+
+TEST_F(SessionStartupPrefTest, URLListIsFixedUp) {
+ auto url_pref_list = std::make_unique<base::ListValue>();
+ url_pref_list->Set(0, std::make_unique<base::Value>("google.com"));
+ url_pref_list->Set(1, std::make_unique<base::Value>("chromium.org"));
+ pref_service_->SetUserPref(prefs::kURLsToRestoreOnStartup,
+ std::move(url_pref_list));
+
+ SessionStartupPref result =
+ SessionStartupPref::GetStartupPref(pref_service_.get());
+ EXPECT_EQ(2u, result.urls.size());
+ EXPECT_EQ("http://google.com/", result.urls[0].spec());
+ EXPECT_EQ("http://chromium.org/", result.urls[1].spec());
+}
+
+TEST_F(SessionStartupPrefTest, URLListManagedOverridesUser) {
+ auto url_pref_list1 = std::make_unique<base::ListValue>();
+ url_pref_list1->Set(0, std::make_unique<base::Value>("chromium.org"));
+ pref_service_->SetUserPref(prefs::kURLsToRestoreOnStartup,
+ std::move(url_pref_list1));
+
+ auto url_pref_list2 = std::make_unique<base::ListValue>();
+ url_pref_list2->Set(0, std::make_unique<base::Value>("chromium.org"));
+ url_pref_list2->Set(1, std::make_unique<base::Value>("chromium.org"));
+ url_pref_list2->Set(2, std::make_unique<base::Value>("chromium.org"));
+ pref_service_->SetManagedPref(prefs::kURLsToRestoreOnStartup,
+ std::move(url_pref_list2));
+
+ SessionStartupPref result =
+ SessionStartupPref::GetStartupPref(pref_service_.get());
+ EXPECT_EQ(3u, result.urls.size());
+
+ SessionStartupPref override_test =
+ SessionStartupPref(SessionStartupPref::URLS);
+ override_test.urls.push_back(GURL("dev.chromium.org"));
+ SessionStartupPref::SetStartupPref(pref_service_.get(), override_test);
+
+ result = SessionStartupPref::GetStartupPref(pref_service_.get());
+ EXPECT_EQ(3u, result.urls.size());
+}
diff --git a/chromium/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc b/chromium/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
new file mode 100644
index 00000000000..a0624c1c365
--- /dev/null
+++ b/chromium/chrome/browser/prefs/synced_pref_change_registrar_browsertest.cc
@@ -0,0 +1,205 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/message_loop/message_loop_current.h"
+#include "base/run_loop.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/pref_service_syncable_util.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/policy_types.h"
+#include "components/policy/policy_constants.h"
+#include "components/sync/model/fake_sync_change_processor.h"
+#include "components/sync/model/sync_change.h"
+#include "components/sync/model/sync_error_factory.h"
+#include "components/sync/model/sync_error_factory_mock.h"
+#include "components/sync/model/syncable_service.h"
+#include "components/sync/protocol/sync.pb.h"
+#include "components/sync_preferences/synced_pref_change_registrar.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "content/public/test/test_utils.h"
+
+namespace {
+
+using testing::Return;
+using testing::_;
+
+class SyncedPrefChangeRegistrarTest : public InProcessBrowserTest {
+ public:
+ SyncedPrefChangeRegistrarTest() : next_sync_data_id_(0) {}
+ ~SyncedPrefChangeRegistrarTest() override {}
+
+ void UpdateChromePolicy(const policy::PolicyMap& policies) {
+ policy_provider_.UpdateChromePolicy(policies);
+ DCHECK(base::MessageLoopCurrent::Get());
+ base::RunLoop loop;
+ loop.RunUntilIdle();
+ }
+
+ void SetBooleanPrefValueFromSync(const std::string& name, bool value) {
+ std::string serialized_value;
+ JSONStringValueSerializer json(&serialized_value);
+ json.Serialize(base::Value(value));
+
+ sync_pb::EntitySpecifics specifics;
+ sync_pb::PreferenceSpecifics* pref_specifics =
+ specifics.mutable_preference();
+ pref_specifics->set_name(name);
+ pref_specifics->set_value(serialized_value);
+
+ syncer::SyncData change_data =
+ syncer::SyncData::CreateRemoteData(++next_sync_data_id_, specifics);
+ syncer::SyncChange change(
+ FROM_HERE, syncer::SyncChange::ACTION_UPDATE, change_data);
+
+ syncer::SyncChangeList change_list;
+ change_list.push_back(change);
+
+ syncer_->ProcessSyncChanges(FROM_HERE, change_list);
+ }
+
+ void SetBooleanPrefValueFromLocal(const std::string& name, bool value) {
+ prefs_->SetBoolean(name.c_str(), value);
+ }
+
+ bool GetBooleanPrefValue(const std::string& name) {
+ return prefs_->GetBoolean(name.c_str());
+ }
+
+ sync_preferences::PrefServiceSyncable* prefs() const { return prefs_; }
+
+ sync_preferences::SyncedPrefChangeRegistrar* registrar() const {
+ return registrar_.get();
+ }
+
+ private:
+ void SetUpInProcessBrowserTestFixture() override {
+ EXPECT_CALL(policy_provider_, IsInitializationComplete(_))
+ .WillRepeatedly(Return(true));
+ policy::BrowserPolicyConnector::SetPolicyProviderForTesting(
+ &policy_provider_);
+ }
+
+ void SetUpOnMainThread() override {
+ prefs_ = PrefServiceSyncableFromProfile(browser()->profile());
+ syncer_ = prefs_->GetSyncableService(syncer::PREFERENCES);
+ syncer_->MergeDataAndStartSyncing(
+ syncer::PREFERENCES, syncer::SyncDataList(),
+ std::unique_ptr<syncer::SyncChangeProcessor>(
+ new syncer::FakeSyncChangeProcessor),
+ std::unique_ptr<syncer::SyncErrorFactory>(
+ new syncer::SyncErrorFactoryMock));
+ registrar_.reset(new sync_preferences::SyncedPrefChangeRegistrar(prefs_));
+ }
+
+ void TearDownOnMainThread() override { registrar_.reset(); }
+
+ sync_preferences::PrefServiceSyncable* prefs_;
+ syncer::SyncableService* syncer_;
+ int next_sync_data_id_;
+
+ std::unique_ptr<sync_preferences::SyncedPrefChangeRegistrar> registrar_;
+ policy::MockConfigurationPolicyProvider policy_provider_;
+};
+
+struct TestSyncedPrefObserver {
+ bool last_seen_value;
+ bool last_update_is_from_sync;
+ bool has_been_notified;
+};
+
+void TestPrefChangeCallback(PrefService* prefs,
+ TestSyncedPrefObserver* observer,
+ const std::string& path,
+ bool from_sync) {
+ observer->last_seen_value = prefs->GetBoolean(path.c_str());
+ observer->last_update_is_from_sync = from_sync;
+ observer->has_been_notified = true;
+}
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+ DifferentiateRemoteAndLocalChanges) {
+ TestSyncedPrefObserver observer = {};
+ registrar()->Add(prefs::kShowHomeButton,
+ base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+ EXPECT_FALSE(observer.has_been_notified);
+
+ SetBooleanPrefValueFromSync(prefs::kShowHomeButton, true);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_TRUE(observer.last_update_is_from_sync);
+ EXPECT_TRUE(observer.last_seen_value);
+
+ observer.has_been_notified = false;
+ SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_FALSE(observer.last_update_is_from_sync);
+ EXPECT_FALSE(observer.last_seen_value);
+
+ observer.has_been_notified = false;
+ SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, true);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_FALSE(observer.last_update_is_from_sync);
+ EXPECT_TRUE(observer.last_seen_value);
+
+ observer.has_been_notified = false;
+ SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false);
+ EXPECT_TRUE(observer.has_been_notified);
+ EXPECT_FALSE(GetBooleanPrefValue(prefs::kShowHomeButton));
+ EXPECT_TRUE(observer.last_update_is_from_sync);
+ EXPECT_FALSE(observer.last_seen_value);
+}
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+ IgnoreLocalChangesToManagedPrefs) {
+ TestSyncedPrefObserver observer = {};
+ registrar()->Add(prefs::kShowHomeButton,
+ base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+ policy::PolicyMap policies;
+ policies.Set(policy::key::kShowHomeButton, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+ std::make_unique<base::Value>(true), nullptr);
+ UpdateChromePolicy(policies);
+
+ EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton));
+
+ SetBooleanPrefValueFromLocal(prefs::kShowHomeButton, false);
+ EXPECT_FALSE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+}
+
+IN_PROC_BROWSER_TEST_F(SyncedPrefChangeRegistrarTest,
+ IgnoreSyncChangesToManagedPrefs) {
+ TestSyncedPrefObserver observer = {};
+ registrar()->Add(prefs::kShowHomeButton,
+ base::Bind(&TestPrefChangeCallback, prefs(), &observer));
+
+ policy::PolicyMap policies;
+ policies.Set(policy::key::kShowHomeButton, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+ std::make_unique<base::Value>(true), nullptr);
+ UpdateChromePolicy(policies);
+
+ EXPECT_TRUE(prefs()->IsManagedPreference(prefs::kShowHomeButton));
+ SetBooleanPrefValueFromSync(prefs::kShowHomeButton, false);
+ EXPECT_FALSE(observer.has_been_notified);
+ EXPECT_TRUE(GetBooleanPrefValue(prefs::kShowHomeButton));
+}
diff --git a/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc b/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
new file mode 100644
index 00000000000..67913e7e49d
--- /dev/null
+++ b/chromium/chrome/browser/prefs/tracked/pref_hash_browsertest.cc
@@ -0,0 +1,1284 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/json/json_reader.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/metrics/statistics_recorder.h"
+#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "build/build_config.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/prefs/chrome_pref_service_factory.h"
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
+#include "chrome/browser/prefs/session_startup_pref.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/prefs/pref_service.h"
+#include "components/prefs/scoped_user_pref_update.h"
+#include "components/search_engines/default_search_manager.h"
+#include "components/search_engines/template_url_data.h"
+#include "content/public/test/test_launcher.h"
+#include "extensions/browser/pref_names.h"
+#include "extensions/common/extension.h"
+#include "services/preferences/public/cpp/tracked/tracked_preference_histogram_names.h"
+
+#if defined(OS_CHROMEOS)
+#include "chromeos/constants/chromeos_switches.h"
+#endif
+
+#if defined(OS_WIN)
+#include "base/win/registry.h"
+#include "chrome/install_static/install_util.h"
+#endif
+
+namespace {
+
+// Extension ID of chrome/test/data/extensions/good.crx
+const char kGoodCrxId[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf";
+
+// Explicit expectations from the caller of GetTrackedPrefHistogramCount(). This
+// enables detailed reporting of the culprit on failure.
+enum AllowedBuckets {
+ // Allow no samples in any buckets.
+ ALLOW_NONE = -1,
+ // Any integer between BEGIN_ALLOW_SINGLE_BUCKET and END_ALLOW_SINGLE_BUCKET
+ // indicates that only this specific bucket is allowed to have a sample.
+ BEGIN_ALLOW_SINGLE_BUCKET = 0,
+ END_ALLOW_SINGLE_BUCKET = 100,
+ // Allow any buckets (no extra verifications performed).
+ ALLOW_ANY
+};
+
+#if defined(OS_WIN)
+base::string16 GetRegistryPathForTestProfile() {
+ // Cleanup follow-up to http://crbug.com/721245 for the previous location of
+ // this test key which had similar problems (to a lesser extent). It's
+ // redundant but harmless to have multiple callers hit this on the same
+ // machine. TODO(gab): remove this mid-june 2017.
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\Chromium\\PrefHashBrowserTest",
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ LONG result = key.DeleteKey(L"");
+ EXPECT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ }
+
+ base::FilePath profile_dir;
+ EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
+
+ // Use a location under the real PreferenceMACs path so that the backup
+ // cleanup logic in ChromeTestLauncherDelegate::PreSharding() for interrupted
+ // tests covers this test key as well.
+ return install_static::GetRegistryPath() +
+ L"\\PreferenceMACs\\PrefHashBrowserTest\\" +
+ profile_dir.BaseName().value();
+}
+#endif
+
+// Returns the number of times |histogram_name| was reported so far; adding the
+// results of the first 100 buckets (there are only ~19 reporting IDs as of this
+// writing; varies depending on the platform). |allowed_buckets| hints at extra
+// requirements verified in this method (see AllowedBuckets for details).
+int GetTrackedPrefHistogramCount(const char* histogram_name,
+ const char* histogram_suffix,
+ int allowed_buckets) {
+ std::string full_histogram_name(histogram_name);
+ if (*histogram_suffix)
+ full_histogram_name.append(".").append(histogram_suffix);
+ const base::HistogramBase* histogram =
+ base::StatisticsRecorder::FindHistogram(full_histogram_name);
+ if (!histogram)
+ return 0;
+
+ std::unique_ptr<base::HistogramSamples> samples(histogram->SnapshotSamples());
+ int sum = 0;
+ for (int i = 0; i < 100; ++i) {
+ int count_for_id = samples->GetCount(i);
+ EXPECT_GE(count_for_id, 0);
+ sum += count_for_id;
+
+ if (allowed_buckets == ALLOW_NONE ||
+ (allowed_buckets != ALLOW_ANY && i != allowed_buckets)) {
+ EXPECT_EQ(0, count_for_id) << "Unexpected reporting_id: " << i;
+ }
+ }
+ return sum;
+}
+
+// Helper function to call GetTrackedPrefHistogramCount with no external
+// validation suffix.
+int GetTrackedPrefHistogramCount(const char* histogram_name,
+ int allowed_buckets) {
+ return GetTrackedPrefHistogramCount(histogram_name, "", allowed_buckets);
+}
+
+std::unique_ptr<base::DictionaryValue> ReadPrefsDictionary(
+ const base::FilePath& pref_file) {
+ JSONFileValueDeserializer deserializer(pref_file);
+ int error_code = JSONFileValueDeserializer::JSON_NO_ERROR;
+ std::string error_str;
+ std::unique_ptr<base::Value> prefs =
+ deserializer.Deserialize(&error_code, &error_str);
+ if (!prefs || error_code != JSONFileValueDeserializer::JSON_NO_ERROR) {
+ ADD_FAILURE() << "Error #" << error_code << ": " << error_str;
+ return std::unique_ptr<base::DictionaryValue>();
+ }
+ if (!prefs->is_dict()) {
+ ADD_FAILURE();
+ return std::unique_ptr<base::DictionaryValue>();
+ }
+ return std::unique_ptr<base::DictionaryValue>(
+ static_cast<base::DictionaryValue*>(prefs.release()));
+}
+
+// Returns whether external validation is supported on the platform through
+// storing MACs in the registry.
+bool SupportsRegistryValidation() {
+#if defined(OS_WIN)
+ return true;
+#else
+ return false;
+#endif
+}
+
+#define PREF_HASH_BROWSER_TEST(fixture, test_name) \
+ IN_PROC_BROWSER_TEST_P(fixture, PRE_##test_name) { SetupPreferences(); } \
+ IN_PROC_BROWSER_TEST_P(fixture, test_name) { VerifyReactionToPrefAttack(); } \
+ INSTANTIATE_TEST_SUITE_P( \
+ fixture##Instance, fixture, \
+ testing::Values( \
+ chrome_prefs::internals::kSettingsEnforcementGroupNoEnforcement, \
+ chrome_prefs::internals::kSettingsEnforcementGroupEnforceAlways, \
+ chrome_prefs::internals:: \
+ kSettingsEnforcementGroupEnforceAlwaysWithDSE, \
+ chrome_prefs::internals:: \
+ kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE))
+
+// A base fixture designed such that implementations do two things:
+// 1) Override all three pure-virtual methods below to setup, attack, and
+// verify preferences throughout the tests provided by this fixture.
+// 2) Instantiate their test via the PREF_HASH_BROWSER_TEST macro above.
+// Based on top of ExtensionBrowserTest to allow easy interaction with the
+// ExtensionRegistry.
+class PrefHashBrowserTestBase
+ : public extensions::ExtensionBrowserTest,
+ public testing::WithParamInterface<std::string> {
+ public:
+ // List of potential protection levels for this test in strict increasing
+ // order of protection levels.
+ enum SettingsProtectionLevel {
+ PROTECTION_DISABLED_ON_PLATFORM,
+ PROTECTION_DISABLED_FOR_GROUP,
+ PROTECTION_ENABLED_BASIC,
+ PROTECTION_ENABLED_DSE,
+ PROTECTION_ENABLED_EXTENSIONS,
+ // Represents the strongest level (i.e. always equivalent to the last one in
+ // terms of protection), leave this one last when adding new levels.
+ PROTECTION_ENABLED_ALL
+ };
+
+ PrefHashBrowserTestBase()
+ : protection_level_(GetProtectionLevelFromTrialGroup(GetParam())) {
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ extensions::ExtensionBrowserTest::SetUpCommandLine(command_line);
+ EXPECT_FALSE(command_line->HasSwitch(switches::kForceFieldTrials));
+ command_line->AppendSwitchASCII(
+ switches::kForceFieldTrials,
+ std::string(chrome_prefs::internals::kSettingsEnforcementTrialName) +
+ "/" + GetParam() + "/");
+#if defined(OS_CHROMEOS)
+ command_line->AppendSwitch(
+ chromeos::switches::kIgnoreUserProfileMappingForTests);
+#endif
+ }
+
+ bool SetUpUserDataDirectory() override {
+ // Do the normal setup in the PRE test and attack preferences in the main
+ // test.
+ if (content::IsPreTest())
+ return extensions::ExtensionBrowserTest::SetUpUserDataDirectory();
+
+#if defined(OS_CHROMEOS)
+ // For some reason, the Preferences file does not exist in the location
+ // below on Chrome OS. Since protection is disabled on Chrome OS, it's okay
+ // to simply not attack preferences at all (and still assert that no
+ // hardening related histogram kicked in in VerifyReactionToPrefAttack()).
+ // TODO(gab): Figure out why there is no Preferences file in this location
+ // on Chrome OS (and re-enable the section disabled for OS_CHROMEOS further
+ // below).
+ EXPECT_EQ(PROTECTION_DISABLED_ON_PLATFORM, protection_level_);
+ return true;
+#endif
+
+ base::FilePath profile_dir;
+ EXPECT_TRUE(base::PathService::Get(chrome::DIR_USER_DATA, &profile_dir));
+ profile_dir = profile_dir.AppendASCII(TestingProfile::kTestUserProfileDir);
+
+ // Sanity check that old protected pref file is never present in modern
+ // Chromes.
+ EXPECT_FALSE(base::PathExists(
+ profile_dir.Append(FILE_PATH_LITERAL("Protected Preferences"))));
+
+ // Read the preferences from disk.
+
+ const base::FilePath unprotected_pref_file =
+ profile_dir.Append(chrome::kPreferencesFilename);
+ EXPECT_TRUE(base::PathExists(unprotected_pref_file));
+
+ const base::FilePath protected_pref_file =
+ profile_dir.Append(chrome::kSecurePreferencesFilename);
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
+ base::PathExists(protected_pref_file));
+
+ std::unique_ptr<base::DictionaryValue> unprotected_preferences(
+ ReadPrefsDictionary(unprotected_pref_file));
+ if (!unprotected_preferences)
+ return false;
+
+ std::unique_ptr<base::DictionaryValue> protected_preferences;
+ if (protection_level_ > PROTECTION_DISABLED_ON_PLATFORM) {
+ protected_preferences = ReadPrefsDictionary(protected_pref_file);
+ if (!protected_preferences)
+ return false;
+ }
+
+ // Let the underlying test modify the preferences.
+ AttackPreferencesOnDisk(unprotected_preferences.get(),
+ protected_preferences.get());
+
+ // Write the modified preferences back to disk.
+
+ JSONFileValueSerializer unprotected_prefs_serializer(unprotected_pref_file);
+ EXPECT_TRUE(
+ unprotected_prefs_serializer.Serialize(*unprotected_preferences));
+
+ if (protected_preferences) {
+ JSONFileValueSerializer protected_prefs_serializer(protected_pref_file);
+ EXPECT_TRUE(protected_prefs_serializer.Serialize(*protected_preferences));
+ }
+
+ return true;
+ }
+
+ void SetUpInProcessBrowserTestFixture() override {
+ extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
+
+ // Bots are on a domain, turn off the domain check for settings hardening in
+ // order to be able to test all SettingsEnforcement groups.
+ chrome_prefs::DisableDomainCheckForTesting();
+
+#if defined(OS_WIN)
+ // Avoid polluting prefs for the user and the bots by writing to a specific
+ // testing registry path.
+ registry_key_for_external_validation_ = GetRegistryPathForTestProfile();
+ ProfilePrefStoreManager::SetPreferenceValidationRegistryPathForTesting(
+ &registry_key_for_external_validation_);
+
+ // Keys should be unique, but to avoid flakes in the long run make sure an
+ // identical test key wasn't left behind by a previous test.
+ if (content::IsPreTest()) {
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER,
+ registry_key_for_external_validation_.c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ LONG result = key.DeleteKey(L"");
+ ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ }
+ }
+#endif
+ }
+
+ void TearDown() override {
+#if defined(OS_WIN)
+ // When done, delete the Registry key to avoid polluting the registry.
+ if (!content::IsPreTest()) {
+ base::string16 registry_key = GetRegistryPathForTestProfile();
+ base::win::RegKey key;
+ if (key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY) == ERROR_SUCCESS) {
+ LONG result = key.DeleteKey(L"");
+ ASSERT_TRUE(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
+ }
+ }
+#endif
+ extensions::ExtensionBrowserTest::TearDown();
+ }
+
+ // In the PRE_ test, find the number of tracked preferences that were
+ // initialized and save it to a file to be read back in the main test and used
+ // as the total number of tracked preferences.
+ void SetUpOnMainThread() override {
+ extensions::ExtensionBrowserTest::SetUpOnMainThread();
+
+ // File in which the PRE_ test will save the number of tracked preferences
+ // on this platform.
+ const char kNumTrackedPrefFilename[] = "NumTrackedPrefs";
+
+ base::FilePath num_tracked_prefs_file;
+ ASSERT_TRUE(
+ base::PathService::Get(chrome::DIR_USER_DATA, &num_tracked_prefs_file));
+ num_tracked_prefs_file =
+ num_tracked_prefs_file.AppendASCII(kNumTrackedPrefFilename);
+
+ if (content::IsPreTest()) {
+ num_tracked_prefs_ = GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized, ALLOW_ANY);
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
+ num_tracked_prefs_ > 0);
+
+ // Split tracked prefs are reported as Unchanged not as NullInitialized
+ // when an empty dictionary is encountered on first run (this should only
+ // hit for pref #5 in the current design).
+ int num_split_tracked_prefs = GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+ BEGIN_ALLOW_SINGLE_BUCKET + 5);
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ num_split_tracked_prefs);
+
+ if (SupportsRegistryValidation()) {
+ // Same checks as above, but for the registry.
+ num_tracked_prefs_ = GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ ALLOW_ANY);
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
+ num_tracked_prefs_ > 0);
+
+ int num_split_tracked_prefs = GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 5);
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ num_split_tracked_prefs);
+ }
+
+ num_tracked_prefs_ += num_split_tracked_prefs;
+
+ std::string num_tracked_prefs_str =
+ base::NumberToString(num_tracked_prefs_);
+ EXPECT_EQ(static_cast<int>(num_tracked_prefs_str.size()),
+ base::WriteFile(num_tracked_prefs_file,
+ num_tracked_prefs_str.c_str(),
+ num_tracked_prefs_str.size()));
+ } else {
+ std::string num_tracked_prefs_str;
+ EXPECT_TRUE(base::ReadFileToString(num_tracked_prefs_file,
+ &num_tracked_prefs_str));
+ EXPECT_TRUE(
+ base::StringToInt(num_tracked_prefs_str, &num_tracked_prefs_));
+ }
+ }
+
+ protected:
+ // Called from the PRE_ test's body. Overrides should use it to setup
+ // preferences through Chrome.
+ virtual void SetupPreferences() = 0;
+
+ // Called prior to the main test launching its browser. Overrides should use
+ // it to attack preferences. |(un)protected_preferences| represent the state
+ // on disk prior to launching the main test, they can be modified by this
+ // method and modifications will be flushed back to disk before launching the
+ // main test. |unprotected_preferences| is never NULL, |protected_preferences|
+ // may be NULL if in PROTECTION_DISABLED_ON_PLATFORM mode.
+ virtual void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) = 0;
+
+ // Called from the body of the main test. Overrides should use it to verify
+ // that the browser had the desired reaction when faced when the attack
+ // orchestrated in AttackPreferencesOnDisk().
+ virtual void VerifyReactionToPrefAttack() = 0;
+
+ int num_tracked_prefs() const { return num_tracked_prefs_; }
+
+ const SettingsProtectionLevel protection_level_;
+
+ private:
+ SettingsProtectionLevel GetProtectionLevelFromTrialGroup(
+ const std::string& trial_group) {
+ if (!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking)
+ return PROTECTION_DISABLED_ON_PLATFORM;
+
+// Protection levels can't be adjusted via --force-fieldtrials in official
+// builds.
+#if defined(OFFICIAL_BUILD)
+
+#if defined(OS_WIN) || defined(OS_MACOSX)
+ // The strongest mode is enforced on Windows and MacOS in the absence of a
+ // field trial.
+ return PROTECTION_ENABLED_ALL;
+#else
+ return PROTECTION_DISABLED_FOR_GROUP;
+#endif // defined(OS_WIN) || defined(OS_MACOSX)
+
+#else // defined(OFFICIAL_BUILD)
+
+ namespace internals = chrome_prefs::internals;
+ if (trial_group == internals::kSettingsEnforcementGroupNoEnforcement)
+ return PROTECTION_DISABLED_FOR_GROUP;
+ if (trial_group == internals::kSettingsEnforcementGroupEnforceAlways)
+ return PROTECTION_ENABLED_BASIC;
+ if (trial_group == internals::kSettingsEnforcementGroupEnforceAlwaysWithDSE)
+ return PROTECTION_ENABLED_DSE;
+ if (trial_group ==
+ internals::kSettingsEnforcementGroupEnforceAlwaysWithExtensionsAndDSE) {
+ return PROTECTION_ENABLED_EXTENSIONS;
+ }
+ ADD_FAILURE();
+ return static_cast<SettingsProtectionLevel>(-1);
+#endif // defined(OFFICIAL_BUILD)
+ }
+
+ int num_tracked_prefs_;
+
+#if defined(OS_WIN)
+ base::string16 registry_key_for_external_validation_;
+#endif
+};
+
+} // namespace
+
+// Verifies that nothing is reset when nothing is tampered with.
+// Also sanity checks that the expected preferences files are in place.
+class PrefHashBrowserTestUnchangedDefault : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ // Default Chrome setup.
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ // No attack.
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Expect all prefs to be reported as Unchanged with no resets.
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs()
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ // Expect all prefs to be reported as Unchanged.
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs()
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ ALLOW_ANY));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUnchangedDefault, UnchangedDefault);
+
+// Augments PrefHashBrowserTestUnchangedDefault to confirm that nothing is reset
+// when nothing is tampered with, even if Chrome itself wrote custom prefs in
+// its last run.
+class PrefHashBrowserTestUnchangedCustom
+ : public PrefHashBrowserTestUnchangedDefault {
+ public:
+ void SetupPreferences() override {
+ profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
+
+ InstallExtensionWithUIAutoConfirm(
+ test_data_dir_.AppendASCII("good.crx"), 1, browser());
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Make sure the settings written in the last run stuck.
+ EXPECT_EQ("http://example.com",
+ profile()->GetPrefs()->GetString(prefs::kHomePage));
+
+ EXPECT_TRUE(extension_registry()->enabled_extensions().GetByID(kGoodCrxId));
+
+ // Reaction should be identical to unattacked default prefs.
+ PrefHashBrowserTestUnchangedDefault::VerifyReactionToPrefAttack();
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUnchangedCustom, UnchangedCustom);
+
+// Verifies that cleared prefs are reported.
+class PrefHashBrowserTestClearedAtomic : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ base::DictionaryValue* selected_prefs =
+ protection_level_ >= PROTECTION_ENABLED_BASIC ? protected_preferences
+ : unprotected_preferences;
+ // |selected_prefs| should never be NULL under the protection level picking
+ // it.
+ EXPECT_TRUE(selected_prefs);
+ EXPECT_TRUE(selected_prefs->Remove(prefs::kHomePage, NULL));
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // The clearance of homepage should have been noticed (as pref #2 being
+ // cleared), but shouldn't have triggered a reset (as there is nothing we
+ // can do when the pref is already gone).
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs() - 1
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ // Expect homepage clearance to have been noticed by registry validation.
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestClearedAtomic, ClearedAtomic);
+
+// Verifies that clearing the MACs results in untrusted Initialized pings for
+// non-null protected prefs.
+class PrefHashBrowserTestUntrustedInitialized : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ // Explicitly set the DSE (it's otherwise NULL by default, preventing
+ // thorough testing of the PROTECTION_ENABLED_DSE level).
+ DefaultSearchManager default_search_manager(
+ profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
+ DefaultSearchManager::Source dse_source =
+ static_cast<DefaultSearchManager::Source>(-1);
+
+ const TemplateURLData* default_template_url_data =
+ default_search_manager.GetDefaultSearchEngine(&dse_source);
+ EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, dse_source);
+
+ default_search_manager.SetUserSelectedDefaultSearchEngine(
+ *default_template_url_data);
+
+ default_search_manager.GetDefaultSearchEngine(&dse_source);
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
+
+ // Also explicitly set an atomic pref that falls under
+ // PROTECTION_ENABLED_BASIC.
+ profile()->GetPrefs()->SetInteger(prefs::kRestoreOnStartup,
+ SessionStartupPref::URLS);
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ unprotected_preferences->Remove("protection.macs", NULL);
+ if (protected_preferences)
+ protected_preferences->Remove("protection.macs", NULL);
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Preferences that are NULL by default will be NullInitialized.
+ int num_null_values = GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized, ALLOW_ANY);
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM,
+ num_null_values > 0);
+ if (num_null_values > 0) {
+ // This test requires that at least 3 prefs be non-null (extensions, DSE,
+ // and 1 atomic pref explictly set for this test above).
+ EXPECT_GE(num_tracked_prefs() - num_null_values, 3);
+ }
+
+ // Expect all non-null prefs to be reported as Initialized (with
+ // accompanying resets or wanted resets based on the current protection
+ // level).
+ EXPECT_EQ(
+ num_tracked_prefs() - num_null_values,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized, ALLOW_ANY));
+
+ int num_protected_prefs = 0;
+ // A switch statement falling through each protection level in decreasing
+ // levels of protection to add expectations for each level which augments
+ // the previous one.
+ switch (protection_level_) {
+ case PROTECTION_ENABLED_ALL:
+ case PROTECTION_ENABLED_EXTENSIONS:
+ ++num_protected_prefs;
+ FALLTHROUGH;
+ case PROTECTION_ENABLED_DSE:
+ ++num_protected_prefs;
+ FALLTHROUGH;
+ case PROTECTION_ENABLED_BASIC:
+ num_protected_prefs += num_tracked_prefs() - num_null_values - 2;
+ FALLTHROUGH;
+ case PROTECTION_DISABLED_FOR_GROUP:
+ case PROTECTION_DISABLED_ON_PLATFORM:
+ // No protection.
+ break;
+ }
+
+ EXPECT_EQ(
+ num_tracked_prefs() - num_null_values - num_protected_prefs,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset, ALLOW_ANY));
+ EXPECT_EQ(num_protected_prefs,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_ANY));
+
+ // Explicitly verify the result of reported resets.
+
+ DefaultSearchManager default_search_manager(
+ profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
+ DefaultSearchManager::Source dse_source =
+ static_cast<DefaultSearchManager::Source>(-1);
+ default_search_manager.GetDefaultSearchEngine(&dse_source);
+ EXPECT_EQ(protection_level_ < PROTECTION_ENABLED_DSE
+ ? DefaultSearchManager::FROM_USER
+ : DefaultSearchManager::FROM_FALLBACK,
+ dse_source);
+
+ EXPECT_EQ(protection_level_ < PROTECTION_ENABLED_BASIC,
+ profile()->GetPrefs()->GetInteger(prefs::kRestoreOnStartup) ==
+ SessionStartupPref::URLS);
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged, ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ // The MACs have been cleared but the preferences have not been tampered.
+ // The registry should report all prefs as unchanged.
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs()
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ ALLOW_ANY));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedInitialized,
+ UntrustedInitialized);
+
+// Verifies that changing an atomic pref results in it being reported (and reset
+// if the protection level allows it).
+class PrefHashBrowserTestChangedAtomic : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ profile()->GetPrefs()->SetInteger(prefs::kRestoreOnStartup,
+ SessionStartupPref::URLS);
+
+ ListPrefUpdate update(profile()->GetPrefs(),
+ prefs::kURLsToRestoreOnStartup);
+ update->AppendString("http://example.com");
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ base::DictionaryValue* selected_prefs =
+ protection_level_ >= PROTECTION_ENABLED_BASIC ? protected_preferences
+ : unprotected_preferences;
+ // |selected_prefs| should never be NULL under the protection level picking
+ // it.
+ EXPECT_TRUE(selected_prefs);
+ base::ListValue* startup_urls;
+ EXPECT_TRUE(
+ selected_prefs->GetList(prefs::kURLsToRestoreOnStartup, &startup_urls));
+ EXPECT_TRUE(startup_urls);
+ EXPECT_EQ(1U, startup_urls->GetSize());
+ startup_urls->AppendString("http://example.org");
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Expect a single Changed event for tracked pref #4 (startup URLs).
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ BEGIN_ALLOW_SINGLE_BUCKET + 4));
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs() - 1
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+ EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+ protection_level_ < PROTECTION_ENABLED_BASIC)
+ ? 1
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+ BEGIN_ALLOW_SINGLE_BUCKET + 4));
+ EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_BASIC ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset,
+ BEGIN_ALLOW_SINGLE_BUCKET + 4));
+
+// TODO(gab): This doesn't work on OS_CHROMEOS because we fail to attack
+// Preferences.
+#if !defined(OS_CHROMEOS)
+ // Explicitly verify the result of reported resets.
+ EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_BASIC ? 0U : 2U,
+ profile()
+ ->GetPrefs()
+ ->GetList(prefs::kURLsToRestoreOnStartup)
+ ->GetSize());
+#endif
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ // Expect a single Changed event for tracked pref #4 (startup URLs).
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 4));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestChangedAtomic, ChangedAtomic);
+
+// Verifies that changing or adding an entry in a split pref results in both
+// items being reported (and remove if the protection level allows it).
+class PrefHashBrowserTestChangedSplitPref : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ InstallExtensionWithUIAutoConfirm(
+ test_data_dir_.AppendASCII("good.crx"), 1, browser());
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ base::DictionaryValue* selected_prefs =
+ protection_level_ >= PROTECTION_ENABLED_EXTENSIONS
+ ? protected_preferences
+ : unprotected_preferences;
+ // |selected_prefs| should never be NULL under the protection level picking
+ // it.
+ EXPECT_TRUE(selected_prefs);
+ base::DictionaryValue* extensions_dict;
+ EXPECT_TRUE(selected_prefs->GetDictionary(
+ extensions::pref_names::kExtensions, &extensions_dict));
+ EXPECT_TRUE(extensions_dict);
+
+ // Tamper with any installed setting for good.crx
+ base::DictionaryValue* good_crx_dict;
+ EXPECT_TRUE(extensions_dict->GetDictionary(kGoodCrxId, &good_crx_dict));
+ int good_crx_state;
+ EXPECT_TRUE(good_crx_dict->GetInteger("state", &good_crx_state));
+ EXPECT_EQ(extensions::Extension::ENABLED, good_crx_state);
+ good_crx_dict->SetInteger("state", extensions::Extension::DISABLED);
+
+ // Drop a fake extension (for the purpose of this test, dropped settings
+ // don't need to be valid extension settings).
+ auto fake_extension = std::make_unique<base::DictionaryValue>();
+ fake_extension->SetString("name", "foo");
+ extensions_dict->Set(std::string(32, 'a'), std::move(fake_extension));
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Expect a single split pref changed report with a count of 2 for tracked
+ // pref #5 (extensions).
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ BEGIN_ALLOW_SINGLE_BUCKET + 5));
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ "Settings.TrackedSplitPreferenceChanged.extensions.settings",
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+
+ // Everything else should have remained unchanged.
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs() - 1
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+ EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+ protection_level_ < PROTECTION_ENABLED_EXTENSIONS)
+ ? 1
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+ BEGIN_ALLOW_SINGLE_BUCKET + 5));
+ EXPECT_EQ(protection_level_ >= PROTECTION_ENABLED_EXTENSIONS ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset,
+ BEGIN_ALLOW_SINGLE_BUCKET + 5));
+
+ EXPECT_EQ(
+ protection_level_ < PROTECTION_ENABLED_EXTENSIONS,
+ extension_registry()->GetExtensionById(
+ kGoodCrxId, extensions::ExtensionRegistry::EVERYTHING) != nullptr);
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ // Expect that the registry validation caught the invalid MAC in split
+ // pref #5 (extensions).
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 5));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestChangedSplitPref, ChangedSplitPref);
+
+// Verifies that adding a value to unprotected preferences for a key which is
+// still using the default (i.e. has no value stored in protected preferences)
+// doesn't allow that value to slip in with no valid MAC (regression test for
+// http://crbug.com/414554)
+class PrefHashBrowserTestUntrustedAdditionToPrefs
+ : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ // Ensure there is no user-selected value for kRestoreOnStartup.
+ EXPECT_FALSE(
+ profile()->GetPrefs()->GetUserPrefValue(prefs::kRestoreOnStartup));
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ unprotected_preferences->SetInteger(prefs::kRestoreOnStartup,
+ SessionStartupPref::LAST);
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Expect a single Changed event for tracked pref #3 (kRestoreOnStartup) if
+ // not protecting; if protection is enabled the change should be a no-op.
+ int changed_expected =
+ protection_level_ == PROTECTION_DISABLED_FOR_GROUP ? 1 : 0;
+ EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+ protection_level_ < PROTECTION_ENABLED_BASIC)
+ ? changed_expected
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ BEGIN_ALLOW_SINGLE_BUCKET + 3));
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs() - changed_expected
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+ EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+ protection_level_ < PROTECTION_ENABLED_BASIC)
+ ? 1
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+ BEGIN_ALLOW_SINGLE_BUCKET + 3));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared, ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ EXPECT_EQ((protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+ protection_level_ < PROTECTION_ENABLED_BASIC)
+ ? changed_expected
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 3));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefs,
+ UntrustedAdditionToPrefs);
+
+// Verifies that adding a value to unprotected preferences while wiping a
+// user-selected value from protected preferences doesn't allow that value to
+// slip in with no valid MAC (regression test for http://crbug.com/414554).
+class PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe
+ : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ // Set or change the value in Preferences to the attacker's choice.
+ unprotected_preferences->SetString(prefs::kHomePage, "http://example.net");
+ // Clear the value in Secure Preferences, if any.
+ if (protected_preferences)
+ protected_preferences->Remove(prefs::kHomePage, NULL);
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ // Expect a single Changed event for tracked pref #2 (kHomePage) if
+ // not protecting; if protection is enabled the change should be a Cleared.
+ int changed_expected =
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM &&
+ protection_level_ < PROTECTION_ENABLED_BASIC
+ ? 1 : 0;
+ int cleared_expected =
+ protection_level_ >= PROTECTION_ENABLED_BASIC
+ ? 1 : 0;
+ EXPECT_EQ(changed_expected,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ EXPECT_EQ(cleared_expected,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs() - changed_expected - cleared_expected
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+ EXPECT_EQ(changed_expected,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramWantedReset,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramReset, ALLOW_NONE));
+
+ // Nothing else should have triggered.
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramTrustedInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramNullInitialized,
+ ALLOW_NONE));
+ EXPECT_EQ(
+ 0, GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramMigratedLegacyDeviceId,
+ ALLOW_NONE));
+
+ if (SupportsRegistryValidation()) {
+ EXPECT_EQ(changed_expected,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ EXPECT_EQ(cleared_expected,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramCleared,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestUntrustedAdditionToPrefsAfterWipe,
+ UntrustedAdditionToPrefsAfterWipe);
+
+#if defined(OS_WIN)
+class PrefHashBrowserTestRegistryValidationFailure
+ : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ profile()->GetPrefs()->SetString(prefs::kHomePage, "http://example.com");
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ base::string16 registry_key =
+ GetRegistryPathForTestProfile() + L"\\PreferenceMACs\\Default";
+ base::win::RegKey key;
+ ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, registry_key.c_str(),
+ KEY_SET_VALUE | KEY_WOW64_32KEY));
+ // An incorrect hash should still have the correct size.
+ ASSERT_EQ(ERROR_SUCCESS,
+ key.WriteValue(L"homepage", base::string16(64, 'A').c_str()));
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ EXPECT_EQ(
+ protection_level_ > PROTECTION_DISABLED_ON_PLATFORM
+ ? num_tracked_prefs()
+ : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramUnchanged, ALLOW_ANY));
+
+ if (SupportsRegistryValidation()) {
+ // Expect that the registry validation caught the invalid MAC for pref #2
+ // (homepage).
+ EXPECT_EQ(protection_level_ > PROTECTION_DISABLED_ON_PLATFORM ? 1 : 0,
+ GetTrackedPrefHistogramCount(
+ user_prefs::tracked::kTrackedPrefHistogramChanged,
+ user_prefs::tracked::kTrackedPrefRegistryValidationSuffix,
+ BEGIN_ALLOW_SINGLE_BUCKET + 2));
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestRegistryValidationFailure,
+ RegistryValidationFailure);
+#endif
+
+// Verifies that all preferences related to choice of default search engine are
+// protected.
+class PrefHashBrowserTestDefaultSearch : public PrefHashBrowserTestBase {
+ public:
+ void SetupPreferences() override {
+ // Set user selected default search engine.
+ DefaultSearchManager default_search_manager(
+ profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
+ DefaultSearchManager::Source dse_source =
+ static_cast<DefaultSearchManager::Source>(-1);
+
+ TemplateURLData user_dse;
+ user_dse.SetKeyword(base::UTF8ToUTF16("userkeyword"));
+ user_dse.SetShortName(base::UTF8ToUTF16("username"));
+ user_dse.SetURL("http://user_default_engine/search?q=good_user_query");
+ default_search_manager.SetUserSelectedDefaultSearchEngine(user_dse);
+
+ const TemplateURLData* current_dse =
+ default_search_manager.GetDefaultSearchEngine(&dse_source);
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
+ EXPECT_EQ(current_dse->keyword(), base::UTF8ToUTF16("userkeyword"));
+ EXPECT_EQ(current_dse->short_name(), base::UTF8ToUTF16("username"));
+ EXPECT_EQ(current_dse->url(),
+ "http://user_default_engine/search?q=good_user_query");
+ }
+
+ void AttackPreferencesOnDisk(
+ base::DictionaryValue* unprotected_preferences,
+ base::DictionaryValue* protected_preferences) override {
+ static constexpr char default_search_provider_data[] = R"(
+ {
+ "default_search_provider_data" : {
+ "template_url_data" : {
+ "keyword" : "badkeyword",
+ "short_name" : "badname",
+ "url" : "http://bad_default_engine/search?q=dirty_user_query"
+ }
+ }
+ })";
+ static constexpr char search_provider_overrides[] = R"(
+ {
+ "search_provider_overrides" : [
+ {
+ "keyword" : "badkeyword",
+ "name" : "badname",
+ "search_url" : "http://bad_default_engine/search?q=dirty_user_query",
+ "encoding" : "utf-8",
+ "id" : 1
+ }, {
+ "keyword" : "badkeyword2",
+ "name" : "badname2",
+ "search_url" : "http://bad_default_engine2/search?q=dirty_user_query",
+ "encoding" : "utf-8",
+ "id" : 2
+ }
+ ]
+ })";
+
+ // Try to override default search in all three of available preferences.
+ auto attack1 = base::DictionaryValue::From(
+ base::JSONReader::ReadDeprecated(default_search_provider_data));
+ auto attack2 = base::DictionaryValue::From(
+ base::JSONReader::ReadDeprecated(search_provider_overrides));
+ unprotected_preferences->MergeDictionary(attack1.get());
+ unprotected_preferences->MergeDictionary(attack2.get());
+ if (protected_preferences) {
+ // Override here, too.
+ protected_preferences->MergeDictionary(attack1.get());
+ protected_preferences->MergeDictionary(attack2.get());
+ }
+ }
+
+ void VerifyReactionToPrefAttack() override {
+ DefaultSearchManager default_search_manager(
+ profile()->GetPrefs(), DefaultSearchManager::ObserverCallback());
+ DefaultSearchManager::Source dse_source =
+ static_cast<DefaultSearchManager::Source>(-1);
+
+ const TemplateURLData* current_dse =
+ default_search_manager.GetDefaultSearchEngine(&dse_source);
+
+ if (protection_level_ < PROTECTION_ENABLED_DSE) {
+// This doesn't work on OS_CHROMEOS because we fail to attack Preferences.
+#if !defined(OS_CHROMEOS)
+ // Attack is successful.
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, dse_source);
+ EXPECT_EQ(current_dse->keyword(), base::UTF8ToUTF16("badkeyword"));
+ EXPECT_EQ(current_dse->short_name(), base::UTF8ToUTF16("badname"));
+ EXPECT_EQ(current_dse->url(),
+ "http://bad_default_engine/search?q=dirty_user_query");
+#endif
+ } else {
+ // Attack fails.
+ EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, dse_source);
+ EXPECT_NE(current_dse->keyword(), base::UTF8ToUTF16("badkeyword"));
+ EXPECT_NE(current_dse->short_name(), base::UTF8ToUTF16("badname"));
+ EXPECT_NE(current_dse->url(),
+ "http://bad_default_engine/search?q=dirty_user_query");
+ }
+ }
+};
+
+PREF_HASH_BROWSER_TEST(PrefHashBrowserTestDefaultSearch, SearchProtected);