Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: chrome/browser/geolocation/geolocation_permission_context_android.cc

Issue 2742373003: Limit the amount the Location Settings Dialog will be shown to users. (Closed)
Patch Set: Feedback Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/geolocation/geolocation_permission_context_android.h" 5 #include "chrome/browser/geolocation/geolocation_permission_context_android.h"
6 6
7 #include <utility> 7 #include <utility>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/feature_list.h" 11 #include "base/feature_list.h"
12 #include "chrome/browser/android/location_settings.h" 12 #include "chrome/browser/android/location_settings.h"
13 #include "chrome/browser/android/location_settings_impl.h" 13 #include "chrome/browser/android/location_settings_impl.h"
14 #include "chrome/browser/android/search_geolocation/search_geolocation_disclosur e_tab_helper.h" 14 #include "chrome/browser/android/search_geolocation/search_geolocation_disclosur e_tab_helper.h"
15 #include "chrome/browser/android/search_geolocation/search_geolocation_service.h " 15 #include "chrome/browser/android/search_geolocation/search_geolocation_service.h "
16 #include "chrome/browser/permissions/permission_request_id.h" 16 #include "chrome/browser/permissions/permission_request_id.h"
17 #include "chrome/browser/permissions/permission_update_infobar_delegate_android. h" 17 #include "chrome/browser/permissions/permission_update_infobar_delegate_android. h"
18 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/search_engines/template_url_service_factory.h" 19 #include "chrome/browser/search_engines/template_url_service_factory.h"
20 #include "chrome/common/chrome_features.h" 20 #include "chrome/common/chrome_features.h"
21 #include "chrome/common/pref_names.h"
21 #include "components/infobars/core/infobar.h" 22 #include "components/infobars/core/infobar.h"
23 #include "components/prefs/pref_registry_simple.h"
24 #include "components/prefs/pref_service.h"
22 #include "components/search_engines/template_url.h" 25 #include "components/search_engines/template_url.h"
23 #include "components/search_engines/template_url_service.h" 26 #include "components/search_engines/template_url_service.h"
24 #include "content/public/browser/browser_thread.h" 27 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/render_frame_host.h" 28 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/web_contents.h" 29 #include "content/public/browser/web_contents.h"
27 #include "url/gurl.h" 30 #include "url/gurl.h"
28 31
32 namespace {
33
34 int g_day_offset_for_testing = 0;
35
36 const char* g_dse_origin_for_testing = nullptr;
37
38 base::Time GetTimeNow() {
39 return base::Time::Now() +
40 base::TimeDelta::FromDays(g_day_offset_for_testing);
41 }
42
43 } // namespace
44
45 // static
46 void GeolocationPermissionContextAndroid::RegisterProfilePrefs(
47 PrefRegistrySimple* registry) {
48 registry->RegisterIntegerPref(prefs::kLocationSettingsBackoffLevelDSE, 0);
49 registry->RegisterIntegerPref(prefs::kLocationSettingsBackoffLevelDefault, 0);
50 registry->RegisterInt64Pref(prefs::kLocationSettingsNextShowDSE, 0);
51 registry->RegisterInt64Pref(prefs::kLocationSettingsNextShowDefault, 0);
52 }
53
29 GeolocationPermissionContextAndroid:: 54 GeolocationPermissionContextAndroid::
30 GeolocationPermissionContextAndroid(Profile* profile) 55 GeolocationPermissionContextAndroid(Profile* profile)
31 : GeolocationPermissionContext(profile), 56 : GeolocationPermissionContext(profile),
32 location_settings_(new LocationSettingsImpl()), 57 location_settings_(new LocationSettingsImpl()),
33 permission_update_infobar_(nullptr), 58 permission_update_infobar_(nullptr),
34 weak_factory_(this) { 59 weak_factory_(this) {
35 } 60 }
36 61
37 GeolocationPermissionContextAndroid::~GeolocationPermissionContextAndroid() { 62 GeolocationPermissionContextAndroid::~GeolocationPermissionContextAndroid() {
38 } 63 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 } else if (!profile()->IsOffTheRecord()) { 95 } else if (!profile()->IsOffTheRecord()) {
71 // Otherwise, return ALLOW only if this is not incognito. 96 // Otherwise, return ALLOW only if this is not incognito.
72 value = CONTENT_SETTING_ALLOW; 97 value = CONTENT_SETTING_ALLOW;
73 } 98 }
74 } 99 }
75 } 100 }
76 101
77 return value; 102 return value;
78 } 103 }
79 104
105 // static
106 void GeolocationPermissionContextAndroid::AddDayOffsetForTesting(int days) {
107 g_day_offset_for_testing += days;
108 }
109
110 // static
111 void GeolocationPermissionContextAndroid::SetDSEOriginForTesting(
112 const char* dse_origin) {
113 g_dse_origin_for_testing = dse_origin;
114 }
115
80 void GeolocationPermissionContextAndroid::RequestPermission( 116 void GeolocationPermissionContextAndroid::RequestPermission(
81 content::WebContents* web_contents, 117 content::WebContents* web_contents,
82 const PermissionRequestID& id, 118 const PermissionRequestID& id,
83 const GURL& requesting_frame_origin, 119 const GURL& requesting_frame_origin,
84 bool user_gesture, 120 bool user_gesture,
85 const BrowserPermissionCallback& callback) { 121 const BrowserPermissionCallback& callback) {
86 if (!IsLocationAccessPossible(web_contents, requesting_frame_origin, 122 if (!IsLocationAccessPossible(web_contents, requesting_frame_origin,
87 user_gesture)) { 123 user_gesture)) {
88 PermissionDecided(id, requesting_frame_origin, 124 PermissionDecided(id, requesting_frame_origin,
89 web_contents->GetLastCommittedURL().GetOrigin(), 125 web_contents->GetLastCommittedURL().GetOrigin(),
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 content::WebContents* web_contents, 158 content::WebContents* web_contents,
123 const PermissionRequestID& id) { 159 const PermissionRequestID& id) {
124 if (permission_update_infobar_) { 160 if (permission_update_infobar_) {
125 permission_update_infobar_->RemoveSelf(); 161 permission_update_infobar_->RemoveSelf();
126 permission_update_infobar_ = nullptr; 162 permission_update_infobar_ = nullptr;
127 } 163 }
128 164
129 GeolocationPermissionContext::CancelPermissionRequest(web_contents, id); 165 GeolocationPermissionContext::CancelPermissionRequest(web_contents, id);
130 } 166 }
131 167
168 void GeolocationPermissionContextAndroid::UserMadePermissionDecision(
169 const PermissionRequestID& id,
170 const GURL& requesting_origin,
171 const GURL& embedding_origin,
172 ContentSetting content_setting) {
173 // If the user has accepted geolocation, reset the location settings dialog
174 // backoff.
175 if (content_setting == CONTENT_SETTING_ALLOW)
176 ResetLocationSettingsBackOff(requesting_origin);
177 }
178
132 void GeolocationPermissionContextAndroid::NotifyPermissionSet( 179 void GeolocationPermissionContextAndroid::NotifyPermissionSet(
133 const PermissionRequestID& id, 180 const PermissionRequestID& id,
134 const GURL& requesting_origin, 181 const GURL& requesting_origin,
135 const GURL& embedding_origin, 182 const GURL& embedding_origin,
136 const BrowserPermissionCallback& callback, 183 const BrowserPermissionCallback& callback,
137 bool persist, 184 bool persist,
138 ContentSetting content_setting) { 185 ContentSetting content_setting) {
139 if (content_setting == CONTENT_SETTING_ALLOW && 186 if (content_setting == CONTENT_SETTING_ALLOW &&
140 !location_settings_->IsSystemLocationSettingEnabled()) { 187 !location_settings_->IsSystemLocationSettingEnabled()) {
141 // There is no need to check CanShowLocationSettingsDialog here again, as it 188 // There is no need to check CanShowLocationSettingsDialog here again, as it
142 // must have been checked to get this far. 189 // must have been checked to get this far. But, the backoff will not have
190 // been checked, so check that. Backoff isn't checked earlier because if the
191 // content setting is ASK the backoff should be ignored. However if we get
192 // here and the content setting was ASK, the user must have accepted which
193 // would reset the backoff.
194 if (IsInLocationSettingsBackOff(requesting_origin)) {
195 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin,
196 callback, false /* persist */,
197 CONTENT_SETTING_BLOCK);
198 return;
199 }
200
143 content::WebContents* web_contents = 201 content::WebContents* web_contents =
144 content::WebContents::FromRenderFrameHost( 202 content::WebContents::FromRenderFrameHost(
145 content::RenderFrameHost::FromID(id.render_process_id(), 203 content::RenderFrameHost::FromID(id.render_process_id(),
146 id.render_frame_id())); 204 id.render_frame_id()));
147 location_settings_->PromptToEnableSystemLocationSetting( 205 location_settings_->PromptToEnableSystemLocationSetting(
148 GetLocationSettingsDialogContext(requesting_origin), web_contents, 206 IsRequestingOriginDSE(requesting_origin) ? SEARCH : DEFAULT,
207 web_contents,
149 base::BindOnce( 208 base::BindOnce(
150 &GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown, 209 &GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown,
151 weak_factory_.GetWeakPtr(), id, requesting_origin, embedding_origin, 210 weak_factory_.GetWeakPtr(), id, requesting_origin, embedding_origin,
152 callback, persist, content_setting)); 211 callback, persist, content_setting));
153 return; 212 return;
154 } 213 }
155 214
156 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 215 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
157 persist, content_setting); 216 persist, content_setting);
158 } 217 }
159 218
160 PermissionResult 219 PermissionResult
161 GeolocationPermissionContextAndroid::UpdatePermissionStatusWithDeviceStatus( 220 GeolocationPermissionContextAndroid::UpdatePermissionStatusWithDeviceStatus(
162 PermissionResult result, 221 PermissionResult result,
163 const GURL& requesting_origin, 222 const GURL& requesting_origin,
164 const GURL& embedding_origin) const { 223 const GURL& embedding_origin) const {
165 if (base::FeatureList::IsEnabled(features::kLsdPermissionPrompt) && 224 if (base::FeatureList::IsEnabled(features::kLsdPermissionPrompt) &&
166 result.content_setting != CONTENT_SETTING_BLOCK) { 225 result.content_setting != CONTENT_SETTING_BLOCK) {
167 if (!location_settings_->IsSystemLocationSettingEnabled()) { 226 if (!location_settings_->IsSystemLocationSettingEnabled()) {
168 // As this is returning the status for possible future permission 227 // As this is returning the status for possible future permission
169 // requests, whose gesture status is unknown, pretend there is a user 228 // requests, whose gesture status is unknown, pretend there is a user
170 // gesture here. If there is a possibility of PROMPT (i.e. if there is a 229 // gesture here. If there is a possibility of PROMPT (i.e. if there is a
171 // user gesture attached to the later request) that should be returned, 230 // user gesture attached to the later request) that should be returned,
172 // not BLOCK. 231 // not BLOCK.
173 if (CanShowLocationSettingsDialog(requesting_origin, 232 // If the permission is in the ASK state, backoff is ignored. Permission
174 true /* user_gesture */)) { 233 // prompts are shown regardless of backoff, if the location is off and the
234 // LSD can be shown, as permission prompts are less annoying than the
235 // modal LSD, and if the user accepts the permission prompt the LSD
236 // backoff will be reset.
237 if (CanShowLocationSettingsDialog(
238 requesting_origin, true /* user_gesture */,
239 result.content_setting ==
240 CONTENT_SETTING_ASK /* ignore_backoff */)) {
175 result.content_setting = CONTENT_SETTING_ASK; 241 result.content_setting = CONTENT_SETTING_ASK;
176 } else { 242 } else {
177 result.content_setting = CONTENT_SETTING_BLOCK; 243 result.content_setting = CONTENT_SETTING_BLOCK;
178 } 244 }
179 result.source = PermissionStatusSource::UNSPECIFIED; 245 result.source = PermissionStatusSource::UNSPECIFIED;
180 } 246 }
181 247
182 if (result.content_setting != CONTENT_SETTING_BLOCK && 248 if (result.content_setting != CONTENT_SETTING_BLOCK &&
183 !location_settings_->HasAndroidLocationPermission()) { 249 !location_settings_->HasAndroidLocationPermission()) {
184 // TODO(benwells): plumb through the RFH and use the associated 250 // TODO(benwells): plumb through the RFH and use the associated
185 // WebContents to check that the android location can be prompted for. 251 // WebContents to check that the android location can be prompted for.
186 result.content_setting = CONTENT_SETTING_ASK; 252 result.content_setting = CONTENT_SETTING_ASK;
187 result.source = PermissionStatusSource::UNSPECIFIED; 253 result.source = PermissionStatusSource::UNSPECIFIED;
188 } 254 }
189 } 255 }
190 256
191 return result; 257 return result;
192 } 258 }
193 259
260 std::string
261 GeolocationPermissionContextAndroid::GetLocationSettingsBackOffLevelPref(
262 const GURL& requesting_origin) const {
263 if (IsRequestingOriginDSE(requesting_origin))
264 return prefs::kLocationSettingsBackoffLevelDSE;
265
266 return prefs::kLocationSettingsBackoffLevelDefault;
267 }
268
269 std::string
270 GeolocationPermissionContextAndroid::GetLocationSettingsNextShowPref(
271 const GURL& requesting_origin) const {
272 if (IsRequestingOriginDSE(requesting_origin))
273 return prefs::kLocationSettingsNextShowDSE;
274
275 return prefs::kLocationSettingsNextShowDefault;
276 }
277
278 bool GeolocationPermissionContextAndroid::IsInLocationSettingsBackOff(
279 const GURL& requesting_origin) const {
280 base::Time next_show =
281 base::Time::FromInternalValue(profile()->GetPrefs()->GetInt64(
282 GetLocationSettingsNextShowPref(requesting_origin)));
283
284 return GetTimeNow() < next_show;
285 }
286
287 void GeolocationPermissionContextAndroid::ResetLocationSettingsBackOff(
288 const GURL& requesting_origin) {
289 PrefService* prefs = profile()->GetPrefs();
290 prefs->ClearPref(GetLocationSettingsNextShowPref(requesting_origin));
291 prefs->ClearPref(GetLocationSettingsBackOffLevelPref(requesting_origin));
292 }
293
294 void GeolocationPermissionContextAndroid::UpdateLocationSettingsBackOff(
295 const GURL& requesting_origin) {
296 // Backoff levels:
297 // 0: 1 week
298 // 1: 1 month
299 // 2: 3 months
300 PrefService* prefs = profile()->GetPrefs();
301 int backoff_level =
302 prefs->GetInteger(GetLocationSettingsBackOffLevelPref(requesting_origin));
303
304 base::Time next_show = GetTimeNow();
305 switch (backoff_level) {
306 case 0:
307 next_show += base::TimeDelta::FromDays(7);
308 break;
309 case 1:
310 next_show += base::TimeDelta::FromDays(30);
311 break;
312 default:
313 next_show += base::TimeDelta::FromDays(90);
314 }
315
316 if (backoff_level < 2)
317 backoff_level++;
318
319 prefs->SetInteger(GetLocationSettingsBackOffLevelPref(requesting_origin),
320 backoff_level);
321 prefs->SetInt64(GetLocationSettingsNextShowPref(requesting_origin),
322 next_show.ToInternalValue());
323 }
324
194 bool GeolocationPermissionContextAndroid::IsLocationAccessPossible( 325 bool GeolocationPermissionContextAndroid::IsLocationAccessPossible(
195 content::WebContents* web_contents, 326 content::WebContents* web_contents,
196 const GURL& requesting_origin, 327 const GURL& requesting_origin,
197 bool user_gesture) { 328 bool user_gesture) {
198 return (location_settings_->HasAndroidLocationPermission() || 329 return (location_settings_->HasAndroidLocationPermission() ||
199 location_settings_->CanPromptForAndroidLocationPermission( 330 location_settings_->CanPromptForAndroidLocationPermission(
200 web_contents)) && 331 web_contents)) &&
201 (location_settings_->IsSystemLocationSettingEnabled() || 332 (location_settings_->IsSystemLocationSettingEnabled() ||
202 CanShowLocationSettingsDialog(requesting_origin, user_gesture)); 333 CanShowLocationSettingsDialog(requesting_origin, user_gesture,
334 true /* ignore_backoff */));
203 } 335 }
204 336
205 LocationSettingsDialogContext 337 bool GeolocationPermissionContextAndroid::IsRequestingOriginDSE(
206 GeolocationPermissionContextAndroid::GetLocationSettingsDialogContext(
207 const GURL& requesting_origin) const { 338 const GURL& requesting_origin) const {
208 bool is_dse_origin = false; 339 GURL dse_url;
209 TemplateURLService* template_url_service = 340
210 TemplateURLServiceFactory::GetForProfile(profile()); 341 if (g_dse_origin_for_testing) {
211 if (template_url_service) { 342 dse_url = GURL(g_dse_origin_for_testing);
212 const TemplateURL* template_url = 343 } else {
213 template_url_service->GetDefaultSearchProvider(); 344 TemplateURLService* template_url_service =
214 if (template_url) { 345 TemplateURLServiceFactory::GetForProfile(profile());
215 GURL search_url = template_url->GenerateSearchURL( 346 if (template_url_service) {
216 template_url_service->search_terms_data()); 347 const TemplateURL* template_url =
217 is_dse_origin = url::IsSameOriginWith(requesting_origin, search_url); 348 template_url_service->GetDefaultSearchProvider();
349 if (template_url) {
350 dse_url = template_url->GenerateSearchURL(
351 template_url_service->search_terms_data());
352 }
218 } 353 }
219 } 354 }
220 355
221 return is_dse_origin ? SEARCH : DEFAULT; 356 return url::IsSameOriginWith(requesting_origin, dse_url);
222 } 357 }
223 358
224 void GeolocationPermissionContextAndroid::HandleUpdateAndroidPermissions( 359 void GeolocationPermissionContextAndroid::HandleUpdateAndroidPermissions(
225 const PermissionRequestID& id, 360 const PermissionRequestID& id,
226 const GURL& requesting_frame_origin, 361 const GURL& requesting_frame_origin,
227 const GURL& embedding_origin, 362 const GURL& embedding_origin,
228 const BrowserPermissionCallback& callback, 363 const BrowserPermissionCallback& callback,
229 bool permissions_updated) { 364 bool permissions_updated) {
230 permission_update_infobar_ = nullptr; 365 permission_update_infobar_ = nullptr;
231 366
232 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 367 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
233 ContentSetting new_setting = permissions_updated 368 ContentSetting new_setting = permissions_updated
234 ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; 369 ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
235 370
236 NotifyPermissionSet(id, requesting_frame_origin, embedding_origin, callback, 371 NotifyPermissionSet(id, requesting_frame_origin, embedding_origin, callback,
237 false /* persist */, new_setting); 372 false /* persist */, new_setting);
238 } 373 }
239 374
240 bool GeolocationPermissionContextAndroid::CanShowLocationSettingsDialog( 375 bool GeolocationPermissionContextAndroid::CanShowLocationSettingsDialog(
241 const GURL& requesting_origin, 376 const GURL& requesting_origin,
242 bool user_gesture) const { 377 bool user_gesture,
378 bool ignore_backoff) const {
243 if (!base::FeatureList::IsEnabled(features::kLsdPermissionPrompt)) 379 if (!base::FeatureList::IsEnabled(features::kLsdPermissionPrompt))
244 return false; 380 return false;
245 381
246 // If this isn't the default search engine, a gesture is needed. 382 // If this isn't the default search engine, a gesture is needed.
247 if (GetLocationSettingsDialogContext(requesting_origin) == DEFAULT && 383 if (!IsRequestingOriginDSE(requesting_origin) && !user_gesture) {
248 !user_gesture) {
249 return false; 384 return false;
250 } 385 }
251 386
252 // TODO(benwells): Also check backoff for |requesting_origin|. 387 if (!ignore_backoff && IsInLocationSettingsBackOff(requesting_origin))
388 return false;
389
253 return location_settings_->CanPromptToEnableSystemLocationSetting(); 390 return location_settings_->CanPromptToEnableSystemLocationSetting();
254 } 391 }
255 392
256 void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown( 393 void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown(
257 const PermissionRequestID& id, 394 const PermissionRequestID& id,
258 const GURL& requesting_origin, 395 const GURL& requesting_origin,
259 const GURL& embedding_origin, 396 const GURL& embedding_origin,
260 const BrowserPermissionCallback& callback, 397 const BrowserPermissionCallback& callback,
261 bool persist, 398 bool persist,
262 ContentSetting content_setting, 399 ContentSetting content_setting,
263 LocationSettingsDialogOutcome prompt_outcome) { 400 LocationSettingsDialogOutcome prompt_outcome) {
264 if (prompt_outcome != GRANTED) { 401 if (prompt_outcome == GRANTED) {
402 ResetLocationSettingsBackOff(requesting_origin);
403 } else {
404 UpdateLocationSettingsBackOff(requesting_origin);
265 content_setting = CONTENT_SETTING_BLOCK; 405 content_setting = CONTENT_SETTING_BLOCK;
266 persist = false; 406 persist = false;
267 } 407 }
268 408
269 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 409 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
270 persist, content_setting); 410 persist, content_setting);
271 } 411 }
272 412
273 void GeolocationPermissionContextAndroid::FinishNotifyPermissionSet( 413 void GeolocationPermissionContextAndroid::FinishNotifyPermissionSet(
274 const PermissionRequestID& id, 414 const PermissionRequestID& id,
(...skipping 22 matching lines...) Expand all
297 // The tab helper can be null in tests. 437 // The tab helper can be null in tests.
298 if (disclosure_helper) 438 if (disclosure_helper)
299 disclosure_helper->MaybeShowDisclosure(requesting_origin); 439 disclosure_helper->MaybeShowDisclosure(requesting_origin);
300 } 440 }
301 } 441 }
302 442
303 void GeolocationPermissionContextAndroid::SetLocationSettingsForTesting( 443 void GeolocationPermissionContextAndroid::SetLocationSettingsForTesting(
304 std::unique_ptr<LocationSettings> settings) { 444 std::unique_ptr<LocationSettings> settings) {
305 location_settings_ = std::move(settings); 445 location_settings_ = std::move(settings);
306 } 446 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698