diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-02-13 10:55:42 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-03-05 13:33:38 +0000 |
commit | 248b70b82a40964d5594eb04feca0fa36716185d (patch) | |
tree | 44e31d9dd0ac2cb79f48633eefbc5496e013c347 /chromium/chrome/browser/prefs | |
parent | cabfcdd1db482729ded525feae56911a99792773 (diff) | |
download | qtwebengine-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')
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(®istry_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(®istry_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(®istry_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(®istry_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( + ®istry_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); |