Experimental implementation of (a small subset of) mozbrowser APIs.

This commit is contained in:
Glenn Watson 2015-03-19 15:40:04 +10:00
parent fef439726a
commit bf9b8f7050
10 changed files with 393 additions and 40 deletions

View file

@ -379,6 +379,16 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
debug!("constellation got get-pipeline-title message");
self.handle_get_pipeline_title_msg(pipeline_id);
}
ConstellationMsg::MozBrowserEvent(pipeline_id,
subpage_id,
event_name,
event_detail) => {
debug!("constellation got mozbrowser event message");
self.handle_mozbrowser_event_msg(pipeline_id,
subpage_id,
event_name,
event_detail);
}
}
true
}
@ -640,6 +650,24 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
}
}
fn handle_mozbrowser_event_msg(&mut self,
pipeline_id: PipelineId,
subpage_id: SubpageId,
event_name: String,
event_detail: Option<String>) {
assert!(opts::experimental_enabled());
// Find the script channel for the given parent pipeline,
// and pass the event to that script task.
let pipeline = self.pipeline(pipeline_id);
let ScriptControlChan(ref script_channel) = pipeline.script_chan;
let event = ConstellationControlMsg::MozBrowserEvent(pipeline_id,
subpage_id,
event_name,
event_detail);
script_channel.send(event).unwrap();
}
fn add_or_replace_pipeline_in_frame_tree(&mut self, frame_change: FrameChange) {
let evicted_frames = match frame_change.old_pipeline_id {
Some(old_pipeline_id) => {

View file

@ -84,6 +84,7 @@ impl Pipeline {
let (script_chan, script_port) = channel();
ScriptTaskFactory::create(None::<&mut STF>,
id,
parent_info,
compositor_proxy.clone_compositor_proxy(),
&layout_pair,
ScriptControlChan(script_chan.clone()),

View file

@ -212,6 +212,8 @@ pub enum Msg {
GetPipelineTitle(PipelineId),
/// Requests that the constellation inform the compositor of the a cursor change.
SetCursor(Cursor),
/// Dispatch a mozbrowser event to a given iframe. Only available in experimental mode.
MozBrowserEvent(PipelineId, SubpageId, String, Option<String>),
}
/// Similar to net::resource_task::LoadData

View file

@ -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};
@ -1434,7 +1435,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);
}
}

View file

@ -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> {

View 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);
};

View file

@ -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;

View file

@ -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,

View file

