From d0fc68897b5a7379951aaa5d50f0802dbe9e00d4 Mon Sep 17 00:00:00 2001 From: Ben Murdoch Date: Fri, 10 Sep 2010 19:21:43 +0100 Subject: Initial autofill changes in libwebcore. Initial checkin of WebKit source for enabling AutoFill on Android. This code calls into the chromium library to perform the autofill magic. There's still lots to do, but this and a corresponding change in external/chromium enable the feature (basically) end to end. The feature is disabled by default until we implement it more fully with some proper UI. To turn it on, set the ENABLE_AUTOFILL environment variable to "true" and rebuild. This is only useful for preliminary testing though as for now we use a precanned profile, which won't be relevant unless your name happens to be John Smith. Change-Id: I4a3e0e840617f7cf8f522af33ae1be560768a6c5 --- Android.mk | 41 ++ WebCore/Android.derived.mk | 48 ++ WebKit/Android.mk | 11 + WebKit/android/WebCoreSupport/ChromiumIncludes.h | 16 + .../android/WebCoreSupport/EditorClientAndroid.cpp | 27 + .../android/WebCoreSupport/EditorClientAndroid.h | 12 + .../android/WebCoreSupport/WebRequestContext.cpp | 4 +- WebKit/android/WebCoreSupport/WebUrlLoaderClient.h | 6 +- .../autofill/AutoFillHostAndroid.cpp | 50 ++ .../WebCoreSupport/autofill/AutoFillHostAndroid.h | 54 ++ .../WebCoreSupport/autofill/FormFieldAndroid.cpp | 80 +++ .../WebCoreSupport/autofill/FormFieldAndroid.h | 100 ++++ .../WebCoreSupport/autofill/FormManagerAndroid.cpp | 637 +++++++++++++++++++++ .../WebCoreSupport/autofill/FormManagerAndroid.h | 163 ++++++ .../WebCoreSupport/autofill/MainThreadProxy.cpp | 35 ++ .../WebCoreSupport/autofill/MainThreadProxy.h | 37 ++ .../WebCoreSupport/autofill/WebAutoFill.cpp | 125 ++++ .../android/WebCoreSupport/autofill/WebAutoFill.h | 80 +++ WebKit/android/jni/WebCoreFrameBridge.cpp | 11 + 19 files changed, 1533 insertions(+), 4 deletions(-) create mode 100644 WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.h create mode 100644 WebKit/android/WebCoreSupport/autofill/FormFieldAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/autofill/FormFieldAndroid.h create mode 100644 WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.cpp create mode 100644 WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.h create mode 100644 WebKit/android/WebCoreSupport/autofill/MainThreadProxy.cpp create mode 100644 WebKit/android/WebCoreSupport/autofill/MainThreadProxy.h create mode 100644 WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp create mode 100644 WebKit/android/WebCoreSupport/autofill/WebAutoFill.h diff --git a/Android.mk b/Android.mk index f7af340..a464425 100644 --- a/Android.mk +++ b/Android.mk @@ -101,6 +101,20 @@ ifneq ($(HTTP_STACK),chrome) endif endif +# Read the environment variable to determine if Autofill is enabled. +# The default is off. Chrome HTTP stack must be used when Autofill +# is turned on. + +ifneq ($(ENABLE_AUTOFILL),true) + ENABLE_AUTOFILL=false +endif + +ifneq ($(HTTP_STACK),chrome) + ifeq ($(ENABLE_AUTOFILL),true) + ENABLE_AUTOFILL = false + endif +endif + BASE_PATH := $(call my-dir) include $(CLEAR_VARS) @@ -218,6 +232,16 @@ LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ $(base_intermediates)/WebCore/html \ $(base_intermediates)/WebCore/platform +# The following includes are needed by the AutoFill feature. +LOCAL_C_INCLUDES := $(LOCAL_C_INCLUDES) \ + $(LOCAL_PATH)/WebKit/chromium \ + $(LOCAL_PATH)/WebKit/chromium/public \ + external/chromium/chrome/browser \ + external/chromium/chrome/renderer \ + external/chromium/android \ + external/chromium/chrome \ + external/skia + ifeq ($(JAVASCRIPT_ENGINE),v8) # Include WTF source file. d := JavaScriptCore @@ -364,6 +388,10 @@ LOCAL_STATIC_LIBRARIES += libchromium_net LOCAL_SHARED_LIBRARIES += libcrypto libssl libz endif # HTTP_STACK == chrome +ifeq ($(ENABLE_AUTOFILL),true) +LOCAL_SHARED_LIBRARIES += libexpat +endif + # Redefine LOCAL_SRC_FILES to be all the WebKit source files LOCAL_SRC_FILES := $(WEBKIT_SRC_FILES) @@ -428,6 +456,19 @@ LOCAL_C_INCLUDES := $(WEBKIT_C_INCLUDES) LOCAL_PATH := $(BASE_PATH) LOCAL_SRC_FILES := \ WebKit/android/jni/WebCoreJniOnLoad.cpp + +ifeq ($(ENABLE_AUTOFILL),true) +# AutoFill requires some cpp files from Chromium to link with +# libchromium_net. We cannot compile them into libchromium_net +# because they have cpp file extensions, not .cc. +LOCAL_CFLAGS += -DWEBKIT_IMPLEMENTATION=1 +LOCAL_SRC_FILES += \ + WebKit/android/WebCoreSupport/autofill/MainThreadProxy.cpp \ + WebKit/chromium/src/WebCString.cpp \ + WebKit/chromium/src/WebRegularExpression.cpp \ + WebKit/chromium/src/WebString.cpp +endif + # Do this dependency by hand. The reason we have to do this is because the # headers that this file pulls in are generated during the build of webcore. # We make all of our object files depend on those files so that they are built diff --git a/WebCore/Android.derived.mk b/WebCore/Android.derived.mk index e913a48..e2cf096 100644 --- a/WebCore/Android.derived.mk +++ b/WebCore/Android.derived.mk @@ -176,3 +176,51 @@ $(GEN): xlink_attrs := $(LOCAL_PATH)/svg/xlinkattrs.in $(GEN): $(LOCAL_PATH)/dom/make_names.pl $(xlink_attrs) $(transform-generated-source) LOCAL_GENERATED_SOURCES += $(GEN) + +ifeq ($(ENABLE_AUTOFILL),true) +# This is really ugly, but necessary. The following rules are taken from +# external/chromium/Android.mk. +# Chromium uses several third party libraries and headers that are already +# present on Android, but in different include paths. Generate a set of +# forwarding headers in the location that Chromium expects. We need to do +# this in both the Chromium and WebCore projects because of the +# WebKit <-> Chromium bindings which include headers from the Chromuim project. + +THIRD_PARTY = $(intermediates)/third_party +CHROMIUM_SRC_DIR := $(LOCAL_PATH)/../../chromium +SCRIPT := $(CHROMIUM_SRC_DIR)/android/generateAndroidForwardingHeader.pl + +GEN := $(THIRD_PARTY)/expat/files/lib/expat.h +$(GEN): $(SCRIPT) +$(GEN): + perl $(SCRIPT) $@ "lib/expat.h" +LOCAL_GENERATED_SOURCES += $(GEN) + +GEN := $(THIRD_PARTY)/skia/include/core/SkBitmap.h +$(GEN): $(SCRIPT) +$(GEN): + perl $(SCRIPT) $@ "include/core/SkBitmap.h" +LOCAL_GENERATED_SOURCES += $(GEN) + +GEN := $(THIRD_PARTY)/WebKit/WebKit/chromium/public/WebFormControlElement.h +$(GEN): $(SCRIPT) +$(GEN): + perl $(SCRIPT) $@ "public/WebFormControlElement.h" +LOCAL_GENERATED_SOURCES += $(GEN) + +GEN := $(THIRD_PARTY)/WebKit/WebKit/chromium/public/WebRegularExpression.h +$(GEN): $(SCRIPT) +$(GEN): + perl $(SCRIPT) $@ "public/WebRegularExpression.h" +LOCAL_GENERATED_SOURCES += $(GEN) + +GEN := $(THIRD_PARTY)/WebKit/WebKit/chromium/public/WebString.h +$(GEN): $(SCRIPT) +$(GEN): + perl $(SCRIPT) $@ "public/WebString.h" +LOCAL_GENERATED_SOURCES += $(GEN) + +endif + +LOCAL_SRC_FILES += $(LOCAL_GENERATED_SOURCES) + diff --git a/WebKit/Android.mk b/WebKit/Android.mk index 01ede0f..a361974 100644 --- a/WebKit/Android.mk +++ b/WebKit/Android.mk @@ -106,3 +106,14 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ android/wds/Command.cpp \ android/wds/Connection.cpp \ android/wds/DebugServer.cpp + +# Needed for autofill. +ifeq ($(ENABLE_AUTOFILL),true) +LOCAL_CFLAGS += -DENABLE_WEB_AUTOFILL + +LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \ + android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp \ + android/WebCoreSupport/autofill/FormFieldAndroid.cpp \ + android/WebCoreSupport/autofill/FormManagerAndroid.cpp \ + android/WebCoreSupport/autofill/WebAutoFill.cpp +endif # ENABLE_AUTOFILL == true diff --git a/WebKit/android/WebCoreSupport/ChromiumIncludes.h b/WebKit/android/WebCoreSupport/ChromiumIncludes.h index a7abef1..1a69ff1 100644 --- a/WebKit/android/WebCoreSupport/ChromiumIncludes.h +++ b/WebKit/android/WebCoreSupport/ChromiumIncludes.h @@ -26,6 +26,8 @@ #ifndef ChromiumIncludes_h #define ChromiumIncludes_h +#include "config.h" + // Include all external/chromium files in this file so the problems with the LOG // and LOG_ASSERT defines can be handled in one place. @@ -64,6 +66,20 @@ #include #include +#if ENABLE(WEB_AUTOFILL) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + #undef LOG #if defined(LOG_WAS_DEFINED) && defined(LOG_PRI) #define LOG(priority, tag, ...) LOG_PRI(ANDROID_##priority, tag, __VA_ARGS__) diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp index 45498c0..f5f8211 100644 --- a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp @@ -32,6 +32,7 @@ #include "EventNames.h" #include "FocusController.h" #include "Frame.h" +#include "HTMLNames.h" #include "KeyboardEvent.h" #include "NotImplemented.h" #include "PlatformKeyboardEvent.h" @@ -39,6 +40,8 @@ #include "WebViewCore.h" #include "WindowsKeyboardCodes.h" +using namespace WebCore::HTMLNames; + namespace android { void EditorClientAndroid::pageDestroyed() { @@ -235,6 +238,19 @@ void EditorClientAndroid::respondToChangedSelection() { Frame* frame = m_page->focusController()->focusedOrMainFrame(); if (!frame || !frame->view()) return; + +#if ENABLE(WEB_AUTOFILL) + WebCore::Node* focusedNode = frame->document()->focusedNode(); + if (focusedNode && focusedNode->hasTagName(inputTag)) { + WebCore::HTMLInputElement* element = static_cast(focusedNode); + // TODO: If it's a text field, inform AutoFill that it should get AutoFill suggestions for + // the form it belongs to. AutoFill can also work with select-one elements (i.e. + // Note the lack of whitespace between

