Commit f9fc7cc0 authored by Judy Wang's avatar Judy Wang Committed by Chromium LUCI CQ

capture_mode: Enable fullscreen capture mode in accelerator.

Add new full screen capture function in accelerator, hide behind capture mode flag for now.

Test: Manual test
Bug: 1149725
Change-Id: I0ca1beb067aaa98d4c0099f6803515142ec5c616
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2572686
Commit-Queue: Judy Wang <shidi@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#838726}
parent 525e8789
...@@ -794,7 +794,10 @@ void HandleTakePartialScreenshot() { ...@@ -794,7 +794,10 @@ void HandleTakePartialScreenshot() {
void HandleTakeScreenshot() { void HandleTakeScreenshot() {
base::RecordAction(UserMetricsAction("Accel_Take_Screenshot")); base::RecordAction(UserMetricsAction("Accel_Take_Screenshot"));
Shell::Get()->screenshot_controller()->TakeScreenshotForAllRootWindows(); if (!features::IsCaptureModeEnabled())
Shell::Get()->screenshot_controller()->TakeScreenshotForAllRootWindows();
else
CaptureModeController::Get()->CaptureScreenshotsOfAllDisplays();
} }
void HandleToggleSystemTrayBubbleInternal(bool focus_message_center) { void HandleToggleSystemTrayBubbleInternal(bool focus_message_center) {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "ash/public/cpp/holding_space/holding_space_controller.h" #include "ash/public/cpp/holding_space/holding_space_controller.h"
#include "ash/public/cpp/notification_utils.h" #include "ash/public/cpp/notification_utils.h"
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h" #include "ash/session/session_controller_impl.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h" #include "ash/strings/grit/ash_strings.h"
...@@ -68,8 +69,8 @@ constexpr char kScreenCaptureNotifierId[] = "ash.capture_mode_controller"; ...@@ -68,8 +69,8 @@ constexpr char kScreenCaptureNotifierId[] = "ash.capture_mode_controller";
// The format strings of the file names of captured images. // The format strings of the file names of captured images.
// TODO(afakhry): Discuss with UX localizing "Screenshot" and "Screen // TODO(afakhry): Discuss with UX localizing "Screenshot" and "Screen
// recording". // recording".
constexpr char kScreenshotFileNameFmtStr[] = "Screenshot %s %s.png"; constexpr char kScreenshotFileNameFmtStr[] = "Screenshot %s %s";
constexpr char kVideoFileNameFmtStr[] = "Screen recording %s %s.webm"; constexpr char kVideoFileNameFmtStr[] = "Screen recording %s %s";
constexpr char kDateFmtStr[] = "%d-%02d-%02d"; constexpr char kDateFmtStr[] = "%d-%02d-%02d";
constexpr char k24HourTimeFmtStr[] = "%02d.%02d.%02d"; constexpr char k24HourTimeFmtStr[] = "%02d.%02d.%02d";
constexpr char kAmPmTimeFmtStr[] = "%d.%02d.%02d"; constexpr char kAmPmTimeFmtStr[] = "%d.%02d.%02d";
...@@ -347,6 +348,29 @@ void CaptureModeController::SetUserCaptureRegion(const gfx::Rect& region, ...@@ -347,6 +348,29 @@ void CaptureModeController::SetUserCaptureRegion(const gfx::Rect& region,
last_capture_region_update_time_ = base::TimeTicks::Now(); last_capture_region_update_time_ = base::TimeTicks::Now();
} }
void CaptureModeController::CaptureScreenshotsOfAllDisplays() {
if (delegate_->IsCaptureModeInitRestricted()) {
ShowDisabledNotification();
return;
}
// Get a vector of RootWindowControllers with primary root window at first.
const std::vector<RootWindowController*> controllers =
RootWindowController::root_window_controllers();
// Capture screenshot for each individual display.
int display_index = 1;
for (RootWindowController* controller : controllers) {
// TODO(shidi): Check with UX what notification should show if
// some (but not all) of the displays have restricted content and
// whether we should localize the display name.
const CaptureParams capture_params{controller->GetRootWindow(),
controller->GetRootWindow()->bounds()};
CaptureImage(capture_params, controllers.size() == 1
? BuildImagePath()
: BuildImagePathForDisplay(display_index));
++display_index;
}
}
void CaptureModeController::PerformCapture() { void CaptureModeController::PerformCapture() {
DCHECK(IsActive()); DCHECK(IsActive());
const base::Optional<CaptureParams> capture_params = GetCaptureParams(); const base::Optional<CaptureParams> capture_params = GetCaptureParams();
...@@ -362,8 +386,10 @@ void CaptureModeController::PerformCapture() { ...@@ -362,8 +386,10 @@ void CaptureModeController::PerformCapture() {
DCHECK(capture_mode_session_); DCHECK(capture_mode_session_);
capture_mode_session_->ReportSessionHistograms(); capture_mode_session_->ReportSessionHistograms();
if (type_ == CaptureModeType::kImage) if (type_ == CaptureModeType::kImage) {
CaptureImage(*capture_params); CaptureImage(*capture_params, BuildImagePath());
}
else else
CaptureVideo(*capture_params); CaptureVideo(*capture_params);
} }
...@@ -608,20 +634,21 @@ void CaptureModeController::TerminateRecordingUiElements() { ...@@ -608,20 +634,21 @@ void CaptureModeController::TerminateRecordingUiElements() {
video_recording_watcher_.reset(); video_recording_watcher_.reset();
} }
void CaptureModeController::CaptureImage(const CaptureParams& capture_params) { void CaptureModeController::CaptureImage(const CaptureParams& capture_params,
const base::FilePath& path) {
DCHECK_EQ(CaptureModeType::kImage, type_); DCHECK_EQ(CaptureModeType::kImage, type_);
DCHECK(IsCaptureAllowed(capture_params)); DCHECK(IsCaptureAllowed(capture_params));
// Stop the capture session now, so as not to take a screenshot of the capture // Stop the capture session now, so as not to take a screenshot of the capture
// bar. // bar.
Stop(); if (IsActive())
Stop();
DCHECK(!capture_params.bounds.IsEmpty()); DCHECK(!capture_params.bounds.IsEmpty());
ui::GrabWindowSnapshotAsyncPNG( ui::GrabWindowSnapshotAsyncPNG(
capture_params.window, capture_params.bounds, capture_params.window, capture_params.bounds,
base::BindOnce(&CaptureModeController::OnImageCaptured, base::BindOnce(&CaptureModeController::OnImageCaptured,
weak_ptr_factory_.GetWeakPtr(), base::Time::Now())); weak_ptr_factory_.GetWeakPtr(), path));
++num_screenshots_taken_in_last_day_; ++num_screenshots_taken_in_last_day_;
++num_screenshots_taken_in_last_week_; ++num_screenshots_taken_in_last_week_;
...@@ -645,7 +672,7 @@ void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) { ...@@ -645,7 +672,7 @@ void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) {
} }
void CaptureModeController::OnImageCaptured( void CaptureModeController::OnImageCaptured(
base::Time timestamp, const base::FilePath& path,
scoped_refptr<base::RefCountedMemory> png_bytes) { scoped_refptr<base::RefCountedMemory> png_bytes) {
if (!png_bytes || !png_bytes->size()) { if (!png_bytes || !png_bytes->size()) {
LOG(ERROR) << "Failed to capture image."; LOG(ERROR) << "Failed to capture image.";
...@@ -653,7 +680,6 @@ void CaptureModeController::OnImageCaptured( ...@@ -653,7 +680,6 @@ void CaptureModeController::OnImageCaptured(
return; return;
} }
const base::FilePath path = BuildImagePath(timestamp);
blocking_task_runner_->PostTaskAndReplyWithResult( blocking_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&SaveFile, png_bytes, path), FROM_HERE, base::BindOnce(&SaveFile, png_bytes, path),
base::BindOnce(&CaptureModeController::OnImageFileSaved, base::BindOnce(&CaptureModeController::OnImageFileSaved,
...@@ -791,18 +817,29 @@ void CaptureModeController::HandleNotificationClicked( ...@@ -791,18 +817,29 @@ void CaptureModeController::HandleNotificationClicked(
kScreenCaptureNotificationId, /*by_user=*/false); kScreenCaptureNotificationId, /*by_user=*/false);
} }
base::FilePath CaptureModeController::BuildImagePath( base::FilePath CaptureModeController::BuildImagePath() const {
base::Time timestamp) const { return BuildPathNoExtension(kScreenshotFileNameFmtStr, base::Time::Now())
return BuildPath(kScreenshotFileNameFmtStr, timestamp); .AddExtension("png");
} }
base::FilePath CaptureModeController::BuildVideoPath( base::FilePath CaptureModeController::BuildVideoPath() const {
base::Time timestamp) const { return BuildPathNoExtension(kVideoFileNameFmtStr, base::Time::Now())
return BuildPath(kVideoFileNameFmtStr, timestamp); .AddExtension("webm");
}
base::FilePath CaptureModeController::BuildImagePathForDisplay(
int display_index) const {
auto path_str =
BuildPathNoExtension(kScreenshotFileNameFmtStr, base::Time::Now())
.value();
auto full_path = base::StringPrintf("%s - Display %d.png", path_str.c_str(),
display_index);
return base::FilePath(full_path);
} }
base::FilePath CaptureModeController::BuildPath(const char* const format_string, base::FilePath CaptureModeController::BuildPathNoExtension(
base::Time timestamp) const { const char* const format_string,
base::Time timestamp) const {
const base::FilePath path = delegate_->GetActiveUserDownloadsDir(); const base::FilePath path = delegate_->GetActiveUserDownloadsDir();
base::Time::Exploded exploded_time; base::Time::Exploded exploded_time;
timestamp.LocalExplode(&exploded_time); timestamp.LocalExplode(&exploded_time);
...@@ -865,7 +902,7 @@ void CaptureModeController::OnVideoRecordCountDownFinished() { ...@@ -865,7 +902,7 @@ void CaptureModeController::OnVideoRecordCountDownFinished() {
DCHECK(current_video_file_path_.empty()); DCHECK(current_video_file_path_.empty());
recording_start_time_ = base::TimeTicks::Now(); recording_start_time_ = base::TimeTicks::Now();
current_video_file_path_ = BuildVideoPath(base::Time::Now()); current_video_file_path_ = BuildVideoPath();
video_file_handler_ = VideoFileHandler::Create( video_file_handler_ = VideoFileHandler::Create(
blocking_task_runner_, current_video_file_path_, blocking_task_runner_, current_video_file_path_,
kVideoBufferCapacityBytes, kLowDiskSpaceThresholdInBytes, kVideoBufferCapacityBytes, kLowDiskSpaceThresholdInBytes,
......
...@@ -84,6 +84,11 @@ class ASH_EXPORT CaptureModeController ...@@ -84,6 +84,11 @@ class ASH_EXPORT CaptureModeController
// update |last_capture_region_update_time_|. // update |last_capture_region_update_time_|.
void SetUserCaptureRegion(const gfx::Rect& region, bool by_user); void SetUserCaptureRegion(const gfx::Rect& region, bool by_user);
// Full screen capture for each available display if no restricted
// content exists on that display, each capture is saved as an individual
// file. Note: this won't start a capture mode session.
void CaptureScreenshotsOfAllDisplays();
// Called only while a capture session is in progress to perform the actual // Called only while a capture session is in progress to perform the actual
// capture depending on the current selected |source_| and |type_|, and ends // capture depending on the current selected |source_| and |type_|, and ends
// the capture session. // the capture session.
...@@ -151,14 +156,15 @@ class ASH_EXPORT CaptureModeController ...@@ -151,14 +156,15 @@ class ASH_EXPORT CaptureModeController
// the capture session is still active when called, so they can retrieve the // the capture session is still active when called, so they can retrieve the
// capture parameters they need. They will end the sessions themselves. // capture parameters they need. They will end the sessions themselves.
// They should never be called if IsCaptureAllowed() returns false. // They should never be called if IsCaptureAllowed() returns false.
void CaptureImage(const CaptureParams& capture_params); void CaptureImage(const CaptureParams& capture_params,
const base::FilePath& path);
void CaptureVideo(const CaptureParams& capture_params); void CaptureVideo(const CaptureParams& capture_params);
// Called back when an image has been captured to trigger an attempt to save // Called back when an image has been captured to trigger an attempt to save
// the image as a file. |timestamp| is the time at which the capture was // the image as a file. |timestamp| is the time at which the capture was
// triggered, and |png_bytes| is the buffer containing the captured image in a // triggered, |png_bytes| is the buffer containing the captured image in a
// PNG format. // PNG format.
void OnImageCaptured(base::Time timestamp, void OnImageCaptured(const base::FilePath& path,
scoped_refptr<base::RefCountedMemory> png_bytes); scoped_refptr<base::RefCountedMemory> png_bytes);
// Called back when an attempt to save the image file has been completed, with // Called back when an attempt to save the image file has been completed, with
...@@ -190,13 +196,17 @@ class ASH_EXPORT CaptureModeController ...@@ -190,13 +196,17 @@ class ASH_EXPORT CaptureModeController
base::Optional<int> button_index); base::Optional<int> button_index);
// Builds a path for a file of an image screenshot, or a video screen // Builds a path for a file of an image screenshot, or a video screen
// recording, which were taken at |timestamp|. // recording, builds with display index if there are
base::FilePath BuildImagePath(base::Time timestamp) const; // multiple displays.
base::FilePath BuildVideoPath(base::Time timestamp) const; base::FilePath BuildImagePath() const;
// Used by the above two functions by providing the corresponding file name base::FilePath BuildVideoPath() const;
// |format_string| to a capture type (image or video). base::FilePath BuildImagePathForDisplay(int display_index) const;
base::FilePath BuildPath(const char* const format_string, // Used by the above three functions by providing the corresponding file name
base::Time timestamp) const; // |format_string| to a capture type (image or video). The returned file path
// excludes the file extension. The above functions are responsible for adding
// it.
base::FilePath BuildPathNoExtension(const char* const format_string,
base::Time timestamp) const;
// Records the number of screenshots taken. // Records the number of screenshots taken.
void RecordAndResetScreenshotsTakenInLastDay(); void RecordAndResetScreenshotsTakenInLastDay();
......
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