0

[LNA] Add Local Network Access permission type

This adds a new PermissionType and ContentSettingsType for Local Network
Access (LNA) in preparation for adding a new permission prompt to
restrict this capability.

Followup CLs will add UI integrations and
permission prompts:
- crrev.com/c/6330700 (ContentSetting and PageInfo)
- crrev.com/c/6337340 (Permission request)

Bug: 400455013
Change-Id: Icc851197deb8162e8686fe13f035300dbcd5bf63
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6325710
Reviewed-by: Rainhard Findling <rainhard@chromium.org>
Commit-Queue: Chris Thompson <cthomp@chromium.org>
Reviewed-by: Camille Lamy <clamy@chromium.org>
Reviewed-by: Richard (Torne) Coles <torne@chromium.org>
Reviewed-by: Christian Dullweber <dullweber@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1431774}
This commit is contained in:
Chris Thompson
2025-03-12 14:59:57 -07:00
committed by Chromium LUCI CQ
parent 2e7502431b
commit a9d4580fce
22 changed files with 81 additions and 2 deletions
android_webview/browser
chrome
android
javatests
src
org
chromium
chrome
browser
components
browser_ui
site_settings
android
java
src
org
chromium
components
browser_ui
content_settings
permissions
content
headless/test/data/protocol/sanity
third_party/blink
common
public
common
devtools_protocol
mojom
permissions
renderer
tools/metrics/histograms

