Auto merge of #9930 - rebstar6:htmlclick, r=jdm

Remove activatable element filter within HTMLElement#click()

Address https://github.com/servo/servo/issues/6542

Ensure that click() calls are not limited to activatable elements. Also makes the isTrusted attribute false when synthetic click activation are called from a click() method (as per spec).

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9930)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-03-11 10:06:24 +05:30
commit f2f6787189
9 changed files with 95 additions and 66 deletions

View file

@ -29,14 +29,22 @@ pub trait Activatable {
// https://html.spec.whatwg.org/multipage/#implicit-submission
fn implicit_submission(&self, ctrlKey: bool, shiftKey: bool, altKey: bool, metaKey: bool);
}
/// Whether an activation was initiated via the click() method
#[derive(PartialEq)]
pub enum ActivationSource {
FromClick,
NotFromClick,
}
// https://html.spec.whatwg.org/multipage/#run-synthetic-click-activation-steps
fn synthetic_click_activation(&self,
pub fn synthetic_click_activation(element: &Element,
ctrlKey: bool,
shiftKey: bool,
altKey: bool,
metaKey: bool) {
let element = self.as_element();
metaKey: bool,
source: ActivationSource) {
// Step 1
if element.click_in_progress() {
return;
@ -44,12 +52,15 @@ pub trait Activatable {
// Step 2
element.set_click_in_progress(true);
// Step 3
self.pre_click_activation();
let activatable = element.as_maybe_activatable();
if let Some(a) = activatable {
a.pre_click_activation();
}
// Step 4
// https://html.spec.whatwg.org/multipage/#fire-a-synthetic-mouse-event
let win = window_from_node(element);
let target = element.upcast();
let target = element.upcast::<EventTarget>();
let mouse = MouseEvent::new(win.r(),
DOMString::from("click"),
EventBubbles::DoesNotBubble,
@ -67,17 +78,21 @@ pub trait Activatable {
0,
None);
let event = mouse.upcast::<Event>();
event.fire(target);
if source == ActivationSource::FromClick {
event.set_trusted(false);
}
target.dispatch_event(event);
// Step 5
if let Some(a) = activatable {
if event.DefaultPrevented() {
self.canceled_activation();
a.canceled_activation();
} else {
// post click activation
self.activation_behavior(event, target);
a.activation_behavior(event, target);
}
}
// Step 6
element.set_click_in_progress(false);
}
}

View file

@ -4,6 +4,7 @@
use devtools_traits::CSSError;
use document_loader::{DocumentLoader, LoadType};
use dom::activation::{ActivationSource, synthetic_click_activation};
use dom::attr::{Attr, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
@ -1083,9 +1084,12 @@ impl Document {
Key::Space if !prevented && state == KeyState::Released => {
let maybe_elem = target.downcast::<Element>();
if let Some(el) = maybe_elem {
if let Some(a) = el.as_maybe_activatable() {
a.synthetic_click_activation(ctrl, alt, shift, meta);
}
synthetic_click_activation(el,
false,
false,
false,
false,
ActivationSource::NotFromClick)
}
}
Key::Enter if !prevented && state == KeyState::Released => {

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::activation::Activatable;
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding;
use dom::bindings::codegen::Bindings::HTMLButtonElementBinding::HTMLButtonElementMethods;
@ -256,6 +256,11 @@ impl Activatable for HTMLButtonElement {
node.query_selector_iter(DOMString::from("button[type=submit]")).unwrap()
.filter_map(Root::downcast::<HTMLButtonElement>)
.find(|r| r.form_owner() == owner)
.map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey));
.map(|s| synthetic_click_activation(s.r().as_element(),
ctrlKey,
shiftKey,
altKey,
metaKey,
ActivationSource::NotFromClick));
}
}

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::activation::{ActivationSource, synthetic_click_activation};
use dom::attr::Attr;
use dom::attr::AttrValue;
use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
@ -9,7 +10,6 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::Bindings::EventHandlerBinding::OnErrorEventHandlerNonNull;
use dom::bindings::codegen::Bindings::HTMLElementBinding;
use dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use dom::bindings::error::{Error, ErrorResult};
use dom::bindings::inheritance::Castable;
@ -200,16 +200,15 @@ impl HTMLElementMethods for HTMLElement {
// https://html.spec.whatwg.org/multipage/#dom-click
fn Click(&self) {
if let Some(i) = self.downcast::<HTMLInputElement>() {
if i.Disabled() {
return;
if !self.upcast::<Element>().get_disabled_state() {
synthetic_click_activation(self.upcast::<Element>(),
false,
false,
false,
false,
ActivationSource::FromClick)
}
}
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=27430 ?
self.upcast::<Element>()
.as_maybe_activatable()
.map(|a| a.synthetic_click_activation(false, false, false, false));
}
// https://html.spec.whatwg.org/multipage/#dom-focus
fn Focus(&self) {

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use caseless::compatibility_caseless_match_str;
use dom::activation::Activatable;
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
use dom::attr::{Attr, AttrValue};
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
@ -1091,7 +1091,12 @@ impl Activatable for HTMLInputElement {
match submit_button {
Some(ref button) => {
if button.is_instance_activatable() {
button.synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey)
synthetic_click_activation(button.as_element(),
ctrlKey,
shiftKey,
altKey,
metaKey,
ActivationSource::NotFromClick)
}
}
None => {

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::activation::Activatable;
use dom::activation::{Activatable, ActivationSource, synthetic_click_activation};
use dom::attr::AttrValue;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding;
use dom::bindings::codegen::Bindings::HTMLLabelElementBinding::HTMLLabelElementMethods;
@ -63,9 +63,12 @@ impl Activatable for HTMLLabelElement {
// https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps
fn activation_behavior(&self, _event: &Event, _target: &EventTarget) {
self.upcast::<Element>()
.as_maybe_activatable()
.map(|a| a.synthetic_click_activation(false, false, false, false));
synthetic_click_activation(self.upcast::<Element>(),
false,
false,
false,
false,
ActivationSource::NotFromClick);
}
// https://html.spec.whatwg.org/multipage/#implicit-submission

View file

@ -15,6 +15,10 @@ skip: true
skip: false
[html]
skip: false
[editing]
skip: true
[activation]
skip: false
[url]
skip: false
[touch-events]

View file

@ -1,5 +0,0 @@
[throwing-in-listener-when-all-have-not-run-yet.html]
type: testharness
[Throwing in event listener]
expected: FAIL

View file

@ -1 +0,0 @@
disabled: for now