blob: 7d9b045e6dab80f577469792bf9ffe1140e5a488 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/permissions/system/system_media_source_win.h"
#include <windows.foundation.h>
#include <windows.media.capture.h>
#include <optional>
#include <string_view>
#include "base/memory/raw_ref.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/win/core_winrt_util.h"
#include "base/win/post_async_results.h"
namespace {
using ::ABI::Windows::Security::Authorization::AppCapabilityAccess::
IAppCapability;
using ::Microsoft::WRL::ComPtr;
// Create an AppCapability object for the capability named `name`.
ComPtr<IAppCapability> CreateAppCapability(std::string_view name) {
using ::ABI::Windows::Security::Authorization::AppCapabilityAccess::
IAppCapabilityStatics;
ComPtr<IAppCapabilityStatics> app_capability_statics;
HRESULT hr = base::win::GetActivationFactory<
IAppCapabilityStatics,
RuntimeClass_Windows_Security_Authorization_AppCapabilityAccess_AppCapability>(
&app_capability_statics);
if (FAILED(hr)) {
return nullptr;
}
auto capability_name = base::win::ScopedHString::Create(name);
ComPtr<IAppCapability> app_capability;
hr = app_capability_statics->Create(capability_name.get(), &app_capability);
if (FAILED(hr)) {
return nullptr;
}
return app_capability;
}
SystemMediaSourceWin::Status SystemPermissionStatusImpl(
ComPtr<IAppCapability> app_capability) {
using ::ABI::Windows::Security::Authorization::AppCapabilityAccess::
AppCapabilityAccessStatus;
using ::ABI::Windows::Security::Authorization::AppCapabilityAccess::
AppCapabilityAccessStatus_Allowed;
using ::ABI::Windows::Security::Authorization::AppCapabilityAccess::
AppCapabilityAccessStatus_UserPromptRequired;
if (!app_capability) {
return SystemMediaSourceWin::Status::kNotDetermined;
}
AppCapabilityAccessStatus access_status;
HRESULT hr = app_capability->CheckAccess(&access_status);
if (FAILED(hr)) {
return SystemMediaSourceWin::Status::kNotDetermined;
}
if (access_status == AppCapabilityAccessStatus_Allowed) {
return SystemMediaSourceWin::Status::kAllowed;
}
if (access_status == AppCapabilityAccessStatus_UserPromptRequired) {
return SystemMediaSourceWin::Status::kNotDetermined;
}
return SystemMediaSourceWin::Status::kDenied;
}
} // namespace
using ::Microsoft::WRL::ComPtr;
SystemMediaSourceWin::SystemMediaSourceWin()
: camera_capability_(CreateAppCapability("webcam")),
microphone_capability_(CreateAppCapability("Microphone")) {}
SystemMediaSourceWin::~SystemMediaSourceWin() = default;
// static
SystemMediaSourceWin& SystemMediaSourceWin::GetInstance() {
static base::NoDestructor<SystemMediaSourceWin> instance;
return *instance;
}
void SystemMediaSourceWin::OnLaunchUriSuccess(uint8_t launched) {
launch_uri_op_.Reset();
}
void SystemMediaSourceWin::OnLaunchUriFailure(HRESULT result) {
launch_uri_op_.Reset();
}
// static
void SystemMediaSourceWin::OpenSystemPermissionSetting(
ContentSettingsType type) {
using ABI::Windows::Foundation::IUriRuntimeClass;
using ABI::Windows::Foundation::IUriRuntimeClassFactory;
using ABI::Windows::System::ILauncherStatics;
if (launch_uri_op_) {
return;
}
std::string capability_name;
switch (type) {
case ContentSettingsType::MEDIASTREAM_MIC:
capability_name = "ms-settings:privacy-microphone";
break;
case ContentSettingsType::MEDIASTREAM_CAMERA:
case ContentSettingsType::CAMERA_PAN_TILT_ZOOM:
capability_name = "ms-settings:privacy-webcam";
break;
default:
NOTREACHED();
}
ComPtr<IUriRuntimeClassFactory> uri_runtime_class_factory;
HRESULT hr =
base::win::GetActivationFactory<IUriRuntimeClassFactory,
RuntimeClass_Windows_Foundation_Uri>(
&uri_runtime_class_factory);
if (FAILED(hr)) {
return;
}
ComPtr<IUriRuntimeClass> uri_runtime_class;
base::win::ScopedHString uri_string =
base::win::ScopedHString::Create(capability_name);
hr = uri_runtime_class_factory->CreateUri(uri_string.get(),
&uri_runtime_class);
if (FAILED(hr)) {
return;
}
ComPtr<ILauncherStatics> launcher_statics;
hr = base::win::GetActivationFactory<ILauncherStatics,
RuntimeClass_Windows_System_Launcher>(
&launcher_statics);
if (FAILED(hr)) {
return;
}
hr = launcher_statics->LaunchUriAsync(uri_runtime_class.Get(),
&launch_uri_op_);
if (FAILED(hr)) {
return;
}
base::win::PostAsyncHandlers(
launch_uri_op_.Get(),
base::BindOnce(&SystemMediaSourceWin::OnLaunchUriSuccess,
weak_factory_.GetWeakPtr()),
base::BindOnce(&SystemMediaSourceWin::OnLaunchUriFailure,
weak_factory_.GetWeakPtr()));
}
SystemMediaSourceWin::Status SystemMediaSourceWin::SystemPermissionStatus(
ContentSettingsType type) {
switch (type) {
case ContentSettingsType::MEDIASTREAM_MIC:
return SystemPermissionStatusImpl(microphone_capability_);
case ContentSettingsType::MEDIASTREAM_CAMERA:
case ContentSettingsType::CAMERA_PAN_TILT_ZOOM:
return SystemPermissionStatusImpl(camera_capability_);
default:
NOTREACHED();
}
}