servo: Merge #4657 - Add basic support for closing cef tabs. Prevents crashes, but leaks memory for now (from glennw:cef-close); r=larsbergstrom
authorGlenn Watson <gw@intuitionlibrary.com>
Mon, 19 Jan 2015 07:57:47 -0700
changeset 382257 54cd5c8903e1d8c794567bfee10062bbdec9e651
parent 382256 bf099dd3e2170bbeb7c96adcdc4a91c8e240425d
child 382258 daa6433f3094986513e91d1e0de225c2aefd622d
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslarsbergstrom
servo: Merge #4657 - Add basic support for closing cef tabs. Prevents crashes, but leaks memory for now (from glennw:cef-close); r=larsbergstrom Source-Repo: https://github.com/servo/servo Source-Revision: f3dfe04fa45bd723fac40d1452550d55240f80f8
servo/ports/cef/browser.rs
servo/ports/cef/browser_host.rs
--- a/servo/ports/cef/browser.rs
+++ b/servo/ports/cef/browser.rs
@@ -12,17 +12,19 @@ use servo::Browser;
 use types::{cef_browser_settings_t, cef_string_t, cef_window_info_t};
 use window;
 
 use compositing::windowing::{WindowNavigateMsg, WindowEvent};
 use glfw_app;
 use libc::c_int;
 use servo_util::opts;
 use std::cell::{Cell, RefCell};
+use std::sync::atomic::{AtomicInt, SeqCst};
 
+thread_local!(pub static ID_COUNTER: AtomicInt = AtomicInt::new(0))
 thread_local!(pub static BROWSERS: RefCell<Vec<CefBrowser>> = RefCell::new(vec!()))
 
 pub enum ServoBrowser {
     Invalid,
     OnScreen(Browser<glfw_app::window::Window>),
     OffScreen(Browser<window::Window>),
 }
 
@@ -78,16 +80,17 @@ pub struct ServoCefBrowser {
     pub frame: CefFrame,
     /// A reference to the browser's host.
     pub host: CefBrowserHost,
     /// A reference to the browser client.
     pub client: CefClient,
     /// Whether the on-created callback has fired yet.
     pub callback_executed: Cell<bool>,
 
+    id: int,
     servo_browser: RefCell<ServoBrowser>,
     message_queue: RefCell<Vec<WindowEvent>>,
 }
 
 impl ServoCefBrowser {
     pub fn new(window_info: &cef_window_info_t, client: CefClient) -> ServoCefBrowser {
         let frame = ServoCefFrame::new().as_cef_interface();
         let host = ServoCefBrowserHost::new(client.clone()).as_cef_interface();
@@ -95,23 +98,28 @@ impl ServoCefBrowser {
         let servo_browser = if window_info.windowless_rendering_enabled == 0 {
             let glfw_window = glfw_app::create_window();
             let servo_browser = Browser::new(Some(glfw_window.clone()));
             ServoBrowser::OnScreen(servo_browser)
         } else {
             ServoBrowser::Invalid
         };
 
+        let id = ID_COUNTER.with(|counter| {
+            counter.fetch_add(1, SeqCst)
+        });
+
         ServoCefBrowser {
             frame: frame,
             host: host,
             client: client,
             callback_executed: Cell::new(false),
             servo_browser: RefCell::new(servo_browser),
             message_queue: RefCell::new(vec!()),
+            id: id,
         }
     }
 }
 
 pub trait ServoCefBrowserExtensions {
     fn init(&self, window_info: &cef_window_info_t);
     fn send_window_event(&self, event: WindowEvent);
     fn get_title_for_main_frame(&self);
@@ -165,16 +173,25 @@ impl ServoCefBrowserExtensions for CefBr
 pub fn update() {
     BROWSERS.with(|browsers| {
         for browser in browsers.borrow().iter() {
             browser.send_window_event(WindowEvent::Idle);
         }
     });
 }
 
+pub fn close(browser: CefBrowser) {
+    BROWSERS.with(|browsers| {
+        let mut browsers = browsers.borrow_mut();
+        browsers.iter()
+                .position(|&ref n| n.downcast().id == browser.downcast().id)
+                .map(|e| browsers.remove(e));
+    });
+}
+
 pub fn browser_callback_after_created(browser: CefBrowser) {
     if browser.downcast().client.is_null_cef_object() {
         return
     }
     let client = browser.downcast().client.clone();
     let life_span_handler = client.get_life_span_handler();
     if life_span_handler.is_not_null_cef_object() {
         life_span_handler.on_after_created(browser.clone());
--- a/servo/ports/cef/browser_host.rs
+++ b/servo/ports/cef/browser_host.rs
@@ -1,17 +1,17 @@
 /* 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/. */
 
 use eutil::Downcast;
 use interfaces::{CefBrowser, CefBrowserHost, CefClient, cef_browser_host_t, cef_client_t};
 use types::{cef_mouse_button_type_t, cef_mouse_event, cef_rect_t, cef_key_event};
 use types::cef_key_event_type_t::{KEYEVENT_CHAR, KEYEVENT_KEYDOWN, KEYEVENT_KEYUP, KEYEVENT_RAWKEYDOWN};
-use browser::ServoCefBrowserExtensions;
+use browser::{mod, ServoCefBrowserExtensions};
 
 use compositing::windowing::{WindowEvent, MouseWindowEvent};
 use geom::point::TypedPoint2D;
 use geom::size::TypedSize2D;
 use libc::{c_double, c_int};
 use servo_msg::constellation_msg::{mod, KeyModifiers, KeyState};
 use std::cell::RefCell;
 
@@ -32,18 +32,18 @@ cef_class_impl! {
             let mut rect = cef_rect_t::zero();
             this.get_client()
                 .get_render_handler()
                 .get_backing_rect(this.downcast().browser.borrow().clone().unwrap(), &mut rect);
             let size = TypedSize2D(rect.width as uint, rect.height as uint);
             this.downcast().send_window_event(WindowEvent::Resize(size));
         }
 
-        fn close_browser(&_this, _force: c_int) -> () {
-            // TODO: Clean shutdown.
+        fn close_browser(&this, _force: c_int) -> () {
+            browser::close(this.downcast().browser.borrow_mut().take().unwrap());
         }
 
         fn send_focus_event(&this, focus: c_int) -> () {
             if focus != 0 {
                 this.downcast().send_window_event(WindowEvent::Refresh);
             }
         }