Skip to content

Commit b74cc7a

Browse files
Review
1 parent 83035b0 commit b74cc7a

File tree

8 files changed

+66
-83
lines changed

8 files changed

+66
-83
lines changed

desktop/src/app.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ impl App {
316316
}
317317
DesktopFrontendMessage::PersistenceLoadDocuments => {
318318
// Open all documents in persisted tab order, then select the current one
319-
for (id, document) in self.persistent_data.all_documents() {
319+
for (id, document) in self.persistent_data.documents() {
320320
responses.push(DesktopWrapperMessage::LoadDocument {
321321
id,
322322
document,

desktop/src/cef.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ use crate::wrapper::{WgpuContext, deserialize_editor_message};
2727

2828
mod consts;
2929
mod context;
30-
mod dirs;
3130
mod input;
3231
mod internal;
3332
mod ipc;

desktop/src/cef/context/builder.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ use cef::{
44
App, BrowserSettings, CefString, Client, DictionaryValue, ImplCommandLine, ImplRequestContext, LogSeverity, RequestContextSettings, SchemeHandlerFactory, Settings, WindowInfo, api_hash,
55
browser_host_create_browser_sync, execute_process,
66
};
7-
use std::path::{Path, PathBuf};
7+
use std::path::Path;
88

99
use super::CefContext;
1010
use super::singlethreaded::SingleThreadedCefContext;
1111
use crate::cef::CefEventHandler;
1212
use crate::cef::consts::{RESOURCE_DOMAIN, RESOURCE_SCHEME};
13-
use crate::cef::dirs::{create_instance_dir, delete_instance_dirs};
1413
use crate::cef::input::InputState;
1514
use crate::cef::internal::{BrowserProcessAppImpl, BrowserProcessClientImpl, RenderProcessAppImpl, SchemeHandlerFactoryImpl};
15+
use crate::dirs::TempDir;
1616

1717
pub(crate) struct CefContextBuilder<H: CefEventHandler> {
1818
pub(crate) args: Args,
@@ -97,8 +97,7 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
9797

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

103102
let exe = std::env::current_exe().expect("cannot get current exe path");
104103
let app_root = exe.parent().and_then(|p| p.parent()).expect("bad path structure").parent().expect("bad path structure");
@@ -108,7 +107,7 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
108107
multi_threaded_message_loop: 0,
109108
external_message_pump: 1,
110109
no_sandbox: 1, // GPU helper crashes when running with sandbox
111-
..Self::common_settings(&instance_dir)
110+
..Self::common_settings(instance_dir.as_ref())
112111
};
113112

114113
self.initialize_inner(&event_handler, settings)?;
@@ -118,14 +117,13 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
118117

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

124122
let settings = Settings {
125123
multi_threaded_message_loop: 1,
126124
#[cfg(target_os = "linux")]
127125
no_sandbox: 1,
128-
..Self::common_settings(&instance_dir)
126+
..Self::common_settings(instance_dir.as_ref())
129127
};
130128

131129
self.initialize_inner(&event_handler, settings)?;
@@ -157,7 +155,7 @@ impl<H: CefEventHandler> CefContextBuilder<H> {
157155
}
158156
}
159157

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

163161
#[cfg(feature = "accelerated_paint")]
@@ -211,7 +209,7 @@ fn create_browser<H: CefEventHandler>(event_handler: H, instance_dir: PathBuf, d
211209
event_handler: Box::new(event_handler),
212210
browser,
213211
input_state: InputState::default(),
214-
instance_dir,
212+
_instance_dir: instance_dir,
215213
})
216214
} else {
217215
tracing::error!("Failed to create browser");

desktop/src/cef/context/multithreaded.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,12 @@ impl CefContext for MultiThreadedCefContextProxy {
5454
impl Drop for MultiThreadedCefContextProxy {
5555
fn drop(&mut self) {
5656
// Force dropping underlying context on the UI thread
57-
run_on_ui_thread(move || drop(CONTEXT.take()));
57+
let (sync_drop_tx, sync_drop_rx) = std::sync::mpsc::channel();
58+
run_on_ui_thread(move || {
59+
drop(CONTEXT.take());
60+
sync_drop_tx.send(()).unwrap();
61+
});
62+
sync_drop_rx.recv().unwrap();
5863
}
5964
}
6065

desktop/src/cef/context/singlethreaded.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ use winit::event::WindowEvent;
44
use crate::cef::input::InputState;
55
use crate::cef::ipc::{MessageType, SendMessage};
66
use crate::cef::{CefEventHandler, input};
7+
use crate::dirs::TempDir;
78

89
use super::CefContext;
910

1011
pub(super) struct SingleThreadedCefContext {
1112
pub(super) event_handler: Box<dyn CefEventHandler>,
1213
pub(super) browser: Browser,
1314
pub(super) input_state: InputState,
14-
pub(super) instance_dir: std::path::PathBuf,
15+
pub(super) _instance_dir: TempDir,
1516
}
1617

1718
impl CefContext for SingleThreadedCefContext {
@@ -46,19 +47,6 @@ impl Drop for SingleThreadedCefContext {
4647
// CEF wants us to close the browser before shutting down, otherwise it may run longer that necessary.
4748
self.browser.host().unwrap().close_browser(1);
4849
cef::shutdown();
49-
50-
// Sometimes some CEF processes still linger at this point and hold file handles to the cache directory.
51-
// To mitigate this, we try to remove the directory multiple times with some delay.
52-
// TODO: find a better solution if possible.
53-
for _ in 0..30 {
54-
match std::fs::remove_dir_all(&self.instance_dir) {
55-
Ok(_) => break,
56-
Err(e) => {
57-
tracing::warn!("Failed to remove CEF cache directory, retrying...: {e}");
58-
std::thread::sleep(std::time::Duration::from_millis(100));
59-
}
60-
}
61-
}
6250
}
6351
}
6452

@@ -68,7 +56,6 @@ impl SendMessage for SingleThreadedCefContext {
6856
tracing::error!("Main frame is not available, cannot send message");
6957
return;
7058
};
71-
7259
frame.send_message(message_type, message);
7360
}
7461
}

desktop/src/cef/dirs.rs

Lines changed: 0 additions & 24 deletions
This file was deleted.

desktop/src/dirs.rs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
use std::fs::create_dir_all;
2-
use std::path::PathBuf;
1+
use std::fs;
2+
use std::io;
3+
use std::path::{Component, Path, PathBuf};
34

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

67
pub(crate) fn ensure_dir_exists(path: &PathBuf) {
78
if !path.exists() {
8-
create_dir_all(path).unwrap_or_else(|_| panic!("Failed to create directory at {path:?}"));
9+
fs::create_dir_all(path).unwrap_or_else(|_| panic!("Failed to create directory at {path:?}"));
910
}
1011
}
1112

@@ -20,3 +21,37 @@ pub(crate) fn app_autosave_documents_dir() -> PathBuf {
2021
ensure_dir_exists(&path);
2122
path
2223
}
24+
25+
/// Temporary directory that is automatically deleted when dropped.
26+
pub struct TempDir {
27+
path: PathBuf,
28+
}
29+
30+
impl TempDir {
31+
pub fn new() -> io::Result<Self> {
32+
Self::new_with_parent(dirs::cache_dir().unwrap_or_else(std::env::temp_dir))
33+
}
34+
35+
pub fn new_with_parent(parent: impl AsRef<Path>) -> io::Result<Self> {
36+
let random_suffix: String = (0..32).map(|_| format!("{:x}", rand::random::<u8>() % 16)).collect();
37+
let name = format!("{}_{}_{}", APP_DIRECTORY_NAME, std::process::id(), random_suffix);
38+
let path = parent.as_ref().join(name);
39+
fs::create_dir_all(&path)?;
40+
Ok(Self { path })
41+
}
42+
}
43+
44+
impl Drop for TempDir {
45+
fn drop(&mut self) {
46+
let result = fs::remove_dir_all(&self.path);
47+
if let Err(e) = result {
48+
tracing::error!("Failed to remove temporary directory at {:?}: {}", self.path, e);
49+
}
50+
}
51+
}
52+
53+
impl AsRef<Path> for TempDir {
54+
fn as_ref(&self) -> &Path {
55+
&self.path
56+
}
57+
}

desktop/src/persist.rs

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ impl PersistentData {
2929
tracing::error!("Failed to write document {id:?} to disk: {e}");
3030
}
3131

32-
if let Some(order) = &self.document_order {
33-
self.force_order(&order.clone());
34-
}
3532
self.flush();
3633
}
3734

@@ -55,7 +52,7 @@ impl PersistentData {
5552
}
5653
}
5754

