do not rely on UWP URL parser

This commit is contained in:
Paul Rouget 2019-11-06 07:38:19 +01:00
parent 147c042c5a
commit 1c3da95b70
7 changed files with 67 additions and 35 deletions

View file

@ -152,6 +152,12 @@ pub fn servo_version() -> String {
servo::config::servo_version() servo::config::servo_version()
} }
/// Test if a url is valid.
pub fn is_uri_valid(url: &str) -> bool {
info!("load_uri: {}", url);
ServoUrl::parse(url).is_ok()
}
/// Initialize Servo. At that point, we need a valid GL context. /// Initialize Servo. At that point, we need a valid GL context.
/// In the future, this will be done in multiple steps. /// In the future, this will be done in multiple steps.
pub fn init( pub fn init(

View file

@ -186,16 +186,17 @@ fn do_redirect_stdout_stderr() -> Result<(), ()> {
Ok(()) Ok(())
} }
fn call<F>(f: F) fn call<T, F>(f: F) -> T
where where
F: Fn(&mut ServoGlue) -> Result<(), &'static str>, F: Fn(&mut ServoGlue) -> Result<T, &'static str>,
{ {
if let Err(e) = SERVO.with(|s| match s.borrow_mut().as_mut() { match SERVO.with(|s| match s.borrow_mut().as_mut() {
Some(ref mut s) => (f)(s), Some(ref mut s) => (f)(s),
None => Err("Servo not available in this thread"), None => Err("Servo not available in this thread"),
}) { }) {
panic!(e); Err(e) => panic!(e),
}; Ok(r) => r,
}
} }
/// Callback used by Servo internals /// Callback used by Servo internals
@ -430,13 +431,23 @@ pub extern "C" fn perform_updates() {
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn load_uri(url: *const c_char) { pub extern "C" fn is_uri_valid(url: *const c_char) -> bool {
catch_any_panic(|| {
debug!("is_uri_valid");
let url = unsafe { CStr::from_ptr(url) };
let url = url.to_str().expect("Can't read string");
simpleservo::is_uri_valid(url)
})
}
#[no_mangle]
pub extern "C" fn load_uri(url: *const c_char) -> bool {
catch_any_panic(|| { catch_any_panic(|| {
debug!("load_url"); debug!("load_url");
let url = unsafe { CStr::from_ptr(url) }; let url = unsafe { CStr::from_ptr(url) };
let url = url.to_str().expect("Can't read string"); let url = url.to_str().expect("Can't read string");
call(|s| s.load_uri(url)); call(|s| Ok(s.load_uri(url).is_ok()))
}); })
} }
#[no_mangle] #[no_mangle]

View file

@ -116,7 +116,7 @@ void BrowserPage::OnURLEdited(IInspectable const &,
servoControl().Focus(FocusState::Programmatic); servoControl().Focus(FocusState::Programmatic);
auto input = urlTextbox().Text(); auto input = urlTextbox().Text();
auto uri = servoControl().LoadURIOrSearch(input); auto uri = servoControl().LoadURIOrSearch(input);
urlTextbox().Text(uri.ToString()); urlTextbox().Text(uri);
} }
} }

View file

@ -66,7 +66,10 @@ public:
void Reload() { capi::reload(); } void Reload() { capi::reload(); }
void Stop() { capi::stop(); } void Stop() { capi::stop(); }
void LoadUri(hstring uri) { capi::load_uri(*hstring2char(uri)); } bool LoadUri(hstring uri) { return capi::load_uri(*hstring2char(uri)); }
bool IsUriValid(hstring uri) {
return capi::is_uri_valid(*hstring2char(uri));
}
void Scroll(float dx, float dy, float x, float y) { void Scroll(float dx, float dy, float x, float y) {
capi::scroll((int32_t)dx, (int32_t)dy, (int32_t)x, (int32_t)y); capi::scroll((int32_t)dx, (int32_t)dy, (int32_t)x, (int32_t)y);
} }

View file

