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/ScriptPromiseResolver.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_scriptState->isolate(); | |
127 NewScriptState::Scope scope(m_scriptState.get()); | |
yhirano
2014/04/17 10:57:48
Can you use ScriptPromiseResolverWithContext inste
Dan Beam
2014/04/17 23:02:04
Done. (patched in your CL locally)
| |
128 if (reason.isEmpty()) { | |
129 m_resolver->resolve(v8::Undefined(isolate)); | |
130 } else { | |
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)); | |
134 } | |
135 } | |
136 | |
137 private: | |
138 AutocompleteRequest(HTMLFormElement* form) | |
139 : m_form(form) | |
140 , m_resolver(ScriptPromiseResolver::create(form->executionContext())) | |
141 , m_scriptState(NewScriptState::current(toIsolate(form->executionContext ()))) | |
142 , m_isResultSet(false) | |
143 { } | |
144 | |
145 HTMLFormElement* m_form; | |
146 RefPtr<ScriptPromiseResolver> m_resolver; | |
147 RefPtr<NewScriptState> m_scriptState; | |
148 HTMLFormElement::AutocompleteResult m_result; | |
149 bool m_isResultSet; | |
150 }; | |
151 | |
88 bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style) | 152 bool HTMLFormElement::rendererIsNeeded(const RenderStyle& style) |
89 { | 153 { |
90 if (!m_wasDemoted) | 154 if (!m_wasDemoted) |
91 return HTMLElement::rendererIsNeeded(style); | 155 return HTMLElement::rendererIsNeeded(style); |
92 | 156 |
93 ContainerNode* node = parentNode(); | 157 ContainerNode* node = parentNode(); |
94 if (!node || !node->renderer()) | 158 if (!node || !node->renderer()) |
95 return HTMLElement::rendererIsNeeded(style); | 159 return HTMLElement::rendererIsNeeded(style); |
96 RenderObject* parentRenderer = node->renderer(); | 160 RenderObject* parentRenderer = node->renderer(); |
97 // FIXME: Shouldn't we also check for table caption (see |formIsTablePart| b elow). | 161 // 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 | 473 |
410 const Vector<FormAssociatedElement*>& elements = associatedElements(); | 474 const Vector<FormAssociatedElement*>& elements = associatedElements(); |
411 for (unsigned i = 0; i < elements.size(); ++i) { | 475 for (unsigned i = 0; i < elements.size(); ++i) { |
412 if (elements[i]->isFormControlElement()) | 476 if (elements[i]->isFormControlElement()) |
413 toHTMLFormControlElement(elements[i])->reset(); | 477 toHTMLFormControlElement(elements[i])->reset(); |
414 } | 478 } |
415 | 479 |
416 m_isInResetFunction = false; | 480 m_isInResetFunction = false; |
417 } | 481 } |
418 | 482 |
419 void HTMLFormElement::requestAutocomplete(const Dictionary& details) | 483 ScriptPromise HTMLFormElement::requestAutocomplete(const Dictionary& details) |
420 { | 484 { |
485 OwnPtr<AutocompleteRequest> request = AutocompleteRequest::create(this); | |
486 ScriptPromise promise = request->promise(); | |
487 | |
421 String errorMessage; | 488 String errorMessage; |
422 | |
423 if (!document().frame()) | 489 if (!document().frame()) |
424 errorMessage = "requestAutocomplete: form is not owned by a displayed do cument."; | 490 errorMessage = "requestAutocomplete: form is not owned by a displayed do cument."; |
425 else if (!shouldAutocomplete()) | 491 else if (!shouldAutocomplete()) |
426 errorMessage = "requestAutocomplete: form autocomplete attribute is set to off."; | 492 errorMessage = "requestAutocomplete: form autocomplete attribute is set to off."; |
427 else if (!UserGestureIndicator::processingUserGesture()) | 493 else if (!UserGestureIndicator::processingUserGesture()) |
428 errorMessage = "requestAutocomplete: must be called in response to a use r gesture."; | 494 errorMessage = "requestAutocomplete: must be called in response to a use r gesture."; |
495 else if (m_pendingAutocompleteRequest) | |
496 errorMessage = "requestAutocomplete: already in progess."; | |
429 | 497 |
430 if (!errorMessage.isEmpty()) { | 498 if (!errorMessage.isEmpty()) { |
431 document().addConsoleMessage(RenderingMessageSource, LogMessageLevel, er rorMessage); | 499 document().addConsoleMessage(RenderingMessageSource, LogMessageLevel, er rorMessage); |
432 finishRequestAutocomplete(AutocompleteResultErrorDisabled); | 500 doFinishRequestAutocomplete(AutocompleteResultErrorDisabled, request.rel ease()); |
433 } else { | 501 } else { |
502 m_pendingAutocompleteRequest = request.release(); | |
434 document().frame()->loader().client()->didRequestAutocomplete(this, deta ils); | 503 document().frame()->loader().client()->didRequestAutocomplete(this, deta ils); |
435 } | 504 } |
505 | |
506 return promise; | |
436 } | 507 } |
437 | 508 |
438 void HTMLFormElement::finishRequestAutocomplete(AutocompleteResult result) | 509 void HTMLFormElement::finishRequestAutocomplete(AutocompleteResult result) |
439 { | 510 { |
440 RefPtrWillBeRawPtr<Event> event = nullptr; | 511 doFinishRequestAutocomplete(result, m_pendingAutocompleteRequest.release()); |
441 if (result == AutocompleteResultSuccess) | 512 } |
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 | 513 |
452 event->setTarget(this); | 514 void HTMLFormElement::doFinishRequestAutocomplete(AutocompleteResult result, Pas sOwnPtr<AutocompleteRequest> request) |
453 m_pendingAutocompleteEvents.append(event.release()); | 515 { |
516 request->setResult(result); | |
517 m_finishedAutocompleteRequests.append(request); | |
454 | 518 |
455 // Dispatch events later as this API is meant to work asynchronously in all situations and implementations. | 519 // Finish the request later as this API is meant to work asynchronously in a ll situations and implementations. |
456 if (!m_requestAutocompleteTimer.isActive()) | 520 if (!m_requestAutocompleteTimer.isActive()) |
457 m_requestAutocompleteTimer.startOneShot(0, FROM_HERE); | 521 m_requestAutocompleteTimer.startOneShot(0, FROM_HERE); |
458 } | 522 } |
459 | 523 |
460 void HTMLFormElement::requestAutocompleteTimerFired(Timer<HTMLFormElement>*) | 524 void HTMLFormElement::requestAutocompleteTimerFired(Timer<HTMLFormElement>*) |
461 { | 525 { |
462 WillBeHeapVector<RefPtrWillBeMember<Event> > pendingEvents; | 526 WillBeHeapVector<OwnPtrWillBeMember<AutocompleteRequest> > finishedRequests; |
463 m_pendingAutocompleteEvents.swap(pendingEvents); | 527 m_finishedAutocompleteRequests.swap(finishedRequests); |
464 for (size_t i = 0; i < pendingEvents.size(); ++i) | 528 |
465 dispatchEvent(pendingEvents[i].release()); | 529 RefPtr<HTMLFormElement> protector(this); |
530 for (size_t i = 0; i < finishedRequests.size(); ++i) | |
531 finishedRequests[i]->dispatchAndFulfill(); | |
466 } | 532 } |
467 | 533 |
468 void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicStri ng& value) | 534 void HTMLFormElement::parseAttribute(const QualifiedName& name, const AtomicStri ng& value) |
469 { | 535 { |
470 if (name == actionAttr) | 536 if (name == actionAttr) |
471 m_attributes.parseAction(value); | 537 m_attributes.parseAction(value); |
472 else if (name == targetAttr) | 538 else if (name == targetAttr) |
473 m_attributes.setTarget(value); | 539 m_attributes.setTarget(value); |
474 else if (name == methodAttr) | 540 else if (name == methodAttr) |
475 m_attributes.updateMethodType(value); | 541 m_attributes.updateMethodType(value); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 } | 844 } |
779 | 845 |
780 void HTMLFormElement::setDemoted(bool demoted) | 846 void HTMLFormElement::setDemoted(bool demoted) |
781 { | 847 { |
782 if (demoted) | 848 if (demoted) |
783 UseCounter::count(document(), UseCounter::DemotedFormElement); | 849 UseCounter::count(document(), UseCounter::DemotedFormElement); |
784 m_wasDemoted = demoted; | 850 m_wasDemoted = demoted; |
785 } | 851 } |
786 | 852 |
787 } // namespace | 853 } // namespace |
OLD | NEW |