From d7ad5d6ea2378bf3c55ece8637bf5126af5c5eba Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 14:47:00 -0400 Subject: [PATCH 01/27] add cef method for notifying the main loop of work available --- .../interfaces/cef_browser_process_handler.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ports/cef/interfaces/cef_browser_process_handler.rs b/ports/cef/interfaces/cef_browser_process_handler.rs index 672247169fd..49cc9e327b1 100644 --- a/ports/cef/interfaces/cef_browser_process_handler.rs +++ b/ports/cef/interfaces/cef_browser_process_handler.rs @@ -94,6 +94,12 @@ pub struct _cef_browser_process_handler_t { pub get_print_handler: Option *mut interfaces::cef_print_handler_t>, + // + // Called when the application should call cef_do_message_loop_work() + // + pub on_work_available: Option ()>, + // // The reference count. This will only be present for Rust instances! // @@ -253,6 +259,21 @@ impl CefBrowserProcessHandler { self.c_object)) } } + + // + // Called when the application should call cef_do_message_loop_work() + // + pub fn on_work_available(&self) -> () { + if self.c_object.is_null() || + self.c_object as usize == mem::POST_DROP_USIZE { + panic!("called a CEF method on a null object") + } + unsafe { + CefWrap::to_rust( + ((*self.c_object).on_work_available.unwrap())( + self.c_object)) + } + } } impl CefWrap<*mut cef_browser_process_handler_t> for CefBrowserProcessHandler { From 83e605d2fb3ec0bf56b6e803b698952550a62893 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 15:53:18 -0400 Subject: [PATCH 02/27] add no_mangle to servo_test() embedding function --- ports/cef/eutil.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/cef/eutil.rs b/ports/cef/eutil.rs index 1291a7dce09..39b30cfa481 100644 --- a/ports/cef/eutil.rs +++ b/ports/cef/eutil.rs @@ -77,6 +77,7 @@ pub unsafe fn add_ref(c_object: *mut cef_base_t) { ((*c_object).add_ref.unwrap())(c_object); } +#[no_mangle] pub extern "C" fn servo_test() -> c_int { 1 } From af1dce5a2e0128bc9853dbad90aa936500fa42d7 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 17:21:53 -0400 Subject: [PATCH 03/27] add new browser process interface method for main loop integration regular CEF requires the user to either run the cef main loop or poll on a function to drain events. now the engine will trigger a callback in some application thread which will notify it that there is work to be done by the browser --- ports/cef/core.rs | 8 ++++++++ ports/cef/window.rs | 9 ++++++++- ports/cef/wrappers.rs | 4 +++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/ports/cef/core.rs b/ports/cef/core.rs index aa49bb17b51..847fbe185b9 100644 --- a/ports/cef/core.rs +++ b/ports/cef/core.rs @@ -26,6 +26,8 @@ static CEF_API_HASH_PLATFORM: &'static [u8] = b"6813214accbf2ebfb6bdcf8d00654650 #[cfg(target_os="linux")] static CEF_API_HASH_PLATFORM: &'static [u8] = b"2bc564c3871965ef3a2531b528bda3e17fa17a6d\0"; +pub static mut CEF_APP: *mut cef_app_t = 0 as *mut cef_app_t; + #[no_mangle] pub extern "C" fn cef_initialize(args: *const cef_main_args_t, @@ -36,6 +38,11 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t, if args.is_null() { return 0; } + unsafe { + if !CEF_APP.is_null() { + panic!("Attempting to call cef_initialize() multiple times!"); + } + } unsafe { command_line_init((*args).argc, (*args).argv); @@ -47,6 +54,7 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t, (*handler).on_context_initialized.map(|hcb| hcb(handler)); } }); + CEF_APP = application; } } diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 8bf21db2ef4..87bda1af854 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -7,8 +7,9 @@ //! This is used for off-screen rendering mode only; on-screen windows (the default embedding mode) //! are managed by a platform toolkit (Glutin). +use core::CEF_APP; use eutil::Downcast; -use interfaces::CefBrowser; +use interfaces::{CefApp, CefBrowser}; use render_handler::CefRenderHandlerExtensions; use rustc_unicode::str::Utf16Encoder; use types::{cef_cursor_handle_t, cef_cursor_type_t, cef_rect_t}; @@ -428,6 +429,12 @@ impl CompositorProxy for CefCompositorProxy { #[cfg(target_os="linux")] fn send(&mut self, msg: compositor_task::Msg) { self.sender.send(msg).unwrap(); + unsafe { if CEF_APP.is_null() { return; } } + let capp = unsafe { CefApp::from_c_object_addref(CEF_APP) }; + if unsafe { (*CEF_APP).get_browser_process_handler.is_some() } && + check_ptr_exist!(capp.get_browser_process_handler(), on_work_available) { + capp.get_browser_process_handler().on_work_available(); + } } fn clone_compositor_proxy(&self) -> Box { diff --git a/ports/cef/wrappers.rs b/ports/cef/wrappers.rs index edeb664e2e5..2cc1d48fe63 100644 --- a/ports/cef/wrappers.rs +++ b/ports/cef/wrappers.rs @@ -2,7 +2,7 @@ * 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/. */ -use interfaces::{cef_drag_data_t, cef_post_data_element_t, cef_v8value_t, CefPostDataElement}; +use interfaces::{cef_app_t, CefApp, cef_drag_data_t, cef_post_data_element_t, cef_v8value_t, CefPostDataElement}; use interfaces::{CefV8Value}; use interfaces::{cef_download_handler_t, cef_drag_handler_t, cef_context_menu_handler_t}; use interfaces::{cef_dialog_handler_t, cef_focus_handler_t}; @@ -98,6 +98,7 @@ cef_pointer_wrapper!(()); cef_pointer_wrapper!(*mut ()); cef_pointer_wrapper!(*mut c_void); cef_pointer_wrapper!(c_void); +cef_pointer_wrapper!(cef_app_t); cef_pointer_wrapper!(cef_base_t); cef_pointer_wrapper!(cef_browser_settings_t); cef_pointer_wrapper!(cef_cookie_t); @@ -137,6 +138,7 @@ 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); cef_noop_wrapper!(CefBrowserSettings); cef_noop_wrapper!(CefScreenInfo); cef_noop_wrapper!(CefRequestContextSettings); From caa8172560b523c9bba343942a2a1020d60d2fa4 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 18:22:35 -0400 Subject: [PATCH 04/27] implement cef browser title setting callback --- ports/cef/lib.rs | 1 + ports/cef/window.rs | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ports/cef/lib.rs b/ports/cef/lib.rs index 54225fd3ae7..bc26e01b3a3 100644 --- a/ports/cef/lib.rs +++ b/ports/cef/lib.rs @@ -8,6 +8,7 @@ #![feature(link_args)] #![feature(thread_local)] #![feature(core)] +#![feature(convert)] #![feature(std_misc)] #![feature(rustc_private)] #![feature(collections)] diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 87bda1af854..d6a5a1cb3f4 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -340,18 +340,24 @@ impl WindowMethods for Window { let frame = browser.get_main_frame(); let frame = frame.downcast(); let mut title_visitor = frame.title_visitor.borrow_mut(); - match &mut *title_visitor { - &mut None => {} - &mut Some(ref mut visitor) => { - match string { - None => visitor.visit(&[]), - Some(string) => { - let utf16_chars: Vec = Utf16Encoder::new(string.chars()).collect(); - visitor.visit(&utf16_chars) - } - } + let str = match string { + Some(s) => { + let utf16_chars: Vec = Utf16Encoder::new(s.chars()).collect(); + utf16_chars } + None => vec![] + }; + + if check_ptr_exist!(browser.get_host().get_client(), get_display_handler) && + check_ptr_exist!(browser.get_host().get_client().get_display_handler(), on_title_change) { + browser.get_host().get_client().get_display_handler().on_title_change((*browser).clone(), str.as_slice()); } + match &mut *title_visitor { + &mut None => {}, + &mut Some(ref mut visitor) => { + visitor.visit(&str); + } + }; } fn set_page_url(&self, url: Url) { From cf388cd90903536db5c0f17ba6a7c4e86c030499 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 19:13:29 -0400 Subject: [PATCH 05/27] call compositor.window.set_page_url() on WindowEvent::LoadUrl --- components/compositing/compositor.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 346666ac31b..a50b51ebc0e 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -883,9 +883,10 @@ impl IOCompositor { None => panic!("Compositor: Received WindowEvent::LoadUrl without initialized compositor \ layers"), }; + let url = Url::parse(&url_string).unwrap(); + self.window.set_page_url(url.clone()); - let msg = ConstellationMsg::LoadUrl(root_pipeline_id, - LoadData::new(Url::parse(&url_string).unwrap())); + let msg = ConstellationMsg::LoadUrl(root_pipeline_id, LoadData::new(url)); let ConstellationChan(ref chan) = self.constellation_chan; chan.send(msg).unwrap() } From 92d44fb36e6a6ad4548a611da86bd8d1492413fe Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 19:14:07 -0400 Subject: [PATCH 06/27] send ChangeUrl message from constellation on init --- components/compositing/constellation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index af94cea02e9..750c124a13a 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -519,8 +519,9 @@ impl Constellation { fn handle_init_load(&mut self, url: Url) { let window_rect = Rect(Point2D::zero(), self.window_size.visible_viewport); let root_pipeline_id = - self.new_pipeline(None, Some(window_rect), None, LoadData::new(url)); + self.new_pipeline(None, Some(window_rect), None, LoadData::new(url.clone())); self.push_pending_frame(root_pipeline_id, None); + self.compositor_proxy.send(CompositorMsg::ChangePageUrl(root_pipeline_id, url)); } fn handle_frame_rect_msg(&mut self, containing_pipeline_id: PipelineId, subpage_id: SubpageId, From 02606fada4012dddf85256af317ce6b83606883e Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 19:14:42 -0400 Subject: [PATCH 07/27] implement on_address_change handler for cef port --- ports/cef/window.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ports/cef/window.rs b/ports/cef/window.rs index d6a5a1cb3f4..b22c8703067 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -367,10 +367,15 @@ impl WindowMethods for Window { Some(ref browser) => browser, }; let frame = browser.get_main_frame(); - let frame = frame.downcast(); + let servoframe = frame.downcast(); // FIXME(https://github.com/rust-lang/rust/issues/23338) - let mut frame_url = frame.url.borrow_mut(); - *frame_url = url.to_string() + let mut frame_url = servoframe.url.borrow_mut(); + *frame_url = url.to_string(); + let utf16_chars: Vec = Utf16Encoder::new((*frame_url).chars()).collect(); + if check_ptr_exist!(browser.get_host().get_client(), get_display_handler) && + check_ptr_exist!(browser.get_host().get_client().get_display_handler(), on_address_change) { + browser.get_host().get_client().get_display_handler().on_address_change((*browser).clone(), frame.clone(), utf16_chars.as_slice()); + } } fn handle_key(&self, _: Key, _: KeyModifiers) { From a809d6b911973e61af33a0d8c19ad114206e3b72 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 19 May 2015 19:15:09 -0400 Subject: [PATCH 08/27] remove unused cef imports --- ports/cef/browser.rs | 2 -- ports/cef/window.rs | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index cf868cb10d0..98681198db2 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -11,13 +11,11 @@ use interfaces::{cef_request_context_t}; use servo::Browser; use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t}; use window; -use wrappers::CefWrap; use compositing::windowing::{WindowNavigateMsg, WindowEvent}; use glutin_app; use libc::c_int; use std::cell::{Cell, RefCell, BorrowState}; -use std::ptr; use std::rc::Rc; use std::sync::atomic::{AtomicIsize, Ordering}; diff --git a/ports/cef/window.rs b/ports/cef/window.rs index b22c8703067..bab2d5bbac0 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -22,7 +22,7 @@ use geom::size::TypedSize2D; use gleam::gl; use layers::geometry::DevicePixel; use layers::platform::surface::NativeGraphicsMetadata; -use libc::{c_char, c_int, c_void}; +use libc::{c_char, c_void}; use msg::constellation_msg::{Key, KeyModifiers}; use std::ptr; use std_url::Url; From efc75ef40eba5c379a141c76d8bf49eda2f6db3f Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 21 May 2015 13:31:00 -0400 Subject: [PATCH 09/27] ignore KEYEVENT_RAWKEYDOWN in cef browser events I'm not sure exactly what this is supposed to do and there are no docs. from what I've observed, nothing happens on this event --- ports/cef/browser_host.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ports/cef/browser_host.rs b/ports/cef/browser_host.rs index 680f7e8b99b..30645d17b39 100644 --- a/ports/cef/browser_host.rs +++ b/ports/cef/browser_host.rs @@ -111,8 +111,10 @@ full_cef_class_impl! { _ => constellation_msg::Key::Space, }; let key_state = match (*event).t { - KEYEVENT_RAWKEYDOWN => KeyState::Pressed, - KEYEVENT_KEYDOWN | KEYEVENT_CHAR => KeyState::Repeated, + // in tests with cef-real, this event had no effect + KEYEVENT_RAWKEYDOWN => return, + KEYEVENT_KEYDOWN => KeyState::Pressed, + KEYEVENT_CHAR => KeyState::Repeated, KEYEVENT_KEYUP => KeyState::Released, }; let key_modifiers = KeyModifiers::empty(); // TODO(pcwalton) From 28aed52a4bdc01399843d69c7c196c2bfa3344ba Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 21 May 2015 15:52:16 -0400 Subject: [PATCH 10/27] improve cef keyboard handling this is a rough approximation of the handling of various keycodes/syms within chromium. it needs work, but for my system it works okay --- ports/cef/browser_host.rs | 379 +++++++++++++++++++++++++++++++++----- 1 file changed, 338 insertions(+), 41 deletions(-) diff --git a/ports/cef/browser_host.rs b/ports/cef/browser_host.rs index 30645d17b39..4c6686ee0e2 100644 --- a/ports/cef/browser_host.rs +++ b/ports/cef/browser_host.rs @@ -16,6 +16,7 @@ use libc::{c_double, c_int}; use msg::constellation_msg::{self, KeyModifiers, KeyState}; use script_traits::MouseButton; use std::cell::{Cell, RefCell}; +use std::mem::transmute; pub struct ServoCefBrowserHost { /// A reference to the browser. @@ -26,6 +27,337 @@ pub struct ServoCefBrowserHost { pub composite_ok: Cell, } +// From blink ui/events/keycodes/keyboard_codes_posix.h. +#[allow(dead_code)] +enum KeyboardCode { + VKEY_BACK = 0x08, + VKEY_TAB = 0x09, + VKEY_BACKTAB = 0x0A, + VKEY_CLEAR = 0x0C, + VKEY_RETURN = 0x0D, + VKEY_SHIFT = 0x10, + VKEY_CONTROL = 0x11, + VKEY_MENU = 0x12, + VKEY_PAUSE = 0x13, + VKEY_CAPITAL = 0x14, + VKEY_KANA = 0x15, + //VKEY_HANGUL = 0x15, + VKEY_JUNJA = 0x17, + VKEY_FINAL = 0x18, + VKEY_HANJA = 0x19, + //VKEY_KANJI = 0x19, + VKEY_ESCAPE = 0x1B, + VKEY_CONVERT = 0x1C, + VKEY_NONCONVERT = 0x1D, + VKEY_ACCEPT = 0x1E, + VKEY_MODECHANGE = 0x1F, + VKEY_SPACE = 0x20, + VKEY_PRIOR = 0x21, + VKEY_NEXT = 0x22, + VKEY_END = 0x23, + VKEY_HOME = 0x24, + VKEY_LEFT = 0x25, + VKEY_UP = 0x26, + VKEY_RIGHT = 0x27, + VKEY_DOWN = 0x28, + VKEY_SELECT = 0x29, + VKEY_PRINT = 0x2A, + VKEY_EXECUTE = 0x2B, + VKEY_SNAPSHOT = 0x2C, + VKEY_INSERT = 0x2D, + VKEY_DELETE = 0x2E, + VKEY_HELP = 0x2F, + VKEY_0 = 0x30, + VKEY_1 = 0x31, + VKEY_2 = 0x32, + VKEY_3 = 0x33, + VKEY_4 = 0x34, + VKEY_5 = 0x35, + VKEY_6 = 0x36, + VKEY_7 = 0x37, + VKEY_8 = 0x38, + VKEY_9 = 0x39, + VKEY_A = 0x41, + VKEY_B = 0x42, + VKEY_C = 0x43, + VKEY_D = 0x44, + VKEY_E = 0x45, + VKEY_F = 0x46, + VKEY_G = 0x47, + VKEY_H = 0x48, + VKEY_I = 0x49, + VKEY_J = 0x4A, + VKEY_K = 0x4B, + VKEY_L = 0x4C, + VKEY_M = 0x4D, + VKEY_N = 0x4E, + VKEY_O = 0x4F, + VKEY_P = 0x50, + VKEY_Q = 0x51, + VKEY_R = 0x52, + VKEY_S = 0x53, + VKEY_T = 0x54, + VKEY_U = 0x55, + VKEY_V = 0x56, + VKEY_W = 0x57, + VKEY_X = 0x58, + VKEY_Y = 0x59, + VKEY_Z = 0x5A, + VKEY_LWIN = 0x5B, + VKEY_RWIN = 0x5C, + VKEY_APPS = 0x5D, + VKEY_SLEEP = 0x5F, + VKEY_NUMPAD0 = 0x60, + VKEY_NUMPAD1 = 0x61, + VKEY_NUMPAD2 = 0x62, + VKEY_NUMPAD3 = 0x63, + VKEY_NUMPAD4 = 0x64, + VKEY_NUMPAD5 = 0x65, + VKEY_NUMPAD6 = 0x66, + VKEY_NUMPAD7 = 0x67, + VKEY_NUMPAD8 = 0x68, + VKEY_NUMPAD9 = 0x69, + VKEY_MULTIPLY = 0x6A, + VKEY_ADD = 0x6B, + VKEY_SEPARATOR = 0x6C, + VKEY_SUBTRACT = 0x6D, + VKEY_DECIMAL = 0x6E, + VKEY_DIVIDE = 0x6F, + VKEY_F1 = 0x70, + VKEY_F2 = 0x71, + VKEY_F3 = 0x72, + VKEY_F4 = 0x73, + VKEY_F5 = 0x74, + VKEY_F6 = 0x75, + VKEY_F7 = 0x76, + VKEY_F8 = 0x77, + VKEY_F9 = 0x78, + VKEY_F10 = 0x79, + VKEY_F11 = 0x7A, + VKEY_F12 = 0x7B, + VKEY_F13 = 0x7C, + VKEY_F14 = 0x7D, + VKEY_F15 = 0x7E, + VKEY_F16 = 0x7F, + VKEY_F17 = 0x80, + VKEY_F18 = 0x81, + VKEY_F19 = 0x82, + VKEY_F20 = 0x83, + VKEY_F21 = 0x84, + VKEY_F22 = 0x85, + VKEY_F23 = 0x86, + VKEY_F24 = 0x87, + VKEY_NUMLOCK = 0x90, + VKEY_SCROLL = 0x91, + VKEY_LSHIFT = 0xA0, + VKEY_RSHIFT = 0xA1, + VKEY_LCONTROL = 0xA2, + VKEY_RCONTROL = 0xA3, + VKEY_LMENU = 0xA4, + VKEY_RMENU = 0xA5, + VKEY_BROWSER_BACK = 0xA6, + VKEY_BROWSER_FORWARD = 0xA7, + VKEY_BROWSER_REFRESH = 0xA8, + VKEY_BROWSER_STOP = 0xA9, + VKEY_BROWSER_SEARCH = 0xAA, + VKEY_BROWSER_FAVORITES = 0xAB, + VKEY_BROWSER_HOME = 0xAC, + VKEY_VOLUME_MUTE = 0xAD, + VKEY_VOLUME_DOWN = 0xAE, + VKEY_VOLUME_UP = 0xAF, + VKEY_MEDIA_NEXT_TRACK = 0xB0, + VKEY_MEDIA_PREV_TRACK = 0xB1, + VKEY_MEDIA_STOP = 0xB2, + VKEY_MEDIA_PLAY_PAUSE = 0xB3, + VKEY_MEDIA_LAUNCH_MAIL = 0xB4, + VKEY_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5, + VKEY_MEDIA_LAUNCH_APP1 = 0xB6, + VKEY_MEDIA_LAUNCH_APP2 = 0xB7, + VKEY_OEM_1 = 0xBA, + VKEY_OEM_PLUS = 0xBB, + VKEY_OEM_COMMA = 0xBC, + VKEY_OEM_MINUS = 0xBD, + VKEY_OEM_PERIOD = 0xBE, + VKEY_OEM_2 = 0xBF, + VKEY_OEM_3 = 0xC0, + VKEY_OEM_4 = 0xDB, + VKEY_OEM_5 = 0xDC, + VKEY_OEM_6 = 0xDD, + VKEY_OEM_7 = 0xDE, + VKEY_OEM_8 = 0xDF, + VKEY_OEM_102 = 0xE2, + VKEY_OEM_103 = 0xE3, // GTV KEYCODE_MEDIA_REWIND + VKEY_OEM_104 = 0xE4, // GTV KEYCODE_MEDIA_FAST_FORWARD + VKEY_PROCESSKEY = 0xE5, + VKEY_PACKET = 0xE7, + VKEY_DBE_SBCSCHAR = 0xF3, + VKEY_DBE_DBCSCHAR = 0xF4, + VKEY_ATTN = 0xF6, + VKEY_CRSEL = 0xF7, + VKEY_EXSEL = 0xF8, + VKEY_EREOF = 0xF9, + VKEY_PLAY = 0xFA, + VKEY_ZOOM = 0xFB, + VKEY_NONAME = 0xFC, + VKEY_PA1 = 0xFD, + VKEY_OEM_CLEAR = 0xFE, + VKEY_UNKNOWN = 0, + + // POSIX specific VKEYs. Note that as of Windows SDK 7.1, 0x97-9F, 0xD8-DA, + // and 0xE8 are unassigned. + VKEY_WLAN = 0x97, + VKEY_POWER = 0x98, + VKEY_BRIGHTNESS_DOWN = 0xD8, + VKEY_BRIGHTNESS_UP = 0xD9, + VKEY_KBD_BRIGHTNESS_DOWN = 0xDA, + VKEY_KBD_BRIGHTNESS_UP = 0xE8, + + // Windows does not have a specific key code for AltGr. We use the unused 0xE1 + // (VK_OEM_AX) code to represent AltGr, matching the behaviour of Firefox on + // Linux. + VKEY_ALTGR = 0xE1, + // Windows does not have a specific key code for Compose. We use the unused + // 0xE6 (VK_ICO_CLEAR) code to represent Compose. + VKEY_COMPOSE = 0xE6, +} + +// this is way too much work to do 100% correctly right now. +// see xkb_keyboard_layout_engine.cc -> XkbKeyboardLayoutEngine::Lookup in chromium for details +fn get_key_msg(keycode: c_int, character: u16) -> Option { + let code: KeyboardCode = unsafe { transmute(keycode as u8) }; + match code { + KeyboardCode::VKEY_BACK => Some(constellation_msg::Key::Backspace), + KeyboardCode::VKEY_RIGHT => Some(constellation_msg::Key::Right), + KeyboardCode::VKEY_LEFT => Some(constellation_msg::Key::Left), + KeyboardCode::VKEY_UP => Some(constellation_msg::Key::Up), + KeyboardCode::VKEY_DOWN => Some(constellation_msg::Key::Down), + KeyboardCode::VKEY_RSHIFT => Some(constellation_msg::Key::RightShift), + KeyboardCode::VKEY_SHIFT | KeyboardCode::VKEY_LSHIFT => Some(constellation_msg::Key::LeftShift), + KeyboardCode::VKEY_RCONTROL => Some(constellation_msg::Key::RightControl), + KeyboardCode::VKEY_CONTROL | KeyboardCode::VKEY_LCONTROL => Some(constellation_msg::Key::LeftControl), + KeyboardCode::VKEY_LWIN => Some(constellation_msg::Key::LeftSuper), + KeyboardCode::VKEY_RWIN => Some(constellation_msg::Key::RightSuper), + KeyboardCode::VKEY_MENU => Some(constellation_msg::Key::LeftAlt), + KeyboardCode::VKEY_APPS => Some(constellation_msg::Key::Menu), + KeyboardCode::VKEY_ALTGR => Some(constellation_msg::Key::RightAlt), //not sure if correct... + KeyboardCode::VKEY_ESCAPE => Some(constellation_msg::Key::Escape), + KeyboardCode::VKEY_INSERT => Some(constellation_msg::Key::Insert), + KeyboardCode::VKEY_DELETE => Some(constellation_msg::Key::Delete), + KeyboardCode::VKEY_NEXT => Some(constellation_msg::Key::PageUp), + KeyboardCode::VKEY_PRIOR => Some(constellation_msg::Key::PageDown), + KeyboardCode::VKEY_HOME => Some(constellation_msg::Key::Home), + KeyboardCode::VKEY_END => Some(constellation_msg::Key::End), + KeyboardCode::VKEY_CAPITAL => Some(constellation_msg::Key::CapsLock), + KeyboardCode::VKEY_F1 => Some(constellation_msg::Key::F1), + KeyboardCode::VKEY_F2 => Some(constellation_msg::Key::F2), + KeyboardCode::VKEY_F3 => Some(constellation_msg::Key::F3), + KeyboardCode::VKEY_F4 => Some(constellation_msg::Key::F4), + KeyboardCode::VKEY_F5 => Some(constellation_msg::Key::F5), + KeyboardCode::VKEY_F6 => Some(constellation_msg::Key::F6), + KeyboardCode::VKEY_F7 => Some(constellation_msg::Key::F7), + KeyboardCode::VKEY_F8 => Some(constellation_msg::Key::F8), + KeyboardCode::VKEY_F9 => Some(constellation_msg::Key::F9), + KeyboardCode::VKEY_F10 => Some(constellation_msg::Key::F10), + KeyboardCode::VKEY_F11 => Some(constellation_msg::Key::F11), + KeyboardCode::VKEY_F12 => Some(constellation_msg::Key::F12), + KeyboardCode::VKEY_F13 => Some(constellation_msg::Key::F13), + KeyboardCode::VKEY_F14 => Some(constellation_msg::Key::F14), + KeyboardCode::VKEY_F15 => Some(constellation_msg::Key::F15), + KeyboardCode::VKEY_F16 => Some(constellation_msg::Key::F16), + KeyboardCode::VKEY_F17 => Some(constellation_msg::Key::F17), + KeyboardCode::VKEY_F18 => Some(constellation_msg::Key::F18), + KeyboardCode::VKEY_F19 => Some(constellation_msg::Key::F19), + KeyboardCode::VKEY_F20 => Some(constellation_msg::Key::F20), + KeyboardCode::VKEY_F21 => Some(constellation_msg::Key::F21), + KeyboardCode::VKEY_F22 => Some(constellation_msg::Key::F22), + KeyboardCode::VKEY_F23 => Some(constellation_msg::Key::F23), + KeyboardCode::VKEY_F24 => Some(constellation_msg::Key::F24), + KeyboardCode::VKEY_NUMPAD0 => Some(constellation_msg::Key::Kp0), + KeyboardCode::VKEY_NUMPAD1 => Some(constellation_msg::Key::Kp1), + KeyboardCode::VKEY_NUMPAD2 => Some(constellation_msg::Key::Kp2), + KeyboardCode::VKEY_NUMPAD3 => Some(constellation_msg::Key::Kp3), + KeyboardCode::VKEY_NUMPAD4 => Some(constellation_msg::Key::Kp4), + KeyboardCode::VKEY_NUMPAD5 => Some(constellation_msg::Key::Kp5), + KeyboardCode::VKEY_NUMPAD6 => Some(constellation_msg::Key::Kp6), + KeyboardCode::VKEY_NUMPAD7 => Some(constellation_msg::Key::Kp7), + KeyboardCode::VKEY_NUMPAD8 => Some(constellation_msg::Key::Kp8), + KeyboardCode::VKEY_NUMPAD9 => Some(constellation_msg::Key::Kp9), + KeyboardCode::VKEY_DECIMAL => Some(constellation_msg::Key::KpDecimal), + KeyboardCode::VKEY_DIVIDE => Some(constellation_msg::Key::KpDivide), + KeyboardCode::VKEY_MULTIPLY => Some(constellation_msg::Key::KpMultiply), + KeyboardCode::VKEY_SUBTRACT => Some(constellation_msg::Key::KpSubtract), + KeyboardCode::VKEY_ADD => Some(constellation_msg::Key::KpAdd), + KeyboardCode::VKEY_NUMLOCK => Some(constellation_msg::Key::NumLock), + KeyboardCode::VKEY_PRINT => Some(constellation_msg::Key::PrintScreen), + KeyboardCode::VKEY_PAUSE => Some(constellation_msg::Key::Pause), + //VKEY_BACK + _ => { match character as u8 { + b'[' => Some(constellation_msg::Key::LeftBracket), + b']' => Some(constellation_msg::Key::RightBracket), + b'=' => Some(constellation_msg::Key::Equal), + b';' => Some(constellation_msg::Key::Semicolon), + b'/' => Some(constellation_msg::Key::Slash), + b'.' => Some(constellation_msg::Key::Period), + b'-' => Some(constellation_msg::Key::Minus), + b',' => Some(constellation_msg::Key::Comma), + b'\'' => Some(constellation_msg::Key::Apostrophe), + b'\\' => Some(constellation_msg::Key::Backslash), + b'`' => Some(constellation_msg::Key::GraveAccent), + b'\t' => Some(constellation_msg::Key::Tab), + b'a' | b'A' => Some(constellation_msg::Key::A), + b'b' | b'B' => Some(constellation_msg::Key::B), + b'c' | b'C' => Some(constellation_msg::Key::C), + b'd' | b'D' => Some(constellation_msg::Key::D), + b'e' | b'E' => Some(constellation_msg::Key::E), + b'f' | b'F' => Some(constellation_msg::Key::F), + b'g' | b'G' => Some(constellation_msg::Key::G), + b'h' | b'H' => Some(constellation_msg::Key::H), + b'i' | b'I' => Some(constellation_msg::Key::I), + b'j' | b'J' => Some(constellation_msg::Key::J), + b'k' | b'K' => Some(constellation_msg::Key::K), + b'l' | b'L' => Some(constellation_msg::Key::L), + b'm' | b'M' => Some(constellation_msg::Key::M), + b'n' | b'N' => Some(constellation_msg::Key::N), + b'o' | b'O' => Some(constellation_msg::Key::O), + b'p' | b'P' => Some(constellation_msg::Key::P), + b'q' | b'Q' => Some(constellation_msg::Key::Q), + b'r' | b'R' => Some(constellation_msg::Key::R), + b's' | b'S' => Some(constellation_msg::Key::S), + b't' | b'T' => Some(constellation_msg::Key::T), + b'u' | b'U' => Some(constellation_msg::Key::U), + b'v' | b'V' => Some(constellation_msg::Key::V), + b'w' | b'W' => Some(constellation_msg::Key::W), + b'x' | b'X' => Some(constellation_msg::Key::X), + b'y' | b'Y' => Some(constellation_msg::Key::Y), + b'z' | b'Z' => Some(constellation_msg::Key::Z), + b'0' => Some(constellation_msg::Key::Num0), + b'1' => Some(constellation_msg::Key::Num1), + b'2' => Some(constellation_msg::Key::Num2), + b'3' => Some(constellation_msg::Key::Num3), + b'4' => Some(constellation_msg::Key::Num4), + b'5' => Some(constellation_msg::Key::Num5), + b'6' => Some(constellation_msg::Key::Num6), + b'7' => Some(constellation_msg::Key::Num7), + b'8' => Some(constellation_msg::Key::Num8), + b'9' => Some(constellation_msg::Key::Num9), + b'\n' | b'\r' => Some(constellation_msg::Key::Enter), + b' ' => Some(constellation_msg::Key::Space), + _ => None + } + } + } +} + +// unhandled +//pub enum Key { + //World1, + //World2, + //ScrollLock, + //KpEnter, + //KpEqual, + //RightAlt, +//} + full_cef_class_impl! { ServoCefBrowserHost : CefBrowserHost, cef_browser_host_t { fn get_client(&this,) -> *mut cef_client_t {{ @@ -67,48 +399,13 @@ full_cef_class_impl! { }} fn send_key_event(&this, event: *const cef_key_event [&cef_key_event],) -> () {{ - // FIXME(pcwalton): So awful. But it's nearly midnight here and I have to get - // Google working. let event: &cef_key_event = event; - let key = match (*event).character as u8 { - b'a' | b'A' => constellation_msg::Key::A, - b'b' | b'B' => constellation_msg::Key::B, - b'c' | b'C' => constellation_msg::Key::C, - b'd' | b'D' => constellation_msg::Key::D, - b'e' | b'E' => constellation_msg::Key::E, - b'f' | b'F' => constellation_msg::Key::F, - b'g' | b'G' => constellation_msg::Key::G, - b'h' | b'H' => constellation_msg::Key::H, - b'i' | b'I' => constellation_msg::Key::I, - b'j' | b'J' => constellation_msg::Key::J, - b'k' | b'K' => constellation_msg::Key::K, - b'l' | b'L' => constellation_msg::Key::L, - b'm' | b'M' => constellation_msg::Key::M, - b'n' | b'N' => constellation_msg::Key::N, - b'o' | b'O' => constellation_msg::Key::O, - b'p' | b'P' => constellation_msg::Key::P, - b'q' | b'Q' => constellation_msg::Key::Q, - b'r' | b'R' => constellation_msg::Key::R, - b's' | b'S' => constellation_msg::Key::S, - b't' | b'T' => constellation_msg::Key::T, - b'u' | b'U' => constellation_msg::Key::U, - b'v' | b'V' => constellation_msg::Key::V, - b'w' | b'W' => constellation_msg::Key::W, - b'x' | b'X' => constellation_msg::Key::X, - b'y' | b'Y' => constellation_msg::Key::Y, - b'z' | b'Z' => constellation_msg::Key::Z, - b'0' => constellation_msg::Key::Num0, - b'1' => constellation_msg::Key::Num1, - b'2' => constellation_msg::Key::Num2, - b'3' => constellation_msg::Key::Num3, - b'4' => constellation_msg::Key::Num4, - b'5' => constellation_msg::Key::Num5, - b'6' => constellation_msg::Key::Num6, - b'7' => constellation_msg::Key::Num7, - b'8' => constellation_msg::Key::Num8, - b'9' => constellation_msg::Key::Num9, - b'\n' | b'\r' => constellation_msg::Key::Enter, - _ => constellation_msg::Key::Space, + let key = match get_key_msg((*event).windows_key_code, (*event).character) { + Some(keycode) => keycode, + None => { + error!("Unhandled keycode({}) passed!", (*event).windows_key_code); + return; + } }; let key_state = match (*event).t { // in tests with cef-real, this event had no effect From 1e4ceb0a1f3856fbef338bb715ac0f91cfe21190 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Thu, 21 May 2015 16:32:08 -0400 Subject: [PATCH 11/27] more accurately handle key modifiers in cef --- ports/cef/browser_host.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ports/cef/browser_host.rs b/ports/cef/browser_host.rs index 4c6686ee0e2..7c0e7f9f1ff 100644 --- a/ports/cef/browser_host.rs +++ b/ports/cef/browser_host.rs @@ -6,6 +6,7 @@ use eutil::Downcast; use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_t, cef_browser_host_t, cef_client_t}; use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t, cef_key_event, cef_window_handle_t}; use types::cef_key_event_type_t::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN}; +use types::cef_event_flags_t::{EVENTFLAG_ALT_DOWN, EVENTFLAG_CONTROL_DOWN, EVENTFLAG_SHIFT_DOWN}; use browser::{self, ServoCefBrowserExtensions}; use wrappers::CefWrap; @@ -17,6 +18,7 @@ use msg::constellation_msg::{self, KeyModifiers, KeyState}; use script_traits::MouseButton; use std::cell::{Cell, RefCell}; use std::mem::transmute; +use std::intrinsics; pub struct ServoCefBrowserHost { /// A reference to the browser. @@ -414,7 +416,16 @@ full_cef_class_impl! { KEYEVENT_CHAR => KeyState::Repeated, KEYEVENT_KEYUP => KeyState::Released, }; - let key_modifiers = KeyModifiers::empty(); // TODO(pcwalton) + let mut key_modifiers = KeyModifiers::empty(); + if (*event).modifiers & unsafe { intrinsics::discriminant_value(&EVENTFLAG_SHIFT_DOWN) as u32 } != 0 { + key_modifiers = key_modifiers | constellation_msg::SHIFT; + } + if (*event).modifiers & unsafe { intrinsics::discriminant_value(&EVENTFLAG_CONTROL_DOWN) as u32 } != 0 { + key_modifiers = key_modifiers | constellation_msg::CONTROL; + } + if (*event).modifiers & unsafe { intrinsics::discriminant_value(&EVENTFLAG_ALT_DOWN) as u32 } != 0 { + key_modifiers = key_modifiers | constellation_msg::ALT; + } this.downcast().send_window_event(WindowEvent::KeyEvent(key, key_state, key_modifiers)) }} From cd9dab7b5bf69347e6ebd34b3f6761b55891effa Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 22 May 2015 16:46:26 -0400 Subject: [PATCH 12/27] implement cef_load_handler::on_load_start() --- ports/cef/window.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ports/cef/window.rs b/ports/cef/window.rs index bab2d5bbac0..a5a70cb19d2 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -361,6 +361,9 @@ impl WindowMethods for Window { } fn set_page_url(&self, url: Url) { + // it seems to be the case that load start is always called + // IMMEDIATELY before address change, so just stick it here + on_load_start(self); let browser = self.cef_browser.borrow(); let browser = match *browser { None => return, @@ -455,6 +458,21 @@ impl CompositorProxy for CefCompositorProxy { } } +fn on_load_start(window: &Window) { + let browser = window.cef_browser.borrow(); + let browser = match *browser { + None => return, + Some(ref browser) => browser, + }; + if check_ptr_exist!(browser.get_host().get_client(), get_load_handler) && + check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_load_start) { + browser.get_host() + .get_client() + .get_load_handler() + .on_load_start((*browser).clone(), browser.get_main_frame()); + } +} + #[cfg(target_os="linux")] pub fn init_window() { unsafe { From 3481c752cd6514a50980044e425d65de80ebf608 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 22 May 2015 16:46:55 -0400 Subject: [PATCH 13/27] add CompositorMsg::LoadStart, implement cef_load_handler::on_loading_state_change() only adds the loading:true callback this time... --- components/compositing/compositor.rs | 4 ++++ components/compositing/compositor_task.rs | 3 +++ components/compositing/constellation.rs | 19 +++++++++++++++++++ components/compositing/headless.rs | 1 + components/compositing/windowing.rs | 2 ++ ports/cef/window.rs | 16 ++++++++++++++++ ports/glutin/window.rs | 3 +++ ports/gonk/src/window.rs | 3 +++ 8 files changed, 51 insertions(+) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index a50b51ebc0e..0d2b7f08b38 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -384,6 +384,10 @@ impl IOCompositor { self.scroll_fragment_to_point(pipeline_id, layer_id, point); } + (Msg::LoadStart(back, forward), ShutdownState::NotShuttingDown) => { + self.window.load_start(back, forward); + } + (Msg::LoadComplete, ShutdownState::NotShuttingDown) => { self.got_load_complete_message = true; diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index 904e69da83b..1eb4ac215e0 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -160,6 +160,8 @@ pub enum Msg { ChangeRunningAnimationsState(PipelineId, AnimationState), /// Replaces the current frame tree, typically called during main frame navigation. SetFrameTree(SendableFrameTree, Sender<()>, ConstellationChan), + /// The load of a page has begun: (can go back, can go forward). + LoadStart(bool, bool), /// The load of a page has completed. LoadComplete, /// Indicates that the scrolling timeout with the given starting timestamp has happened and a @@ -195,6 +197,7 @@ impl Debug for Msg { Msg::ChangePageUrl(..) => write!(f, "ChangePageUrl"), Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), Msg::LoadComplete => write!(f, "LoadComplete"), + Msg::LoadStart(..) => write!(f, "LoadStart"), Msg::ScrollTimeout(..) => write!(f, "ScrollTimeout"), Msg::RecompositeAfterScroll => write!(f, "RecompositeAfterScroll"), Msg::KeyEvent(..) => write!(f, "KeyEvent"), diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 750c124a13a..59d5c5444fa 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -520,6 +520,7 @@ impl Constellation { let window_rect = Rect(Point2D::zero(), self.window_size.visible_viewport); let root_pipeline_id = self.new_pipeline(None, Some(window_rect), None, LoadData::new(url.clone())); + self.handle_load_start_msg(&root_pipeline_id); self.push_pending_frame(root_pipeline_id, None); self.compositor_proxy.send(CompositorMsg::ChangePageUrl(root_pipeline_id, url)); } @@ -630,6 +631,7 @@ impl Constellation { // requested change so it can update its internal state. match self.pipeline(source_id).parent_info { Some((parent_pipeline_id, subpage_id)) => { + self.handle_load_start_msg(&source_id); // Message the constellation to find the script task for this iframe // and issue an iframe load through there. let parent_pipeline = self.pipeline(parent_pipeline_id); @@ -647,6 +649,7 @@ impl Constellation { } } + self.handle_load_start_msg(&source_id); // Being here means either there are no pending frames, or none of the pending // changes would be overridden by changing the subframe associated with source_id. @@ -662,6 +665,22 @@ impl Constellation { } } + fn handle_load_start_msg(&mut self, pipeline_id: &PipelineId) { + let mut back = false; + let mut forward = false; + let frameid = self.pipeline_to_frame_map.get(pipeline_id); + match frameid { + Some(frame_id) => { + forward = if !self.frame(*frame_id).next.is_empty() { true } + else { false }; + back = if !self.frame(*frame_id).prev.is_empty() { true } + else { false }; + }, + None => {} + }; + self.compositor_proxy.send(CompositorMsg::LoadStart(back, forward)); + } + fn handle_load_complete_msg(&mut self) { self.compositor_proxy.send(CompositorMsg::LoadComplete); if let Some(ref reply_chan) = self.webdriver.load_channel { diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index 2f9aa30e744..e289cc12dd9 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -97,6 +97,7 @@ impl CompositorEventListener for NullCompositor { Msg::AssignPaintedBuffers(..) | Msg::ChangeRunningAnimationsState(..) | Msg::ScrollFragmentPoint(..) | + Msg::LoadStart(..) | Msg::LoadComplete | Msg::ScrollTimeout(..) | Msg::RecompositeAfterScroll | diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 196e1e2653f..ec215a93edd 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -103,6 +103,8 @@ pub trait WindowMethods { fn set_page_title(&self, title: Option); /// Sets the load data for the current page. fn set_page_url(&self, url: Url); + /// Called when the browser has started loading a frame. + fn load_start(&self, back: bool, forward: bool); /// Called when the browser is done loading a frame. fn load_end(&self); diff --git a/ports/cef/window.rs b/ports/cef/window.rs index a5a70cb19d2..f0dac467033 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -315,6 +315,22 @@ impl WindowMethods for Window { } } + 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, + Some(ref browser) => browser, + }; + 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() + .get_client() + .get_load_handler() + .on_loading_state_change((*browser).clone(), 1i32, back as i32, forward as i32); + } + } + fn load_end(&self) { // FIXME(pcwalton): The status code 200 is a lie. let browser = self.cef_browser.borrow(); diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 8caa33d286e..df7bc24eea0 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -505,6 +505,9 @@ impl WindowMethods for Window { fn set_page_url(&self, _: Url) { } + fn load_start(&self, _: bool, _: bool) { + } + fn load_end(&self) { } diff --git a/ports/gonk/src/window.rs b/ports/gonk/src/window.rs index 632f0257855..8d480dde8e4 100644 --- a/ports/gonk/src/window.rs +++ b/ports/gonk/src/window.rs @@ -802,6 +802,9 @@ impl WindowMethods for Window { fn set_page_url(&self, _: Url) { } + fn load_start(&self, _: bool, _: bool) { + } + fn load_end(&self) { } From 0d46a3b89a3fb56340b4109b6ecb17cd8da7d3af Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 22 May 2015 16:57:47 -0400 Subject: [PATCH 14/27] add navigation state data to LoadComplete messages, finish cef load state cbs --- components/compositing/compositor.rs | 4 ++-- components/compositing/compositor_task.rs | 6 +++--- components/compositing/constellation.rs | 12 ++++++++---- components/compositing/headless.rs | 2 +- components/compositing/windowing.rs | 2 +- components/msg/constellation_msg.rs | 2 +- components/script/script_task.rs | 2 +- ports/cef/window.rs | 9 ++++++++- ports/glutin/window.rs | 2 +- ports/gonk/src/window.rs | 2 +- 10 files changed, 27 insertions(+), 16 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 0d2b7f08b38..18f6618a58c 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -388,7 +388,7 @@ impl IOCompositor { self.window.load_start(back, forward); } - (Msg::LoadComplete, ShutdownState::NotShuttingDown) => { + (Msg::LoadComplete(back, forward), ShutdownState::NotShuttingDown) => { self.got_load_complete_message = true; // If we're painting in headless mode, schedule a recomposite. @@ -399,7 +399,7 @@ impl IOCompositor { // Inform the embedder that the load has finished. // // TODO(pcwalton): Specify which frame's load completed. - self.window.load_end(); + self.window.load_end(back, forward); } (Msg::ScrollTimeout(timestamp), ShutdownState::NotShuttingDown) => { diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index 1eb4ac215e0..9a47fce1600 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -162,8 +162,8 @@ pub enum Msg { SetFrameTree(SendableFrameTree, Sender<()>, ConstellationChan), /// The load of a page has begun: (can go back, can go forward). LoadStart(bool, bool), - /// The load of a page has completed. - LoadComplete, + /// The load of a page has completed: (can go back, can go forward). + LoadComplete(bool, bool), /// Indicates that the scrolling timeout with the given starting timestamp has happened and a /// composite should happen. (See the `scrolling` module.) ScrollTimeout(u64), @@ -196,7 +196,7 @@ impl Debug for Msg { Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"), Msg::ChangePageUrl(..) => write!(f, "ChangePageUrl"), Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), - Msg::LoadComplete => write!(f, "LoadComplete"), + Msg::LoadComplete(..) => write!(f, "LoadComplete"), Msg::LoadStart(..) => write!(f, "LoadStart"), Msg::ScrollTimeout(..) => write!(f, "ScrollTimeout"), Msg::RecompositeAfterScroll => write!(f, "RecompositeAfterScroll"), diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 59d5c5444fa..bfcb0693c1e 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -391,9 +391,9 @@ impl Constellation { } // A page loaded through one of several methods above has completed all parsing, // script, and reflow messages have been sent. - ConstellationMsg::LoadComplete => { + ConstellationMsg::LoadComplete(pipeline_id) => { debug!("constellation got load complete message"); - self.handle_load_complete_msg() + self.handle_load_complete_msg(&pipeline_id) } // Handle a forward or back request ConstellationMsg::Navigate(pipeline_info, direction) => { @@ -681,8 +681,12 @@ impl Constellation { self.compositor_proxy.send(CompositorMsg::LoadStart(back, forward)); } - fn handle_load_complete_msg(&mut self) { - self.compositor_proxy.send(CompositorMsg::LoadComplete); + fn handle_load_complete_msg(&mut self, pipeline_id: &PipelineId) { + let frame_id = *self.pipeline_to_frame_map.get(pipeline_id).unwrap(); + + let forward = !self.mut_frame(frame_id).next.is_empty(); + let back = !self.mut_frame(frame_id).prev.is_empty(); + self.compositor_proxy.send(CompositorMsg::LoadComplete(back, forward)); if let Some(ref reply_chan) = self.webdriver.load_channel { reply_chan.send(webdriver_traits::LoadComplete).unwrap(); } diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index e289cc12dd9..c58532e81ed 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -98,7 +98,7 @@ impl CompositorEventListener for NullCompositor { Msg::ChangeRunningAnimationsState(..) | Msg::ScrollFragmentPoint(..) | Msg::LoadStart(..) | - Msg::LoadComplete | + Msg::LoadComplete(..) | Msg::ScrollTimeout(..) | Msg::RecompositeAfterScroll | Msg::ChangePageTitle(..) | diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index ec215a93edd..51a97ec86f4 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -106,7 +106,7 @@ pub trait WindowMethods { /// Called when the browser has started loading a frame. fn load_start(&self, back: bool, forward: bool); /// Called when the browser is done loading a frame. - fn load_end(&self); + fn load_end(&self, back: bool, forward: bool); /// Returns the hidpi factor of the monitor. fn hidpi_factor(&self) -> ScaleFactor; diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 623f801ddb4..8706a807cab 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -211,7 +211,7 @@ pub enum Msg { Exit, Failure(Failure), InitLoadUrl(Url), - LoadComplete, + LoadComplete(PipelineId), FrameRect(PipelineId, SubpageId, Rect), LoadUrl(PipelineId, LoadData), ScriptLoadedURLInIFrame(Url, PipelineId, SubpageId, Option, IFrameSandboxState), diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 573827cc267..cad737b4af4 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -960,7 +960,7 @@ impl ScriptTask { self.chan.send(ScriptMsg::RunnableMsg(handler)).unwrap(); let ConstellationChan(ref chan) = self.constellation_chan; - chan.send(ConstellationMsg::LoadComplete).unwrap(); + chan.send(ConstellationMsg::LoadComplete(pipeline)).unwrap(); } /// Handles a timer that fired. diff --git a/ports/cef/window.rs b/ports/cef/window.rs index f0dac467033..7fc1222efa2 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -331,13 +331,20 @@ impl WindowMethods for Window { } } - fn load_end(&self) { + fn load_end(&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, Some(ref browser) => browser, }; + 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() + .get_client() + .get_load_handler() + .on_loading_state_change((*browser).clone(), 0i32, back as i32, forward as i32); + } if check_ptr_exist!(browser.get_host().get_client(), get_load_handler) && check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_load_end) { browser.get_host() diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index df7bc24eea0..16d8c509317 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -508,7 +508,7 @@ impl WindowMethods for Window { fn load_start(&self, _: bool, _: bool) { } - fn load_end(&self) { + fn load_end(&self, _: bool, _: bool) { } /// Has no effect on Android. diff --git a/ports/gonk/src/window.rs b/ports/gonk/src/window.rs index 8d480dde8e4..f751d239e42 100644 --- a/ports/gonk/src/window.rs +++ b/ports/gonk/src/window.rs @@ -805,7 +805,7 @@ impl WindowMethods for Window { fn load_start(&self, _: bool, _: bool) { } - fn load_end(&self) { + fn load_end(&self, _: bool, _: bool) { } fn hidpi_factor(&self) -> ScaleFactor { From 3f8d8a3cc961f8e6be8ec2c4bf12dda3251d045f Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Fri, 22 May 2015 17:13:13 -0400 Subject: [PATCH 15/27] add back/forward/loading members to ServoCefBrowser with related browser methods --- ports/cef/browser.rs | 21 +++++++++++++++++++++ ports/cef/window.rs | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index 98681198db2..3eb8a70c730 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -60,6 +60,18 @@ cef_class_impl! { this.downcast().host.clone() }} + fn can_go_back(&this,) -> c_int {{ + this.downcast().back.get() as c_int + }} + + fn can_go_forward(&this,) -> c_int {{ + this.downcast().forward.get() as c_int + }} + + fn is_loading(&this,) -> c_int {{ + this.downcast().loading.get() as c_int + }} + fn go_back(&this,) -> () {{ this.send_window_event(WindowEvent::Navigation(WindowNavigateMsg::Back)); }} @@ -90,6 +102,12 @@ pub struct ServoCefBrowser { pub window: Option>, /// Whether the on-created callback has fired yet. pub callback_executed: Cell, + /// whether the browser can navigate back + pub back: Cell, + /// whether the browser can navigate forward + pub forward: Cell, + /// whether the browser is loading + pub loading: Cell, /// the display system window handle: only to be used with host.get_window_handle() window_handle: cef_window_handle_t, @@ -130,6 +148,9 @@ impl ServoCefBrowser { servo_browser: RefCell::new(servo_browser), message_queue: RefCell::new(vec!()), id: id, + back: Cell::new(false), + forward: Cell::new(false), + loading: Cell::new(false), window_handle: window_handle, } } diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 7fc1222efa2..af0f89f36be 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -322,6 +322,9 @@ impl WindowMethods for Window { None => return, Some(ref browser) => browser, }; + browser.downcast().loading.set(true); + browser.downcast().back.set(back); + browser.downcast().forward.set(forward); 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() @@ -338,6 +341,9 @@ impl WindowMethods for Window { None => return, Some(ref browser) => browser, }; + browser.downcast().loading.set(false); + browser.downcast().back.set(back); + browser.downcast().forward.set(forward); 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() From 68fc51205f1fe74c8faaadbeaeda5aefbf5986b0 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 13:26:47 -0400 Subject: [PATCH 16/27] add error enum for chromium net errors, create window method for error propagation --- components/compositing/windowing.rs | 3 + components/net/lib.rs | 1 + components/net/net_error_list.rs | 203 ++++++++++++++++++++++++++++ ports/cef/Cargo.lock | 1 + ports/cef/window.rs | 4 + ports/glutin/Cargo.toml | 3 + ports/glutin/lib.rs | 1 + ports/glutin/window.rs | 4 + ports/gonk/src/window.rs | 4 + 9 files changed, 224 insertions(+) create mode 100644 components/net/net_error_list.rs diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 51a97ec86f4..1b1cac23025 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -12,6 +12,7 @@ use geom::size::TypedSize2D; use layers::geometry::DevicePixel; use layers::platform::surface::NativeGraphicsMetadata; use msg::constellation_msg::{Key, KeyState, KeyModifiers}; +use net::net_error_list::NetError; use script_traits::MouseButton; use url::Url; use util::cursor::Cursor; @@ -107,6 +108,8 @@ pub trait WindowMethods { fn load_start(&self, back: bool, forward: bool); /// Called when the browser is done loading a frame. 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); /// Returns the hidpi factor of the monitor. fn hidpi_factor(&self) -> ScaleFactor; diff --git a/components/net/lib.rs b/components/net/lib.rs index d00f458b505..6e845bbff0a 100644 --- a/components/net/lib.rs +++ b/components/net/lib.rs @@ -39,6 +39,7 @@ pub mod data_loader; pub mod cookie; pub mod cookie_storage; pub mod image_cache_task; +pub mod net_error_list; pub mod pub_domains; pub mod resource_task; pub mod storage_task; diff --git a/components/net/net_error_list.rs b/components/net/net_error_list.rs new file mode 100644 index 00000000000..a09be7b07de --- /dev/null +++ b/components/net/net_error_list.rs @@ -0,0 +1,203 @@ +/* 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/. */ + +// see https://github.com/adobe/chromium/blob/master/net/base/net_error_list.h +#[allow(dead_code, non_camel_case_types)] +pub enum NetError { + IO_PENDING = 1, + FAILED = 2, + ABORTED = 3, + INVALID_ARGUMENT = 4, + INVALID_HANDLE = 5, + FILE_NOT_FOUND = 6, + TIMED_OUT = 7, + FILE_TOO_BIG = 8, + UNEXPECTED = 9, + ACCESS_DENIED = 10, + NOT_IMPLEMENTED = 11, + INSUFFICIENT_RESOURCES = 12, + OUT_OF_MEMORY = 13, + UPLOAD_FILE_CHANGED = 14, + SOCKET_NOT_CONNECTED = 15, + FILE_EXISTS = 16, + FILE_PATH_TOO_LONG = 17, + FILE_NO_SPACE = 18, + FILE_VIRUS_INFECTED = 19, + BLOCKED_BY_CLIENT = 20, + NETWORK_CHANGED = 21, + BLOCKED_BY_ADMINISTRATOR = 22, + SOCKET_IS_CONNECTED = 23, + BLOCKED_ENROLLMENT_CHECK_PENDING = 24, + UPLOAD_STREAM_REWIND_NOT_SUPPORTED = 25, + CONNECTION_CLOSED = 100, + CONNECTION_RESET = 101, + CONNECTION_REFUSED = 102, + CONNECTION_ABORTED = 103, + CONNECTION_FAILED = 104, + NAME_NOT_RESOLVED = 105, + INTERNET_DISCONNECTED = 106, + SSL_PROTOCOL_ERROR = 107, + ADDRESS_INVALID = 108, + ADDRESS_UNREACHABLE = 109, + SSL_CLIENT_AUTH_CERT_NEEDED = 110, + TUNNEL_CONNECTION_FAILED = 111, + NO_SSL_VERSIONS_ENABLED = 112, + SSL_VERSION_OR_CIPHER_MISMATCH = 113, + SSL_RENEGOTIATION_REQUESTED = 114, + PROXY_AUTH_UNSUPPORTED = 115, + CERT_ERROR_IN_SSL_RENEGOTIATION = 116, + BAD_SSL_CLIENT_AUTH_CERT = 117, + CONNECTION_TIMED_OUT = 118, + HOST_RESOLVER_QUEUE_TOO_LARGE = 119, + SOCKS_CONNECTION_FAILED = 120, + SOCKS_CONNECTION_HOST_UNREACHABLE = 121, + NPN_NEGOTIATION_FAILED = 122, + SSL_NO_RENEGOTIATION = 123, + WINSOCK_UNEXPECTED_WRITTEN_BYTES = 124, + SSL_DECOMPRESSION_FAILURE_ALERT = 125, + SSL_BAD_RECORD_MAC_ALERT = 126, + PROXY_AUTH_REQUESTED = 127, + SSL_UNSAFE_NEGOTIATION = 128, + SSL_WEAK_SERVER_EPHEMERAL_DH_KEY = 129, + PROXY_CONNECTION_FAILED = 130, + MANDATORY_PROXY_CONFIGURATION_FAILED = 131, + PRECONNECT_MAX_SOCKET_LIMIT = 133, + SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED = 134, + SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY = 135, + PROXY_CERTIFICATE_INVALID = 136, + NAME_RESOLUTION_FAILED = 137, + NETWORK_ACCESS_DENIED = 138, + TEMPORARILY_THROTTLED = 139, + HTTPS_PROXY_TUNNEL_RESPONSE = 140, + SSL_CLIENT_AUTH_SIGNATURE_FAILED = 141, + MSG_TOO_BIG = 142, + SPDY_SESSION_ALREADY_EXISTS = 143, + WS_PROTOCOL_ERROR = 145, + ADDRESS_IN_USE = 147, + SSL_HANDSHAKE_NOT_COMPLETED = 148, + SSL_BAD_PEER_PUBLIC_KEY = 149, + SSL_PINNED_KEY_NOT_IN_CERT_CHAIN = 150, + CLIENT_AUTH_CERT_TYPE_UNSUPPORTED = 151, + ORIGIN_BOUND_CERT_GENERATION_TYPE_MISMATCH = 152, + SSL_DECRYPT_ERROR_ALERT = 153, + WS_THROTTLE_QUEUE_TOO_LARGE = 154, + SSL_SERVER_CERT_CHANGED = 156, + SSL_INAPPROPRIATE_FALLBACK = 157, + CT_NO_SCTS_VERIFIED_OK = 158, + SSL_UNRECOGNIZED_NAME_ALERT = 159, + SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR = 160, + SOCKET_SET_SEND_BUFFER_SIZE_ERROR = 161, + SOCKET_RECEIVE_BUFFER_SIZE_UNCHANGEABLE = 162, + SOCKET_SEND_BUFFER_SIZE_UNCHANGEABLE = 163, + SSL_CLIENT_AUTH_CERT_BAD_FORMAT = 164, + SSL_FALLBACK_BEYOND_MINIMUM_VERSION = 165, + CERT_COMMON_NAME_INVALID = 200, + CERT_DATE_INVALID = 201, + CERT_AUTHORITY_INVALID = 202, + CERT_CONTAINS_ERRORS = 203, + CERT_NO_REVOCATION_MECHANISM = 204, + CERT_UNABLE_TO_CHECK_REVOCATION = 205, + CERT_REVOKED = 206, + CERT_INVALID = 207, + CERT_WEAK_SIGNATURE_ALGORITHM = 208, + CERT_NON_UNIQUE_NAME = 210, + CERT_WEAK_KEY = 211, + CERT_NAME_CONSTRAINT_VIOLATION = 212, + CERT_VALIDITY_TOO_LONG = 213, + CERT_END = 214, + INVALID_URL = 300, + DISALLOWED_URL_SCHEME = 301, + UNKNOWN_URL_SCHEME = 302, + TOO_MANY_REDIRECTS = 310, + UNSAFE_REDIRECT = 311, + UNSAFE_PORT = 312, + INVALID_RESPONSE = 320, + INVALID_CHUNKED_ENCODING = 321, + METHOD_NOT_SUPPORTED = 322, + UNEXPECTED_PROXY_AUTH = 323, + EMPTY_RESPONSE = 324, + RESPONSE_HEADERS_TOO_BIG = 325, + PAC_STATUS_NOT_OK = 326, + PAC_SCRIPT_FAILED = 327, + REQUEST_RANGE_NOT_SATISFIABLE = 328, + MALFORMED_IDENTITY = 329, + CONTENT_DECODING_FAILED = 330, + NETWORK_IO_SUSPENDED = 331, + SYN_REPLY_NOT_RECEIVED = 332, + ENCODING_CONVERSION_FAILED = 333, + UNRECOGNIZED_FTP_DIRECTORY_LISTING_FORMAT = 334, + INVALID_SPDY_STREAM = 335, + NO_SUPPORTED_PROXIES = 336, + SPDY_PROTOCOL_ERROR = 337, + INVALID_AUTH_CREDENTIALS = 338, + UNSUPPORTED_AUTH_SCHEME = 339, + ENCODING_DETECTION_FAILED = 340, + MISSING_AUTH_CREDENTIALS = 341, + UNEXPECTED_SECURITY_LIBRARY_STATUS = 342, + MISCONFIGURED_AUTH_ENVIRONMENT = 343, + UNDOCUMENTED_SECURITY_LIBRARY_STATUS = 344, + RESPONSE_BODY_TOO_BIG_TO_DRAIN = 345, + RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH = 346, + INCOMPLETE_SPDY_HEADERS = 347, + PAC_NOT_IN_DHCP = 348, + RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION = 349, + RESPONSE_HEADERS_MULTIPLE_LOCATION = 350, + SPDY_SERVER_REFUSED_STREAM = 351, + SPDY_PING_FAILED = 352, + CONTENT_LENGTH_MISMATCH = 354, + INCOMPLETE_CHUNKED_ENCODING = 355, + QUIC_PROTOCOL_ERROR = 356, + RESPONSE_HEADERS_TRUNCATED = 357, + QUIC_HANDSHAKE_FAILED = 358, + REQUEST_FOR_SECURE_RESOURCE_OVER_INSECURE_QUIC = 359, + SPDY_INADEQUATE_TRANSPORT_SECURITY = 360, + SPDY_FLOW_CONTROL_ERROR = 361, + SPDY_FRAME_SIZE_ERROR = 362, + SPDY_COMPRESSION_ERROR = 363, + PROXY_AUTH_REQUESTED_WITH_NO_CONNECTION = 364, + HTTP_1_1_REQUIRED = 365, + PROXY_HTTP_1_1_REQUIRED = 366, + CACHE_MISS = 400, + CACHE_READ_FAILURE = 401, + CACHE_WRITE_FAILURE = 402, + CACHE_OPERATION_NOT_SUPPORTED = 403, + CACHE_OPEN_FAILURE = 404, + CACHE_CREATE_FAILURE = 405, + CACHE_RACE = 406, + CACHE_CHECKSUM_READ_FAILURE = 407, + CACHE_CHECKSUM_MISMATCH = 408, + CACHE_LOCK_TIMEOUT = 409, + INSECURE_RESPONSE = 501, + NO_PRIVATE_KEY_FOR_CERT = 502, + ADD_USER_CERT_FAILED = 503, + FTP_FAILED = 601, + FTP_SERVICE_UNAVAILABLE = 602, + FTP_TRANSFER_ABORTED = 603, + FTP_FILE_BUSY = 604, + FTP_SYNTAX_ERROR = 605, + FTP_COMMAND_NOT_SUPPORTED = 606, + FTP_BAD_COMMAND_SEQUENCE = 607, + PKCS12_IMPORT_BAD_PASSWORD = 701, + PKCS12_IMPORT_FAILED = 702, + IMPORT_CA_CERT_NOT_CA = 703, + IMPORT_CERT_ALREADY_EXISTS = 704, + IMPORT_CA_CERT_FAILED = 705, + IMPORT_SERVER_CERT_FAILED = 706, + PKCS12_IMPORT_INVALID_MAC = 707, + PKCS12_IMPORT_INVALID_FILE = 708, + PKCS12_IMPORT_UNSUPPORTED = 709, + KEY_GENERATION_FAILED = 710, + ORIGIN_BOUND_CERT_GENERATION_FAILED = 711, + PRIVATE_KEY_EXPORT_FAILED = 712, + SELF_SIGNED_CERT_GENERATION_FAILED = 713, + CERT_DATABASE_CHANGED = 714, + CHANNEL_ID_IMPORT_FAILED = 715, + DNS_MALFORMED_RESPONSE = 800, + DNS_SERVER_REQUIRES_TCP = 801, + DNS_SERVER_FAILED = 802, + DNS_TIMED_OUT = 803, + DNS_CACHE_MISS = 804, + DNS_SEARCH_EMPTY = 805, + DNS_SORT_ERROR = 806, +} diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 9541567da8f..a9202a2bd16 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -479,6 +479,7 @@ dependencies = [ "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", + "net 0.0.1", "script_traits 0.0.1", "time 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/cef/window.rs b/ports/cef/window.rs index af0f89f36be..43e8c38cee2 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -24,6 +24,7 @@ use layers::geometry::DevicePixel; use layers::platform::surface::NativeGraphicsMetadata; use libc::{c_char, c_void}; use msg::constellation_msg::{Key, KeyModifiers}; +use net::net_error_list::NetError; use std::ptr; use std_url::Url; use util::cursor::Cursor; @@ -360,6 +361,9 @@ impl WindowMethods for Window { } } + fn load_error(&self, _: NetError, _: String) { + } + fn set_page_title(&self, string: Option) { let browser = self.cef_browser.borrow(); let browser = match *browser { diff --git a/ports/glutin/Cargo.toml b/ports/glutin/Cargo.toml index f503ee86441..c816d777ec7 100644 --- a/ports/glutin/Cargo.toml +++ b/ports/glutin/Cargo.toml @@ -26,6 +26,9 @@ git = "https://github.com/servo/rust-layers" [dependencies.msg] path = "../../components/msg" +[dependencies.net] +path = "../../components/net" + [dependencies.util] path = "../../components/util" diff --git a/ports/glutin/lib.rs b/ports/glutin/lib.rs index 3d66e50a5e4..b360649255c 100644 --- a/ports/glutin/lib.rs +++ b/ports/glutin/lib.rs @@ -16,6 +16,7 @@ extern crate glutin; extern crate layers; extern crate libc; extern crate msg; +extern crate net; #[cfg(feature = "window")] extern crate script_traits; extern crate time; extern crate util; diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index 16d8c509317..e762d91d112 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -14,6 +14,7 @@ use layers::geometry::DevicePixel; use layers::platform::surface::NativeGraphicsMetadata; use msg::constellation_msg; use msg::constellation_msg::Key; +use net::net_error_list::NetError; use std::mem; use std::rc::Rc; use std::sync::mpsc::{channel, Sender}; @@ -511,6 +512,9 @@ impl WindowMethods for Window { fn load_end(&self, _: bool, _: bool) { } + fn load_error(&self, _: NetError, _: String) { + } + /// Has no effect on Android. fn set_cursor(&self, c: Cursor) { use glutin::MouseCursor; diff --git a/ports/gonk/src/window.rs b/ports/gonk/src/window.rs index f751d239e42..67254dd663c 100644 --- a/ports/gonk/src/window.rs +++ b/ports/gonk/src/window.rs @@ -12,6 +12,7 @@ use layers::geometry::DevicePixel; use layers::platform::surface::NativeGraphicsMetadata; use libc::c_int; use msg::constellation_msg::{Key, KeyModifiers}; +use net::net_error_list::NetError; use std::sync::mpsc::{channel, Sender, Receiver}; use std::rc::Rc; use std::mem::transmute; @@ -808,6 +809,9 @@ impl WindowMethods for Window { fn load_end(&self, _: bool, _: bool) { } + fn load_error(&self, _: NetError, _: String) { + } + fn hidpi_factor(&self) -> ScaleFactor { ScaleFactor::new(1.0) } From 8e78febaac66ffe33ff4f4c7b355c48af7a90c4f Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 14:03:00 -0400 Subject: [PATCH 17/27] make cef_errorcode_t a typedef for net::NetError --- ports/cef/types.rs | 58 +++------------------------------------------- 1 file changed, 3 insertions(+), 55 deletions(-) diff --git a/ports/cef/types.rs b/ports/cef/types.rs index 4369930b105..38accd438e1 100644 --- a/ports/cef/types.rs +++ b/ports/cef/types.rs @@ -9,6 +9,8 @@ use libc::c_ulong; use libc::c_void; use libc::types::os::arch::c95::wchar_t; +use net::net_error_list::NetError; + pub use self::cef_rect as cef_rect_t; pub enum cef_string_map_t {} @@ -276,61 +278,7 @@ pub enum cef_urlrequest_status_t { -// -// Supported error code values. See net\base\net_error_list.h for complete -// descriptions of the error codes. -// -pub enum cef_errorcode_t { - ERR_NONE = 0, - ERR_FAILED = -2, - ERR_ABORTED = -3, - ERR_INVALID_ARGUMENT = -4, - ERR_INVALID_HANDLE = -5, - ERR_FILE_NOT_FOUND = -6, - ERR_TIMED_OUT = -7, - ERR_FILE_TOO_BIG = -8, - ERR_UNEXPECTED = -9, - ERR_ACCESS_DENIED = -10, - ERR_NOT_IMPLEMENTED = -11, - ERR_CONNECTION_CLOSED = -100, - ERR_CONNECTION_RESET = -101, - ERR_CONNECTION_REFUSED = -102, - ERR_CONNECTION_ABORTED = -103, - ERR_CONNECTION_FAILED = -104, - ERR_NAME_NOT_RESOLVED = -105, - ERR_INTERNET_DISCONNECTED = -106, - ERR_SSL_PROTOCOL_ERROR = -107, - ERR_ADDRESS_INVALID = -108, - ERR_ADDRESS_UNREACHABLE = -109, - ERR_SSL_CLIENT_AUTH_CERT_NEEDED = -110, - ERR_TUNNEL_CONNECTION_FAILED = -111, - ERR_NO_SSL_VERSIONS_ENABLED = -112, - ERR_SSL_VERSION_OR_CIPHER_MISMATCH = -113, - ERR_SSL_RENEGOTIATION_REQUESTED = -114, - ERR_CERT_COMMON_NAME_INVALID = -200, - ERR_CERT_DATE_INVALID = -201, - ERR_CERT_AUTHORITY_INVALID = -202, - ERR_CERT_CONTAINS_ERRORS = -203, - ERR_CERT_NO_REVOCATION_MECHANISM = -204, - ERR_CERT_UNABLE_TO_CHECK_REVOCATION = -205, - ERR_CERT_REVOKED = -206, - ERR_CERT_INVALID = -207, - ERR_CERT_END = -208, - ERR_INVALID_URL = -300, - ERR_DISALLOWED_URL_SCHEME = -301, - ERR_UNKNOWN_URL_SCHEME = -302, - ERR_TOO_MANY_REDIRECTS = -310, - ERR_UNSAFE_REDIRECT = -311, - ERR_UNSAFE_PORT = -312, - ERR_INVALID_RESPONSE = -320, - ERR_INVALID_CHUNKED_ENCODING = -321, - ERR_METHOD_NOT_SUPPORTED = -322, - ERR_UNEXPECTED_PROXY_AUTH = -323, - ERR_EMPTY_RESPONSE = -324, - ERR_RESPONSE_HEADERS_TOO_BIG = -325, - ERR_CACHE_MISS = -400, - ERR_INSECURE_RESPONSE = -501, -} +pub type cef_errorcode_t = NetError; // From 14a6390f0375323fed8898729feb3479f5462404 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 14:03:19 -0400 Subject: [PATCH 18/27] add embedding method for load_handler::on_load_error still needs error text messages I guess --- ports/cef/window.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/ports/cef/window.rs b/ports/cef/window.rs index 43e8c38cee2..c717bc2595c 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -361,7 +361,21 @@ impl WindowMethods for Window { } } - fn load_error(&self, _: NetError, _: String) { + fn load_error(&self, code: NetError, url: String) { + 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_load_handler) && + check_ptr_exist!(browser.get_host().get_client().get_load_handler(), on_load_error) { + let utf16_chars: Vec = Utf16Encoder::new((url).chars()).collect(); + browser.get_host() + .get_client() + .get_load_handler() + .on_load_error((*browser).clone(), browser.get_main_frame(), + code, &[], utf16_chars.as_slice()); + } } fn set_page_title(&self, string: Option) { From 90169e8f3b80e361e11e121a84441bcef844fe84 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 17:58:33 -0400 Subject: [PATCH 19/27] force resize after sending cef_browser::on_after_created() callback this fixes rendering of the first frame to be at the size of the browser instead of the size of the initial window_info --- ports/cef/browser.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index 3eb8a70c730..95f3551ce11 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -262,6 +262,7 @@ pub fn browser_callback_after_created(browser: CefBrowser) { life_span_handler.on_after_created(browser.clone()); } browser.downcast().callback_executed.set(true); + browser.downcast().host.was_resized(); } fn browser_host_create(window_info: &cef_window_info_t, From aef321816969a24c050c9854c3526dc97b0f57e7 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 18:12:03 -0400 Subject: [PATCH 20/27] Revert "temp re-set default url for cef while I figure out wtf is going on" This reverts commit 8330eabac191af1d724621a18b85e2c61539612a. --- ports/cef/browser.rs | 8 +++++--- ports/cef/core.rs | 4 +--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index 95f3551ce11..2aaa926afa4 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -11,11 +11,13 @@ use interfaces::{cef_request_context_t}; use servo::Browser; use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t}; use window; +use wrappers::CefWrap; use compositing::windowing::{WindowNavigateMsg, WindowEvent}; use glutin_app; use libc::c_int; use std::cell::{Cell, RefCell, BorrowState}; +use std::ptr; use std::rc::Rc; use std::sync::atomic::{AtomicIsize, Ordering}; @@ -275,9 +277,9 @@ fn browser_host_create(window_info: &cef_window_info_t, if callback_executed { browser_callback_after_created(browser.clone()); } - //if url != ptr::null() { - //unsafe { browser.downcast().frame.load_url(CefWrap::to_rust(url)); } - //} + if url != ptr::null() { + unsafe { browser.downcast().frame.load_url(CefWrap::to_rust(url)); } + } BROWSERS.with(|browsers| { browsers.borrow_mut().push(browser.clone()); }); diff --git a/ports/cef/core.rs b/ports/cef/core.rs index 847fbe185b9..cfd411da3ad 100644 --- a/ports/cef/core.rs +++ b/ports/cef/core.rs @@ -12,11 +12,10 @@ use util::opts; use std::ffi; use std::str; use browser; -use std_url::Url; const MAX_RENDERING_THREADS: usize = 128; -static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg"; +//static HOME_URL: &'static str = "http://s27.postimg.org/vqbtrolyr/servo.jpg"; static CEF_API_HASH_UNIVERSAL: &'static [u8] = b"8efd129f4afc344bd04b2feb7f73a149b6c4e27f\0"; #[cfg(target_os="windows")] @@ -75,7 +74,6 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t, temp_opts.hard_fail = false; temp_opts.enable_text_antialiasing = true; temp_opts.resources_path = None; - temp_opts.url = Url::parse(HOME_URL).unwrap(); opts::set(temp_opts); if unsafe { (*settings).windowless_rendering_enabled != 0 } { From 64ff2c4a54643d773220e3d6ef19f4d68622c026 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 18:52:54 -0400 Subject: [PATCH 21/27] handle early LoadURL messages without panicking by sending initial url load fixes #6126 --- components/compositing/compositor.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 18f6618a58c..f039d7bee27 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -882,15 +882,13 @@ impl IOCompositor { fn on_load_url_window_event(&mut self, url_string: String) { debug!("osmain: loading URL `{}`", url_string); self.got_load_complete_message = false; - let root_pipeline_id = match self.scene.root { - Some(ref layer) => layer.get_pipeline_id(), - None => panic!("Compositor: Received WindowEvent::LoadUrl without initialized compositor \ - layers"), - }; let url = Url::parse(&url_string).unwrap(); self.window.set_page_url(url.clone()); + let msg = match self.scene.root { + Some(ref layer) => ConstellationMsg::LoadUrl(layer.get_pipeline_id(), LoadData::new(url)), + None => ConstellationMsg::InitLoadUrl(url) + }; - let msg = ConstellationMsg::LoadUrl(root_pipeline_id, LoadData::new(url)); let ConstellationChan(ref chan) = self.constellation_chan; chan.send(msg).unwrap() } From 45116dca7130576b8ac9cdc75ad7715d9faa8c23 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 21:16:04 -0400 Subject: [PATCH 22/27] break out cef app wakeup code into separate pub function --- ports/cef/window.rs | 73 +++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/ports/cef/window.rs b/ports/cef/window.rs index c717bc2595c..05af8fdbf8f 100644 --- a/ports/cef/window.rs +++ b/ports/cef/window.rs @@ -458,44 +458,9 @@ struct CefCompositorProxy { } impl CompositorProxy for CefCompositorProxy { - #[cfg(target_os="macos")] - fn send(&mut self, msg: compositor_task::Msg) { - use cocoa::appkit::{NSApp, NSApplication, NSApplicationDefined}; - use cocoa::appkit::{NSEvent, NSEventModifierFlags, NSEventSubtype}; - use cocoa::base::nil; - use cocoa::foundation::{NSAutoreleasePool, NSPoint}; - - // Send a message and kick the OS event loop awake. - self.sender.send(msg).unwrap(); - - unsafe { - let pool = NSAutoreleasePool::new(nil); - let event = - NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_( - nil, - NSApplicationDefined, - NSPoint::new(0.0, 0.0), - NSEventModifierFlags::empty(), - 0.0, - 0, - nil, - NSEventSubtype::NSWindowExposedEventType, - 0, - 0); - NSApp().postEvent_atStart_(event, 0); - pool.drain(); - } - } - - #[cfg(target_os="linux")] fn send(&mut self, msg: compositor_task::Msg) { self.sender.send(msg).unwrap(); - unsafe { if CEF_APP.is_null() { return; } } - let capp = unsafe { CefApp::from_c_object_addref(CEF_APP) }; - if unsafe { (*CEF_APP).get_browser_process_handler.is_some() } && - check_ptr_exist!(capp.get_browser_process_handler(), on_work_available) { - capp.get_browser_process_handler().on_work_available(); - } + app_wakeup(); } fn clone_compositor_proxy(&self) -> Box { @@ -520,6 +485,42 @@ fn on_load_start(window: &Window) { } } +#[cfg(target_os="macos")] +pub fn app_wakeup() { + use cocoa::appkit::{NSApp, NSApplication, NSApplicationDefined}; + use cocoa::appkit::{NSEvent, NSEventModifierFlags, NSEventSubtype}; + use cocoa::base::nil; + use cocoa::foundation::{NSAutoreleasePool, NSPoint}; + + unsafe { + let pool = NSAutoreleasePool::new(nil); + let event = + NSEvent::otherEventWithType_location_modifierFlags_timestamp_windowNumber_context_subtype_data1_data2_( + nil, + NSApplicationDefined, + NSPoint::new(0.0, 0.0), + NSEventModifierFlags::empty(), + 0.0, + 0, + nil, + NSEventSubtype::NSWindowExposedEventType, + 0, + 0); + NSApp().postEvent_atStart_(event, 0); + pool.drain(); + } +} + +#[cfg(target_os="linux")] +pub fn app_wakeup() { + unsafe { if CEF_APP.is_null() { return; } } + let capp = unsafe { CefApp::from_c_object_addref(CEF_APP) }; + if unsafe { (*CEF_APP).get_browser_process_handler.is_some() } && + check_ptr_exist!(capp.get_browser_process_handler(), on_work_available) { + capp.get_browser_process_handler().on_work_available(); + } +} + #[cfg(target_os="linux")] pub fn init_window() { unsafe { From fcf449517ddff5d1b74f284c8c27166e105b9611 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 21:17:04 -0400 Subject: [PATCH 23/27] handle case of deleted pipeline when preparing to send load_end constellation msg --- components/compositing/constellation.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index bfcb0693c1e..6b79722b7e4 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -666,8 +666,8 @@ impl Constellation { } fn handle_load_start_msg(&mut self, pipeline_id: &PipelineId) { - let mut back = false; - let mut forward = false; + let mut back; + let mut forward; let frameid = self.pipeline_to_frame_map.get(pipeline_id); match frameid { Some(frame_id) => { @@ -676,13 +676,16 @@ impl Constellation { back = if !self.frame(*frame_id).prev.is_empty() { true } else { false }; }, - None => {} + None => return }; self.compositor_proxy.send(CompositorMsg::LoadStart(back, forward)); } fn handle_load_complete_msg(&mut self, pipeline_id: &PipelineId) { - let frame_id = *self.pipeline_to_frame_map.get(pipeline_id).unwrap(); + let frame_id = match self.pipeline_to_frame_map.get(pipeline_id) { + Some(frame) => *frame, + None => return + }; let forward = !self.mut_frame(frame_id).next.is_empty(); let back = !self.mut_frame(frame_id).prev.is_empty(); From b1ae5e7523461390d332e39a98a847b243afab3b Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 21:18:32 -0400 Subject: [PATCH 24/27] make Opts.url an Option<> type, only emit initial url load if url exists this is a necessary change for embedded apps to prevent an initial about:blank page load from overwriting whatever the app was actually trying to load --- components/servo/lib.rs | 11 +++++++---- components/util/opts.rs | 6 +++--- ports/cef/core.rs | 1 + 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/components/servo/lib.rs b/components/servo/lib.rs index 4f254d5f682..1cc349de1dd 100644 --- a/components/servo/lib.rs +++ b/components/servo/lib.rs @@ -168,10 +168,13 @@ fn create_constellation(opts: opts::Opts, storage_task); // Send the URL command to the constellation. - { - let ConstellationChan(ref chan) = constellation_chan; - chan.send(ConstellationMsg::InitLoadUrl(opts.url.clone())).unwrap(); - } + match opts.url { + Some(url) => { + let ConstellationChan(ref chan) = constellation_chan; + chan.send(ConstellationMsg::InitLoadUrl(url.clone())).unwrap(); + }, + None => () + }; constellation_chan } diff --git a/components/util/opts.rs b/components/util/opts.rs index f3e7487f468..0b19f815596 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -24,7 +24,7 @@ use url::{self, Url}; #[derive(Clone)] pub struct Opts { /// The initial URL to load. - pub url: Url, + pub url: Option, /// How many threads to use for CPU painting (`-t`). /// @@ -198,7 +198,7 @@ static FORCE_CPU_PAINTING: bool = false; pub fn default_opts() -> Opts { Opts { - url: Url::parse("about:blank").unwrap(), + url: Some(Url::parse("about:blank").unwrap()), paint_threads: 1, gpu_painting: false, tile_size: 512, @@ -370,7 +370,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool { }; let opts = Opts { - url: url, + url: Some(url), paint_threads: paint_threads, gpu_painting: gpu_painting, tile_size: tile_size, diff --git a/ports/cef/core.rs b/ports/cef/core.rs index cfd411da3ad..04a88991838 100644 --- a/ports/cef/core.rs +++ b/ports/cef/core.rs @@ -74,6 +74,7 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t, temp_opts.hard_fail = false; temp_opts.enable_text_antialiasing = true; temp_opts.resources_path = None; + temp_opts.url = None; opts::set(temp_opts); if unsafe { (*settings).windowless_rendering_enabled != 0 } { From 81eb426b04ab6d68f542fb047bb9706795d0f3a5 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 21:20:33 -0400 Subject: [PATCH 25/27] when creating a cef browser, setup the url to load but don't load it cef apps will expect to enter their main loops before this happens due to various callbacks being hit, so it's necessary to punt this loading off until a later time --- ports/cef/browser.rs | 8 ++++---- ports/cef/frame.rs | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index 2aaa926afa4..4da87e906ea 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -264,7 +264,7 @@ pub fn browser_callback_after_created(browser: CefBrowser) { life_span_handler.on_after_created(browser.clone()); } browser.downcast().callback_executed.set(true); - browser.downcast().host.was_resized(); + browser.downcast().frame.load(); } fn browser_host_create(window_info: &cef_window_info_t, @@ -274,12 +274,12 @@ fn browser_host_create(window_info: &cef_window_info_t, -> CefBrowser { let browser = ServoCefBrowser::new(window_info, client).as_cef_interface(); browser.init(window_info); + if url != ptr::null() { + unsafe { browser.downcast().frame.set_url(CefWrap::to_rust(url)); } + } if callback_executed { browser_callback_after_created(browser.clone()); } - if url != ptr::null() { - unsafe { browser.downcast().frame.load_url(CefWrap::to_rust(url)); } - } BROWSERS.with(|browsers| { browsers.borrow_mut().push(browser.clone()); }); diff --git a/ports/cef/frame.rs b/ports/cef/frame.rs index 61ae9de2821..e6a166be121 100644 --- a/ports/cef/frame.rs +++ b/ports/cef/frame.rs @@ -53,10 +53,20 @@ full_cef_class_impl! { pub trait ServoCefFrameExtensions { fn set_browser(&self, browser: CefBrowser); + fn set_url(&self, url: &[u16]); + fn load(&self); } impl ServoCefFrameExtensions for CefFrame { fn set_browser(&self, browser: CefBrowser) { *self.downcast().browser.borrow_mut() = Some(browser) } + fn set_url(&self, url: &[u16]) { + let frame = self.downcast(); + *frame.url.borrow_mut() = String::from_utf16(url).unwrap(); + } + fn load(&self) { + let event = WindowEvent::LoadUrl(self.downcast().url.borrow().clone()); + self.downcast().browser.borrow_mut().as_mut().unwrap().send_window_event(event); + } } From ca1f49aaa3ff257bdac1235f107c81a244b2d739 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Tue, 26 May 2015 21:22:07 -0400 Subject: [PATCH 26/27] spawn a task for cef async browser creation to kick the main loop awake without this, the initial url loading message will never be sent to the constellation, preventing the engine from ever doing anything --- ports/cef/browser.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ports/cef/browser.rs b/ports/cef/browser.rs index 4da87e906ea..39139c5b8ff 100644 --- a/ports/cef/browser.rs +++ b/ports/cef/browser.rs @@ -10,6 +10,7 @@ use interfaces::{cef_browser_t, cef_browser_host_t, cef_client_t, cef_frame_t}; use interfaces::{cef_request_context_t}; use servo::Browser; use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t, cef_window_handle_t}; +use util::task::spawn_named; use window; use wrappers::CefWrap; @@ -297,6 +298,9 @@ cef_static_method_impls! { let _browser_settings: &cef_browser_settings_t = _browser_settings; let _request_context: CefRequestContext = _request_context; browser_host_create(window_info, client, url, false); + spawn_named("async_browser_creation".to_owned(), move || { + window::app_wakeup(); + }); 1i32 }} fn cef_browser_host_create_browser_sync(window_info: *const cef_window_info_t, From 8c278d30a62da8457fc055dbc54a47be2fef9b64 Mon Sep 17 00:00:00 2001 From: Mike Blumenkrantz Date: Wed, 27 May 2015 13:51:39 -0400 Subject: [PATCH 27/27] fix glutin headless compile errors --- ports/glutin/window.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index e762d91d112..64de0e784ed 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -693,7 +693,11 @@ impl WindowMethods for Window { fn set_page_url(&self, _: Url) { } - fn load_end(&self) { + fn load_start(&self, _: bool, _: bool) { + } + fn load_end(&self, _: bool, _: bool) { + } + fn load_error(&self, _: NetError, _: String) { } fn set_cursor(&self, _: Cursor) {