58-
pub(crate) fn all_documents(&self) -> Vec<(DocumentId, Document)> {
55+
pub(crate) fn documents(&self) -> Vec<(DocumentId, Document)> {
5956
self.documents.iter().filter_map(|doc| Some((doc.id, self.read_document(&doc.id)?))).collect()
6057
}
6158

@@ -65,7 +62,16 @@ impl PersistentData {
6562
}
6663

6764
pub(crate) fn force_document_order(&mut self, order: Vec<DocumentId>) {
68-
self.force_order(&order);
65+
let mut ordered_prefix_length = 0;
66+
for id in &order {
67+
if let Some(offset) = self.documents[ordered_prefix_length..].iter().position(|doc| doc.id == *id) {
68+
let found_index = ordered_prefix_length + offset;
69+
if found_index != ordered_prefix_length {
70+
self.documents[ordered_prefix_length..=found_index].rotate_right(1);
71+
}
72+
ordered_prefix_length += 1;
73+
}
74+
}
6975
self.document_order = Some(order);
7076
self.flush();
7177
}
@@ -82,20 +88,6 @@ impl PersistentData {
8288
})
8389
}
8490

85-
// Reorders the documents array to match a desired ordering, keeping unmentioned documents at the end
86-
fn force_order(&mut self, desired_order: &[DocumentId]) {
87-
let mut ordered_prefix_length = 0;
88-
for id in desired_order {
89-
if let Some(offset) = self.documents[ordered_prefix_length..].iter().position(|doc| doc.id == *id) {
90-
let found_index = ordered_prefix_length + offset;
91-
if found_index != ordered_prefix_length {
92-
self.documents[ordered_prefix_length..=found_index].rotate_right(1);
93-
}
94-
ordered_prefix_length += 1;
95-
}
96-
}
97-
}
98-
9991
fn flush(&self) {
10092
let data = match ron::ser::to_string_pretty(self, Default::default()) {
10193
Ok(d) => d,
@@ -132,7 +124,6 @@ impl PersistentData {
132124
*self = loaded;
133125

134126
self.garbage_collect_document_files();
135-
Self::delete_old_cef_browser_directory();
136127
}
137128

138129
// Remove orphaned document content files that have no corresponding entry in the persisted state
@@ -159,14 +150,6 @@ impl PersistentData {
159150
}
160151
}
161152

162-
// TODO: Eventually remove this cleanup code for the old "browser" CEF directory (renamed to "cef")
163-
fn delete_old_cef_browser_directory() {
164-
let old_browser_dir = crate::dirs::app_data_dir().join("browser");
165-
if old_browser_dir.is_dir() {
166-
let _ = std::fs::remove_dir_all(&old_browser_dir);
167-
}
168-
}
169-
170153
fn state_file_path() -> std::path::PathBuf {
171154
let mut path = crate::dirs::app_data_dir();
172155
path.push(crate::consts::APP_STATE_FILE_NAME);

0 commit comments

Comments
 (0)