Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 7 additions & 27 deletions desktop/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,39 +314,19 @@ impl App {
responses.push(message);
}
}
DesktopFrontendMessage::PersistenceLoadCurrentDocument => {
if let Some((id, document)) = self.persistent_data.current_document() {
let message = DesktopWrapperMessage::LoadDocument {
id,
document,
to_front: false,
select_after_open: true,
};
responses.push(message);
}
}
DesktopFrontendMessage::PersistenceLoadRemainingDocuments => {
for (id, document) in self.persistent_data.documents_before_current().into_iter().rev() {
let message = DesktopWrapperMessage::LoadDocument {
id,
document,
to_front: true,
select_after_open: false,
};
responses.push(message);
}
for (id, document) in self.persistent_data.documents_after_current() {
let message = DesktopWrapperMessage::LoadDocument {
DesktopFrontendMessage::PersistenceLoadDocuments => {
// Open all documents in persisted tab order, then select the current one
for (id, document) in self.persistent_data.documents() {
responses.push(DesktopWrapperMessage::LoadDocument {
id,
document,
to_front: false,
select_after_open: false,
};
responses.push(message);
});
}

if let Some(id) = self.persistent_data.current_document_id() {
let message = DesktopWrapperMessage::SelectDocument { id };
responses.push(message);
responses.push(DesktopWrapperMessage::SelectDocument { id });
}
}
DesktopFrontendMessage::OpenLaunchDocuments => {
Expand Down
1 change: 0 additions & 1 deletion desktop/src/cef.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use crate::wrapper::{WgpuContext, deserialize_editor_message};

mod consts;
mod context;
mod dirs;
mod input;
mod internal;
mod ipc;
Expand Down
13 changes: 6 additions & 7 deletions desktop/src/cef/context/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ use cef::{
App, BrowserSettings, CefString, Client, DictionaryValue, ImplCommandLine, ImplRequestContext, LogSeverity, RequestContextSettings, SchemeHandlerFactory, Settings, WindowInfo, api_hash,
browser_host_create_browser_sync, execute_process,
};
use std::path::{Path, PathBuf};
use std::path::Path;

use super::CefContext;
use super::singlethreaded::SingleThreadedCefContext;
use crate::cef::CefEventHandler;
use crate::cef::consts::{RESOURCE_DOMAIN, RESOURCE_SCHEME};
use crate::cef::dirs::{create_instance_dir, delete_instance_dirs};
use crate::cef::input::InputState;
use crate::cef::internal::{BrowserProcessAppImpl, BrowserProcessClientImpl, RenderProcessAppImpl, SchemeHandlerFactoryImpl};
use crate::dirs::TempDir;

pub(crate) struct CefContextBuilder<H: CefEventHandler> {
pub(crate) args: Args,
Expand Down Expand Up @@ -118,14 +118,13 @@ impl<H: CefEventHandler> CefContextBuilder<H> {

#[cfg(not(target_os = "macos"))]
pub(crate) fn initialize(self, event_handler: H, disable_gpu_acceleration: bool) -> Result<impl CefContext, InitError> {
delete_instance_dirs();
let instance_dir = create_instance_dir();
let instance_dir = TempDir::new().expect("Failed to create temporary directory for CEF instance");

let settings = Settings {
multi_threaded_message_loop: 1,
#[cfg(target_os = "linux")]
no_sandbox: 1,
..Self::common_settings(&instance_dir)
..Self::common_settings(instance_dir.as_ref())
};

self.initialize_inner(&event_handler, settings)?;
Expand Down Expand Up @@ -157,7 +156,7 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
}
}

fn create_browser<H: CefEventHandler>(event_handler: H, instance_dir: PathBuf, disable_gpu_acceleration: bool) -> Result<SingleThreadedCefContext, InitError> {
fn create_browser<H: CefEventHandler>(event_handler: H, instance_dir: TempDir, disable_gpu_acceleration: bool) -> Result<SingleThreadedCefContext, InitError> {
let mut client = Client::new(BrowserProcessClientImpl::new(&event_handler));

#[cfg(feature = "accelerated_paint")]
Expand Down Expand Up @@ -211,7 +210,7 @@ fn create_browser<H: CefEventHandler>(event_handler: H, instance_dir: PathBuf, d
event_handler: Box::new(event_handler),
browser,
input_state: InputState::default(),
instance_dir,
_instance_dir: instance_dir,
})
} else {
tracing::error!("Failed to create browser");
Expand Down
17 changes: 2 additions & 15 deletions desktop/src/cef/context/singlethreaded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use winit::event::WindowEvent;
use crate::cef::input::InputState;
use crate::cef::ipc::{MessageType, SendMessage};
use crate::cef::{CefEventHandler, input};
use crate::dirs::TempDir;

use super::CefContext;

pub(super) struct SingleThreadedCefContext {
pub(super) event_handler: Box<dyn CefEventHandler>,
pub(super) browser: Browser,
pub(super) input_state: InputState,
pub(super) instance_dir: std::path::PathBuf,
pub(super) _instance_dir: TempDir,
}

impl CefContext for SingleThreadedCefContext {
Expand Down Expand Up @@ -46,19 +47,6 @@ impl Drop for SingleThreadedCefContext {
// CEF wants us to close the browser before shutting down, otherwise it may run longer that necessary.
self.browser.host().unwrap().close_browser(1);
cef::shutdown();

// Sometimes some CEF processes still linger at this point and hold file handles to the cache directory.
// To mitigate this, we try to remove the directory multiple times with some delay.
// TODO: find a better solution if possible.
for _ in 0..30 {
match std::fs::remove_dir_all(&self.instance_dir) {
Ok(_) => break,
Err(e) => {
tracing::warn!("Failed to remove CEF cache directory, retrying...: {e}");
std::thread::sleep(std::time::Duration::from_millis(100));
}
}
}
}
}

Expand All @@ -68,7 +56,6 @@ impl SendMessage for SingleThreadedCefContext {
tracing::error!("Main frame is not available, cannot send message");
return;
};

frame.send_message(message_type, message);
}
}
24 changes: 0 additions & 24 deletions desktop/src/cef/dirs.rs

This file was deleted.

54 changes: 51 additions & 3 deletions desktop/src/dirs.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::fs::create_dir_all;
use std::path::PathBuf;
use std::fs;
use std::io;
use std::path::{Component, Path, PathBuf};

use crate::consts::{APP_DIRECTORY_NAME, APP_DOCUMENTS_DIRECTORY_NAME};

pub(crate) fn ensure_dir_exists(path: &PathBuf) {
if !path.exists() {
create_dir_all(path).unwrap_or_else(|_| panic!("Failed to create directory at {path:?}"));
fs::create_dir_all(path).unwrap_or_else(|_| panic!("Failed to create directory at {path:?}"));
}
}

Expand All @@ -20,3 +21,50 @@ pub(crate) fn app_autosave_documents_dir() -> PathBuf {
ensure_dir_exists(&path);
path
}

/// Temporary directory that is automatically deleted when dropped.
pub struct TempDir {
path: PathBuf,
}

impl TempDir {
pub fn new() -> io::Result<Self> {
Self::new_with_parent(dirs::cache_dir().unwrap_or_else(std::env::temp_dir))
}

pub fn new_with_parent(parent: impl AsRef<Path>) -> io::Result<Self> {
let random_suffix: String = (0..32).map(|_| format!("{:x}", rand::random::<u8>() % 16)).collect();
let name = format!("{}_{}_{}", APP_DIRECTORY_NAME, std::process::id(), random_suffix);
let path = parent.as_ref().join(name);
fs::create_dir_all(&path)?;
Ok(Self { path })
}

pub fn child(&self, rel: impl AsRef<Path>) -> PathBuf {
let joined = self.path.join(rel.as_ref());
let mut normalized = PathBuf::new();
for c in joined.components() {
match c {
Component::ParentDir => {
normalized.pop();
}
Component::CurDir => {}
c => normalized.push(c),
}
}
assert!(normalized.starts_with(&self.path), "child path escapes TempDir: {}", rel.as_ref().display());
normalized
}
}

impl Drop for TempDir {
fn drop(&mut self) {
let _ = fs::remove_dir_all(&self.path);
}
}

impl AsRef<Path> for TempDir {
fn as_ref(&self) -> &Path {
&self.path
}
}
Loading
Loading