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

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: 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 bool gHasDSEOriginForTesting = false;
raymes 2017/03/15 04:28:25 Could you just use if (!gDSEOriginForTesting.empt
benwells 2017/03/15 23:10:48 Done.
37 GURL gDSEOriginForTesting;
raymes 2017/03/15 04:28:25 I think we avoid non-POD globals because it leads
benwells 2017/03/15 23:10:48 Done.
38
39 base::Time GetTimeNow() {
40 return base::Time::Now() + base::TimeDelta::FromDays(gDayOffsetForTesting);
raymes 2017/03/15 04:28:25 A more standard pattern is to store a base::Clock
benwells 2017/03/15 23:10:48 Yep, I know. I think I even added the clock to the
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 gDayOffsetForTesting += days;
108 }
109
110 // static
111 void GeolocationPermissionContextAndroid::SetDSEOriginForTesting(
112 const GURL& dse_origin) {
113 gHasDSEOriginForTesting = true;
114 gDSEOriginForTesting = dse_origin;
115 }
116
80 void GeolocationPermissionContextAndroid::RequestPermission( 117 void GeolocationPermissionContextAndroid::RequestPermission(
81 content::WebContents* web_contents, 118 content::WebContents* web_contents,
82 const PermissionRequestID& id, 119 const PermissionRequestID& id,
83 const GURL& requesting_frame_origin, 120 const GURL& requesting_frame_origin,
84 bool user_gesture, 121 bool user_gesture,
85 const BrowserPermissionCallback& callback) { 122 const BrowserPermissionCallback& callback) {
86 if (!IsLocationAccessPossible(web_contents, requesting_frame_origin, 123 if (!IsLocationAccessPossible(web_contents, requesting_frame_origin,
87 user_gesture)) { 124 user_gesture)) {
88 PermissionDecided(id, requesting_frame_origin, 125 PermissionDecided(id, requesting_frame_origin,
89 web_contents->GetLastCommittedURL().GetOrigin(), 126 web_contents->GetLastCommittedURL().GetOrigin(),
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 content::WebContents* web_contents, 159 content::WebContents* web_contents,
123 const PermissionRequestID& id) { 160 const PermissionRequestID& id) {
124 if (permission_update_infobar_) { 161 if (permission_update_infobar_) {
125 permission_update_infobar_->RemoveSelf(); 162 permission_update_infobar_->RemoveSelf();
126 permission_update_infobar_ = nullptr; 163 permission_update_infobar_ = nullptr;
127 } 164 }
128 165
129 GeolocationPermissionContext::CancelPermissionRequest(web_contents, id); 166 GeolocationPermissionContext::CancelPermissionRequest(web_contents, id);
130 } 167 }
131 168
169 void GeolocationPermissionContextAndroid::PermissionDecided(
170 const PermissionRequestID& id,
171 const GURL& requesting_origin,
172 const GURL& embedding_origin,
173 bool user_gesture,
174 const BrowserPermissionCallback& callback,
175 bool persist,
176 ContentSetting content_setting) {
177 // If the user has accepted geolocation, reset the location settings dialog
178 // backoff.
179 if (content_setting == CONTENT_SETTING_ALLOW)
180 ResetLocationSettingsBackOff(requesting_origin);
181
182 GeolocationPermissionContext::PermissionDecided(
183 id, requesting_origin, embedding_origin, user_gesture, callback, persist,
184 content_setting);
185 }
186
132 void GeolocationPermissionContextAndroid::NotifyPermissionSet( 187 void GeolocationPermissionContextAndroid::NotifyPermissionSet(
133 const PermissionRequestID& id, 188 const PermissionRequestID& id,
134 const GURL& requesting_origin, 189 const GURL& requesting_origin,
135 const GURL& embedding_origin, 190 const GURL& embedding_origin,
136 const BrowserPermissionCallback& callback, 191 const BrowserPermissionCallback& callback,
137 bool persist, 192 bool persist,
138 ContentSetting content_setting) { 193 ContentSetting content_setting) {
139 if (content_setting == CONTENT_SETTING_ALLOW && 194 if (content_setting == CONTENT_SETTING_ALLOW &&
140 !location_settings_->IsSystemLocationSettingEnabled()) { 195 !location_settings_->IsSystemLocationSettingEnabled()) {
141 // There is no need to check CanShowLocationSettingsDialog here again, as it 196 // There is no need to check CanShowLocationSettingsDialog here again, as it
142 // must have been checked to get this far. 197 // must have been checked to get this far. But, the backoff will not have
198 // been checked, so check that.
raymes 2017/03/15 04:28:25 nit: maybe explain why the backoff hasn't been che
benwells 2017/03/15 23:10:48 Done.
199 if (IsInLocationSettingsBackOff(requesting_origin)) {
200 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin,
201 callback, false /* persist */,
202 CONTENT_SETTING_BLOCK);
203 return;
204 }
205
143 content::WebContents* web_contents = 206 content::WebContents* web_contents =
144 content::WebContents::FromRenderFrameHost( 207 content::WebContents::FromRenderFrameHost(
145 content::RenderFrameHost::FromID(id.render_process_id(), 208 content::RenderFrameHost::FromID(id.render_process_id(),
146 id.render_frame_id())); 209 id.render_frame_id()));
147 location_settings_->PromptToEnableSystemLocationSetting( 210 location_settings_->PromptToEnableSystemLocationSetting(
148 GetLocationSettingsDialogContext(requesting_origin), web_contents, 211 GetLocationSettingsDialogContext(requesting_origin), web_contents,
149 base::BindOnce( 212 base::BindOnce(
150 &GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown, 213 &GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown,
151 weak_factory_.GetWeakPtr(), id, requesting_origin, embedding_origin, 214 weak_factory_.GetWeakPtr(), id, requesting_origin, embedding_origin,
152 callback, persist, content_setting)); 215 callback, persist, content_setting));
(...skipping 10 matching lines...) Expand all
163 const GURL& requesting_origin, 226 const GURL& requesting_origin,
164 const GURL& embedding_origin) const { 227 const GURL& embedding_origin) const {
165 if (base::FeatureList::IsEnabled(features::kLsdPermissionPrompt) && 228 if (base::FeatureList::IsEnabled(features::kLsdPermissionPrompt) &&
166 result.content_setting != CONTENT_SETTING_BLOCK) { 229 result.content_setting != CONTENT_SETTING_BLOCK) {
167 if (!location_settings_->IsSystemLocationSettingEnabled()) { 230 if (!location_settings_->IsSystemLocationSettingEnabled()) {
168 // As this is returning the status for possible future permission 231 // As this is returning the status for possible future permission
169 // requests, whose gesture status is unknown, pretend there is a user 232 // 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 233 // 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, 234 // user gesture attached to the later request) that should be returned,
172 // not BLOCK. 235 // not BLOCK.
173 if (CanShowLocationSettingsDialog(requesting_origin, 236 // If the permission is in the ASK state, backoff is ignored.
raymes 2017/03/15 04:28:25 nit: maybe explain why this is the case here? I th
benwells 2017/03/15 23:10:48 Done.
174 true /* user_gesture */)) { 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::LocationSettingsBackOffLevelPref(
262 const GURL& requesting_origin) const {
263 if (GetLocationSettingsDialogContext(requesting_origin) == SEARCH)
264 return prefs::kLocationSettingsBackoffLevelDSE;
265
266 return prefs::kLocationSettingsBackoffLevelDefault;
267 }
268
269 std::string GeolocationPermissionContextAndroid::LocationSettingsNextShowPref(
270 const GURL& requesting_origin) const {
271 if (GetLocationSettingsDialogContext(requesting_origin) == SEARCH)
272 return prefs::kLocationSettingsNextShowDSE;
273
274 return prefs::kLocationSettingsNextShowDefault;
275 }
276
277 bool GeolocationPermissionContextAndroid::IsInLocationSettingsBackOff(
278 const GURL& requesting_origin) const {
279 base::Time next_show =
280 base::Time::FromInternalValue(profile()->GetPrefs()->GetInt64(
281 LocationSettingsNextShowPref(requesting_origin)));
282
283 return GetTimeNow() < next_show;
284 }
285
286 void GeolocationPermissionContextAndroid::ResetLocationSettingsBackOff(
287 const GURL& requesting_origin) {
288 PrefService* prefs = profile()->GetPrefs();
289 prefs->ClearPref(LocationSettingsNextShowPref(requesting_origin));
290 prefs->ClearPref(LocationSettingsBackOffLevelPref(requesting_origin));
291 }
292
293 void GeolocationPermissionContextAndroid::SetLocationSettingsBackOff(
raymes 2017/03/15 04:28:25 nit: maybe this should be ApplyLocationSettingsBac
benwells 2017/03/15 23:10:49 Done.
294 const GURL& requesting_origin) {
295 // Backoff levels:
296 // 0: 1 week
297 // 1: 1 month
298 // 2: 3 months
299 PrefService* prefs = profile()->GetPrefs();
300 int backoff_level =
301 prefs->GetInteger(LocationSettingsBackOffLevelPref(requesting_origin));
302
303 base::Time next_show = GetTimeNow();
304 switch (backoff_level) {
305 case 0:
306 next_show += base::TimeDelta::FromDays(7);
307 break;
308 case 1:
309 next_show += base::TimeDelta::FromDays(30);
310 break;
311 default:
312 next_show += base::TimeDelta::FromDays(90);
313 }
314
315 if (backoff_level < 2)
316 backoff_level++;
317
318 prefs->SetInteger(LocationSettingsBackOffLevelPref(requesting_origin),
319 backoff_level);
320 prefs->SetInt64(LocationSettingsNextShowPref(requesting_origin),
321 next_show.ToInternalValue());
322 }
323
194 bool GeolocationPermissionContextAndroid::IsLocationAccessPossible( 324 bool GeolocationPermissionContextAndroid::IsLocationAccessPossible(
195 content::WebContents* web_contents, 325 content::WebContents* web_contents,
196 const GURL& requesting_origin, 326 const GURL& requesting_origin,
197 bool user_gesture) { 327 bool user_gesture) {
198 return (location_settings_->HasAndroidLocationPermission() || 328 return (location_settings_->HasAndroidLocationPermission() ||
199 location_settings_->CanPromptForAndroidLocationPermission( 329 location_settings_->CanPromptForAndroidLocationPermission(
200 web_contents)) && 330 web_contents)) &&
201 (location_settings_->IsSystemLocationSettingEnabled() || 331 (location_settings_->IsSystemLocationSettingEnabled() ||
202 CanShowLocationSettingsDialog(requesting_origin, user_gesture)); 332 CanShowLocationSettingsDialog(requesting_origin, user_gesture,
333 true /* ignore_backoff */));
203 } 334 }
204 335
205 LocationSettingsDialogContext 336 LocationSettingsDialogContext
206 GeolocationPermissionContextAndroid::GetLocationSettingsDialogContext( 337 GeolocationPermissionContextAndroid::GetLocationSettingsDialogContext(
raymes 2017/03/15 04:28:25 nit: I wonder if this is more clearly framed as I
benwells 2017/03/15 23:10:48 Done.
207 const GURL& requesting_origin) const { 338 const GURL& requesting_origin) const {
208 bool is_dse_origin = false; 339 bool is_dse_origin = false;
209 TemplateURLService* template_url_service = 340 GURL dse_url;
210 TemplateURLServiceFactory::GetForProfile(profile()); 341
211 if (template_url_service) { 342 if (gHasDSEOriginForTesting) {
212 const TemplateURL* template_url = 343 dse_url = gDSEOriginForTesting;
213 template_url_service->GetDefaultSearchProvider(); 344 } else {
214 if (template_url) { 345 TemplateURLService* template_url_service =
215 GURL search_url = template_url->GenerateSearchURL( 346 TemplateURLServiceFactory::GetForProfile(profile());
216 template_url_service->search_terms_data()); 347 if (template_url_service) {
217 is_dse_origin = url::IsSameOriginWith(requesting_origin, search_url); 348 const TemplateURL* template_url =
349 template_url_service->GetDefaultSearchProvider();
350 if (template_url) {
351 dse_url = template_url->GenerateSearchURL(
352 template_url_service->search_terms_data());
353 }
218 } 354 }
219 } 355 }
220 356
357 is_dse_origin = url::IsSameOriginWith(requesting_origin, dse_url);
221 return is_dse_origin ? SEARCH : DEFAULT; 358 return is_dse_origin ? SEARCH : DEFAULT;
222 } 359 }
223 360
224 void GeolocationPermissionContextAndroid::HandleUpdateAndroidPermissions( 361 void GeolocationPermissionContextAndroid::HandleUpdateAndroidPermissions(
225 const PermissionRequestID& id, 362 const PermissionRequestID& id,
226 const GURL& requesting_frame_origin, 363 const GURL& requesting_frame_origin,
227 const GURL& embedding_origin, 364 const GURL& embedding_origin,
228 const BrowserPermissionCallback& callback, 365 const BrowserPermissionCallback& callback,
229 bool permissions_updated) { 366 bool permissions_updated) {
230 permission_update_infobar_ = nullptr; 367 permission_update_infobar_ = nullptr;
231 368
232 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 369 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
233 ContentSetting new_setting = permissions_updated 370 ContentSetting new_setting = permissions_updated
234 ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; 371 ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
235 372
236 NotifyPermissionSet(id, requesting_frame_origin, embedding_origin, callback, 373 NotifyPermissionSet(id, requesting_frame_origin, embedding_origin, callback,
237 false /* persist */, new_setting); 374 false /* persist */, new_setting);
238 } 375 }
239 376
240 bool GeolocationPermissionContextAndroid::CanShowLocationSettingsDialog( 377 bool GeolocationPermissionContextAndroid::CanShowLocationSettingsDialog(
241 const GURL& requesting_origin, 378 const GURL& requesting_origin,
242 bool user_gesture) const { 379 bool user_gesture,
380 bool ignore_backoff) const {
243 if (!base::FeatureList::IsEnabled(features::kLsdPermissionPrompt)) 381 if (!base::FeatureList::IsEnabled(features::kLsdPermissionPrompt))
244 return false; 382 return false;
245 383
246 // If this isn't the default search engine, a gesture is needed. 384 // If this isn't the default search engine, a gesture is needed.
247 if (GetLocationSettingsDialogContext(requesting_origin) == DEFAULT && 385 if (GetLocationSettingsDialogContext(requesting_origin) == DEFAULT &&
248 !user_gesture) { 386 !user_gesture) {
249 return false; 387 return false;
250 } 388 }
251 389
252 // TODO(benwells): Also check backoff for |requesting_origin|. 390 if (!ignore_backoff && IsInLocationSettingsBackOff(requesting_origin))
391 return false;
392
253 return location_settings_->CanPromptToEnableSystemLocationSetting(); 393 return location_settings_->CanPromptToEnableSystemLocationSetting();
254 } 394 }
255 395
256 void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown( 396 void GeolocationPermissionContextAndroid::OnLocationSettingsDialogShown(
257 const PermissionRequestID& id, 397 const PermissionRequestID& id,
258 const GURL& requesting_origin, 398 const GURL& requesting_origin,
259 const GURL& embedding_origin, 399 const GURL& embedding_origin,
260 const BrowserPermissionCallback& callback, 400 const BrowserPermissionCallback& callback,
261 bool persist, 401 bool persist,
262 ContentSetting content_setting, 402 ContentSetting content_setting,
263 LocationSettingsDialogOutcome prompt_outcome) { 403 LocationSettingsDialogOutcome prompt_outcome) {
264 if (prompt_outcome != GRANTED) { 404 if (prompt_outcome == GRANTED) {
405 ResetLocationSettingsBackOff(requesting_origin);
406 } else {
407 SetLocationSettingsBackOff(requesting_origin);
265 content_setting = CONTENT_SETTING_BLOCK; 408 content_setting = CONTENT_SETTING_BLOCK;
266 persist = false; 409 persist = false;
267 } 410 }
268 411
269 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, callback, 412 FinishNotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
270 persist, content_setting); 413 persist, content_setting);
271 } 414 }
272 415
273 void GeolocationPermissionContextAndroid::FinishNotifyPermissionSet( 416 void GeolocationPermissionContextAndroid::FinishNotifyPermissionSet(
274 const PermissionRequestID& id, 417 const PermissionRequestID& id,
(...skipping 22 matching lines...) Expand all
297 // The tab helper can be null in tests. 440 // The tab helper can be null in tests.
298 if (disclosure_helper) 441 if (disclosure_helper)
299 disclosure_helper->MaybeShowDisclosure(requesting_origin); 442 disclosure_helper->MaybeShowDisclosure(requesting_origin);
300 } 443 }
301 } 444 }
302 445
303 void GeolocationPermissionContextAndroid::SetLocationSettingsForTesting( 446 void GeolocationPermissionContextAndroid::SetLocationSettingsForTesting(
304 std::unique_ptr<LocationSettings> settings) { 447 std::unique_ptr<LocationSettings> settings) {
305 location_settings_ = std::move(settings); 448 location_settings_ = std::move(settings);
306 } 449 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698