1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef CHROME_BROWSER_ANDROID_SEARCH_PERMISSIONS_SEARCH_PERMISSIONS_SERVICE_H_ 6 #define CHROME_BROWSER_ANDROID_SEARCH_PERMISSIONS_SEARCH_PERMISSIONS_SERVICE_H_ 7 8 #include "base/callback_forward.h" 9 #include "base/memory/singleton.h" 10 #include "base/strings/string16.h" 11 #include "components/content_settings/core/common/content_settings.h" 12 #include "components/keyed_service/content/browser_context_keyed_service_factory.h" 13 #include "components/keyed_service/core/keyed_service.h" 14 #include "url/origin.h" 15 16 namespace content { 17 class BrowserContext; 18 } 19 20 namespace user_prefs { 21 class PrefRegistrySyncable; 22 } 23 24 class HostContentSettingsMap; 25 class PrefService; 26 class Profile; 27 28 // Helper class to manage DSE permissions. It keeps the setting valid by 29 // watching change to the CCTLD and DSE. 30 // Glossary: 31 // DSE: Default Search Engine 32 // CCTLD: Country Code Top Level Domain (e.g. google.com.au) 33 class SearchPermissionsService : public KeyedService { 34 public: 35 // Delegate for search engine related functionality. Can be overridden for 36 // testing. 37 class SearchEngineDelegate { 38 public: ~SearchEngineDelegate()39 virtual ~SearchEngineDelegate() {} 40 41 // Returns the name of the current DSE. 42 virtual base::string16 GetDSEName() = 0; 43 44 // Returns the origin of the DSE. If the current DSE is Google this will 45 // return the current CCTLD. 46 virtual url::Origin GetDSEOrigin() = 0; 47 48 // Set a callback that will be called if the DSE or CCTLD changes for any 49 // reason. 50 virtual void SetDSEChangedCallback(base::RepeatingClosure callback) = 0; 51 }; 52 53 // Factory implementation will not create a service in incognito. 54 class Factory : public BrowserContextKeyedServiceFactory { 55 public: 56 static SearchPermissionsService* GetForBrowserContext( 57 content::BrowserContext* context); 58 59 static Factory* GetInstance(); 60 61 private: 62 friend struct base::DefaultSingletonTraits<Factory>; 63 64 Factory(); 65 ~Factory() override; 66 67 // BrowserContextKeyedServiceFactory 68 bool ServiceIsCreatedWithBrowserContext() const override; 69 KeyedService* BuildServiceInstanceFor( 70 content::BrowserContext* profile) const override; 71 void RegisterProfilePrefs( 72 user_prefs::PrefRegistrySyncable* registry) override; 73 }; 74 75 explicit SearchPermissionsService(Profile* profile); 76 77 // Returns whether the given permission is being configured for the DSE for 78 // the given origin. 79 bool IsPermissionControlledByDSE(ContentSettingsType type, 80 const url::Origin& requesting_origin); 81 82 // Resets the DSE permission for a single ContentSettingsType. 83 void ResetDSEPermission(ContentSettingsType type); 84 85 // Reset all supported DSE permissions. 86 void ResetDSEPermissions(); 87 88 // KeyedService: 89 void Shutdown() override; 90 91 private: 92 friend class ChromeBrowsingDataRemoverDelegateTest; 93 friend class SearchPermissionsServiceTest; 94 FRIEND_TEST_ALL_PREFIXES(GeolocationPermissionContextDelegateTests, 95 SearchGeolocationInIncognito); 96 struct PrefValue; 97 98 ~SearchPermissionsService() override; 99 100 // When the DSE CCTLD changes (either by changing their DSE or by changing 101 // their CCTLD) we carry over the geolocation/notification permissions from 102 // the last DSE CCTLD. Before carrying them over, we store the old value 103 // of the permissions in a pref so the user's settings can be restored if 104 // they change DSE in the future. 105 // We resolve conflicts in the following way: 106 // * If the DSE CCTLD origin permission is BLOCK, but the old DSE's permission 107 // is ALLOW, change the DSE permission setting to BLOCK. 108 // * If the DSE CCTLD origin permission is ALLOW, but the old DSE's permission 109 // is BLOCK, change the DSE permission setting to BLOCK but restore it to 110 // ASK later. 111 // * If the user changes the DSE CCTLD origin permission, we restore it back 112 // to ASK when they change DSE. 113 // Also, if the DSE changes and geolocation is enabled, we reset the 114 // geolocation disclosure so that it will be shown again. 115 void OnDSEChanged(); 116 117 // Restore the setting for an origin before it became the DSE. Returns the 118 // setting that the origin was set to before restoring the old value. 119 ContentSetting RestoreOldSettingAndReturnPrevious( 120 const GURL& dse_origin, 121 ContentSettingsType type, 122 ContentSetting setting_to_restore); 123 124 // Helper function for OnDSEChanged which transitions the DSE setting for a 125 // specific permission. It returns the content setting to be restored later 126 // for |new_dse_origin|. 127 ContentSetting UpdatePermissionAndReturnPrevious(ContentSettingsType type, 128 const GURL& old_dse_origin, 129 const GURL& new_dse_origin, 130 ContentSetting old_setting, 131 bool dse_name_changed); 132 133 // Initialize the DSE permission settings if they haven't already been 134 // initialized. Also, if they haven't been initialized, reset whether the DSE 135 // geolocation disclosure has been shown to ensure user who may have seen it 136 // on earlier versions (due to Finch experiments) see it again. 137 void InitializeSettingsIfNeeded(); 138 139 PrefValue GetDSEPref(); 140 void SetDSEPref(const PrefValue& pref); 141 142 // Retrieve the content setting for the given permission/origin. 143 ContentSetting GetContentSetting(const GURL& origin, 144 ContentSettingsType type); 145 // Set the content setting for the given permission/origin. 146 void SetContentSetting(const GURL& origin, 147 ContentSettingsType type, 148 ContentSetting setting); 149 150 void SetSearchEngineDelegateForTest( 151 std::unique_ptr<SearchEngineDelegate> delegate); 152 153 Profile* profile_; 154 PrefService* pref_service_; 155 HostContentSettingsMap* host_content_settings_map_; 156 std::unique_ptr<SearchEngineDelegate> delegate_; 157 }; 158 159 #endif // CHROME_BROWSER_ANDROID_SEARCH_PERMISSIONS_SEARCH_PERMISSIONS_SERVICE_H_ 160