Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 386b21db7bdc2fc5135138027639ef8bf8a0402b
      
https://github.com/WebKit/WebKit/commit/386b21db7bdc2fc5135138027639ef8bf8a0402b
  Author: Rupin Mittal <[email protected]>
  Date:   2025-05-21 (Wed, 21 May 2025)

  Changed paths:
    M Source/WebCore/Modules/geolocation/Geolocation.cpp
    M Source/WebCore/Modules/geolocation/Geolocation.h
    M Source/WebCore/Modules/geolocation/NavigatorGeolocation.cpp
    M Source/WebCore/Modules/geolocation/NavigatorGeolocation.h
    M Source/WebCore/Modules/permissions/Permissions.cpp
    M Source/WebCore/Modules/permissions/Permissions.h
    M Source/WebKit/UIProcess/WebPageProxy.cpp
    M Tools/TestWebKitAPI/Tests/WebKitCocoa/PermissionsAPI.mm

  Log Message:
  -----------
  [Permissions API] Report the true permission state of Geolocation only when 
that API has been used since the page load
https://bugs.webkit.org/show_bug.cgi?id=293089
rdar://151426960

Reviewed by Youenn Fablet.

The current behavior of the Permissions API is:
- Return PROMPT in all cases where the permission state of the Geolocation API 
is DENIED.
- Return GRANTED in all cases where the permission state of the Geolocation API 
is GRANTED.

This PR changes WebKit's Permissions API to behave like so:
(On both MacOS and iOS).

User action                                   || Client tells WebKit || WebKit 
tells website    ||
----------------------------------------------||---------------------||-------------------------||
User says GRANTED to prompt once              || PROMPT              || GRANTED 
                || geolocation requested by page since page load
                                              || PROMPT              || PROMPT  
                || not requested since page load
User says GRANTED to prompt twice (24h grant) || PROMPT              || GRANTED 
                || geolocation requested by page since page load
                                              || PROMPT              || PROMPT  
                || not requested since page load
User says DENIED to prompt once               || PROMPT              || DENIED  
                || geolocation requested by page since page load
                                              || PROMPT              || PROMPT  
                || not requested since page load
User says DENIED to prompt twice (24h grant)  || PROMPT              || DENIED  
                || geolocation requested by page since page load
                                              || PROMPT              || PROMPT  
                || not requested since page load
User says GRANTED in permanent settings       || GRANTED             || GRANTED 
                ||
User says DENIED in permanent settings        || DENIED              || DENIED  
                || geolocation requested by page since page load
                                              || DENIED              || PROMPT 
(fingerprinting) || not requested since page load

The "Client tells WebKit" column represents how the client's implementation of 
the queryPermission
delegate behaves. Given this behavior, this PR makes changes so that the 
Permissions API behaves
like the "WebKit tells website" column.

WebKit's position is that the geolocation permission state should only be 
revealed to a site if
that site is willing to show a prompt asking for permission to use that API.

Prompts for geolocation are shown when one of the functions of the Geolocation 
API are called
(for example navigator.geolocation.getCurrentPosition). So the Permissions API 
should only reveal
the true permission state of the Geolocation API if such a function has been 
called since the page
load. If you reload the page, WebKit forgets that you've tried to use the API.

The only exception to this rule is that if a user has permanently GRANTED--the 
user is indicating
that they trust this site, so the Permissions API will return the true state 
regardless of if the
site has attempted to get the geolocation. It's important to note that these 
settings (both permanent
and for a prompt) are per-site settings.

We don't make this exception in the case of permanently DENIED--as 
fingerprinting countermeasure,
we still return PROMPT in the case where Geolocation hasn't been requested.

Implementation details:

Navigator has a Geolocation object. On this object, we add a property 
(m_hasBeenRequested) which
gets set any time permission to get geolocation is requested. The Geolocation 
object is reset
every page load and so is this property.

When Permissions::query is called, it gets the permission state from the 
client. For geolocation,
clients return GRANTED or DENIED only in the cases where the user has granted 
or denied *permanently*.
If no permanent setting has been set, and user has simply granted or denied via 
a prompt, clients
return PROMPT. But if the user grants or denies via a prompt, the 
m_allowGeolocation property gets
set on the Geolocation object.

This means that Permissions::queryPermission can see that:
- If the result returned by client is GRANTED or DENIED --> that's a permanent 
setting
- If the result returned by client is PROMPT and Geolocation has been requested 
--> the user has
  responded to the prompt and their answer is contained in 
Geolocation::isAllowed()

The behavior in the table is tested by new API tests. These tests work on both 
MacOS and iOS.

* Source/WebCore/Modules/geolocation/Geolocation.cpp:
(WebCore::Geolocation::requestPermission):
(WebCore::Geolocation::resetIsAllowed):
* Source/WebCore/Modules/geolocation/Geolocation.h:

We add the new property m_hasBeenRequested here with a function to access it.

To access Geolocation's m_hasBeenRequested property, the Permissions API
code first gets the Geolocation from the NavigatorGeolocation. This is
supplement to the WebPage. Service workers don't have a WebPage and thus
don't have a NavigationGeolocation object. So we want to make sure
we don't try to createa Geolocation object in this case because attempting
to delete it later will result in a crash (we delete it by accessing it
from the supplement first--which doesn't exist in the worker case).

* Source/WebCore/Modules/permissions/Permissions.cpp:
(WebCore::Permissions::query):
(WebCore::Permissions::determineGeolocationPermissionState):

This function decides if the permission state is a permanent one, or a temporary
user-response to a prompt. It contains the logic to change GRANTED and DENIED to
PROMPT in cases where the Geolocation API hasn't been used since the page load.
(The main logic of the above table is implemented here).

* Source/WebCore/Modules/permissions/Permissions.h:
* Source/WebKit/UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::queryPermission):
* Tools/TestWebKitAPI/Tests/WebKitCocoa/PermissionsAPI.mm:
(-[PermissionsAPIUIDelegate 
_webView:queryPermission:forOrigin:completionHandler:]):
(-[PermissionsAPIAndGeolocationRequestUIDelegate 
_webView:requestGeolocationPermissionForFrame:decisionHandler:]):
(TestWebKitAPI::TEST(PermissionsAPI, DataURL)):
(TestWebKitAPI::TEST(PermissionsAPI, OnChange)):
(TestWebKitAPI::testPermissionsAPIForGeolocation):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolocationPermissionGrantedFromPromptAndGeolcationRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolocationPermissionGrantedFromPromptAndGeolocationNotRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolcolationPermissionDeniedFromPromptAndGeolocationRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolcolationPermissionDeniedFromPromptAndGeolocationNotRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolcolationPermissionGrantedPermanentlyAndGeolocationRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolcolationPermissionGrantedPermanentlyAndGeolocationNotRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolcolationPermissionDeniedPermanentlyAndGeolocationRequestedSinceLoad)):
(TestWebKitAPI::TEST(PermissionsAPI, 
GeolcolationPermissionDeniedPermanentlyAndGeolocationNotRequestedSinceLoad)):

Canonical link: https://commits.webkit.org/295237@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to