and elements. + if (inferred_label.empty()) { + if (previous->isElementNode()) { + if (previous->hasTagName(pTag)) { + inferred_label = FindChildText((HTMLElement*)previous); + } + } + } + + // If we didn't find paragraph, check for previous paragraph to this. + // Eg.

Some Text

+ // Note the whitespace between

and elements. + if (inferred_label.empty()) { + previous = previous->previousSibling(); + if (previous) { + if (previous->hasTagName(pTag)) { + inferred_label = FindChildText((HTMLElement*)previous); + } + } + } + } + + // If we didn't find paragraph, check for table cell case. + // Eg. Some Text + // Eg. Some Text + if (inferred_label.empty()) { + Node* parent = element.parentNode(); + while (parent && + !parent->hasTagName(tdTag)) + parent = parent->parentNode(); + + if (parent) { + if (parent->hasTagName(tdTag)) { + previous = parent->previousSibling(); + + // Skip by any intervening text nodes. + while (previous && previous->isTextNode()) + previous = previous->previousSibling(); + + if (previous) { + if (previous->hasTagName(tdTag)) { + inferred_label = FindChildText((HTMLElement*)previous); + } + } + } + } + } + return inferred_label; +} + +} diff --git a/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.h b/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.h new file mode 100644 index 0000000..395e651 --- /dev/null +++ b/WebKit/android/WebCoreSupport/autofill/FormManagerAndroid.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2010 The Chromium Authors. All rights reserved. + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef FormManagerAndroid_h +#define FormManagerAndroid_h + +#include "ChromiumIncludes.h" + +#include +#include + +// TODO: This file is taken from chromium/chrome/renderer/form_manager.h and +// customised to use WebCore types rather than WebKit API types. It would be +// nice and would ease future merge pain if the two could be combined. + +namespace webkit_glue { +struct FormData; +class FormField; +} // namespace webkit_glue + +namespace WebCore { + class HTMLFormControlElement; + class HTMLFormElement; + class Document; +} + +namespace android { + +// Manages the forms in a Document. +class FormManager { + public: + // A bit field mask for form requirements. + enum RequirementsMask { + REQUIRE_NONE = 0x0, // No requirements. + REQUIRE_AUTOCOMPLETE = 0x1, // Require that autocomplete != off. + REQUIRE_ELEMENTS_ENABLED = 0x2 // Require that disabled attribute is off. + }; + + FormManager(); + virtual ~FormManager(); + + // Fills out a FormField object from a given WebFormControlElement. + // If |get_value| is true, |field| will have the value set from |element|. + static void HTMLFormControlElementToFormField( + const WebCore::HTMLFormControlElement& element, + bool get_value, + webkit_glue::FormField* field); + + // Returns the corresponding label for |element|. WARNING: This method can + // potentially be very slow. Do not use during any code paths where the page + // is loading. + static string16 LabelForElement(const WebCore::HTMLFormControlElement& element); + + // Fills out a FormData object from a given WebFormElement. If |get_values| + // is true, the fields in |form| will have the values filled out. Returns + // true if |form| is filled out; it's possible that |element| won't meet the + // requirements in |requirements|. This also returns false if there are no + // fields in |form|. + // TODO: Remove the user of this in RenderView and move this to + // private. + static bool HTMLFormElementToFormData(WebCore::HTMLFormElement& element, + RequirementsMask requirements, + bool get_values, + webkit_glue::FormData* form); + + // Scans the DOM in |document| extracting and storing forms. + void ExtractForms(WebCore::Document* document); + + // Returns a vector of forms that match |requirements|. + void GetForms(RequirementsMask requirements, + std::vector* forms); + + // Returns a vector of forms in |document| that match |requirements|. + void GetFormsInDocument(const WebCore::Document* document, + RequirementsMask requirements, + std::vector* forms); + + // Returns the cached FormData for |element|. Returns true if the form was + // found in the cache. + bool FindForm(const WebCore::HTMLFormElement& element, + RequirementsMask requirements, + webkit_glue::FormData* form); + + // Finds the form that contains |element| and returns it in |form|. Returns + // false if the form is not found. + bool FindFormWithFormControlElement( + const WebCore::HTMLFormControlElement& element, + RequirementsMask requirements, + webkit_glue::FormData* form); + + // Fills the form represented by |form|. |form| should have the name set to + // the name of the form to fill out, and the number of elements and values + // must match the number of stored elements in the form. + // TODO: Is matching on name alone good enough? It's possible to + // store multiple forms with the same names from different frames. + bool FillForm(const webkit_glue::FormData& form); + + // Fills all of the forms in the cache with form data from |forms|. + void FillForms(const std::vector& forms); + + // Resets the stored set of forms. + void Reset(); + + // Resets the forms for the specified |document|. + void ResetFrame(const WebCore::Document* document); + + private: + // Stores the HTMLFormElement and the form control elements for a form. + struct FormElement { + WebCore::HTMLFormElement* form_element; + std::vector control_elements; + }; + + // A map of vectors of FormElements keyed by the Document containing each + // form. + typedef std::map > + DocumentFormElementMap; + + // Converts a FormElement to FormData storage. Returns false if the form does + // not meet all the requirements in the requirements mask. + static bool FormElementToFormData(const WebCore::Document* document, + const FormElement* form_element, + RequirementsMask requirements, + webkit_glue::FormData* form); + + // Infers corresponding label for |element| from surrounding context in the + // DOM. Contents of preceeding