@ -24,6 +24,7 @@ use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, Documen
use dom::bindings::codegen::InheritTypes::{ElementCast, EventTargetCast, HTMLIFrameElementCast, NodeCast, EventCast};
use dom::bindings::conversions::FromJSValConvertible;
use dom::bindings::conversions::StringificationBehavior;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, RootedReference};
use dom::bindings::js::{RootCollection, RootCollectionPtr};
use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference};
@ -116,7 +117,7 @@ struct InProgressLoad {
/// The pipeline which requested this load.
pipeline_id: PipelineId,
/// The parent pipeline and child subpage associated with this load, if any.
subpage_id: Option<(PipelineId, SubpageId)>,
parent_info: Option<(PipelineId, SubpageId)>,
/// The current window size associated with this pipeline.
window_size: Option<WindowSizeData>,
/// Channel to the layout task associated with this pipeline.
@ -130,13 +131,13 @@ struct InProgressLoad {
impl InProgressLoad {
/// Create a new InProgressLoad object.
fn new(id: PipelineId,
subpage_id: Option<(PipelineId, SubpageId)>,
parent_info: Option<(PipelineId, SubpageId)>,
layout_chan: LayoutChan,
window_size: Option<WindowSizeData>,
url: Url) -> InProgressLoad {
InProgressLoad {
pipeline_id: id,
subpage_id: subpage_id,
parent_info: parent_info,
layout_chan: layout_chan,
window_size: window_size,
clip_rect: None,
@ -332,6 +333,7 @@ impl ScriptTaskFactory for ScriptTask {
fn create<C>(_phantom: Option<&mut ScriptTask>,
id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>,
compositor: C,
layout_chan: &OpaqueScriptLayoutChannel,
control_chan: ScriptControlChan,
@ -365,7 +367,7 @@ impl ScriptTaskFactory for ScriptTask {
});
let mut failsafe = ScriptMemoryFailsafe::new(&script_task);
let new_load = InProgressLoad::new(id, None, layout_chan, window_size,
let new_load = InProgressLoad::new(id, parent_info, layout_chan, window_size,
load_data.url.clone());
script_task.start_page_load(new_load, load_data);
@ -641,7 +643,15 @@ impl ScriptTask {
ConstellationControlMsg::Freeze(pipeline_id) =>
self.handle_freeze_msg(pipeline_id),
ConstellationControlMsg::Thaw(pipeline_id) =>
self.handle_thaw_msg(pipeline_id)
self.handle_thaw_msg(pipeline_id),
ConstellationControlMsg::MozBrowserEvent(parent_pipeline_id,
subpage_id,
event_name,
event_detail) =>
self.handle_mozbrowser_event_msg(parent_pipeline_id,
subpage_id,
event_name,
event_detail),
}
}
@ -783,6 +793,30 @@ impl ScriptTask {
window.r().thaw();
}
/// Handles a mozbrowser event, for example see:
/// https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadstart
fn handle_mozbrowser_event_msg(&self,
parent_pipeline_id: PipelineId,
subpage_id: SubpageId,
event_name: String,
event_detail: Option<String>) {
let borrowed_page = self.root_page();
let frame_element = borrowed_page.find(parent_pipeline_id).and_then(|page| {
let doc = page.document().root();
let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
doc.traverse_preorder()
.filter_map(HTMLIFrameElementCast::to_ref)
.find(|node| node.subpage_id() == Some(subpage_id))
.map(Temporary::from_rooted)
}).root();
if let Some(frame_element) = frame_element {
frame_element.r().dispatch_mozbrowser_event(event_name, event_detail);
}
}
/// Handles a notification that reflow completed.
fn handle_reflow_complete_msg(&self, pipeline_id: PipelineId, reflow_id: uint) {
debug!("Script: Reflow {:?} complete for {:?}", reflow_id, pipeline_id);
@ -832,7 +866,7 @@ impl ScriptTask {
response: LoadResponse) {
// Any notification received should refer to an existing, in-progress load that is tracked.
let idx = self.incomplete_loads.borrow().iter().position(|load| {
load.pipeline_id == id && load.subpage_id.map(|sub| sub.1) == subpage
load.pipeline_id == id && load.parent_info.map(|info| info.1) == subpage
}).unwrap();
let load = self.incomplete_loads.borrow_mut().remove(idx);
self.load(response, load);
@ -876,10 +910,12 @@ impl ScriptTask {
// We should either be initializing a root page or loading a child page of an
// existing one.
let root_page_exists = self.page.borrow().is_some();
assert!(incomplete.subpage_id.is_none() || root_page_exists);
let frame_element = incomplete.subpage_id.and_then(|(parent_id, subpage_id)| {
let borrowed_page = self.root_page();
let frame_element = incomplete.parent_info.and_then(|(parent_id, subpage_id)| {
// The root page may not exist yet, if the parent of this frame
// exists in a different script task.
let borrowed_page = self.page.borrow();
// In the case a parent id exists but the matching page
// cannot be found, this means the page exists in a different
// script task (due to origin) so it shouldn't be returned.
@ -887,6 +923,7 @@ impl ScriptTask {
// case, which is wrong. We should be returning an object that
// denies access to most properties (per
// https://github.com/servo/servo/issues/3939#issuecomment-62287025).
borrowed_page.as_ref().and_then(|borrowed_page| {
borrowed_page.find(parent_id).and_then(|page| {
let doc = page.document().root();
let doc: JSRef<Node> = NodeCast::from_ref(doc.r());
@ -897,6 +934,7 @@ impl ScriptTask {
.map(ElementCast::from_ref)
.map(Temporary::from_rooted)
})
})
}).root();
self.compositor.borrow_mut().set_ready_state(incomplete.pipeline_id, Loading);
@ -909,9 +947,11 @@ impl ScriptTask {
if !root_page_exists {
// We have a new root frame tree.
*self.page.borrow_mut() = Some(page.clone());
} else if let Some((parent, _)) = incomplete.subpage_id {
} else if let Some((parent, _)) = incomplete.parent_info {
// We have a new child frame.
let parent_page = self.root_page();
// TODO(gw): This find will fail when we are sharing script tasks
// between cross origin iframes in the same TLD.
parent_page.find(parent).expect("received load for subpage with missing parent");
parent_page.children.borrow_mut().push(page.clone());
}
@ -972,7 +1012,7 @@ impl ScriptTask {
self.constellation_chan.clone(),
incomplete.layout_chan,
incomplete.pipeline_id,
incomplete.subpage_id.map(|s| s.1),
incomplete.parent_info,
incomplete.window_size).root();
let last_modified: Option<DOMString> = response.metadata.headers.as_ref().and_then(|headers| {
@ -1219,7 +1259,7 @@ impl ScriptTask {
/// argument until a notification is received that the fetch is complete.
fn start_page_load(&self, incomplete: InProgressLoad, mut load_data: LoadData) {
let id = incomplete.pipeline_id.clone();
let subpage = incomplete.subpage_id.clone().map(|p| p.1);
let subpage = incomplete.parent_info.clone().map(|p| p.1);
let script_chan = self.chan.clone();
let resource_task = self.resource_task.clone();

View file

@ -72,6 +72,8 @@ pub enum ConstellationControlMsg {
Thaw(PipelineId),
/// Notifies script task that a url should be loaded in this iframe.
Navigate(PipelineId, SubpageId, LoadData),
/// Requests the script task forward a mozbrowser event to an iframe it owns
MozBrowserEvent(PipelineId, SubpageId, String, Option<String>),
}
unsafe impl Send for ConstellationControlMsg {
@ -99,6 +101,7 @@ pub struct ScriptControlChan(pub Sender<ConstellationControlMsg>);
pub trait ScriptTaskFactory {
fn create<C>(_phantom: Option<&mut Self>,
id: PipelineId,
parent_info: Option<(PipelineId, SubpageId)>,
compositor: C,
layout_chan: &OpaqueScriptLayoutChannel,
control_chan: ScriptControlChan,