mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
auto merge of #5281 : glennw/servo/mozbrowser, r=jdm
This commit is contained in:
commit
1f682d878d
10 changed files with 393 additions and 40 deletions
|
@ -60,13 +60,14 @@ use dom::window::{Window, WindowHelpers, ReflowReason};
|
|||
|
||||
use layout_interface::{HitTestResponse, MouseOverResponse};
|
||||
use msg::compositor_msg::ScriptListener;
|
||||
use msg::constellation_msg::{Key, KeyState, KeyModifiers};
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use msg::constellation_msg::{ConstellationChan, Key, KeyState, KeyModifiers};
|
||||
use msg::constellation_msg::{SUPER, ALT, SHIFT, CONTROL};
|
||||
use net::resource_task::ControlMsg::{SetCookiesForUrl, GetCookiesForUrl};
|
||||
use net::cookie_storage::CookieSource::NonHTTP;
|
||||
use script_task::Runnable;
|
||||
use script_traits::UntrustedNodeAddress;
|
||||
use util::namespace;
|
||||
use util::{opts, namespace};
|
||||
use util::str::{DOMString, split_html_space_chars};
|
||||
use layout_interface::{ReflowGoal, ReflowQueryType};
|
||||
|
||||
|
@ -1450,7 +1451,23 @@ impl DocumentProgressHandler {
|
|||
event.r().fire(target);
|
||||
});
|
||||
|
||||
window_ref.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::DocumentLoaded);
|
||||
if opts::experimental_enabled() {
|
||||
// If this is a child frame, and experimental mode is enabled,
|
||||
// send the mozbrowserloadend event. For details, see
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadend
|
||||
if let Some((containing_pipeline_id, subpage_id)) = window_ref.parent_info() {
|
||||
let ConstellationChan(ref chan) = window_ref.constellation_chan();
|
||||
let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id,
|
||||
subpage_id,
|
||||
"mozbrowserloadend".to_owned(),
|
||||
None);
|
||||
chan.send(event);
|
||||
}
|
||||
}
|
||||
|
||||
window_ref.reflow(ReflowGoal::ForDisplay,
|
||||
ReflowQueryType::NoQuery,
|
||||
ReflowReason::DocumentLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,12 +8,18 @@ use dom::attr::AttrHelpers;
|
|||
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
|
||||
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
|
||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast};
|
||||
use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLIFrameElementDerived};
|
||||
use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventCast};
|
||||
use dom::bindings::codegen::InheritTypes::{EventTargetCast, HTMLElementCast, HTMLIFrameElementDerived};
|
||||
use dom::bindings::conversions::ToJSValConvertible;
|
||||
use dom::bindings::error::{ErrorResult, Fallible};
|
||||
use dom::bindings::error::Error::NotSupported;
|
||||
use dom::bindings::global::GlobalRef;
|
||||
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
|
||||
use dom::customevent::CustomEvent;
|
||||
use dom::document::Document;
|
||||
use dom::element::Element;
|
||||
use dom::element::AttributeHandlers;
|
||||
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
|
||||
use dom::eventtarget::{EventTarget, EventTargetTypeId};
|
||||
use dom::element::ElementTypeId;
|
||||
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
|
||||
|
@ -23,13 +29,15 @@ use dom::virtualmethods::VirtualMethods;
|
|||
use dom::window::{Window, WindowHelpers};
|
||||
use page::IterablePage;
|
||||
|
||||
use msg::constellation_msg::{PipelineId, SubpageId, ConstellationChan};
|
||||
use msg::constellation_msg::{PipelineId, SubpageId, ConstellationChan, NavigationDirection};
|
||||
use msg::constellation_msg::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
|
||||
use msg::constellation_msg::Msg as ConstellationMsg;
|
||||
use util::opts;
|
||||
use util::str::DOMString;
|
||||
use string_cache::Atom;
|
||||
|
||||
use std::ascii::AsciiExt;
|
||||
use std::borrow::ToOwned;
|
||||
use std::cell::Cell;
|
||||
use url::{Url, UrlParser};
|
||||
|
||||
|
@ -64,6 +72,7 @@ pub trait HTMLIFrameElementHelpers {
|
|||
fn process_the_iframe_attributes(self);
|
||||
fn generate_new_subpage_id(self) -> (SubpageId, Option<SubpageId>);
|
||||
fn navigate_child_browsing_context(self, url: Url);
|
||||
fn dispatch_mozbrowser_event(self, event_name: String, event_detail: Option<String>);
|
||||
}
|
||||
|
||||
impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
||||
|
@ -112,6 +121,11 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
|||
new_subpage_id,
|
||||
old_subpage_id,
|
||||
sandboxed)).unwrap();
|
||||
|
||||
if opts::experimental_enabled() {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
|
||||
self.dispatch_mozbrowser_event("mozbrowserloadstart".to_owned(), None);
|
||||
}
|
||||
}
|
||||
|
||||
fn process_the_iframe_attributes(self) {
|
||||
|
@ -122,6 +136,26 @@ impl<'a> HTMLIFrameElementHelpers for JSRef<'a, HTMLIFrameElement> {
|
|||
|
||||
self.navigate_child_browsing_context(url);
|
||||
}
|
||||
|
||||
fn dispatch_mozbrowser_event(self, event_name: String, event_detail: Option<String>) {
|
||||
// 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!(opts::experimental_enabled());
|
||||
|
||||
if self.Mozbrowser() {
|
||||
let window = window_from_node(self).root();
|
||||
let cx = window.r().get_cx();
|
||||
let custom_event = CustomEvent::new(GlobalRef::Window(window.r()),
|
||||
event_name.to_owned(),
|
||||
true,
|
||||
true,
|
||||
event_detail.to_jsval(cx)).root();
|
||||
let target: JSRef<EventTarget> = EventTargetCast::from_ref(self);
|
||||
let event: JSRef<Event> = EventCast::from_ref(custom_event.r());
|
||||
event.fire(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HTMLIFrameElement {
|
||||
|
@ -199,6 +233,85 @@ impl<'a> HTMLIFrameElementMethods for JSRef<'a, HTMLIFrameElement> {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Experimental mozbrowser implementation is based on the webidl
|
||||
// present in the gecko source tree, and the documentation here:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Using_the_Browser_API
|
||||
|
||||
// TODO(gw): Use experimental codegen when it is available to avoid
|
||||
// exposing these APIs. See https://github.com/servo/servo/issues/5264.
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-mozbrowser
|
||||
fn Mozbrowser(self) -> bool {
|
||||
if opts::experimental_enabled() {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.has_attribute(&Atom::from_slice("mozbrowser"))
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn SetMozbrowser(self, value: bool) -> ErrorResult {
|
||||
if opts::experimental_enabled() {
|
||||
let element: JSRef<Element> = ElementCast::from_ref(self);
|
||||
element.set_bool_attribute(&Atom::from_slice("mozbrowser"), value);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goBack
|
||||
fn GoBack(self) -> Fallible<()> {
|
||||
if self.Mozbrowser() {
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.is_in_doc() {
|
||||
let window = window_from_node(self).root();
|
||||
let window = window.r();
|
||||
|
||||
let pipeline_info = Some((self.containing_page_pipeline_id().unwrap(),
|
||||
self.subpage_id().unwrap()));
|
||||
let ConstellationChan(ref chan) = window.constellation_chan();
|
||||
let msg = ConstellationMsg::Navigate(pipeline_info, NavigationDirection::Back);
|
||||
chan.send(msg).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
debug!("this frame is not mozbrowser (or experimental_enabled is false)");
|
||||
Err(NotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/goForward
|
||||
fn GoForward(self) -> Fallible<()> {
|
||||
if self.Mozbrowser() {
|
||||
let node: JSRef<Node> = NodeCast::from_ref(self);
|
||||
if node.is_in_doc() {
|
||||
let window = window_from_node(self).root();
|
||||
let window = window.r();
|
||||
|
||||
let pipeline_info = Some((self.containing_page_pipeline_id().unwrap(),
|
||||
self.subpage_id().unwrap()));
|
||||
let ConstellationChan(ref chan) = window.constellation_chan();
|
||||
let msg = ConstellationMsg::Navigate(pipeline_info, NavigationDirection::Forward);
|
||||
chan.send(msg).unwrap();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
debug!("this frame is not mozbrowser (or experimental_enabled is false)");
|
||||
Err(NotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/reload
|
||||
fn Reload(self, _hardReload: bool) -> Fallible<()> {
|
||||
Err(NotSupported)
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLIFrameElement/stop
|
||||
fn Stop(self) -> Fallible<()> {
|
||||
Err(NotSupported)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> VirtualMethods for JSRef<'a, HTMLIFrameElement> {
|
||||
|
|
138
components/script/dom/webidls/BrowserElement.webidl
Normal file
138
components/script/dom/webidls/BrowserElement.webidl
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
//callback BrowserElementNextPaintEventCallback = void ();
|
||||
|
||||
//dictionary BrowserElementDownloadOptions {
|
||||
// DOMString? filename;
|
||||
//};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface BrowserElement {
|
||||
};
|
||||
|
||||
BrowserElement implements BrowserElementCommon;
|
||||
BrowserElement implements BrowserElementPrivileged;
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface BrowserElementCommon {
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser embed-widgets"]
|
||||
//void setVisible(boolean visible);
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser embed-widgets"]
|
||||
//DOMRequest getVisible();
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser embed-widgets"]
|
||||
//void addNextPaintListener(BrowserElementNextPaintEventCallback listener);
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser embed-widgets"]
|
||||
//void removeNextPaintListener(BrowserElementNextPaintEventCallback listener);
|
||||
};
|
||||
|
||||
[NoInterfaceObject]
|
||||
interface BrowserElementPrivileged {
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//void sendMouseEvent(DOMString type,
|
||||
// unsigned long x,
|
||||
// unsigned long y,
|
||||
// unsigned long button,
|
||||
// unsigned long clickCount,
|
||||
// unsigned long modifiers);
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// Func="TouchEvent::PrefEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//void sendTouchEvent(DOMString type,
|
||||
// sequence<unsigned long> identifiers,
|
||||
// sequence<long> x,
|
||||
// sequence<long> y,
|
||||
// sequence<unsigned long> rx,
|
||||
// sequence<unsigned long> ry,
|
||||
// sequence<float> rotationAngles,
|
||||
// sequence<float> forces,
|
||||
// unsigned long count,
|
||||
// unsigned long modifiers);
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void goBack();
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void goForward();
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void reload(optional boolean hardReload = false);
|
||||
|
||||
[Throws,
|
||||
Pref="dom.mozBrowserFramesEnabled",
|
||||
CheckPermissions="browser"]
|
||||
void stop();
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest download(DOMString url,
|
||||
// optional BrowserElementDownloadOptions options);
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest purgeHistory();
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest getScreenshot([EnforceRange] unsigned long width,
|
||||
// [EnforceRange] unsigned long height,
|
||||
// optional DOMString mimeType="");
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//void zoom(float zoom);
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest getCanGoBack();
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest getCanGoForward();
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest getContentDimensions();
|
||||
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//DOMRequest setInputMethodActive(boolean isActive);
|
||||
|
||||
// Additional |nfc-manager| permission is required for setNFCFocus API
|
||||
//[Throws,
|
||||
// Pref="dom.mozBrowserFramesEnabled",
|
||||
// CheckPermissions="browser"]
|
||||
//void setNFCFocus(boolean isFocus);
|
||||
};
|
|
@ -31,3 +31,10 @@ partial interface HTMLIFrameElement {
|
|||
//[TreatNullAs=EmptyString] attribute DOMString marginHeight;
|
||||
//[TreatNullAs=EmptyString] attribute DOMString marginWidth;
|
||||
};
|
||||
|
||||
partial interface HTMLIFrameElement {
|
||||
[ChromeOnly,SetterThrows]
|
||||
attribute boolean mozbrowser;
|
||||
};
|
||||
|
||||
HTMLIFrameElement implements BrowserElement;
|
||||
|
|
|
@ -114,7 +114,7 @@ pub struct Window {
|
|||
id: PipelineId,
|
||||
|
||||
/// Subpage id associated with this page, if any.
|
||||
subpage_id: Option<SubpageId>,
|
||||
parent_info: Option<(PipelineId, SubpageId)>,
|
||||
|
||||
/// Unique id for last reflow request; used for confirming completion reply.
|
||||
last_reflow_id: Cell<uint>,
|
||||
|
@ -164,11 +164,15 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn pipeline(&self) -> PipelineId {
|
||||
self.id.clone()
|
||||
self.id
|
||||
}
|
||||
|
||||
pub fn subpage(&self) -> Option<SubpageId> {
|
||||
self.subpage_id.clone()
|
||||
self.parent_info.map(|p| p.1)
|
||||
}
|
||||
|
||||
pub fn parent_info(&self) -> Option<(PipelineId, SubpageId)> {
|
||||
self.parent_info
|
||||
}
|
||||
|
||||
pub fn control_chan<'a>(&'a self) -> &'a ScriptControlChan {
|
||||
|
@ -549,7 +553,7 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
|||
let reflow = box Reflow {
|
||||
document_root: root.to_trusted_node_address(),
|
||||
url: self.get_url(),
|
||||
iframe: self.subpage_id.is_some(),
|
||||
iframe: self.parent_info.is_some(),
|
||||
goal: goal,
|
||||
window_size: window_size,
|
||||
script_chan: self.control_chan.clone(),
|
||||
|
@ -768,7 +772,7 @@ impl Window {
|
|||
constellation_chan: ConstellationChan,
|
||||
layout_chan: LayoutChan,
|
||||
id: PipelineId,
|
||||
subpage_id: Option<SubpageId>,
|
||||
parent_info: Option<(PipelineId, SubpageId)>,
|
||||
window_size: Option<WindowSizeData>)
|
||||
-> Temporary<Window> {
|
||||
let layout_rpc: Box<LayoutRPC> = {
|
||||
|
@ -797,7 +801,7 @@ impl Window {
|
|||
local_storage: Default::default(),
|
||||
timers: TimerManager::new(),
|
||||
id: id,
|
||||
subpage_id: subpage_id,
|
||||
parent_info: parent_info,
|
||||
dom_static: GlobalStaticData::new(),
|
||||
js_context: DOMRefCell::new(Some(js_context.clone())),
|
||||
resource_task: resource_task,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue