summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrouslan <rouslan@chromium.org>2014-11-26 12:30:34 -0800
committerCommit bot <commit-bot@chromium.org>2014-11-26 20:31:41 +0000
commit497109dae349b8ba88e6abad95f697fbd8f80454 (patch)
treeb185725bc8579987ef4ec444141ddf2d8a7b2a00
parent711e0bc408a3123e457006dfb5476da93a3dc592 (diff)
downloadchromium_src-497109dae349b8ba88e6abad95f697fbd8f80454.zip
chromium_src-497109dae349b8ba88e6abad95f697fbd8f80454.tar.gz
chromium_src-497109dae349b8ba88e6abad95f697fbd8f80454.tar.bz2
[android] Scan new credit card from autofill popup.
This patch adds a "Scan new card" menu item to the autofill popup on Android. The feature is behind the command line flag: --enable-credit-card-scan BUG=428085 Review URL: https://codereview.chromium.org/700623004 Cr-Commit-Position: refs/heads/master@{#305869}
-rw-r--r--android_webview/native/aw_autofill_client.cc8
-rw-r--r--android_webview/native/aw_autofill_client.h2
-rw-r--r--build/ios/grit_whitelist.txt1
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/autofill/CreditCardScanner.java121
-rw-r--r--chrome/app/generated_resources.grd8
-rw-r--r--chrome/browser/about_flags.cc7
-rw-r--r--chrome/browser/android/chrome_jni_registrar.cc2
-rw-r--r--chrome/browser/ui/android/autofill/credit_card_scanner_view_android.cc73
-rw-r--r--chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h59
-rw-r--r--chrome/browser/ui/autofill/chrome_autofill_client.cc10
-rw-r--r--chrome/browser/ui/autofill/chrome_autofill_client.h3
-rw-r--r--chrome/browser/ui/autofill/credit_card_scanner_controller.cc76
-rw-r--r--chrome/browser/ui/autofill/credit_card_scanner_controller.h37
-rw-r--r--chrome/browser/ui/autofill/credit_card_scanner_view.cc24
-rw-r--r--chrome/browser/ui/autofill/credit_card_scanner_view.h41
-rw-r--r--chrome/browser/ui/autofill/credit_card_scanner_view_delegate.h32
-rw-r--r--chrome/chrome_browser.gypi1
-rw-r--r--chrome/chrome_browser_ui.gypi7
-rw-r--r--components/autofill/core/browser/autofill_client.h13
-rw-r--r--components/autofill/core/browser/autofill_external_delegate.cc20
-rw-r--r--components/autofill/core/browser/autofill_external_delegate.h12
-rw-r--r--components/autofill/core/browser/autofill_external_delegate_unittest.cc32
-rw-r--r--components/autofill/core/browser/autofill_manager.cc293
-rw-r--r--components/autofill/core/browser/autofill_manager.h31
-rw-r--r--components/autofill/core/browser/credit_card.cc9
-rw-r--r--components/autofill/core/browser/credit_card.h3
-rw-r--r--components/autofill/core/browser/credit_card_unittest.cc10
-rw-r--r--components/autofill/core/browser/popup_item_ids.h1
-rw-r--r--components/autofill/core/browser/test_autofill_client.cc8
-rw-r--r--components/autofill/core/browser/test_autofill_client.h2
-rw-r--r--components/autofill/core/common/autofill_switches.cc4
-rw-r--r--components/autofill/core/common/autofill_switches.h1
-rw-r--r--components/autofill_strings.grdp4
-rw-r--r--tools/metrics/histograms/histograms.xml1
34 files changed, 829 insertions, 127 deletions
diff --git a/android_webview/native/aw_autofill_client.cc b/android_webview/native/aw_autofill_client.cc
index 2460088..31c21a8 100644
--- a/android_webview/native/aw_autofill_client.cc
+++ b/android_webview/native/aw_autofill_client.cc
@@ -187,6 +187,14 @@ void AwAutofillClient::ConfirmSaveCreditCard(
NOTIMPLEMENTED();
}
+bool AwAutofillClient::HasCreditCardScanFeature() {
+ return false;
+}
+
+void AwAutofillClient::ScanCreditCard(const CreditCardScanCallback& callback) {
+ NOTIMPLEMENTED();
+}
+
void AwAutofillClient::ShowRequestAutocompleteDialog(
const autofill::FormData& form,
const GURL& source_url,
diff --git a/android_webview/native/aw_autofill_client.h b/android_webview/native/aw_autofill_client.h
index 372c220..10a2310 100644
--- a/android_webview/native/aw_autofill_client.h
+++ b/android_webview/native/aw_autofill_client.h
@@ -64,6 +64,8 @@ class AwAutofillClient : public autofill::AutofillClient,
virtual void ConfirmSaveCreditCard(
const autofill::AutofillMetrics& metric_logger,
const base::Closure& save_card_callback) override;
+ virtual bool HasCreditCardScanFeature() override;
+ virtual void ScanCreditCard(const CreditCardScanCallback& callback) override;
virtual void ShowRequestAutocompleteDialog(
const autofill::FormData& form,
const GURL& source_url,
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index aa579ce..6fbe58d5 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -154,6 +154,7 @@ IDS_AUTOFILL_FIELD_LABEL_PROVINCE
IDS_AUTOFILL_FIELD_LABEL_STATE
IDS_AUTOFILL_FIELD_LABEL_ZIP_CODE
IDS_AUTOFILL_OPTIONS_POPUP
+IDS_AUTOFILL_SCAN_CREDIT_CARD
IDS_AUTOFILL_WARNING_FORM_DISABLED
IDS_AUTOFILL_WARNING_INSECURE_CONNECTION
IDS_AUTOLOGIN_INFOBAR_CANCEL_BUTTON
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/CreditCardScanner.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CreditCardScanner.java
new file mode 100644
index 0000000..b03efca
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/CreditCardScanner.java
@@ -0,0 +1,121 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.autofill;
+
+import android.content.Context;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
+import org.chromium.ui.base.WindowAndroid;
+
+/**
+ * Helper for detecting whether the device supports scanning credit cards and for scanning credit
+ * cards. The default implementation cannot scan cards. An implementing subclass must provide a
+ * factory that builds its instances.
+ */
+@JNINamespace("autofill")
+public class CreditCardScanner {
+ /**
+ * Can be used to build subclasses of the scanner without the user of the class knowing about
+ * the subclass name.
+ */
+ static Factory sFactory;
+
+ /**
+ * Pointer to the native object that receives scanning callbacks.
+ */
+ protected long mNativeScanner;
+
+ /**
+ * Application context.
+ */
+ protected Context mContext;
+
+ /**
+ * The window that's requesting a scan.
+ */
+ protected WindowAndroid mWindow;
+
+ /**
+ * Builds instances of credit card scanners.
+ */
+ public interface Factory {
+ /**
+ * Builds an instance of credit card scanner.
+ * @param nativeScanner Pointer to the native object that receives scanning callbacks.
+ * @param context Application context.
+ * @param window The window that's requesting a scan.
+ * @return An object that can scan a credit card.
+ */
+ CreditCardScanner create(long nativeScanner, Context context, WindowAndroid window);
+ }
+
+ /**
+ * Sets the factory that can build instances of credit card scanners.
+ * @param factory Can build instances of credit card scanners.
+ */
+ public static void setFactory(Factory factory) {
+ sFactory = factory;
+ }
+
+ /**
+ * Called by the native object to create an instance of a credit card scanner.
+ * @param nativeScanner Pointer to the native object that receives scanning callbacks.
+ * @param context Application context.
+ * @param window The window that's requesting a scan.
+ * @return An object that can scan a credit card.
+ */
+ @CalledByNative
+ private static CreditCardScanner create(long nativeScanner, Context context,
+ WindowAndroid window) {
+ return sFactory != null ? sFactory.create(nativeScanner, context, window)
+ : new CreditCardScanner(nativeScanner, context, window);
+ }
+
+ /**
+ * Constructor for the credit card scanner.
+ * @param nativeScanner Pointer to the native object that receives scanning callbacks.
+ * @param context Application context.
+ * @param window The window that's requesting a scan.
+ */
+ protected CreditCardScanner(long nativeScanner, Context context, WindowAndroid window) {
+ mNativeScanner = nativeScanner;
+ mContext = context;
+ mWindow = window;
+ }
+
+ /**
+ * Returns true if this instance has the ability to scan credit cards.
+ * @return True if has ability to scan credit cards.
+ */
+ @CalledByNative
+ protected boolean canScan() {
+ return false;
+ }
+
+ /**
+ * Scans a credit card. Will invoke a native callback with the result.
+ */
+ @CalledByNative
+ protected void scan() {
+ nativeScanCancelled(mNativeScanner);
+ }
+
+ /**
+ * Notifies the native object that scanning was cancelled.
+ * @param nativeCreditCardScannerViewAndroid Pointer to the native object.
+ */
+ protected native void nativeScanCancelled(long nativeCreditCardScannerViewAndroid);
+
+ /**
+ * Notifies the native object that scanning was successful.
+ * @param nativeCreditCardScannerViewAndroid Pointer to the native object.
+ * @param cardNumber Credit card number.
+ * @param expirationMonth Expiration month in the range [1, 12].
+ * @param expirationYear Expiration year, e.g. 2000.
+ */
+ protected native void nativeScanCompleted(long nativeCreditCardScannerViewAndroid,
+ String cardNumber, int expirationMonth, int expirationYear);
+}
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index c5c900a..013df0e 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -14123,6 +14123,14 @@ Do you accept?
TLS 1.2
</message>
+ <!-- Strings for controlling credit card scanning feature in about:flags. -->
+ <message name="IDS_FLAGS_ENABLE_CREDIT_CARD_SCAN_NAME" desc="The name of about:flags option to enable scanning of credit cards using device camera.">
+ Credit card scanning
+ </message>
+ <message name="IDS_FLAGS_ENABLE_CREDIT_CARD_SCAN_DESCRIPTION" desc="The description of about:flags option to enable scanning of credit cards using device camera.">
+ Enable scanning a new credit card number when filling out a credit card form.
+ </message>
+
<!-- Simple Cache Backend experiment. -->
<message name="IDS_FLAGS_ENABLE_SIMPLE_CACHE_BACKEND_NAME" desc="Name of about:flags option to turn on the Simple Cache Backend">
Simple Cache for HTTP.
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index f7bbfd3..4d440a0 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2016,6 +2016,13 @@ const Experiment kExperiments[] = {
kOsAll,
MULTI_VALUE_TYPE(kSSLVersionMinChoices)
},
+ {
+ "enable-credit-card-scan",
+ IDS_FLAGS_ENABLE_CREDIT_CARD_SCAN_NAME,
+ IDS_FLAGS_ENABLE_CREDIT_CARD_SCAN_DESCRIPTION,
+ kOsAndroid,
+ SINGLE_VALUE_TYPE(autofill::switches::kEnableCreditCardScan)
+ },
// NOTE: Adding new command-line switches requires adding corresponding
// entries to enum "LoginCustomFlags" in histograms.xml. See note in
// histograms.xml and don't forget to run AboutFlagsHistogramTest unit test.
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index bcfcdec..1d033fd 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -60,6 +60,7 @@
#include "chrome/browser/ui/android/autofill/autofill_dialog_result.h"
#include "chrome/browser/ui/android/autofill/autofill_logger_android.h"
#include "chrome/browser/ui/android/autofill/autofill_popup_view_android.h"
+#include "chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h"
#include "chrome/browser/ui/android/autofill/password_generation_popup_view_android.h"
#include "chrome/browser/ui/android/chrome_http_auth_handler.h"
#include "chrome/browser/ui/android/context_menu_helper.h"
@@ -137,6 +138,7 @@ static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
{ "ConfirmInfoBarDelegate", RegisterConfirmInfoBarDelegate },
{ "ContentViewUtil", RegisterContentViewUtil },
{ "ContextMenuHelper", RegisterContextMenuHelper },
+ { "CreditCardScanner", autofill::CreditCardScannerViewAndroid::Register },
{ "DataReductionProxyInfoBarDelegate", DataReductionProxyInfoBar::Register },
{ "DataReductionProxySettings", DataReductionProxySettingsAndroid::Register },
{ "DevToolsServer", RegisterDevToolsServer },
diff --git a/chrome/browser/ui/android/autofill/credit_card_scanner_view_android.cc b/chrome/browser/ui/android/autofill/credit_card_scanner_view_android.cc
new file mode 100644
index 0000000..7121557
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/credit_card_scanner_view_android.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/android/window_android_helper.h"
+#include "chrome/browser/ui/autofill/credit_card_scanner_view_delegate.h"
+#include "content/public/browser/android/content_view_core.h"
+#include "jni/CreditCardScanner_jni.h"
+#include "ui/base/android/view_android.h"
+#include "ui/base/android/window_android.h"
+
+namespace autofill {
+
+// static
+bool CreditCardScannerView::CanShow() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaGlobalRef<jobject> java_object(
+ Java_CreditCardScanner_create(
+ env, 0, base::android::GetApplicationContext(), 0));
+ return Java_CreditCardScanner_canScan(env, java_object.obj());
+}
+
+// static
+scoped_ptr<CreditCardScannerView> CreditCardScannerView::Create(
+ const base::WeakPtr<CreditCardScannerViewDelegate>& delegate,
+ content::WebContents* web_contents) {
+ return make_scoped_ptr(
+ new CreditCardScannerViewAndroid(delegate, web_contents));
+}
+
+// static
+bool CreditCardScannerViewAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+CreditCardScannerViewAndroid::CreditCardScannerViewAndroid(
+ const base::WeakPtr<CreditCardScannerViewDelegate>& delegate,
+ content::WebContents* web_contents)
+ : delegate_(delegate),
+ java_object_(Java_CreditCardScanner_create(
+ base::android::AttachCurrentThread(),
+ reinterpret_cast<intptr_t>(this),
+ base::android::GetApplicationContext(),
+ WindowAndroidHelper::FromWebContents(web_contents)
+ ->GetWindowAndroid()->GetJavaObject().obj())) {}
+
+CreditCardScannerViewAndroid::~CreditCardScannerViewAndroid() {}
+
+void CreditCardScannerViewAndroid::ScanCancelled(JNIEnv* env, jobject object) {
+ delegate_->ScanCancelled();
+}
+
+void CreditCardScannerViewAndroid::ScanCompleted(JNIEnv* env,
+ jobject object,
+ jstring card_number,
+ jint expiration_month,
+ jint expiration_year) {
+ delegate_->ScanCompleted(
+ base::android::ConvertJavaStringToUTF16(env, card_number),
+ static_cast<int>(expiration_month), static_cast<int>(expiration_year));
+}
+
+void CreditCardScannerViewAndroid::Show() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_CreditCardScanner_scan(env, java_object_.obj());
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h b/chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h
new file mode 100644
index 0000000..8bfb3be
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/credit_card_scanner_view_android.h
@@ -0,0 +1,59 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ANDROID_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/ui/autofill/credit_card_scanner_view.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace autofill {
+
+class CreditCardScannerViewDelegate;
+
+// Android implementation of the view for credit card scanner UI. Uses Android
+// APIs through JNI service.
+class CreditCardScannerViewAndroid : public CreditCardScannerView {
+ public:
+ // Registers with JNI services.
+ static bool Register(JNIEnv* env);
+
+ CreditCardScannerViewAndroid(
+ const base::WeakPtr<CreditCardScannerViewDelegate>& delegate,
+ content::WebContents* web_contents);
+ ~CreditCardScannerViewAndroid() override;
+
+ // Called by JNI when user cancelled credit card scan.
+ void ScanCancelled(JNIEnv* env, jobject object);
+
+ // Called by JNI when credit card scan completed successfully.
+ void ScanCompleted(JNIEnv* env,
+ jobject object,
+ jstring card_number,
+ jint expiration_month,
+ jint expiration_year);
+ private:
+ // CreditCardScannerView implementation.
+ void Show() override;
+
+ // The object to be notified when scanning was cancelled or completed.
+ base::WeakPtr<CreditCardScannerViewDelegate> delegate_;
+
+ // The corresponding Java object that uses Android APIs for scanning.
+ base::android::ScopedJavaGlobalRef<jobject> java_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(CreditCardScannerViewAndroid);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_ANDROID_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_ANDROID_H_
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc
index 41f2aaa..c008944 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.cc
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -13,6 +13,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
+#include "chrome/browser/ui/autofill/credit_card_scanner_controller.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
@@ -113,6 +114,15 @@ void ChromeAutofillClient::ConfirmSaveCreditCard(
infobar_service, &metric_logger, save_card_callback);
}
+bool ChromeAutofillClient::HasCreditCardScanFeature() {
+ return CreditCardScannerController::HasCreditCardScanFeature();
+}
+
+void ChromeAutofillClient::ScanCreditCard(
+ const CreditCardScanCallback& callback) {
+ CreditCardScannerController::ScanCreditCard(web_contents(), callback);
+}
+
void ChromeAutofillClient::ShowRequestAutocompleteDialog(
const FormData& form,
const GURL& source_url,
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h
index 323eb5f..09d346a 100644
--- a/chrome/browser/ui/autofill/chrome_autofill_client.h
+++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -25,6 +25,7 @@ namespace autofill {
class AutofillDialogController;
class AutofillKeystoneBridgeWrapper;
class AutofillPopupControllerImpl;
+class CreditCardScannerController;
struct FormData;
// Chrome implementation of AutofillClient.
@@ -47,6 +48,8 @@ class ChromeAutofillClient
void ShowAutofillSettings() override;
void ConfirmSaveCreditCard(const AutofillMetrics& metric_logger,
const base::Closure& save_card_callback) override;
+ bool HasCreditCardScanFeature() override;
+ void ScanCreditCard(const CreditCardScanCallback& callback) override;
void ShowRequestAutocompleteDialog(const FormData& form,
const GURL& source_url,
const ResultCallback& callback) override;
diff --git a/chrome/browser/ui/autofill/credit_card_scanner_controller.cc b/chrome/browser/ui/autofill/credit_card_scanner_controller.cc
new file mode 100644
index 0000000..2d3d0bc
--- /dev/null
+++ b/chrome/browser/ui/autofill/credit_card_scanner_controller.cc
@@ -0,0 +1,76 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/credit_card_scanner_controller.h"
+
+#include "base/callback.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/autofill/credit_card_scanner_view.h"
+#include "chrome/browser/ui/autofill/credit_card_scanner_view_delegate.h"
+
+namespace autofill {
+
+namespace {
+
+// Controller for the credit card scanner UI. The controller deletes itself
+// after the view is dismissed.
+class Controller : public CreditCardScannerViewDelegate,
+ public base::SupportsWeakPtr<Controller> {
+ public:
+ Controller(content::WebContents* web_contents,
+ const AutofillClient::CreditCardScanCallback& callback)
+ : view_(CreditCardScannerView::Create(AsWeakPtr(), web_contents)),
+ callback_(callback) {
+ DCHECK(view_);
+ }
+
+ // Shows the UI to scan the credit card.
+ void Show() {
+ view_->Show();
+ }
+
+ private:
+ ~Controller() {}
+
+ // CreditCardScannerViewDelegate implementation.
+ void ScanCancelled() override {
+ delete this;
+ }
+
+ // CreditCardScannerViewDelegate implementation.
+ void ScanCompleted(const base::string16& card_number,
+ int expiration_month,
+ int expiration_year) override {
+ callback_.Run(card_number, expiration_month, expiration_year);
+ delete this;
+ }
+
+ // The view for the credit card scanner.
+ scoped_ptr<CreditCardScannerView> view_;
+
+ // The callback to be invoked when scanning completes successfully.
+ AutofillClient::CreditCardScanCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(Controller);
+};
+
+} // namespace
+
+// static
+bool CreditCardScannerController::HasCreditCardScanFeature() {
+ return CreditCardScannerView::CanShow();
+}
+
+// static
+void CreditCardScannerController::ScanCreditCard(
+ content::WebContents* web_contents,
+ const AutofillClient::CreditCardScanCallback& callback) {
+ (new Controller(web_contents, callback))->Show();
+}
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/credit_card_scanner_controller.h b/chrome/browser/ui/autofill/credit_card_scanner_controller.h
new file mode 100644
index 0000000..7329f08
--- /dev/null
+++ b/chrome/browser/ui/autofill/credit_card_scanner_controller.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_CONTROLLER_H_
+
+#include "components/autofill/core/browser/autofill_client.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace autofill {
+
+class CreditCardScannerView;
+
+// Controller for the credit card scanner UI. The controller deletes itself
+// after the view is dismissed.
+class CreditCardScannerController {
+ public:
+ // Returns true if both platform and device support scanning credit cards. The
+ // platform must have the required APIs. The device must have, e.g., a camera.
+ static bool HasCreditCardScanFeature();
+
+ // Shows the UI to scan a credit card. The UI is associated with the
+ // |web_contents|. Notifies the |delegate| when scanning completes
+ // successfully. Destroys itself when the UI is dismissed. Should be called
+ // only if HasCreditCardScanScanFeature() returns true.
+ static void ScanCreditCard(
+ content::WebContents* web_contents,
+ const AutofillClient::CreditCardScanCallback& callback);
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/credit_card_scanner_view.cc b/chrome/browser/ui/autofill/credit_card_scanner_view.cc
new file mode 100644
index 0000000..0f6e5b6
--- /dev/null
+++ b/chrome/browser/ui/autofill/credit_card_scanner_view.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/autofill/credit_card_scanner_view.h"
+
+namespace autofill {
+
+// Not implemented on other platforms yet.
+#if !defined(OS_ANDROID)
+// static
+bool CreditCardScannerView::CanShow() {
+ return false;
+}
+
+// static
+scoped_ptr<CreditCardScannerView> CreditCardScannerView::Create(
+ const base::WeakPtr<CreditCardScannerViewDelegate>& delegate,
+ content::WebContents* web_contents) {
+ return scoped_ptr<CreditCardScannerView>();
+}
+#endif // !defined(OS_ANDROID)
+
+} // namespace autofill
diff --git a/chrome/browser/ui/autofill/credit_card_scanner_view.h b/chrome/browser/ui/autofill/credit_card_scanner_view.h
new file mode 100644
index 0000000..c01e2eb
--- /dev/null
+++ b/chrome/browser/ui/autofill/credit_card_scanner_view.h
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_H_
+#define CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace autofill {
+
+class CreditCardScannerViewDelegate;
+
+// View for the credit card scanner UI. Owned by the controller.
+class CreditCardScannerView {
+ public:
+ // Returns true if the platform implements the credit card scanner UI and the
+ // device supports scanning credit cards, e.g., it has a camera.
+ static bool CanShow();
+
+ // Creates a view for the credit card scanner UI. The view is associated with
+ // the |web_contents| and notifies the |delegate| when a scan is cancelled or
+ // completed. Should be called only if CanShow() returns true.
+ static scoped_ptr<CreditCardScannerView> Create(
+ const base::WeakPtr<CreditCardScannerViewDelegate>& delegate,
+ content::WebContents* web_contents);
+
+ virtual ~CreditCardScannerView() {}
+
+ // Shows the UI for scanning credit cards.
+ virtual void Show() = 0;
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_H_
diff --git a/chrome/browser/ui/autofill/credit_card_scanner_view_delegate.h b/chrome/browser/ui/autofill/credit_card_scanner_view_delegate.h
new file mode 100644
index 0000000..48956d2
--- /dev/null
+++ b/chrome/browser/ui/autofill/credit_card_scanner_view_delegate.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_DELEGATE_H_
+#define CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_DELEGATE_H_
+
+#include "base/strings/string16.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace autofill {
+
+// Receives notifications when credit card scanner UI is dismissed either due to
+// user cancelling the scan or successfully completing the scan.
+class CreditCardScannerViewDelegate {
+ public:
+ // Called when user cancelled the scan.
+ virtual void ScanCancelled() = 0;
+
+ // Called when the scan completed successfully.
+ virtual void ScanCompleted(const base::string16& card_number,
+ int expiration_month,
+ int expiration_year) = 0;
+
+ protected:
+ // Destroys the delegate.
+ virtual ~CreditCardScannerViewDelegate() {}
+};
+
+} // namespace autofill
+
+#endif // CHROME_BROWSER_UI_AUTOFILL_CREDIT_CARD_SCANNER_VIEW_DELEGATE_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index df5d523..da7a572 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2749,6 +2749,7 @@
'android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogResult.java',
'android/java/src/org/chromium/chrome/browser/autofill/AutofillLogger.java',
'android/java/src/org/chromium/chrome/browser/autofill/AutofillPopupBridge.java',
+ 'android/java/src/org/chromium/chrome/browser/autofill/CreditCardScanner.java',
'android/java/src/org/chromium/chrome/browser/autofill/PasswordGenerationPopupBridge.java',
'android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManager.java',
'android/java/src/org/chromium/chrome/browser/BookmarksBridge.java',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index b233c86..331b042e 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -86,6 +86,11 @@
'browser/ui/autofill/chrome_autofill_client_mac.mm',
'browser/ui/autofill/country_combobox_model.cc',
'browser/ui/autofill/country_combobox_model.h',
+ 'browser/ui/autofill/credit_card_scanner_controller.cc',
+ 'browser/ui/autofill/credit_card_scanner_controller.h',
+ 'browser/ui/autofill/credit_card_scanner_view_delegate.h',
+ 'browser/ui/autofill/credit_card_scanner_view.cc',
+ 'browser/ui/autofill/credit_card_scanner_view.h',
'browser/ui/autofill/loading_animation.cc',
'browser/ui/autofill/loading_animation.h',
'browser/ui/autofill/password_generation_popup_controller_impl.cc',
@@ -1318,6 +1323,8 @@
'browser/ui/certificate_dialogs.h',
],
'chrome_browser_ui_android_sources': [
+ 'browser/ui/android/autofill/credit_card_scanner_view_android.cc',
+ 'browser/ui/android/autofill/credit_card_scanner_view_android.h',
'browser/ui/android/infobars/generated_password_saved_infobar.cc',
'browser/ui/android/infobars/generated_password_saved_infobar.h',
'browser/ui/auto_login_infobar_delegate.cc',
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h
index 28bd59f..452c793 100644
--- a/components/autofill/core/browser/autofill_client.h
+++ b/components/autofill/core/browser/autofill_client.h
@@ -51,6 +51,10 @@ class AutofillClient {
const base::string16&,
const FormStructure*)> ResultCallback;
+ typedef base::Callback<void(const base::string16& /* card number */,
+ int /* exp month */,
+ int /* exp year */)> CreditCardScanCallback;
+
virtual ~AutofillClient() {}
// Gets the PersonalDataManager instance associated with the client.
@@ -74,6 +78,15 @@ class AutofillClient {
const AutofillMetrics& metric_logger,
const base::Closure& save_card_callback) = 0;
+ // Returns true if both the platform and the device support scanning credit
+ // cards. Should be called before ScanCreditCard().
+ virtual bool HasCreditCardScanFeature() = 0;
+
+ // Shows the user interface for scanning a credit card. Invokes the |callback|
+ // when a credit card is scanned successfully. Should be called only if
+ // HasCreditCardScanFeature() returns true.
+ virtual void ScanCreditCard(const CreditCardScanCallback& callback) = 0;
+
// Causes the dialog for request autocomplete feature to be shown.
virtual void ShowRequestAutocompleteDialog(
const FormData& form,
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index eccd75a..82a6d67 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -4,6 +4,7 @@
#include "components/autofill/core/browser/autofill_external_delegate.h"
+#include "base/bind.h"
#include "base/command_line.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
@@ -107,6 +108,13 @@ void AutofillExternalDelegate::OnSuggestionsReturned(
icons.push_back(base::string16());
ids.push_back(POPUP_ITEM_ID_SEPARATOR);
+ if (manager_->ShouldShowScanCreditCard(query_form_, query_field_)) {
+ values.push_back(l10n_util::GetStringUTF16(IDS_AUTOFILL_SCAN_CREDIT_CARD));
+ labels.push_back(base::string16());
+ icons.push_back(base::string16());
+ ids.push_back(POPUP_ITEM_ID_SCAN_CREDIT_CARD);
+ }
+
// Only include "Autofill Options" special menu item if we have Autofill
// suggestions.
has_suggestion_ = false;
@@ -253,6 +261,9 @@ void AutofillExternalDelegate::DidAcceptSuggestion(const base::string16& value,
#else
NOTREACHED();
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+ } else if (identifier == POPUP_ITEM_ID_SCAN_CREDIT_CARD) {
+ manager_->client()->ScanCreditCard(base::Bind(
+ &AutofillExternalDelegate::OnCreditCardScanned, GetWeakPtr()));
} else {
FillAutofillFormData(identifier, false);
}
@@ -295,6 +306,15 @@ base::WeakPtr<AutofillExternalDelegate> AutofillExternalDelegate::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
+void AutofillExternalDelegate::OnCreditCardScanned(
+ const base::string16& card_number,
+ int expiration_month,
+ int expiration_year) {
+ manager_->FillCreditCardForm(
+ query_id_, query_form_, query_field_,
+ CreditCard(card_number, expiration_month, expiration_year));
+}
+
void AutofillExternalDelegate::FillAutofillFormData(int unique_id,
bool is_preview) {
// If the selected element is a warning we don't want to do anything.
diff --git a/components/autofill/core/browser/autofill_external_delegate.h b/components/autofill/core/browser/autofill_external_delegate.h
index 971af23..ed745e0 100644
--- a/components/autofill/core/browser/autofill_external_delegate.h
+++ b/components/autofill/core/browser/autofill_external_delegate.h
@@ -8,6 +8,7 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "components/autofill/core/browser/autofill_popup_delegate.h"
@@ -25,8 +26,7 @@ class AutofillManager;
// this logic. See http://crbug.com/51644
// Delegate for in-browser Autocomplete and Autofill display and selection.
-class AutofillExternalDelegate
- : public AutofillPopupDelegate {
+class AutofillExternalDelegate : public AutofillPopupDelegate {
public:
// Creates an AutofillExternalDelegate for the specified AutofillManager and
// AutofillDriver.
@@ -86,6 +86,14 @@ class AutofillExternalDelegate
base::WeakPtr<AutofillExternalDelegate> GetWeakPtr();
private:
+ FRIEND_TEST_ALL_PREFIXES(AutofillExternalDelegateUnitTest,
+ FillCreditCardForm);
+
+ // Called when a credit card is scanned using device camera.
+ void OnCreditCardScanned(const base::string16& card_number,
+ int expiration_month,
+ int expiration_year);
+
// Fills the form with the Autofill data corresponding to |unique_id|.
// If |is_preview| is true then this is just a preview to show the user what
// would be selected and if |is_preview| is false then the user has selected
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
index 4899a10..267bc5f 100644
--- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc
+++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -55,6 +55,9 @@ class MockAutofillClient : public autofill::TestAutofillClient {
public:
MockAutofillClient() {}
+ MOCK_METHOD1(ScanCreditCard,
+ void(const CreditCardScanCallback& callbacK));
+
MOCK_METHOD7(ShowAutofillPopup,
void(const gfx::RectF& element_bounds,
base::i18n::TextDirection text_direction,
@@ -89,6 +92,12 @@ class MockAutofillManager : public AutofillManager {
const FormFieldData& field,
int unique_id));
+ MOCK_METHOD4(FillCreditCardForm,
+ void(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard& credit_card));
+
private:
DISALLOW_COPY_AND_ASSIGN(MockAutofillManager);
};
@@ -429,6 +438,29 @@ TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateClearForm) {
POPUP_ITEM_ID_CLEAR_FORM);
}
+// Test that autofill client will scan a credit card after use accepted the
+// suggestion to scan a credit card.
+TEST_F(AutofillExternalDelegateUnitTest, ScanCreditCardMenuItem) {
+ EXPECT_CALL(autofill_client_, ScanCreditCard(_));
+ EXPECT_CALL(autofill_client_, HideAutofillPopup());
+ external_delegate_->DidAcceptSuggestion(base::string16(),
+ POPUP_ITEM_ID_SCAN_CREDIT_CARD);
+}
+
+// Test that autofill manager will fill the credit card form after user scans a
+// credit card.
+TEST_F(AutofillExternalDelegateUnitTest, FillCreditCardForm) {
+ base::string16 card_number = base::ASCIIToUTF16("test");
+ int expiration_month = 1;
+ int expiration_year = 3000;
+ EXPECT_CALL(
+ *autofill_manager_,
+ FillCreditCardForm(
+ _, _, _, CreditCard(card_number, expiration_month, expiration_year)));
+ external_delegate_->OnCreditCardScanned(card_number, expiration_month,
+ expiration_year);
+}
+
TEST_F(AutofillExternalDelegateUnitTest, ExternalDelegateHideWarning) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kRespectAutocompleteOffForAutofill);
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 63093c9..b1f3ad6 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -30,6 +30,7 @@
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
+#include "components/autofill/core/browser/field_types.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/phone_number.h"
@@ -282,19 +283,10 @@ void AutofillManager::ShowAutofillSettings() {
bool AutofillManager::ShouldShowAccessAddressBookSuggestion(
const FormData& form,
const FormFieldData& field) {
- if (!personal_data_ || !field.should_autocomplete)
- return false;
-
- FormStructure* form_structure = NULL;
- AutofillField* autofill_field = NULL;
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
- return false;
-
- if (!form_structure->IsAutofillable())
- return false;
-
- return personal_data_->ShouldShowAccessAddressBookSuggestion(
- autofill_field->Type());
+ AutofillField* autofill_field = GetAutofillField(form, field);
+ return autofill_field &&
+ personal_data_->ShouldShowAccessAddressBookSuggestion(
+ autofill_field->Type());
}
bool AutofillManager::AccessAddressBook() {
@@ -316,6 +308,21 @@ int AutofillManager::AccessAddressBookPromptCount() {
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+bool AutofillManager::ShouldShowScanCreditCard(const FormData& form,
+ const FormFieldData& field) {
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ autofill::switches::kEnableCreditCardScan)) {
+ return false;
+ }
+
+ if (!client_->HasCreditCardScanFeature())
+ return false;
+
+ AutofillField* autofill_field = GetAutofillField(form, field);
+ return autofill_field &&
+ autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER;
+}
+
bool AutofillManager::OnFormSubmitted(const FormData& form,
const TimeTicks& timestamp) {
if (!IsValidFormData(form))
@@ -556,8 +563,6 @@ void AutofillManager::FillOrPreviewForm(
const AutofillDataModel* data_model = NULL;
size_t variant = 0;
- FormStructure* form_structure = NULL;
- AutofillField* autofill_field = NULL;
bool is_credit_card = false;
// NOTE: RefreshDataModels may invalidate |data_model| because it causes the
// PersonalDataManager to reload Mac address book entries. Thus it must come
@@ -565,119 +570,25 @@ void AutofillManager::FillOrPreviewForm(
if (!RefreshDataModels() ||
!driver_->RendererIsAvailable() ||
!GetProfileOrCreditCard(
- unique_id, &data_model, &variant, &is_credit_card) ||
- !GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ unique_id, &data_model, &variant, &is_credit_card)) {
return;
-
- DCHECK(form_structure);
- DCHECK(autofill_field);
-
- FormData result = form;
-
- base::string16 profile_full_name;
- std::string profile_language_code;
- if (!is_credit_card) {
- profile_full_name = data_model->GetInfo(
- AutofillType(NAME_FULL), app_locale_);
- profile_language_code =
- static_cast<const AutofillProfile*>(data_model)->language_code();
}
- // If the relevant section is auto-filled, we should fill |field| but not the
- // rest of the form.
- if (SectionIsAutofilled(*form_structure, form, autofill_field->section())) {
- for (std::vector<FormFieldData>::iterator iter = result.fields.begin();
- iter != result.fields.end(); ++iter) {
- if (iter->SameFieldAs(field)) {
- base::string16 value = data_model->GetInfoForVariant(
- autofill_field->Type(), variant, app_locale_);
- if (AutofillField::FillFormField(*autofill_field,
- value,
- profile_language_code,
- app_locale_,
- &(*iter))) {
- // Mark the cached field as autofilled, so that we can detect when a
- // user edits an autofilled field (for metrics).
- autofill_field->is_autofilled = true;
-
- // Mark the field as autofilled when a non-empty value is assigned to
- // it. This allows the renderer to distinguish autofilled fields from
- // fields with non-empty values, such as select-one fields.
- iter->is_autofilled = true;
-
- if (!is_credit_card && !value.empty())
- client_->DidFillOrPreviewField(value, profile_full_name);
- }
- break;
- }
- }
+ FillOrPreviewDataModelForm(action, query_id, form, field, data_model, variant,
+ is_credit_card);
+}
- driver_->SendFormDataToRenderer(query_id, action, result);
+void AutofillManager::FillCreditCardForm(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard& credit_card) {
+ if (!IsValidFormData(form) || !IsValidFormFieldData(field) ||
+ !driver_->RendererIsAvailable()) {
return;
}
- // Cache the field type for the field from which the user initiated autofill.
- FieldTypeGroup initiating_group_type = autofill_field->Type().group();
- DCHECK_EQ(form_structure->field_count(), form.fields.size());
- for (size_t i = 0; i < form_structure->field_count(); ++i) {
- if (form_structure->field(i)->section() != autofill_field->section())
- continue;
-
- DCHECK(form_structure->field(i)->SameFieldAs(result.fields[i]));
-
- const AutofillField* cached_field = form_structure->field(i);
- FieldTypeGroup field_group_type = cached_field->Type().group();
- if (field_group_type != NO_GROUP) {
- // If the field being filled is either
- // (a) the field that the user initiated the fill from, or
- // (b) part of the same logical unit, e.g. name or phone number,
- // then take the multi-profile "variant" into account.
- // Otherwise fill with the default (zeroth) variant.
- size_t use_variant = 0;
- if (result.fields[i].SameFieldAs(field) ||
- field_group_type == initiating_group_type) {
- use_variant = variant;
- }
- base::string16 value = data_model->GetInfoForVariant(
- cached_field->Type(), use_variant, app_locale_);
-
- // Must match ForEachMatchingFormField() in form_autofill_util.cc.
- // Only notify autofilling of empty fields and the field that initiated
- // the filling (note that "select-one" controls may not be empty but will
- // still be autofilled).
- bool should_notify =
- !is_credit_card &&
- !value.empty() &&
- (result.fields[i].SameFieldAs(field) ||
- result.fields[i].form_control_type == "select-one" ||
- result.fields[i].value.empty());
- if (AutofillField::FillFormField(*cached_field,
- value,
- profile_language_code,
- app_locale_,
- &result.fields[i])) {
- // Mark the cached field as autofilled, so that we can detect when a
- // user edits an autofilled field (for metrics).
- form_structure->field(i)->is_autofilled = true;
-
- // Mark the field as autofilled when a non-empty value is assigned to
- // it. This allows the renderer to distinguish autofilled fields from
- // fields with non-empty values, such as select-one fields.
- result.fields[i].is_autofilled = true;
-
- if (should_notify)
- client_->DidFillOrPreviewField(value, profile_full_name);
- }
- }
- }
-
- autofilled_form_signatures_.push_front(form_structure->FormSignature());
- // Only remember the last few forms that we've seen, both to avoid false
- // positives and to avoid wasting memory.
- if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
- autofilled_form_signatures_.pop_back();
-
- driver_->SendFormDataToRenderer(query_id, action, result);
+ FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id,
+ form, field, &credit_card, 0, true);
}
void AutofillManager::OnDidPreviewAutofillFormData() {
@@ -970,6 +881,130 @@ bool AutofillManager::GetProfileOrCreditCard(
return !!*data_model;
}
+void AutofillManager::FillOrPreviewDataModelForm(
+ AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const AutofillDataModel* data_model,
+ size_t variant,
+ bool is_credit_card) {
+ FormStructure* form_structure = NULL;
+ AutofillField* autofill_field = NULL;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return;
+
+ DCHECK(form_structure);
+ DCHECK(autofill_field);
+
+ FormData result = form;
+
+ base::string16 profile_full_name;
+ std::string profile_language_code;
+ if (!is_credit_card) {
+ profile_full_name = data_model->GetInfo(
+ AutofillType(NAME_FULL), app_locale_);
+ profile_language_code =
+ static_cast<const AutofillProfile*>(data_model)->language_code();
+ }
+
+ // If the relevant section is auto-filled, we should fill |field| but not the
+ // rest of the form.
+ if (SectionIsAutofilled(*form_structure, form, autofill_field->section())) {
+ for (std::vector<FormFieldData>::iterator iter = result.fields.begin();
+ iter != result.fields.end(); ++iter) {
+ if (iter->SameFieldAs(field)) {
+ base::string16 value = data_model->GetInfoForVariant(
+ autofill_field->Type(), variant, app_locale_);
+ if (AutofillField::FillFormField(*autofill_field,
+ value,
+ profile_language_code,
+ app_locale_,
+ &(*iter))) {
+ // Mark the cached field as autofilled, so that we can detect when a
+ // user edits an autofilled field (for metrics).
+ autofill_field->is_autofilled = true;
+
+ // Mark the field as autofilled when a non-empty value is assigned to
+ // it. This allows the renderer to distinguish autofilled fields from
+ // fields with non-empty values, such as select-one fields.
+ iter->is_autofilled = true;
+
+ if (!is_credit_card && !value.empty())
+ client_->DidFillOrPreviewField(value, profile_full_name);
+ }
+ break;
+ }
+ }
+
+ driver_->SendFormDataToRenderer(query_id, action, result);
+ return;
+ }
+
+ // Cache the field type for the field from which the user initiated autofill.
+ FieldTypeGroup initiating_group_type = autofill_field->Type().group();
+ DCHECK_EQ(form_structure->field_count(), form.fields.size());
+ for (size_t i = 0; i < form_structure->field_count(); ++i) {
+ if (form_structure->field(i)->section() != autofill_field->section())
+ continue;
+
+ DCHECK(form_structure->field(i)->SameFieldAs(result.fields[i]));
+
+ const AutofillField* cached_field = form_structure->field(i);
+ FieldTypeGroup field_group_type = cached_field->Type().group();
+ if (field_group_type != NO_GROUP) {
+ // If the field being filled is either
+ // (a) the field that the user initiated the fill from, or
+ // (b) part of the same logical unit, e.g. name or phone number,
+ // then take the multi-profile "variant" into account.
+ // Otherwise fill with the default (zeroth) variant.
+ size_t use_variant = 0;
+ if (result.fields[i].SameFieldAs(field) ||
+ field_group_type == initiating_group_type) {
+ use_variant = variant;
+ }
+ base::string16 value = data_model->GetInfoForVariant(
+ cached_field->Type(), use_variant, app_locale_);
+
+ // Must match ForEachMatchingFormField() in form_autofill_util.cc.
+ // Only notify autofilling of empty fields and the field that initiated
+ // the filling (note that "select-one" controls may not be empty but will
+ // still be autofilled).
+ bool should_notify =
+ !is_credit_card &&
+ !value.empty() &&
+ (result.fields[i].SameFieldAs(field) ||
+ result.fields[i].form_control_type == "select-one" ||
+ result.fields[i].value.empty());
+ if (AutofillField::FillFormField(*cached_field,
+ value,
+ profile_language_code,
+ app_locale_,
+ &result.fields[i])) {
+ // Mark the cached field as autofilled, so that we can detect when a
+ // user edits an autofilled field (for metrics).
+ form_structure->field(i)->is_autofilled = true;
+
+ // Mark the field as autofilled when a non-empty value is assigned to
+ // it. This allows the renderer to distinguish autofilled fields from
+ // fields with non-empty values, such as select-one fields.
+ result.fields[i].is_autofilled = true;
+
+ if (should_notify)
+ client_->DidFillOrPreviewField(value, profile_full_name);
+ }
+ }
+ }
+
+ autofilled_form_signatures_.push_front(form_structure->FormSignature());
+ // Only remember the last few forms that we've seen, both to avoid false
+ // positives and to avoid wasting memory.
+ if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
+ autofilled_form_signatures_.pop_back();
+
+ driver_->SendFormDataToRenderer(query_id, action, result);
+}
+
bool AutofillManager::FindCachedForm(const FormData& form,
FormStructure** form_structure) const {
// Find the FormStructure that corresponds to |form|.
@@ -1036,6 +1071,22 @@ bool AutofillManager::GetCachedFormAndField(const FormData& form,
return *autofill_field != NULL;
}
+AutofillField* AutofillManager::GetAutofillField(const FormData& form,
+ const FormFieldData& field) {
+ if (!personal_data_ || !field.should_autocomplete)
+ return NULL;
+
+ FormStructure* form_structure = NULL;
+ AutofillField* autofill_field = NULL;
+ if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
+ return NULL;
+
+ if (!form_structure->IsAutofillable())
+ return NULL;
+
+ return autofill_field;
+}
+
bool AutofillManager::UpdateCachedForm(const FormData& live_form,
const FormStructure* cached_form,
FormStructure** updated_form) {
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 58058c7..326dd8b 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -81,10 +81,10 @@ class AutofillManager : public AutofillDownloadManager::Observer {
void ShowAutofillSettings();
#if defined(OS_MACOSX) && !defined(OS_IOS)
- // Whether the field represented by |fieldData| should show an entry to prompt
- // the user to give Chrome access to the user's address book.
- bool ShouldShowAccessAddressBookSuggestion(const FormData& data,
- const FormFieldData& field_data);
+ // Whether the |field| should show an entry to prompt the user to give Chrome
+ // access to the user's address book.
+ bool ShouldShowAccessAddressBookSuggestion(const FormData& form,
+ const FormFieldData& field);
// If Chrome has not prompted for access to the user's address book, the
// method prompts the user for permission and blocks the process. Otherwise,
@@ -99,12 +99,20 @@ class AutofillManager : public AutofillDownloadManager::Observer {
int AccessAddressBookPromptCount();
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+ // Whether the |field| should show an entry to scan a credit card.
+ bool ShouldShowScanCreditCard(const FormData& form,
+ const FormFieldData& field);
+
// Called from our external delegate so they cannot be private.
virtual void FillOrPreviewForm(AutofillDriver::RendererFormDataAction action,
int query_id,
const FormData& form,
const FormFieldData& field,
int unique_id);
+ virtual void FillCreditCardForm(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const CreditCard& credit_card);
void DidShowSuggestions(bool is_new_popup);
void OnDidFillAutofillFormData(const base::TimeTicks& timestamp);
void OnDidPreviewAutofillFormData();
@@ -229,6 +237,15 @@ class AutofillManager : public AutofillDownloadManager::Observer {
size_t* variant,
bool* is_credit_card) const WARN_UNUSED_RESULT;
+ // Fills or previews |data_model| in the |form|.
+ void FillOrPreviewDataModelForm(AutofillDriver::RendererFormDataAction action,
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const AutofillDataModel* data_model,
+ size_t variant,
+ bool is_credit_card);
+
// Fills |form_structure| cached element corresponding to |form|.
// Returns false if the cached element was not found.
bool FindCachedForm(const FormData& form,
@@ -243,6 +260,12 @@ class AutofillManager : public AutofillDownloadManager::Observer {
FormStructure** form_structure,
AutofillField** autofill_field) WARN_UNUSED_RESULT;
+ // Returns the field corresponding to |form| and |field| that can be
+ // autofilled. Returns NULL if the field cannot be autofilled.
+ AutofillField* GetAutofillField(const FormData& form,
+ const FormFieldData& field)
+ WARN_UNUSED_RESULT;
+
// Re-parses |live_form| and adds the result to |form_structures_|.
// |cached_form| should be a pointer to the existing version of the form, or
// NULL if no cached version exists. The updated form is then written into
diff --git a/components/autofill/core/browser/credit_card.cc b/components/autofill/core/browser/credit_card.cc
index c15b9dc..85c50ed 100644
--- a/components/autofill/core/browser/credit_card.cc
+++ b/components/autofill/core/browser/credit_card.cc
@@ -118,6 +118,15 @@ CreditCard::CreditCard(const std::string& guid, const std::string& origin)
expiration_year_(0) {
}
+CreditCard::CreditCard(const base::string16& card_number,
+ int expiration_month,
+ int expiration_year)
+ : AutofillDataModel(std::string(), std::string()) {
+ SetNumber(card_number);
+ SetExpirationMonth(expiration_month);
+ SetExpirationYear(expiration_year);
+}
+
CreditCard::CreditCard()
: AutofillDataModel(base::GenerateGUID(), std::string()),
record_type_(LOCAL_CARD),
diff --git a/components/autofill/core/browser/credit_card.h b/components/autofill/core/browser/credit_card.h
index 9c38d4a..311d784 100644
--- a/components/autofill/core/browser/credit_card.h
+++ b/components/autofill/core/browser/credit_card.h
@@ -33,6 +33,9 @@ class CreditCard : public AutofillDataModel {
};
CreditCard(const std::string& guid, const std::string& origin);
+ CreditCard(const base::string16& card_number,
+ int expiration_month,
+ int expiration_year);
// For use in STL containers.
CreditCard();
diff --git a/components/autofill/core/browser/credit_card_unittest.cc b/components/autofill/core/browser/credit_card_unittest.cc
index 515b189..3469646 100644
--- a/components/autofill/core/browser/credit_card_unittest.cc
+++ b/components/autofill/core/browser/credit_card_unittest.cc
@@ -545,4 +545,14 @@ TEST(CreditCardTest, LastFourDigits) {
ASSERT_EQ(base::ASCIIToUTF16("489"), card.LastFourDigits());
}
+TEST(CreditCardTest, CanBuildFromCardNumberAndExpirationDate) {
+ base::string16 card_number = base::ASCIIToUTF16("test");
+ int month = 1;
+ int year = 3000;
+ CreditCard card(card_number, month, year);
+ EXPECT_EQ(card_number, card.number());
+ EXPECT_EQ(month, card.expiration_month());
+ EXPECT_EQ(year, card.expiration_year());
+}
+
} // namespace autofill
diff --git a/components/autofill/core/browser/popup_item_ids.h b/components/autofill/core/browser/popup_item_ids.h
index 7a8e843..7dd75d8 100644
--- a/components/autofill/core/browser/popup_item_ids.h
+++ b/components/autofill/core/browser/popup_item_ids.h
@@ -18,6 +18,7 @@ enum PopupItemId {
POPUP_ITEM_ID_AUTOFILL_OPTIONS = -5,
POPUP_ITEM_ID_DATALIST_ENTRY = -6,
POPUP_ITEM_ID_MAC_ACCESS_CONTACTS = -7,
+ POPUP_ITEM_ID_SCAN_CREDIT_CARD = -8,
};
} // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc
index 3b73339..6a2b1ae 100644
--- a/components/autofill/core/browser/test_autofill_client.cc
+++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -36,6 +36,14 @@ void TestAutofillClient::ConfirmSaveCreditCard(
const base::Closure& save_card_callback) {
}
+bool TestAutofillClient::HasCreditCardScanFeature() {
+ return false;
+}
+
+void TestAutofillClient::ScanCreditCard(
+ const CreditCardScanCallback& callback) {
+}
+
void TestAutofillClient::ShowRequestAutocompleteDialog(
const FormData& form,
const GURL& source_url,
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h
index 6fc8153..f3d8328 100644
--- a/components/autofill/core/browser/test_autofill_client.h
+++ b/components/autofill/core/browser/test_autofill_client.h
@@ -27,6 +27,8 @@ class TestAutofillClient : public AutofillClient {
void ShowAutofillSettings() override;
void ConfirmSaveCreditCard(const AutofillMetrics& metric_logger,
const base::Closure& save_card_callback) override;
+ bool HasCreditCardScanFeature() override;
+ void ScanCreditCard(const CreditCardScanCallback& callback) override;
void ShowRequestAutocompleteDialog(const FormData& form,
const GURL& source_url,
const ResultCallback& callback) override;
diff --git a/components/autofill/core/common/autofill_switches.cc b/components/autofill/core/common/autofill_switches.cc
index 7e7a16b..f0120d4 100644
--- a/components/autofill/core/common/autofill_switches.cc
+++ b/components/autofill/core/common/autofill_switches.cc
@@ -15,6 +15,10 @@ const char kDisablePasswordGeneration[] = "disable-password-generation";
const char kDisambiguateAutofillServerNameTypes[] =
"disambiguate-autofill-server-name-types";
+// Enables using device's camera to scan a new credit card when filling out a
+// credit card form.
+const char kEnableCreditCardScan[] = "enable-credit-card-scan";
+
// Enables password generation when we detect that the user is going through
// account creation.
const char kEnablePasswordGeneration[] = "enable-password-generation";
diff --git a/components/autofill/core/common/autofill_switches.h b/components/autofill/core/common/autofill_switches.h
index 69f2e4a..cdf6078 100644
--- a/components/autofill/core/common/autofill_switches.h
+++ b/components/autofill/core/common/autofill_switches.h
@@ -12,6 +12,7 @@ namespace switches {
// alongside the definition of their values in the .cc file.
extern const char kDisablePasswordGeneration[];
extern const char kDisambiguateAutofillServerNameTypes[];
+extern const char kEnableCreditCardScan[];
extern const char kEnablePasswordGeneration[];
extern const char kIgnoreAutocompleteOffForAutofill[];
extern const char kLocalHeuristicsOnlyForPasswordGeneration[];
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index 5a3fd5e..bb95163 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -124,4 +124,8 @@
</message>
</if>
+ <message name="IDS_AUTOFILL_SCAN_CREDIT_CARD" desc="An item in the autofill popup that triggers a new credit card to be scanned using the camera on the device.">
+ Scan new card
+ </message>
+
</grit-part>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index f0229db..95b8cea 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -48913,6 +48913,7 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="887011602" label="enable-spelling-auto-correct"/>
<int value="909439558" label="disable-device-discovery"/>
<int value="929462705" label="disable-link-disambiguation-popup"/>
+ <int value="939554480" label="enable-credit-card-scan"/>
<int value="952558794" label="enable-remote-assistance"/>
<int value="980396200" label="enable-new-korean-ime"/>
<int value="1022992701" label="enable-origin-chip-always"/>