OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. | 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv ed. |
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 10 matching lines...) Expand all Loading... | |
21 * Boston, MA 02110-1301, USA. | 21 * Boston, MA 02110-1301, USA. |
22 * | 22 * |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 #include "core/html/HTMLFormElement.h" | 26 #include "core/html/HTMLFormElement.h" |
27 | 27 |
28 #include <limits> | 28 #include <limits> |
29 #include "HTMLNames.h" | 29 #include "HTMLNames.h" |
30 #include "bindings/v8/Dictionary.h" | 30 #include "bindings/v8/Dictionary.h" |
31 #include "bindings/v8/NewScriptState.h" | |
31 #include "bindings/v8/ScriptController.h" | 32 #include "bindings/v8/ScriptController.h" |
32 #include "bindings/v8/ScriptEventListener.h" | 33 #include "bindings/v8/ScriptEventListener.h" |
34 #include "bindings/v8/ScriptPromiseResolverWithContext.h" | |
35 #include "bindings/v8/ScriptValue.h" | |
33 #include "core/dom/Attribute.h" | 36 #include "core/dom/Attribute.h" |
34 #include "core/dom/Document.h" | 37 #include "core/dom/Document.h" |
35 #include "core/dom/ElementTraversal.h" | 38 #include "core/dom/ElementTraversal.h" |
36 #include "core/dom/IdTargetObserverRegistry.h" | 39 #include "core/dom/IdTargetObserverRegistry.h" |
37 #include "core/events/AutocompleteErrorEvent.h" | 40 #include "core/events/AutocompleteErrorEvent.h" |
38 #include "core/events/Event.h" | 41 #include "core/events/Event.h" |
39 #include "core/events/ScopedEventQueue.h" | 42 #include "core/events/ScopedEventQueue.h" |
40 #include "core/html/HTMLCollection.h" | 43 #include "core/html/HTMLCollection.h" |
41 #include "core/html/HTMLDialogElement.h" | 44 #include "core/html/HTMLDialogElement.h" |
42 #include "core/html/HTMLImageElement.h" | 45 #include "core/html/HTMLImageElement.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
78 { | 81 { |
79 UseCounter::count(document, UseCounter::FormElement); | 82 UseCounter::count(document, UseCounter::FormElement); |
80 return adoptRef(new HTMLFormElement(document)); | 83 return adoptRef(new HTMLFormElement(document)); |
81 } | 84 } |
82 | 85 |
83 HTMLFormElement::~HTMLFormElement() | 86 HTMLFormElement::~HTMLFormElement() |
84 { | 87 { |
85 document().formController().willDeleteForm(this); | 88 document().formController().willDeleteForm(this); |
86 } | 89 } |
87 | 90 |
91 class AutocompleteRequest { | |
92 public: | |
93 static PassOwnPtr<AutocompleteRequest> create(HTMLFormElement* form) | |
94 { | |
95 return adoptPtr(new AutocompleteRequest(form)); | |
96 } | |
97 | |
98 ScriptPromise promise() | |
99 { | |
100 return m_resolver->promise(); | |
101 } | |
102 | |
103 void setResult(HTMLFormElement::AutocompleteResult result) | |
104 { | |
105 ASSERT(!m_isResultSet); | |
106 m_result = result; | |
107 m_isResultSet = true; | |
108 } | |
109 | |
110 void dispatchAndFulfill() | |
111 { | |
112 ASSERT(m_isResultSet); | |
113 | |
114 String reason; | |
115 if (m_result == HTMLFormElement::AutocompleteResultErrorDisabled) | |
116 reason = "disabled"; | |
117 else if (m_result == HTMLFormElement::AutocompleteResultErrorCancel) | |
118 reason = "cancel"; | |
119 else if (m_result == HTMLFormElement::AutocompleteResultErrorInvalid) | |
120 reason = "invalid"; | |
121 | |
122 RefPtrWillBeRawPtr<Event> event = reason.isEmpty() ? Event::createBubble (EventTypeNames::autocomplete) : AutocompleteErrorEvent::create(reason); | |
123 event->setTarget(m_form); | |
124 m_form->dispatchEvent(event.release()); | |
125 | |
126 v8::Isolate* isolate = m_resolver->scriptState()->isolate(); | |
127 if (reason.isEmpty()) { | |
128 m_resolver->resolve(V8UndefinedType()); | |
129 } else { | |
130 NewScriptState::Scope scope(m_resolver->scriptState()); | |
131 v8::Handle<v8::Value> error = v8::Exception::Error(v8String(isolate, "requestAutocomplete: failed.")); | |
132 error.As<v8::Object>()->Set(v8String(isolate, "reason"), v8String(is olate, reason)); | |
133 m_resolver->reject(ScriptValue(error, isolate)); | |
yhirano
2014/04/22 02:03:37
Please call resolve or reject out of the extent of
Dan Beam
2014/04/23 01:21:03
Done.
| |
134 } | |
135 } | |
136 | |
137 private: | |
138 AutocompleteRequest(HTMLFormElement* form) | |
139 : m_form(form) | |
140 , m_resolver(ScriptPromiseResolverWithContext::create(NewScriptState::cu rrent(toIsolate(form->executionContext())))) | |
141 , m_isResultSet(false) | |
142 { } | |
143 | |
144 HTMLFormElement* m_form; | |
145 RefPtr<ScriptPromiseResolverWithContext> m_resolver; | |
146 HTMLFormElement::AutocompleteResult m_result; | |
147 bool m_isResultSet; | |
148 }; | |
149 | |
88 bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style) | 150 bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style) |
89 { | 151 { |
90 if (!m_wasDemoted) | 152 if (!m_wasDemoted) |
91 return HTMLElement::rendererIsNeeded(style); | 153 return HTMLElement::rendererIsNeeded(style); |
92 | 154 |
93 ContainerNode* node = parentNode(); | 155 ContainerNode* node = parentNode(); |
94 if (!node || !node->renderer()) | 156 if (!node || !node->renderer()) |
95 return HTMLElement::rendererIsNeeded(style); | 157 return HTMLElement::rendererIsNeeded(style); |
96 RenderObject* parentRenderer = node->renderer(); | 158 RenderObject* parentRenderer = node->renderer(); |
97 // FIXME: Shouldn't we also check for table caption (see |formIsTablePart| b elow). | 159 // FIXME: Shouldn't we also check for table caption (see |formIsTablePart| b elow). |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
409 | 471 |
410 const Vector<FormAssociatedElement*>& elements = associatedElements(); | 472 const Vector<FormAssociatedElement*>& elements = associatedElements(); |
411 for (unsigned i = 0; i < elements.size(); ++i) { | 473 for (unsigned i = 0; i < elements.size(); ++i) { |
412 if (elements[i]->isFormControlElement()) | 474 if (elements[i]->isFormControlElement()) |
413 toHTMLFormControlElement(elements[i])->reset(); | 475 toHTMLFormControlElement(elements[i])->reset(); |
414 } | 476 } |
415 | 477 |
416 m_isInResetFunction = false; | 478 m_isInResetFunction = false; |
417 } | 479 } |
418 | 480 |
419 void HTMLFormElement::requestAutocomplete(const Dictionary& details) | 481 ScriptPromise HTMLFormElement::requestAutocomplete(const Dictionary& details) |
420 { | 482 { |
483 OwnPtr<AutocompleteRequest> request = AutocompleteRequest::create(this); | |
484 ScriptPromise promise = request->promise(); | |
485 | |
421 String errorMessage; | 486 String errorMessage; |
422 | |
423 if (!document().frame()) | 487 if (!document().frame()) |
424 errorMessage = "requestAutocomplete: form is not owned by a displayed do cument."; | 488 errorMessage = "requestAutocomplete: form is not owned by a displayed do cument."; |
425 else if (!shouldAutocomplete()) | 489 else if (!shouldAutocomplete()) |
426 errorMessage = "requestAutocomplete: form autocomplete attribute is set to off."; | 490 errorMessage = "requestAutocomplete: form autocomplete attribute is set to off."; |
427 else if (!UserGestureIndicator::processingUserGesture()) | 491 else if (!UserGestureIndicator::processingUserGesture()) |
428 errorMessage = "requestAutocomplete: must be called in response to a use r gesture."; | 492 errorMessage = "requestAutocomplete: must be called in response to a use r gesture."; |
493 else if (!!m_pendingAutocompleteRequest) | |
494 errorMessage = "requestAutocomplete: already in progess."; | |
429 | 495 |
430 if (!errorMessage.isEmpty()) { | 496 if (!errorMessage.isEmpty()) { |
431 document().addConsoleMessage(RenderingMessageSource, LogMessageLevel, er rorMessage); | 497 document().addConsoleMessage(RenderingMessageSource, LogMessageLevel, er rorMessage); |
432 finishRequestAutocomplete(AutocompleteResultErrorDisabled); | 498 doFinishRequestAutocomplete(AutocompleteResultErrorDisabled, request.rel ease()); |
433 } else { | 499 } else { |
500 m_pendingAutocompleteRequest = request.release(); | |
434 document().frame()->loader().client()->didRequestAutocomplete(this, deta ils); | 501 document().frame()->loader().client()->didRequestAutocomplete(this, deta ils); |
435 } | 502 } |
503 | |
504 return promise; | |
436 } | 505 } |
437 | 506 |
438 void HTMLFormElement::finishRequestAutocomplete(AutocompleteResult result) | 507 void HTMLFormElement::finishRequestAutocomplete(AutocompleteResult result) |
439 { | 508 { |
440 RefPtrWillBeRawPtr<Event> event = nullptr; | 509 doFinishRequestAutocomplete(result, m_pendingAutocompleteRequest.release()); |
441 if (result == AutocompleteResultSuccess) | 510 } |
442 event = Event::createBubble(EventTypeNames::autocomplete); | |
443 else if (result == AutocompleteResultErrorDisabled) | |
444 event = AutocompleteErrorEvent::create("disabled"); | |
445 else if (result == AutocompleteResultErrorCancel) | |
446 event = AutocompleteErrorEvent::create("cancel"); | |
447 else if (result == AutocompleteResultErrorInvalid) | |
448 event = AutocompleteErrorEvent::create("invalid"); | |
449 else | |
450 ASSERT_NOT_REACHED(); | |
451 | 511 |
452 event->setTarget(this); | 512 void HTMLFormElement::doFinishRequestAutocomplete(AutocompleteResult result, Pas sOwnPtr<AutocompleteRequest> request) |
453 m_pendingAutocompleteEvents.append(event.release()); | 513 { |
514 request->setResult(result); | |
515 m_finishedAutocompleteRequests.append(request); | |
454 | 516 |
455 // Dispatch events later as this API is meant to work asynchronously in all situations and implementations. | 517 // Finish the request later as this API is meant to work asynchronously in a ll situations and implementations. |
456 if (!m_requestAutocompleteTimer.isActive()) | 518 if (!m_requestAutocompleteTimer.isActive()) |
457 m_requestAutocompleteTimer.startOneShot(0, FROM_HERE); | 519 m_requestAutocompleteTimer.startOneShot(0, FROM_HERE); |
458 } | 520 } |
459 | 521 |
460 void HTMLFormElement::requestAutocompleteTimerFired(Timer<HTMLFormElement>*) | 522 void HTMLFormElement::requestAutocompleteTimerFired(Timer<HTMLFormElement>*) |
461 { | 523 { |
462 WillBeHeapVector<RefPtrWillBeMember<Event> > pendingEvents; | 524 Vector<OwnPtr<AutocompleteRequest> > finishedRequests; |
463 m_pendingAutocompleteEvents.swap(pendingEvents); | 525 m_finishedAutocompleteRequests.swap(finishedRequests); |
464 for (size_t i = 0; i < pendingEvents.size(); ++i) | 526 |
465 dispatchEvent(pendingEvents[i].release()); | 527 RefPtr<HTMLFormElement> protector(this); |
528 for (size_t i = 0; i < finishedRequests.size(); ++i) | |
529 finishedRequests[i]->dispatchAndFulfill(); | |
466 } | 530 } |
467 | 531 |
468 void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicStri ng& value) | 532 void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicStri ng& value) |
469 { | 533 { |
470 if (name == actionAttr) | 534 if (name == actionAttr) |
471 m_attributes.parseAction(value); | 535 m_attributes.parseAction(value); |
472 else if (name == targetAttr) | 536 else if (name == targetAttr) |
473 m_attributes.setTarget(value); | 537 m_attributes.setTarget(value); |
474 else if (name == methodAttr) | 538 else if (name == methodAttr) |
475 m_attributes.updateMethodType(value); | 539 m_attributes.updateMethodType(value); |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
773 } | 837 } |
774 | 838 |
775 void HTMLFormElement::setDemoted(bool demoted) | 839 void HTMLFormElement::setDemoted(bool demoted) |
776 { | 840 { |
777 if (demoted) | 841 if (demoted) |
778 UseCounter::count(document(), UseCounter::DemotedFormElement); | 842 UseCounter::count(document(), UseCounter::DemotedFormElement); |
779 m_wasDemoted = demoted; | 843 m_wasDemoted = demoted; |
780 } | 844 } |
781 | 845 |
782 } // namespace | 846 } // namespace |
OLD | NEW |