Add CefPermissionHandler callback for media access (fixes issue #2582)

This commit is contained in:
Marshall Greenblatt 2022-06-30 07:31:18 +00:00
parent c05cb73de1
commit 85bda40d95
29 changed files with 1852 additions and 83 deletions

View File

@ -577,6 +577,8 @@ static_library("libcef_static") {
"libcef/browser/javascript_dialog_manager.h",
"libcef/browser/main_runner.cc",
"libcef/browser/main_runner.h",
"libcef/browser/media_access_query.cc",
"libcef/browser/media_access_query.h",
"libcef/browser/media_capture_devices_dispatcher.cc",
"libcef/browser/media_capture_devices_dispatcher.h",
"libcef/browser/media_router/media_route_impl.cc",

View File

@ -8,7 +8,7 @@
# by hand. See the translator.README.txt file in the tools directory for
# more information.
#
# $hash=7ee0c6a789cc0574798332fe7c7cc10f862280af$
# $hash=f8ae899cc69a48e9878fa4db2fcc3b7e54230062$
#
{
@ -55,6 +55,7 @@
'include/cef_origin_whitelist.h',
'include/cef_parser.h',
'include/cef_path_util.h',
'include/cef_permission_handler.h',
'include/cef_print_handler.h',
'include/cef_print_settings.h',
'include/cef_process_message.h',
@ -154,6 +155,7 @@
'include/capi/cef_origin_whitelist_capi.h',
'include/capi/cef_parser_capi.h',
'include/capi/cef_path_util_capi.h',
'include/capi/cef_permission_handler_capi.h',
'include/capi/cef_print_handler_capi.h',
'include/capi/cef_print_settings_capi.h',
'include/capi/cef_process_message_capi.h',
@ -328,6 +330,8 @@
'libcef_dll/cpptoc/list_value_cpptoc.h',
'libcef_dll/ctocpp/load_handler_ctocpp.cc',
'libcef_dll/ctocpp/load_handler_ctocpp.h',
'libcef_dll/cpptoc/media_access_callback_cpptoc.cc',
'libcef_dll/cpptoc/media_access_callback_cpptoc.h',
'libcef_dll/ctocpp/media_observer_ctocpp.cc',
'libcef_dll/ctocpp/media_observer_ctocpp.h',
'libcef_dll/cpptoc/media_route_cpptoc.cc',
@ -364,6 +368,8 @@
'libcef_dll/ctocpp/views/panel_delegate_ctocpp.h',
'libcef_dll/ctocpp/pdf_print_callback_ctocpp.cc',
'libcef_dll/ctocpp/pdf_print_callback_ctocpp.h',
'libcef_dll/ctocpp/permission_handler_ctocpp.cc',
'libcef_dll/ctocpp/permission_handler_ctocpp.h',
'libcef_dll/cpptoc/post_data_cpptoc.cc',
'libcef_dll/cpptoc/post_data_cpptoc.h',
'libcef_dll/cpptoc/post_data_element_cpptoc.cc',
@ -636,6 +642,8 @@
'libcef_dll/ctocpp/list_value_ctocpp.h',
'libcef_dll/cpptoc/load_handler_cpptoc.cc',
'libcef_dll/cpptoc/load_handler_cpptoc.h',
'libcef_dll/ctocpp/media_access_callback_ctocpp.cc',
'libcef_dll/ctocpp/media_access_callback_ctocpp.h',
'libcef_dll/cpptoc/media_observer_cpptoc.cc',
'libcef_dll/cpptoc/media_observer_cpptoc.h',
'libcef_dll/ctocpp/media_route_ctocpp.cc',
@ -672,6 +680,8 @@
'libcef_dll/cpptoc/views/panel_delegate_cpptoc.h',
'libcef_dll/cpptoc/pdf_print_callback_cpptoc.cc',
'libcef_dll/cpptoc/pdf_print_callback_cpptoc.h',
'libcef_dll/cpptoc/permission_handler_cpptoc.cc',
'libcef_dll/cpptoc/permission_handler_cpptoc.h',
'libcef_dll/ctocpp/post_data_ctocpp.cc',
'libcef_dll/ctocpp/post_data_ctocpp.h',
'libcef_dll/ctocpp/post_data_element_ctocpp.cc',

View File

@ -475,6 +475,7 @@
'tests/ceftests/image_util.h',
'tests/ceftests/jsdialog_unittest.cc',
'tests/ceftests/life_span_unittest.cc',
'tests/ceftests/media_access_unittest.cc',
'tests/ceftests/message_router_unittest.cc',
'tests/ceftests/navigation_unittest.cc',
'tests/ceftests/os_rendering_unittest.cc',
@ -562,6 +563,7 @@
'tests/ceftests/cors_unittest.cc',
'tests/ceftests/dom_unittest.cc',
'tests/ceftests/frame_unittest.cc',
'tests/ceftests/media_access_unittest.cc',
'tests/ceftests/message_router_unittest.cc',
'tests/ceftests/navigation_unittest.cc',
'tests/ceftests/pdf_viewer_unittest.cc',

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=7df3c13b75072c2ad5061cd3a344811222798903$
// $hash=7e03d64dfcefc287c083e35e5ef9b3fa4f762b1b$
//
#ifndef CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_
@ -55,6 +55,7 @@
#include "include/capi/cef_keyboard_handler_capi.h"
#include "include/capi/cef_life_span_handler_capi.h"
#include "include/capi/cef_load_handler_capi.h"
#include "include/capi/cef_permission_handler_capi.h"
#include "include/capi/cef_print_handler_capi.h"
#include "include/capi/cef_process_message_capi.h"
#include "include/capi/cef_render_handler_capi.h"
@ -139,6 +140,13 @@ typedef struct _cef_client_t {
struct _cef_frame_handler_t*(CEF_CALLBACK* get_frame_handler)(
struct _cef_client_t* self);
///
// Return the handler for permission requests. If no handler is provided
// requests be denied by default.
///
struct _cef_permission_handler_t*(CEF_CALLBACK* get_permission_handler)(
struct _cef_client_t* self);
///
// Return the handler for JavaScript dialogs. If no handler is provided the
// default implementation will be used.

View File

@ -0,0 +1,108 @@
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=91101808168ec0faf1f39b1924579e31478a6616$
//
#ifndef CEF_INCLUDE_CAPI_CEF_MEDIA_ACCESS_HANDLER_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_MEDIA_ACCESS_HANDLER_CAPI_H_
#pragma once
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_browser_capi.h"
#ifdef __cplusplus
extern "C" {
#endif
///
// Callback structure used for asynchronous continuation of media access
// permission requests.
///
typedef struct _cef_media_access_callback_t {
///
// Base structure.
///
cef_base_ref_counted_t base;
///
// Call to allow or deny media access. If this callback was initiated in
// response to a getUserMedia (indicated by
// CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE and/or
// CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE being set) the
// |allowed_permissions| are required to match those given in
// |required_permissions| in the OnRequestMediaAccessPermission.
///
void(CEF_CALLBACK* cont)(struct _cef_media_access_callback_t* self,
int allowed_permissions);
///
// Cancel the media access request.
///
void(CEF_CALLBACK* cancel)(struct _cef_media_access_callback_t* self);
} cef_media_access_callback_t;
///
// Implement this structure to handle events related to media access permission
// requests. The functions of this structure will be called on the browser
// process UI thread.
///
typedef struct _cef_media_access_handler_t {
///
// Base structure.
///
cef_base_ref_counted_t base;
///
// Called when a page requests permission to access media. |requesting_url| is
// the URL requesting permission. Return true (1) and call
// cef_media_access_callback_t::cont() either in this function or at a later
// time to continue or cancel the request. Return false (0) to cancel the
// request immediately.
///
int(CEF_CALLBACK* on_request_media_access_permission)(
struct _cef_media_access_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame,
const cef_string_t* requesting_url,
int32_t requested_permissions,
struct _cef_media_access_callback_t* callback);
} cef_media_access_handler_t;
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_MEDIA_ACCESS_HANDLER_CAPI_H_

View File

@ -0,0 +1,110 @@
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=e25fb66e356e1f01d67cb86433382b3318e9778d$
//
#ifndef CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_
#pragma once
#include "include/capi/cef_base_capi.h"
#include "include/capi/cef_browser_capi.h"
#ifdef __cplusplus
extern "C" {
#endif
///
// Callback structure used for asynchronous continuation of media access
// permission requests.
///
typedef struct _cef_media_access_callback_t {
///
// Base structure.
///
cef_base_ref_counted_t base;
///
// Call to allow or deny media access. If this callback was initiated in
// response to a getUserMedia (indicated by
// CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE and/or
// CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE being set) then
// |allowed_permissions| must match |required_permissions| passed to
// OnRequestMediaAccessPermission.
///
void(CEF_CALLBACK* cont)(struct _cef_media_access_callback_t* self,
uint32 allowed_permissions);
///
// Cancel the media access request.
///
void(CEF_CALLBACK* cancel)(struct _cef_media_access_callback_t* self);
} cef_media_access_callback_t;
///
// Implement this structure to handle events related to permission requests. The
// functions of this structure will be called on the browser process UI thread.
///
typedef struct _cef_permission_handler_t {
///
// Base structure.
///
cef_base_ref_counted_t base;
///
// Called when a page requests permission to access media. |requesting_url| is
// the URL requesting permission. |requested_permissions| is a combination of
// values from cef_media_access_permission_types_t that represent the
// requested permissions. Return true (1) and call
// cef_media_access_callback_t::cont() either in this function or at a later
// time to continue or cancel the request. Return false (0) to cancel the
// request immediately. This function will not be called if the "--enable-
// media-stream" command-line switch is used to grant all permissions.
///
int(CEF_CALLBACK* on_request_media_access_permission)(
struct _cef_permission_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_frame_t* frame,
const cef_string_t* requesting_url,
uint32 requested_permissions,
struct _cef_media_access_callback_t* callback);
} cef_permission_handler_t;
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_PERMISSION_HANDLER_CAPI_H_

View File

@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "eb7cc5b2fb5c87d0f580e8df1bb609729fc731d0"
#define CEF_API_HASH_UNIVERSAL "f0b6806a3e15f849013e58992ef11c99e5cfeb60"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "b61f8f06751ed7231b2036b71d714d074feadf5b"
#define CEF_API_HASH_PLATFORM "55ba6603a77fcbf93d58a44fbeae9ea52d000153"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "d4ac1390d4c202e26633a0c95a560171ad05e4fe"
#define CEF_API_HASH_PLATFORM "4028739577ee54f7049f354acd724ecee071aa22"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "0d9fe8afb1b67a6098e08f7fe6d0ac7e70ce29e6"
#define CEF_API_HASH_PLATFORM "7464b32d2ed43a15d68a651199fda0c0fe040a8d"
#endif
#ifdef __cplusplus

View File

@ -53,6 +53,7 @@
#include "include/cef_keyboard_handler.h"
#include "include/cef_life_span_handler.h"
#include "include/cef_load_handler.h"
#include "include/cef_permission_handler.h"
#include "include/cef_print_handler.h"
#include "include/cef_process_message.h"
#include "include/cef_render_handler.h"
@ -132,6 +133,14 @@ class CefClient : public virtual CefBaseRefCounted {
/*--cef()--*/
virtual CefRefPtr<CefFrameHandler> GetFrameHandler() { return nullptr; }
///
// Return the handler for permission requests.
///
/*--cef()--*/
virtual CefRefPtr<CefPermissionHandler> GetPermissionHandler() {
return nullptr;
}
///
// Return the handler for JavaScript dialogs. If no handler is provided the
// default implementation will be used.

View File

@ -0,0 +1,97 @@
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---------------------------------------------------------------------------
//
// The contents of this file must follow a specific format in order to
// support the CEF translator tool. See the translator.README.txt file in the
// tools directory for more information.
//
#ifndef CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_
#define CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_
#pragma once
#include "include/cef_base.h"
#include "include/cef_browser.h"
///
// Callback interface used for asynchronous continuation of media access
// permission requests.
///
/*--cef(source=library)--*/
class CefMediaAccessCallback : public virtual CefBaseRefCounted {
public:
///
// Call to allow or deny media access. If this callback was initiated in
// response to a getUserMedia (indicated by
// CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE and/or
// CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE being set) then
// |allowed_permissions| must match |required_permissions| passed to
// OnRequestMediaAccessPermission.
///
/*--cef(capi_name=cont)--*/
virtual void Continue(uint32 allowed_permissions) = 0;
///
// Cancel the media access request.
///
/*--cef()--*/
virtual void Cancel() = 0;
};
///
// Implement this interface to handle events related to permission requests. The
// methods of this class will be called on the browser process UI thread.
///
/*--cef(source=client)--*/
class CefPermissionHandler : public virtual CefBaseRefCounted {
public:
///
// Called when a page requests permission to access media. |requesting_url| is
// the URL requesting permission. |requested_permissions| is a combination of
// values from cef_media_access_permission_types_t that represent the
// requested permissions. Return true and call
// CefMediaAccessCallback::Continue() either in this method or at a later time
// to continue or cancel the request. Return false to cancel the request
// immediately. This method will not be called if the "--enable-media-stream"
// command-line switch is used to grant all permissions.
///
/*--cef()--*/
virtual bool OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& requesting_url,
uint32 requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback) {
return false;
}
};
#endif // CEF_INCLUDE_CEF_PERMISSION_HANDLER_H_

View File

@ -3262,7 +3262,7 @@ typedef struct _cef_touch_handle_state_t {
// Combination of cef_touch_handle_state_flags_t values indicating what state
// is set.
///
uint32_t flags;
uint32 flags;
///
// Enabled state. Only set if |flags| contains CEF_THS_FLAG_ENABLED.
@ -3287,6 +3287,36 @@ typedef struct _cef_touch_handle_state_t {
float alpha;
} cef_touch_handle_state_t;
///
// Media access permissions used by OnRequestMediaAccessPermission.
///
typedef enum {
///
// No permission.
///
CEF_MEDIA_PERMISSION_NONE = 0,
///
// Device audio capture permission.
///
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE = 1 << 0,
///
// Device video capture permission.
///
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE = 1 << 1,
///
// Desktop audio capture permission.
///
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE = 1 << 2,
///
// Desktop video capture permission.
///
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE = 1 << 3,
} cef_media_access_permission_types_t;
#ifdef __cplusplus
}
#endif

View File

@ -17,7 +17,7 @@
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/context.h"
#include "libcef/browser/devtools/devtools_manager.h"
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/media_access_query.h"
#include "libcef/browser/osr/osr_util.h"
#include "libcef/browser/request_context_impl.h"
#include "libcef/browser/thread_util.h"
@ -51,7 +51,6 @@
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
#include "net/base/net_errors.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
#include "ui/events/base_event_utils.h"
using content::KeyboardEventProcessingResult;
@ -1299,82 +1298,16 @@ void AlloyBrowserHostImpl::RequestMediaAccessPermission(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
CEF_REQUIRE_UIT();
blink::MediaStreamDevices audio_devices;
blink::MediaStreamDevices video_devices;
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kEnableMediaStream)) {
// Cancel the request.
std::move(callback).Run(
blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
std::unique_ptr<content::MediaStreamUI>());
return;
}
// Based on chrome/browser/media/media_stream_devices_controller.cc
bool microphone_requested =
(request.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE);
bool webcam_requested = (request.video_type ==
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
bool screen_requested =
(request.video_type ==
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE);
if (microphone_requested || webcam_requested || screen_requested) {
// Pick the desired device or fall back to the first available of the
// given type.
if (microphone_requested) {
CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
request.requested_audio_device_id, true, false, &audio_devices);
}
if (webcam_requested) {
CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
request.requested_video_device_id, false, true, &video_devices);
}
if (screen_requested) {
content::DesktopMediaID media_id;
if (request.requested_video_device_id.empty()) {
media_id =
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
-1 /* webrtc::kFullDesktopScreenId */);
} else {
media_id =
content::DesktopMediaID::Parse(request.requested_video_device_id);
}
video_devices.push_back(blink::MediaStreamDevice(
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE,
media_id.ToString(), "Screen"));
}
}
blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
// At most one audio device and one video device can be used in a stream.
if (!audio_devices.empty())
devices.audio_device = audio_devices.front();
if (!video_devices.empty())
devices.video_device = video_devices.front();
std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK,
std::unique_ptr<content::MediaStreamUI>());
media_access_query::RequestMediaAccessPermission(this, request,
std::move(callback));
}
bool AlloyBrowserHostImpl::CheckMediaAccessPermission(
content::RenderFrameHost* render_frame_host,
const GURL& security_origin,
blink::mojom::MediaStreamType type) {
// Check media access permission without prompting the user.
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
return command_line->HasSwitch(switches::kEnableMediaStream);
return media_access_query::CheckMediaAccessPermission(this, render_frame_host,
security_origin, type);
}
bool AlloyBrowserHostImpl::IsNeverComposited(

View File

@ -0,0 +1,319 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#include "libcef/browser/media_access_query.h"
#include "include/cef_permission_handler.h"
#include "libcef/browser/browser_host_base.h"
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/common/cef_switches.h"
#include "base/command_line.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
namespace media_access_query {
namespace {
class CefMediaAccessQuery {
public:
using CallbackType = content::MediaResponseCallback;
explicit CefMediaAccessQuery(const content::MediaStreamRequest& request,
CallbackType&& callback)
: request_(request), callback_(std::move(callback)) {}
CefMediaAccessQuery(CefMediaAccessQuery&& query)
: request_(query.request_), callback_(std::move(query.callback_)) {}
CefMediaAccessQuery& operator=(CefMediaAccessQuery&& query) {
request_ = query.request_;
callback_ = std::move(query.callback_);
return *this;
}
CefMediaAccessQuery(const CefMediaAccessQuery&) = delete;
CefMediaAccessQuery& operator=(const CefMediaAccessQuery&) = delete;
bool is_null() const { return callback_.is_null(); }
uint32_t requested_permissions() const {
int requested_permissions = CEF_MEDIA_PERMISSION_NONE;
if (device_audio_requested()) {
requested_permissions |= CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
}
if (device_video_requested()) {
requested_permissions |= CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
}
if (desktop_audio_requested()) {
requested_permissions |= CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
}
if (desktop_video_requested()) {
requested_permissions |= CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
}
return requested_permissions;
}
void ExecuteCallback(uint32_t allowed_permissions) {
CEF_REQUIRE_UIT();
blink::mojom::MediaStreamRequestResult result;
blink::mojom::StreamDevicesSetPtr stream_devices_set;
if (allowed_permissions == CEF_MEDIA_PERMISSION_NONE) {
result = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
stream_devices_set = blink::mojom::StreamDevicesSet::New();
} else {
bool error = false;
if (allowed_permissions == requested_permissions()) {
stream_devices_set = GetRequestedMediaDevices();
} else {
stream_devices_set = GetAllowedMediaDevices(allowed_permissions, error);
}
result = error ? blink::mojom::MediaStreamRequestResult::INVALID_STATE
: blink::mojom::MediaStreamRequestResult::OK;
}
std::move(callback_).Run(*stream_devices_set, result,
std::unique_ptr<content::MediaStreamUI>());
}
private:
bool device_audio_requested() const {
return request_.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE;
}
bool device_video_requested() const {
return request_.video_type ==
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE;
}
bool desktop_audio_requested() const {
return (request_.audio_type ==
blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE) ||
(request_.audio_type ==
blink::mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE);
}
bool desktop_video_requested() const {
return (request_.video_type ==
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) ||
(request_.video_type ==
blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE);
}
blink::mojom::StreamDevicesSetPtr GetRequestedMediaDevices() const {
CEF_REQUIRE_UIT();
blink::MediaStreamDevices audio_devices;
blink::MediaStreamDevices video_devices;
if (device_audio_requested()) {
// Pick the desired device or fall back to the first available of the
// given type.
CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
request_.requested_audio_device_id, true, false, &audio_devices);
}
if (device_video_requested()) {
// Pick the desired device or fall back to the first available of the
// given type.
CefMediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
request_.requested_video_device_id, false, true, &video_devices);
}
if (desktop_audio_requested()) {
audio_devices.push_back(blink::MediaStreamDevice(
request_.audio_type, "loopback", "System Audio"));
}
if (desktop_video_requested()) {
content::DesktopMediaID media_id;
if (request_.requested_video_device_id.empty()) {
media_id =
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
-1 /* webrtc::kFullDesktopScreenId */);
} else {
media_id =
content::DesktopMediaID::Parse(request_.requested_video_device_id);
}
video_devices.push_back(blink::MediaStreamDevice(
request_.video_type, media_id.ToString(), "Screen"));
}
blink::mojom::StreamDevicesSetPtr stream_devices_set =
blink::mojom::StreamDevicesSet::New();
stream_devices_set->stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices =
*stream_devices_set->stream_devices[0];
// At most one audio device and one video device can be used in a stream.
if (!audio_devices.empty())
devices.audio_device = audio_devices.front();
if (!video_devices.empty())
devices.video_device = video_devices.front();
return stream_devices_set;
}
blink::mojom::StreamDevicesSetPtr GetAllowedMediaDevices(
uint32_t allowed_permissions,
bool& error) {
error = false;
const auto req_permissions = requested_permissions();
const bool device_audio_allowed =
allowed_permissions & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
const bool device_video_allowed =
allowed_permissions & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
const bool desktop_audio_allowed =
allowed_permissions & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
const bool desktop_video_allowed =
allowed_permissions & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
blink::mojom::StreamDevicesSetPtr stream_devices_set;
// getDisplayMedia must always request video
if (desktop_video_requested() &&
(!desktop_video_allowed && desktop_audio_allowed)) {
LOG(WARNING) << "Response to getDisplayMedia is not allowed to only "
"return Audio";
error = true;
} else if (!desktop_video_requested() &&
req_permissions != allowed_permissions) {
LOG(WARNING)
<< "Response to getUserMedia must match requested permissions ("
<< req_permissions << " vs " << allowed_permissions << ")";
error = true;
}
if (error) {
stream_devices_set = blink::mojom::StreamDevicesSet::New();
} else {
if (!device_audio_allowed && !desktop_audio_allowed) {
request_.audio_type = blink::mojom::MediaStreamType::NO_SERVICE;
}
if (!device_video_allowed && !desktop_video_allowed) {
request_.video_type = blink::mojom::MediaStreamType::NO_SERVICE;
}
stream_devices_set = GetRequestedMediaDevices();
}
return stream_devices_set;
}
content::MediaStreamRequest request_;
CallbackType callback_;
};
class CefMediaAccessCallbackImpl : public CefMediaAccessCallback {
public:
using CallbackType = CefMediaAccessQuery;
explicit CefMediaAccessCallbackImpl(CallbackType&& callback)
: callback_(std::move(callback)) {}
CefMediaAccessCallbackImpl(const CefMediaAccessCallbackImpl&) = delete;
CefMediaAccessCallbackImpl& operator=(const CefMediaAccessCallbackImpl&) =
delete;
~CefMediaAccessCallbackImpl() override {
if (!callback_.is_null()) {
// The callback is still pending. Cancel it now.
if (CEF_CURRENTLY_ON_UIT()) {
RunNow(std::move(callback_), CEF_MEDIA_PERMISSION_NONE);
} else {
CEF_POST_TASK(
CEF_UIT,
base::BindOnce(&CefMediaAccessCallbackImpl::RunNow,
std::move(callback_), CEF_MEDIA_PERMISSION_NONE));
}
}
}
void Continue(uint32_t allowed_permissions) override {
if (CEF_CURRENTLY_ON_UIT()) {
if (!callback_.is_null()) {
RunNow(std::move(callback_), allowed_permissions);
}
} else {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&CefMediaAccessCallbackImpl::Continue, this,
allowed_permissions));
}
}
void Cancel() override { Continue(CEF_MEDIA_PERMISSION_NONE); }
[[nodiscard]] CallbackType Disconnect() { return std::move(callback_); }
private:
static void RunNow(CallbackType callback, uint32_t allowed_permissions) {
callback.ExecuteCallback(allowed_permissions);
}
CallbackType callback_;
IMPLEMENT_REFCOUNTING(CefMediaAccessCallbackImpl);
};
bool CheckCommandLinePermission() {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
return command_line->HasSwitch(switches::kEnableMediaStream);
}
} // namespace
bool CheckMediaAccessPermission(CefBrowserHostBase* browser,
content::RenderFrameHost* render_frame_host,
const GURL& security_origin,
blink::mojom::MediaStreamType type) {
// Always allowed here. RequestMediaAccessPermission will be called.
return true;
}
void RequestMediaAccessPermission(CefBrowserHostBase* browser,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
CEF_REQUIRE_UIT();
CefMediaAccessQuery query(request, std::move(callback));
if (CheckCommandLinePermission()) {
// Allow all requested permissions.
query.ExecuteCallback(query.requested_permissions());
return;
}
bool proceed = false;
if (auto client = browser->GetClient()) {
if (auto handler = client->GetPermissionHandler()) {
const auto requested_permissions = query.requested_permissions();
CefRefPtr<CefMediaAccessCallbackImpl> callbackImpl(
new CefMediaAccessCallbackImpl(std::move(query)));
auto frame =
browser->GetFrameForGlobalId(content::GlobalRenderFrameHostId(
request.render_process_id, request.render_frame_id));
if (!frame)
frame = browser->GetMainFrame();
proceed = handler->OnRequestMediaAccessPermission(
browser, frame, request.security_origin.spec(), requested_permissions,
callbackImpl.get());
if (!proceed)
query = callbackImpl->Disconnect();
}
}
if (!proceed && !query.is_null()) {
// Disallow access by default.
query.ExecuteCallback(CEF_MEDIA_PERMISSION_NONE);
}
}
} // namespace media_access_query

