Auto merge of #6219 - zmike:favicons_and_stringlOWWW-MY-HEAD, r=pcwalton

Getting these down to the embedding API level required that I redo the bindings generator again, so this is more commits than anticipated.

@mbrubeck @Manishearth @pcwalton but NOT @larsbergstrom so don't even look at this.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/6219)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-06-03 00:27:41 -05:00
commit b0f3417cff
26 changed files with 182 additions and 62 deletions

View file

@ -454,6 +454,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
self.composite_if_necessary(CompositingReason::Headless);
}
(Msg::NewFavicon(url), ShutdownState::NotShuttingDown) => {
self.window.set_favicon(url);
}
(Msg::HeadParsed, ShutdownState::NotShuttingDown) => {
self.window.head_parsed();
}
// When we are shutting_down, we need to avoid performing operations
// such as Paint that may crash because we have begun tearing down
// the rest of our resources.

View file

@ -180,6 +180,10 @@ pub enum Msg {
ViewportConstrained(PipelineId, ViewportConstraints),
/// A reply to the compositor asking if the output image is stable.
IsReadyToSaveImageReply(bool),
/// A favicon was detected
NewFavicon(Url),
/// <head> tag finished parsing
HeadParsed,
}
impl Debug for Msg {
@ -206,6 +210,8 @@ impl Debug for Msg {
Msg::PaintTaskExited(..) => write!(f, "PaintTaskExited"),
Msg::ViewportConstrained(..) => write!(f, "ViewportConstrained"),
Msg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"),
Msg::NewFavicon(..) => write!(f, "NewFavicon"),
Msg::HeadParsed => write!(f, "HeadParsed"),
}
}
}

View file

@ -468,6 +468,14 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> {
debug!("constellation got remove iframe message");
self.handle_remove_iframe_msg(containing_pipeline_id, subpage_id);
}
ConstellationMsg::NewFavicon(url) => {
debug!("constellation got new favicon message");
self.compositor_proxy.send(CompositorMsg::NewFavicon(url));
}
ConstellationMsg::HeadParsed => {
debug!("constellation got head parsed message");
self.compositor_proxy.send(CompositorMsg::HeadParsed);
}
}
true
}

View file

@ -109,6 +109,8 @@ impl CompositorEventListener for NullCompositor {
Msg::CreatePng(..) |
Msg::PaintTaskExited(..) |
Msg::IsReadyToSaveImageReply(..) => {}
Msg::NewFavicon(..) => {}
Msg::HeadParsed => {}
}
true
}

View file

