From a5b05f64bda3dea3ba23e77e9eb2ef59812cdc86 Mon Sep 17 00:00:00 2001 From: Kristian Monsen Date: Mon, 27 Jun 2011 10:47:13 +0100 Subject: Merge Chromium at r11.0.696.0: Just AutoFill => Autofill renaming Change-Id: Iefb91f0b784c26b503125017ae3582a28e7d530d --- Source/WebKit/Android.mk | 2 +- .../android/WebCoreSupport/EditorClientAndroid.cpp | 4 +- .../android/WebCoreSupport/EditorClientAndroid.h | 6 +- .../WebCoreSupport/FrameLoaderClientAndroid.cpp | 4 +- .../autofill/AutoFillHostAndroid.cpp | 14 +- .../WebCoreSupport/autofill/AutoFillHostAndroid.h | 8 +- .../WebCoreSupport/autofill/WebAutoFill.cpp | 296 --------------------- .../android/WebCoreSupport/autofill/WebAutoFill.h | 128 --------- .../WebCoreSupport/autofill/WebAutofill.cpp | 296 +++++++++++++++++++++ .../android/WebCoreSupport/autofill/WebAutofill.h | 128 +++++++++ Source/WebKit/android/jni/WebCoreFrameBridge.cpp | 4 +- Source/WebKit/android/jni/WebSettings.cpp | 12 +- Source/WebKit/android/jni/WebViewCore.cpp | 6 +- 13 files changed, 454 insertions(+), 454 deletions(-) delete mode 100644 Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp delete mode 100644 Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h create mode 100644 Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.cpp create mode 100644 Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.h diff --git a/Source/WebKit/Android.mk b/Source/WebKit/Android.mk index 7a5fabf..3a47909 100644 --- a/Source/WebKit/Android.mk +++ b/Source/WebKit/Android.mk @@ -133,5 +133,5 @@ LOCAL_SRC_FILES += \ android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp \ android/WebCoreSupport/autofill/FormFieldAndroid.cpp \ android/WebCoreSupport/autofill/FormManagerAndroid.cpp \ - android/WebCoreSupport/autofill/WebAutoFill.cpp + android/WebCoreSupport/autofill/WebAutofill.cpp endif # ENABLE_AUTOFILL == true diff --git a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp index 2667b71..785f0a8 100644 --- a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp @@ -270,10 +270,10 @@ void EditorClientAndroid::willSetInputMethodState() void EditorClientAndroid::requestCheckingOfString(SpellChecker*, int, TextCheckingTypeMask, const String&) {} #if ENABLE(WEB_AUTOFILL) -WebAutoFill* EditorClientAndroid::getAutoFill() +WebAutofill* EditorClientAndroid::getAutofill() { if (!m_autoFill) - m_autoFill.set(new WebAutoFill()); + m_autoFill.set(new WebAutofill()); return m_autoFill.get(); } diff --git a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h index 9bf6e1f..385d75c 100644 --- a/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h +++ b/Source/WebKit/android/WebCoreSupport/EditorClientAndroid.h @@ -32,7 +32,7 @@ #include "EditorClient.h" #include "Page.h" #include "TextCheckerClient.h" -#include "autofill/WebAutoFill.h" +#include "autofill/WebAutofill.h" #include @@ -124,14 +124,14 @@ public: void setShouldChangeSelectedRange(bool shouldChangeSelectedRange) { m_shouldChangeSelectedRange = shouldChangeSelectedRange; } void setUiGeneratedSelectionChange(bool uiGenerated) { m_uiGeneratedSelectionChange = uiGenerated; } #if ENABLE(WEB_AUTOFILL) - WebAutoFill* getAutoFill(); + WebAutofill* getAutofill(); #endif private: Page* m_page; bool m_shouldChangeSelectedRange; bool m_uiGeneratedSelectionChange; #if ENABLE(WEB_AUTOFILL) - OwnPtr m_autoFill; + OwnPtr m_autoFill; #endif }; diff --git a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp index 99f34d5..88ab4a3 100644 --- a/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -76,7 +76,7 @@ #include "WebFrameView.h" #include "WebViewClientError.h" #include "WebViewCore.h" -#include "autofill/WebAutoFill.h" +#include "autofill/WebAutofill.h" #include "android_graphics.h" #include @@ -301,7 +301,7 @@ void FrameLoaderClientAndroid::dispatchDidCommitLoad() { #if ENABLE(WEB_AUTOFILL) if (m_frame == m_frame->page()->mainFrame()) { EditorClientAndroid* editorC = static_cast(m_frame->page()->editorClient()); - WebAutoFill* autoFill = editorC->getAutoFill(); + WebAutofill* autoFill = editorC->getAutofill(); autoFill->reset(); } #endif diff --git a/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp b/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp index 5bc4c92..d2dc201 100644 --- a/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp +++ b/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.cpp @@ -26,26 +26,26 @@ #include "config.h" #include "AutoFillHostAndroid.h" -#include "autofill/WebAutoFill.h" +#include "autofill/WebAutofill.h" namespace android { -AutoFillHostAndroid::AutoFillHostAndroid(WebAutoFill* autoFill) - : mAutoFill(autoFill) +AutoFillHostAndroid::AutoFillHostAndroid(WebAutofill* autofill) + : mAutofill(autofill) { } void AutoFillHostAndroid::AutoFillSuggestionsReturned(const std::vector& names, const std::vector& labels, const std::vector& icons, const std::vector& uniqueIds) { // TODO: what do we do with icons? - if (mAutoFill) - mAutoFill->querySuccessful(names[0], labels[0], uniqueIds[0]); + if (mAutofill) + mAutofill->querySuccessful(names[0], labels[0], uniqueIds[0]); } void AutoFillHostAndroid::AutoFillFormDataFilled(int queryId, const webkit_glue::FormData& form) { - if (mAutoFill) - mAutoFill->fillFormInPage(queryId, form); + if (mAutofill) + mAutofill->fillFormInPage(queryId, form); } } diff --git a/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.h b/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.h index 9677b46..31767d5 100644 --- a/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.h +++ b/Source/WebKit/android/WebCoreSupport/autofill/AutoFillHostAndroid.h @@ -35,19 +35,19 @@ class FormData; } namespace android { -class WebAutoFill; +class WebAutofill; -// This class receives the callbacks from the AutoFillManager in the Chromium code. +// This class receives the callbacks from the AutofillManager in the Chromium code. class AutoFillHostAndroid : public AutoFillHost { public: - AutoFillHostAndroid(WebAutoFill* autoFill); + AutoFillHostAndroid(WebAutofill* autofill); virtual ~AutoFillHostAndroid() { } virtual void AutoFillSuggestionsReturned(const std::vector& names, const std::vector& labels, const std::vector& icons, const std::vector& uniqueIds); virtual void AutoFillFormDataFilled(int queryId, const webkit_glue::FormData&); private: - WebAutoFill* mAutoFill; + WebAutofill* mAutofill; }; } diff --git a/Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp b/Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp deleted file mode 100644 index 1fdb671..0000000 --- a/Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp +++ /dev/null @@ -1,296 +0,0 @@ -/* - * 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 "Frame.h" -#include "FormData.h" -#include "FormManagerAndroid.h" -#include "FrameLoader.h" -#include "HTMLFormControlElement.h" -#include "MainThreadProxy.h" -#include "Node.h" -#include "Page.h" -#include "Settings.h" -#include "WebFrame.h" -#include "WebRequestContext.h" -#include "WebUrlLoaderClient.h" -#include "WebViewCore.h" - -#define NO_PROFILE_SET 0 -#define FORM_NOT_AUTOFILLABLE -1 - -namespace android -{ -WebAutoFill::WebAutoFill() - : mQueryId(1) - , mWebViewCore(0) - , mLastSearchDomVersion(0) - , mParsingForms(false) -{ - mTabContents = new TabContents(); - setEmptyProfile(); -} - -void WebAutoFill::init() -{ - if (mAutoFillManager) - return; - - mFormManager = new FormManager(); - // We use the WebView's WebRequestContext, which may be a private browsing context. - ASSERT(mWebViewCore); - mAutoFillManager = new AutoFillManager(mTabContents.get()); - mAutoFillHost = new AutoFillHostAndroid(this); - mTabContents->SetProfileRequestContext(new AndroidURLRequestContextGetter(mWebViewCore->webRequestContext(), WebUrlLoaderClient::ioThread())); - mTabContents->SetAutoFillHost(mAutoFillHost.get()); -} - -WebAutoFill::~WebAutoFill() -{ - cleanUpQueryMap(); - mUniqueIdMap.clear(); -} - -void WebAutoFill::cleanUpQueryMap() -{ - for (AutoFillQueryFormDataMap::iterator it = mQueryMap.begin(); it != mQueryMap.end(); it++) - delete it->second; - mQueryMap.clear(); -} - -void WebAutoFill::searchDocument(WebCore::Frame* frame) -{ - if (!enabled()) - return; - - MutexLocker lock(mFormsSeenMutex); - - init(); - - cleanUpQueryMap(); - mUniqueIdMap.clear(); - mForms.clear(); - mQueryId = 1; - - ASSERT(mFormManager); - ASSERT(mAutoFillManager); - - mAutoFillManager->Reset(); - mFormManager->Reset(); - - mFormManager->ExtractForms(frame); - mFormManager->GetFormsInFrame(frame, FormManager::REQUIRE_AUTOCOMPLETE, &mForms); - - // Needs to be done on a Chrome thread as it will make a URL request to the AutoFill server. - // TODO: Use our own Autofill thread instead of the IO thread. - // TODO: For now, block here. Would like to make this properly async. - base::Thread* thread = WebUrlLoaderClient::ioThread(); - mParsingForms = true; - thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebAutoFill::formsSeenImpl)); - while (mParsingForms) - mFormsSeenCondition.wait(mFormsSeenMutex); -} - -// Called on the Chromium IO thread. -void WebAutoFill::formsSeenImpl() -{ - MutexLocker lock(mFormsSeenMutex); - mAutoFillManager->OnFormsSeenWrapper(mForms); - mParsingForms = false; - mFormsSeenCondition.signal(); -} - -void WebAutoFill::formFieldFocused(WebCore::HTMLFormControlElement* formFieldElement) -{ - ASSERT(formFieldElement); - - Document* doc = formFieldElement->document(); - Frame* frame = doc->frame(); - - // FIXME: AutoFill only works in main frame for now. Should consider - // child frames. - if (frame != frame->page()->mainFrame()) - return; - - unsigned domVersion = doc->domTreeVersion(); - ASSERT(domVersion > 0); - - if (mLastSearchDomVersion != domVersion) { - // Need to extract forms as DOM version has changed since the last time - // we searched. - searchDocument(formFieldElement->document()->frame()); - mLastSearchDomVersion = domVersion; - } - - if (!enabled()) { - // In case that we've just been disabled and the last time we got autofill - // suggestions and told Java about them, clear that bit Java side now - // we're disabled. - mWebViewCore->setWebTextViewAutoFillable(FORM_NOT_AUTOFILLABLE, string16()); - return; - } - - // Get the FormField from the Node. - webkit_glue::FormField* formField = new webkit_glue::FormField; - FormManager::HTMLFormControlElementToFormField(formFieldElement, FormManager::EXTRACT_NONE, formField); - formField->set_label(FormManager::LabelForElement(*formFieldElement)); - - webkit_glue::FormData* form = new webkit_glue::FormData; - mFormManager->FindFormWithFormControlElement(formFieldElement, FormManager::REQUIRE_AUTOCOMPLETE, form); - mQueryMap[mQueryId] = new FormDataAndField(form, formField); - - bool suggestions = mAutoFillManager->OnQueryFormFieldAutoFillWrapper(*form, *formField); - - mQueryId++; - if (!suggestions) { - ASSERT(mWebViewCore); - // Tell Java no autofill suggestions for this form. - mWebViewCore->setWebTextViewAutoFillable(FORM_NOT_AUTOFILLABLE, string16()); - return; - } -} - -void WebAutoFill::querySuccessful(const string16& value, const string16& label, int uniqueId) -{ - if (!enabled()) - return; - - // Store the unique ID for the query and inform java that autofill suggestions for this form are available. - // Pass java the queryId so that it can pass it back if the user decides to use autofill. - mUniqueIdMap[mQueryId] = uniqueId; - - ASSERT(mWebViewCore); - mWebViewCore->setWebTextViewAutoFillable(mQueryId, mAutoFillProfile->Label()); -} - -void WebAutoFill::fillFormFields(int queryId) -{ - if (!enabled()) - return; - - webkit_glue::FormData* form = mQueryMap[queryId]->form(); - webkit_glue::FormField* field = mQueryMap[queryId]->field(); - ASSERT(form); - ASSERT(field); - - AutoFillQueryToUniqueIdMap::iterator iter = mUniqueIdMap.find(queryId); - if (iter == mUniqueIdMap.end()) { - // The user has most likely tried to AutoFill the form again without - // refocussing the form field. The UI should protect against this - // but stop here to be certain. - return; - } - mAutoFillManager->OnFillAutoFillFormDataWrapper(queryId, *form, *field, iter->second); - mUniqueIdMap.erase(iter); -} - -void WebAutoFill::fillFormInPage(int queryId, const webkit_glue::FormData& form) -{ - if (!enabled()) - return; - - // FIXME: Pass a pointer to the Node that triggered the AutoFill flow here instead of 0. - // The consquence of passing 0 is that we should always fail the test in FormManader::ForEachMathcingFormField():169 - // that says "only overwrite an elements current value if the user triggered autofill through that element" - // for elements that have a value already. But by a quirk of Android text views we are OK. We should still - // fix this though. - mFormManager->FillForm(form, 0); -} - -bool WebAutoFill::enabled() const -{ - Page* page = mWebViewCore->mainFrame()->page(); - return page ? page->settings()->autoFillEnabled() : false; -} - -void WebAutoFill::setProfile(const string16& fullName, const string16& emailAddress, const string16& companyName, - const string16& addressLine1, const string16& addressLine2, const string16& city, - const string16& state, const string16& zipCode, const string16& country, const string16& phoneNumber) -{ - if (!mAutoFillProfile) - mAutoFillProfile.set(new AutoFillProfile()); - - // Update the profile. - // Constants for AutoFill field types are found in external/chromium/chrome/browser/autofill/field_types.h. - mAutoFillProfile->SetInfo(AutoFillType(NAME_FULL), fullName); - mAutoFillProfile->SetInfo(AutoFillType(EMAIL_ADDRESS), emailAddress); - mAutoFillProfile->SetInfo(AutoFillType(COMPANY_NAME), companyName); - mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_LINE1), addressLine1); - mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_LINE2), addressLine2); - mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_CITY), city); - mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_STATE), state); - mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_ZIP), zipCode); - mAutoFillProfile->SetInfo(AutoFillType(ADDRESS_HOME_COUNTRY), country); - mAutoFillProfile->SetInfo(AutoFillType(PHONE_HOME_WHOLE_NUMBER), phoneNumber); - - std::vector profiles; - profiles.push_back(*mAutoFillProfile); - updateProfileLabel(); - mTabContents->profile()->GetPersonalDataManager()->SetProfiles(&profiles); -} - -bool WebAutoFill::updateProfileLabel() -{ - std::vector profiles; - profiles.push_back(mAutoFillProfile.get()); - return AutoFillProfile::AdjustInferredLabels(&profiles); -} - -void WebAutoFill::clearProfiles() -{ - if (!mAutoFillProfile) - return; - // For now Chromium only ever knows about one profile, so we can just - // remove it. If we support multiple profiles in the future - // we need to remove them all here. - std::string profileGuid = mAutoFillProfile->guid(); - mTabContents->profile()->GetPersonalDataManager()->RemoveProfile(profileGuid); - setEmptyProfile(); -} - -void WebAutoFill::setEmptyProfile() -{ - // Set an empty profile. This will ensure that when autofill is enabled, - // we will still search the document for autofillable forms and inform - // java of their presence so we can invite the user to set up - // their own profile. - - // Chromium code will strip the values sent into the profile so we need them to be - // at least one non-whitespace character long. We need to set all fields of the - // profile to a non-empty string so that any field type can trigger the autofill - // suggestion. AutoFill will not detect form fields if the profile value for that - // field is an empty string. - static const string16 empty = string16(ASCIIToUTF16("a")); - setProfile(empty, empty, empty, empty, empty, empty, empty, empty, empty, empty); -} - -} - -#endif diff --git a/Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h b/Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h deleted file mode 100644 index 4dbd8ba..0000000 --- a/Source/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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 -#include - -class AutoFillManager; -class AutoFillProfile; -class AutoFillHost; - -namespace WebCore { -class Frame; -class HTMLFormControlElement; -} - -namespace android -{ -class FormManager; -class WebViewCore; - -class FormDataAndField { -public: - FormDataAndField(webkit_glue::FormData* form, webkit_glue::FormField* field) - : mForm(form) - , mField(field) - { - } - - webkit_glue::FormData* form() { return mForm.get(); } - webkit_glue::FormField* field() { return mField.get(); } - -private: - OwnPtr mForm; - OwnPtr mField; -}; - -class WebAutoFill -{ - WTF_MAKE_NONCOPYABLE(WebAutoFill); -public: - WebAutoFill(); - virtual ~WebAutoFill(); - void formFieldFocused(WebCore::HTMLFormControlElement*); - void fillFormFields(int queryId); - void querySuccessful(const string16& value, const string16& label, int uniqueId); - void fillFormInPage(int queryId, const webkit_glue::FormData& form); - void setWebViewCore(WebViewCore* webViewCore) { mWebViewCore = webViewCore; } - bool enabled() const; - - void setProfile(const string16& fullName, const string16& emailAddress, const string16& companyName, - const string16& addressLine1, const string16& addressLine2, const string16& city, - const string16& state, const string16& zipCode, const string16& country, const string16& phoneNumber); - void clearProfiles(); - - bool updateProfileLabel(); - - void reset() { mLastSearchDomVersion = 0; } - -private: - void init(); - void searchDocument(WebCore::Frame*); - void setEmptyProfile(); - void formsSeenImpl(); - void cleanUpQueryMap(); - - OwnPtr mFormManager; - OwnPtr mAutoFillManager; - OwnPtr mAutoFillHost; - OwnPtr mTabContents; - OwnPtr mAutoFillProfile; - - typedef std::vector > FormList; - FormList mForms; - - typedef std::map AutoFillQueryFormDataMap; - AutoFillQueryFormDataMap mQueryMap; - - typedef std::map AutoFillQueryToUniqueIdMap; - AutoFillQueryToUniqueIdMap mUniqueIdMap; - int mQueryId; - - WebViewCore* mWebViewCore; - - unsigned mLastSearchDomVersion; - - WTF::Mutex mFormsSeenMutex; // Guards mFormsSeenCondition and mParsingForms. - WTF::ThreadCondition mFormsSeenCondition; - bool volatile mParsingForms; -}; - -} - -DISABLE_RUNNABLE_METHOD_REFCOUNT(android::WebAutoFill); - -#endif // ENABLE(WEB_AUTOFILL) -#endif // WebAutoFill_h diff --git a/Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.cpp b/Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.cpp new file mode 100644 index 0000000..ff4f593 --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.cpp @@ -0,0 +1,296 @@ +/* + * 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 "Frame.h" +#include "FormData.h" +#include "FormManagerAndroid.h" +#include "FrameLoader.h" +#include "HTMLFormControlElement.h" +#include "MainThreadProxy.h" +#include "Node.h" +#include "Page.h" +#include "Settings.h" +#include "WebFrame.h" +#include "WebRequestContext.h" +#include "WebUrlLoaderClient.h" +#include "WebViewCore.h" + +#define NO_PROFILE_SET 0 +#define FORM_NOT_AUTOFILLABLE -1 + +namespace android +{ +WebAutofill::WebAutofill() + : mQueryId(1) + , mWebViewCore(0) + , mLastSearchDomVersion(0) + , mParsingForms(false) +{ + mTabContents = new TabContents(); + setEmptyProfile(); +} + +void WebAutofill::init() +{ + if (mAutofillManager) + return; + + mFormManager = new FormManager(); + // We use the WebView's WebRequestContext, which may be a private browsing context. + ASSERT(mWebViewCore); + mAutofillManager = new AutofillManager(mTabContents.get()); + mAutofillHost = new AutoFillHostAndroid(this); + mTabContents->SetProfileRequestContext(new AndroidURLRequestContextGetter(mWebViewCore->webRequestContext(), WebUrlLoaderClient::ioThread())); + mTabContents->SetAutoFillHost(mAutofillHost.get()); +} + +WebAutofill::~WebAutofill() +{ + cleanUpQueryMap(); + mUniqueIdMap.clear(); +} + +void WebAutofill::cleanUpQueryMap() +{ + for (AutofillQueryFormDataMap::iterator it = mQueryMap.begin(); it != mQueryMap.end(); it++) + delete it->second; + mQueryMap.clear(); +} + +void WebAutofill::searchDocument(WebCore::Frame* frame) +{ + if (!enabled()) + return; + + MutexLocker lock(mFormsSeenMutex); + + init(); + + cleanUpQueryMap(); + mUniqueIdMap.clear(); + mForms.clear(); + mQueryId = 1; + + ASSERT(mFormManager); + ASSERT(mAutofillManager); + + mAutofillManager->Reset(); + mFormManager->Reset(); + + mFormManager->ExtractForms(frame); + mFormManager->GetFormsInFrame(frame, FormManager::REQUIRE_AUTOCOMPLETE, &mForms); + + // Needs to be done on a Chrome thread as it will make a URL request to the Autofill server. + // TODO: Use our own Autofill thread instead of the IO thread. + // TODO: For now, block here. Would like to make this properly async. + base::Thread* thread = WebUrlLoaderClient::ioThread(); + mParsingForms = true; + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebAutofill::formsSeenImpl)); + while (mParsingForms) + mFormsSeenCondition.wait(mFormsSeenMutex); +} + +// Called on the Chromium IO thread. +void WebAutofill::formsSeenImpl() +{ + MutexLocker lock(mFormsSeenMutex); + mAutofillManager->OnFormsSeenWrapper(mForms); + mParsingForms = false; + mFormsSeenCondition.signal(); +} + +void WebAutofill::formFieldFocused(WebCore::HTMLFormControlElement* formFieldElement) +{ + ASSERT(formFieldElement); + + Document* doc = formFieldElement->document(); + Frame* frame = doc->frame(); + + // FIXME: Autofill only works in main frame for now. Should consider + // child frames. + if (frame != frame->page()->mainFrame()) + return; + + unsigned domVersion = doc->domTreeVersion(); + ASSERT(domVersion > 0); + + if (mLastSearchDomVersion != domVersion) { + // Need to extract forms as DOM version has changed since the last time + // we searched. + searchDocument(formFieldElement->document()->frame()); + mLastSearchDomVersion = domVersion; + } + + if (!enabled()) { + // In case that we've just been disabled and the last time we got autofill + // suggestions and told Java about them, clear that bit Java side now + // we're disabled. + mWebViewCore->setWebTextViewAutoFillable(FORM_NOT_AUTOFILLABLE, string16()); + return; + } + + // Get the FormField from the Node. + webkit_glue::FormField* formField = new webkit_glue::FormField; + FormManager::HTMLFormControlElementToFormField(formFieldElement, FormManager::EXTRACT_NONE, formField); + formField->set_label(FormManager::LabelForElement(*formFieldElement)); + + webkit_glue::FormData* form = new webkit_glue::FormData; + mFormManager->FindFormWithFormControlElement(formFieldElement, FormManager::REQUIRE_AUTOCOMPLETE, form); + mQueryMap[mQueryId] = new FormDataAndField(form, formField); + + bool suggestions = mAutofillManager->OnQueryFormFieldAutoFillWrapper(*form, *formField); + + mQueryId++; + if (!suggestions) { + ASSERT(mWebViewCore); + // Tell Java no autofill suggestions for this form. + mWebViewCore->setWebTextViewAutoFillable(FORM_NOT_AUTOFILLABLE, string16()); + return; + } +} + +void WebAutofill::querySuccessful(const string16& value, const string16& label, int uniqueId) +{ + if (!enabled()) + return; + + // Store the unique ID for the query and inform java that autofill suggestions for this form are available. + // Pass java the queryId so that it can pass it back if the user decides to use autofill. + mUniqueIdMap[mQueryId] = uniqueId; + + ASSERT(mWebViewCore); + mWebViewCore->setWebTextViewAutoFillable(mQueryId, mAutofillProfile->Label()); +} + +void WebAutofill::fillFormFields(int queryId) +{ + if (!enabled()) + return; + + webkit_glue::FormData* form = mQueryMap[queryId]->form(); + webkit_glue::FormField* field = mQueryMap[queryId]->field(); + ASSERT(form); + ASSERT(field); + + AutofillQueryToUniqueIdMap::iterator iter = mUniqueIdMap.find(queryId); + if (iter == mUniqueIdMap.end()) { + // The user has most likely tried to Autofill the form again without + // refocussing the form field. The UI should protect against this + // but stop here to be certain. + return; + } + mAutofillManager->OnFillAutoFillFormDataWrapper(queryId, *form, *field, iter->second); + mUniqueIdMap.erase(iter); +} + +void WebAutofill::fillFormInPage(int queryId, const webkit_glue::FormData& form) +{ + if (!enabled()) + return; + + // FIXME: Pass a pointer to the Node that triggered the Autofill flow here instead of 0. + // The consquence of passing 0 is that we should always fail the test in FormManader::ForEachMathcingFormField():169 + // that says "only overwrite an elements current value if the user triggered autofill through that element" + // for elements that have a value already. But by a quirk of Android text views we are OK. We should still + // fix this though. + mFormManager->FillForm(form, 0); +} + +bool WebAutofill::enabled() const +{ + Page* page = mWebViewCore->mainFrame()->page(); + return page ? page->settings()->autoFillEnabled() : false; +} + +void WebAutofill::setProfile(const string16& fullName, const string16& emailAddress, const string16& companyName, + const string16& addressLine1, const string16& addressLine2, const string16& city, + const string16& state, const string16& zipCode, const string16& country, const string16& phoneNumber) +{ + if (!mAutofillProfile) + mAutofillProfile.set(new AutoFillProfile()); + + // Update the profile. + // Constants for Autofill field types are found in external/chromium/chrome/browser/autofill/field_types.h. + mAutofillProfile->SetInfo(AutofillType(NAME_FULL), fullName); + mAutofillProfile->SetInfo(AutofillType(EMAIL_ADDRESS), emailAddress); + mAutofillProfile->SetInfo(AutofillType(COMPANY_NAME), companyName); + mAutofillProfile->SetInfo(AutofillType(ADDRESS_HOME_LINE1), addressLine1); + mAutofillProfile->SetInfo(AutofillType(ADDRESS_HOME_LINE2), addressLine2); + mAutofillProfile->SetInfo(AutofillType(ADDRESS_HOME_CITY), city); + mAutofillProfile->SetInfo(AutofillType(ADDRESS_HOME_STATE), state); + mAutofillProfile->SetInfo(AutofillType(ADDRESS_HOME_ZIP), zipCode); + mAutofillProfile->SetInfo(AutofillType(ADDRESS_HOME_COUNTRY), country); + mAutofillProfile->SetInfo(AutofillType(PHONE_HOME_WHOLE_NUMBER), phoneNumber); + + std::vector profiles; + profiles.push_back(*mAutofillProfile); + updateProfileLabel(); + mTabContents->profile()->GetPersonalDataManager()->SetProfiles(&profiles); +} + +bool WebAutofill::updateProfileLabel() +{ + std::vector profiles; + profiles.push_back(mAutofillProfile.get()); + return AutoFillProfile::AdjustInferredLabels(&profiles); +} + +void WebAutofill::clearProfiles() +{ + if (!mAutofillProfile) + return; + // For now Chromium only ever knows about one profile, so we can just + // remove it. If we support multiple profiles in the future + // we need to remove them all here. + std::string profileGuid = mAutofillProfile->guid(); + mTabContents->profile()->GetPersonalDataManager()->RemoveProfile(profileGuid); + setEmptyProfile(); +} + +void WebAutofill::setEmptyProfile() +{ + // Set an empty profile. This will ensure that when autofill is enabled, + // we will still search the document for autofillable forms and inform + // java of their presence so we can invite the user to set up + // their own profile. + + // Chromium code will strip the values sent into the profile so we need them to be + // at least one non-whitespace character long. We need to set all fields of the + // profile to a non-empty string so that any field type can trigger the autofill + // suggestion. Autofill will not detect form fields if the profile value for that + // field is an empty string. + static const string16 empty = string16(ASCIIToUTF16("a")); + setProfile(empty, empty, empty, empty, empty, empty, empty, empty, empty, empty); +} + +} + +#endif diff --git a/Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.h b/Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.h new file mode 100644 index 0000000..a2f56a2 --- /dev/null +++ b/Source/WebKit/android/WebCoreSupport/autofill/WebAutofill.h @@ -0,0 +1,128 @@ +/* + * 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 +#include + +class AutofillManager; +class AutoFillProfile; +class AutoFillHost; + +namespace WebCore { +class Frame; +class HTMLFormControlElement; +} + +namespace android +{ +class FormManager; +class WebViewCore; + +class FormDataAndField { +public: + FormDataAndField(webkit_glue::FormData* form, webkit_glue::FormField* field) + : mForm(form) + , mField(field) + { + } + + webkit_glue::FormData* form() { return mForm.get(); } + webkit_glue::FormField* field() { return mField.get(); } + +private: + OwnPtr mForm; + OwnPtr mField; +}; + +class WebAutofill +{ + WTF_MAKE_NONCOPYABLE(WebAutofill); +public: + WebAutofill(); + virtual ~WebAutofill(); + void formFieldFocused(WebCore::HTMLFormControlElement*); + void fillFormFields(int queryId); + void querySuccessful(const string16& value, const string16& label, int uniqueId); + void fillFormInPage(int queryId, const webkit_glue::FormData& form); + void setWebViewCore(WebViewCore* webViewCore) { mWebViewCore = webViewCore; } + bool enabled() const; + + void setProfile(const string16& fullName, const string16& emailAddress, const string16& companyName, + const string16& addressLine1, const string16& addressLine2, const string16& city, + const string16& state, const string16& zipCode, const string16& country, const string16& phoneNumber); + void clearProfiles(); + + bool updateProfileLabel(); + + void reset() { mLastSearchDomVersion = 0; } + +private: + void init(); + void searchDocument(WebCore::Frame*); + void setEmptyProfile(); + void formsSeenImpl(); + void cleanUpQueryMap(); + + OwnPtr mFormManager; + OwnPtr mAutofillManager; + OwnPtr mAutofillHost; + OwnPtr mTabContents; + OwnPtr mAutofillProfile; + + typedef std::vector > FormList; + FormList mForms; + + typedef std::map AutofillQueryFormDataMap; + AutofillQueryFormDataMap mQueryMap; + + typedef std::map AutofillQueryToUniqueIdMap; + AutofillQueryToUniqueIdMap mUniqueIdMap; + int mQueryId; + + WebViewCore* mWebViewCore; + + unsigned mLastSearchDomVersion; + + WTF::Mutex mFormsSeenMutex; // Guards mFormsSeenCondition and mParsingForms. + WTF::ThreadCondition mFormsSeenCondition; + bool volatile mParsingForms; +}; + +} + +DISABLE_RUNNABLE_METHOD_REFCOUNT(android::WebAutofill); + +#endif // ENABLE(WEB_AUTOFILL) +#endif // WebAutoFill_h diff --git a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp index fb558c6..bdb502e 100644 --- a/Source/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/Source/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -124,7 +124,7 @@ #endif #if ENABLE(WEB_AUTOFILL) -#include "autofill/WebAutoFill.h" +#include "autofill/WebAutofill.h" #endif using namespace JSC::Bindings; @@ -1334,7 +1334,7 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss WebViewCore* webViewCore = new WebViewCore(env, javaview, frame); #if ENABLE(WEB_AUTOFILL) - editorC->getAutoFill()->setWebViewCore(webViewCore); + editorC->getAutofill()->setWebViewCore(webViewCore); #endif // Create a FrameView diff --git a/Source/WebKit/android/jni/WebSettings.cpp b/Source/WebKit/android/jni/WebSettings.cpp index 6f18695..589615d 100644 --- a/Source/WebKit/android/jni/WebSettings.cpp +++ b/Source/WebKit/android/jni/WebSettings.cpp @@ -293,7 +293,7 @@ inline string16 getStringFieldAsString16(JNIEnv* env, jobject autoFillProfile, j return str ? jstringToString16(env, str) : string16(); } -void syncAutoFillProfile(JNIEnv* env, jobject autoFillProfile, WebAutoFill* webAutoFill) +void syncAutoFillProfile(JNIEnv* env, jobject autoFillProfile, WebAutofill* webAutofill) { string16 fullName = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileFullName); string16 emailAddress = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileEmailAddress); @@ -306,7 +306,7 @@ void syncAutoFillProfile(JNIEnv* env, jobject autoFillProfile, WebAutoFill* webA string16 country = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfileCountry); string16 phoneNumber = getStringFieldAsString16(env, autoFillProfile, gFieldIds->mAutoFillProfilePhoneNumber); - webAutoFill->setProfile(fullName, emailAddress, companyName, addressLine1, addressLine2, city, state, zipCode, country, phoneNumber); + webAutofill->setProfile(fullName, emailAddress, companyName, addressLine1, addressLine2, city, state, zipCode, country, phoneNumber); } #endif @@ -554,16 +554,16 @@ public: if (flag) { EditorClientAndroid* editorC = static_cast(pFrame->page()->editorClient()); - WebAutoFill* webAutoFill = editorC->getAutoFill(); - // Set the active AutoFillProfile data. + WebAutofill* webAutofill = editorC->getAutofill(); + // Set the active AutofillProfile data. jobject autoFillProfile = env->GetObjectField(obj, gFieldIds->mAutoFillProfile); if (autoFillProfile) - syncAutoFillProfile(env, autoFillProfile, webAutoFill); + syncAutoFillProfile(env, autoFillProfile, webAutofill); else { // The autofill profile is null. We need to tell Chromium about this because // this may be because the user just deleted their profile but left the // autofill feature setting enabled. - webAutoFill->clearProfiles(); + webAutofill->clearProfiles(); } } #endif diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 96045c6..966a540 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -117,7 +117,7 @@ #include "WebFrameView.h" #include "WindowsKeyboardCodes.h" #include "android_graphics.h" -#include "autofill/WebAutoFill.h" +#include "autofill/WebAutofill.h" #include "htmlediting.h" #include "markup.h" @@ -3279,7 +3279,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node #if ENABLE(WEB_AUTOFILL) if (renderer->isTextField()) { EditorClientAndroid* editorC = static_cast(framePtr->page()->editorClient()); - WebAutoFill* autoFill = editorC->getAutoFill(); + WebAutofill* autoFill = editorC->getAutofill(); autoFill->formFieldFocused(static_cast(focusNode)); } #endif @@ -4566,7 +4566,7 @@ static void AutoFillForm(JNIEnv* env, jobject obj, jint queryId) WebCore::Frame* frame = viewImpl->mainFrame(); if (frame) { EditorClientAndroid* editorC = static_cast(frame->page()->editorClient()); - WebAutoFill* autoFill = editorC->getAutoFill(); + WebAutofill* autoFill = editorC->getAutofill(); autoFill->fillFormFields(queryId); } #endif -- cgit v1.1