Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

avm1: Partially implement FileReference (Part of #307) #5086

Closed
wants to merge 1 commit into from

Conversation

hatal175
Copy link
Contributor

I've implemented mostly just the browse function which opens a file dialog. The download and upload have security implications, so I'm not sure how to take them into consideration (if the framework is implemented at all).

For the dialog, I've added the rfd crate. It allows for asynchronous file dialogs which the tiny dialog crate don't have, and are part of the spec according the docs.

@midgleyc
Copy link
Contributor

The download and upload have security implications, so I'm not sure how to take them into consideration (if the framework is implemented at all).

At the moment, I think we ignore the security framework (e.g. on LoadVars or XML).

I think that this doesn't matter so much: download is effectively a GET of a given URL, and upload a POST: if a user can do these inside Flash, they can also do them outside Flash, so I don't find it terribly concerning if Ruffle just does these ignoring the sandboxing.

@hatal175
Copy link
Contributor Author

hatal175 commented Aug 17, 2021 via email

@midgleyc
Copy link
Contributor

I think that would be nice :)

In terms of SWFs in the wild using this: I know of one web-based management interface that uses upload (first parameter only). I don't know of anything using download, but I wouldn't be surprised to see it.

Copy link
Contributor

@midgleyc midgleyc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments on the desktop file selector also apply to the web one. A lot of the code is shared: can it be moved up a level somehow?

core/src/avm1/globals.rs Outdated Show resolved Hide resolved
core/src/loader.rs Outdated Show resolved Hide resolved
desktop/src/ui.rs Outdated Show resolved Hide resolved
desktop/src/ui.rs Show resolved Hide resolved
@kmeisthax
Copy link
Member

Regarding the security checks: our intention on web is to not open up any new web attack surface, so on the web we don't need to run the same security checks for download or upload since we're not bothering with policy files or anything. browse is equivalent to populating a file upload input on web and is perfectly fine.

On desktop the story changes a little. Flash movies on desktop inherently don't come with an origin. The original security model for local file access was web-only or filesystem-only, controlled with some movie metadata. This is a restriction we absolutely don't implement right now. When we implement download or upload we may want to consider changing ExternalNavigatorBackend so that it can be locked one way or the other.

@hatal175
Copy link
Contributor Author

hatal175 commented Aug 20, 2021

Comments on the desktop file selector also apply to the web one. A lot of the code is shared: can it be moved up a level somehow?

Well, technically yes, but no :) I could put in core but there are no other implementations of obviously ui code there... if other people also think so, I can move it.

@hatal175
Copy link
Contributor Author

I don't think I'm going to implement the download/upload pair in this pull request. After an answer to the duplication of the ui code, I'll rebase this and consider this complete for now.

@midgleyc
Copy link
Contributor

You have a leftover log::warn!("{}", extensions[0]); in desktop/src/ui.rs, other than that looks good to me.

@hatal175 hatal175 force-pushed the filereference branch 2 times, most recently from deb1592 to 563b6a8 Compare August 22, 2021 03:55
@adrian17
Copy link
Collaborator

adrian17 commented Sep 5, 2021

For the record, the web popup looks like this:
image

@adrian17
Copy link
Collaborator

adrian17 commented Sep 5, 2021

I think the PR is good. One question from reading the docs:

Only one browse() session can be performed at a time (because only one dialog box can be displayed at a time).

Do we have a guard against that? What would happen if we called browse twice?
I don't think it's an issue on web (rfd shows a popup that makes it impossible to trigger new AS click events, right?), but not sure about desktop. If it's impossible on desktop too, then it's cool.

Also notes for the future:

Because of new functionality added to Flash Player, when publishing to Flash Player 10, you can have only one of the following operations active at one time: FileReference.browse(), FileReference.upload(), FileReference.download(). Otherwise, Flash Player throws a runtime error (code 2174). Use FileReference.cancel() to stop an operation in progress.

We'll probably need a guard against that, when we get upload/download.

In Flash Player 10 and later, you can call this method successfully only in response to a user event (for example, in an event handler for a mouse click or keypress event). Otherwise, calling this method results in Flash Player throwing an Error.

Ideally we should implement this at some point, but it's probably not a big immediate risk - since FP blocked this behavior, I don't think people bothered to even try to trigger this without user event.

Copy link
Collaborator

@adrian17 adrian17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(I'd appreciate if kmeisthax looked at the async portion too, but I think it's mergeable as-is)

@Herschel
Copy link
Member

Since this uses rfd, can we also use rfd for the initial Choose SWF dialog on desktop and remove tinyfiledialog? It feels odd to have two separate file dialog crates.

Copy link
Member

@Herschel Herschel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

Comment on lines +93 to +99
impl<'gc> From<u64> for Value<'gc> {
fn from(value: u64) -> Self {
Value::Number(value as f64)
}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get nervous about these kind of conversions, because u64 -> f64 can be lossy and from::From by convention should be a lossless conversion. But we already have From<usize>, so this is fine for now.


impl DesktopFileDialogResult {
pub fn new(handle: Option<FileHandle>) -> Self {
let md = handle.as_ref().and_then(|x| metadata(x.path()).ok());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style nit: Let's import fs::self and then do fs::metadata (makes it a little clearer that it's the standard metadata fn and not our own fn.)

Comment on lines +40 to +43
#[cfg(not(target_arch = "wasm32"))]
fn creation_time(&self) -> Option<DateTime<Utc>> {
unreachable!();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make two separate impl blocks and #[cfg(not(target_arch = "wasm32"))] on the impl block, instead of doing #[cfg] on each method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are functions that should be in both configs and functions that should be in just one. Since I can't do two trait implemenrations, it means I have to duplicate the functions that are in both... advice?

@Herschel
Copy link
Member

Also, looks like there's an undocumented FileReference.convertToPPT and deleteConvertedPPT, at least in the desktop player(?):

ASSetPropFlags(flash.net.FileReference.prototype, null, 6, 1);
for(var k in flash.net.FileReference.prototype) {
	trace(k);
}

No clue what they do, but we should at least mention these in a comment and/or possibly stub them out.

@hatal175
Copy link
Contributor Author

hatal175 commented Sep 12, 2021

I've fixed most of the issues you've raised except the cfg thing.

  1. I've removed tinyfiledialogs from the license - I hope that's ok.
  2. rfd can't set file dialog title for now - I have a pending pull request: Add set_title to FileDialog PolyMeilex/rfd#23. Pull request was merged and title was readded.
  3. I chose to add a comment since there's no real mention of those functions anywhere. It's probably used internally by flash somewhere so no real reason to stub.
  4. Also updated rfd crate while I'm at it.

@PolyMeilex
Copy link

For the record, the web popup looks like this:
image

I intentionally designed it in a way that is easy to customize, so you don't have to stick to that in case you don't like it, you can just provide CSS styles for IDs that RFD is using rfd-overlay,rfd-card,rfd-input,rfd-button

Default style can be used as a reference: https://github.com/PolyMeilex/rfd/blob/master/src/backend/wasm/style.css

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants