diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-26 16:12:55 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-03-26 16:12:55 +0000 |
commit | ea05398d96221f8cc20939bad5fe52d4b11d3bd4 (patch) | |
tree | 6cd25c8065d5743a3f682c18c61f4d5da726d709 /chrome/browser | |
parent | 9d6dcdf0882b57fbb0825ab880f321d7682bad4a (diff) | |
download | chromium_src-ea05398d96221f8cc20939bad5fe52d4b11d3bd4.zip chromium_src-ea05398d96221f8cc20939bad5fe52d4b11d3bd4.tar.gz chromium_src-ea05398d96221f8cc20939bad5fe52d4b11d3bd4.tar.bz2 |
Adds obscuring to credit card numbers when displayed.
xib change: added tag to fields that are used for credit card numbers.
BUG=http://crbug.com/38259
TEST=as in bug
Review URL: http://codereview.chromium.org/1219009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42768 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/autofill/autofill_text_field_mac.h | 18 | ||||
-rw-r--r-- | chrome/browser/autofill/autofill_text_field_mac.mm | 60 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card.cc | 12 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card.h | 2 | ||||
-rw-r--r-- | chrome/browser/autofill/credit_card_unittest.cc | 14 |
5 files changed, 99 insertions, 7 deletions
diff --git a/chrome/browser/autofill/autofill_text_field_mac.h b/chrome/browser/autofill/autofill_text_field_mac.h index 559b0a8..a774aca 100644 --- a/chrome/browser/autofill/autofill_text_field_mac.h +++ b/chrome/browser/autofill/autofill_text_field_mac.h @@ -7,11 +7,21 @@ #import <Cocoa/Cocoa.h> -// Subclass of NSTextField that automatically scrolls containing NSScrollView -// to visually reveal the text field. When the user tabs between text fields -// embedded in a scrolling view they'd like the "first responder" to be visible. -// This class helps achieve that. +#import "base/scoped_nsobject.h" + +#define AUTOFILL_CC_TAG 22 + +// Subclass of NSTextField with special abilities: +// - automatically scrolls containing NSScrollView to visually reveal itself +// on focus +// - properly obfuscates credit card numbers + @interface AutoFillTextField : NSTextField { + BOOL isCreditCardField_; + BOOL isObfuscated_; + BOOL isBeingSelected_; + + scoped_nsobject<NSString> obfuscatedValue_; } @end diff --git a/chrome/browser/autofill/autofill_text_field_mac.mm b/chrome/browser/autofill/autofill_text_field_mac.mm index 3b19da0..ff5b1a0 100644 --- a/chrome/browser/autofill/autofill_text_field_mac.mm +++ b/chrome/browser/autofill/autofill_text_field_mac.mm @@ -4,8 +4,16 @@ #import "chrome/browser/autofill/autofill_text_field_mac.h" +#include "base/sys_string_conversions.h" +#include "chrome/browser/autofill/credit_card.h" + @implementation AutoFillTextField +- (void)awakeFromNib { + if ([self tag] == AUTOFILL_CC_TAG) + isCreditCardField_ = YES; +} + // Override NSResponder method for when the text field may gain focus. We // call |scrollRectToVisible| to ensure that this text field is visible within // the scrolling area. @@ -20,4 +28,56 @@ return becoming; } +- (void)setObjectValue:(id)object { + if (isCreditCardField_ && [object isKindOfClass:[NSString class]]) { + // Obfuscate the number. + NSString* string = object; + CreditCard card; + card.SetInfo(AutoFillType(CREDIT_CARD_NUMBER), + base::SysNSStringToUTF16(string)); + NSString* starredString = base::SysUTF16ToNSString(card.ObfuscatedNumber()); + + [super setObjectValue:starredString]; + isObfuscated_ = YES; + obfuscatedValue_.reset([string copy]); + } else { + [super setObjectValue:object]; + } +} + +- (id)objectValue { + if (isObfuscated_) { + // This should not happen. This field is bound, and its value will only be + // fetched if it is changed, and since we force selection, that should clear + // the obfuscation. Nevertheless, we'll be paranoid here since we don't want + // the obfuscating ***s to end up in the database. + return obfuscatedValue_.get(); + } else { + return [super objectValue]; + } +} + +// |self| is automatically set to be the delegate of the field editor; this +// method is called by the field editor. +- (void)textViewDidChangeSelection:(NSNotification *)notification { + if (isCreditCardField_ && !isBeingSelected_ && isObfuscated_) { + // Can't edit obfuscated credit card info; force a select-all in that case. + isBeingSelected_ = YES; + NSText* editor = [notification object]; + [editor selectAll:self]; + isBeingSelected_ = NO; + } +} + +// Docs aren't clear, but this is called on the first keypress, not when the +// field takes focus. +- (BOOL)textShouldBeginEditing:(NSText*)textObject { + BOOL should = [super textShouldBeginEditing:textObject]; + // On editing, since everything is selected, the field is now clear. + isObfuscated_ = !should; + if (!isObfuscated_) + obfuscatedValue_.reset(); + return should; +} + @end diff --git a/chrome/browser/autofill/credit_card.cc b/chrome/browser/autofill/credit_card.cc index 8c6a3fd..b412241 100644 --- a/chrome/browser/autofill/credit_card.cc +++ b/chrome/browser/autofill/credit_card.cc @@ -203,12 +203,20 @@ void CreditCard::SetInfo(const AutoFillType& type, const string16& value) { } } +string16 CreditCard::ObfuscatedNumber() const { + if (number().empty()) + return string16(); // No CC number, means empty preview. + string16 result(ASCIIToUTF16("************")); + result.append(last_four_digits()); + + return result; +} + string16 CreditCard::PreviewSummary() const { string16 preview; if (number().empty()) return preview; // No CC number, means empty preview. - string16 obfuscated_cc_number(ASCIIToUTF16("************")); - obfuscated_cc_number.append(last_four_digits()); + string16 obfuscated_cc_number = ObfuscatedNumber(); if (!expiration_month() || !expiration_year()) return obfuscated_cc_number; // no expiration date set // TODO(georgey): internationalize date diff --git a/chrome/browser/autofill/credit_card.h b/chrome/browser/autofill/credit_card.h index ec1bd6e..295ec79 100644 --- a/chrome/browser/autofill/credit_card.h +++ b/chrome/browser/autofill/credit_card.h @@ -30,6 +30,8 @@ class CreditCard : public FormGroup { virtual void SetInfo(const AutoFillType& type, const string16& value); const string16& Label() const { return label_; } + // The number altered for display, for example: ******1234 + string16 ObfuscatedNumber() const; // Credit card preview summary, for example: ******1234, Exp: 01/2020 string16 PreviewSummary() const; diff --git a/chrome/browser/autofill/credit_card_unittest.cc b/chrome/browser/autofill/credit_card_unittest.cc index 53df1fc..8241e0b 100644 --- a/chrome/browser/autofill/credit_card_unittest.cc +++ b/chrome/browser/autofill/credit_card_unittest.cc @@ -12,11 +12,13 @@ namespace { // Tests credit card summary string generation. This test simulates a variety // of different possible summary strings. Variations occur based on the // existence of credit card number, month, and year fields. -TEST(CreditCardTest, PreviewSummaryString) { +TEST(CreditCardTest, PreviewSummaryAndObfuscatedNumberStrings) { // Case 0: empty credit card. CreditCard credit_card0(string16(), 0); string16 summary0 = credit_card0.PreviewSummary(); EXPECT_EQ(summary0, string16()); + string16 obfuscated0 = credit_card0.ObfuscatedNumber(); + EXPECT_EQ(obfuscated0, string16()); // Case 00: Empty credit card with empty strings. CreditCard credit_card00(string16(), 0); @@ -33,6 +35,8 @@ TEST(CreditCardTest, PreviewSummaryString) { "Indianapolis"); string16 summary00 = credit_card00.PreviewSummary(); EXPECT_EQ(summary00, string16()); + string16 obfuscated00 = credit_card00.ObfuscatedNumber(); + EXPECT_EQ(obfuscated00, string16()); // Case 1: No credit card number. CreditCard credit_card1(string16(), 0); @@ -49,6 +53,8 @@ TEST(CreditCardTest, PreviewSummaryString) { "Indianapolis"); string16 summary1 = credit_card1.PreviewSummary(); EXPECT_EQ(summary1, string16()); + string16 obfuscated1 = credit_card1.ObfuscatedNumber(); + EXPECT_EQ(obfuscated1, string16()); // Case 2: No month. CreditCard credit_card2(string16(), 0); @@ -65,6 +71,8 @@ TEST(CreditCardTest, PreviewSummaryString) { "Indianapolis"); string16 summary2 = credit_card2.PreviewSummary(); EXPECT_EQ(summary2, string16(ASCIIToUTF16("************9012"))); + string16 obfuscated2 = credit_card2.ObfuscatedNumber(); + EXPECT_EQ(obfuscated2, string16(ASCIIToUTF16("************9012"))); // Case 3: No year. CreditCard credit_card3(string16(), 0); @@ -81,6 +89,8 @@ TEST(CreditCardTest, PreviewSummaryString) { "Indianapolis"); string16 summary3 = credit_card3.PreviewSummary(); EXPECT_EQ(summary3, string16(ASCIIToUTF16("************9012"))); + string16 obfuscated3 = credit_card3.ObfuscatedNumber(); + EXPECT_EQ(obfuscated3, string16(ASCIIToUTF16("************9012"))); // Case 4: Have everything. CreditCard credit_card4(string16(), 0); @@ -97,6 +107,8 @@ TEST(CreditCardTest, PreviewSummaryString) { "Indianapolis"); string16 summary4 = credit_card4.PreviewSummary(); EXPECT_EQ(summary4, string16(ASCIIToUTF16("************9012, Exp: 01/2010"))); + string16 obfuscated4 = credit_card4.ObfuscatedNumber(); + EXPECT_EQ(obfuscated4, string16(ASCIIToUTF16("************9012"))); } } // namespace |