blob: edd5233b9a1db493be1a51866ac8e4c5f48da756 [file] [log] [blame]
// 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/ui/ash/chrome_capture_mode_delegate.h"
#include "ash/services/recording/public/mojom/recording_service.mojom.h"
#include "base/check.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/i18n/time_formatting.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/apps/app_service/launch_utils.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/policy/dlp/dlp_content_manager.h"
#include "chrome/browser/chromeos/service_sandbox_type.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/screenshot_area.h"
#include "chrome/browser/ui/web_applications/system_web_app_ui_utils.h"
#include "chrome/browser/web_applications/components/web_app_id_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/login/login_state/login_state.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/audio_service.h"
#include "content/public/browser/service_process_host.h"
#include "ui/aura/window.h"
#include "ui/base/window_open_disposition.h"
namespace {
ChromeCaptureModeDelegate* g_instance = nullptr;
ScreenshotArea ConvertToScreenshotArea(const aura::Window* window,
const gfx::Rect& bounds) {
return window->IsRootWindow()
? ScreenshotArea::CreateForPartialWindow(window, bounds)
: ScreenshotArea::CreateForWindow(window);
}
bool IsScreenCaptureDisabledByPolicy() {
return g_browser_process->local_state()->GetBoolean(
prefs::kDisableScreenshots);
}
} // namespace
ChromeCaptureModeDelegate::ChromeCaptureModeDelegate() {
DCHECK_EQ(g_instance, nullptr);
g_instance = this;
}
ChromeCaptureModeDelegate::~ChromeCaptureModeDelegate() {
DCHECK_EQ(g_instance, this);
g_instance = nullptr;
}
// static
ChromeCaptureModeDelegate* ChromeCaptureModeDelegate::Get() {
DCHECK(g_instance);
return g_instance;
}
void ChromeCaptureModeDelegate::SetIsScreenCaptureLocked(bool locked) {
is_screen_capture_locked_ = locked;
if (is_screen_capture_locked_)
InterruptVideoRecordingIfAny();
}
void ChromeCaptureModeDelegate::InterruptVideoRecordingIfAny() {
if (interrupt_video_recording_callback_)
std::move(interrupt_video_recording_callback_).Run();
}
base::FilePath ChromeCaptureModeDelegate::GetScreenCaptureDir() const {
if (chromeos::LoginState::Get()->IsUserLoggedIn()) {
DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext(
ProfileManager::GetActiveUserProfile());
// We use the default downloads directory instead of the one that can be
// configured from the browser's settings, since it can point to an invalid
// location, which the browser handles by prompting the user to select
// another one when accessed, but Capture Mode doesn't have this capability.
// We also decided that this browser setting should not affect when the OS
// saves the captured files. https://crbug.com/1192406.
return download_prefs->GetDefaultDownloadDirectoryForProfile();
}
base::FilePath tmp_dir;
if (!base::GetTempDir(&tmp_dir))
LOG(ERROR) << "Failed to find temporary directory.";
return tmp_dir;
}
void ChromeCaptureModeDelegate::ShowScreenCaptureItemInFolder(
const base::FilePath& file_path) {
platform_util::ShowItemInFolder(ProfileManager::GetActiveUserProfile(),
file_path);
}
void ChromeCaptureModeDelegate::OpenScreenshotInImageEditor(
const base::FilePath& file_path) {
Profile* profile = ProfileManager::GetActiveUserProfile();
if (!profile)
return;
web_app::SystemAppLaunchParams params;
params.launch_paths = {file_path};
params.launch_source = apps::mojom::LaunchSource::kFromFileManager;
web_app::LaunchSystemWebAppAsync(profile, web_app::SystemAppType::MEDIA,
params);
}
bool ChromeCaptureModeDelegate::Uses24HourFormat() const {
Profile* profile = ProfileManager::GetActiveUserProfile();
// TODO(afakhry): Consider moving |prefs::kUse24HourClock| to ash/public so
// we can do this entirely in ash.
if (profile)
return profile->GetPrefs()->GetBoolean(prefs::kUse24HourClock);
return base::GetHourClockType() == base::k24HourClock;
}
bool ChromeCaptureModeDelegate::IsCaptureModeInitRestrictedByDlp() const {
return policy::DlpContentManager::Get()->IsCaptureModeInitRestricted();
}
bool ChromeCaptureModeDelegate::IsCaptureAllowedByDlp(
const aura::Window* window,
const gfx::Rect& bounds,
bool for_video) const {
policy::DlpContentManager* dlp_content_manager =
policy::DlpContentManager::Get();
const ScreenshotArea area = ConvertToScreenshotArea(window, bounds);
return for_video ? !dlp_content_manager->IsVideoCaptureRestricted(area)
: !dlp_content_manager->IsScreenshotRestricted(area);
}
bool ChromeCaptureModeDelegate::IsCaptureAllowedByPolicy() const {
return !is_screen_capture_locked_ && !IsScreenCaptureDisabledByPolicy();
}
void ChromeCaptureModeDelegate::StartObservingRestrictedContent(
const aura::Window* window,
const gfx::Rect& bounds,
base::OnceClosure stop_callback) {
// The order here matters, since DlpContentManager::OnVideoCaptureStarted()
// may call InterruptVideoRecordingIfAny() right away, so the callback must be
// set first.
interrupt_video_recording_callback_ = std::move(stop_callback);
policy::DlpContentManager::Get()->OnVideoCaptureStarted(
ConvertToScreenshotArea(window, bounds));
}
void ChromeCaptureModeDelegate::StopObservingRestrictedContent() {
interrupt_video_recording_callback_.Reset();
policy::DlpContentManager::Get()->OnVideoCaptureStopped();
}
mojo::Remote<recording::mojom::RecordingService>
ChromeCaptureModeDelegate::LaunchRecordingService() {
return content::ServiceProcessHost::Launch<
recording::mojom::RecordingService>(
content::ServiceProcessHost::Options()
.WithDisplayName("Recording Service")
.Pass());
}
void ChromeCaptureModeDelegate::BindAudioStreamFactory(
mojo::PendingReceiver<media::mojom::AudioStreamFactory> receiver) {
content::GetAudioService().BindStreamFactory(std::move(receiver));
}
void ChromeCaptureModeDelegate::OnSessionStateChanged(bool started) {
is_session_active_ = started;
}
void ChromeCaptureModeDelegate::OnServiceRemoteReset() {}