1919#include < LibURL/Parser.h>
2020#include < LibWeb/CSS/SystemColor.h>
2121#include < LibWeb/Crypto/Crypto.h>
22+ #include < LibWeb/Geolocation/GeolocationPositionError.h>
2223#include < LibWeb/Infra/Strings.h>
2324#include < LibWeb/WebDriver/Error.h>
2425#include < LibWebView/Application.h>
@@ -85,6 +86,10 @@ ViewImplementation::ViewImplementation(IsPrivate is_private)
8586
8687ViewImplementation::~ViewImplementation ()
8788{
89+ for (auto const & watch : m_geolocation_watch_ids)
90+ Application::the ().stop_watching_geolocation_position (watch.value );
91+ m_geolocation_watch_ids.clear ();
92+
8893 all_views ().remove (m_view_id);
8994
9095 if (m_client_state.client )
@@ -1475,6 +1480,88 @@ void ViewImplementation::initialize_client(CreateNewClient create_new_client)
14751480 browsing_behavior_changed ();
14761481 autoplay_settings_changed ();
14771482 global_privacy_control_changed ();
1483+ geolocation_settings_changed ();
1484+
1485+ auto make_geolocation_success_handler = [this ](u64 request_id) {
1486+ auto weak_this = make_weak_ptr ();
1487+ auto request_page_id = page_id ();
1488+ auto request_client_handle = m_client_state.client_handle ;
1489+
1490+ return [weak_this, request_page_id, request_client_handle, request_id](Core::GeolocationCoordinates coords) {
1491+ auto * view = weak_this.ptr ();
1492+ if (!view || !view->m_client_state .client || view->m_client_state .page_index != request_page_id || view->m_client_state .client_handle != request_client_handle)
1493+ return ;
1494+
1495+ view->client ().async_geolocation_position_response (request_page_id, request_id,
1496+ coords.latitude , coords.longitude , coords.accuracy ,
1497+ coords.altitude , coords.altitude_accuracy ,
1498+ coords.heading , coords.speed , {});
1499+ };
1500+ };
1501+
1502+ auto make_geolocation_error_handler = [this ](u64 request_id, bool is_watch) {
1503+ using ErrorCode = Web::Geolocation::GeolocationPositionError::ErrorCode;
1504+
1505+ auto weak_this = make_weak_ptr ();
1506+ auto request_page_id = page_id ();
1507+ auto request_client_handle = m_client_state.client_handle ;
1508+
1509+ return [weak_this, request_page_id, request_client_handle, request_id, is_watch](Core::GeolocationError error) {
1510+ auto * view = weak_this.ptr ();
1511+ if (!view || !view->m_client_state .client || view->m_client_state .page_index != request_page_id || view->m_client_state .client_handle != request_client_handle)
1512+ return ;
1513+
1514+ ErrorCode code;
1515+ switch (error.type ) {
1516+ case Core::GeolocationError::Type::PermissionDenied:
1517+ code = ErrorCode::PermissionDenied;
1518+ break ;
1519+ case Core::GeolocationError::Type::Timeout:
1520+ code = ErrorCode::Timeout;
1521+ break ;
1522+ case Core::GeolocationError::Type::PositionUnavailable:
1523+ code = ErrorCode::PositionUnavailable;
1524+ break ;
1525+ }
1526+
1527+ if (is_watch && code == ErrorCode::PermissionDenied) {
1528+ auto provider_watch_id = view->m_geolocation_watch_ids .take (request_id);
1529+ if (provider_watch_id.has_value ())
1530+ Application::the ().stop_watching_geolocation_position (*provider_watch_id);
1531+ }
1532+
1533+ view->client ().async_geolocation_position_response (request_page_id, request_id,
1534+ {}, {}, {}, {}, {}, {}, {},
1535+ to_underlying (code));
1536+ };
1537+ };
1538+
1539+ on_request_geolocation_position = [make_geolocation_success_handler, make_geolocation_error_handler](u64 request_id) {
1540+ Application::the ().request_geolocation_position (
1541+ make_geolocation_success_handler (request_id),
1542+ make_geolocation_error_handler (request_id, false ));
1543+ };
1544+
1545+ on_start_geolocation_position_watch = [this , make_geolocation_success_handler, make_geolocation_error_handler](u64 request_id) {
1546+ auto provider_watch_id = Application::the ().start_watching_geolocation_position (
1547+ make_geolocation_success_handler (request_id),
1548+ make_geolocation_error_handler (request_id, true ));
1549+
1550+ if (provider_watch_id.is_error ()) {
1551+ make_geolocation_error_handler (request_id, true )(provider_watch_id.release_error ());
1552+ return ;
1553+ }
1554+
1555+ m_geolocation_watch_ids.set (request_id, provider_watch_id.release_value ());
1556+ };
1557+
1558+ on_stop_geolocation_position_watch = [this ](u64 request_id) {
1559+ auto provider_watch_id = m_geolocation_watch_ids.take (request_id);
1560+ if (!provider_watch_id.has_value ())
1561+ return ;
1562+
1563+ Application::the ().stop_watching_geolocation_position (*provider_watch_id);
1564+ };
14781565
14791566 // If DevTools is connected, notify the new WebContent process.
14801567 if (m_devtools_connected)
@@ -2115,7 +2202,25 @@ void ViewImplementation::geolocation_settings_changed()
21152202{
21162203 using ErrorCode = Web::Geolocation::GeolocationPositionError::ErrorCode;
21172204
2205+ auto stop_native_position_watches = [this ](Optional<ErrorCode> error_code) {
2206+ auto geolocation_watch_ids = move (m_geolocation_watch_ids);
2207+ m_geolocation_watch_ids.clear ();
2208+
2209+ for (auto const & watch : geolocation_watch_ids) {
2210+ Application::the ().stop_watching_geolocation_position (watch.value );
2211+
2212+ if (error_code.has_value ()) {
2213+ client ().async_geolocation_position_response (page_id (), watch.key ,
2214+ {}, {}, {}, {}, {}, {}, {},
2215+ to_underlying (*error_code));
2216+ } else {
2217+ client ().async_cancel_geolocation_position_request (page_id (), watch.key );
2218+ }
2219+ }
2220+ };
2221+
21182222 if (Application::web_content_options ().is_test_mode == IsTestMode::Yes) {
2223+ stop_native_position_watches ({});
21192224 client ().async_set_geolocation_emulated_position (page_id (), 37.7647658 , -122.4345892 , 100.0 , 0.0 , 0.0 , 0.0 , 0.0 , {});
21202225 return ;
21212226 }
@@ -2124,9 +2229,11 @@ void ViewImplementation::geolocation_settings_changed()
21242229
21252230 switch (settings.geolocation_mode ()) {
21262231 case GeolocationMode::Disabled:
2232+ stop_native_position_watches (ErrorCode::PermissionDenied);
21272233 client ().async_set_geolocation_emulated_position (page_id (), {}, {}, {}, {}, {}, {}, {}, to_underlying (ErrorCode::PermissionDenied));
21282234 break ;
21292235 case GeolocationMode::Emulated: {
2236+ stop_native_position_watches ({});
21302237 auto const & coords = settings.emulated_geolocation_coordinates ();
21312238 client ().async_set_geolocation_emulated_position (page_id (), coords.latitude , coords.longitude , coords.accuracy , coords.altitude , coords.altitude_accuracy , coords.heading , coords.speed , {});
21322239 break ;
0 commit comments