Chromium Code Reviews| 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 |