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