web: Fix cors issues with http (close ruffle-rs#1486)
This commit is contained in:
parent
8f34023ad2
commit
c4d7b24629
|
@ -198,6 +198,12 @@ pub trait NavigatorBackend {
|
|||
/// current document's base URL, while the most obvious base for a desktop
|
||||
/// client would be the file-URL form of the current path.
|
||||
fn resolve_relative_url<'a>(&mut self, url: &'a str) -> Cow<'a, str>;
|
||||
|
||||
/// Handle any context specific pre-processing
|
||||
///
|
||||
/// Changing http -> https for example. This function may alter any part of the
|
||||
/// URL (generally only if configured to do so by the user).
|
||||
fn pre_process_url(&self, url: Url) -> Url;
|
||||
}
|
||||
|
||||
/// A null implementation of an event loop that only supports blocking.
|
||||
|
@ -378,4 +384,8 @@ impl NavigatorBackend for NullNavigatorBackend {
|
|||
url.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn pre_process_url(&self, url: Url) -> Url {
|
||||
url
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,6 +76,10 @@ struct Opt {
|
|||
/// (Optional) Proxy to use when loading movies via URL
|
||||
#[clap(long, case_insensitive = true)]
|
||||
proxy: Option<Url>,
|
||||
|
||||
/// (Optional) Replace all embedded http URLs with https
|
||||
#[clap(long, case_insensitive = true, takes_value = false)]
|
||||
upgrade_to_https: bool,
|
||||
}
|
||||
|
||||
#[cfg(feature = "render_trace")]
|
||||
|
@ -207,6 +211,7 @@ fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> {
|
|||
chan,
|
||||
event_loop.create_proxy(),
|
||||
opt.proxy,
|
||||
opt.upgrade_to_https,
|
||||
)); //TODO: actually implement this backend type
|
||||
let input = Box::new(input::WinitInputBackend::new(window.clone()));
|
||||
let storage = Box::new(DiskStorageBackend::new(
|
||||
|
|
|
@ -34,6 +34,8 @@ pub struct ExternalNavigatorBackend {
|
|||
|
||||
// Client to use for network requests
|
||||
client: Option<Rc<HttpClient>>,
|
||||
|
||||
upgrade_to_https: bool,
|
||||
}
|
||||
|
||||
impl ExternalNavigatorBackend {
|
||||
|
@ -44,6 +46,7 @@ impl ExternalNavigatorBackend {
|
|||
channel: Sender<OwnedFuture<(), Error>>,
|
||||
event_loop: EventLoopProxy<RuffleEvent>,
|
||||
proxy: Option<Url>,
|
||||
upgrade_to_https: bool,
|
||||
) -> Self {
|
||||
let proxy = proxy.and_then(|url| url.as_str().parse().ok());
|
||||
let builder = HttpClient::builder()
|
||||
|
@ -58,6 +61,7 @@ impl ExternalNavigatorBackend {
|
|||
client,
|
||||
movie_url,
|
||||
start_time: Instant::now(),
|
||||
upgrade_to_https,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -96,36 +100,37 @@ impl NavigatorBackend for ExternalNavigatorBackend {
|
|||
}
|
||||
}
|
||||
|
||||
parsed_url.into_string()
|
||||
parsed_url
|
||||
}
|
||||
None => url,
|
||||
None => parsed_url,
|
||||
};
|
||||
|
||||
match webbrowser::open(&modified_url) {
|
||||
let processed_url = self.pre_process_url(modified_url);
|
||||
|
||||
match webbrowser::open(&processed_url.to_string()) {
|
||||
Ok(_output) => {}
|
||||
Err(e) => log::error!("Could not open URL {}: {}", modified_url, e),
|
||||
Err(e) => log::error!("Could not open URL {}: {}", processed_url.as_str(), e),
|
||||
};
|
||||
}
|
||||
|
||||
fn time_since_launch(&mut self) -> Duration {
|
||||
Instant::now().duration_since(self.start_time)
|
||||
}
|
||||
|
||||
fn fetch(&self, url: &str, options: RequestOptions) -> OwnedFuture<Vec<u8>, Error> {
|
||||
// TODO: honor sandbox type (local-with-filesystem, local-with-network, remote, ...)
|
||||
let full_url = self.movie_url.clone().join(url).unwrap();
|
||||
|
||||
let processed_url = self.pre_process_url(full_url);
|
||||
|
||||
let client = self.client.clone();
|
||||
match full_url.scheme() {
|
||||
|
||||
match processed_url.scheme() {
|
||||
"file" => Box::pin(async move {
|
||||
fs::read(full_url.to_file_path().unwrap()).map_err(Error::NetworkError)
|
||||
fs::read(processed_url.to_file_path().unwrap()).map_err(Error::NetworkError)
|
||||
}),
|
||||
_ => Box::pin(async move {
|
||||
let client = client.ok_or(Error::NetworkUnavailable)?;
|
||||
|
||||
let request = match options.method() {
|
||||
NavigationMethod::GET => Request::get(full_url.to_string()),
|
||||
NavigationMethod::POST => Request::post(full_url.to_string()),
|
||||
NavigationMethod::GET => Request::get(processed_url.to_string()),
|
||||
NavigationMethod::POST => Request::post(processed_url.to_string()),
|
||||
};
|
||||
|
||||
let (body_data, _) = options.body().clone().unwrap_or_default();
|
||||
|
@ -143,6 +148,10 @@ impl NavigatorBackend for ExternalNavigatorBackend {
|
|||
}
|
||||
}
|
||||
|
||||
fn time_since_launch(&mut self) -> Duration {
|
||||
Instant::now().duration_since(self.start_time)
|
||||
}
|
||||
|
||||
fn spawn_future(&mut self, future: OwnedFuture<(), Error>) {
|
||||
self.channel.send(future).expect("working channel send");
|
||||
|
||||
|
@ -161,6 +170,13 @@ impl NavigatorBackend for ExternalNavigatorBackend {
|
|||
url.into()
|
||||
}
|
||||
}
|
||||
|
||||
fn pre_process_url(&self, mut url: Url) -> Url {
|
||||
if self.upgrade_to_https && url.scheme() == "http" && url.set_scheme("https").is_err() {
|
||||
log::error!("Url::set_scheme failed on: {}", url);
|
||||
}
|
||||
url
|
||||
}
|
||||
}
|
||||
|
||||
fn response_to_bytes(res: Response<Body>) -> Result<Vec<u8>, std::io::Error> {
|
||||
|
|
|
@ -69,6 +69,19 @@ export interface BaseLoadOptions {
|
|||
* @default UnmuteOverlay.Visible
|
||||
*/
|
||||
unmuteOverlay?: UnmuteOverlay;
|
||||
|
||||
/**
|
||||
* Whether or not to auto-upgrade all embedded URLs to https.
|
||||
*
|
||||
* Flash content that embeds http urls will be blocked from
|
||||
* accessing those urls by the browser when Ruffle is loaded
|
||||
* in a https context. Set to `true` to automatically change
|
||||
* `http://` to `https://` for all embedded URLs when Ruffle is
|
||||
* loaded in an https context.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
upgradeToHttps?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -314,7 +314,9 @@ export class RufflePlayer extends HTMLElement {
|
|||
this.instance = new ruffleConstructor(
|
||||
this.container,
|
||||
this,
|
||||
this.allowScriptAccess
|
||||
this.allowScriptAccess,
|
||||
config.upgradeToHttps !== false &&
|
||||
window.location.protocol === "https:"
|
||||
);
|
||||
console.log("New Ruffle instance created.");
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ impl Ruffle {
|
|||
parent: HtmlElement,
|
||||
js_player: JavascriptPlayer,
|
||||
allow_script_access: bool,
|
||||
upgrade_to_https: bool,
|
||||
) -> Result<Ruffle, JsValue> {
|
||||
if RUFFLE_GLOBAL_PANIC.is_completed() {
|
||||
// If an actual panic happened, then we can't trust the state it left us in.
|
||||
|
@ -122,7 +123,7 @@ impl Ruffle {
|
|||
return Err("Ruffle is panicking!".into());
|
||||
}
|
||||
set_panic_handler();
|
||||
Ruffle::new_internal(parent, js_player, allow_script_access)
|
||||
Ruffle::new_internal(parent, js_player, allow_script_access, upgrade_to_https)
|
||||
.map_err(|_| "Error creating player".into())
|
||||
}
|
||||
|
||||
|
@ -284,6 +285,7 @@ impl Ruffle {
|
|||
parent: HtmlElement,
|
||||
js_player: JavascriptPlayer,
|
||||
allow_script_access: bool,
|
||||
upgrade_to_https: bool,
|
||||
) -> Result<Ruffle, Box<dyn Error>> {
|
||||
let _ = console_log::init_with_level(log::Level::Trace);
|
||||
|
||||
|
@ -296,7 +298,7 @@ impl Ruffle {
|
|||
.into_js_result()?;
|
||||
|
||||
let audio = Box::new(WebAudioBackend::new()?);
|
||||
let navigator = Box::new(WebNavigatorBackend::new());
|
||||
let navigator = Box::new(WebNavigatorBackend::new(upgrade_to_https));
|
||||
let input = Box::new(WebInputBackend::new(&canvas));
|
||||
let locale = Box::new(WebLocaleBackend::new());
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
//! Navigator backend for web
|
||||
|
||||
use js_sys::{Array, ArrayBuffer, Uint8Array};
|
||||
use ruffle_core::backend::navigator::{
|
||||
url_from_relative_url, NavigationMethod, NavigatorBackend, OwnedFuture, RequestOptions,
|
||||
|
@ -8,6 +7,7 @@ use ruffle_core::indexmap::IndexMap;
|
|||
use ruffle_core::loader::Error;
|
||||
use std::borrow::Cow;
|
||||
use std::time::Duration;
|
||||
use url::Url;
|
||||
use wasm_bindgen::JsCast;
|
||||
use wasm_bindgen_futures::{spawn_local, JsFuture};
|
||||
use web_sys::{window, Blob, BlobPropertyBag, Performance, Request, RequestInit, Response};
|
||||
|
@ -15,16 +15,18 @@ use web_sys::{window, Blob, BlobPropertyBag, Performance, Request, RequestInit,
|
|||
pub struct WebNavigatorBackend {
|
||||
performance: Performance,
|
||||
start_time: f64,
|
||||
upgrade_to_https: bool,
|
||||
}
|
||||
|
||||
impl WebNavigatorBackend {
|
||||
pub fn new() -> Self {
|
||||
pub fn new(upgrade_to_https: bool) -> Self {
|
||||
let window = web_sys::window().expect("window()");
|
||||
let performance = window.performance().expect("window.performance()");
|
||||
|
||||
WebNavigatorBackend {
|
||||
start_time: performance.now(),
|
||||
performance,
|
||||
upgrade_to_https,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,6 +39,12 @@ impl NavigatorBackend for WebNavigatorBackend {
|
|||
vars_method: Option<(NavigationMethod, IndexMap<String, String>)>,
|
||||
) {
|
||||
if let Some(window) = window() {
|
||||
let url = if let Ok(parsed_url) = Url::parse(&url) {
|
||||
self.pre_process_url(parsed_url).to_string()
|
||||
} else {
|
||||
url.to_string()
|
||||
};
|
||||
|
||||
//TODO: Should we return a result for failed opens? Does Flash care?
|
||||
#[allow(unused_must_use)]
|
||||
match (vars_method, window_spec) {
|
||||
|
@ -95,7 +103,12 @@ impl NavigatorBackend for WebNavigatorBackend {
|
|||
}
|
||||
|
||||
fn fetch(&self, url: &str, options: RequestOptions) -> OwnedFuture<Vec<u8>, Error> {
|
||||
let url = url.to_string();
|
||||
let url = if let Ok(parsed_url) = Url::parse(url) {
|
||||
self.pre_process_url(parsed_url).to_string()
|
||||
} else {
|
||||
url.to_string()
|
||||
};
|
||||
|
||||
Box::pin(async move {
|
||||
let mut init = RequestInit::new();
|
||||
|
||||
|
@ -172,4 +185,11 @@ impl NavigatorBackend for WebNavigatorBackend {
|
|||
|
||||
url.into()
|
||||
}
|
||||
|
||||
fn pre_process_url(&self, mut url: Url) -> Url {
|
||||
if self.upgrade_to_https && url.scheme() == "http" && url.set_scheme("https").is_err() {
|
||||
log::error!("Url::set_scheme failed on: {}", url);
|
||||
}
|
||||
url
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue