Auto merge of #8449 - paulrouget:favicon, r=jdm

mozbrowsericonchange event (Browser API)

fixes #8347

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/8449)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-11-14 19:54:03 +05:30
commit 7f076c628b
8 changed files with 154 additions and 25 deletions

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use dom::attr::{Attr, AttrValue};
use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementIconChangeEventDetail;
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding;
use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding::HTMLIFrameElementMethods;
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
@ -21,8 +22,8 @@ use dom::node::{Node, window_from_node};
use dom::urlhelper::UrlHelper;
use dom::virtualmethods::VirtualMethods;
use dom::window::Window;
use js::jsapi::{JSAutoCompartment, JSAutoRequest, RootedValue};
use js::jsval::UndefinedValue;
use js::jsapi::{JSAutoCompartment, JSAutoRequest, RootedValue, JSContext, MutableHandleValue};
use js::jsval::{UndefinedValue, NullValue};
use msg::constellation_msg::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, IframeLoadInfo, MozBrowserEvent};
@ -143,9 +144,10 @@ impl HTMLIFrameElement {
let _ar = JSAutoRequest::new(cx);
let _ac = JSAutoCompartment::new(cx, window.reflector().get_jsobject().get());
let mut detail = RootedValue::new(cx, UndefinedValue());
event.detail().to_jsval(cx, detail.handle_mut());
let event_name = DOMString::from(event.name().to_owned());
self.build_mozbrowser_event_detail(event, cx, detail.handle_mut());
CustomEvent::new(GlobalRef::Window(window.r()),
DOMString::from(event.name()),
event_name,
true,
true,
detail.handle())
@ -225,6 +227,41 @@ 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);
}
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::Error | MozBrowserEvent::LoadEnd | MozBrowserEvent::LoadStart |
MozBrowserEvent::OpenWindow | MozBrowserEvent::SecurityChange | MozBrowserEvent::OpenSearch |
MozBrowserEvent::ShowModalPrompt | MozBrowserEvent::UsernameAndPasswordRequired => {
rval.set(NullValue());
}
MozBrowserEvent::LocationChange(ref string) | MozBrowserEvent::TitleChange(ref string) => {
string.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);
}
}
}
}
pub fn Navigate(iframe: &HTMLIFrameElement, direction: NavigationDirection) -> Fallible<()> {
if iframe.Mozbrowser() {
if iframe.upcast::<Node>().is_in_doc() {

View file

@ -24,8 +24,8 @@ use encoding::all::UTF_8;
use ipc_channel::ipc;
use ipc_channel::router::ROUTER;
use layout_interface::{LayoutChan, Msg};
use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg;
use msg::constellation_msg::{ConstellationChan, MozBrowserEvent};
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata};
use network_listener::{NetworkListener, PreInvoke};
use std::ascii::AsciiExt;
@ -102,7 +102,7 @@ fn is_favicon(value: &Option<String>) -> bool {
match *value {
Some(ref value) => {
value.split(HTML_SPACE_CHARACTERS)
.any(|s| s.eq_ignore_ascii_case("icon"))
.any(|s| s.eq_ignore_ascii_case("icon") || s.eq_ignore_ascii_case("apple-touch-icon"))
},
None => false,
}
@ -118,13 +118,23 @@ impl VirtualMethods for HTMLLinkElement {
if !self.upcast::<Node>().is_in_doc() || mutation == AttributeMutation::Removed {
return;
}
let sizes_atom = &Atom::from_slice("sizes");
let rel = get_attr(self.upcast(), &atom!(rel));
match attr.local_name() {
&atom!(href) => {
if string_is_stylesheet(&rel) {
self.handle_stylesheet_url(&attr.value());
} else if is_favicon(&rel) {
self.handle_favicon_url(&attr.value());
let sizes = get_attr(self.upcast(), sizes_atom);
self.handle_favicon_url(rel.as_ref().unwrap(), &attr.value(), &sizes);
}
},
atom if atom == sizes_atom => {
if is_favicon(&rel) {
if let Some(ref href) = get_attr(self.upcast(), &atom!("href")) {
self.handle_favicon_url(rel.as_ref().unwrap(), href, &Some(attr.value().to_string()));
}
}
},
&atom!(media) => {
@ -153,13 +163,14 @@ impl VirtualMethods for HTMLLinkElement {
let rel = get_attr(element, &atom!("rel"));
let href = get_attr(element, &atom!("href"));
let sizes = get_attr(self.upcast(), &Atom::from_slice("sizes"));
match (rel, href) {
(ref rel, Some(ref href)) if string_is_stylesheet(rel) => {
match href {
Some(ref href) if string_is_stylesheet(&rel) => {
self.handle_stylesheet_url(href);
}
(ref rel, Some(ref href)) if is_favicon(rel) => {
self.handle_favicon_url(href);
Some(ref href) if is_favicon(&rel) => {
self.handle_favicon_url(rel.as_ref().unwrap(), href, &sizes);
}
_ => {}
}
@ -219,7 +230,7 @@ impl HTMLLinkElement {
}
}
fn handle_favicon_url(&self, href: &str) {
fn handle_favicon_url(&self, rel: &str, href: &str, sizes: &Option<String>) {
let window = window_from_node(self);
let window = window.r();
match UrlParser::new().base_url(&window.get_url()).parse(href) {
@ -227,6 +238,12 @@ impl HTMLLinkElement {
let ConstellationChan(ref chan) = window.constellation_chan();
let event = ConstellationMsg::NewFavicon(url.clone());
chan.send(event).unwrap();
let mozbrowser_event = match *sizes {
Some(ref sizes) => MozBrowserEvent::IconChange(rel.to_owned(), url.to_string(), sizes.to_owned()),
None => MozBrowserEvent::IconChange(rel.to_owned(), url.to_string(), "".to_owned())
};
window.Document().trigger_mozbrowser_event(mozbrowser_event);
}
Err(e) => debug!("Parsing url {} failed: {}", href, e)
}

View file

@ -24,6 +24,12 @@ callback BrowserElementNextPaintEventCallback = void ();
interface BrowserElement {
};
dictionary BrowserElementIconChangeEventDetail {
DOMString rel;
DOMString href;
DOMString sizes;
};
BrowserElement implements BrowserElementCommon;
BrowserElement implements BrowserElementPrivileged;