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
|
/// current document's base URL, while the most obvious base for a desktop
|
||||||
/// client would be the file-URL form of the current path.
|
/// client would be the file-URL form of the current path.
|
||||||
fn resolve_relative_url<'a>(&mut self, url: &'a str) -> Cow<'a, str>;
|
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.
|
/// A null implementation of an event loop that only supports blocking.
|
||||||
|
@ -378,4 +384,8 @@ impl NavigatorBackend for NullNavigatorBackend {
|
||||||
url.into()
|
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
|
/// (Optional) Proxy to use when loading movies via URL
|
||||||
#[clap(long, case_insensitive = true)]
|
#[clap(long, case_insensitive = true)]
|
||||||
proxy: Option<Url>,
|
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")]
|
#[cfg(feature = "render_trace")]
|
||||||
|
@ -207,6 +211,7 @@ fn run_player(opt: Opt) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
chan,
|
chan,
|
||||||
event_loop.create_proxy(),
|
event_loop.create_proxy(),
|
||||||
opt.proxy,
|
opt.proxy,
|
||||||
|
opt.upgrade_to_https,
|
||||||
)); //TODO: actually implement this backend type
|
)); //TODO: actually implement this backend type
|
||||||
let input = Box::new(input::WinitInputBackend::new(window.clone()));
|
let input = Box::new(input::WinitInputBackend::new(window.clone()));
|
||||||
let storage = Box::new(DiskStorageBackend::new(
|
let storage = Box::new(DiskStorageBackend::new(
|
||||||
|
|
|
@ -34,6 +34,8 @@ pub struct ExternalNavigatorBackend {
|
||||||
|
|
||||||
// Client to use for network requests
|
// Client to use for network requests
|
||||||
client: Option<Rc<HttpClient>>,
|
client: Option<Rc<HttpClient>>,
|
||||||
|
|
||||||
|
upgrade_to_https: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExternalNavigatorBackend {
|
impl ExternalNavigatorBackend {
|
||||||
|
@ -44,6 +46,7 @@ impl ExternalNavigatorBackend {
|
||||||
channel: Sender<OwnedFuture<(), Error>>,
|
channel: Sender<OwnedFuture<(), Error>>,
|
||||||
event_loop: EventLoopProxy<RuffleEvent>,
|
event_loop: EventLoopProxy<RuffleEvent>,
|
||||||
proxy: Option<Url>,
|
proxy: Option<Url>,
|
||||||
|
upgrade_to_https: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let proxy = proxy.and_then(|url| url.as_str().parse().ok());
|
let proxy = proxy.and_then(|url| url.as_str().parse().ok());
|
||||||
let builder = HttpClient::builder()
|
let builder = HttpClient::builder()
|
||||||
|
@ -58,6 +61,7 @@ impl ExternalNavigatorBackend {
|
||||||
client,
|
client,
|
||||||
movie_url,
|
movie_url,
|
||||||
start_time: Instant::now(),
|
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) => {}
|
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> {
|
fn fetch(&self, url: &str, options: RequestOptions) -> OwnedFuture<Vec<u8>, Error> {
|
||||||
// TODO: honor sandbox type (local-with-filesystem, local-with-network, remote, ...)
|
// TODO: honor sandbox type (local-with-filesystem, local-with-network, remote, ...)
|
||||||
let full_url = self.movie_url.clone().join(url).unwrap();
|
let full_url = self.movie_url.clone().join(url).unwrap();
|
||||||
|
|
||||||
|
let processed_url = self.pre_process_url(full_url);
|
||||||
|
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
match full_url.scheme() {
|
|
||||||
|
match processed_url.scheme() {
|
||||||
"file" => Box::pin(async move {
|
"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 {
|
_ => Box::pin(async move {
|
||||||
let client = client.ok_or(Error::NetworkUnavailable)?;
|
let client = client.ok_or(Error::NetworkUnavailable)?;
|
||||||
|
|
||||||
let request = match options.method() {
|
let request = match options.method() {
|
||||||
NavigationMethod::GET => Request::get(full_url.to_string()),
|
NavigationMethod::GET => Request::get(processed_url.to_string()),
|
||||||
NavigationMethod::POST => Request::post(full_url.to_string()),
|
NavigationMethod::POST => Request::post(processed_url.to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let (body_data, _) = options.body().clone().unwrap_or_default();
|
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>) {
|
fn spawn_future(&mut self, future: OwnedFuture<(), Error>) {
|
||||||
self.channel.send(future).expect("working channel send");
|
self.channel.send(future).expect("working channel send");
|
||||||
|
|
||||||
|
@ -161,6 +170,13 @@ impl NavigatorBackend for ExternalNavigatorBackend {
|
||||||
url.into()
|
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> {
|
fn response_to_bytes(res: Response<Body>) -> Result<Vec<u8>, std::io::Error> {
|
||||||
|
|
|
@ -69,6 +69,19 @@ export interface BaseLoadOptions {
|
||||||
* @default UnmuteOverlay.Visible
|
* @default UnmuteOverlay.Visible
|
||||||
*/
|
*/
|
||||||
unmuteOverlay?: UnmuteOverlay;
|
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.instance = new ruffleConstructor(
|
||||||
this.container,
|
this.container,
|
||||||
this,
|
this,
|
||||||
this.allowScriptAccess
|
this.allowScriptAccess,
|
||||||
|
config.upgradeToHttps !== false &&
|
||||||
|
window.location.protocol === "https:"
|
||||||
);
|
);
|
||||||
console.log("New Ruffle instance created.");
|
console.log("New Ruffle instance created.");
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,7 @@ impl Ruffle {
|
||||||
parent: HtmlElement,
|
parent: HtmlElement,
|
||||||
js_player: JavascriptPlayer,
|
js_player: JavascriptPlayer,
|
||||||
allow_script_access: bool,
|
allow_script_access: bool,
|
||||||
|
upgrade_to_https: bool,
|
||||||
) -> Result<Ruffle, JsValue> {
|
) -> Result<Ruffle, JsValue> {
|
||||||
if RUFFLE_GLOBAL_PANIC.is_completed() {
|
if RUFFLE_GLOBAL_PANIC.is_completed() {
|
||||||
// If an actual panic happened, then we can't trust the state it left us in.
|
// 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());
|
return Err("Ruffle is panicking!".into());
|
||||||
}
|
}
|
||||||
set_panic_handler();
|
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())
|
.map_err(|_| "Error creating player".into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +285,7 @@ impl Ruffle {
|
||||||
parent: HtmlElement,
|
parent: HtmlElement,
|
||||||
js_player: JavascriptPlayer,
|
js_player: JavascriptPlayer,
|
||||||
allow_script_access: bool,
|
allow_script_access: bool,
|
||||||
|
upgrade_to_https: bool,
|
||||||
) -> Result<Ruffle, Box<dyn Error>> {
|
) -> Result<Ruffle, Box<dyn Error>> {
|
||||||
let _ = console_log::init_with_level(log::Level::Trace);
|
let _ = console_log::init_with_level(log::Level::Trace);
|
||||||
|
|
||||||
|
@ -296,7 +298,7 @@ impl Ruffle {
|
||||||
.into_js_result()?;
|
.into_js_result()?;
|
||||||
|
|
||||||
let audio = Box::new(WebAudioBackend::new()?);
|
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 input = Box::new(WebInputBackend::new(&canvas));
|
||||||
let locale = Box::new(WebLocaleBackend::new());
|
let locale = Box::new(WebLocaleBackend::new());
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
//! Navigator backend for web
|
//! Navigator backend for web
|
||||||
|
|
||||||
use js_sys::{Array, ArrayBuffer, Uint8Array};
|
use js_sys::{Array, ArrayBuffer, Uint8Array};
|
||||||
use ruffle_core::backend::navigator::{
|
use ruffle_core::backend::navigator::{
|
||||||
url_from_relative_url, NavigationMethod, NavigatorBackend, OwnedFuture, RequestOptions,
|
url_from_relative_url, NavigationMethod, NavigatorBackend, OwnedFuture, RequestOptions,
|
||||||
|
@ -8,6 +7,7 @@ use ruffle_core::indexmap::IndexMap;
|
||||||
use ruffle_core::loader::Error;
|
use ruffle_core::loader::Error;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use url::Url;
|
||||||
use wasm_bindgen::JsCast;
|
use wasm_bindgen::JsCast;
|
||||||
use wasm_bindgen_futures::{spawn_local, JsFuture};
|
use wasm_bindgen_futures::{spawn_local, JsFuture};
|
||||||
use web_sys::{window, Blob, BlobPropertyBag, Performance, Request, RequestInit, Response};
|
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 {
|
pub struct WebNavigatorBackend {
|
||||||
performance: Performance,
|
performance: Performance,
|
||||||
start_time: f64,
|
start_time: f64,
|
||||||
|
upgrade_to_https: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebNavigatorBackend {
|
impl WebNavigatorBackend {
|
||||||
pub fn new() -> Self {
|
pub fn new(upgrade_to_https: bool) -> Self {
|
||||||
let window = web_sys::window().expect("window()");
|
let window = web_sys::window().expect("window()");
|
||||||
let performance = window.performance().expect("window.performance()");
|
let performance = window.performance().expect("window.performance()");
|
||||||
|
|
||||||
WebNavigatorBackend {
|
WebNavigatorBackend {
|
||||||
start_time: performance.now(),
|
start_time: performance.now(),
|
||||||
performance,
|
performance,
|
||||||
|
upgrade_to_https,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,6 +39,12 @@ impl NavigatorBackend for WebNavigatorBackend {
|
||||||
vars_method: Option<(NavigationMethod, IndexMap<String, String>)>,
|
vars_method: Option<(NavigationMethod, IndexMap<String, String>)>,
|
||||||
) {
|
) {
|
||||||
if let Some(window) = window() {
|
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?
|
//TODO: Should we return a result for failed opens? Does Flash care?
|
||||||
#[allow(unused_must_use)]
|
#[allow(unused_must_use)]
|
||||||
match (vars_method, window_spec) {
|
match (vars_method, window_spec) {
|
||||||
|
@ -95,7 +103,12 @@ impl NavigatorBackend for WebNavigatorBackend {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fetch(&self, url: &str, options: RequestOptions) -> OwnedFuture<Vec<u8>, Error> {
|
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 {
|
Box::pin(async move {
|
||||||
let mut init = RequestInit::new();
|
let mut init = RequestInit::new();
|
||||||
|
|
||||||
|
@ -172,4 +185,11 @@ impl NavigatorBackend for WebNavigatorBackend {
|
||||||
|
|
||||||
url.into()
|
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