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

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

Powered by Google App Engine
This is Rietveld 408576698