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

Side by Side Diff: components/autofill/core/browser/personal_data_manager_mac.mm

Issue 286243002: Mac: Autofill should not immediately request access to address book. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address second round of comments from isherman. Created 6 years, 7 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/autofill/core/browser/personal_data_manager.h" 5 #include "components/autofill/core/browser/personal_data_manager.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #import <AddressBook/AddressBook.h> 9 #import <AddressBook/AddressBook.h>
10 10
11 #include "base/format_macros.h" 11 #include "base/format_macros.h"
12 #include "base/guid.h" 12 #include "base/guid.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #import "base/mac/scoped_nsexception_enabler.h" 14 #import "base/mac/scoped_nsexception_enabler.h"
15 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/scoped_vector.h" 16 #include "base/memory/scoped_vector.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/prefs/pref_service.h" 18 #include "base/prefs/pref_service.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/strings/sys_string_conversions.h" 20 #include "base/strings/sys_string_conversions.h"
21 #include "components/autofill/core/browser/autofill_country.h" 21 #include "components/autofill/core/browser/autofill_country.h"
22 #include "components/autofill/core/browser/autofill_profile.h" 22 #include "components/autofill/core/browser/autofill_profile.h"
23 #include "components/autofill/core/browser/autofill_type.h" 23 #include "components/autofill/core/browser/autofill_type.h"
24 #include "components/autofill/core/browser/form_structure.h"
24 #include "components/autofill/core/browser/phone_number.h" 25 #include "components/autofill/core/browser/phone_number.h"
25 #include "components/autofill/core/common/autofill_pref_names.h" 26 #include "components/autofill/core/common/autofill_pref_names.h"
27 #include "components/autofill/core/common/form_data.h"
26 #include "grit/component_strings.h" 28 #include "grit/component_strings.h"
27 #include "ui/base/l10n/l10n_util_mac.h" 29 #include "ui/base/l10n/l10n_util_mac.h"
28 30
29 namespace autofill { 31 namespace autofill {
30 namespace { 32 namespace {
31 33
32 const char kAddressBookOrigin[] = "OS X Address Book"; 34 const char kAddressBookOrigin[] = "OS X Address Book";
33 35
36 ABAddressBook* GetAddressBook(PrefService* pref_service) {
37 // +[ABAddressBook sharedAddressBook] throws an exception internally in
38 // circumstances that aren't clear. The exceptions are only observed in crash
39 // reports, so it is unknown whether they would be caught by AppKit and nil
40 // returned, or if they would take down the app. In either case, avoid
41 // crashing. http://crbug.com/129022
42 ABAddressBook* addressBook = base::mac::RunBlockIgnoringExceptions(
43 ^{ return [ABAddressBook sharedAddressBook]; });
44 UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailable", addressBook != nil);
45 pref_service->SetBoolean(prefs::kAutofillAuxiliaryProfilesQueried, true);
46 return addressBook;
47 }
48
49 // Whether Chrome has prompted the user for permission to access the user's
50 // address book.
51 bool HasPromptedForAccessToAddressBook(PrefService* pref_service) {
52 return pref_service->GetBoolean(prefs::kAutofillAuxiliaryProfilesQueried);
53 }
54
34 // This implementation makes use of the Address Book API. Profiles are 55 // This implementation makes use of the Address Book API. Profiles are
35 // generated that correspond to addresses in the "me" card that reside in the 56 // generated that correspond to addresses in the "me" card that reside in the
36 // user's Address Book. The caller passes a vector of profiles into the 57 // user's Address Book. The caller passes a vector of profiles into the
37 // the constructer and then initiate the fetch from the Mac Address Book "me" 58 // the constructer and then initiate the fetch from the Mac Address Book "me"
38 // card using the main |GetAddressBookMeCard()| method. This clears any 59 // card using the main |GetAddressBookMeCard()| method. This clears any
39 // existing addresses and populates new addresses derived from the data found 60 // existing addresses and populates new addresses derived from the data found
40 // in the "me" card. 61 // in the "me" card.
41 class AuxiliaryProfilesImpl { 62 class AuxiliaryProfilesImpl {
42 public: 63 public:
43 // Constructor takes a reference to the |profiles| that will be filled in 64 // Constructor takes a reference to the |profiles| that will be filled in
(...skipping 30 matching lines...) Expand all
74 }; 95 };
75 96
76 // This method uses the |ABAddressBook| system service to fetch the "me" card 97 // This method uses the |ABAddressBook| system service to fetch the "me" card
77 // from the active user's address book. It looks for the user address 98 // from the active user's address book. It looks for the user address
78 // information and translates it to the internal list of |AutofillProfile| data 99 // information and translates it to the internal list of |AutofillProfile| data
79 // structures. 100 // structures.
80 void AuxiliaryProfilesImpl::GetAddressBookMeCard(const std::string& app_locale, 101 void AuxiliaryProfilesImpl::GetAddressBookMeCard(const std::string& app_locale,
81 PrefService* pref_service) { 102 PrefService* pref_service) {
82 profiles_.clear(); 103 profiles_.clear();
83 104
84 // +[ABAddressBook sharedAddressBook] throws an exception internally in 105 // Chrome has not yet requested address book permissions. Attempting to do so
85 // circumstances that aren't clear. The exceptions are only observed in crash 106 // presents a blocking modal dialog, which is undesirable. Instead, just show
86 // reports, so it is unknown whether they would be caught by AppKit and nil 107 // no results.
87 // returned, or if they would take down the app. In either case, avoid 108 if (!HasPromptedForAccessToAddressBook(pref_service))
88 // crashing. http://crbug.com/129022 109 return;
89 ABAddressBook* addressBook = base::mac::RunBlockIgnoringExceptions(^{ 110
90 return [ABAddressBook sharedAddressBook]; 111 ABAddressBook* addressBook = GetAddressBook(pref_service);
91 });
92 UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailable", addressBook != nil);
93 if (!pref_service->GetBoolean(prefs::kAutofillAuxiliaryProfilesQueried)) {
94 pref_service->SetBoolean(prefs::kAutofillAuxiliaryProfilesQueried, true);
95 UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailableOnFirstAttempt",
96 addressBook != nil);
97 }
98 112
99 ABPerson* me = [addressBook me]; 113 ABPerson* me = [addressBook me];
100 if (!me) 114 if (!me)
101 return; 115 return;
102 116
103 ABMultiValue* addresses = [me valueForProperty:kABAddressProperty]; 117 ABMultiValue* addresses = [me valueForProperty:kABAddressProperty];
104 118
105 // The number of characters at the end of the GUID to reserve for 119 // The number of characters at the end of the GUID to reserve for
106 // distinguishing addresses within the "me" card. Cap the number of addresses 120 // distinguishing addresses within the "me" card. Cap the number of addresses
107 // we will fetch to the number that can be distinguished by this fragment of 121 // we will fetch to the number that can be distinguished by this fragment of
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
274 } 288 }
275 289
276 } // namespace 290 } // namespace
277 291
278 // Populate |auxiliary_profiles_| with the Address Book data. 292 // Populate |auxiliary_profiles_| with the Address Book data.
279 void PersonalDataManager::LoadAuxiliaryProfiles() const { 293 void PersonalDataManager::LoadAuxiliaryProfiles() const {
280 AuxiliaryProfilesImpl impl(&auxiliary_profiles_); 294 AuxiliaryProfilesImpl impl(&auxiliary_profiles_);
281 impl.GetAddressBookMeCard(app_locale_, pref_service_); 295 impl.GetAddressBookMeCard(app_locale_, pref_service_);
282 } 296 }
283 297
298 bool PersonalDataManager::AccessAddressBook() {
299 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled))
300 return false;
301
302 if (HasPromptedForAccessToAddressBook(pref_service_))
303 return false;
304
305 // Request permissions.
306 ABAddressBook* addressBook = GetAddressBook(pref_service_);
erikchen 2014/05/21 22:00:54 It's possible for a user to mess with the configur
307
308 UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailableOnFirstAttempt",
309 addressBook != nil);
Ilya Sherman 2014/05/22 15:13:59 I'd prefer for this to be in GetAddressBook() as w
erikchen 2014/05/22 20:40:59 Done.
310 return true;
311 }
312
313 bool PersonalDataManager::ShouldShowAccessAddressBookSuggestion(
314 const FormData& data,
315 const FormFieldData& field_data,
316 const ScopedVector<FormStructure>& form_structures) {
317 if (!pref_service_->GetBoolean(prefs::kAutofillAuxiliaryProfilesEnabled))
318 return false;
319
320 if (HasPromptedForAccessToAddressBook(pref_service_))
321 return false;
322
323 for (ScopedVector<FormStructure>::const_iterator it = form_structures.begin();
324 it != form_structures.end();
325 ++it) {
326 // The form does not match.
327 if ((*it)->ToFormData().name != data.name)
328 continue;
329 for (size_t index = 0; index < (*it)->field_count(); ++index) {
330 const AutofillField* field = (*it)->field(index);
331 // The field does not match.
332 if (field->name != field_data.name)
333 continue;
334
335 switch (field->Type().group()) {
336 case ADDRESS_BILLING:
337 case ADDRESS_HOME:
338 case EMAIL:
339 case NAME:
340 case NAME_BILLING:
341 case PHONE_BILLING:
342 case PHONE_HOME:
343 return true;
344 case NO_GROUP:
345 case COMPANY:
346 case CREDIT_CARD:
347 case PASSWORD_FIELD:
348 return false;
349 }
350 }
351 }
352
353 return false;
354 }
355
284 } // namespace autofill 356 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698