Repository: servo/servo
File: components/net/filemanager_thread.rs (Rust)

Code before:
    }

    fn select_files(
        &self,
        control_id: EmbedderControlId,
        file_picker_request: FilePickerRequest,
        response_sender: IpcSender<EmbedderControlResponse>,
        embedder_proxy: EmbedderProxy,
    ) {
        let (ipc_sender, ipc_receiver) =
            generic_channel::channel().expect("Failed to create IPC channel!");

        let origin = file_picker_request.origin.clone();
        embedder_proxy.send(EmbedderMsg::SelectFiles(
            control_id,
            file_picker_request,
            ipc_sender,
        ));

        let paths = match ipc_receiver.recv() {
            Ok(Some(result)) => result,
            Ok(None) => {
                let _ = response_sender.send(EmbedderControlResponse::FilePicker(None));
                return;
            },
            Err(error) => {
                warn!("Failed to receive files from embedder ({:?}).", error);
                let _ = response_sender.send(EmbedderControlResponse::FilePicker(None));
                return;
            },
        };

        let mut failed = false;
        let files: Vec<_> = paths
            .into_iter()
            .filter_map(|path| match self.create_entry(&path, &origin) {
                Ok(entry) => Some(entry),
                Err(error) => {
                    failed = true;
                    warn!("Failed to create entry for selected file: {error:?}");
                    None
                },
            })
            .collect();

        // From <https://w3c.github.io/webdriver/#dfn-element-send-keys>:
        //
        // > Step 8.5: Verify that each file given by the user exists. If any do not,
        // > return error with error code invalid argument.
        //
        // WebDriver expects that if any of the files isn't found we don't select any files.

Review comment (suggestion):
The file picker dialog will now block one of the task pool threads until it's closed. We can use https://github.com/servo/ipc-channel/blob/6997d3f089f5d656ca3a94f4ea71533d002a4eb5/src/asynch.rs#L84 to avoid this and make the blocking recv async-friendly.

Code after:
                // We assume that the returned id will be held by BlobImpl::File
                let _ = sender.send(Ok(new_id));
            },
            Err(e) => {
                let _ = sender.send(Err(e));
            },
        }
    }

    async fn select_files(
        &self,
        control_id: EmbedderControlId,
        file_picker_request: FilePickerRequest,
        embedder_proxy: EmbedderProxy,
    ) -> EmbedderControlResponse {
        let (ipc_sender, ipc_receiver) =
            generic_channel::channel().expect("Failed to create IPC channel!");

        let origin = file_picker_request.origin.clone();
        embedder_proxy.send(EmbedderMsg::SelectFiles(
            control_id,
            file_picker_request,
            ipc_sender,
        ));

        let paths = match ipc_receiver.recv() {
            Ok(Some(result)) => result,
            Ok(None) => {
                return EmbedderControlResponse::FilePicker(None);
            },
            Err(error) => {
                warn!("Failed to receive files from embedder ({:?}).", error);
                return EmbedderControlResponse::FilePicker(None);
            },
        };

        let mut failed = false;
        let files: Vec<_> = paths
            .into_iter()
            .filter_map(|path| match self.create_entry(&path, &origin) {
                Ok(entry) => Some(entry),
                Err(error) => {
                    failed = true;
                    warn!("Failed to create entry for selected file: {error:?}");
                    None
                },
            })
            .collect();

        // From <https://w3c.github.io/webdriver/#dfn-element-send-keys>:
        //