Skip to content

Commit

Permalink
Add OnMediaAccessChange notification (fixes issue #3310)
Browse files Browse the repository at this point in the history
  • Loading branch information
magreenblatt committed Jun 30, 2022
1 parent e34e914 commit 521546d
Show file tree
Hide file tree
Showing 14 changed files with 347 additions and 34 deletions.
2 changes: 2 additions & 0 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ static_library("libcef_static") {
"libcef/browser/media_router/media_sink_impl.h",
"libcef/browser/media_router/media_source_impl.cc",
"libcef/browser/media_router/media_source_impl.h",
"libcef/browser/media_stream_registrar.cc",
"libcef/browser/media_stream_registrar.h",
"libcef/browser/menu_manager.cc",
"libcef/browser/menu_manager.h",
"libcef/browser/menu_model_impl.cc",
Expand Down
5 changes: 2 additions & 3 deletions include/capi/cef_client_capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=7e03d64dfcefc287c083e35e5ef9b3fa4f762b1b$
// $hash=03ae4ba9762510e2b0c19ea29322c20ebaf2e683$
//

#ifndef CEF_INCLUDE_CAPI_CEF_CLIENT_CAPI_H_
Expand Down Expand Up @@ -141,8 +141,7 @@ typedef struct _cef_client_t {
struct _cef_client_t* self);

///
// Return the handler for permission requests. If no handler is provided
// requests be denied by default.
// Return the handler for permission requests.
///
struct _cef_permission_handler_t*(CEF_CALLBACK* get_permission_handler)(
struct _cef_client_t* self);
Expand Down
12 changes: 11 additions & 1 deletion include/capi/cef_display_handler_capi.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=142637539a094a03adc71d2f3f5b711ba64918b1$
// $hash=5e52ae520b7eda3595683d428aa578bbc776956b$
//

#ifndef CEF_INCLUDE_CAPI_CEF_DISPLAY_HANDLER_CAPI_H_
Expand Down Expand Up @@ -154,6 +154,16 @@ typedef struct _cef_display_handler_t {
cef_cursor_handle_t cursor,
cef_cursor_type_t type,
const struct _cef_cursor_info_t* custom_cursor_info);

///
// Called when the browser's access to an audio and/or video source has
// changed.
///
void(CEF_CALLBACK* on_media_access_change)(
struct _cef_display_handler_t* self,
struct _cef_browser_t* browser,
int has_video_access,
int has_audio_access);
} cef_display_handler_t;

#ifdef __cplusplus
Expand Down
8 changes: 4 additions & 4 deletions include/cef_api_hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 "f0b6806a3e15f849013e58992ef11c99e5cfeb60"
#define CEF_API_HASH_UNIVERSAL "794a4cf2ad83db17558bd2ca2d721487875a37e8"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "55ba6603a77fcbf93d58a44fbeae9ea52d000153"
#define CEF_API_HASH_PLATFORM "aa627f71c1cbdf13beeb3fe740337f4cc1cb5dc5"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "4028739577ee54f7049f354acd724ecee071aa22"
#define CEF_API_HASH_PLATFORM "6bda80f2ee107a22780193a7af9101eb5a4db8a0"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "7464b32d2ed43a15d68a651199fda0c0fe040a8d"
#define CEF_API_HASH_PLATFORM "c83b942ce72835d0ea01bfc4cab3928b92abdb85"
#endif

#ifdef __cplusplus
Expand Down
9 changes: 9 additions & 0 deletions include/cef_display_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ class CefDisplayHandler : public virtual CefBaseRefCounted {
const CefCursorInfo& custom_cursor_info) {
return false;
}

///
// Called when the browser's access to an audio and/or video source has
// changed.
///
/*--cef()--*/
virtual void OnMediaAccessChange(CefRefPtr<CefBrowser> browser,
bool has_video_access,
bool has_audio_access) {}
};

