| Index: Source/core/html/HTMLFormElement.cpp
|
| diff --git a/Source/core/html/HTMLFormElement.cpp b/Source/core/html/HTMLFormElement.cpp
|
| index 089fde6522475add928e10b5772f182147afaf8d..0406277c9d5ad14758e591d26e814e464dcb59dd 100644
|
| --- a/Source/core/html/HTMLFormElement.cpp
|
| +++ b/Source/core/html/HTMLFormElement.cpp
|
| @@ -28,9 +28,12 @@
|
| #include <limits>
|
| #include "HTMLNames.h"
|
| #include "bindings/v8/Dictionary.h"
|
| +#include "bindings/v8/NewScriptState.h"
|
| #include "bindings/v8/ScriptController.h"
|
| #include "bindings/v8/ScriptEventListener.h"
|
| +#include "bindings/v8/ScriptPromiseResolverWithContext.h"
|
| #include "core/dom/Attribute.h"
|
| +#include "core/dom/AutocompleteError.h"
|
| #include "core/dom/Document.h"
|
| #include "core/dom/ElementTraversal.h"
|
| #include "core/dom/IdTargetObserverRegistry.h"
|
| @@ -85,6 +88,60 @@ HTMLFormElement::~HTMLFormElement()
|
| document().formController().willDeleteForm(this);
|
| }
|
|
|
| +class AutocompleteRequest {
|
| +public:
|
| + static PassOwnPtr<AutocompleteRequest> create(HTMLFormElement* form)
|
| + {
|
| + return adoptPtr(new AutocompleteRequest(form));
|
| + }
|
| +
|
| + ScriptPromise promise()
|
| + {
|
| + return m_resolver->promise();
|
| + }
|
| +
|
| + void setResult(HTMLFormElement::AutocompleteResult result)
|
| + {
|
| + ASSERT(!m_isResultSet);
|
| + m_result = result;
|
| + m_isResultSet = true;
|
| + }
|
| +
|
| + void dispatchAndFulfill()
|
| + {
|
| + ASSERT(m_isResultSet);
|
| +
|
| + String reason;
|
| + if (m_result == HTMLFormElement::AutocompleteResultErrorDisabled)
|
| + reason = "disabled";
|
| + else if (m_result == HTMLFormElement::AutocompleteResultErrorCancel)
|
| + reason = "cancel";
|
| + else if (m_result == HTMLFormElement::AutocompleteResultErrorInvalid)
|
| + reason = "invalid";
|
| +
|
| + RefPtrWillBeRawPtr<Event> event = reason.isEmpty() ? Event::createBubble(EventTypeNames::autocomplete) : AutocompleteErrorEvent::create(reason);
|
| + event->setTarget(m_form);
|
| + m_form->dispatchEvent(event.release());
|
| +
|
| + if (reason.isEmpty())
|
| + m_resolver->resolve(V8UndefinedType());
|
| + else
|
| + m_resolver->reject(AutocompleteError::create(reason));
|
| + }
|
| +
|
| +private:
|
| + AutocompleteRequest(HTMLFormElement* form)
|
| + : m_form(form)
|
| + , m_resolver(ScriptPromiseResolverWithContext::create(NewScriptState::current(toIsolate(form->executionContext()))))
|
| + , m_isResultSet(false)
|
| + { }
|
| +
|
| + HTMLFormElement* m_form;
|
| + RefPtr<ScriptPromiseResolverWithContext> m_resolver;
|
| + HTMLFormElement::AutocompleteResult m_result;
|
| + bool m_isResultSet;
|
| +};
|
| +
|
| bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style)
|
| {
|
| if (!m_wasDemoted)
|
| @@ -416,53 +473,55 @@ void HTMLFormElement::reset()
|
| m_isInResetFunction = false;
|
| }
|
|
|
| -void HTMLFormElement::requestAutocomplete(const Dictionary& details)
|
| +ScriptPromise HTMLFormElement::requestAutocomplete(const Dictionary& details)
|
| {
|
| - String errorMessage;
|
| + OwnPtr<AutocompleteRequest> request = AutocompleteRequest::create(this);
|
| + ScriptPromise promise = request->promise();
|
|
|
| + String errorMessage;
|
| if (!document().frame())
|
| errorMessage = "requestAutocomplete: form is not owned by a displayed document.";
|
| else if (!shouldAutocomplete())
|
| errorMessage = "requestAutocomplete: form autocomplete attribute is set to off.";
|
| else if (!UserGestureIndicator::processingUserGesture())
|
| errorMessage = "requestAutocomplete: must be called in response to a user gesture.";
|
| + else if (!!m_pendingAutocompleteRequest)
|
| + errorMessage = "requestAutocomplete: already in progess.";
|
|
|
| if (!errorMessage.isEmpty()) {
|
| document().addConsoleMessage(RenderingMessageSource, LogMessageLevel, errorMessage);
|
| - finishRequestAutocomplete(AutocompleteResultErrorDisabled);
|
| + doFinishRequestAutocomplete(AutocompleteResultErrorDisabled, request.release());
|
| } else {
|
| + m_pendingAutocompleteRequest = request.release();
|
| document().frame()->loader().client()->didRequestAutocomplete(this, details);
|
| }
|
| +
|
| + return promise;
|
| }
|
|
|
| void HTMLFormElement::finishRequestAutocomplete(AutocompleteResult result)
|
| {
|
| - RefPtrWillBeRawPtr<Event> event = nullptr;
|
| - if (result == AutocompleteResultSuccess)
|
| - event = Event::createBubble(EventTypeNames::autocomplete);
|
| - else if (result == AutocompleteResultErrorDisabled)
|
| - event = AutocompleteErrorEvent::create("disabled");
|
| - else if (result == AutocompleteResultErrorCancel)
|
| - event = AutocompleteErrorEvent::create("cancel");
|
| - else if (result == AutocompleteResultErrorInvalid)
|
| - event = AutocompleteErrorEvent::create("invalid");
|
| - else
|
| - ASSERT_NOT_REACHED();
|
| + doFinishRequestAutocomplete(result, m_pendingAutocompleteRequest.release());
|
| +}
|
|
|
| - event->setTarget(this);
|
| - m_pendingAutocompleteEvents.append(event.release());
|
| +void HTMLFormElement::doFinishRequestAutocomplete(AutocompleteResult result, PassOwnPtr<AutocompleteRequest> request)
|
| +{
|
| + request->setResult(result);
|
| + m_finishedAutocompleteRequests.append(request);
|
|
|
| - // Dispatch events later as this API is meant to work asynchronously in all situations and implementations.
|
| + // Finish the request later as this API is meant to work asynchronously in all situations and implementations.
|
| if (!m_requestAutocompleteTimer.isActive())
|
| m_requestAutocompleteTimer.startOneShot(0, FROM_HERE);
|
| }
|
|
|
| void HTMLFormElement::requestAutocompleteTimerFired(Timer<HTMLFormElement>*)
|
| {
|
| - WillBeHeapVector<RefPtrWillBeMember<Event> > pendingEvents;
|
| - m_pendingAutocompleteEvents.swap(pendingEvents);
|
| - for (size_t i = 0; i < pendingEvents.size(); ++i)
|
| - dispatchEvent(pendingEvents[i].release());
|
| + Vector<OwnPtr<AutocompleteRequest> > finishedRequests;
|
| + m_finishedAutocompleteRequests.swap(finishedRequests);
|
| +
|
| + RefPtr<HTMLFormElement> protector(this);
|
| + for (size_t i = 0; i < finishedRequests.size(); ++i)
|
| + finishedRequests[i]->dispatchAndFulfill();
|
| }
|
|
|
| void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
|
|
|