Chromium Code Reviews| Index: Source/core/html/HTMLFormElement.cpp |
| diff --git a/Source/core/html/HTMLFormElement.cpp b/Source/core/html/HTMLFormElement.cpp |
| index 089fde6522475add928e10b5772f182147afaf8d..bdee11d4bac8bb6f1d742b37f221e87e5d6e8214 100644 |
| --- a/Source/core/html/HTMLFormElement.cpp |
| +++ b/Source/core/html/HTMLFormElement.cpp |
| @@ -28,8 +28,11 @@ |
| #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 "bindings/v8/ScriptValue.h" |
| #include "core/dom/Attribute.h" |
| #include "core/dom/Document.h" |
| #include "core/dom/ElementTraversal.h" |
| @@ -85,6 +88,66 @@ 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()); |
| + |
| + v8::Isolate* isolate = m_resolver->scriptState()->isolate(); |
| + NewScriptState::Scope scope(m_resolver->scriptState()); |
|
Dan Beam
2014/04/17 23:02:04
^ still had to create a script scope to create new
yhirano
2014/04/18 07:32:33
When https://codereview.chromium.org/238723009/ la
Dan Beam
2014/04/18 21:33:07
yeah, it's all good -- this CL isn't incredibly ur
yhirano
2014/04/21 09:31:32
You can use it now. Thanks!
Dan Beam
2014/04/22 00:43:54
merged in your change, ptal
|
| + if (reason.isEmpty()) { |
| + v8::Handle<v8::Value> undefined = v8::Undefined(isolate); |
| + m_resolver->resolve(ScriptValue(undefined, isolate)); |
| + } else { |
| + v8::Handle<v8::Value> error = v8::Exception::Error(v8String(isolate, "requestAutocomplete: failed.")); |
| + error.As<v8::Object>()->Set(v8String(isolate, "reason"), v8String(isolate, reason)); |
| + m_resolver->reject(ScriptValue(error, isolate)); |
| + } |
| + } |
| + |
| +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 +479,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) |