summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android_webview/lib/main/webview_stubs.cc10
-rwxr-xr-xbase/android/jni_generator/jni_generator.py4
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExternalDelegate.java102
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java28
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillWindow.java203
-rw-r--r--chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java3
-rw-r--r--chrome/android/testshell/res/layout/autofill_text.xml29
-rw-r--r--chrome/android/testshell/testshell_stubs.cc7
-rw-r--r--chrome/browser/android/chrome_jni_registrar.cc3
-rw-r--r--chrome/browser/autofill/test_autofill_external_delegate_android.cc16
-rw-r--r--chrome/browser/ui/android/autofill/autofill_external_delegate.cc126
-rw-r--r--chrome/browser/ui/android/autofill/autofill_external_delegate.h64
-rw-r--r--chrome/chrome_browser.gypi1
-rw-r--r--chrome/chrome_browser_ui.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/test/base/chrome_test_suite.cc2
-rw-r--r--content/browser/android/content_view_core_impl.cc8
-rw-r--r--content/browser/android/content_view_core_impl.h2
-rw-r--r--content/public/android/java/src/org/chromium/content/app/AppResource.java9
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java25
-rw-r--r--content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java26
-rw-r--r--content/public/browser/android/content_view_core.h2
22 files changed, 638 insertions, 35 deletions
diff --git a/android_webview/lib/main/webview_stubs.cc b/android_webview/lib/main/webview_stubs.cc
index 50179d2..de2a058 100644
--- a/android_webview/lib/main/webview_stubs.cc
+++ b/android_webview/lib/main/webview_stubs.cc
@@ -4,7 +4,6 @@
#include "chrome/browser/android/tab_android.h"
#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
-#include "chrome/browser/autofill/autofill_external_delegate.h"
// This file contains temporary stubs to allow the libwebview target to compile.
// They will be removed once real implementations are written/upstreamed, or
@@ -18,15 +17,6 @@ TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
}
// static
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
- // We don't need to return a real AutofillExternalDelegate yet.
- // Eventually, WebView will need an implementation (probably shared with
- // Chrome).
-}
-
-// static
InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
return NULL;
}
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py
index afc2389..431a6c2 100755
--- a/base/android/jni_generator/jni_generator.py
+++ b/base/android/jni_generator/jni_generator.py
@@ -153,7 +153,6 @@ def JavaParamToJni(param):
]
app_param_list = [
'Landroid/graphics/SurfaceTexture',
- 'Lcom/google/android/apps/chrome/AutofillData',
'Lcom/google/android/apps/chrome/ChromeContextMenuInfo',
'Lcom/google/android/apps/chrome/ChromeWindow',
'Lcom/google/android/apps/chrome/OmniboxSuggestion',
@@ -173,6 +172,8 @@ def JavaParamToJni(param):
'Lorg/chromium/android_webview/JsResultHandler',
'Lorg/chromium/android_webview/JsResultReceiver',
'Lorg/chromium/base/SystemMessageHandler',
+ 'Lorg/chromium/chrome/browser/autofill/AutofillExternalDelegate',
+ 'Lorg/chromium/chrome/browser/autofill/AutofillSuggestion',
'Lorg/chromium/chrome/browser/ChromeBrowserProvider$BookmarkNode',
'Lorg/chromium/chrome/browser/ChromeHttpAuthHandler',
'Lorg/chromium/chrome/browser/ChromeWebContentsDelegateAndroid',
@@ -186,6 +187,7 @@ def JavaParamToJni(param):
'WebContentsDelegateAndroid'),
'Lorg/chromium/chrome/browser/database/SQLiteCursor',
'Lorg/chromium/content/app/SandboxedProcessService',
+ 'Lorg/chromium/content/browser/ContainerViewDelegate',
'Lorg/chromium/content/browser/ContentVideoView',
'Lorg/chromium/content/browser/ContentViewCore',
'Lorg/chromium/content/browser/DeviceOrientation',
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExternalDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExternalDelegate.java
new file mode 100644
index 0000000..50ca016
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillExternalDelegate.java
@@ -0,0 +1,102 @@
+// Copyright (c) 2012 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.graphics.Rect;
+
+import org.chromium.base.CalledByNative;
+import org.chromium.content.browser.ContainerViewDelegate;
+import org.chromium.ui.gfx.NativeWindow;
+
+/**
+ * Android specific external delegate for display and selection of autofill data.
+ */
+public class AutofillExternalDelegate {
+
+ // Area of the Autofill popup anchor position used to position the Autofill window.
+ private Rect mAutofillAnchorRect;
+ private AutofillWindow mAutofillWindow;
+ private final int mNativeAutofillExternalDelegate;
+ private final ContainerViewDelegate mContainerViewDelegate;
+
+ /**
+ * Creates an AutofillExternalDelegate object.
+ * @param nativeAutofillExternalDelegate A pointer to the native AutofillExternalDelegate.
+ * @param containerViewDelegate A delegate that allows adding and removing views.
+ */
+ public AutofillExternalDelegate(int nativeAutofillExternalDelegate,
+ ContainerViewDelegate containerViewDelegate) {
+ mNativeAutofillExternalDelegate = nativeAutofillExternalDelegate;
+ mContainerViewDelegate = containerViewDelegate;
+ }
+
+ @CalledByNative
+ private static AutofillExternalDelegate create(int nativeAutofillExternalDelegate,
+ ContainerViewDelegate containerViewDelegate) {
+ return new AutofillExternalDelegate(nativeAutofillExternalDelegate, containerViewDelegate);
+ }
+
+ /**
+ * Sets the autofill window's position in the proper space (window space).
+ */
+ private void setAutofillWindowPosition() {
+ if (mAutofillWindow != null && mAutofillAnchorRect != null) {
+ mAutofillWindow.setPositionAround(mAutofillAnchorRect);
+ }
+ }
+
+ /**
+ * Informs the native delegate that an Autofill suggestion has been chosen.
+ * @param listIndex The index of the autofill suggestion selected
+ * @param value The value of the autofill suggestion.
+ * @param uniqueId The unique ID of the autofill suggestion selected.
+ */
+ public void autofillPopupSelected(int listIndex, String value, int uniqueId) {
+ if (mNativeAutofillExternalDelegate != 0) {
+ nativeAutofillPopupSelected(
+ mNativeAutofillExternalDelegate, listIndex, value, uniqueId);
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void openAutofillPopup(NativeWindow nativeWindow, AutofillSuggestion[] data) {
+ if (mAutofillWindow == null) {
+ mAutofillWindow = new AutofillWindow(nativeWindow, mContainerViewDelegate, this, data);
+ } else {
+ mAutofillWindow.setAutofillSuggestions(data);
+ }
+ if (mAutofillAnchorRect != null) {
+ setAutofillWindowPosition();
+ mAutofillWindow.show();
+ }
+ }
+
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void closeAutofillPopup() {
+ if (mAutofillWindow == null) return;
+ mAutofillWindow.dismiss();
+ mAutofillWindow = null;
+ mAutofillAnchorRect = null;
+ }
+
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private void setAutofillAnchorRect(float x, float y, float width, float height) {
+ mAutofillAnchorRect = new Rect((int) x, (int) y, (int) (x + width), (int) (y + height));
+ setAutofillWindowPosition();
+ }
+
+ @SuppressWarnings("unused")
+ @CalledByNative
+ private static AutofillSuggestion createAutofillSuggestion(String name, String label,
+ int uniqueId) {
+ return new AutofillSuggestion(name, label, uniqueId);
+ }
+
+ private native void nativeAutofillPopupSelected(int nativeAutofillExternalDelegateAndroid,
+ int listIndex, String value, int uniqueId);
+} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java
new file mode 100644
index 0000000..4a5dfa4
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillSuggestion.java
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 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 org.chromium.base.CalledByNative;
+
+/**
+ * Autofill suggestion container used to store information needed for each Autofill popup entry.
+ */
+class AutofillSuggestion {
+ public final String mName;
+ public final String mLabel;
+ public final int mUniqueId;
+
+ /**
+ * Constructs a Autofill suggestion container.
+ * @param name The name of the Autofill suggestion.
+ * @param label The describing label of the Autofill suggestion.
+ * @param uniqueId The unique id used to identify the Autofill suggestion.
+ */
+ AutofillSuggestion(String name, String label, int uniqueId) {
+ mName = name;
+ mLabel = label;
+ mUniqueId = uniqueId;
+ }
+} \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillWindow.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillWindow.java
new file mode 100644
index 0000000..cd48573
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillWindow.java
@@ -0,0 +1,203 @@
+// Copyright (c) 2012 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 android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+import android.widget.ListPopupWindow;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+
+import org.chromium.content.app.AppResource;
+import org.chromium.content.browser.ContainerViewDelegate;
+import org.chromium.ui.gfx.NativeWindow;
+
+/**
+ * The Autofill suggestion window that lists relevant suggestions.
+ */
+public class AutofillWindow extends ListPopupWindow {
+
+ private static final int TEXT_PADDING_DP = 30;
+
+ private NativeWindow mNativeWindow;
+ private int mDesiredWidth;
+ private AnchorView mAnchorView;
+ private ContainerViewDelegate mContainerViewDelegate;
+ private Paint mNameViewPaint;
+ private Paint mLabelViewPaint;
+
+ private static class AutofillListAdapter extends ArrayAdapter<AutofillSuggestion> {
+ private Context mContext;
+
+ AutofillListAdapter(Context context, ArrayList<AutofillSuggestion> objects) {
+ super(context, AppResource.LAYOUT_AUTOFILL_TEXT, objects);
+ mContext = context;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View layout = convertView;
+ if (convertView == null) {
+ LayoutInflater inflater =
+ (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ layout = inflater.inflate(AppResource.LAYOUT_AUTOFILL_TEXT, null);
+ }
+ TextView nameView = (TextView) layout.findViewById(AppResource.ID_AUTOFILL_NAME);
+ nameView.setText(getItem(position).mName);
+ TextView labelView = (TextView) layout.findViewById(AppResource.ID_AUTOFILL_LABEL);
+ labelView.setText(getItem(position).mLabel);
+
+ return layout;
+ }
+ }
+
+ // ListPopupWindow needs an anchor view to determine it's size and position. We create a view
+ // with the given desired width at the text edit area as a stand-in. This is "Fake" in the
+ // sense that it draws nothing, accepts no input, and thwarts all attempts at laying it out
+ // "properly".
+ private static class AnchorView extends View {
+ AnchorView(Context c) {
+ super(c);
+ }
+
+ public void setSize(Rect r, int desiredWidth) {
+ setLeft(r.left);
+ // If the desired width is smaller than the text edit box, use the width of the text
+ // editbox.
+ if (desiredWidth < r.right - r.left) {
+ setRight(r.right);
+ } else {
+ // Make sure that the anchor view does not go outside the screen.
+ Point size = new Point();
+ WindowManager wm = (WindowManager) getContext().getSystemService(
+ Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getSize(size);
+ if (r.left + desiredWidth > size.x) {
+ setRight(size.x);
+ } else {
+ setRight(r.left + desiredWidth);
+ }
+ }
+ setBottom(r.bottom);
+ setTop(r.top);
+ }
+ }
+
+
+ /**
+ * Creates an AutofillWindow with specified parameters.
+ * @param nativeWindow NativeWindow used to get application context.
+ * @param ContainerViewDelegate View delegate used to add and remove views.
+ * @param autofillExternalDelegate The autofill delegate.
+ * @param data The autofill suggestions.
+ */
+ public AutofillWindow(NativeWindow nativeWindow, ContainerViewDelegate ContainerViewDelegate,
+ final AutofillExternalDelegate autofillExternalDelegate, AutofillSuggestion[] data) {
+ super(nativeWindow.getContext());
+ mNativeWindow = nativeWindow;
+ mContainerViewDelegate = ContainerViewDelegate;
+ setAutofillSuggestions(data);
+ setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ try {
+ ListAdapter adapter = (ListAdapter) parent.getAdapter();
+ AutofillSuggestion data = (AutofillSuggestion) adapter.getItem(position);
+ autofillExternalDelegate.autofillPopupSelected(position, data.mName,
+ data.mUniqueId);
+ } catch (ClassCastException e) {
+ Log.w("AutofillWindow", "error in onItemClick", e);
+ assert false;
+ }
+ }
+ });
+ setWidth(ListPopupWindow.WRAP_CONTENT);
+ }
+
+ /**
+ * Sets the position of the autofill popup "around" the input rectangle.
+ * @param r The rectangle location for the autofill popup.
+ */
+ public void setPositionAround(Rect r) {
+ if (mAnchorView == null) {
+ mAnchorView = new AnchorView(mNativeWindow.getContext());
+ mContainerViewDelegate.addViewToContainerView(mAnchorView);
+ // When the popup goes away we have to remove the fake anchor view.
+ setOnDismissListener(new PopupWindow.OnDismissListener() {
+ @Override
+ public void onDismiss() {
+ mContainerViewDelegate.removeViewFromContainerView(mAnchorView);
+ mAnchorView = null;
+ }
+ });
+ }
+ mAnchorView.setSize(r, mDesiredWidth);
+ setAnchorView(mAnchorView);
+ }
+
+ /**
+ * Sets the autofill data to display in the popup.
+ * @param data Autofill suggestion data.
+ */
+ public void setAutofillSuggestions(AutofillSuggestion[] data) {
+ // Remove the AutofillSuggestions with IDs that are unsupported by Android
+ ArrayList<AutofillSuggestion> cleanedData = new ArrayList<AutofillSuggestion>();
+ for (int i = 0; i < data.length; i++) {
+ if (data[i].mUniqueId >= 0) cleanedData.add(data[i]);
+ }
+
+ mDesiredWidth = getDesiredWidth(data);
+ setAdapter(new AutofillListAdapter(mNativeWindow.getContext(), cleanedData));
+ }
+
+ /**
+ * Get desired popup window width by calculating the maximum text length from Autofill data.
+ * @param data Autofill suggestion data.
+ * @return The popup window width.
+ */
+ private int getDesiredWidth(AutofillSuggestion[] data) {
+ if (mNameViewPaint == null || mLabelViewPaint == null) {
+ LayoutInflater inflater =
+ (LayoutInflater) mNativeWindow.getContext().getSystemService(
+ Context.LAYOUT_INFLATER_SERVICE);
+ View layout = inflater.inflate(AppResource.LAYOUT_AUTOFILL_TEXT, null);
+ TextView nameView = (TextView) layout.findViewById(AppResource.ID_AUTOFILL_NAME);
+ mNameViewPaint = nameView.getPaint();
+ TextView labelView = (TextView) layout.findViewById(AppResource.ID_AUTOFILL_LABEL);
+ mLabelViewPaint = labelView.getPaint();
+ }
+
+ int maxTextWidth = 0;
+ Rect bounds = new Rect();
+ for (int i = 0; i < data.length; ++i) {
+ bounds.setEmpty();
+ String name = data[i].mName;
+ int width = 0;
+ mNameViewPaint.getTextBounds(name, 0, name.length(), bounds);
+ width += bounds.width();
+
+ bounds.setEmpty();
+ String label = data[i].mLabel;
+ mLabelViewPaint.getTextBounds(label, 0, label.length(), bounds);
+ width += bounds.width();
+ maxTextWidth = Math.max(width, maxTextWidth);
+ }
+ // Adding padding.
+ return maxTextWidth + (int) (TEXT_PADDING_DP *
+ mNativeWindow.getContext().getResources().getDisplayMetrics().density);
+ }
+}
diff --git a/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java b/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java
index fada504..5887a69 100644
--- a/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java
+++ b/chrome/android/testshell/java/src/org/chromium/chrome/testshell/ChromiumTestShellActivity.java
@@ -119,6 +119,9 @@ public class ChromiumTestShellActivity extends Activity {
private void initializeContentViewResources() {
AppResource.DIMENSION_LINK_PREVIEW_OVERLAY_RADIUS = R.dimen.link_preview_overlay_radius;
AppResource.DRAWABLE_LINK_PREVIEW_POPUP_OVERLAY = R.drawable.popup_zoomer_overlay;
+ AppResource.ID_AUTOFILL_LABEL = R.id.autofill_label;
+ AppResource.ID_AUTOFILL_NAME = R.id.autofill_name;
+ AppResource.LAYOUT_AUTOFILL_TEXT = R.layout.autofill_text;
AppResource.STRING_CONTENT_VIEW_CONTENT_DESCRIPTION = R.string.accessibility_content_view;
AppResource.STRING_MEDIA_PLAYER_MESSAGE_PLAYBACK_ERROR =
R.string.media_player_error_text_invalid_progressive_playback;
diff --git a/chrome/android/testshell/res/layout/autofill_text.xml b/chrome/android/testshell/res/layout/autofill_text.xml
new file mode 100644
index 0000000..0a9e113
--- /dev/null
+++ b/chrome/android/testshell/res/layout/autofill_text.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright (c) 2012 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.
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="fill_parent"
+ android:layout_width="fill_parent"
+ android:orientation="horizontal">
+ <TextView android:id="@+id/autofill_name"
+ android:layout_alignParentLeft="true"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:background="#FFF"
+ android:padding="5dp"
+ android:textSize="18sp"
+ android:textColor="#000"/>
+ <TextView android:id="@+id/autofill_label"
+ android:layout_alignParentRight="true"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="5dp"
+ android:textSize="18sp"
+ android:background="#FFF"
+ android:textColor="#CCC"/>
+</RelativeLayout> \ No newline at end of file
diff --git a/chrome/android/testshell/testshell_stubs.cc b/chrome/android/testshell/testshell_stubs.cc
index 67edc68..10798d4 100644
--- a/chrome/android/testshell/testshell_stubs.cc
+++ b/chrome/android/testshell/testshell_stubs.cc
@@ -4,7 +4,6 @@
#include "base/logging.h"
#include "chrome/browser/android/tab_android.h"
-#include "chrome/browser/autofill/autofill_external_delegate.h"
#include "chrome/browser/api/infobars/confirm_infobar_delegate.h"
// This file contains temporary stubs to allow the libtestshell target to
@@ -17,12 +16,6 @@ TabAndroid* TabAndroid::FromWebContents(content::WebContents* web_contents) {
return NULL;
}
-// static
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
-}
-
InfoBar* ConfirmInfoBarDelegate::CreateInfoBar(InfoBarService* owner) {
NOTIMPLEMENTED();
return NULL;
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 5d5db92..d8c5e94 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -13,12 +13,15 @@
#include "chrome/browser/android/provider/chrome_browser_provider.h"
#include "chrome/browser/component/web_contents_delegate_android/component_jni_registrar.h"
#include "chrome/browser/history/android/sqlite_cursor.h"
+#include "chrome/browser/ui/android/autofill/autofill_external_delegate.h"
#include "chrome/browser/ui/android/javascript_app_modal_dialog_android.h"
namespace chrome {
namespace android {
static base::android::RegistrationMethod kChromeRegisteredMethods[] = {
+ { "AutofillExternalDelegate",
+ AutofillExternalDelegateAndroid::RegisterAutofillExternalDelegate},
{ "ChromeBrowserProvider",
ChromeBrowserProvider::RegisterChromeBrowserProvider },
{ "ChromeWebContentsDelegateAndroid",
diff --git a/chrome/browser/autofill/test_autofill_external_delegate_android.cc b/chrome/browser/autofill/test_autofill_external_delegate_android.cc
deleted file mode 100644
index 4e42fdf..0000000
--- a/chrome/browser/autofill/test_autofill_external_delegate_android.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright (c) 2012 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/autofill/test_autofill_external_delegate.h"
-
-void AutofillExternalDelegate::CreateForWebContentsAndManager(
- content::WebContents* web_contents,
- AutofillManager* autofill_manager) {
- if (FromWebContents(web_contents))
- return;
-
- web_contents->SetUserData(
- UserDataKey(),
- new TestAutofillExternalDelegate(web_contents, autofill_manager));
-}
diff --git a/chrome/browser/ui/android/autofill/autofill_external_delegate.cc b/chrome/browser/ui/android/autofill/autofill_external_delegate.cc
new file mode 100644
index 0000000..7399034
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_external_delegate.cc
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 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/autofill_external_delegate.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/android/jni_string.h"
+#include "base/string_util.h"
+#include "chrome/browser/autofill/autofill_manager.h"
+#include "chrome/browser/ui/android/window_android_helper.h"
+#include "content/public/browser/android/content_view_core.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "jni/AutofillExternalDelegate_jni.h"
+#include "ui/gfx/android/window_android.h"
+#include "ui/gfx/rect.h"
+
+using base::android::MethodID;
+using content::BrowserThread;
+
+void AutofillExternalDelegate::CreateForWebContentsAndManager(
+ content::WebContents* web_contents,
+ AutofillManager* autofill_manager) {
+ if (FromWebContents(web_contents))
+ return;
+
+ web_contents->SetUserData(
+ UserDataKey(),
+ new AutofillExternalDelegateAndroid(web_contents, autofill_manager));
+}
+
+AutofillExternalDelegateAndroid::AutofillExternalDelegateAndroid(
+ content::WebContents* web_contents, AutofillManager* manager)
+ : AutofillExternalDelegate(web_contents, manager) {
+ content::ContentViewCore* content_view_core =
+ content::ContentViewCore::FromWebContents(web_contents);
+
+ JNIEnv* env = base::android::AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> container_view_delegate;
+ // content_view_core should only be NULL for testing.
+ if (content_view_core) {
+ container_view_delegate = content_view_core->GetContainerViewDelegate();
+ }
+
+ java_object_.Reset(Java_AutofillExternalDelegate_create(env,
+ reinterpret_cast<jint>(this), container_view_delegate.obj()));
+}
+
+AutofillExternalDelegateAndroid::~AutofillExternalDelegateAndroid() {}
+
+void AutofillExternalDelegateAndroid::AutofillPopupSelected(JNIEnv *env,
+ jobject obj,
+ jint list_index,
+ jstring value,
+ jint unique_id) {
+ string16 value_utf16 = base::android::ConvertJavaStringToUTF16(env, value);
+ DidAcceptAutofillSuggestions(value_utf16, unique_id, list_index);
+}
+
+void AutofillExternalDelegateAndroid::ApplyAutofillSuggestions(
+ const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // We need an array of AutofillSuggestion.
+ JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jclass> autofill_suggestion_clazz =
+ base::android::GetClass(env,
+ "org/chromium/chrome/browser/autofill/AutofillSuggestion");
+ ScopedJavaLocalRef<jobjectArray> data_array(env,
+ env->NewObjectArray(autofill_values.size(),
+ autofill_suggestion_clazz.obj(), NULL));
+ base::android::CheckException(env);
+ for (size_t i = 0; i < autofill_values.size(); ++i) {
+ ScopedJavaLocalRef<jstring> value =
+ base::android::ConvertUTF16ToJavaString(env, autofill_values[i]);
+ ScopedJavaLocalRef<jstring> label =
+ base::android::ConvertUTF16ToJavaString(env, autofill_labels[i]);
+ int unique_id = autofill_unique_ids[i];
+ ScopedJavaLocalRef<jobject> data =
+ Java_AutofillExternalDelegate_createAutofillSuggestion(env,
+ value.obj(),
+ label.obj(),
+ unique_id);
+ env->SetObjectArrayElement(data_array.obj(), i, data.obj());
+ base::android::CheckException(env);
+ }
+ ui::WindowAndroid* window_android =
+ WindowAndroidHelper::FromWebContents(web_contents())->GetWindowAndroid();
+ Java_AutofillExternalDelegate_openAutofillPopup(env, java_object_.obj(),
+ window_android->GetJavaObject().obj(), data_array.obj());
+}
+
+void AutofillExternalDelegateAndroid::OnQueryPlatformSpecific(
+ int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::Rect& bounds) {
+ SetBounds(bounds);
+}
+
+void AutofillExternalDelegateAndroid::HideAutofillPopupInternal() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_AutofillExternalDelegate_closeAutofillPopup(env, java_object_.obj());
+}
+
+void AutofillExternalDelegateAndroid::SetBounds(const gfx::Rect& bounds) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_AutofillExternalDelegate_setAutofillAnchorRect(env,
+ java_object_.obj(),
+ bounds.x(),
+ bounds.y(),
+ bounds.width(),
+ bounds.height());
+}
+
+// static
+bool AutofillExternalDelegateAndroid::RegisterAutofillExternalDelegate(
+ JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
diff --git a/chrome/browser/ui/android/autofill/autofill_external_delegate.h b/chrome/browser/ui/android/autofill/autofill_external_delegate.h
new file mode 100644
index 0000000..d565f8d
--- /dev/null
+++ b/chrome/browser/ui/android/autofill/autofill_external_delegate.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2012 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_AUTOFILL_EXTERNAL_DELEGATE_H_
+#define CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_H_
+
+#include <jni.h>
+#include <map>
+#include <vector>
+
+#include "base/android/scoped_java_ref.h"
+#include "base/compiler_specific.h"
+#include "base/string16.h"
+#include "chrome/browser/autofill/autofill_external_delegate.h"
+#include "chrome/common/form_data.h"
+#include "chrome/common/form_field_data.h"
+
+class AutofillManager;
+
+namespace content {
+class WebContents;
+}
+
+// Android implementation of external delegate for display and selection of
+// Autofill suggestions.
+class AutofillExternalDelegateAndroid : public AutofillExternalDelegate {
+ public:
+ AutofillExternalDelegateAndroid(content::WebContents* web_contents,
+ AutofillManager* manager);
+ virtual ~AutofillExternalDelegateAndroid();
+
+ // --------------------------------------------------------------------------
+ // Methods called from Java via JNI
+ // --------------------------------------------------------------------------
+ // Called when an autofill item was selected.
+ void AutofillPopupSelected(JNIEnv* env,
+ jobject obj,
+ jint list_index,
+ jstring value,
+ jint unique_id);
+
+ static bool RegisterAutofillExternalDelegate(JNIEnv* env);
+
+ private:
+ virtual void ApplyAutofillSuggestions(
+ const std::vector<string16>& autofill_values,
+ const std::vector<string16>& autofill_labels,
+ const std::vector<string16>& autofill_icons,
+ const std::vector<int>& autofill_unique_ids) OVERRIDE;
+ virtual void OnQueryPlatformSpecific(int query_id,
+ const FormData& form,
+ const FormFieldData& field,
+ const gfx::Rect& bounds) OVERRIDE;
+ virtual void HideAutofillPopupInternal() OVERRIDE;
+ virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE;
+
+ // The corresponding AutofillExternalDelegate java object.
+ base::android::ScopedJavaGlobalRef<jobject> java_object_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillExternalDelegateAndroid);
+};
+
+#endif // CHROME_BROWSER_UI_ANDROID_AUTOFILL_AUTOFILL_EXTERNAL_DELEGATE_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index f32ddf0..d365e6a 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2868,6 +2868,7 @@
'target_name': 'chrome_browser_jni_headers',
'type': 'none',
'sources': [
+ 'android/java/src/org/chromium/chrome/browser/autofill/AutofillExternalDelegate.java',
'android/java/src/org/chromium/chrome/browser/ChromeBrowserProvider.java',
'android/java/src/org/chromium/chrome/browser/ChromeHttpAuthHandler.java',
'android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index dc12997..21cab93 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -105,6 +105,8 @@
'browser/ui/alternate_error_tab_observer.h',
'browser/ui/android/android_about_app_info.cc',
'browser/ui/android/android_about_app_info.h',
+ 'browser/ui/android/autofill/autofill_external_delegate.cc',
+ 'browser/ui/android/autofill/autofill_external_delegate.h',
'browser/ui/android/certificate_viewer_android.cc',
'browser/ui/android/chrome_http_auth_handler.cc',
'browser/ui/android/chrome_http_auth_handler.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 38f3297..6d70aa9 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -88,7 +88,6 @@
'browser/autofill/data_driven_test.h',
'browser/autofill/test_autofill_external_delegate.cc',
'browser/autofill/test_autofill_external_delegate.h',
- 'browser/autofill/test_autofill_external_delegate_android.cc',
'browser/automation/mock_tab_event_observer.cc',
'browser/automation/mock_tab_event_observer.h',
'browser/chromeos/cros/mock_cert_library.cc',
diff --git a/chrome/test/base/chrome_test_suite.cc b/chrome/test/base/chrome_test_suite.cc
index 11e29f9..d6f6dff 100644
--- a/chrome/test/base/chrome_test_suite.cc
+++ b/chrome/test/base/chrome_test_suite.cc
@@ -33,6 +33,7 @@
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
+#include "chrome/browser/android/chrome_jni_registrar.h"
#include "net/android/net_jni_registrar.h"
#endif
@@ -194,6 +195,7 @@ void ChromeTestSuite::Initialize() {
#if defined(OS_ANDROID)
// Register JNI bindings for android.
net::android::RegisterJni(base::android::AttachCurrentThread());
+ chrome::android::RegisterJni(base::android::AttachCurrentThread());
#endif
chrome::RegisterPathProvider();
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 45c15ce..bd4137a 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -248,6 +248,14 @@ ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetJavaObject() {
return java_ref_.get(env);
}
+ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContainerViewDelegate() {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return ScopedJavaLocalRef<jobject>();
+ return Java_ContentViewCore_getContainerViewDelegate(env, obj.obj());
+}
+
void ContentViewCoreImpl::OnWebPreferencesUpdated() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index bbfc68f..ccc56af 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -44,6 +44,8 @@ class ContentViewCoreImpl : public ContentViewCore,
// ContentViewCore implementation.
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() OVERRIDE;
+ virtual base::android::ScopedJavaLocalRef<jobject> GetContainerViewDelegate()
+ OVERRIDE;
virtual WebContents* GetWebContents() const OVERRIDE;
virtual ui::WindowAndroid* GetWindowAndroid() OVERRIDE;
virtual void LoadUrl(NavigationController::LoadURLParams& params) OVERRIDE;
diff --git a/content/public/android/java/src/org/chromium/content/app/AppResource.java b/content/public/android/java/src/org/chromium/content/app/AppResource.java
index 3a2d06e..9a260f8f 100644
--- a/content/public/android/java/src/org/chromium/content/app/AppResource.java
+++ b/content/public/android/java/src/org/chromium/content/app/AppResource.java
@@ -60,6 +60,12 @@ public class AppResource {
/** Drawable resource for the link preview popup overlay. */
public static int DRAWABLE_LINK_PREVIEW_POPUP_OVERLAY;
+ /** Id of the autofill label. */
+ public static int ID_AUTOFILL_LABEL;
+
+ /** Id of the autofill name. */
+ public static int ID_AUTOFILL_NAME;
+
/** Id of the date picker view. */
public static int ID_DATE_PICKER;
@@ -93,6 +99,9 @@ public class AppResource {
/** Id of the view containing the month and year pickers. */
public static int ID_MONTH_YEAR_PICKERS_CONTAINER;
+ /** Layout of the autofill popup. */
+ public static int LAYOUT_AUTOFILL_TEXT;
+
/** Layout of the date/time picker dialog. */
public static int LAYOUT_DATE_TIME_PICKER_DIALOG;
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java b/content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java
new file mode 100644
index 0000000..8417345
--- /dev/null
+++ b/content/public/android/java/src/org/chromium/content/browser/ContainerViewDelegate.java
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 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.content.browser;
+
+import android.view.View;
+
+/**
+ * Interface to add and remove views from the implementing view.
+ */
+public interface ContainerViewDelegate {
+
+ /**
+ * Add the view.
+ * @param view The view to be added.
+ */
+ public void addViewToContainerView(View view);
+
+ /**
+ * Remove the view if it is present, otherwise do nothing.
+ * @param view The view to be removed.
+ */
+ public void removeViewFromContainerView(View view);
+} \ No newline at end of file
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 5941d8d..0812b1a 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -304,6 +304,32 @@ public class ContentViewCore implements MotionEventDelegate {
return mContainerView;
}
+ /**
+ * Returns a delegate that can be used to add and remove views from the ContainerView.
+ *
+ * NOTE: Use with care, as not all ContentViewCore users setup their ContainerView in the same
+ * way. In particular, the Android WebView has limitations on what implementation details can
+ * be provided via a child view, as they are visible in the API and could introduce
+ * compatibility breaks with existing applications. If in doubt, contact the
+ * android_webview/OWNERS
+ *
+ * @return A ContainerViewDelegate that can be used to add and remove views.
+ */
+ @CalledByNative
+ public ContainerViewDelegate getContainerViewDelegate() {
+ return new ContainerViewDelegate() {
+ @Override
+ public void addViewToContainerView(View view) {
+ mContainerView.addView(view);
+ }
+
+ @Override
+ public void removeViewFromContainerView(View view) {
+ mContainerView.removeView(view);
+ }
+ };
+ }
+
private ImeAdapter createImeAdapter(Context context) {
return new ImeAdapter(context, getSelectionHandleController(),
getInsertionHandleController(),
diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h
index bce865f..7be47e9 100644
--- a/content/public/browser/android/content_view_core.h
+++ b/content/public/browser/android/content_view_core.h
@@ -32,6 +32,8 @@ class ContentViewCore {
virtual WebContents* GetWebContents() const = 0;
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaObject() = 0;
+ virtual base::android::ScopedJavaLocalRef<jobject> GetContainerViewDelegate()
+ = 0;
virtual ui::WindowAndroid* GetWindowAndroid() = 0;
virtual void LoadUrl(NavigationController::LoadURLParams& params) = 0;
virtual void OnWebPreferencesUpdated() = 0;