@ -416,6 +416,13 @@ void AwPermissionManager::RequestPermissions(
pending_request_raw->SetPermissionStatus(permissions[i],
PermissionStatus::DENIED);
break;
case PermissionType::LOCAL_NETWORK_ACCESS:
// PermissionType::LOCAL_NETWORK_ACCESS requests are always granted so
// that local network requests in WebView work as-is. WebView is
// currently out-of-scope for Local Network Access restrictions.
pending_request_raw->SetPermissionStatus(permissions[i],
PermissionStatus::GRANTED);
break;
case PermissionType::NUM:
NOTREACHED() << "PermissionType::NUM was not expected here.";
}
@ -557,6 +564,7 @@ PermissionStatus AwPermissionManager::GetPermissionStatusInternal(
case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE:
case blink::PermissionType::MIDI:
case blink::PermissionType::SENSORS:
case blink::PermissionType::LOCAL_NETWORK_ACCESS:
// These permissions are auto-granted by WebView.
return PermissionStatus::GRANTED;
@ -751,6 +759,7 @@ void AwPermissionManager::CancelPermissionRequest(int request_id) {
case PermissionType::SENSORS:
case PermissionType::WAKE_LOCK_SCREEN:
case PermissionType::WAKE_LOCK_SYSTEM:
case PermissionType::LOCAL_NETWORK_ACCESS:
// There is nothing to cancel so this is simply ignored.
break;
case PermissionType::NUM:

@ -268,6 +268,17 @@ TEST_F(AwPermissionManagerTest, ClipboardPermissionIsGrantedSynchronously) {
EXPECT_EQ(PermissionStatus::GRANTED, resolved_permission_status[0]);
}
TEST_F(AwPermissionManagerTest,
LocalNetworkAccessPermissionIsGrantedSynchronously) {
RequestPermissions(
{PermissionType::LOCAL_NETWORK_ACCESS}, render_frame_host,
GURL(kRequestingOrigin1), true,
base::BindOnce(&AwPermissionManagerTest::PermissionRequestResponse,
base::Unretained(this), 0));
ASSERT_EQ(1u, resolved_permission_status.size());
EXPECT_EQ(PermissionStatus::GRANTED, resolved_permission_status[0]);
}
// Test the case a delegate is called, and it resolves the permission
// synchronously.
TEST_F(AwPermissionManagerTest, SinglePermissionRequestIsGrantedSynchronously) {

@ -700,6 +700,13 @@ public class WebsitePermissionsFetcherTest {
SITE_WILDCARD,
/* isEmbargoed= */ false,
SessionModel.DURABLE));
websitePreferenceBridge.addPermissionInfo(
new PermissionInfo(
ContentSettingsType.LOCAL_NETWORK_ACCESS,
ORIGIN,
SITE_WILDCARD,
/* isEmbargoed= */ false,
SessionModel.DURABLE));
// Add content setting exception types.
// If the ContentSettingsType.MAX_VALUE value changes *and* a new value has been exposed on
@ -707,7 +714,7 @@ public class WebsitePermissionsFetcherTest {
// Otherwise, just update count in the assert.
// TODO(https://b/332704817): Add test for Tracking Protection content setting after Android
// integration.
assertEquals(118, ContentSettingsType.MAX_VALUE);
assertEquals(119, ContentSettingsType.MAX_VALUE);
websitePreferenceBridge.addContentSettingException(
new ContentSettingException(
ContentSettingsType.COOKIES,
@ -881,6 +888,8 @@ public class WebsitePermissionsFetcherTest {
Assert.assertNotNull(site.getPermissionInfo(ContentSettingsType.VR));
Assert.assertNotNull(site.getPermissionInfo(ContentSettingsType.HAND_TRACKING));
Assert.assertNotNull(site.getPermissionInfo(ContentSettingsType.AR));
Assert.assertNotNull(
site.getPermissionInfo(ContentSettingsType.LOCAL_NETWORK_ACCESS));
// Check content setting exception types.
assertEquals(

@ -197,6 +197,7 @@ TEST_F(ControlledFramePermissionsTest, Verify) {
ARE_SUSPICIOUS_NOTIFICATIONS_ALLOWLISTED_BY_USER:
case ContentSettingsType::CONTROLLED_FRAME:
case ContentSettingsType::REVOKED_DISRUPTIVE_NOTIFICATION_PERMISSIONS:
case ContentSettingsType::LOCAL_NETWORK_ACCESS:
break;
default:
@ -254,6 +255,7 @@ TEST_F(ControlledFramePermissionsTest, Verify) {
case blink::PermissionType::AUTOMATIC_FULLSCREEN:
case blink::PermissionType::HAND_TRACKING:
case blink::PermissionType::WEB_APP_INSTALLATION:
case blink::PermissionType::LOCAL_NETWORK_ACCESS:
break;
default:

@ -1035,6 +1035,8 @@ TEST_F(SafetyHubHandlerTest, RevokeAllContentSettingTypes) {
ContentSettingsType::CAMERA_PAN_TILT_ZOOM,
ContentSettingsType::FILE_SYSTEM_ACCESS_EXTENDED_PERMISSION,
ContentSettingsType::POINTER_LOCK,
// TODO(crbug.com/400455013): Remove once settings UI is added.
ContentSettingsType::LOCAL_NETWORK_ACCESS,
// clang-format on
});

@ -248,6 +248,8 @@ constexpr auto kContentSettingsTypeGroupNames = std::to_array<
// POINTER_LOCK has been deprecated.
{ContentSettingsType::POINTER_LOCK, nullptr},
{ContentSettingsType::REVOKED_DISRUPTIVE_NOTIFICATION_PERMISSIONS, nullptr},
// TODO(crbug.com/400455013): Implement UI for LNA permission.
{ContentSettingsType::LOCAL_NETWORK_ACCESS, nullptr},
});
static_assert(

@ -104,6 +104,7 @@ public class WebsitePermissionsFetcher {
case ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER:
case ContentSettingsType.SENSORS:
case ContentSettingsType.VR:
case ContentSettingsType.LOCAL_NETWORK_ACCESS:
return WebsitePermissionsType.PERMISSION_INFO;
case ContentSettingsType.STORAGE_ACCESS:
return WebsitePermissionsType.EMBEDDED_PERMISSION;

@ -860,6 +860,17 @@ void ContentSettingsRegistry::Init() {
WebsiteSettingsRegistry::PLATFORM_ANDROID,
ContentSettingsInfo::INHERIT_IN_INCOGNITO,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
Register(ContentSettingsType::LOCAL_NETWORK_ACCESS, "local-network-access",
CONTENT_SETTING_ASK, WebsiteSettingsInfo::UNSYNCABLE,
/*allowlisted_primary_schemes=*/{},
/*valid_settings=*/
{CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK},
WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE,
WebsiteSettingsRegistry::DESKTOP |
WebsiteSettingsRegistry::PLATFORM_ANDROID,
ContentSettingsInfo::INHERIT_IF_LESS_PERMISSIVE,
ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
}
void ContentSettingsRegistry::Register(

@ -154,6 +154,7 @@ constexpr auto kHistogramValue = base::MakeFixedFlatMap<ContentSettingsType,
132},
{ContentSettingsType::CONTROLLED_FRAME, 133},
{ContentSettingsType::REVOKED_DISRUPTIVE_NOTIFICATION_PERMISSIONS, 134},
{ContentSettingsType::LOCAL_NETWORK_ACCESS, 135},
// As mentioned at the top, please don't forget to update ContentType in
// enums.xml when you add entries here!

@ -479,5 +479,9 @@ enum ContentSettingsType {
// Website setting which is used for UnusedSitePermissionsService to
// store revoked notification permissions of disruptive sites.
REVOKED_DISRUPTIVE_NOTIFICATION_PERMISSIONS,
// Content setting for whether the site is allowed to make local network
// requests.
LOCAL_NETWORK_ACCESS,
};
// LINT.ThenChange(//components/content_settings/core/browser/content_settings_uma_util.cc:kHistogramValue)

@ -212,6 +212,9 @@ bool PermissionUtil::GetPermissionType(ContentSettingsType type,
case ContentSettingsType::WEB_APP_INSTALLATION:
*out = PermissionType::WEB_APP_INSTALLATION;
break;
case ContentSettingsType::LOCAL_NETWORK_ACCESS:
*out = PermissionType::LOCAL_NETWORK_ACCESS;
break;
default:
return false;
}
@ -384,6 +387,8 @@ ContentSettingsType PermissionUtil::PermissionTypeToContentSettingsTypeSafe(
return ContentSettingsType::AUTOMATIC_FULLSCREEN;
case PermissionType::WEB_APP_INSTALLATION:
return ContentSettingsType::WEB_APP_INSTALLATION;
case PermissionType::LOCAL_NETWORK_ACCESS:
return ContentSettingsType::LOCAL_NETWORK_ACCESS;
case PermissionType::NUM:
break;
}

@ -207,6 +207,8 @@ Response PermissionDescriptorToPermissionType(
*permission_type = PermissionType::AUTOMATIC_FULLSCREEN;
} else if (name == "web-app-installation") {
*permission_type = PermissionType::WEB_APP_INSTALLATION;
} else if (name == "local-network-access") {
*permission_type = PermissionType::LOCAL_NETWORK_ACCESS;
} else {
return Response::InvalidParams("Invalid PermissionDescriptor name: " +
name);
@ -300,6 +302,9 @@ Response FromProtocolPermissionType(
} else if (type ==
protocol::Browser::PermissionTypeEnum::WebAppInstallation) {
*out_type = PermissionType::WEB_APP_INSTALLATION;
} else if (type ==
protocol::Browser::PermissionTypeEnum::LocalNetworkAccess) {
*out_type = PermissionType::LOCAL_NETWORK_ACCESS;
} else {
return Response::InvalidParams("Unknown permission type: " + type);
}

@ -86,6 +86,7 @@ PermissionToSchedulingFeature(PermissionType permission_name) {
case PermissionType::POINTER_LOCK:
case PermissionType::AUTOMATIC_FULLSCREEN:
case PermissionType::WEB_APP_INSTALLATION:
case PermissionType::LOCAL_NETWORK_ACCESS:
return std::nullopt;
}
}

@ -76,6 +76,7 @@ bool IsAllowlistedPermissionType(PermissionType permission) {
case PermissionType::POINTER_LOCK:
case PermissionType::AUTOMATIC_FULLSCREEN:
case PermissionType::WEB_APP_INSTALLATION:
case PermissionType::LOCAL_NETWORK_ACCESS:
return false;
}

@ -34,4 +34,5 @@ Granted 'keyboardLock'
Granted 'pointerLock'
Granted 'automaticFullscreen'
Granted 'handTracking'
Granted 'webAppInstallation'
Granted 'webAppInstallation'
Granted 'localNetworkAccess'

@ -99,6 +99,8 @@ std::string GetPermissionString(PermissionType permission) {
return "AutomaticFullscreen";
case PermissionType::WEB_APP_INSTALLATION:
return "WebAppInstallation";
case PermissionType::LOCAL_NETWORK_ACCESS:
return "LocalNetworkAccess";
case PermissionType::NUM:
NOTREACHED();
}
@ -171,6 +173,8 @@ PermissionTypeToPermissionsPolicyFeature(PermissionType permission) {
case PermissionType::NOTIFICATIONS:
case PermissionType::KEYBOARD_LOCK:
case PermissionType::POINTER_LOCK:
// TODO(crbug.com/394009026): Add permission policy for LNA.
case PermissionType::LOCAL_NETWORK_ACCESS:
return std::nullopt;
case PermissionType::NUM:
@ -307,6 +311,8 @@ std::optional<PermissionType> PermissionDescriptorInfoToPermissionType(
return std::nullopt;
case PermissionName::WEB_APP_INSTALLATION:
return PermissionType::WEB_APP_INSTALLATION;
case PermissionName::LOCAL_NETWORK_ACCESS:
return PermissionType::LOCAL_NETWORK_ACCESS;
default:
NOTREACHED();
}

@ -64,6 +64,7 @@ enum class PermissionType {
AUTOMATIC_FULLSCREEN = 40,
HAND_TRACKING = 41,
WEB_APP_INSTALLATION = 42,
LOCAL_NETWORK_ACCESS = 43,
// Always keep this at the end.
NUM,

@ -1481,6 +1481,7 @@ domain Browser
idleDetection
keyboardLock
localFonts
localNetworkAccess
midi
midiSysex
nfc

@ -38,6 +38,7 @@ enum PermissionName {
POINTER_LOCK,
FULLSCREEN,
WEB_APP_INSTALLATION,
LOCAL_NETWORK_ACCESS,
};
struct MidiPermissionDescriptor {

@ -42,6 +42,7 @@ enum PermissionName {
"pointer-lock",
"fullscreen",
"web-app-installation",
"local-network-access",
};
// The PermissionDescriptor dictionary is a base to describe permissions. Some

@ -133,6 +133,8 @@ String PermissionNameToString(PermissionName name) {
return "fullscreen";
case PermissionName::WEB_APP_INSTALLATION:
return "web-app-installation";
case PermissionName::LOCAL_NETWORK_ACCESS:
return "local-network-access";
}
}

@ -2693,6 +2693,7 @@ Called by update_net_error_codes.py.-->
<int value="132" label="Are suspicious notifications allowlisted by user"/>
<int value="133" label="Controlled Frame"/>
<int value="134" label="Revoked disruptive notification permissions"/>
<int value="135" label="Local network access"/>
</enum>
<!-- LINT.ThenChange(//components/content_settings/core/browser/content_settings_uma_util.cc:kHistogramValue) -->
@ -21586,6 +21587,7 @@ Called by update_net_error_codes.py.-->
<int value="32" label="PERMISSION_FILE_HANDLING__REMOVED_IN_M98"/>
<int value="33" label="PERMISSION_TOP_LEVEL_STORAGE_ACCESS"/>
<int value="34" label="PERMISSION_WEB_APP_INSTALLATION"/>
<int value="35" label="PERMISSION_LOCAL_NETWORK_ACCESS"/>
</enum>
<enum name="PIIType">