View File

@ -0,0 +1,33 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#ifndef CEF_LIBCEF_BROWSER_MEDIA_ACCESS_QUERY_H_
#define CEF_LIBCEF_BROWSER_MEDIA_ACCESS_QUERY_H_
#pragma once
#include "content/public/browser/media_stream_request.h"
namespace content {
class RenderFrameHost;
}
class CefBrowserHostBase;
class GURL;
namespace media_access_query {
// Called from WebContentsDelegate::CheckMediaAccessPermission.
bool CheckMediaAccessPermission(CefBrowserHostBase* browser,
content::RenderFrameHost* render_frame_host,
const GURL& security_origin,
blink::mojom::MediaStreamType type);
// Called from WebContentsDelegate::RequestMediaAccessPermission.
void RequestMediaAccessPermission(CefBrowserHostBase* browser,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback);
} // namespace media_access_query
#endif // CEF_LIBCEF_BROWSER_MEDIA_ACCESS_QUERY_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=b299c22d4f97022efefefeb17a7848b0b44d4af3$
// $hash=6af3f901e4429197d0e47b15a68e980ea574b256$
//
#include "libcef_dll/cpptoc/client_cpptoc.h"
@ -27,6 +27,7 @@
#include "libcef_dll/cpptoc/keyboard_handler_cpptoc.h"
#include "libcef_dll/cpptoc/life_span_handler_cpptoc.h"
#include "libcef_dll/cpptoc/load_handler_cpptoc.h"
#include "libcef_dll/cpptoc/permission_handler_cpptoc.h"
#include "libcef_dll/cpptoc/print_handler_cpptoc.h"
#include "libcef_dll/cpptoc/render_handler_cpptoc.h"
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
@ -198,6 +199,22 @@ client_get_frame_handler(struct _cef_client_t* self) {
return CefFrameHandlerCppToC::Wrap(_retval);
}
struct _cef_permission_handler_t* CEF_CALLBACK
client_get_permission_handler(struct _cef_client_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Execute
CefRefPtr<CefPermissionHandler> _retval =
CefClientCppToC::Get(self)->GetPermissionHandler();
// Return type: refptr_same
return CefPermissionHandlerCppToC::Wrap(_retval);
}
struct _cef_jsdialog_handler_t* CEF_CALLBACK
client_get_jsdialog_handler(struct _cef_client_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -358,6 +375,7 @@ CefClientCppToC::CefClientCppToC() {
GetStruct()->get_find_handler = client_get_find_handler;
GetStruct()->get_focus_handler = client_get_focus_handler;
GetStruct()->get_frame_handler = client_get_frame_handler;
GetStruct()->get_permission_handler = client_get_permission_handler;
GetStruct()->get_jsdialog_handler = client_get_jsdialog_handler;
GetStruct()->get_keyboard_handler = client_get_keyboard_handler;
GetStruct()->get_life_span_handler = client_get_life_span_handler;

View File

@ -0,0 +1,81 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=dd3f62153541c74c294da2a33265a96491d17f2b$
//
#include "libcef_dll/cpptoc/media_access_callback_cpptoc.h"
#include "libcef_dll/shutdown_checker.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK
media_access_callback_cont(struct _cef_media_access_callback_t* self,
uint32 allowed_permissions) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefMediaAccessCallbackCppToC::Get(self)->Continue(allowed_permissions);
}
void CEF_CALLBACK
media_access_callback_cancel(struct _cef_media_access_callback_t* self) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefMediaAccessCallbackCppToC::Get(self)->Cancel();
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefMediaAccessCallbackCppToC::CefMediaAccessCallbackCppToC() {
GetStruct()->cont = media_access_callback_cont;
GetStruct()->cancel = media_access_callback_cancel;
}
// DESTRUCTOR - Do not edit by hand.
CefMediaAccessCallbackCppToC::~CefMediaAccessCallbackCppToC() {
shutdown_checker::AssertNotShutdown();
}
template <>
CefRefPtr<CefMediaAccessCallback> CefCppToCRefCounted<
CefMediaAccessCallbackCppToC,
CefMediaAccessCallback,
cef_media_access_callback_t>::UnwrapDerived(CefWrapperType type,
cef_media_access_callback_t*
s) {
NOTREACHED() << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType CefCppToCRefCounted<CefMediaAccessCallbackCppToC,
CefMediaAccessCallback,
cef_media_access_callback_t>::kWrapperType =
WT_MEDIA_ACCESS_CALLBACK;

View File

@ -0,0 +1,38 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=0adf2c32c67b7480fa4c544c5c570674d6917f7f$
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_MEDIA_ACCESS_CALLBACK_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_MEDIA_ACCESS_CALLBACK_CPPTOC_H_
#pragma once
#if !defined(BUILDING_CEF_SHARED)
#error This file can be included DLL-side only
#endif
#include "include/capi/cef_permission_handler_capi.h"
#include "include/cef_permission_handler.h"
#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefMediaAccessCallbackCppToC
: public CefCppToCRefCounted<CefMediaAccessCallbackCppToC,
CefMediaAccessCallback,
cef_media_access_callback_t> {
public:
CefMediaAccessCallbackCppToC();
virtual ~CefMediaAccessCallbackCppToC();
};
#endif // CEF_LIBCEF_DLL_CPPTOC_MEDIA_ACCESS_CALLBACK_CPPTOC_H_

View File

@ -0,0 +1,96 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=9c8d3c2295998f7a976967aa7f4b6a6da7c5c53d$
//
#include "libcef_dll/cpptoc/permission_handler_cpptoc.h"
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/media_access_callback_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK permission_handler_on_request_media_access_permission(
struct _cef_permission_handler_t* self,
cef_browser_t* browser,
cef_frame_t* frame,
const cef_string_t* requesting_url,
uint32 requested_permissions,
cef_media_access_callback_t* callback) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser)
return 0;
// Verify param: frame; type: refptr_diff
DCHECK(frame);
if (!frame)
return 0;
// Verify param: requesting_url; type: string_byref_const
DCHECK(requesting_url);
if (!requesting_url)
return 0;
// Verify param: callback; type: refptr_diff
DCHECK(callback);
if (!callback)
return 0;
// Execute
bool _retval =
CefPermissionHandlerCppToC::Get(self)->OnRequestMediaAccessPermission(
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
CefString(requesting_url), requested_permissions,
CefMediaAccessCallbackCToCpp::Wrap(callback));
// Return type: bool
return _retval;
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefPermissionHandlerCppToC::CefPermissionHandlerCppToC() {
GetStruct()->on_request_media_access_permission =
permission_handler_on_request_media_access_permission;
}
// DESTRUCTOR - Do not edit by hand.
CefPermissionHandlerCppToC::~CefPermissionHandlerCppToC() {
shutdown_checker::AssertNotShutdown();
}
template <>
CefRefPtr<CefPermissionHandler> CefCppToCRefCounted<
CefPermissionHandlerCppToC,
CefPermissionHandler,
cef_permission_handler_t>::UnwrapDerived(CefWrapperType type,
cef_permission_handler_t* s) {
NOTREACHED() << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType CefCppToCRefCounted<CefPermissionHandlerCppToC,
CefPermissionHandler,
cef_permission_handler_t>::kWrapperType =
WT_PERMISSION_HANDLER;

View File

@ -0,0 +1,38 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=0f90cfade714209df150953eabed70bc7b264122$
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_
#pragma once
#if !defined(WRAPPING_CEF_SHARED)
#error This file can be included wrapper-side only
#endif
#include "include/capi/cef_permission_handler_capi.h"
#include "include/cef_permission_handler.h"
#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefPermissionHandlerCppToC
: public CefCppToCRefCounted<CefPermissionHandlerCppToC,
CefPermissionHandler,
cef_permission_handler_t> {
public:
CefPermissionHandlerCppToC();
virtual ~CefPermissionHandlerCppToC();
};
#endif // CEF_LIBCEF_DLL_CPPTOC_PERMISSION_HANDLER_CPPTOC_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=8e158f3ea54211b95f0b716b1eeec2ff475f1245$
// $hash=71c2e9dd248276daa80be557773fe86bdc2bcb99$
//
#include "libcef_dll/ctocpp/client_ctocpp.h"
@ -30,6 +30,7 @@
#include "libcef_dll/ctocpp/keyboard_handler_ctocpp.h"
#include "libcef_dll/ctocpp/life_span_handler_ctocpp.h"
#include "libcef_dll/ctocpp/load_handler_ctocpp.h"
#include "libcef_dll/ctocpp/permission_handler_ctocpp.h"
#include "libcef_dll/ctocpp/print_handler_ctocpp.h"
#include "libcef_dll/ctocpp/render_handler_ctocpp.h"
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
@ -187,6 +188,21 @@ CefRefPtr<CefFrameHandler> CefClientCToCpp::GetFrameHandler() {
return CefFrameHandlerCToCpp::Wrap(_retval);
}
NO_SANITIZE("cfi-icall")
CefRefPtr<CefPermissionHandler> CefClientCToCpp::GetPermissionHandler() {
cef_client_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_permission_handler))
return nullptr;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_permission_handler_t* _retval = _struct->get_permission_handler(_struct);
// Return type: refptr_same
return CefPermissionHandlerCToCpp::Wrap(_retval);
}
NO_SANITIZE("cfi-icall")
CefRefPtr<CefJSDialogHandler> CefClientCToCpp::GetJSDialogHandler() {
cef_client_t* _struct = GetStruct();

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=69f82ee575779deaf1d3581dbedcf8aa75f35710$
// $hash=821429d4e38b03407a1e6cf73a67e479810f0c21$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_CLIENT_CTOCPP_H_
@ -43,6 +43,7 @@ class CefClientCToCpp
CefRefPtr<CefFindHandler> GetFindHandler() override;
CefRefPtr<CefFocusHandler> GetFocusHandler() override;
CefRefPtr<CefFrameHandler> GetFrameHandler() override;
CefRefPtr<CefPermissionHandler> GetPermissionHandler() override;
CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() override;
CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override;
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override;

View File

@ -0,0 +1,71 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=bfd836add2381882b8c0408181621ebf24cddce1$
//
#include "libcef_dll/ctocpp/media_access_callback_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
// VIRTUAL METHODS - Body may be edited by hand.
NO_SANITIZE("cfi-icall")
void CefMediaAccessCallbackCToCpp::Continue(uint32 allowed_permissions) {
shutdown_checker::AssertNotShutdown();
cef_media_access_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, cont))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->cont(_struct, allowed_permissions);
}
NO_SANITIZE("cfi-icall") void CefMediaAccessCallbackCToCpp::Cancel() {
shutdown_checker::AssertNotShutdown();
cef_media_access_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, cancel))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->cancel(_struct);
}
// CONSTRUCTOR - Do not edit by hand.
CefMediaAccessCallbackCToCpp::CefMediaAccessCallbackCToCpp() {}
// DESTRUCTOR - Do not edit by hand.
CefMediaAccessCallbackCToCpp::~CefMediaAccessCallbackCToCpp() {
shutdown_checker::AssertNotShutdown();
}
template <>
cef_media_access_callback_t* CefCToCppRefCounted<
CefMediaAccessCallbackCToCpp,
CefMediaAccessCallback,
cef_media_access_callback_t>::UnwrapDerived(CefWrapperType type,
CefMediaAccessCallback* c) {
NOTREACHED() << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType CefCToCppRefCounted<CefMediaAccessCallbackCToCpp,
CefMediaAccessCallback,
cef_media_access_callback_t>::kWrapperType =
WT_MEDIA_ACCESS_CALLBACK;

View File

@ -0,0 +1,42 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=1b4c8da03ff2853b057860369bdb5dd1b48cf046$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_MEDIA_ACCESS_CALLBACK_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_MEDIA_ACCESS_CALLBACK_CTOCPP_H_
#pragma once
#if !defined(WRAPPING_CEF_SHARED)
#error This file can be included wrapper-side only
#endif
#include "include/capi/cef_permission_handler_capi.h"
#include "include/cef_permission_handler.h"
#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefMediaAccessCallbackCToCpp
: public CefCToCppRefCounted<CefMediaAccessCallbackCToCpp,
CefMediaAccessCallback,
cef_media_access_callback_t> {
public:
CefMediaAccessCallbackCToCpp();
virtual ~CefMediaAccessCallbackCToCpp();
// CefMediaAccessCallback methods.
void Continue(uint32 allowed_permissions) override;
void Cancel() override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_MEDIA_ACCESS_CALLBACK_CTOCPP_H_

View File

@ -0,0 +1,89 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=f9073ac6e5a3634a3bf3c919ac1b0a9c607b4398$
//
#include "libcef_dll/ctocpp/permission_handler_ctocpp.h"
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/media_access_callback_cpptoc.h"
#include "libcef_dll/shutdown_checker.h"
// VIRTUAL METHODS - Body may be edited by hand.
NO_SANITIZE("cfi-icall")
bool CefPermissionHandlerCToCpp::OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& requesting_url,
uint32 requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback) {
shutdown_checker::AssertNotShutdown();
cef_permission_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_request_media_access_permission))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get())
return false;
// Verify param: frame; type: refptr_diff
DCHECK(frame.get());
if (!frame.get())
return false;
// Verify param: requesting_url; type: string_byref_const
DCHECK(!requesting_url.empty());
if (requesting_url.empty())
return false;
// Verify param: callback; type: refptr_diff
DCHECK(callback.get());
if (!callback.get())
return false;
// Execute
int _retval = _struct->on_request_media_access_permission(
_struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
requesting_url.GetStruct(), requested_permissions,
CefMediaAccessCallbackCppToC::Wrap(callback));
// Return type: bool
return _retval ? true : false;
}
// CONSTRUCTOR - Do not edit by hand.
CefPermissionHandlerCToCpp::CefPermissionHandlerCToCpp() {}
// DESTRUCTOR - Do not edit by hand.
CefPermissionHandlerCToCpp::~CefPermissionHandlerCToCpp() {
shutdown_checker::AssertNotShutdown();
}
template <>
cef_permission_handler_t* CefCToCppRefCounted<
CefPermissionHandlerCToCpp,
CefPermissionHandler,
cef_permission_handler_t>::UnwrapDerived(CefWrapperType type,
CefPermissionHandler* c) {
NOTREACHED() << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType CefCToCppRefCounted<CefPermissionHandlerCToCpp,
CefPermissionHandler,
cef_permission_handler_t>::kWrapperType =
WT_PERMISSION_HANDLER;

View File

@ -0,0 +1,46 @@
// Copyright (c) 2022 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=1c8392555b99119b866989c5461ad48a0ac662b5$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_
#pragma once
#if !defined(BUILDING_CEF_SHARED)
#error This file can be included DLL-side only
#endif
#include "include/capi/cef_permission_handler_capi.h"
#include "include/cef_permission_handler.h"
#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefPermissionHandlerCToCpp
: public CefCToCppRefCounted<CefPermissionHandlerCToCpp,
CefPermissionHandler,
cef_permission_handler_t> {
public:
CefPermissionHandlerCToCpp();
virtual ~CefPermissionHandlerCToCpp();
// CefPermissionHandler methods.
bool OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& requesting_url,
uint32 requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback) override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_PERMISSION_HANDLER_CTOCPP_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=98d509772d772e85d47d53e3df21f7317799c19e$
// $hash=54ed016f3b2bbffebc96ac9cadd3c3986d240342$
//
#ifndef CEF_LIBCEF_DLL_WRAPPER_TYPES_H_
@ -77,6 +77,7 @@ enum CefWrapperType {
WT_LIFE_SPAN_HANDLER,
WT_LIST_VALUE,
WT_LOAD_HANDLER,
WT_MEDIA_ACCESS_CALLBACK,
WT_MEDIA_OBSERVER,
WT_MEDIA_ROUTE,
WT_MEDIA_ROUTE_CREATE_CALLBACK,
@ -95,6 +96,7 @@ enum CefWrapperType {
WT_PANEL,
WT_PANEL_DELEGATE,
WT_PDF_PRINT_CALLBACK,
WT_PERMISSION_HANDLER,
WT_POST_DATA,
WT_POST_DATA_ELEMENT,
WT_PRINT_DIALOG_CALLBACK,

View File

@ -43,6 +43,7 @@ enum client_menu_ids {
CLIENT_ID_INSPECT_ELEMENT,
CLIENT_ID_SHOW_SSL_INFO,
CLIENT_ID_CURSOR_CHANGE_DISABLED,
CLIENT_ID_MEDIA_HANDLING_DISABLED,
CLIENT_ID_OFFLINE,
CLIENT_ID_TESTMENU_SUBMENU,
CLIENT_ID_TESTMENU_CHECKITEM,
@ -407,6 +408,12 @@ void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
"Cursor change disabled");
if (mouse_cursor_change_disabled_)
model->SetChecked(CLIENT_ID_CURSOR_CHANGE_DISABLED, true);
model->AddSeparator();
model->AddCheckItem(CLIENT_ID_MEDIA_HANDLING_DISABLED,
"Media handling disabled");
if (media_handling_disabled_)
model->SetChecked(CLIENT_ID_MEDIA_HANDLING_DISABLED, true);
}
model->AddSeparator();
@ -445,6 +452,9 @@ bool ClientHandler::OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
case CLIENT_ID_CURSOR_CHANGE_DISABLED:
mouse_cursor_change_disabled_ = !mouse_cursor_change_disabled_;
return true;
case CLIENT_ID_MEDIA_HANDLING_DISABLED:
media_handling_disabled_ = !media_handling_disabled_;
return true;
case CLIENT_ID_OFFLINE:
offline_ = !offline_;
SetOfflineState(browser, offline_);
@ -777,6 +787,17 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
LoadErrorPage(frame, failedUrl, errorCode, errorText);
}
bool ClientHandler::OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& requesting_url,
uint32 requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback) {
callback->Continue(media_handling_disabled_ ? CEF_MEDIA_PERMISSION_NONE
: requested_permissions);
return true;
}
bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,