#endif // CEF_INCLUDE_CEF_DISPLAY_HANDLER_H_
13 changes: 11 additions & 2 deletions libcef/browser/browser_host_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,10 @@ void CefBrowserHostBase::InitializeBrowser() {
void CefBrowserHostBase::DestroyBrowser() {
CEF_REQUIRE_UIT();

devtools_manager_.reset(nullptr);
devtools_manager_.reset();
media_stream_registrar_.reset();

platform_delegate_.reset(nullptr);
platform_delegate_.reset();

contents_delegate_->RemoveObserver(this);
contents_delegate_->ObserveWebContents(nullptr);
Expand Down Expand Up @@ -972,6 +973,14 @@ content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const {
return nullptr;
}

CefMediaStreamRegistrar* CefBrowserHostBase::GetMediaStreamRegistrar() {
CEF_REQUIRE_UIT();
if (!media_stream_registrar_) {
media_stream_registrar_ = std::make_unique<CefMediaStreamRegistrar>(this);
}
return media_stream_registrar_.get();
}

views::Widget* CefBrowserHostBase::GetWindowWidget() const {
CEF_REQUIRE_UIT();
if (!platform_delegate_)
Expand Down
4 changes: 4 additions & 0 deletions libcef/browser/browser_host_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "libcef/browser/devtools/devtools_manager.h"
#include "libcef/browser/file_dialog_manager.h"
#include "libcef/browser/frame_host_impl.h"
#include "libcef/browser/media_stream_registrar.h"
#include "libcef/browser/request_context_impl.h"

#include "base/observer_list.h"
Expand Down Expand Up @@ -301,6 +302,7 @@ class CefBrowserHostBase : public CefBrowserHost,
CefBrowserContentsDelegate* contents_delegate() const {
return contents_delegate_.get();
}
CefMediaStreamRegistrar* GetMediaStreamRegistrar();

// Returns the Widget owner for the browser window. Only used with windowed
// browsers.
Expand Down Expand Up @@ -371,6 +373,8 @@ class CefBrowserHostBase : public CefBrowserHost,
// Used for creating and managing DevTools instances.
std::unique_ptr<CefDevToolsManager> devtools_manager_;

std::unique_ptr<CefMediaStreamRegistrar> media_stream_registrar_;

private:
IMPLEMENT_REFCOUNTING(CefBrowserHostBase);
};
Expand Down
30 changes: 24 additions & 6 deletions libcef/browser/media_access_query.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "include/cef_permission_handler.h"
#include "libcef/browser/browser_host_base.h"
#include "libcef/browser/media_capture_devices_dispatcher.h"
#include "libcef/browser/media_stream_registrar.h"
#include "libcef/common/cef_switches.h"

#include "base/command_line.h"
Expand All @@ -20,13 +21,17 @@ class CefMediaAccessQuery {
public:
using CallbackType = content::MediaResponseCallback;

explicit CefMediaAccessQuery(const content::MediaStreamRequest& request,
CallbackType&& callback)
: request_(request), callback_(std::move(callback)) {}
CefMediaAccessQuery(CefBrowserHostBase* const browser,
const content::MediaStreamRequest& request,
CallbackType&& callback)
: browser_(browser), request_(request), callback_(std::move(callback)) {}

CefMediaAccessQuery(CefMediaAccessQuery&& query)
: request_(query.request_), callback_(std::move(query.callback_)) {}
: browser_(query.browser_),
request_(query.request_),
callback_(std::move(query.callback_)) {}
CefMediaAccessQuery& operator=(CefMediaAccessQuery&& query) {
browser_ = query.browser_;
request_ = query.request_;
callback_ = std::move(query.callback_);
return *this;
Expand Down Expand Up @@ -74,8 +79,20 @@ class CefMediaAccessQuery {
: blink::mojom::MediaStreamRequestResult::OK;
}

bool has_video = false;
bool has_audio = false;
if (!stream_devices_set->stream_devices.empty()) {
blink::mojom::StreamDevices& devices =
*stream_devices_set->stream_devices[0];
has_video = devices.video_device.has_value();
has_audio = devices.audio_device.has_value();
}
auto media_stream_ui =
browser_->GetMediaStreamRegistrar()->MaybeCreateMediaStreamUI(
has_video, has_audio);

std::move(callback_).Run(*stream_devices_set, result,
std::unique_ptr<content::MediaStreamUI>());
std::move(media_stream_ui));
}

private:
Expand Down Expand Up @@ -205,6 +222,7 @@ class CefMediaAccessQuery {
return stream_devices_set;
}

CefRefPtr<CefBrowserHostBase> browser_;
content::MediaStreamRequest request_;
CallbackType callback_;
};
Expand Down Expand Up @@ -281,7 +299,7 @@ void RequestMediaAccessPermission(CefBrowserHostBase* browser,
content::MediaResponseCallback callback) {
CEF_REQUIRE_UIT();

CefMediaAccessQuery query(request, std::move(callback));
CefMediaAccessQuery query(browser, request, std::move(callback));

if (CheckCommandLinePermission()) {
// Allow all requested permissions.
Expand Down
108 changes: 108 additions & 0 deletions libcef/browser/media_stream_registrar.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// 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_stream_registrar.h"

#include "libcef/browser/browser_host_base.h"
#include "libcef/browser/thread_util.h"

class CefMediaStreamUI : public content::MediaStreamUI {
public:
CefMediaStreamUI(base::WeakPtr<CefMediaStreamRegistrar> registrar,
bool has_video,
bool has_audio)
: registrar_(registrar), has_video_(has_video), has_audio_(has_audio) {}

~CefMediaStreamUI() override {
if (registrar_) {
registrar_->UnregisterMediaStream(label_);
}
}

CefMediaStreamUI(const CefMediaStreamUI&) = delete;
CefMediaStreamUI& operator=(const CefMediaStreamUI&) = delete;

gfx::NativeViewId OnStarted(
base::RepeatingClosure stop,
SourceCallback source,
const std::string& label,
std::vector<content::DesktopMediaID> screen_capture_ids,
StateChangeCallback state_change) override {
if (registrar_) {
label_ = label;
registrar_->RegisterMediaStream(label, has_video_, has_audio_);
}
return 0;
}

void OnDeviceStoppedForSourceChange(
const std::string& label,
const content::DesktopMediaID& old_media_id,
const content::DesktopMediaID& new_media_id) override {}

void OnDeviceStopped(const std::string& label,
const content::DesktopMediaID& media_id) override {}

private:
base::WeakPtr<CefMediaStreamRegistrar> registrar_;
const bool has_video_;
const bool has_audio_;
std::string label_;
};

CefMediaStreamRegistrar::CefMediaStreamRegistrar(CefBrowserHostBase* browser)
: browser_(browser) {}

std::unique_ptr<content::MediaStreamUI>
CefMediaStreamRegistrar::MaybeCreateMediaStreamUI(bool has_video,
bool has_audio) const {
// Only create the object if the callback will be executed.
if (auto client = browser_->GetClient()) {
if (auto handler = client->GetDisplayHandler()) {
return std::make_unique<CefMediaStreamUI>(weak_ptr_factory_.GetWeakPtr(),
has_video, has_audio);
}
}
return nullptr;
}

void CefMediaStreamRegistrar::RegisterMediaStream(const std::string& label,
bool video,
bool audio) {
CEF_REQUIRE_UIT();
MediaStreamInfo info = {video, audio};
registered_streams_.insert(std::make_pair(label, info));
NotifyMediaStreamChange();
}

void CefMediaStreamRegistrar::UnregisterMediaStream(const std::string& label) {
CEF_REQUIRE_UIT();
registered_streams_.erase(label);
NotifyMediaStreamChange();
}

void CefMediaStreamRegistrar::NotifyMediaStreamChange() {
bool video = false;
bool audio = false;
for (const auto& media_stream : registered_streams_) {
const auto& info = media_stream.second;
if (!video)
video = info.video;
if (!audio)
audio = info.audio;
}

if (audio == last_notified_info_.audio &&
video == last_notified_info_.video) {
return;
}

last_notified_info_ = {video, audio};

if (auto client = browser_->GetClient()) {
if (auto handler = client->GetDisplayHandler()) {
handler->OnMediaAccessChange(browser_, video, audio);
}
}
}
56 changes: 56 additions & 0 deletions libcef/browser/media_stream_registrar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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_STREAM_REGISTRAR_H_
#define CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
#pragma once

#include <map>
#include <memory>
#include <string>

#include "base/memory/weak_ptr.h"
#include "content/public/browser/media_stream_request.h"

class CefBrowserHostBase;
class CefMediaStreamUI;

class CefMediaStreamRegistrar {
public:
explicit CefMediaStreamRegistrar(CefBrowserHostBase* browser);

CefMediaStreamRegistrar(const CefMediaStreamRegistrar&) = delete;
CefMediaStreamRegistrar& operator=(const CefMediaStreamRegistrar&) = delete;

std::unique_ptr<content::MediaStreamUI> MaybeCreateMediaStreamUI(
bool has_video,
bool has_audio) const;

private:
friend class CefMediaStreamUI;

// Called from CefMediaStreamUI.
void RegisterMediaStream(const std::string& label, bool video, bool audio);
void UnregisterMediaStream(const std::string& label);

void NotifyMediaStreamChange();

// Guaranteed to outlive this object.
CefBrowserHostBase* const browser_;

struct MediaStreamInfo {
bool video;
bool audio;
};

// Current in use media streams.
std::map<std::string, MediaStreamInfo> registered_streams_;

// Last notified media stream info.
MediaStreamInfo last_notified_info_{};

base::WeakPtrFactory<CefMediaStreamRegistrar> weak_ptr_factory_{this};
};

#endif // CEF_LIBCEF_BROWSER_MEDIA_STREAM_REGISTRAR_H_
Loading

0 comments on commit 521546d

Please sign in to comment.