Bug 1112392: Move webrtc Tab Sharing to work in e10s/fission r=dminor

Also we drop support for an independent-of-scroll/viewport capture, which
the old Tab Sharing supported, for security reasons (and we don't need it).

Differential Revision: https://phabricator.services.mozilla.com/D80974
This commit is contained in:
Randell Jesup 2020-07-10 01:00:51 +00:00
Родитель 95a2e8ea4c
Коммит 9756342857
17 изменённых файлов: 695 добавлений и 574 удалений

Просмотреть файл

@ -5,7 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoEngine.h"
#include "video_engine/browser_capture_impl.h"
#include "video_engine/desktop_capture_impl.h"
#include "webrtc/system_wrappers/include/clock.h"
#ifdef WEBRTC_ANDROID
@ -183,13 +182,8 @@ VideoEngine::GetOrCreateVideoCaptureDeviceInfo() {
LOG(("webrtc::CaptureDeviceType::Camera: Finished creating new device."));
break;
}
case webrtc::CaptureDeviceType::Browser: {
mDeviceInfo.reset(webrtc::BrowserDeviceInfoImpl::CreateDeviceInfo());
LOG((
"webrtc::CaptureDeviceType::Browser: Finished creating new device."));
break;
}
// Window and Screen types are handled by DesktopCapture
// Window and Screen and Browser (tab) types are handled by DesktopCapture
case webrtc::CaptureDeviceType::Browser:
case webrtc::CaptureDeviceType::Window:
case webrtc::CaptureDeviceType::Screen: {
#if !defined(WEBRTC_ANDROID) && !defined(WEBRTC_IOS)

Просмотреть файл

@ -45,6 +45,7 @@ if CONFIG['MOZ_WEBRTC']:
UNIFIED_SOURCES += [
'video_engine/desktop_capture_impl.cc',
'video_engine/platform_uithread.cc',
'video_engine/tab_capturer.cc',
]

Просмотреть файл

@ -299,6 +299,86 @@ int32_t WindowDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
return 0;
}
int32_t BrowserDeviceInfoImpl::Init() {
desktop_device_info_ =
std::unique_ptr<DesktopDeviceInfo>(DesktopDeviceInfoImpl::Create());
return 0;
}
int32_t BrowserDeviceInfoImpl::Refresh() {
desktop_device_info_->Refresh();
return 0;
}
uint32_t BrowserDeviceInfoImpl::NumberOfDevices() {
return desktop_device_info_->getTabCount();
}
int32_t BrowserDeviceInfoImpl::GetDeviceName(
uint32_t deviceNumber, char* deviceNameUTF8, uint32_t deviceNameUTF8Size,
char* deviceUniqueIdUTF8, uint32_t deviceUniqueIdUTF8Size,
char* productUniqueIdUTF8, uint32_t productUniqueIdUTF8Size, pid_t* pid) {
DesktopTab desktopTab;
// always initialize output
if (deviceNameUTF8 && deviceNameUTF8Size > 0) {
memset(deviceNameUTF8, 0, deviceNameUTF8Size);
}
if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Size > 0) {
memset(deviceUniqueIdUTF8, 0, deviceUniqueIdUTF8Size);
}
if (productUniqueIdUTF8 && productUniqueIdUTF8Size > 0) {
memset(productUniqueIdUTF8, 0, productUniqueIdUTF8Size);
}
if (desktop_device_info_->getTabInfo(deviceNumber, desktopTab) == 0) {
size_t len;
const char* deviceName = desktopTab.getTabName();
len = deviceName ? strlen(deviceName) : 0;
if (len && deviceNameUTF8 && len < deviceNameUTF8Size) {
memcpy(deviceNameUTF8, deviceName, len);
}
const char* deviceUniqueId = desktopTab.getUniqueIdName();
len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
if (len && deviceUniqueIdUTF8 && len < deviceUniqueIdUTF8Size) {
memcpy(deviceUniqueIdUTF8, deviceUniqueId, len);
}
}
return 0;
}
int32_t BrowserDeviceInfoImpl::DisplayCaptureSettingsDialogBox(
const char* deviceUniqueIdUTF8, const char* dialogTitleUTF8,
void* parentWindow, uint32_t positionX, uint32_t positionY) {
// no device properties to change
return 0;
}
int32_t BrowserDeviceInfoImpl::NumberOfCapabilities(
const char* deviceUniqueIdUTF8) {
return 0;
}
int32_t BrowserDeviceInfoImpl::GetCapability(
const char* deviceUniqueIdUTF8, const uint32_t deviceCapabilityNumber,
VideoCaptureCapability& capability) {
return 0;
}
int32_t BrowserDeviceInfoImpl::GetBestMatchedCapability(
const char* deviceUniqueIdUTF8, const VideoCaptureCapability& requested,
VideoCaptureCapability& resulting) {
return 0;
}
int32_t BrowserDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
VideoRotation& orientation) {
return 0;
}
VideoCaptureModule::DeviceInfo* DesktopCaptureImpl::CreateDeviceInfo(
const int32_t id, const CaptureDeviceType type) {
if (type == CaptureDeviceType::Screen) {
@ -315,6 +395,14 @@ VideoCaptureModule::DeviceInfo* DesktopCaptureImpl::CreateDeviceInfo(
pWindowDeviceInfoImpl = NULL;
}
return pWindowDeviceInfoImpl;
} else if (type == CaptureDeviceType::Browser) {
BrowserDeviceInfoImpl* pBrowserDeviceInfoImpl =
new BrowserDeviceInfoImpl(id);
if (!pBrowserDeviceInfoImpl || pBrowserDeviceInfoImpl->Init()) {
delete pBrowserDeviceInfoImpl;
pBrowserDeviceInfoImpl = NULL;
}
return pBrowserDeviceInfoImpl;
}
return NULL;
}
@ -364,8 +452,18 @@ int32_t DesktopCaptureImpl::Init() {
desktop_capturer_cursor_composer_ =
std::unique_ptr<DesktopAndCursorComposer>(new DesktopAndCursorComposer(
pWindowCapturer.release(), pMouseCursorMonitor));
}
} else if (_deviceType == CaptureDeviceType::Browser) {
// XXX We don't capture cursors, so avoid the extra indirection layer. We
// could also pass null for the pMouseCursorMonitor.
desktop_capturer_cursor_composer_ =
DesktopCapturer::CreateTabCapturer(options);
if (!desktop_capturer_cursor_composer_) {
return -1;
}
DesktopCapturer::SourceId sourceId = atoi(_deviceUniqueId.c_str());
desktop_capturer_cursor_composer_->SelectSource(sourceId);
}
return 0;
}
@ -387,6 +485,7 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t id, const char* uniqueId,
new rtc::PlatformUIThread(Run, this, "ScreenCaptureThread")),
#else
# if defined(WEBRTC_LINUX)
// We start the thread lazily for Linux
capturer_thread_(nullptr),
# else
capturer_thread_(
@ -394,8 +493,10 @@ DesktopCaptureImpl::DesktopCaptureImpl(const int32_t id, const char* uniqueId,
# endif
#endif
started_(false) {
//-> TODO @@NG why is this crashing (seen on Linux)
//-> capturer_thread_->SetPriority(rtc::kHighPriority);
#if !defined(WEBRTC_LINUX)
// XXX this crashes due to an immediate IsRunning() check on Linux
capturer_thread_->SetPriority(rtc::kHighPriority);
#endif
_requestedCapability.width = kDefaultWidth;
_requestedCapability.height = kDefaultHeight;
_requestedCapability.maxFPS = 30;
@ -582,6 +683,8 @@ int32_t DesktopCaptureImpl::StartCapture(
if (!capturer_thread_) {
capturer_thread_ = std::unique_ptr<rtc::PlatformThread>(
new rtc::PlatformThread(Run, this, "ScreenCaptureThread"));
// XXX this crashes due to an immediate IsRunning() check on Linux
// capturer_thread_->SetPriority(rtc::kHighPriority);
}
#endif

Просмотреть файл

@ -149,6 +149,41 @@ class WindowDeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
std::unique_ptr<DesktopDeviceInfo> desktop_device_info_;
};
class BrowserDeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
public:
BrowserDeviceInfoImpl(const int32_t id) : _id(id){};
virtual ~BrowserDeviceInfoImpl(void){};
int32_t Init();
int32_t Refresh();
virtual uint32_t NumberOfDevices();
virtual int32_t GetDeviceName(uint32_t deviceNumber, char* deviceNameUTF8,
uint32_t deviceNameLength,
char* deviceUniqueIdUTF8,
uint32_t deviceUniqueIdUTF8Length,
char* productUniqueIdUTF8,
uint32_t productUniqueIdUTF8Length, pid_t* pid);
virtual int32_t DisplayCaptureSettingsDialogBox(
const char* deviceUniqueIdUTF8, const char* dialogTitleUTF8,
void* parentWindow, uint32_t positionX, uint32_t positionY);
virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8);
virtual int32_t GetCapability(const char* deviceUniqueIdUTF8,
const uint32_t deviceCapabilityNumber,
VideoCaptureCapability& capability);
virtual int32_t GetBestMatchedCapability(
const char* deviceUniqueIdUTF8, const VideoCaptureCapability& requested,
VideoCaptureCapability& resulting);
virtual int32_t GetOrientation(const char* deviceUniqueIdUTF8,
VideoRotation& orientation);
protected:
int32_t _id;
std::unique_ptr<DesktopDeviceInfo> desktop_device_info_;
};
// Reuses the video engine pipeline for screen sharing.
// As with video, DesktopCaptureImpl is a proxy for screen sharing
// and follows the video pipeline design
@ -242,7 +277,7 @@ class DesktopCaptureImpl : public DesktopCapturer::Callback,
// This is created on the main thread and accessed on both the main thread
// and the capturer thread. It is created prior to the capturer thread
// starting and is destroyed after it is stopped.
std::unique_ptr<DesktopAndCursorComposer> desktop_capturer_cursor_composer_;
std::unique_ptr<DesktopCapturer> desktop_capturer_cursor_composer_;
std::unique_ptr<EventWrapper> time_event_;
#if defined(_WIN32)

Просмотреть файл

@ -0,0 +1,252 @@
/*
* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "tab_capturer.h"
#include <memory>
#include <string>
#include <utility>
#include "modules/desktop_capture/desktop_frame.h"
#include "mozilla/Logging.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/scoped_ref_ptr.h"
#include "nsThreadUtils.h"
#include "nsIDocShellTreeOwner.h"
#include "mozilla/dom/BrowserHost.h"
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/PromiseNativeHandler.h"
#include "mozilla/gfx/2D.h"
mozilla::LazyLogModule gTabShareLog("TabShare");
using namespace mozilla::dom;
// XXX switch once we have UI
#define NO_TABSHARE_UI 1
namespace mozilla {
TabCapturer::TabCapturer(const webrtc::DesktopCaptureOptions& options)
: mMonitor("TabCapture") {}
TabCapturer::~TabCapturer() {}
bool TabCapturer::GetSourceList(webrtc::DesktopCapturer::SourceList* sources) {
MOZ_LOG(gTabShareLog, LogLevel::Debug,
("TabShare: GetSourceList, result %lu", sources->size()));
// XXX UI
return true;
}
bool TabCapturer::SelectSource(webrtc::DesktopCapturer::SourceId id) {
MOZ_LOG(gTabShareLog, LogLevel::Debug, ("TabShare: source %ld", id));
mBrowserId = id;
return true;
}
bool TabCapturer::FocusOnSelectedSource() { return true; }
nsresult TabCapturer::StartRunnable::Run() {
MOZ_ASSERT(NS_IsMainThread());
// We use BrowserId to identify a tab since it's the only stable id; we
// need the top-level browserid for a tab.
#ifdef NO_TABSHARE_UI
// XXX Since we have no UI to feed us a browserid, grab "a" browserid for a
// tab. This is a temporary hack until we have UI (bug 1646597)
nsCOMPtr<nsPIDOMWindowOuter> chromeWindow =
nsContentUtils::GetMostRecentNonPBWindow();
if (!chromeWindow) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShell> docShell = chromeWindow->GetDocShell();
if (!docShell) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDocShellTreeOwner> owner;
docShell->GetTreeOwner(getter_AddRefs(owner));
if (!owner) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIRemoteTab> primaryRemoteTab;
owner->GetPrimaryRemoteTab(getter_AddRefs(primaryRemoteTab));
if (!primaryRemoteTab) {
return NS_ERROR_FAILURE;
}
RefPtr<BrowsingContext> context =
BrowserHost::GetFrom(primaryRemoteTab)->GetBrowsingContext();
if (!context) {
return NS_ERROR_FAILURE;
}
mVideoSource->mBrowserId = context->BrowserId();
#endif
MOZ_LOG(gTabShareLog, LogLevel::Debug,
("TabShare: Start, id=%ld", mVideoSource->mBrowserId));
mVideoSource->CaptureFrameNow();
return NS_OK;
}
void TabCapturer::Start(webrtc::DesktopCapturer::Callback* callback) {
RTC_DCHECK(!mCallback);
RTC_DCHECK(callback);
mCallback = callback;
NS_DispatchToMainThread(new StartRunnable(this));
}
// NOTE: this method is synchronous
void TabCapturer::CaptureFrame() {
MonitorAutoLock monitor(mMonitor);
NS_DispatchToMainThread(NS_NewRunnableFunction("TabCapturer: Capture a frame",
[self = RefPtr{this}] {
self->CaptureFrameNow();
// New frame will be returned
// via Promise callback on
// mThread
}));
// mCallback may not be valid if we don't make this call synchronous;
// especially since CaptureFrameNow isn't a synchronous event
monitor.Wait();
}
bool TabCapturer::IsOccluded(const webrtc::DesktopVector& pos) { return false; }
class TabCapturedHandler final : public dom::PromiseNativeHandler {
public:
NS_DECL_ISUPPORTS
static void Create(dom::Promise* aPromise, TabCapturer* aEngine) {
MOZ_ASSERT(aPromise);
MOZ_ASSERT(NS_IsMainThread());
RefPtr<TabCapturedHandler> handler = new TabCapturedHandler(aEngine);
aPromise->AppendNativeHandler(handler);
}
void ResolvedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock monitor(mEngine->mMonitor);
if (NS_WARN_IF(!aValue.isObject())) {
monitor.Notify();
return;
}
RefPtr<dom::ImageBitmap> bitmap;
if (NS_WARN_IF(NS_FAILED(
UNWRAP_OBJECT(ImageBitmap, &aValue.toObject(), bitmap)))) {
monitor.Notify();
return;
}
mEngine->OnFrame(bitmap);
mEngine->mCapturing = false;
// We no longer will touch mCallback from MainThread for this frame
monitor.Notify();
}
void RejectedCallback(JSContext* aCx, JS::Handle<JS::Value> aValue) override {
MOZ_ASSERT(NS_IsMainThread());
MonitorAutoLock monitor(mEngine->mMonitor);
mEngine->mCapturing = false;
monitor.Notify();
}
private:
explicit TabCapturedHandler(TabCapturer* aEngine) : mEngine(aEngine) {
MOZ_ASSERT(aEngine);
}
~TabCapturedHandler() = default;
RefPtr<TabCapturer> mEngine;
};
NS_IMPL_ISUPPORTS0(TabCapturedHandler)
void TabCapturer::CaptureFrameNow() {
MOZ_ASSERT(NS_IsMainThread());
MOZ_LOG(gTabShareLog, LogLevel::Debug, ("TabShare: CaptureFrameNow"));
// Ensure we clean up on failures
auto autoFailureCallback = MakeScopeExit([&] {
MonitorAutoLock monitor(mMonitor);
mCallback->OnCaptureResult(webrtc::DesktopCapturer::Result::ERROR_TEMPORARY,
nullptr);
monitor.Notify();
});
WindowGlobalParent* wgp = nullptr;
if (mBrowserId != 0) {
RefPtr<BrowsingContext> context =
BrowsingContext::GetCurrentTopByBrowserId(mBrowserId);
if (context) {
wgp = context->Canonical()->GetCurrentWindowGlobal();
}
// If we can't access the window, we just won't capture anything
}
if (!wgp) {
return;
}
if (!mCapturing) {
// XXX This would be more efficient if it returned a MozPromise, and
// even more if we used CrossProcessPaint directly and returned a surface.
RefPtr<dom::Promise> promise = wgp->DrawSnapshot(
nullptr, 1.0, "white"_ns, IgnoreErrors());
if (!promise) {
return;
}
mCapturing = true;
TabCapturedHandler::Create(promise, this);
}
// else we haven't finished the previous capture
autoFailureCallback.release();
}
void TabCapturer::OnFrame(dom::ImageBitmap* aBitmap) {
MOZ_ASSERT(NS_IsMainThread());
mMonitor.AssertCurrentThreadOwns();
UniquePtr<dom::ImageBitmapCloneData> data = aBitmap->ToCloneData();
webrtc::DesktopSize size(data->mPictureRect.Width(),
data->mPictureRect.Height());
webrtc::DesktopRect rect = webrtc::DesktopRect::MakeSize(size);
std::unique_ptr<webrtc::DesktopFrame> frame(
new webrtc::BasicDesktopFrame(size));
gfx::DataSourceSurface::ScopedMap map(data->mSurface,
gfx::DataSourceSurface::READ);
if (!map.IsMapped()) {
mCallback->OnCaptureResult(webrtc::DesktopCapturer::Result::ERROR_TEMPORARY,
nullptr);
return;
}
frame->CopyPixelsFrom(map.GetData(), map.GetStride(), rect);
mCallback->OnCaptureResult(webrtc::DesktopCapturer::Result::SUCCESS,
std::move(frame));
}
} // namespace mozilla
namespace webrtc {
// static
std::unique_ptr<webrtc::DesktopCapturer>
webrtc::DesktopCapturer::CreateRawTabCapturer(
const webrtc::DesktopCaptureOptions& options) {
return std::unique_ptr<webrtc::DesktopCapturer>(
new mozilla::TabCapturerWebrtc(options));
}
} // namespace webrtc

Просмотреть файл

@ -0,0 +1,112 @@
/*
* Copyright 2018 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_DESKTOP_CAPTURE_TAB_CAPTURER_H_
#define MODULES_DESKTOP_CAPTURE_TAB_CAPTURER_H_
#include <memory>
#include <string>
#include "modules/desktop_capture/desktop_capture_options.h"
#include "modules/desktop_capture/desktop_capturer.h"
#include "rtc_base/constructormagic.h"
#include "nsITabSource.h"
#include "nsThreadUtils.h"
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/Monitor.h"
namespace mozilla {
class TabCapturedHandler;
class TabCapturer {
private:
~TabCapturer();
public:
friend class TabCapturedHandler;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TabCapturer)
explicit TabCapturer(const webrtc::DesktopCaptureOptions& options);
static std::unique_ptr<webrtc::DesktopCapturer> CreateRawWindowCapturer(
const webrtc::DesktopCaptureOptions& options);
// support for DesktopCapturer interface.
void Start(webrtc::DesktopCapturer::Callback* callback);
void CaptureFrame();
bool GetSourceList(webrtc::DesktopCapturer::SourceList* sources);
bool SelectSource(webrtc::DesktopCapturer::SourceId id);
bool FocusOnSelectedSource();
bool IsOccluded(const webrtc::DesktopVector& pos);
// Capture code
void CaptureFrameNow();
void OnFrame(dom::ImageBitmap* aBitmap);
class StartRunnable : public Runnable {
public:
explicit StartRunnable(TabCapturer* videoSource)
: Runnable("TabCapturer::StartRunnable"), mVideoSource(videoSource) {}
NS_IMETHOD Run() override;
const RefPtr<TabCapturer> mVideoSource;
};
private:
// Used to protect mCallback, since TabCapturer's lifetime might be
// longer than mCallback's on stop/shutdown, and we may be waiting on a
// tab to finish capturing on MainThread.
Monitor mMonitor;
webrtc::DesktopCapturer::Callback* mCallback = nullptr;
uint64_t mBrowserId = 0;
bool mCapturing = false;
RTC_DISALLOW_COPY_AND_ASSIGN(TabCapturer);
};
// Warning: webrtc capture wants this in a uniqueptr, but it greatly eases
// things for us if it's a refcounted object (so we can pass it around to
// Dispatch/etc). Solve this by having a DesktopCapturer that just holds the
// refcounted TabCapturer.
// XXX This is a little ugly; we could decompose into front-end (webrtc)
// and backend (refcounted), but that doesn't actually make things a lot better.
class TabCapturerWebrtc : public webrtc::DesktopCapturer {
public:
explicit TabCapturerWebrtc(const webrtc::DesktopCaptureOptions& options) {
mInternal = new TabCapturer(options);
}
~TabCapturerWebrtc() override {}
// DesktopCapturer interface.
void Start(Callback* callback) override { mInternal->Start(callback); }
void CaptureFrame() override { mInternal->CaptureFrame(); }
bool GetSourceList(SourceList* sources) override {
return mInternal->GetSourceList(sources);
}
bool SelectSource(SourceId id) override {
return mInternal->SelectSource(id);
}
bool FocusOnSelectedSource() override {
return mInternal->FocusOnSelectedSource();
}
bool IsOccluded(const webrtc::DesktopVector& pos) override {
return mInternal->IsOccluded(pos);
}
private:
RefPtr<TabCapturer> mInternal;
};
} // namespace mozilla
#endif // MODULES_DESKTOP_CAPTURE_TAB_CAPTURER_H_

Просмотреть файл

@ -1,403 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaEngineTabVideoSource.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/DataSurfaceHelpers.h"
#include "mozilla/layers/SharedRGBImage.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/PresShell.h"
#include "mozilla/RefPtr.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "nsGlobalWindow.h"
#include "nsIDocShell.h"
#include "nsPresContext.h"
#include "gfxContext.h"
#include "gfx2DGlue.h"
#include "ImageContainer.h"
#include "Layers.h"
#include "nsIInterfaceRequestorUtils.h"
#include "VideoUtils.h"
#include "nsServiceManagerUtils.h"
#include "MediaTrackConstraints.h"
#include "Tracing.h"
namespace mozilla {
using namespace mozilla::gfx;
MediaEngineTabVideoSource::MediaEngineTabVideoSource()
: mSettings(MakeAndAddRef<media::Refcountable<MediaTrackSettings>>()) {}
nsresult MediaEngineTabVideoSource::StartRunnable::Run() {
MOZ_ASSERT(NS_IsMainThread());
if (mVideoSource->mWindowId != -1) {
nsGlobalWindowOuter* globalWindow =
nsGlobalWindowOuter::GetOuterWindowWithId(mVideoSource->mWindowId);
if (!globalWindow) {
// We can't access the window, just send a blacked out screen.
mVideoSource->mWindow = nullptr;
mVideoSource->mBlackedoutWindow = true;
} else {
mVideoSource->mWindow = globalWindow;
mVideoSource->mBlackedoutWindow = false;
}
}
if (!mVideoSource->mWindow && !mVideoSource->mBlackedoutWindow) {
nsresult rv;
mVideoSource->mTabSource =
do_GetService(NS_TABSOURCESERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIDOMWindowProxy> win;
rv = mVideoSource->mTabSource->GetTabToStream(getter_AddRefs(win));
NS_ENSURE_SUCCESS(rv, rv);
if (!win) {
return NS_OK;
}
mVideoSource->mWindow = nsPIDOMWindowOuter::From(win);
MOZ_ASSERT(mVideoSource->mWindow);
}
mVideoSource->mTimer = NS_NewTimer();
mVideoSource->mTrackMain = mTrack;
mVideoSource->mPrincipalHandleMain = mPrincipal;
mVideoSource->Draw();
mVideoSource->mTimer->InitWithNamedFuncCallback(
[](nsITimer* aTimer, void* aClosure) mutable {
auto source = static_cast<MediaEngineTabVideoSource*>(aClosure);
source->Draw();
},
mVideoSource, mVideoSource->mTimePerFrame, nsITimer::TYPE_REPEATING_SLACK,
"MediaEngineTabVideoSource DrawTimer");
if (mVideoSource->mTabSource) {
mVideoSource->mTabSource->NotifyStreamStart(mVideoSource->mWindow);
}
return NS_OK;
}
nsresult MediaEngineTabVideoSource::StopRunnable::Run() {
MOZ_ASSERT(NS_IsMainThread());
if (mVideoSource->mTimer) {
mVideoSource->mTimer->Cancel();
mVideoSource->mTimer = nullptr;
}
if (mVideoSource->mTabSource) {
mVideoSource->mTabSource->NotifyStreamStop(mVideoSource->mWindow);
}
return NS_OK;
}
nsresult MediaEngineTabVideoSource::DestroyRunnable::Run() {
MOZ_ASSERT(NS_IsMainThread());
mVideoSource->mWindow = nullptr;
mVideoSource->mTabSource = nullptr;
if (mVideoSource->mTrackMain) {
mVideoSource->mTrackMain->End();
}
mVideoSource->mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
mVideoSource->mTrackMain = nullptr;
return NS_OK;
}
nsString MediaEngineTabVideoSource::GetName() const {
return u"&getUserMedia.videoSource.tabShare;"_ns;
}
nsCString MediaEngineTabVideoSource::GetUUID() const { return "tab"_ns; }
nsString MediaEngineTabVideoSource::GetGroupId() const {
return u"&getUserMedia.videoSource.tabShareGroup;"_ns;
}
#define DEFAULT_TABSHARE_VIDEO_MAX_WIDTH 4096
#define DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT 4096
#define DEFAULT_TABSHARE_VIDEO_FRAMERATE 30
nsresult MediaEngineTabVideoSource::Allocate(
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs, uint64_t aWindowID,
const char** aOutBadConstraint) {
AssertIsOnOwningThread();
// windowId is not a proper constraint, so just read it.
// It has no well-defined behavior in advanced, so ignore it there.
int64_t windowId = aConstraints.mBrowserWindow.WasPassed()
? aConstraints.mBrowserWindow.Value()
: -1;
NS_DispatchToMainThread(NS_NewRunnableFunction(
"MediaEngineTabVideoSource::Allocate window id main thread setter",
[self = RefPtr<MediaEngineTabVideoSource>(this), this, windowId] {
mWindowId = windowId;
}));
mState = kAllocated;
return Reconfigure(aConstraints, aPrefs, aOutBadConstraint);
}
nsresult MediaEngineTabVideoSource::Reconfigure(
const dom::MediaTrackConstraints& aConstraints,
const mozilla::MediaEnginePrefs& aPrefs, const char** aOutBadConstraint) {
AssertIsOnOwningThread();
MOZ_ASSERT(mState != kReleased);
// scrollWithPage is not proper a constraint, so just read it.
// It has no well-defined behavior in advanced, so ignore it there.
const bool scrollWithPage = aConstraints.mScrollWithPage.WasPassed()
? aConstraints.mScrollWithPage.Value()
: false;
FlattenedConstraints c(aConstraints);
const int32_t bufWidthMax = c.mWidth.Get(DEFAULT_TABSHARE_VIDEO_MAX_WIDTH);
const int32_t bufHeightMax = c.mHeight.Get(DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT);
const double frameRate = c.mFrameRate.Get(DEFAULT_TABSHARE_VIDEO_FRAMERATE);
const int32_t timePerFrame =
std::max(10, int(1000.0 / (frameRate > 0 ? frameRate : 1)));
Maybe<int32_t> viewportOffsetX;
Maybe<int32_t> viewportOffsetY;
Maybe<int32_t> viewportWidth;
Maybe<int32_t> viewportHeight;
if (!scrollWithPage) {
viewportOffsetX = Some(c.mViewportOffsetX.Get(0));
viewportOffsetY = Some(c.mViewportOffsetY.Get(0));
viewportWidth = Some(c.mViewportWidth.Get(INT32_MAX));
viewportHeight = Some(c.mViewportHeight.Get(INT32_MAX));
}
NS_DispatchToMainThread(NS_NewRunnableFunction(
"MediaEngineTabVideoSource::Reconfigure main thread setter",
[self = RefPtr<MediaEngineTabVideoSource>(this), this, scrollWithPage,
bufWidthMax, bufHeightMax, frameRate, timePerFrame, viewportOffsetX,
viewportOffsetY, viewportWidth, viewportHeight]() {
mScrollWithPage = scrollWithPage;
mBufWidthMax = bufWidthMax;
mBufHeightMax = bufHeightMax;
mTimePerFrame = timePerFrame;
*mSettings = MediaTrackSettings();
mSettings->mScrollWithPage.Construct(scrollWithPage);
mSettings->mWidth.Construct(bufWidthMax);
mSettings->mHeight.Construct(bufHeightMax);
mSettings->mFrameRate.Construct(frameRate);
if (viewportOffsetX.isSome()) {
mSettings->mViewportOffsetX.Construct(*viewportOffsetX);
mViewportOffsetX = *viewportOffsetX;
}
if (viewportOffsetY.isSome()) {
mSettings->mViewportOffsetY.Construct(*viewportOffsetY);
mViewportOffsetY = *viewportOffsetY;
}
if (viewportWidth.isSome()) {
mSettings->mViewportWidth.Construct(*viewportWidth);
mViewportWidth = *viewportWidth;
}
if (viewportHeight.isSome()) {
mSettings->mViewportHeight.Construct(*viewportHeight);
mViewportHeight = *viewportHeight;
}
if (mWindowId != -1) {
mSettings->mBrowserWindow.Construct(mWindowId);
}
}));
return NS_OK;
}
nsresult MediaEngineTabVideoSource::Deallocate() {
AssertIsOnOwningThread();
MOZ_ASSERT(mState == kAllocated || mState == kStopped);
NS_DispatchToMainThread(do_AddRef(new DestroyRunnable(this)));
mState = kReleased;
return NS_OK;
}
void MediaEngineTabVideoSource::SetTrack(
const RefPtr<SourceMediaTrack>& aTrack,
const mozilla::PrincipalHandle& aPrincipal) {
AssertIsOnOwningThread();
MOZ_ASSERT(mState == kAllocated);
MOZ_ASSERT(!mTrack);
MOZ_ASSERT(aTrack);
mTrack = aTrack;
mPrincipalHandle = aPrincipal;
}
nsresult MediaEngineTabVideoSource::Start() {
AssertIsOnOwningThread();
MOZ_ASSERT(mState == kAllocated);
NS_DispatchToMainThread(new StartRunnable(this, mTrack, mPrincipalHandle));
mState = kStarted;
return NS_OK;
}
void MediaEngineTabVideoSource::Draw() {
MOZ_ASSERT(NS_IsMainThread());
if (!mWindow && !mBlackedoutWindow) {
return;
}
if (!mTrackMain || mTrackMain->IsDestroyed()) {
// The track is already gone or destroyed by MediaManager. This can happen
// because stopping the draw timer is async.
return;
}
if (mWindow) {
if (mScrollWithPage || mViewportWidth == INT32_MAX) {
mWindow->GetInnerWidth(&mViewportWidth);
}
if (mScrollWithPage || mViewportHeight == INT32_MAX) {
mWindow->GetInnerHeight(&mViewportHeight);
}
if (!mViewportWidth || !mViewportHeight) {
return;
}
} else {
mViewportWidth = 640;
mViewportHeight = 480;
}
IntSize size;
{
float pixelRatio;
if (mWindow) {
pixelRatio = mWindow->GetDevicePixelRatio(dom::CallerType::System);
} else {
pixelRatio = 1.0f;
}
const int32_t deviceWidth = (int32_t)(pixelRatio * mViewportWidth);
const int32_t deviceHeight = (int32_t)(pixelRatio * mViewportHeight);
if ((deviceWidth <= mBufWidthMax) && (deviceHeight <= mBufHeightMax)) {
size = IntSize(deviceWidth, deviceHeight);
} else {
const float scaleWidth = (float)mBufWidthMax / (float)deviceWidth;
const float scaleHeight = (float)mBufHeightMax / (float)deviceHeight;
const float scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight;
size = IntSize((int)(scale * deviceWidth), (int)(scale * deviceHeight));
}
}
RefPtr<PresShell> presShell;
if (mWindow) {
nsIDocShell* docshell = mWindow->GetDocShell();
if (docshell) {
presShell = docshell->GetPresShell();
}
if (!presShell) {
return;
}
}
if (!mImageContainer) {
mImageContainer = layers::LayerManager::CreateImageContainer(
layers::ImageContainer::ASYNCHRONOUS);
}
RefPtr<layers::SharedRGBImage> rgbImage =
mImageContainer->CreateSharedRGBImage();
if (!rgbImage) {
NS_WARNING("Failed to create SharedRGBImage");
return;
}
if (!rgbImage->Allocate(size, SurfaceFormat::B8G8R8X8)) {
NS_WARNING("Failed to allocate a shared image");
return;
}
RefPtr<layers::TextureClient> texture =
rgbImage->GetTextureClient(/* aKnowsCompositor */ nullptr);
if (!texture) {
NS_WARNING("Failed to allocate TextureClient");
return;
}
{
layers::TextureClientAutoLock autoLock(texture,
layers::OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
NS_WARNING("Failed to lock TextureClient");
return;
}
RefPtr<gfx::DrawTarget> dt = texture->BorrowDrawTarget();
if (!dt || !dt->IsValid()) {
NS_WARNING("Failed to borrow DrawTarget");
return;
}
if (mWindow) {
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(context); // already checked the draw target above
context->SetMatrix(context->CurrentMatrix().PreScale(
(((float)size.width) / mViewportWidth),
(((float)size.height) / mViewportHeight)));
nscolor bgColor = NS_RGB(255, 255, 255);
RenderDocumentFlags renderDocFlags =
mScrollWithPage ? RenderDocumentFlags::None
: (RenderDocumentFlags::IgnoreViewportScrolling |
RenderDocumentFlags::DocumentRelative);
nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
NS_ENSURE_SUCCESS_VOID(
presShell->RenderDocument(r, renderDocFlags, bgColor, context));
} else {
dt->ClearRect(Rect(0, 0, size.width, size.height));
}
}
VideoSegment segment;
segment.AppendFrame(do_AddRef(rgbImage), size, mPrincipalHandle);
mTrackMain->AppendData(&segment);
}
nsresult MediaEngineTabVideoSource::FocusOnSelectedSource() {
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult MediaEngineTabVideoSource::Stop() {
AssertIsOnOwningThread();
if (mState == kStopped || mState == kAllocated) {
return NS_OK;
}
MOZ_ASSERT(mState == kStarted);
// If mBlackedoutWindow is true, we may be running
// despite mWindow == nullptr.
if (!mWindow && !mBlackedoutWindow) {
return NS_OK;
}
NS_DispatchToMainThread(new StopRunnable(this));
mState = kStopped;
return NS_OK;
}
void MediaEngineTabVideoSource::GetSettings(
MediaTrackSettings& aOutSettings) const {
MOZ_ASSERT(NS_IsMainThread());
aOutSettings = *mSettings;
}
} // namespace mozilla

Просмотреть файл

@ -1,117 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MediaEngine.h"
#include "ImageContainer.h"
#include "nsITimer.h"
#include "mozilla/Mutex.h"
#include "mozilla/UniquePtr.h"
#include "nsITabSource.h"
namespace mozilla {
namespace layers {
class ImageContainer;
}
class MediaEngineTabVideoSource : public MediaEngineSource {
public:
MediaEngineTabVideoSource();
nsString GetName() const override;
nsCString GetUUID() const override;
nsString GetGroupId() const override;
bool GetScary() const override { return true; }
dom::MediaSourceEnum GetMediaSource() const override {
return dom::MediaSourceEnum::Browser;
}
nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs, uint64_t aWindowID,
const char** aOutBadConstraint) override;
nsresult Deallocate() override;
void SetTrack(const RefPtr<SourceMediaTrack>& aTrack,
const PrincipalHandle& aPrincipal) override;
nsresult Start() override;
nsresult Reconfigure(const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const char** aOutBadConstraint) override;
nsresult FocusOnSelectedSource() override;
nsresult Stop() override;
void GetSettings(dom::MediaTrackSettings& aOutSettings) const override;
void Draw();
class StartRunnable : public Runnable {
public:
StartRunnable(MediaEngineTabVideoSource* videoSource,
SourceMediaTrack* aTrack, const PrincipalHandle& aPrincipal)
: Runnable("MediaEngineTabVideoSource::StartRunnable"),
mVideoSource(videoSource),
mTrack(aTrack),
mPrincipal(aPrincipal) {}
NS_IMETHOD Run() override;
const RefPtr<MediaEngineTabVideoSource> mVideoSource;
const RefPtr<SourceMediaTrack> mTrack;
const PrincipalHandle mPrincipal;
};
class StopRunnable : public Runnable {
public:
explicit StopRunnable(MediaEngineTabVideoSource* videoSource)
: Runnable("MediaEngineTabVideoSource::StopRunnable"),
mVideoSource(videoSource) {}
NS_IMETHOD Run() override;
const RefPtr<MediaEngineTabVideoSource> mVideoSource;
};
class DestroyRunnable : public Runnable {
public:
explicit DestroyRunnable(MediaEngineTabVideoSource* videoSource)
: Runnable("MediaEngineTabVideoSource::DestroyRunnable"),
mVideoSource(videoSource) {}
NS_IMETHOD Run() override;
const RefPtr<MediaEngineTabVideoSource> mVideoSource;
};
protected:
~MediaEngineTabVideoSource() = default;
private:
// These are accessed only on main thread.
int32_t mBufWidthMax = 0;
int32_t mBufHeightMax = 0;
int64_t mWindowId = 0;
bool mScrollWithPage = false;
int32_t mViewportOffsetX = 0;
int32_t mViewportOffsetY = 0;
int32_t mViewportWidth = 0;
int32_t mViewportHeight = 0;
int32_t mTimePerFrame = 0;
RefPtr<layers::ImageContainer> mImageContainer;
// The current settings of this source.
// Members are main thread only.
const RefPtr<media::Refcountable<dom::MediaTrackSettings>> mSettings;
// Main thread only.
nsCOMPtr<nsPIDOMWindowOuter> mWindow;
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsITabSource> mTabSource;
RefPtr<SourceMediaTrack> mTrackMain;
PrincipalHandle mPrincipalHandleMain = PRINCIPAL_HANDLE_NONE;
// If this is set, we will run despite mWindow == nullptr.
bool mBlackedoutWindow = false;
// Current state of this source. Accessed on owning thread only.
MediaEngineSourceState mState = kReleased;
// mTrack is set in SetTrack() to keep track of what to end in Deallocate().
// Owning thread only.
RefPtr<SourceMediaTrack> mTrack;
PrincipalHandle mPrincipalHandle = PRINCIPAL_HANDLE_NONE;
};
} // namespace mozilla

Просмотреть файл

@ -8,7 +8,6 @@
#include "CamerasChild.h"
#include "CSFLog.h"
#include "MediaEngineTabVideoSource.h"
#include "MediaEngineRemoteVideoSource.h"
#include "MediaEngineWebRTCAudio.h"
#include "MediaManager.h"
@ -35,17 +34,9 @@ CubebDeviceEnumerator* GetEnumerator() {
MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs& aPrefs)
: mDelayAgnostic(aPrefs.mDelayAgnostic),
mExtendedFilter(aPrefs.mExtendedFilter),
mHasTabVideoSource(false) {
mExtendedFilter(aPrefs.mExtendedFilter) {
AssertIsOnOwningThread();
nsCOMPtr<nsIComponentRegistrar> compMgr;
NS_GetComponentRegistrar(getter_AddRefs(compMgr));
if (compMgr) {
compMgr->IsContractIDRegistered(NS_TABSOURCESERVICE_CONTRACTID,
&mHasTabVideoSource);
}
GetChildAndCall(
&CamerasChild::ConnectDeviceListChangeListener<MediaEngineWebRTC>,
&mCameraListChangeListener, AbstractThread::MainThread(), this,
@ -169,14 +160,6 @@ void MediaEngineWebRTC::EnumerateVideoDevices(
vSource, vSource->GetName(), NS_ConvertUTF8toUTF16(vSource->GetUUID()),
vSource->GetGroupId(), u""_ns));
}
if (mHasTabVideoSource || aCapEngine == camera::BrowserEngine) {
RefPtr<MediaEngineSource> tabVideoSource = new MediaEngineTabVideoSource();
aDevices->AppendElement(MakeRefPtr<MediaDevice>(
tabVideoSource, tabVideoSource->GetName(),
NS_ConvertUTF8toUTF16(tabVideoSource->GetUUID()),
tabVideoSource->GetGroupId(), u""_ns));
}
}
void MediaEngineWebRTC::EnumerateMicrophoneDevices(
@ -279,6 +262,7 @@ void MediaEngineWebRTC::EnumerateDevices(
// are still useful for testing.
EnumerateVideoDevices(aWindowId, camera::WinEngine, aDevices);
EnumerateVideoDevices(aWindowId, camera::ScreenEngine, aDevices);
EnumerateVideoDevices(aWindowId, camera::BrowserEngine, aDevices);
break;
case dom::MediaSourceEnum::Screen:
EnumerateVideoDevices(aWindowId, camera::ScreenEngine, aDevices);

Просмотреть файл

@ -227,7 +227,6 @@ class NormalizedConstraintSet {
StringRange mFacingMode;
StringRange mMediaSource;
LongLongRange mBrowserWindow;
BooleanRange mScrollWithPage;
StringRange mDeviceId;
StringRange mGroupId;
LongRange mViewportOffsetX, mViewportOffsetY, mViewportWidth, mViewportHeight;
@ -254,11 +253,6 @@ class NormalizedConstraintSet {
? aOther.mBrowserWindow.Value()
: 0,
aList),
mScrollWithPage(&T::mScrollWithPage, "scrollWithPage",
aOther.mScrollWithPage.WasPassed()
? aOther.mScrollWithPage.Value()
: false,
aList),
mDeviceId(&T::mDeviceId, "deviceId", aOther.mDeviceId, advanced, aList),
mGroupId(&T::mGroupId, "groupId", aOther.mGroupId, advanced, aList),
mViewportOffsetX(&T::mViewportOffsetX, "viewportOffsetX",

Просмотреть файл

@ -35,7 +35,6 @@ if CONFIG['MOZ_WEBRTC']:
EXPORTS.mozilla.dom += [ 'RTCIdentityProviderRegistrar.h' ]
UNIFIED_SOURCES += [
'MediaEngineRemoteVideoSource.cpp',
'MediaEngineTabVideoSource.cpp',
'MediaEngineWebRTCAudio.cpp',
'RTCCertificate.cpp',
'RTCIdentityProviderRegistrar.cpp',

Просмотреть файл

@ -60,6 +60,17 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateScreenCapturer(
return capturer;
}
// static
std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateTabCapturer(
const DesktopCaptureOptions& options) {
std::unique_ptr<DesktopCapturer> capturer = CreateRawTabCapturer(options);
if (capturer && options.detect_updated_region()) {
capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer)));
}
return capturer;
}
#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11)
bool DesktopCapturer::IsRunningUnderWayland() {
const char* xdg_session_type = getenv("XDG_SESSION_TYPE");

Просмотреть файл

@ -139,6 +139,10 @@ class DesktopCapturer {
static std::unique_ptr<DesktopCapturer> CreateAppCapturer(
const DesktopCaptureOptions& options);
// Creates a DesktopCapturer instance which targets to capture tab.
static std::unique_ptr<DesktopCapturer> CreateTabCapturer(
const DesktopCaptureOptions& options);
#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11)
static bool IsRunningUnderWayland();
#endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11)
@ -161,6 +165,10 @@ class DesktopCapturer {
// capture apps.
static std::unique_ptr<DesktopCapturer> CreateRawAppCapturer(
const DesktopCaptureOptions& options);
// Creates a DesktopCapturer instance which targets to capture tabs
static std::unique_ptr<DesktopCapturer> CreateRawTabCapturer(
const DesktopCaptureOptions& options);
};
} // namespace webrtc

Просмотреть файл

@ -170,6 +170,66 @@ DesktopApplication& DesktopApplication::operator= (DesktopApplication& other) {
return *this;
}
DesktopTab::DesktopTab() {
tabBrowserId_ = 0;
tabNameUTF8_= NULL;
tabUniqueIdUTF8_= NULL;
tabCount_ = 0;
}
DesktopTab::~DesktopTab() {
if (tabNameUTF8_) {
delete [] tabNameUTF8_;
}
if (tabUniqueIdUTF8_) {
delete [] tabUniqueIdUTF8_;
}
tabNameUTF8_= NULL;
tabUniqueIdUTF8_= NULL;
}
void DesktopTab::setTabBrowserId(uint64_t tabBrowserId) {
tabBrowserId_ = tabBrowserId;
}
void DesktopTab::setUniqueIdName(const char *tabUniqueIdUTF8) {
SetStringMember(&tabUniqueIdUTF8_, tabUniqueIdUTF8);
}
void DesktopTab::setTabName(const char *tabNameUTF8) {
SetStringMember(&tabNameUTF8_, tabNameUTF8);
}
void DesktopTab::setTabCount(const uint32_t count) {
tabCount_ = count;
}
uint64_t DesktopTab::getTabBrowserId() {
return tabBrowserId_;
}
const char *DesktopTab::getUniqueIdName() {
return tabUniqueIdUTF8_;
}
const char *DesktopTab::getTabName() {
return tabNameUTF8_;
}
uint32_t DesktopTab::getTabCount() {
return tabCount_;
}
DesktopTab& DesktopTab::operator= (DesktopTab& other) {
tabBrowserId_ = other.getTabBrowserId();
setUniqueIdName(other.getUniqueIdName());
setTabName(other.getTabName());
return *this;
}
DesktopDeviceInfoImpl::DesktopDeviceInfoImpl() {
}
@ -183,7 +243,7 @@ int32_t DesktopDeviceInfoImpl::getDisplayDeviceCount() {
int32_t DesktopDeviceInfoImpl::getDesktopDisplayDeviceInfo(int32_t nIndex,
DesktopDisplayDevice & desktopDisplayDevice) {
if(nIndex < 0 || nIndex >= desktop_display_list_.size()) {
if(nIndex < 0 || (size_t) nIndex >= desktop_display_list_.size()) {
return -1;
}
@ -202,7 +262,7 @@ int32_t DesktopDeviceInfoImpl::getWindowCount() {
}
int32_t DesktopDeviceInfoImpl::getWindowInfo(int32_t nIndex,
DesktopDisplayDevice &windowDevice) {
if (nIndex < 0 || nIndex >= desktop_window_list_.size()) {
if (nIndex < 0 || (size_t) nIndex >= desktop_window_list_.size()) {
return -1;
}
@ -223,7 +283,7 @@ int32_t DesktopDeviceInfoImpl::getApplicationCount() {
int32_t DesktopDeviceInfoImpl::getApplicationInfo(int32_t nIndex,
DesktopApplication & desktopApplication) {
if(nIndex < 0 || nIndex >= desktop_application_list_.size()) {
if(nIndex < 0 || (size_t) nIndex >= desktop_application_list_.size()) {
return -1;
}
@ -237,15 +297,37 @@ int32_t DesktopDeviceInfoImpl::getApplicationInfo(int32_t nIndex,
return 0;
}
int32_t DesktopDeviceInfoImpl::getTabCount() {
return desktop_tab_list_.size();
}
int32_t DesktopDeviceInfoImpl::getTabInfo(int32_t nIndex,
DesktopTab & desktopTab) {
if (nIndex < 0 || (size_t) nIndex >= desktop_tab_list_.size()) {
return -1;
}
std::map<intptr_t,DesktopTab*>::iterator iter = desktop_tab_list_.begin();
std::advance(iter, nIndex);
DesktopTab * pDesktopTab = iter->second;
if (pDesktopTab) {
desktopTab = (*pDesktopTab);
}
return 0;
}
void DesktopDeviceInfoImpl::CleanUp() {
CleanUpScreenList();
CleanUpWindowList();
CleanUpApplicationList();
CleanUpTabList();
}
int32_t DesktopDeviceInfoImpl::Init() {
InitializeScreenList();
InitializeWindowList();
InitializeApplicationList();
InitializeTabList();
return 0;
}
@ -253,6 +335,7 @@ int32_t DesktopDeviceInfoImpl::Refresh() {
RefreshScreenList();
RefreshWindowList();
RefreshApplicationList();
RefreshTabList();
return 0;
}
@ -311,6 +394,31 @@ void DesktopDeviceInfoImpl::RefreshApplicationList() {
InitializeApplicationList();
}
void DesktopDeviceInfoImpl::CleanUpTabList() {
for (auto &iterTab : desktop_tab_list_) {
DesktopTab *pDesktopTab = iterTab.second;
delete pDesktopTab;
iterTab.second = NULL;
}
desktop_tab_list_.clear();
}
void DesktopDeviceInfoImpl::DummyTabList(DesktopTabList &list) {
DesktopTab* desktop_tab = new DesktopTab;
if (desktop_tab) {
desktop_tab->setTabBrowserId(0);
desktop_tab->setTabName("dummy tab");
desktop_tab->setUniqueIdName("dummy tab 0");
desktop_tab->setTabCount(1);
list[desktop_tab->getTabBrowserId()] = desktop_tab;
}
}
void DesktopDeviceInfoImpl::RefreshTabList() {
CleanUpTabList();
InitializeTabList();
}
void DesktopDeviceInfoImpl::CleanUpScreenList() {
std::map<intptr_t,DesktopDisplayDevice*>::iterator iterDevice;
for (iterDevice=desktop_display_list_.begin(); iterDevice != desktop_display_list_.end(); iterDevice++){
@ -319,9 +427,11 @@ void DesktopDeviceInfoImpl::CleanUpScreenList() {
iterDevice->second = NULL;
}
desktop_display_list_.clear();
}
}
void DesktopDeviceInfoImpl::RefreshScreenList() {
CleanUpScreenList();
InitializeScreenList();
}
}

Просмотреть файл

@ -65,6 +65,32 @@ protected:
typedef std::map<intptr_t, DesktopApplication*> DesktopApplicationList;
class DesktopTab {
public:
DesktopTab();
~DesktopTab();
void setTabBrowserId(uint64_t tabBrowserId);
void setUniqueIdName(const char *tabUniqueIdUTF8);
void setTabName(const char *tabNameUTF8);
void setTabCount(const uint32_t count);
uint64_t getTabBrowserId();
const char *getUniqueIdName();
const char *getTabName();
uint32_t getTabCount();
DesktopTab& operator= (DesktopTab& other);
protected:
uint64_t tabBrowserId_;
char* tabNameUTF8_;
char* tabUniqueIdUTF8_;
uint32_t tabCount_;
};
typedef std::map<intptr_t, DesktopTab*> DesktopTabList;
class DesktopDeviceInfo {
public:
virtual ~DesktopDeviceInfo() {};
@ -80,6 +106,9 @@ public:
virtual int32_t getApplicationCount() = 0;
virtual int32_t getApplicationInfo(int32_t nIndex,
DesktopApplication & desktopApplication) = 0;
virtual int32_t getTabCount() = 0;
virtual int32_t getTabInfo(int32_t nIndex,
DesktopTab & desktopTab) = 0;
};
class DesktopDeviceInfoImpl : public DesktopDeviceInfo {
@ -87,37 +116,46 @@ public:
DesktopDeviceInfoImpl();
~DesktopDeviceInfoImpl();
virtual int32_t Init();
virtual int32_t Refresh();
virtual int32_t getDisplayDeviceCount();
virtual int32_t getDesktopDisplayDeviceInfo(int32_t nIndex,
DesktopDisplayDevice & desktopDisplayDevice);
virtual int32_t getWindowCount();
virtual int32_t getWindowInfo(int32_t nindex,
DesktopDisplayDevice &windowDevice);
virtual int32_t getApplicationCount();
virtual int32_t getApplicationInfo(int32_t nIndex,
DesktopApplication & desktopApplication);
int32_t Init() override;
int32_t Refresh() override;
int32_t getDisplayDeviceCount() override;
int32_t getDesktopDisplayDeviceInfo(int32_t nIndex,
DesktopDisplayDevice & desktopDisplayDevice) override;
int32_t getWindowCount() override;
int32_t getWindowInfo(int32_t nindex,
DesktopDisplayDevice &windowDevice) override;
int32_t getApplicationCount() override;
int32_t getApplicationInfo(int32_t nIndex,
DesktopApplication & desktopApplication) override;
int32_t getTabCount() override;
int32_t getTabInfo(int32_t nIndex,
DesktopTab & desktopTab) override;
static DesktopDeviceInfo * Create();
protected:
DesktopDisplayDeviceList desktop_display_list_;
DesktopDisplayDeviceList desktop_window_list_;
DesktopApplicationList desktop_application_list_;
DesktopTabList desktop_tab_list_;
void CleanUp();
void CleanUpWindowList();
void CleanUpApplicationList();
void CleanUpTabList();
void CleanUpScreenList();
void InitializeWindowList();
virtual void InitializeApplicationList() = 0;
virtual void InitializeTabList() {
DummyTabList(desktop_tab_list_);
}
virtual void InitializeScreenList() = 0;
void RefreshWindowList();
void RefreshApplicationList();
void RefreshTabList();
void RefreshScreenList();
void DummyTabList(DesktopTabList &list);
};
};

Просмотреть файл

@ -14,6 +14,7 @@ public:
protected:
virtual void InitializeScreenList();
virtual void InitializeApplicationList();
virtual void InitializeTabList();
};
DesktopDeviceInfo * DesktopDeviceInfoImpl::Create() {

Просмотреть файл

@ -133,5 +133,4 @@ void DesktopDeviceInfoX11::InitializeApplicationList() {
}
}
}
} //namespace webrtc