View File

@ -37,6 +37,7 @@ class ClientHandler : public CefClient,
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefPermissionHandler,
public CefRequestHandler,
public CefResourceRequestHandler {
public:
@ -114,6 +115,9 @@ class ClientHandler : public CefClient,
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
return this;
}
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefProcessId source_process,
@ -229,6 +233,14 @@ class ClientHandler : public CefClient,
const CefString& errorText,
const CefString& failedUrl) override;
// CefPermissionHandler methods
bool OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& requesting_url,
uint32 requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback) override;
// CefRequestHandler methods
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
@ -382,6 +394,9 @@ class ClientHandler : public CefClient,
// True if mouse cursor change is disabled.
bool mouse_cursor_change_disabled_;
// True if media handling is disabled.
bool media_handling_disabled_ = true;
// True if the browser is currently offline.
bool offline_;

View File

@ -22,6 +22,11 @@ void CreateBrowserDelegates(ClientAppBrowser::DelegateSet& delegates) {
delegates);
CreatePreferenceBrowserTests(delegates);
// Bring in the media access tests.
extern void CreateMediaAccessBrowserTests(ClientAppBrowser::DelegateSet &
delegates);
CreateMediaAccessBrowserTests(delegates);
// Bring in URLRequest tests.
extern void CreateURLRequestBrowserTests(ClientAppBrowser::DelegateSet &
delegates);