tag or preceeding text element found in + // the form. + static string16 InferLabelForElement( + const WebCore::HTMLFormControlElement& element); + + // The map of form elements. + DocumentFormElementMap form_elements_map_; + + DISALLOW_COPY_AND_ASSIGN(FormManager); +}; + +} // namespace android + +#endif // FormManagerAndroid_h diff --git a/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.cpp b/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.cpp new file mode 100644 index 0000000..598b9c4 --- /dev/null +++ b/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#include "config.h" +#include "MainThreadProxy.h" + +#include + +void MainThreadProxy::CallOnMainThread(CallOnMainThreadFunction f, void* c) +{ + callOnMainThread(f, c); +} diff --git a/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.h b/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.h new file mode 100644 index 0000000..d9310bb --- /dev/null +++ b/WebKit/android/WebCoreSupport/autofill/MainThreadProxy.h @@ -0,0 +1,37 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef MAIN_THREAD_PROXY_H +#define MAIN_THREAD_PROXY_H + +typedef void CallOnMainThreadFunction(void*); + +class MainThreadProxy +{ +public: + static void CallOnMainThread(CallOnMainThreadFunction, void*); +}; + +#endif diff --git a/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp new file mode 100644 index 0000000..08d5e58 --- /dev/null +++ b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp @@ -0,0 +1,125 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebAutoFill.h" + +#if ENABLE(WEB_AUTOFILL) + +#include "AutoFillHostAndroid.h" +#include "Document.h" +#include "Frame.h" +#include "FormData.h" +#include "FormManagerAndroid.h" +#include "FrameLoader.h" +#include "HTMLFormControlElement.h" +#include "MainThreadProxy.h" +#include "Node.h" +#include "WebFrame.h" +#include "WebRequestContext.h" +#include "WebUrlLoaderClient.h" +#include "WebViewCore.h" + +namespace android +{ + +WebAutoFill::WebAutoFill() +{ + mFormManager = new FormManager(); + mQueryId = 1; + + AndroidURLRequestContextGetter::Get()->SetURLRequestContext(WebRequestContext::GetAndroidContext()); + AndroidURLRequestContextGetter::Get()->SetIOThread(WebUrlLoaderClient::ioThread()); + TabContents* tabContents = new TabContents(); + mAutoFillManager = new AutoFillManager(tabContents); + + // FIXME: For testing use a precanned profile. This should come from Java land! + mAutoFillProfile = new AutoFillProfile(); + mAutoFillProfile->SetInfo(AutoFillType(NAME_FULL), string16(ASCIIToUTF16("John Smith"))); + mAutoFillProfile->SetInfo(AutoFillType(EMAIL_ADDRESS), string16(ASCIIToUTF16("jsmith@gmail.com"))); + mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_ZIP), string16(ASCIIToUTF16("AB12 3DE"))); + mAutoFillProfile->SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER), string16(ASCIIToUTF16("0123456789"))); + + std::vector profiles; + profiles.push_back(*mAutoFillProfile); + tabContents->profile()->GetPersonalDataManager()->SetProfiles(&profiles); + mAutoFillHost = new AutoFillHostAndroid(this); + tabContents->SetAutoFillHost(mAutoFillHost.get()); +} + +WebAutoFill::~WebAutoFill() +{ + mQueryMap.clear(); +} + +void WebAutoFill::searchDocument(WebCore::Document* document) +{ + // TODO: This method is called when the main frame finishes loading and + // scans the document for forms and tries to work out the type of the + // fields in those forms. It's currently synchronous and might be slow + // if the page has many or complex forms. Might want to make this an + // async method. + if (!mFormManager) + return; + + mQueryMap.clear(); + mQueryId = 1; + mAutoFillManager->Reset(); + mFormManager->Reset(); + mFormManager->ExtractForms(document); + mForms.clear(); + mFormManager->GetForms(FormManager::REQUIRE_AUTOCOMPLETE, &mForms); + mAutoFillManager->FormsSeen(mForms); +} + +void WebAutoFill::formFieldFocused(WebCore::HTMLFormControlElement* formFieldElement) +{ + // Get the FormField from the Node. + webkit_glue::FormField formField; + FormManager::HTMLFormControlElementToFormField(*formFieldElement, false, &formField); + formField.set_label(FormManager::LabelForElement(*formFieldElement)); + + webkit_glue::FormData* form = new webkit_glue::FormData; + mFormManager->FindFormWithFormControlElement(*formFieldElement, FormManager::REQUIRE_AUTOCOMPLETE, form); + mQueryMap[mQueryId] = form; + + mAutoFillManager->GetAutoFillSuggestions(mQueryId, false, formField); + mQueryId++; +} + +void WebAutoFill::fillFormFields(int queryId, const string16& value, const string16& label, int uniqueId) +{ + webkit_glue::FormData* form = mQueryMap[queryId]; + mAutoFillManager->FillAutoFillFormData(queryId, *form, value, label, uniqueId); +} + +void WebAutoFill::fillFormInPage(int queryId, const webkit_glue::FormData& form) +{ + mFormManager->FillForm(form); +} + +} + +#endif diff --git a/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h new file mode 100644 index 0000000..335f9b2 --- /dev/null +++ b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h @@ -0,0 +1,80 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef WebAutoFill_h +#define WebAutoFill_h + +#if ENABLE(WEB_AUTOFILL) + +#include "ChromiumIncludes.h" + +#include +#include +#include +#include + +class AutoFillManager; +class AutoFillProfile; +class AutoFillHost; + +namespace WebCore { +class Document; +class HTMLFormControlElement; +} + +namespace android +{ +class FormManager; +class WebViewCore; + +class WebAutoFill : public Noncopyable +{ +public: + WebAutoFill(); + virtual ~WebAutoFill(); + + void searchDocument(WebCore::Document*); + void formFieldFocused(WebCore::HTMLFormControlElement*); + void fillFormFields(int queryId, const string16& value, const string16& label, int uniqueId); + void fillFormInPage(int queryId, const webkit_glue::FormData& form); + +private: + OwnPtr mFormManager; + OwnPtr mAutoFillManager; + OwnPtr mAutoFillProfile; + OwnPtr mAutoFillHost; + + typedef std::vector > FormList; + FormList mForms; + + typedef std::map AutoFillQueryMap; + AutoFillQueryMap mQueryMap; + int mQueryId; +}; + +} + +#endif // ENABLE(WEB_AUTOFILL) +#endif // WebAutoFill_h diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index a717301..c1cb907 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -120,6 +120,10 @@ #include "WebArchiveAndroid.h" #endif +#if ENABLE(WEB_AUTOFILL) +#include "autofill/WebAutoFill.h" +#endif + using namespace JSC::Bindings; static String* gUploadFileLabel; @@ -639,6 +643,13 @@ WebFrame::didFinishLoad(WebCore::Frame* frame) (int)loadType, isMainFrame); checkException(env); env->DeleteLocalRef(urlStr); +#if ENABLE(WEB_AUTOFILL) + // TODO: Need to consider child frames. + if (isMainFrame) { + EditorClientAndroid* editorClient = static_cast(mPage->editorClient()); + editorClient->getAutoFill()->searchDocument(frame->document()); + } +#endif } void -- cgit v1.1