@ -195,25 +195,43 @@ void ServoControl::Reload() {
void ServoControl::Stop() { void ServoControl::Stop() {
RunOnGLThread([=] { mServo->Stop(); }); RunOnGLThread([=] { mServo->Stop(); });
} }
Uri ServoControl::LoadURIOrSearch(hstring input) { hstring ServoControl::LoadURIOrSearch(hstring input) {
auto uri = TryParseURI(input); // Initial input is valid
if (uri == std::nullopt) { if (mServo->IsUriValid(input)) {
TryLoadUri(input);
return input;
}
// Not valid. Maybe it's just missing the scheme.
hstring with_scheme = L"https://" + input;
// If the user only types "mozilla" we don't want to go to
// https://mozilla even though it's a valid url.
bool has_dot = wcsstr(input.c_str(), L".") != nullptr; bool has_dot = wcsstr(input.c_str(), L".") != nullptr;
hstring input2 = L"https://" + input; if (mServo->IsUriValid(with_scheme) && has_dot) {
uri = TryParseURI(input2); TryLoadUri(with_scheme);
if (uri == std::nullopt || !has_dot) { return with_scheme;
hstring input3 = }
// Doesn't look like a URI. Let's search for the string.
hstring searchUri =
L"https://duckduckgo.com/html/?q=" + Uri::EscapeComponent(input); L"https://duckduckgo.com/html/?q=" + Uri::EscapeComponent(input);
uri = TryParseURI(input3); TryLoadUri(searchUri);
} return searchUri;
} }
auto finalUri = uri.value();
void ServoControl::TryLoadUri(hstring input) {
if (!mLooping) { if (!mLooping) {
mInitialURL = finalUri.ToString(); mInitialURL = input;
} else { } else {
RunOnGLThread([=] { mServo->LoadUri(finalUri.ToString()); }); RunOnGLThread([=] {
if (!mServo->LoadUri(input)) {
RunOnUIThread([=] {
Windows::UI::Popups::MessageDialog msg{L"URI not valid"};
msg.ShowAsync();
});
}
});
} }
return finalUri;
} }
void ServoControl::RunOnGLThread(std::function<void()> task) { void ServoControl::RunOnGLThread(std::function<void()> task) {

View file

@ -14,7 +14,7 @@ struct ServoControl : ServoControlT<ServoControl>, public servo::ServoDelegate {
void Reload(); void Reload();
void Stop(); void Stop();
void Shutdown(); void Shutdown();
Windows::Foundation::Uri LoadURIOrSearch(hstring); hstring LoadURIOrSearch(hstring);
void OnLoaded(IInspectable const &, void OnLoaded(IInspectable const &,
Windows::UI::Xaml::RoutedEventArgs const &); Windows::UI::Xaml::RoutedEventArgs const &);
@ -110,14 +110,6 @@ private:
void StopRenderLoop(); void StopRenderLoop();
void Loop(); void Loop();
std::optional<Windows::Foundation::Uri> TryParseURI(hstring input) {
try {
return Windows::Foundation::Uri(input);
} catch (hresult_invalid_argument const &) {
return {};
}
}
void OnSurfaceTapped(IInspectable const &, void OnSurfaceTapped(IInspectable const &,
Windows::UI::Xaml::Input::TappedRoutedEventArgs const &); Windows::UI::Xaml::Input::TappedRoutedEventArgs const &);
@ -147,6 +139,8 @@ private:
template <typename Callable> void RunOnUIThread(Callable); template <typename Callable> void RunOnUIThread(Callable);
void RunOnGLThread(std::function<void()>); void RunOnGLThread(std::function<void()>);
void TryLoadUri(hstring);
std::unique_ptr<servo::Servo> mServo; std::unique_ptr<servo::Servo> mServo;
EGLSurface mRenderSurface{EGL_NO_SURFACE}; EGLSurface mRenderSurface{EGL_NO_SURFACE};
OpenGLES mOpenGLES; OpenGLES mOpenGLES;

View file

@ -9,7 +9,7 @@ namespace ServoApp {
void GoForward(); void GoForward();
void Reload(); void Reload();
void Stop(); void Stop();
Windows.Foundation.Uri LoadURIOrSearch(String url); String LoadURIOrSearch(String url);
void SetTransientMode(Boolean transient); void SetTransientMode(Boolean transient);
void SetArgs(String args); void SetArgs(String args);
void Shutdown(); void Shutdown();