View File

@ -0,0 +1,529 @@
// Copyright 2022 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#include <string>
#include <vector>
#include "include/base/cef_bind.h"
#include "include/cef_parser.h"
#include "include/cef_permission_handler.h"
#include "include/cef_request_context_handler.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "tests/ceftests/test_handler.h"
#include "tests/ceftests/test_suite.h"
#include "tests/gtest/include/gtest/gtest.h"
#include "tests/shared/browser/client_app_browser.h"
namespace {
// Media access requires HTTPS.
const char kMediaUrl[] = "https://media-access-test/media.html";
// Browser-side app delegate.
class MediaAccessBrowserTest : public client::ClientAppBrowser::Delegate,
public CefPermissionHandler {
public:
MediaAccessBrowserTest() {}
void OnBeforeCommandLineProcessing(
CefRefPtr<client::ClientAppBrowser> app,
CefRefPtr<CefCommandLine> command_line) override {
// We might run tests on systems that don't have media device,
// so just use fake devices.
command_line->AppendSwitch("use-fake-device-for-media-stream");
}
private:
IMPLEMENT_REFCOUNTING(MediaAccessBrowserTest);
};
class TestSetup {
public:
TestSetup() {}
bool deny_implicitly = false;
bool continue_async = false;
TrackCallback got_success;
TrackCallback got_audio;
TrackCallback got_video;
};
class MediaAccessTestHandler : public TestHandler, public CefPermissionHandler {
public:
MediaAccessTestHandler(TestSetup* tr, uint32 request, uint32 response)
: test_setup_(tr), request_(request), response_(response) {}
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override {
std::string newUrl = request->GetURL();
if (newUrl.find("tests/exit") != std::string::npos) {
CefURLParts url_parts;
CefParseURL(newUrl, url_parts);
if (newUrl.find("SUCCESS") != std::string::npos) {
test_setup_->got_success.yes();
std::string data_string = newUrl.substr(newUrl.find("&data=") +
std::string("&data=").length());
std::string data_string_decoded = CefURIDecode(
data_string, false,
static_cast<cef_uri_unescape_rule_t>(
UU_SPACES | UU_URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS));
auto obj = CefParseJSON(data_string_decoded,
JSON_PARSER_ALLOW_TRAILING_COMMAS);
CefRefPtr<CefDictionaryValue> data = obj->GetDictionary();
const auto got_video = data->GetBool("got_video_track");
const auto got_audio = data->GetBool("got_audio_track");
if (got_video) {
test_setup_->got_video.yes();
}
if (got_audio) {
test_setup_->got_audio.yes();
}
}
DestroyTest();
return RV_CANCEL;
}
return RV_CONTINUE;
}
void RunTest() override {
std::string page =
"<html><head>"
"<script>"
"function onResult(val, data) {"
" if(!data) {"
" data = { got_audio_track: false, got_video_track: false};"
" }"
" document.location = "
"`http://tests/"
"exit?result=${val}&data=${encodeURIComponent(JSON.stringify(data))}`;"
"}";
const bool want_audio_device =
request_ & CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE;
const bool want_video_device =
request_ & CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE;
const bool want_desktop_audio =
request_ & CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE;
const bool want_desktop_video =
request_ & CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE;
if (want_audio_device || want_video_device) {
page += std::string("navigator.mediaDevices.getUserMedia({audio: ") +
(want_audio_device ? "true" : "false") +
", video: " + (want_video_device ? "true" : "false") + "})";
} else {
page += std::string("navigator.mediaDevices.getDisplayMedia({audio: ") +
(want_desktop_audio ? "true" : "false") +
", video: " + (want_desktop_video ? "true" : "false") + "})";
}
page +=
".then(function(stream) {"
"onResult(`SUCCESS`, {got_audio_track: stream.getAudioTracks().length "
"> 0, got_video_track: stream.getVideoTracks().length > 0});"
"})"
".catch(function(err) {"
"console.log(err);"
"onResult(`FAILURE`);"
"});"
"</script>"
"</head><body>MEDIA ACCESS TEST</body></html>";
// Create the request context that will use an in-memory cache.
CefRequestContextSettings settings;
CefRefPtr<CefRequestContext> request_context =
CefRequestContext::CreateContext(settings, nullptr);
AddResource(kMediaUrl, page, "text/html");
// Create the browser.
CreateBrowser(kMediaUrl, request_context);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
return this;
}
void CompleteTest() {
if (!CefCurrentlyOn(TID_UI)) {
CefPostTask(TID_UI,
base::BindOnce(&MediaAccessTestHandler::CompleteTest, this));
return;
}
DestroyTest();
}
bool OnRequestMediaAccessPermission(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& requesting_url,
uint32 requested_permissions,
CefRefPtr<CefMediaAccessCallback> callback) override {
EXPECT_UI_THREAD();
EXPECT_TRUE(frame->IsMain());
if (test_setup_->deny_implicitly) {
return false;
}
EXPECT_EQ(requested_permissions, request_);
if (test_setup_->continue_async) {
CefPostTask(TID_UI, base::BindOnce(&CefMediaAccessCallback::Continue,
callback, response_));
} else {
callback->Continue(response_);
}
return true;
}
protected:
TestSetup* const test_setup_;
const uint32 request_;
const uint32 response_;
IMPLEMENT_REFCOUNTING(MediaAccessTestHandler);
};
} // namespace
// Capture device tests
TEST(MediaAccessTest, DeviceFailureWhenReturningFalse) {
TestSetup test_setup;
test_setup.deny_implicitly = true;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_NONE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermission) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_NONE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningNoPermissionAsync) {
TestSetup test_setup;
test_setup.continue_async = true;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_NONE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenRequestingAudioButReturningVideo) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenRequestingVideoButReturningAudio) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DevicePartialFailureReturningVideo) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DevicePartialFailureReturningAudio) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture1) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture2) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture3) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture4) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture5) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceFailureWhenReturningScreenCapture6) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceSuccessAudioOnly) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceSuccessVideoOnly) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceSuccessAudioVideo) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
}
TEST(MediaAccessTest, DeviceSuccessAudioVideoAsync) {
TestSetup test_setup;
test_setup.continue_async = true;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE,
CEF_MEDIA_PERMISSION_DEVICE_VIDEO_CAPTURE |
CEF_MEDIA_PERMISSION_DEVICE_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_success);
EXPECT_TRUE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
}
// Screen capture tests
TEST(MediaAccessTest, DesktopFailureWhenReturningNoPermission) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_NONE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DesktopFailureWhenRequestingVideoButReturningAudio) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler = new MediaAccessTestHandler(
&test_setup, CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
TEST(MediaAccessTest, DesktopPartialSuccessReturningVideo) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_TRUE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_TRUE(test_setup.got_video);
}
TEST(MediaAccessTest, DesktopPartialFailureReturningAudio) {
TestSetup test_setup;
CefRefPtr<MediaAccessTestHandler> handler =
new MediaAccessTestHandler(&test_setup,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE |
CEF_MEDIA_PERMISSION_DESKTOP_VIDEO_CAPTURE,
CEF_MEDIA_PERMISSION_DESKTOP_AUDIO_CAPTURE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
EXPECT_FALSE(test_setup.got_success);
EXPECT_FALSE(test_setup.got_audio);
EXPECT_FALSE(test_setup.got_video);
}
// Entry point for creating media access browser test objects.
// Called from client_app_delegates.cc.
void CreateMediaAccessBrowserTests(
client::ClientAppBrowser::DelegateSet& delegates) {
delegates.insert(new MediaAccessBrowserTest);
}