@ -110,6 +110,8 @@ pub trait WindowMethods {
fn load_end(&self, back: bool, forward: bool);
/// Called when the browser encounters an error while loading a URL
fn load_error(&self, code: NetError, url: String);
/// Called when the <head> tag has finished parsing
fn head_parsed(&self);
/// Returns the hidpi factor of the monitor.
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32>;
@ -138,4 +140,7 @@ pub trait WindowMethods {
/// Does this window support a clipboard
fn supports_clipboard(&self) -> bool;
/// Add a favicon
fn set_favicon(&self, url: Url);
}

View file

@ -248,6 +248,10 @@ pub enum Msg {
IsReadyToSaveImage(HashMap<PipelineId, Epoch>),
/// Notification that this iframe should be removed.
RemoveIFrame(PipelineId, SubpageId),
/// Favicon detected
NewFavicon(Url),
/// <head> tag finished parsing
HeadParsed,
}
#[derive(Clone, Eq, PartialEq)]

View file

@ -17,6 +17,8 @@ use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg;
use cssparser::RGBA;
use util::str::{self, DOMString};
@ -107,6 +109,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLBodyElement> {
let window = window_from_node(*self).root();
let document = window.r().Document().root();
document.r().set_reflow_timeout(time::precise_time_ns() + INITIAL_REFLOW_DELAY);
let ConstellationChan(ref chan) = window.r().constellation_chan();
let event = ConstellationMsg::HeadParsed;
chan.send(event).unwrap();
}
fn after_set_attr(&self, attr: JSRef<Attr>) {

View file

@ -25,6 +25,8 @@ use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::window::WindowHelpers;
use layout_interface::{LayoutChan, Msg};
use msg::constellation_msg::ConstellationChan;
use msg::constellation_msg::Msg as ConstellationMsg;
use script_traits::StylesheetLoadResponder;
use util::str::{DOMString, HTML_SPACE_CHARACTERS};
use style::media_queries::parse_media_query_list;
@ -85,6 +87,19 @@ fn is_stylesheet(value: &Option<String>) -> bool {
}
}
/// Favicon spec usage in accordance with CEF implementation:
/// only url of icon is required/used
/// https://html.spec.whatwg.org/multipage/#rel-icon
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"))
},
None => false,
}
}
impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self);
@ -105,7 +120,14 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
let rel = get_attr(element, &atom!("rel"));
match (rel, attr.local_name()) {
(ref rel, &atom!("href")) | (ref rel, &atom!("media")) => {
(ref rel, &atom!("href")) => {
if is_stylesheet(rel) {
self.handle_stylesheet_url(&attr.value());
} else if is_favicon(rel) {
self.handle_favicon_url(&attr.value());
}
}
(ref rel, &atom!("media")) => {
if is_stylesheet(rel) {
self.handle_stylesheet_url(&attr.value());
}
@ -136,6 +158,9 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
(ref rel, Some(ref href)) if is_stylesheet(rel) => {
self.handle_stylesheet_url(href);
}
(ref rel, Some(ref href)) if is_favicon(rel) => {
self.handle_favicon_url(href);
}
_ => {}
}
}
@ -144,6 +169,7 @@ impl<'a> VirtualMethods for JSRef<'a, HTMLLinkElement> {
trait PrivateHTMLLinkElementHelpers {
fn handle_stylesheet_url(self, href: &str);
fn handle_favicon_url(self, href: &str);
}
impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
@ -174,6 +200,19 @@ impl<'a> PrivateHTMLLinkElementHelpers for JSRef<'a, HTMLLinkElement> {
Err(e) => debug!("Parsing url {} failed: {}", href, e)
}
}
fn handle_favicon_url(self, href: &str) {
let window = window_from_node(self).root();
let window = window.r();
match UrlParser::new().base_url(&window.get_url()).parse(href) {
Ok(url) => {
let ConstellationChan(ref chan) = window.constellation_chan();
let event = ConstellationMsg::NewFavicon(url.clone());
chan.send(event).unwrap();
}
Err(e) => debug!("Parsing url {} failed: {}", href, e)
}
}
}
impl<'a> HTMLLinkElementMethods for JSRef<'a, HTMLLinkElement> {

View file

@ -111,6 +111,8 @@ pub struct ServoCefBrowser {
pub forward: Cell<bool>,
/// whether the browser is loading
pub loading: Cell<bool>,
/// a vec of favicon urls for the current page
pub favicons: RefCell<Vec<String>>,
/// the display system window handle: only to be used with host.get_window_handle()
window_handle: cef_window_handle_t,
@ -154,6 +156,7 @@ impl ServoCefBrowser {
back: Cell::new(false),
forward: Cell::new(false),
loading: Cell::new(false),
favicons: RefCell::new(vec!()),
window_handle: window_handle,
}
}

View file

@ -174,7 +174,7 @@ pub struct _cef_browser_t {
// Returns the names of all existing frames.
//
pub get_frame_names: Option<extern "C" fn(this: *mut cef_browser_t,
names: types::cef_string_list_t) -> ()>,
names: &types::cef_string_list_t) -> ()>,
//
// Send a message to the specified |target_process|. Returns true (1) if the
@ -567,7 +567,7 @@ impl CefBrowser {
//
// Returns the names of all existing frames.
//
pub fn get_frame_names(&self, names: Vec<String>) -> () {
pub fn get_frame_names(&self, names: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -647,7 +647,7 @@ pub struct _cef_run_file_dialog_callback_t {
pub on_file_dialog_dismissed: Option<extern "C" fn(
this: *mut cef_run_file_dialog_callback_t,
selected_accept_filter: libc::c_int,
file_paths: types::cef_string_list_t) -> ()>,
file_paths: &types::cef_string_list_t) -> ()>,
//
// The reference count. This will only be present for Rust instances!
@ -742,7 +742,7 @@ impl CefRunFileDialogCallback {
// dialog mode. If the selection was cancelled |file_paths| will be NULL.
//
pub fn on_file_dialog_dismissed(&self, selected_accept_filter: libc::c_int,
file_paths: Vec<String>) -> () {
file_paths: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -1047,7 +1047,7 @@ pub struct _cef_browser_host_t {
pub run_file_dialog: Option<extern "C" fn(this: *mut cef_browser_host_t,
mode: types::cef_file_dialog_mode_t, title: *const types::cef_string_t,
default_file_path: *const types::cef_string_t,
accept_filters: types::cef_string_list_t,
accept_filters: &types::cef_string_list_t,
selected_accept_filter: libc::c_int,
callback: *mut interfaces::cef_run_file_dialog_callback_t) -> ()>,
@ -1606,7 +1606,7 @@ impl CefBrowserHost {
// will be initiated asynchronously on the UI thread.
//
pub fn run_file_dialog(&self, mode: types::cef_file_dialog_mode_t,
title: &[u16], default_file_path: &[u16], accept_filters: Vec<String>,
title: &[u16], default_file_path: &[u16], accept_filters: &Vec<String>,
selected_accept_filter: libc::c_int,
callback: interfaces::CefRunFileDialogCallback) -> () {
if self.c_object.is_null() ||

View file

@ -95,7 +95,8 @@ pub struct _cef_browser_process_handler_t {
this: *mut cef_browser_process_handler_t) -> *mut interfaces::cef_print_handler_t>,
//
// Called when the application should call cef_do_message_loop_work()
// Called when the application should call cef_do_message_loop_work(). May be
// called from a thread.
//
pub on_work_available: Option<extern "C" fn(
this: *mut cef_browser_process_handler_t) -> ()>,
@ -261,7 +262,8 @@ impl CefBrowserProcessHandler {
}
//
// Called when the application should call cef_do_message_loop_work()
// Called when the application should call cef_do_message_loop_work(). May be
// called from a thread.
//
pub fn on_work_available(&self) -> () {
if self.c_object.is_null() ||

View file

@ -109,7 +109,7 @@ pub struct _cef_command_line_t {
// array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
//
pub get_argv: Option<extern "C" fn(this: *mut cef_command_line_t,
argv: types::cef_string_list_t) -> ()>,
argv: &types::cef_string_list_t) -> ()>,
//
// Constructs and returns the represented command line string. Use this
@ -183,7 +183,7 @@ pub struct _cef_command_line_t {
// Get the remaining command line arguments.
//
pub get_arguments: Option<extern "C" fn(this: *mut cef_command_line_t,
arguments: types::cef_string_list_t) -> ()>,
arguments: &types::cef_string_list_t) -> ()>,
//
// Add an argument to the end of the command line.
@ -392,7 +392,7 @@ impl CefCommandLine {
// Retrieve the original command line string as a vector of strings. The argv
// array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
//
pub fn get_argv(&self, argv: Vec<String>) -> () {
pub fn get_argv(&self, argv: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -572,7 +572,7 @@ impl CefCommandLine {
//
// Get the remaining command line arguments.
//
pub fn get_arguments(&self, arguments: Vec<String>) -> () {
pub fn get_arguments(&self, arguments: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -403,7 +403,7 @@ pub struct _cef_context_menu_params_t {
//
pub get_dictionary_suggestions: Option<extern "C" fn(
this: *mut cef_context_menu_params_t,
suggestions: types::cef_string_list_t) -> libc::c_int>,
suggestions: &types::cef_string_list_t) -> libc::c_int>,
//
// Returns true (1) if the context menu was invoked on an editable node.
@ -746,7 +746,7 @@ impl CefContextMenuParams {
// is one.
//
pub fn get_dictionary_suggestions(&self,
suggestions: Vec<String>) -> libc::c_int {
suggestions: &Vec<String>) -> libc::c_int {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -64,7 +64,7 @@ pub struct _cef_cookie_manager_t {
// Must be called before any cookies are accessed.
//
pub set_supported_schemes: Option<extern "C" fn(
this: *mut cef_cookie_manager_t, schemes: types::cef_string_list_t,
this: *mut cef_cookie_manager_t, schemes: &types::cef_string_list_t,
callback: *mut interfaces::cef_completion_callback_t) -> ()>,
//
@ -227,7 +227,7 @@ impl CefCookieManager {
// executed asnychronously on the IO thread after the change has been applied.
// Must be called before any cookies are accessed.
//
pub fn set_supported_schemes(&self, schemes: Vec<String>,
pub fn set_supported_schemes(&self, schemes: &Vec<String>,
callback: interfaces::CefCompletionCallback) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {

View file

@ -65,7 +65,7 @@ pub struct _cef_file_dialog_callback_t {
//
pub cont: Option<extern "C" fn(this: *mut cef_file_dialog_callback_t,
selected_accept_filter: libc::c_int,
file_paths: types::cef_string_list_t) -> ()>,
file_paths: &types::cef_string_list_t) -> ()>,
//
// Cancel the file selection.
@ -165,7 +165,7 @@ impl CefFileDialogCallback {
// value is treated the same as calling cancel().
//
pub fn cont(&self, selected_accept_filter: libc::c_int,
file_paths: Vec<String>) -> () {
file_paths: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -251,7 +251,7 @@ pub struct _cef_dialog_handler_t {
browser: *mut interfaces::cef_browser_t,
mode: types::cef_file_dialog_mode_t, title: *const types::cef_string_t,
default_file_path: *const types::cef_string_t,
accept_filters: types::cef_string_list_t,
accept_filters: &types::cef_string_list_t,
selected_accept_filter: libc::c_int,
callback: *mut interfaces::cef_file_dialog_callback_t) -> libc::c_int>,
@ -357,7 +357,7 @@ impl CefDialogHandler {
//
pub fn on_file_dialog(&self, browser: interfaces::CefBrowser,
mode: types::cef_file_dialog_mode_t, title: &[u16],
default_file_path: &[u16], accept_filters: Vec<String>,
default_file_path: &[u16], accept_filters: &Vec<String>,
selected_accept_filter: libc::c_int,
callback: interfaces::CefFileDialogCallback) -> libc::c_int {
if self.c_object.is_null() ||

View file

@ -77,7 +77,7 @@ pub struct _cef_display_handler_t {
//
pub on_favicon_urlchange: Option<extern "C" fn(
this: *mut cef_display_handler_t, browser: *mut interfaces::cef_browser_t,
icon_urls: types::cef_string_list_t) -> ()>,
icon_urls: &types::cef_string_list_t) -> ()>,
//
// Called when the browser is about to display a tooltip. |text| contains the
@ -234,7 +234,7 @@ impl CefDisplayHandler {
// Called when the page icon changes.
//
pub fn on_favicon_urlchange(&self, browser: interfaces::CefBrowser,
icon_urls: Vec<String>) -> () {
icon_urls: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -149,7 +149,7 @@ pub struct _cef_drag_data_t {
// window.
//
pub get_file_names: Option<extern "C" fn(this: *mut cef_drag_data_t,
names: types::cef_string_list_t) -> libc::c_int>,
names: &types::cef_string_list_t) -> libc::c_int>,
//
// Set the link URL that is being dragged.
@ -499,7 +499,7 @@ impl CefDragData {
// Retrieve the list of file names that are being dragged into the browser
// window.
//
pub fn get_file_names(&self, names: Vec<String>) -> libc::c_int {
pub fn get_file_names(&self, names: &Vec<String>) -> libc::c_int {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -97,20 +97,20 @@ pub struct _cef_sslcert_principal_t {
//
pub get_street_addresses: Option<extern "C" fn(
this: *mut cef_sslcert_principal_t,
addresses: types::cef_string_list_t) -> ()>,
addresses: &types::cef_string_list_t) -> ()>,
//
// Retrieve the list of organization names.
//
pub get_organization_names: Option<extern "C" fn(
this: *mut cef_sslcert_principal_t, names: types::cef_string_list_t) -> (
this: *mut cef_sslcert_principal_t, names: &types::cef_string_list_t) -> (
)>,
//
// Retrieve the list of organization unit names.
//
pub get_organization_unit_names: Option<extern "C" fn(
this: *mut cef_sslcert_principal_t, names: types::cef_string_list_t) -> (
this: *mut cef_sslcert_principal_t, names: &types::cef_string_list_t) -> (
)>,
//
@ -118,7 +118,7 @@ pub struct _cef_sslcert_principal_t {
//
pub get_domain_components: Option<extern "C" fn(
this: *mut cef_sslcert_principal_t,
components: types::cef_string_list_t) -> ()>,
components: &types::cef_string_list_t) -> ()>,
//
// The reference count. This will only be present for Rust instances!
@ -288,7 +288,7 @@ impl CefSSLCertPrincipal {
//
// Retrieve the list of street addresses.
//
pub fn get_street_addresses(&self, addresses: Vec<String>) -> () {
pub fn get_street_addresses(&self, addresses: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -304,7 +304,7 @@ impl CefSSLCertPrincipal {
//
// Retrieve the list of organization names.
//
pub fn get_organization_names(&self, names: Vec<String>) -> () {
pub fn get_organization_names(&self, names: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -320,7 +320,7 @@ impl CefSSLCertPrincipal {
//
// Retrieve the list of organization unit names.
//
pub fn get_organization_unit_names(&self, names: Vec<String>) -> () {
pub fn get_organization_unit_names(&self, names: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")
@ -336,7 +336,7 @@ impl CefSSLCertPrincipal {
//
// Retrieve the list of domain components.
//
pub fn get_domain_components(&self, components: Vec<String>) -> () {
pub fn get_domain_components(&self, components: &Vec<String>) -> () {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -1364,7 +1364,7 @@ pub struct _cef_v8value_t {
// based keys will also be returned as strings.
//
pub get_keys: Option<extern "C" fn(this: *mut cef_v8value_t,
keys: types::cef_string_list_t) -> libc::c_int>,
keys: &types::cef_string_list_t) -> libc::c_int>,
//
// Sets the user data for this object and returns true (1) on success. Returns
@ -2117,7 +2117,7 @@ impl CefV8Value {
// Read the keys for the object's values into the specified vector. Integer-
// based keys will also be returned as strings.
//
pub fn get_keys(&self, keys: Vec<String>) -> libc::c_int {
pub fn get_keys(&self, keys: &Vec<String>) -> libc::c_int {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -1099,7 +1099,7 @@ pub struct _cef_dictionary_value_t {
// Reads all keys for this dictionary into the specified vector.
//
pub get_keys: Option<extern "C" fn(this: *mut cef_dictionary_value_t,
keys: types::cef_string_list_t) -> libc::c_int>,
keys: &types::cef_string_list_t) -> libc::c_int>,
//
// Removes the value at the specified key. Returns true (1) is the value was
@ -1489,7 +1489,7 @@ impl CefDictionaryValue {
//
// Reads all keys for this dictionary into the specified vector.
//
pub fn get_keys(&self, keys: Vec<String>) -> libc::c_int {
pub fn get_keys(&self, keys: &Vec<String>) -> libc::c_int {
if self.c_object.is_null() ||
self.c_object as usize == mem::POST_DROP_USIZE {
panic!("called a CEF method on a null object")

View file

@ -4,12 +4,14 @@
use libc::{c_int};
use std::mem;
use string::{cef_string_userfree_utf16_alloc,cef_string_userfree_utf16_free,cef_string_utf16_set};
use std::slice;
use string::cef_string_utf16_set;
use types::{cef_string_list_t,cef_string_t};
use rustc_unicode::str::Utf16Encoder;
fn string_list_to_vec(lt: *mut cef_string_list_t) -> *mut Vec<*mut cef_string_t> {
lt as *mut Vec<*mut cef_string_t>
fn string_list_to_vec(lt: *mut cef_string_list_t) -> *mut Vec<String> {
lt as *mut Vec<String>
}
//cef_string_list
@ -17,7 +19,7 @@ fn string_list_to_vec(lt: *mut cef_string_list_t) -> *mut Vec<*mut cef_string_t>
#[no_mangle]
pub extern "C" fn cef_string_list_alloc() -> *mut cef_string_list_t {
unsafe {
let lt: Box<Vec<*mut cef_string_t>> = box vec!();
let lt: Box<Vec<String>> = box vec!();
mem::transmute(lt)
}
}
@ -36,9 +38,7 @@ pub extern "C" fn cef_string_list_append(lt: *mut cef_string_list_t, value: *con
unsafe {
if lt.is_null() { return; }
let v = string_list_to_vec(lt);
let cs = cef_string_userfree_utf16_alloc();
cef_string_utf16_set(mem::transmute((*value).str), (*value).length, cs, 1);
(*v).push(cs);
(*v).push(String::from_utf16(slice::from_raw_parts((*value).str, (*value).length as usize)).unwrap());
}
}
@ -48,8 +48,9 @@ pub extern "C" fn cef_string_list_value(lt: *mut cef_string_list_t, index: c_int
if index < 0 || lt.is_null() { return 0; }
let v = string_list_to_vec(lt);
if index as usize > (*v).len() - 1 { return 0; }
let cs = (*v)[index as usize];
cef_string_utf16_set(mem::transmute((*cs).str), (*cs).length, value, 1)
let ref string = (*v)[index as usize];
let utf16_chars: Vec<u16> = Utf16Encoder::new(string.chars()).collect();
cef_string_utf16_set(mem::transmute(utf16_chars.as_ptr()), utf16_chars.len() as u64, value, 1)
}
}
@ -58,12 +59,7 @@ pub extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
unsafe {
if lt.is_null() { return; }
let v = string_list_to_vec(lt);
if (*v).len() == 0 { return; }
let mut cs;
while (*v).len() != 0 {
cs = (*v).pop();
cef_string_userfree_utf16_free(cs.unwrap());
}
(*v).clear();
}
}
@ -71,7 +67,7 @@ pub extern "C" fn cef_string_list_clear(lt: *mut cef_string_list_t) {
pub extern "C" fn cef_string_list_free(lt: *mut cef_string_list_t) {
unsafe {
if lt.is_null() { return; }
let v: Box<Vec<*mut cef_string_t>> = mem::transmute(lt);
let v: Box<Vec<String>> = mem::transmute(lt);
cef_string_list_clear(lt);
drop(v);
}
@ -82,10 +78,7 @@ pub extern "C" fn cef_string_list_copy(lt: *mut cef_string_list_t) -> *mut cef_s
unsafe {
if lt.is_null() { return 0 as *mut cef_string_list_t; }
let v = string_list_to_vec(lt);
let lt2 = cef_string_list_alloc();
for cs in (*v).iter() {
cef_string_list_append(lt2, mem::transmute((*cs)));
}
lt2
let copy = (*v).clone();
mem::transmute(box copy)
}
}

View file

@ -15,7 +15,7 @@ pub use self::cef_rect as cef_rect_t;
pub enum cef_string_map_t {}
pub enum cef_string_multimap_t {}
pub enum cef_string_list_t {}
pub type cef_string_list_t = Vec<String>;
pub enum cef_text_input_context_t {}
pub enum cef_event_handle_t {}

View file

@ -316,8 +316,16 @@ impl WindowMethods for Window {
}
}
fn set_favicon(&self, url: Url) {
let browser = self.cef_browser.borrow();
let browser = match *browser {
None => return,
Some(ref browser) => browser,
};
browser.downcast().favicons.borrow_mut().push(url.to_string().clone());
}
fn load_start(&self, back: bool, forward: bool) {
// FIXME(pcwalton): The status code 200 is a lie.
let browser = self.cef_browser.borrow();
let browser = match *browser {
None => return,
@ -326,6 +334,7 @@ impl WindowMethods for Window {
browser.downcast().loading.set(true);
browser.downcast().back.set(back);
browser.downcast().forward.set(forward);
browser.downcast().favicons.borrow_mut().clear();
if check_ptr_exist!(browser.get_host().get_client(), get_load_handler) &&
check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_loading_state_change) {
browser.get_host()
@ -378,6 +387,18 @@ impl WindowMethods for Window {
}
}
fn head_parsed(&self) {
let browser = self.cef_browser.borrow();
let browser = match *browser {
None => return,
Some(ref browser) => browser,
};
if check_ptr_exist!(browser.get_host().get_client(), get_display_handler) &&
check_ptr_exist!(browser.get_host().get_client().get_display_handler(), on_favicon_urlchange) {
browser.get_host().get_client().get_display_handler().on_favicon_urlchange((*browser).clone(), &browser.downcast().favicons.borrow());
}
}
fn set_page_title(&self, string: Option<String>) {
let browser = self.cef_browser.borrow();
let browser = match *browser {

View file

@ -135,7 +135,6 @@ cef_noop_wrapper!(*mut cef_jsdialog_handler_t);
cef_noop_wrapper!(*mut cef_keyboard_handler_t);
cef_noop_wrapper!(*mut cef_load_handler_t);
cef_noop_wrapper!(*mut cef_request_handler_t);
cef_noop_wrapper!(*mut cef_string_list_t);
cef_noop_wrapper!(*mut cef_string_utf16);
cef_noop_wrapper!(c_int);
cef_noop_wrapper!(CefApp);
@ -185,10 +184,10 @@ cef_noop_wrapper!(f64);
cef_noop_wrapper!(i64);
cef_noop_wrapper!(u32);
cef_noop_wrapper!(u64);
cef_noop_wrapper!(cef_string_list_t);
cef_unimplemented_wrapper!(*const *mut cef_v8value_t, *const CefV8Value);
cef_unimplemented_wrapper!(*mut *mut cef_post_data_element_t, *mut CefPostDataElement);
cef_unimplemented_wrapper!(cef_string_list_t, Vec<String>);
cef_unimplemented_wrapper!(cef_string_map_t, HashMap<String,String>);
cef_unimplemented_wrapper!(cef_string_multimap_t, HashMap<String,Vec<String>>);
cef_unimplemented_wrapper!(cef_string_t, String);
@ -293,3 +292,11 @@ impl<'a> CefWrap<cef_string_t> for &'a mut String {
}
}
impl<'a> CefWrap<&'a cef_string_list_t> for &'a cef_string_list_t {
fn to_c(stringlist: &'a cef_string_list_t) -> &'a cef_string_list_t {
stringlist
}
unsafe fn to_rust(_: &'a cef_string_list_t) -> &'a cef_string_list_t {
panic!("unimplemented CEF type conversion: cef_string_t");
}
}

View file

@ -515,6 +515,9 @@ impl WindowMethods for Window {
fn load_error(&self, _: NetError, _: String) {
}
fn head_parsed(&self) {
}
/// Has no effect on Android.
fn set_cursor(&self, c: Cursor) {
use glutin::MouseCursor;
@ -559,6 +562,9 @@ impl WindowMethods for Window {
self.window.set_cursor(glutin_cursor);
}
fn set_favicon(&self, _: Url) {
}
fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
true
}
@ -703,10 +709,15 @@ impl WindowMethods for Window {
}
fn load_error(&self, _: NetError, _: String) {
}
fn head_parsed(&self) {
}
fn set_cursor(&self, _: Cursor) {
}
fn set_favicon(&self, _: Url) {
}
fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
true
}

View file

@ -812,6 +812,9 @@ impl WindowMethods for Window {
fn load_error(&self, _: NetError, _: String) {
}
fn head_parsed(&self) {
}
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
ScaleFactor::new(1.0)
}
@ -838,6 +841,9 @@ impl WindowMethods for Window {
fn set_cursor(&self, _: Cursor) {
}
fn set_favicon(&self, _: Url) {
}
fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
true
}