use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use embedder_traits::{
EmbedderControlId, EmbedderControlResponse, FilePickerRequest, FilterPattern,
};
use ipc_channel::ipc;
use net::async_runtime::init_async_runtime;
use net::embedder::NetToEmbedderMsg;
use net::filemanager_thread::FileManager;
use net_traits::blob_url_store::BlobURLStoreError;
use net_traits::filemanager_thread::{
FileManagerThreadError, FileManagerThreadMsg, ReadFileProgress,
};
use servo_base::id::{TEST_PIPELINE_ID, TEST_WEBVIEW_ID};
use servo_base::{Epoch, generic_channel};
use servo_config::prefs::Preferences;
use servo_url::ServoUrl;
use crate::create_generic_embedder_proxy_and_receiver;
#[test]
fn test_filemanager() {
let _runtime = init_async_runtime();
let mut preferences = Preferences::default();
preferences.dom_testing_html_input_element_select_files_enabled = true;
servo_config::prefs::set(preferences);
let (embedder_proxy, embedder_receiver) = create_generic_embedder_proxy_and_receiver();
let filemanager = FileManager::new(embedder_proxy);
let mut handler = File::open("tests/test.jpeg").expect("test.jpeg is stolen");
let mut test_file_content = vec![];
handler
.read_to_end(&mut test_file_content)
.expect("Read components/net/tests/test.jpeg error");
let origin = ServoUrl::parse("http://test.com").unwrap().origin();
{
let (result_sender, result_receiver) = crossbeam_channel::unbounded();
let callback = profile_traits::generic_callback::GenericCallback::new(
profile_traits::time::ProfilerChan(None),
move |msg| {
result_sender.send(msg.unwrap()).unwrap();
},
)
.unwrap();
let control_id = EmbedderControlId {
webview_id: TEST_WEBVIEW_ID,
pipeline_id: TEST_PIPELINE_ID,
index: Epoch(0),
};
let file_picker_request = FilePickerRequest {
origin: origin.clone(),
current_paths: vec!["tests/test.jpeg".into()],
filter_patterns: vec![FilterPattern(".txt".to_string())],
allow_select_multiple: false,
accept_current_paths_for_testing: true,
};
filemanager.handle(FileManagerThreadMsg::SelectFiles(
control_id,
file_picker_request,
callback,
));
loop {
let message = embedder_receiver
.recv()
.expect("Should always read message properly");
match message {
NetToEmbedderMsg::SelectFiles(_, file_picker_request, response_sender) => {
let _ = response_sender.send(Some(file_picker_request.current_paths));
break;
},
_ => {},
}
}
let selected_files = match result_receiver.recv().expect("Broken channel") {
EmbedderControlResponse::FilePicker(selected_files) => selected_files,
_ => unreachable!("Received unexpected EmbedderControlResponse"),
}
.expect("Expected to get a list of files from embedder.");
let selected = selected_files
.first()
.expect("Should receive at least one file");
assert_eq!(selected.filename, PathBuf::from("test.jpeg"));
assert_eq!(selected.type_string, "image/jpeg".to_string());
{
let (tx2, rx2) = ipc::channel().unwrap();
filemanager.handle(FileManagerThreadMsg::ReadFile(
tx2,
selected.id.clone(),
origin.clone(),
));
let msg = rx2.recv().expect("Broken channel");
if let ReadFileProgress::Meta(blob_buf) =
msg.expect("File manager reading failure is unexpected")
{
let mut bytes = blob_buf.bytes;
loop {
match rx2
.recv()
.expect("Broken channel")
.expect("File manager reading failure is unexpected")
{
ReadFileProgress::Meta(_) => {
panic!("Invalid FileManager reply");
},
ReadFileProgress::Partial(mut bytes_in) => {
bytes.append(&mut bytes_in);
},
ReadFileProgress::EOF => {
break;
},
}
}
assert_eq!(test_file_content, bytes, "Read content differs");
} else {
panic!("Invalid FileManager reply");
}
}
{
let (tx2, rx2) = generic_channel::channel().unwrap();
filemanager.handle(FileManagerThreadMsg::DecRef(
selected.id.clone(),
origin.clone(),
tx2,
));
assert!(rx2.recv().is_ok(), "DecRef is not okay");
}
{
let (tx2, rx2) = ipc::channel().unwrap();
filemanager.handle(FileManagerThreadMsg::ReadFile(
tx2,
selected.id.clone(),
origin.clone(),
));
let msg = rx2.recv().expect("Broken channel");
match msg {
Err(FileManagerThreadError::BlobURLStoreError(
BlobURLStoreError::InvalidFileID,
)) => {},
other => {
assert!(
false,
"Get unexpected response after deleting the id: {:?}",
other
);
},
}
}
}
}