Allow window elements as well as iframes to the the target of mozbrowser events.

This commit is contained in:
Alan Jeffrey 2016-07-12 19:59:04 -05:00
parent fa432a5a34
commit 72aa4f2f62
8 changed files with 162 additions and 152 deletions

View file

@ -1281,7 +1281,7 @@ impl Document {
if PREFS.is_mozbrowser_enabled() {
if let Some((containing_pipeline_id, subpage_id, _)) = self.window.parent_info() {
let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id,
subpage_id,
Some(subpage_id),
event);
self.window.constellation_chan().send(event).unwrap();
}

View file

@ -161,25 +161,11 @@ impl HTMLIFrameElement {
#[allow(unsafe_code)]
pub fn dispatch_mozbrowser_event(&self, event: MozBrowserEvent) {
// TODO(gw): Support mozbrowser event types that have detail which is not a string.
// See https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API
// for a list of mozbrowser events.
assert!(PREFS.is_mozbrowser_enabled());
if self.Mozbrowser() {
let window = window_from_node(self);
let custom_event = unsafe {
let cx = window.get_cx();
let _ac = JSAutoCompartment::new(cx, window.reflector().get_jsobject().get());
rooted!(in(cx) let mut detail = UndefinedValue());
let event_name = Atom::from(event.name());
self.build_mozbrowser_event_detail(event, cx, detail.handle_mut());
CustomEvent::new(GlobalRef::Window(window.r()),
event_name,
true,
true,
detail.handle())
};
let custom_event = build_mozbrowser_custom_event(&window, event);
custom_event.upcast::<Event>().fire(self.upcast());
}
}
@ -336,97 +322,104 @@ impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
}
}
pub trait MozBrowserEventDetailBuilder {
#[allow(unsafe_code)]
unsafe fn build_mozbrowser_event_detail(&self,
event: MozBrowserEvent,
cx: *mut JSContext,
rval: MutableHandleValue);
#[allow(unsafe_code)]
pub fn build_mozbrowser_custom_event(window: &Window, event: MozBrowserEvent) -> Root<CustomEvent> {
// TODO(gw): Support mozbrowser event types that have detail which is not a string.
// See https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API
// for a list of mozbrowser events.
let cx = window.get_cx();
let _ac = JSAutoCompartment::new(cx, window.reflector().get_jsobject().get());
rooted!(in(cx) let mut detail = UndefinedValue());
let event_name = Atom::from(event.name());
unsafe { build_mozbrowser_event_detail(event, cx, detail.handle_mut()); }
CustomEvent::new(GlobalRef::Window(window),
event_name,
true,
true,
detail.handle())
}
impl MozBrowserEventDetailBuilder for HTMLIFrameElement {
#[allow(unsafe_code)]
unsafe fn build_mozbrowser_event_detail(&self,
event: MozBrowserEvent,
cx: *mut JSContext,
rval: MutableHandleValue) {
match event {
MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
MozBrowserEvent::LoadEnd | MozBrowserEvent::LoadStart |
MozBrowserEvent::Connected | MozBrowserEvent::OpenSearch |
MozBrowserEvent::UsernameAndPasswordRequired => {
rval.set(NullValue());
}
MozBrowserEvent::Error(error_type, description, report) => {
BrowserElementErrorEventDetail {
type_: Some(DOMString::from(error_type.name())),
description: description.map(DOMString::from),
report: report.map(DOMString::from),
version: Some(DOMString::from_string(servo_version().into())),
}.to_jsval(cx, rval);
},
MozBrowserEvent::SecurityChange(https_state) => {
BrowserElementSecurityChangeDetail {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsersecuritychange
state: Some(DOMString::from(match https_state {
HttpsState::Modern => "secure",
HttpsState::Deprecated => "broken",
HttpsState::None => "insecure",
}.to_owned())),
// FIXME - Not supported yet:
trackingContent: None,
mixedContent: None,
trackingState: None,
extendedValidation: None,
mixedState: None,
}.to_jsval(cx, rval);
}
MozBrowserEvent::TitleChange(ref string) => {
string.to_jsval(cx, rval);
}
MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward) => {
BrowserElementLocationChangeEventDetail {
url: Some(DOMString::from(url)),
canGoBack: Some(can_go_back),
canGoForward: Some(can_go_forward),
}.to_jsval(cx, rval);
}
MozBrowserEvent::OpenTab(url) => {
BrowserElementOpenTabEventDetail {
url: Some(DOMString::from(url)),
}.to_jsval(cx, rval);
}
MozBrowserEvent::OpenWindow(url, target, features) => {
BrowserElementOpenWindowEventDetail {
url: Some(DOMString::from(url)),
target: target.map(DOMString::from),
features: features.map(DOMString::from),
}.to_jsval(cx, rval);
}
MozBrowserEvent::IconChange(rel, href, sizes) => {
BrowserElementIconChangeEventDetail {
rel: Some(DOMString::from(rel)),
href: Some(DOMString::from(href)),
sizes: Some(DOMString::from(sizes)),
}.to_jsval(cx, rval);
}
MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value) => {
BrowserShowModalPromptEventDetail {
promptType: Some(DOMString::from(prompt_type)),
title: Some(DOMString::from(title)),
message: Some(DOMString::from(message)),
returnValue: Some(DOMString::from(return_value)),
}.to_jsval(cx, rval)
}
MozBrowserEvent::VisibilityChange(visibility) => {
BrowserElementVisibilityChangeEventDetail {
visible: Some(visibility),
}.to_jsval(cx, rval);
}
#[allow(unsafe_code)]
unsafe fn build_mozbrowser_event_detail(event: MozBrowserEvent,
cx: *mut JSContext,
rval: MutableHandleValue) {
match event {
MozBrowserEvent::AsyncScroll | MozBrowserEvent::Close | MozBrowserEvent::ContextMenu |
MozBrowserEvent::LoadEnd | MozBrowserEvent::LoadStart |
MozBrowserEvent::Connected | MozBrowserEvent::OpenSearch |
MozBrowserEvent::UsernameAndPasswordRequired => {
rval.set(NullValue());
}
MozBrowserEvent::Error(error_type, description, report) => {
BrowserElementErrorEventDetail {
type_: Some(DOMString::from(error_type.name())),
description: description.map(DOMString::from),
report: report.map(DOMString::from),
version: Some(DOMString::from_string(servo_version().into())),
}.to_jsval(cx, rval);
},
MozBrowserEvent::SecurityChange(https_state) => {
BrowserElementSecurityChangeDetail {
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowsersecuritychange
state: Some(DOMString::from(match https_state {
HttpsState::Modern => "secure",
HttpsState::Deprecated => "broken",
HttpsState::None => "insecure",
}.to_owned())),
// FIXME - Not supported yet:
trackingContent: None,
mixedContent: None,
trackingState: None,
extendedValidation: None,
mixedState: None,
}.to_jsval(cx, rval);
}
MozBrowserEvent::TitleChange(ref string) => {
string.to_jsval(cx, rval);
}
MozBrowserEvent::LocationChange(url, can_go_back, can_go_forward) => {
BrowserElementLocationChangeEventDetail {
url: Some(DOMString::from(url)),
canGoBack: Some(can_go_back),
canGoForward: Some(can_go_forward),
}.to_jsval(cx, rval);
}
MozBrowserEvent::OpenTab(url) => {
BrowserElementOpenTabEventDetail {
url: Some(DOMString::from(url)),
}.to_jsval(cx, rval);
}
MozBrowserEvent::OpenWindow(url, target, features) => {
BrowserElementOpenWindowEventDetail {
url: Some(DOMString::from(url)),
target: target.map(DOMString::from),
features: features.map(DOMString::from),
}.to_jsval(cx, rval);
}
MozBrowserEvent::IconChange(rel, href, sizes) => {
BrowserElementIconChangeEventDetail {
rel: Some(DOMString::from(rel)),
href: Some(DOMString::from(href)),
sizes: Some(DOMString::from(sizes)),
}.to_jsval(cx, rval);
}
MozBrowserEvent::ShowModalPrompt(prompt_type, title, message, return_value) => {
BrowserShowModalPromptEventDetail {
promptType: Some(DOMString::from(prompt_type)),
title: Some(DOMString::from(title)),
message: Some(DOMString::from(message)),
returnValue: Some(DOMString::from(return_value)),
}.to_jsval(cx, rval)
}
MozBrowserEvent::VisibilityChange(visibility) => {
BrowserElementVisibilityChangeEventDetail {
visible: Some(visibility),
}.to_jsval(cx, rval);
}
}
}
pub fn Navigate(iframe: &HTMLIFrameElement, direction: NavigationDirection) -> ErrorResult {
if iframe.Mozbrowser() {
if iframe.upcast::<Node>().is_in_doc() {

View file

@ -28,7 +28,9 @@ use dom::crypto::Crypto;
use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration};
use dom::document::Document;
use dom::element::Element;
use dom::event::Event;
use dom::eventtarget::EventTarget;
use dom::htmliframeelement::build_mozbrowser_custom_event;
use dom::location::Location;
use dom::navigator::Navigator;
use dom::node::{Node, from_untrusted_node_address, window_from_node};
@ -63,7 +65,7 @@ use script_runtime::{ScriptChan, ScriptPort, maybe_take_panic_result};
use script_thread::SendableMainThreadScriptChan;
use script_thread::{MainThreadScriptChan, MainThreadScriptMsg, RunnableWrapper};
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use script_traits::{ConstellationControlMsg, UntrustedNodeAddress};
use script_traits::{ConstellationControlMsg, MozBrowserEvent, UntrustedNodeAddress};
use script_traits::{DocumentState, MsDuration, TimerEvent, TimerEventId};
use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, TimerSource, WindowSizeData};
use std::ascii::AsciiExt;
@ -1594,6 +1596,13 @@ impl Window {
_ => false,
}
}
#[allow(unsafe_code)]
pub fn dispatch_mozbrowser_event(&self, event: MozBrowserEvent) {
assert!(PREFS.is_mozbrowser_enabled());
let custom_event = build_mozbrowser_custom_event(&self, event);
custom_event.upcast::<Event>().fire(self.upcast());
}
}
impl Window {

View file

@ -1383,17 +1383,17 @@ impl ScriptThread {
/// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
fn handle_mozbrowser_event_msg(&self,
parent_pipeline_id: PipelineId,
subpage_id: SubpageId,
subpage_id: Option<SubpageId>,
event: MozBrowserEvent) {
let borrowed_context = self.root_browsing_context();
let frame_element = borrowed_context.find(parent_pipeline_id).and_then(|context| {
let doc = context.active_document();
doc.find_iframe(subpage_id)
});
if let Some(ref frame_element) = frame_element {
frame_element.dispatch_mozbrowser_event(event);
match self.root_browsing_context().find(parent_pipeline_id) {
None => warn!("Mozbrowser event after pipeline {:?} closed.", parent_pipeline_id),
Some(context) => match subpage_id {
None => context.active_window().dispatch_mozbrowser_event(event),
Some(subpage_id) => match context.active_document().find_iframe(subpage_id) {
None => warn!("Mozbrowser event after iframe {:?}/{:?} closed.", parent_pipeline_id, subpage_id),
Some(frame_element) => frame_element.dispatch_mozbrowser_event(event),
},
},
}
}