OLD | NEW |
---|---|
(Empty) | |
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 #include "chrome/browser/android/search_geolocation/search_geolocation_service.h " | |
6 | |
7 #include "base/feature_list.h" | |
8 #include "base/values.h" | |
9 #include "chrome/browser/android/search_geolocation/search_geolocation_disclosur e_tab_helper.h" | |
10 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | |
11 #include "chrome/browser/profiles/profile.h" | |
12 #include "chrome/browser/search_engines/template_url_service_factory.h" | |
13 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h" | |
14 #include "chrome/common/chrome_features.h" | |
15 #include "chrome/common/pref_names.h" | |
16 #include "components/content_settings/core/browser/content_settings_utils.h" | |
17 #include "components/content_settings/core/browser/host_content_settings_map.h" | |
18 #include "components/content_settings/core/common/content_settings_types.h" | |
19 #include "components/keyed_service/content/browser_context_dependency_manager.h" | |
20 #include "components/pref_registry/pref_registry_syncable.h" | |
21 #include "components/prefs/pref_service.h" | |
22 #include "components/search_engines/template_url.h" | |
23 #include "components/search_engines/template_url_service.h" | |
24 #include "url/gurl.h" | |
25 #include "url/url_constants.h" | |
26 | |
27 namespace { | |
28 | |
29 const char kIsGoogleSearchEngineKey[] = "is_google_search_engine"; | |
30 const char kCCTLDKey[] = "cctld"; | |
31 const char kDSESettingKey[] = "dse_setting"; | |
32 | |
33 } // namespace | |
34 | |
35 struct SearchGeolocationService::PrefValue { | |
36 bool is_google_search_engine = false; | |
37 url::Origin cctld; | |
38 bool setting = false; | |
39 }; | |
40 | |
41 // static | |
42 SearchGeolocationService* | |
43 SearchGeolocationService::Factory::GetForBrowserContext( | |
44 content::BrowserContext* context) { | |
45 return static_cast<SearchGeolocationService*>(GetInstance() | |
46 ->GetServiceForBrowserContext(context, true)); | |
47 } | |
48 | |
49 // static | |
50 SearchGeolocationService::Factory* | |
51 SearchGeolocationService::Factory::GetInstance() { | |
52 return base::Singleton<SearchGeolocationService::Factory>::get(); | |
53 } | |
54 | |
55 SearchGeolocationService::Factory::Factory() | |
56 : BrowserContextKeyedServiceFactory( | |
57 "SearchGeolocationService", | |
58 BrowserContextDependencyManager::GetInstance()) { | |
59 DependsOn(HostContentSettingsMapFactory::GetInstance()); | |
60 DependsOn(TemplateURLServiceFactory::GetInstance()); | |
61 } | |
62 | |
63 SearchGeolocationService::Factory::~Factory() {} | |
64 | |
65 bool SearchGeolocationService::Factory::ServiceIsCreatedWithBrowserContext() | |
66 const { | |
67 return true; | |
68 } | |
69 | |
70 KeyedService* SearchGeolocationService::Factory::BuildServiceInstanceFor( | |
71 content::BrowserContext* context) const { | |
72 return new SearchGeolocationService(Profile::FromBrowserContext(context)); | |
73 } | |
74 | |
75 // static | |
76 void SearchGeolocationService::RegisterProfilePrefs( | |
77 user_prefs::PrefRegistrySyncable* registry) { | |
78 registry->RegisterDictionaryPref(prefs::kGoogleDSEGeolocationSetting); | |
79 } | |
80 | |
81 SearchGeolocationService::SearchGeolocationService(Profile* profile) | |
82 : profile_(profile), | |
83 pref_service_(profile_->GetPrefs()), | |
84 host_content_settings_map_( | |
85 HostContentSettingsMapFactory::GetForProfile(profile_)), | |
86 template_url_service_( | |
87 TemplateURLServiceFactory::GetForProfile(profile_)) { | |
88 if (!UseConsistentSearchGeolocation()) | |
89 return; | |
90 | |
91 template_url_service_->AddObserver(this); | |
92 | |
93 InitializeDSEGeolocationSettingIfNeeded(); | |
94 | |
95 // Make sure the setting is valid now. It's possible that the setting has | |
96 // become invalid either by changes being made to enterprise policy, or while | |
97 // the flag to enable consistent search geolocation was off. | |
98 EnsureDSEGeolocationSettingIsValid(); | |
99 } | |
100 | |
101 bool SearchGeolocationService::UseDSEGeolocationSetting( | |
102 const url::Origin& requesting_origin) { | |
103 if (!UseConsistentSearchGeolocation()) | |
104 return false; | |
105 | |
106 if (profile_->IsOffTheRecord()) | |
107 return false; | |
108 | |
109 if (requesting_origin.scheme() != url::kHttpsScheme) | |
110 return false; | |
111 | |
112 if (!requesting_origin.IsSameOriginWith(GetDSECCTLD())) | |
113 return false; | |
114 | |
115 // If the content setting for the DSE CCTLD is controlled by policy, and is st | |
116 // to ASK, don't use the DSE geolocation setting. | |
117 if (!IsContentSettingUserSettable() && | |
118 GetCurrentContentSetting() == CONTENT_SETTING_ASK) { | |
raymes
2017/01/11 08:30:12
I'm not sure if the check for ASK is actually need
benwells
2017/01/11 09:26:11
We can chat about it more tomorrow. I think it is
| |
119 return false; | |
120 } | |
121 | |
122 return true; | |
123 } | |
124 | |
125 bool SearchGeolocationService::GetDSEGeolocationSetting() { | |
126 // Make sure the setting is valid, in case enterprise policy has changed. | |
127 // TODO(benwells): Check if enterprise policy can change while Chrome is | |
128 // running. If it can't this call is probably not needed. | |
129 EnsureDSEGeolocationSettingIsValid(); | |
130 | |
131 return GetDSEGeolocationPref().setting; | |
132 } | |
133 | |
134 void SearchGeolocationService::SetDSEGeolocationSetting(bool setting) { | |
135 PrefValue pref = GetDSEGeolocationPref(); | |
136 if (setting == pref.setting) | |
137 return; | |
138 | |
139 // If the user cannot change their geolocation content setting (e.g. due to | |
140 // enterprise policy), they also can't change this preference so just bail | |
141 // out. | |
142 if (!IsContentSettingUserSettable()) | |
143 return; | |
144 | |
145 pref.setting = setting; | |
146 SetDSEGeolocationPref(pref); | |
147 | |
148 ResetContentSetting(); | |
149 } | |
150 | |
151 void SearchGeolocationService::Shutdown() { | |
152 if (UseConsistentSearchGeolocation()) | |
153 template_url_service_->RemoveObserver(this); | |
154 } | |
155 | |
156 SearchGeolocationService::~SearchGeolocationService() {} | |
157 | |
158 void SearchGeolocationService::OnTemplateURLServiceChanged() { | |
159 bool is_now_google_search_engine = IsGoogleSearchEngine(); | |
160 PrefValue pref = GetDSEGeolocationPref(); | |
161 ContentSetting content_setting = GetCurrentContentSetting(); | |
162 | |
163 if (is_now_google_search_engine) { | |
164 if (content_setting == CONTENT_SETTING_BLOCK && pref.setting) { | |
165 pref.setting = false; | |
166 } else if (content_setting == CONTENT_SETTING_ALLOW && !pref.setting) { | |
167 ResetContentSetting(); | |
168 } | |
169 } | |
170 | |
171 if (is_now_google_search_engine && !pref.is_google_search_engine && | |
172 pref.setting) { | |
173 SearchGeolocationDisclosureTabHelper::ResetDisclosure(profile_); | |
174 } | |
175 | |
176 pref.is_google_search_engine = is_now_google_search_engine; | |
177 pref.cctld = GetDSECCTLD(); | |
178 SetDSEGeolocationPref(pref); | |
179 } | |
180 | |
181 void SearchGeolocationService::InitializeDSEGeolocationSettingIfNeeded() { | |
182 // Initialize the pref if it hasn't been initialized yet. | |
183 if (!pref_service_->HasPrefPath(prefs::kGoogleDSEGeolocationSetting)) { | |
184 ContentSetting content_setting = GetCurrentContentSetting(); | |
185 | |
186 PrefValue pref; | |
187 pref.is_google_search_engine = IsGoogleSearchEngine(); | |
188 pref.cctld = GetDSECCTLD(); | |
189 pref.setting = content_setting != CONTENT_SETTING_BLOCK; | |
190 SetDSEGeolocationPref(pref); | |
191 | |
192 SearchGeolocationDisclosureTabHelper::ResetDisclosure(profile_); | |
193 } | |
194 } | |
195 | |
196 void SearchGeolocationService::EnsureDSEGeolocationSettingIsValid() { | |
197 PrefValue pref = GetDSEGeolocationPref(); | |
198 ContentSetting content_setting = GetCurrentContentSetting(); | |
199 bool new_setting = pref.setting; | |
200 | |
201 if (pref.setting && content_setting == CONTENT_SETTING_BLOCK) { | |
202 new_setting = false; | |
203 } else if (!pref.setting && content_setting == CONTENT_SETTING_ALLOW) { | |
204 new_setting = true; | |
205 } | |
206 | |
207 if (pref.setting != new_setting) { | |
208 pref.setting = new_setting; | |
209 SetDSEGeolocationPref(pref); | |
210 } | |
211 } | |
212 | |
213 bool SearchGeolocationService::IsGoogleSearchEngine() { | |
214 const TemplateURL* template_url = | |
215 template_url_service_->GetDefaultSearchProvider(); | |
216 return template_url && | |
217 template_url->HasGoogleBaseURLs(UIThreadSearchTermsData(profile_)); | |
218 } | |
219 | |
220 url::Origin SearchGeolocationService::GetDSECCTLD() { | |
221 if (!IsGoogleSearchEngine()) | |
222 return url::Origin(); | |
223 | |
224 GURL origin_url(UIThreadSearchTermsData(profile_).GoogleBaseURLValue()); | |
225 return url::Origin(origin_url); | |
226 } | |
227 | |
228 SearchGeolocationService::PrefValue | |
229 SearchGeolocationService::GetDSEGeolocationPref() { | |
230 const base::DictionaryValue* dict = | |
231 pref_service_->GetDictionary(prefs::kGoogleDSEGeolocationSetting); | |
232 | |
233 PrefValue pref; | |
234 bool is_google_search_engine; | |
235 std::string cctld_string; | |
236 bool setting; | |
237 if (dict->GetBoolean(kIsGoogleSearchEngineKey, &is_google_search_engine) && | |
238 dict->GetString(kCCTLDKey, &cctld_string) && | |
239 dict->GetBoolean(kDSESettingKey, &setting)) { | |
240 pref.is_google_search_engine = is_google_search_engine; | |
241 pref.cctld = url::Origin(GURL(cctld_string)); | |
242 pref.setting = setting; | |
243 } | |
244 | |
245 return pref; | |
246 } | |
247 | |
248 void SearchGeolocationService::SetDSEGeolocationPref( | |
249 const SearchGeolocationService::PrefValue& pref) { | |
250 base::DictionaryValue dict; | |
251 dict.SetBoolean(kIsGoogleSearchEngineKey, pref.is_google_search_engine); | |
252 dict.SetString(kCCTLDKey, pref.cctld.Serialize()); | |
253 dict.SetBoolean(kDSESettingKey, pref.setting); | |
254 pref_service_->Set(prefs::kGoogleDSEGeolocationSetting, dict); | |
255 } | |
256 | |
257 ContentSetting SearchGeolocationService::GetCurrentContentSetting() { | |
258 url::Origin origin = GetDSECCTLD(); | |
259 return host_content_settings_map_->GetContentSetting( | |
260 origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
261 std::string()); | |
262 } | |
263 | |
264 void SearchGeolocationService::ResetContentSetting() { | |
265 url::Origin origin = GetDSECCTLD(); | |
266 host_content_settings_map_->SetContentSettingDefaultScope( | |
267 origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
268 std::string(), CONTENT_SETTING_DEFAULT); | |
269 } | |
270 | |
271 bool SearchGeolocationService::IsContentSettingUserSettable() { | |
272 content_settings::SettingInfo info; | |
273 url::Origin origin = GetDSECCTLD(); | |
274 std::unique_ptr<base::Value> value = | |
275 host_content_settings_map_->GetWebsiteSetting( | |
276 origin.GetURL(), origin.GetURL(), CONTENT_SETTINGS_TYPE_GEOLOCATION, | |
277 std::string(), &info); | |
278 return info.source == content_settings::SETTING_SOURCE_USER; | |
279 } | |
280 | |
281 bool SearchGeolocationService::UseConsistentSearchGeolocation() { | |
282 return base::FeatureList::IsEnabled(features::kConsistentOmniboxGeolocation); | |
283 } | |
OLD | NEW |