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/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 |