Commit bd4024da authored by Luis G Garcia's avatar Luis G Garcia Committed by Commit Bot

Add support for grouped AR/Camera permissions.

Enable grouping of the AR and Camera permission types in order to
present both permissions within a single prompt to the user. This prompt
will be displayed when a session is requested with camera access as a
requested feature.

UX Design Doc: https://docs.google.com/document/d/19iYmlZeyEIYwZFurDbYvwT0WEc1MfJ4TKS9V_JA2fF8/edit#heading=h.kffoh0tkafi0

Fixed: 1105590
Bug: 1106874
Change-Id: Ie6c1985f1dd717d3df88d0a856174ec1bdbc3b99
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2303376
Commit-Queue: Luis Garcia <luisggarcia@google.com>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarPiotr Bialecki <bialpio@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Reviewed-by: default avatarKlaus Weidner <klausw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790518}
parent 5030243c
...@@ -88,12 +88,11 @@ ContentSettingsType PermissionPromptAndroid::GetContentSettingType( ...@@ -88,12 +88,11 @@ ContentSettingsType PermissionPromptAndroid::GetContentSettingType(
return requests[position]->GetContentSettingsType(); return requests[position]->GetContentSettingsType();
} }
// Grouped permission requests can only be Mic+Camera or Camera+Mic static bool IsValidMediaRequestGroup(
static void CheckValidRequestGroup(
const std::vector<permissions::PermissionRequest*>& requests) { const std::vector<permissions::PermissionRequest*>& requests) {
DCHECK_EQ(static_cast<size_t>(2), requests.size()); if (requests.size() < 2)
DCHECK_EQ(requests[0]->GetOrigin(), requests[1]->GetOrigin()); return false;
DCHECK( return (
(requests[0]->GetPermissionRequestType() == (requests[0]->GetPermissionRequestType() ==
permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC && permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC &&
requests[1]->GetPermissionRequestType() == requests[1]->GetPermissionRequestType() ==
...@@ -104,6 +103,31 @@ static void CheckValidRequestGroup( ...@@ -104,6 +103,31 @@ static void CheckValidRequestGroup(
permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC)); permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC));
} }
static bool IsValidARCameraAccessRequestGroup(
const std::vector<permissions::PermissionRequest*>& requests) {
if (requests.size() < 2)
return false;
return (
(requests[0]->GetPermissionRequestType() ==
permissions::PermissionRequestType::PERMISSION_AR &&
requests[1]->GetPermissionRequestType() ==
permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA) ||
(requests[0]->GetPermissionRequestType() ==
permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA &&
requests[1]->GetPermissionRequestType() ==
permissions::PermissionRequestType::PERMISSION_AR));
}
// Grouped permission requests can only be Mic+Camera, Camera+Mic,
// AR + Camera, or Camera + AR.
static void CheckValidRequestGroup(
const std::vector<permissions::PermissionRequest*>& requests) {
DCHECK_EQ(static_cast<size_t>(2u), requests.size());
DCHECK_EQ(requests[0]->GetOrigin(), requests[1]->GetOrigin());
DCHECK((IsValidMediaRequestGroup(requests)) ||
(IsValidARCameraAccessRequestGroup(requests)));
}
int PermissionPromptAndroid::GetIconId() const { int PermissionPromptAndroid::GetIconId() const {
const std::vector<permissions::PermissionRequest*>& requests = const std::vector<permissions::PermissionRequest*>& requests =
delegate_->Requests(); delegate_->Requests();
...@@ -119,11 +143,19 @@ base::string16 PermissionPromptAndroid::GetMessageText() const { ...@@ -119,11 +143,19 @@ base::string16 PermissionPromptAndroid::GetMessageText() const {
if (requests.size() == 1) if (requests.size() == 1)
return requests[0]->GetMessageText(); return requests[0]->GetMessageText();
CheckValidRequestGroup(requests); CheckValidRequestGroup(requests);
return l10n_util::GetStringFUTF16( if (IsValidARCameraAccessRequestGroup(requests)) {
IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_INFOBAR_TEXT, return l10n_util::GetStringFUTF16(
url_formatter::FormatUrlForSecurityDisplay( IDS_AR_AND_MEDIA_CAPTURE_VIDEO_INFOBAR_TEXT,
requests[0]->GetOrigin(), url_formatter::FormatUrlForSecurityDisplay(
url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); requests[0]->GetOrigin(),
url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
} else {
return l10n_util::GetStringFUTF16(
IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_INFOBAR_TEXT,
url_formatter::FormatUrlForSecurityDisplay(
requests[0]->GetOrigin(),
url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
}
} }
void PermissionPromptAndroid::OnInfoBarRemoved(infobars::InfoBar* infobar, void PermissionPromptAndroid::OnInfoBarRemoved(infobars::InfoBar* infobar,
......
...@@ -79,14 +79,28 @@ bool isMediaRequest(PermissionRequestType type) { ...@@ -79,14 +79,28 @@ bool isMediaRequest(PermissionRequestType type) {
type == PermissionRequestType::PERMISSION_CAMERA_PAN_TILT_ZOOM; type == PermissionRequestType::PERMISSION_CAMERA_PAN_TILT_ZOOM;
} }
// We only group together media requests. We don't display grouped requests for bool isArOrCameraRequest(PermissionRequestType type) {
// any other permissions at present. return type == PermissionRequestType::PERMISSION_AR ||
type == PermissionRequestType::PERMISSION_MEDIASTREAM_CAMERA;
}
bool ShouldGroupRequests(PermissionRequest* a, PermissionRequest* b) { bool ShouldGroupRequests(PermissionRequest* a, PermissionRequest* b) {
if (a->GetOrigin() != b->GetOrigin()) if (a->GetOrigin() != b->GetOrigin())
return false; return false;
return isMediaRequest(a->GetPermissionRequestType()) && // Group if both requests are media requests.
isMediaRequest(b->GetPermissionRequestType()); if (isMediaRequest(a->GetPermissionRequestType()) &&
isMediaRequest(b->GetPermissionRequestType())) {
return true;
}
// Group if the requests are an AR and a Camera Access request.
if (isArOrCameraRequest(a->GetPermissionRequestType()) &&
isArOrCameraRequest(b->GetPermissionRequestType())) {
return true;
}
return false;
} }
} // namespace } // namespace
......
...@@ -24,6 +24,12 @@ ...@@ -24,6 +24,12 @@
<message name="IDS_AR_INFOBAR_TEXT" desc="Text requesting permission for a site to use AR"> <message name="IDS_AR_INFOBAR_TEXT" desc="Text requesting permission for a site to use AR">
<ph name="URL">$1<ex>google.com</ex></ph> wants to create a 3D map of your surroundings and track camera position <ph name="URL">$1<ex>google.com</ex></ph> wants to create a 3D map of your surroundings and track camera position
</message> </message>
<!-- TODO(https://bugs.chromium.org/p/chromium/issues/detail?id=1106874) -->
<message name="IDS_AR_AND_MEDIA_CAPTURE_VIDEO_INFOBAR_TEXT" desc="Text requesting permission for a site to use AR and the Camera Access Feature">
<ph name="URL">$1<ex>google.com</ex></ph> wants to:
• Create a 3D map of your surroundings and track camera position
• Use your camera
</message>
<message name="IDS_NOTIFICATION_QUIET_PERMISSION_PROMPT_TITLE" desc="Text used as notification title when requesting permission for Web Notifications via a notification."> <message name="IDS_NOTIFICATION_QUIET_PERMISSION_PROMPT_TITLE" desc="Text used as notification title when requesting permission for Web Notifications via a notification.">
Notifications for <ph name="ORIGIN">$1<ex>example.com</ex></ph> are blocked Notifications for <ph name="ORIGIN">$1<ex>example.com</ex></ph> are blocked
</message> </message>
......
190759b575d8b4da48fc1bdec0a14e94a34c648e
\ No newline at end of file
...@@ -36,16 +36,29 @@ device::mojom::XRRuntimeSessionOptionsPtr GetRuntimeOptions( ...@@ -36,16 +36,29 @@ device::mojom::XRRuntimeSessionOptionsPtr GetRuntimeOptions(
return runtime_options; return runtime_options;
} }
content::PermissionType GetRequiredPermission( std::vector<content::PermissionType> GetRequiredPermissions(
device::mojom::XRSessionMode mode) { device::mojom::XRSessionMode mode,
const std::set<device::mojom::XRSessionFeature>& enabled_features) {
std::vector<content::PermissionType> permissions;
switch (mode) { switch (mode) {
case device::mojom::XRSessionMode::kInline: case device::mojom::XRSessionMode::kInline:
return content::PermissionType::SENSORS; permissions.push_back(content::PermissionType::SENSORS);
break;
case device::mojom::XRSessionMode::kImmersiveVr: case device::mojom::XRSessionMode::kImmersiveVr:
return content::PermissionType::VR; permissions.push_back(content::PermissionType::VR);
break;
case device::mojom::XRSessionMode::kImmersiveAr: case device::mojom::XRSessionMode::kImmersiveAr:
return content::PermissionType::AR; permissions.push_back(content::PermissionType::AR);
break;
}
if (base::Contains(enabled_features,
device::mojom::XRSessionFeature::CAMERA_ACCESS)) {
permissions.push_back(content::PermissionType::VIDEO_CAPTURE);
} }
return permissions;
} }
} // namespace } // namespace
...@@ -360,6 +373,7 @@ void VRServiceImpl::RequestSession( ...@@ -360,6 +373,7 @@ void VRServiceImpl::RequestSession(
// features. // features.
std::set<device::mojom::XRSessionFeature> requested_features; std::set<device::mojom::XRSessionFeature> requested_features;
for (const auto& feature : options->required_features) { for (const auto& feature : options->required_features) {
DVLOG(2) << __func__ << ": required_feature=" << feature;
requested_features.insert(feature); requested_features.insert(feature);
} }
...@@ -394,22 +408,28 @@ void VRServiceImpl::GetPermissionStatus(SessionRequestData request, ...@@ -394,22 +408,28 @@ void VRServiceImpl::GetPermissionStatus(SessionRequestData request,
GetWebContents()->GetBrowserContext()); GetWebContents()->GetBrowserContext());
DCHECK(permission_controller); DCHECK(permission_controller);
// Need to calculate the permission before the call below, as otherwise // Need to calculate the permissions before the call below, as otherwise
// std::move nulls options out before GetRequiredPermission runs. // std::move nulls options out before GetRequiredPermissions runs.
PermissionType permission = GetRequiredPermission(request.options->mode); const std::vector<PermissionType> permissions =
permission_controller->RequestPermission( GetRequiredPermissions(request.options->mode, request.enabled_features);
permission, render_frame_host_, render_frame_host_->GetLastCommittedURL(), permission_controller->RequestPermissions(
true, permissions, render_frame_host_,
base::BindOnce(&VRServiceImpl::OnPermissionResult, render_frame_host_->GetLastCommittedURL(), true,
base::BindOnce(&VRServiceImpl::OnPermissionResults,
weak_ptr_factory_.GetWeakPtr(), std::move(request))); weak_ptr_factory_.GetWeakPtr(), std::move(request)));
} }
void VRServiceImpl::OnPermissionResult( void VRServiceImpl::OnPermissionResults(
SessionRequestData request, SessionRequestData request,
blink::mojom::PermissionStatus permission_status) { const std::vector<blink::mojom::PermissionStatus>& permission_statuses) {
DVLOG(2) << __func__; DVLOG(2) << __func__;
bool is_consent_granted = bool is_consent_granted = true;
(permission_status == blink::mojom::PermissionStatus::GRANTED); for (auto& permission_status : permission_statuses) {
if (permission_status != blink::mojom::PermissionStatus::GRANTED) {
is_consent_granted = false;
break;
}
}
if (!is_consent_granted) { if (!is_consent_granted) {
std::move(request.callback) std::move(request.callback)
......
...@@ -142,8 +142,9 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService, ...@@ -142,8 +142,9 @@ class CONTENT_EXPORT VRServiceImpl : public device::mojom::VRService,
void GetPermissionStatus(SessionRequestData request, void GetPermissionStatus(SessionRequestData request,
BrowserXRRuntimeImpl* runtime); BrowserXRRuntimeImpl* runtime);
void OnPermissionResult(SessionRequestData request, void OnPermissionResults(
blink::mojom::PermissionStatus permission_status); SessionRequestData request,
const std::vector<blink::mojom::PermissionStatus>& permission_statuses);
void EnsureRuntimeInstalled(SessionRequestData request, void EnsureRuntimeInstalled(SessionRequestData request,
BrowserXRRuntimeImpl* runtime); BrowserXRRuntimeImpl* runtime);
......
IDS_ACCESSIBILITY_EVENTS_INFOBAR_TEXT IDS_ACCESSIBILITY_EVENTS_INFOBAR_TEXT
IDS_ACCESSIBILITY_EVENTS_PERMISSION_FRAGMENT IDS_ACCESSIBILITY_EVENTS_PERMISSION_FRAGMENT
IDS_AR_AND_MEDIA_CAPTURE_VIDEO_INFOBAR_TEXT
IDS_AR_INFOBAR_TEXT IDS_AR_INFOBAR_TEXT
IDS_AR_PERMISSION_FRAGMENT IDS_AR_PERMISSION_FRAGMENT
IDS_BEFORERELOAD_APP_MESSAGEBOX_TITLE IDS_BEFORERELOAD_APP_MESSAGEBOX_TITLE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment