Commit 438f0541 authored by Erik Chen's avatar Erik Chen Committed by Commit Bot

Implement basic screen-sharing for lacros.

This CL creates a new mojo interface: ScreenManager. This interface has
a single method TakeScreenSnapshot which returns a bitmap of the
screen's contents. Lacros-chrome uses this interface to implement a
rudimentary version of screen-sharing. This in turn allows
meet.google.com screen sharing to function properly.

This interface will eventually be supplemented with methods to allow
window-sharing as well. The whole interface will likely be overhauled in
the future to create a more performant and fully-featured version of
screen/window sharing.

Change-Id: I821c59464ea4d2ff57665381038837f29645750d
Bug: 1094460
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2261430Reviewed-by: default avatarJorge Lucangeli Obes <jorgelo@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarHidehiko Abe <hidehiko@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Commit-Queue: Ken Rockot <rockot@google.com>
Auto-Submit: Erik Chen <erikchen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#786507}
parent 630c7ae4
......@@ -162,6 +162,7 @@ source_set("chromeos") {
"//chromeos/dbus/upstart",
"//chromeos/disks",
"//chromeos/geolocation",
"//chromeos/lacros/cpp",
"//chromeos/lacros/mojom",
"//chromeos/login/auth",
"//chromeos/login/login_state",
......@@ -1365,6 +1366,8 @@ source_set("chromeos") {
"lacros/lacros_manager.h",
"lacros/lacros_util.cc",
"lacros/lacros_util.h",
"lacros/screen_manager_crosapi.cc",
"lacros/screen_manager_crosapi.h",
"lacros/select_file_impl.cc",
"lacros/select_file_impl.h",
"language_preferences.cc",
......
......@@ -3,4 +3,8 @@ specific_include_rules = {
# For window parenting.
"+ash/shell.h",
],
"screen_manager_crosapi\.cc": [
# For window parenting.
"+ash/shell.h",
],
}
......@@ -7,12 +7,15 @@
#include <utility>
#include "base/logging.h"
#include "chrome/browser/chromeos/lacros/screen_manager_crosapi.h"
#include "chrome/browser/chromeos/lacros/select_file_impl.h"
#include "chromeos/lacros/mojom/screen_manager.mojom.h"
#include "chromeos/lacros/mojom/select_file.mojom.h"
AshChromeServiceImpl::AshChromeServiceImpl(
mojo::PendingReceiver<lacros::mojom::AshChromeService> pending_receiver)
: receiver_(this, std::move(pending_receiver)) {
: receiver_(this, std::move(pending_receiver)),
screen_manager_crosapi_(std::make_unique<ScreenManagerCrosapi>()) {
// TODO(hidehiko): Remove non-critical log from here.
// Currently this is the signal that the connection is established.
LOG(WARNING) << "AshChromeService connected.";
......@@ -24,3 +27,8 @@ void AshChromeServiceImpl::BindSelectFile(
mojo::PendingReceiver<lacros::mojom::SelectFile> receiver) {
select_file_impl_ = std::make_unique<SelectFileImpl>(std::move(receiver));
}
void AshChromeServiceImpl::BindScreenManager(
mojo::PendingReceiver<lacros::mojom::ScreenManager> receiver) {
screen_manager_crosapi_->BindReceiver(std::move(receiver));
}
......@@ -11,6 +11,8 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
class ScreenManagerCrosapi;
class SelectFileImpl;
// Implementation of AshChromeService. It provides a set of APIs that
......@@ -22,12 +24,15 @@ class AshChromeServiceImpl : public lacros::mojom::AshChromeService {
~AshChromeServiceImpl() override;
// lacros::mojom::AshChromeService:
void BindScreenManager(
mojo::PendingReceiver<lacros::mojom::ScreenManager> receiver) override;
void BindSelectFile(
mojo::PendingReceiver<lacros::mojom::SelectFile> receiver) override;
private:
mojo::Receiver<lacros::mojom::AshChromeService> receiver_;
std::unique_ptr<ScreenManagerCrosapi> screen_manager_crosapi_;
std::unique_ptr<SelectFileImpl> select_file_impl_;
};
......
// Copyright 2020 The Chromium 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 "chrome/browser/chromeos/lacros/screen_manager_crosapi.h"
#include <utility>
#include <vector>
#include "ash/shell.h"
#include "base/files/file_path.h"
#include "base/numerics/checked_math.h"
#include "base/numerics/safe_conversions.h"
#include "chromeos/lacros/cpp/window_snapshot.h"
#include "ui/snapshot/snapshot.h"
ScreenManagerCrosapi::ScreenManagerCrosapi() = default;
ScreenManagerCrosapi::~ScreenManagerCrosapi() = default;
void ScreenManagerCrosapi::BindReceiver(
mojo::PendingReceiver<lacros::mojom::ScreenManager> receiver) {
receivers_.Add(this, std::move(receiver));
}
void ScreenManagerCrosapi::TakeScreenSnapshot(
TakeScreenSnapshotCallback callback) {
// TODO(https://crbug.com/1094460): Handle display selection and multiple
// displays.
aura::Window* primary_window = ash::Shell::GetPrimaryRootWindow();
ui::GrabWindowSnapshotAsync(
primary_window, primary_window->bounds(),
base::BindOnce(&ScreenManagerCrosapi::DidTakeScreenSnapshot,
weak_factory_.GetWeakPtr(), std::move(callback)));
}
void ScreenManagerCrosapi::DidTakeScreenSnapshot(
TakeScreenSnapshotCallback callback,
gfx::Image image) {
SkBitmap bitmap = image.AsBitmap();
// This code currently relies on the assumption that the bitmap is unpadded,
// and uses 4 bytes per pixel.
int size;
size = base::CheckMul(bitmap.width(), bitmap.height()).ValueOrDie();
size = base::CheckMul(size, 4).ValueOrDie();
CHECK_EQ(bitmap.computeByteSize(), base::checked_cast<size_t>(size));
uint8_t* base = static_cast<uint8_t*>(bitmap.getPixels());
std::vector<uint8_t> bytes(base, base + bitmap.computeByteSize());
lacros::WindowSnapshot snapshot;
snapshot.width = bitmap.width();
snapshot.height = bitmap.height();
snapshot.bitmap.swap(bytes);
std::move(callback).Run(std::move(snapshot));
}
// Copyright 2020 The Chromium 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 CHROME_BROWSER_CHROMEOS_LACROS_SCREEN_MANAGER_CROSAPI_H_
#define CHROME_BROWSER_CHROMEOS_LACROS_SCREEN_MANAGER_CROSAPI_H_
#include "base/memory/weak_ptr.h"
#include "chromeos/lacros/mojom/screen_manager.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "ui/gfx/image/image.h"
// This class is the ash-chrome implementation of the ScreenManager interface.
// This class must only be used from the main thread.
class ScreenManagerCrosapi : public lacros::mojom::ScreenManager {
public:
ScreenManagerCrosapi();
ScreenManagerCrosapi(const ScreenManagerCrosapi&) = delete;
ScreenManagerCrosapi& operator=(const ScreenManagerCrosapi&) = delete;
~ScreenManagerCrosapi() override;
void BindReceiver(
mojo::PendingReceiver<lacros::mojom::ScreenManager> receiver);
// lacros::mojom::ScreenManager:
void TakeScreenSnapshot(TakeScreenSnapshotCallback callback) override;
private:
void DidTakeScreenSnapshot(TakeScreenSnapshotCallback callback,
gfx::Image image);
// This class supports any number of connections. This allows the client to
// have multiple, potentially thread-affine, remotes. This is needed by
// WebRTC.
mojo::ReceiverSet<lacros::mojom::ScreenManager> receivers_;
base::WeakPtrFactory<ScreenManagerCrosapi> weak_factory_{this};
};
#endif // CHROME_BROWSER_CHROMEOS_LACROS_SCREEN_MANAGER_CROSAPI_H_
......@@ -8,6 +8,7 @@
#include "ui/aura/client/aura_constants.h"
gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) {
// TODO(https://crbug.com/1094460): Hook up Window Icons for lacros.
DCHECK_EQ(content::DesktopMediaID::TYPE_WINDOW, id.type);
// TODO(tonikitoo): can we make the implementation of
// chrome/browser/media/webrtc/window_icon_util_chromeos.cc generic
......
......@@ -42,6 +42,11 @@ void LacrosChromeServiceImpl::BindReceiver(
receiver_.Bind(std::move(receiver));
}
void LacrosChromeServiceImpl::BindScreenManagerReceiver(
mojo::PendingReceiver<lacros::mojom::ScreenManager> pending_receiver) {
ash_chrome_service_->BindScreenManager(std::move(pending_receiver));
}
void LacrosChromeServiceImpl::RequestAshChromeServiceReceiver(
RequestAshChromeServiceReceiverCallback callback) {
// TODO(hidehiko): Remove non-error logging from here.
......
......@@ -7,6 +7,7 @@
#include "base/component_export.h"
#include "chromeos/lacros/mojom/lacros.mojom.h"
#include "chromeos/lacros/mojom/screen_manager.mojom.h"
#include "chromeos/lacros/mojom/select_file.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
......@@ -16,6 +17,7 @@ namespace chromeos {
// Implements LacrosChromeService, which owns the mojo remote connection to
// ash-chrome.
// This class is not thread safe. It can only be used on the main thread.
class COMPONENT_EXPORT(CHROMEOS_LACROS) LacrosChromeServiceImpl
: public lacros::mojom::LacrosChromeService {
public:
......@@ -31,6 +33,9 @@ class COMPONENT_EXPORT(CHROMEOS_LACROS) LacrosChromeServiceImpl
return select_file_remote_;
}
void BindScreenManagerReceiver(
mojo::PendingReceiver<lacros::mojom::ScreenManager> pending_receiver);
// lacros::mojom::LacrosChromeService:
void RequestAshChromeServiceReceiver(
RequestAshChromeServiceReceiverCallback callback) override;
......
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# C++ components used by both lacros-chrome and ash-chrome.
config("lacros_implementation") {
defines = [ "IS_LACROS_IMPL" ]
}
component("cpp") {
output_name = "lacros_public_cpp"
sources = [
"window_snapshot.cc",
"window_snapshot.h",
]
configs += [ ":lacros_implementation" ]
deps = [ "//base" ]
}
// Copyright 2020 The Chromium 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 "chromeos/lacros/cpp/window_snapshot.h"
namespace lacros {
WindowSnapshot::WindowSnapshot() = default;
WindowSnapshot::~WindowSnapshot() = default;
} // namespace lacros
// Copyright 2020 The Chromium 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 CHROMEOS_LACROS_CPP_WINDOW_SNAPSHOT_H_
#define CHROMEOS_LACROS_CPP_WINDOW_SNAPSHOT_H_
#include <stdint.h>
#include <vector>
#include "base/component_export.h"
namespace lacros {
// bitmap is a 4-byte RGBA bitmap representation of the window. Its size must
// be exactly equal to width * height * 4.
struct COMPONENT_EXPORT(LACROS) WindowSnapshot {
WindowSnapshot();
~WindowSnapshot();
uint32_t width = 0;
uint32_t height = 0;
std::vector<uint8_t> bitmap;
};
} // namespace lacros
#endif // CHROMEOS_LACROS_CPP_WINDOW_SNAPSHOT_H_
......@@ -7,8 +7,43 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojom") {
sources = [
"lacros.mojom",
"screen_manager.mojom",
"select_file.mojom",
]
cpp_typemaps = [
{
types = [
{
mojom = "lacros.mojom.WindowSnapshot"
cpp = "lacros::WindowSnapshot"
},
]
traits_headers =
[ "//chromeos/lacros/mojom/window_snapshot_mojom_traits.h" ]
traits_public_deps = [
":mojom_traits",
"//chromeos/lacros/cpp",
]
},
]
public_deps = [ "//mojo/public/mojom/base" ]
}
component("mojom_traits") {
output_name = "lacros_mojom_traits"
sources = [
"window_snapshot_mojom_traits.cc",
"window_snapshot_mojom_traits.h",
]
defines = [ "IS_LACROS_MOJOM_TRAITS_IMPL" ]
public_deps = [
":mojom_shared",
"//chromeos/lacros/cpp",
"//mojo/public/cpp/base:shared_typemap_traits",
]
}
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
# Prefer Chrome OS owners for large changes to the Lacros API.
per-file *.mojom=file://chromeos/SECURITY_OWNERS
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.mojom_traits*.*=file://chromeos/SECURITY_OWNERS
......@@ -4,11 +4,16 @@
module lacros.mojom;
import "chromeos/lacros/mojom/screen_manager.mojom";
import "chromeos/lacros/mojom/select_file.mojom";
// AshChromeService defines the APIs that live in ash-chrome and are
// accessed from lacros-chrome.
interface AshChromeService {
// Binds the ScreenManager interface for interacting with windows, screens and
// displays.
BindScreenManager@1(pending_receiver<ScreenManager> receiver);
// Binds the SelectFile interface for open/save dialogs.
BindSelectFile@0(pending_receiver<SelectFile> receiver);
};
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module lacros.mojom;
// A bitmap representation of the current contents of a window or screen. Each
// pixel is represented by 4 bytes [RGBA].
struct WindowSnapshot {
uint32 width;
uint32 height;
array<uint8> bitmap;
};
// This interface is implemented by ash-chrome. It allows lacros-chrome to query
// information about existing windows, screens, and displays.
//
// This interface cannot be used to make changes to screens, windows or
// displays. That's because Wayland is the protocol for that, and attempting to
// introduce another protocol would require careful synchronization between the
// two, which we'd like to avoid.
//
// TODO(https://crbug.com/1094460): This is a very simple interface. We will
// likely want to replace it with a more feature-complete and performant
// interface in the future.
interface ScreenManager {
// TODO(https://crbug.com/1094460): We will need to add more methods for
// querying screens, windows, etc. Details still TBD.
// TODO(https://crbug.com/1094460): Use a more performant transport
// mechanism.
// This method assumes that there's exactly one screen. The implementation
// of this method takes a screenshot and converts it into a bitmap. Each
// pixel is represented by 4 bytes [RGBA].
//
// The media screen capture implementation assumes that every platform
// provides a synchronous method to take a snapshot of the screen.
[Sync]
TakeScreenSnapshot@0() => (WindowSnapshot snapshot);
};
// Copyright 2020 The Chromium 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 "chromeos/lacros/mojom/window_snapshot_mojom_traits.h"
#include "base/numerics/checked_math.h"
namespace mojo {
// static
bool StructTraits<
lacros::mojom::WindowSnapshotDataView,
lacros::WindowSnapshot>::Read(lacros::mojom::WindowSnapshotDataView data,
lacros::WindowSnapshot* out) {
out->width = data.width();
out->height = data.height();
ArrayDataView<uint8_t> bitmap;
data.GetBitmapDataView(&bitmap);
uint32_t size;
size = base::CheckMul(out->width, out->height).ValueOrDie();
size = base::CheckMul(size, 4).ValueOrDie();
if (bitmap.size() != base::checked_cast<size_t>(size))
return false;
const uint8_t* base = bitmap.data();
out->bitmap.assign(base, base + bitmap.size());
return true;
}
} // namespace mojo
// Copyright 2020 The Chromium 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 CHROMEOS_LACROS_MOJOM_WINDOW_SNAPSHOT_MOJOM_TRAITS_H_
#define CHROMEOS_LACROS_MOJOM_WINDOW_SNAPSHOT_MOJOM_TRAITS_H_
#include "base/component_export.h"
#include "chromeos/lacros/cpp/window_snapshot.h"
#include "chromeos/lacros/mojom/screen_manager.mojom-shared.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
namespace mojo {
template <>
struct COMPONENT_EXPORT(LACROS_MOJOM_TRAITS)
StructTraits<lacros::mojom::WindowSnapshotDataView,
lacros::WindowSnapshot> {
static uint32_t width(const lacros::WindowSnapshot& snapshot) {
return snapshot.width;
}
static uint32_t height(const lacros::WindowSnapshot& snapshot) {
return snapshot.height;
}
static const std::vector<uint8_t>& bitmap(
const lacros::WindowSnapshot& snapshot) {
return snapshot.bitmap;
}
static bool Read(lacros::mojom::WindowSnapshotDataView,
lacros::WindowSnapshot* out);
};
} // namespace mojo
#endif // CHROMEOS_LACROS_MOJOM_WINDOW_SNAPSHOT_MOJOM_TRAITS_H_
......@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/buildflag_header.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/features.gni")
import("//build/config/jumbo.gni")
import("//build/config/linux/pangocairo/pangocairo.gni")
......@@ -49,6 +50,7 @@ jumbo_source_set("browser") {
"//base:clang_profiling_buildflags",
"//base/third_party/dynamic_annotations",
"//build:branding_buildflags",
"//build:lacros_buildflags",
"//cc",
"//cc/animation",
"//cc/mojo_embedder",
......@@ -2179,6 +2181,16 @@ jumbo_source_set("browser") {
"//sandbox/mac:seatbelt_extension",
]
}
if (chromeos_is_browser_only) {
sources += [
"media/capture/desktop_capturer_lacros.cc",
"media/capture/desktop_capturer_lacros.h",
]
deps += [
"//chromeos/lacros/browser",
"//chromeos/lacros/mojom",
]
}
}
if (is_win) {
......
......@@ -25,6 +25,7 @@
#include "base/time/tick_clock.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "build/lacros_buildflags.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
......@@ -48,6 +49,10 @@
#include "third_party/webrtc/modules/desktop_capture/mouse_cursor_monitor.h"
#include "ui/gfx/icc_profile.h"
#if BUILDFLAG(IS_LACROS)
#include "content/browser/media/capture/desktop_capturer_lacros.h"
#endif
namespace content {
namespace {
......@@ -509,8 +514,15 @@ std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
switch (source.type) {
case DesktopMediaID::TYPE_SCREEN: {
#if BUILDFLAG(IS_LACROS)
// TODO(https://crbug.com/1094460): Handle options.
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer =
std::make_unique<DesktopCapturerLacros>(
webrtc::DesktopCaptureOptions());
#else
std::unique_ptr<webrtc::DesktopCapturer> screen_capturer(
webrtc::DesktopCapturer::CreateScreenCapturer(options));
#endif
if (screen_capturer && screen_capturer->SelectSource(source.id)) {
capturer.reset(new webrtc::DesktopAndCursorComposer(
std::move(screen_capturer), options));
......@@ -523,6 +535,7 @@ std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
}
case DesktopMediaID::TYPE_WINDOW: {
// TODO(https://crbug.com/1094460): Implement window capture for Lacros.
std::unique_ptr<webrtc::DesktopCapturer> window_capturer =
webrtc::CroppingWindowCapturer::CreateCapturer(options);
if (window_capturer && window_capturer->SelectSource(source.id)) {
......
// Copyright 2020 The Chromium 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 "content/browser/media/capture/desktop_capturer_lacros.h"
#include "base/debug/stack_trace.h"
#include "base/logging.h"
#include "chromeos/lacros/browser/lacros_chrome_service_impl.h"
#include "chromeos/lacros/cpp/window_snapshot.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace content {
DesktopCapturerLacros::DesktopCapturerLacros(
const webrtc::DesktopCaptureOptions& options)
: options_(options) {
mojo::PendingRemote<lacros::mojom::ScreenManager> pending_screen_manager;
mojo::PendingReceiver<lacros::mojom::ScreenManager> pending_receiver =
pending_screen_manager.InitWithNewPipeAndPassReceiver();
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&DesktopCapturerLacros::BindReceiverMainThread,
std::move(pending_receiver)));
// We create a SharedRemote that binds the underlying Remote onto a
// dedicated sequence.
screen_manager_ = mojo::SharedRemote<lacros::mojom::ScreenManager>(
std::move(pending_screen_manager),
base::ThreadPool::CreateSequencedTaskRunner({}));
}
DesktopCapturerLacros::~DesktopCapturerLacros() = default;
bool DesktopCapturerLacros::GetSourceList(SourceList* sources) {
// TODO(https://crbug.com/1094460): Implement this source list appropriately.
Source w;
w.id = 1;
sources->push_back(w);
return true;
}
bool DesktopCapturerLacros::SelectSource(SourceId id) {
return true;
}
bool DesktopCapturerLacros::FocusOnSelectedSource() {
return true;
}
void DesktopCapturerLacros::Start(Callback* callback) {
callback_ = callback;
}
void DesktopCapturerLacros::CaptureFrame() {
lacros::WindowSnapshot snapshot;
{
// lacros-chrome is allowed to make sync calls to ash-chrome.
mojo::SyncCallRestrictions::ScopedAllowSyncCall allow_sync_call;
screen_manager_->TakeScreenSnapshot(&snapshot);
}
DidTakeScreenSnapshot(snapshot);
}
bool DesktopCapturerLacros::IsOccluded(const webrtc::DesktopVector& pos) {
return false;
}
void DesktopCapturerLacros::SetSharedMemoryFactory(
std::unique_ptr<webrtc::SharedMemoryFactory> shared_memory_factory) {}
void DesktopCapturerLacros::SetExcludedWindow(webrtc::WindowId window) {}
// static
void DesktopCapturerLacros::BindReceiverMainThread(
mojo::PendingReceiver<lacros::mojom::ScreenManager> receiver) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// The lacros chrome service must exist at all points in time for the lacros
// browser.
auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get();
DCHECK(lacros_chrome_service);
lacros_chrome_service->BindScreenManagerReceiver(std::move(receiver));
}
void DesktopCapturerLacros::DidTakeScreenSnapshot(
const lacros::WindowSnapshot& snapshot) {
std::unique_ptr<webrtc::DesktopFrame> frame =
std::make_unique<webrtc::BasicDesktopFrame>(
webrtc::DesktopSize(snapshot.width, snapshot.height));
// This code assumes that the stride is 4 * width. This relies on the
// assumption that there's no padding and each pixel is 4 bytes.
frame->CopyPixelsFrom(
snapshot.bitmap.data(), 4 * snapshot.width,
webrtc::DesktopRect::MakeWH(snapshot.width, snapshot.height));
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
}
} // namespace content
// Copyright 2020 The Chromium 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 CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURER_LACROS_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURER_LACROS_H_
#include "base/memory/weak_ptr.h"
#include "chromeos/lacros/mojom/screen_manager.mojom.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
namespace lacros {
struct WindowSnapshot;
} // namespace lacros
namespace content {
// This class is responsible for communicating with ash-chrome to get snapshots
// of the desktop. This class is used on several different threads with no clear
// signaling. This is a contextual requirement of the current implementation of
// the media capture code. We do our best to:
// * Minimize state stored in this class.
// * Ensure that stored state is accessed safely.
class DesktopCapturerLacros : public webrtc::DesktopCapturer {
public:
explicit DesktopCapturerLacros(const webrtc::DesktopCaptureOptions& options);
DesktopCapturerLacros(const DesktopCapturerLacros&) = delete;
DesktopCapturerLacros& operator=(const DesktopCapturerLacros&) = delete;
~DesktopCapturerLacros() override;
// DesktopCapturer:
void Start(Callback* callback) override;
void CaptureFrame() override;
bool GetSourceList(SourceList* sources) override;
bool SelectSource(SourceId id) override;
bool FocusOnSelectedSource() override;
bool IsOccluded(const webrtc::DesktopVector& pos) override;
void SetSharedMemoryFactory(std::unique_ptr<webrtc::SharedMemoryFactory>
shared_memory_factory) override;
void SetExcludedWindow(webrtc::WindowId window) override;
private:
static void BindReceiverMainThread(
mojo::PendingReceiver<lacros::mojom::ScreenManager> receiver);
// Callback for when ash-chrome returns a snapshot of the screen as a
// bitmap.
void DidTakeScreenSnapshot(const lacros::WindowSnapshot& snapshot);
// TODO(https://crbug.com/1094460): The webrtc options for screen/display
// capture are currently ignored.
const webrtc::DesktopCaptureOptions options_;
// The webrtc::DesktopCapturer interface expects the implementation to hold
// onto and call a Callback* object. This instance relies on the assumption
// that Callback* will outlive this instance.
//
// The current media capture implementation expects that the implementation of
// CaptureFrame() synchronously invokes |callback_| in a re-entrant fashion.
// Thus, we do not worry about thread safety when invoking callback_.
Callback* callback_ = nullptr;
// This remote is thread safe. Callbacks are invoked on the calling sequence.
mojo::SharedRemote<lacros::mojom::ScreenManager> screen_manager_;
base::WeakPtrFactory<DesktopCapturerLacros> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURER_LACROS_H_
......@@ -459,6 +459,7 @@ jumbo_source_set("browser_sources") {
"//storage/browser",
]
deps = [
"//build:lacros_buildflags",
"//cc",
"//components/viz/host",
"//content/browser", # Must not be public_deps!
......
......@@ -6,8 +6,13 @@
#include "base/feature_list.h"
#include "build/build_config.h"
#include "build/lacros_buildflags.h"
#include "content/public/common/content_features.h"
#if BUILDFLAG(IS_LACROS)
#include "content/browser/media/capture/desktop_capturer_lacros.h"
#endif
namespace content {
namespace desktop_capture {
......@@ -39,11 +44,17 @@ webrtc::DesktopCaptureOptions CreateDesktopCaptureOptions() {
}
std::unique_ptr<webrtc::DesktopCapturer> CreateScreenCapturer() {
#if BUILDFLAG(IS_LACROS)
return std::make_unique<DesktopCapturerLacros>(
webrtc::DesktopCaptureOptions());
#else
return webrtc::DesktopCapturer::CreateScreenCapturer(
CreateDesktopCaptureOptions());
#endif
}
std::unique_ptr<webrtc::DesktopCapturer> CreateWindowCapturer() {
// TODO(https://crbug.com/1094460): Implement window capture.
return webrtc::DesktopCapturer::CreateWindowCapturer(
CreateDesktopCaptureOptions());
}
......
......@@ -19,6 +19,10 @@ namespace chromecast {
class CastCdmOriginProvider;
} // namespace chromecast
namespace content {
class DesktopCapturerLacros;
} // namespace content
namespace ui {
class Compositor;
} // namespace ui
......@@ -67,6 +71,9 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions {
// BEGIN ALLOWED USAGE.
// SynchronousCompositorHost is used for Android webview.
friend class content::SynchronousCompositorHost;
// Lacros-chrome is allowed to make sync calls to ash-chrome to mimic
// cross-platform sync APIs.
friend class content::DesktopCapturerLacros;
friend class mojo::ScopedAllowSyncCallForTesting;
// For destroying the GL context/surface that draw to a platform window before
// the platform window is destroyed.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment