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() {
void HandleTakeScreenshot() {
base::RecordAction(UserMetricsAction("Accel_Take_Screenshot"));
if (!features::IsCaptureModeEnabled())
Shell::Get()->screenshot_controller()->TakeScreenshotForAllRootWindows();
else
CaptureModeController::Get()->CaptureScreenshotsOfAllDisplays();
}
void HandleToggleSystemTrayBubbleInternal(bool focus_message_center) {
......
......@@ -16,6 +16,7 @@
#include "ash/public/cpp/holding_space/holding_space_controller.h"
#include "ash/public/cpp/notification_utils.h"
#include "ash/resources/vector_icons/vector_icons.h"
#include "ash/root_window_controller.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
......@@ -68,8 +69,8 @@ constexpr char kScreenCaptureNotifierId[] = "ash.capture_mode_controller";
// The format strings of the file names of captured images.
// TODO(afakhry): Discuss with UX localizing "Screenshot" and "Screen
// recording".
constexpr char kScreenshotFileNameFmtStr[] = "Screenshot %s %s.png";
constexpr char kVideoFileNameFmtStr[] = "Screen recording %s %s.webm";
constexpr char kScreenshotFileNameFmtStr[] = "Screenshot %s %s";
constexpr char kVideoFileNameFmtStr[] = "Screen recording %s %s";
constexpr char kDateFmtStr[] = "%d-%02d-%02d";
constexpr char k24HourTimeFmtStr[] = "%02d.%02d.%02d";
constexpr char kAmPmTimeFmtStr[] = "%d.%02d.%02d";
......@@ -347,6 +348,29 @@ void CaptureModeController::SetUserCaptureRegion(const gfx::Rect& region,
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() {
DCHECK(IsActive());
const base::Optional<CaptureParams> capture_params = GetCaptureParams();
......@@ -362,8 +386,10 @@ void CaptureModeController::PerformCapture() {
DCHECK(capture_mode_session_);
capture_mode_session_->ReportSessionHistograms();
if (type_ == CaptureModeType::kImage)
CaptureImage(*capture_params);
if (type_ == CaptureModeType::kImage) {
CaptureImage(*capture_params, BuildImagePath());
}
else
CaptureVideo(*capture_params);
}
......@@ -608,20 +634,21 @@ void CaptureModeController::TerminateRecordingUiElements() {
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(IsCaptureAllowed(capture_params));
// Stop the capture session now, so as not to take a screenshot of the capture
// bar.
if (IsActive())
Stop();
DCHECK(!capture_params.bounds.IsEmpty());
ui::GrabWindowSnapshotAsyncPNG(
capture_params.window, capture_params.bounds,
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_week_;
......@@ -645,7 +672,7 @@ void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) {
}
void CaptureModeController::OnImageCaptured(
base::Time timestamp,
const base::FilePath& path,
scoped_refptr<base::RefCountedMemory> png_bytes) {
if (!png_bytes || !png_bytes->size()) {
LOG(ERROR) << "Failed to capture image.";
......@@ -653,7 +680,6 @@ void CaptureModeController::OnImageCaptured(
return;
}
const base::FilePath path = BuildImagePath(timestamp);
blocking_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&SaveFile, png_bytes, path),
base::BindOnce(&CaptureModeController::OnImageFileSaved,
......@@ -791,17 +817,28 @@ void CaptureModeController::HandleNotificationClicked(
kScreenCaptureNotificationId, /*by_user=*/false);
}
base::FilePath CaptureModeController::BuildImagePath(
base::Time timestamp) const {
return BuildPath(kScreenshotFileNameFmtStr, timestamp);
base::FilePath CaptureModeController::BuildImagePath() const {
return BuildPathNoExtension(kScreenshotFileNameFmtStr, base::Time::Now())
.AddExtension("png");
}
base::FilePath CaptureModeController::BuildVideoPath(
base::Time timestamp) const {
return BuildPath(kVideoFileNameFmtStr, timestamp);
base::FilePath CaptureModeController::BuildVideoPath() const {
return BuildPathNoExtension(kVideoFileNameFmtStr, base::Time::Now())
.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(
const char* const format_string,
base::Time timestamp) const {
const base::FilePath path = delegate_->GetActiveUserDownloadsDir();
base::Time::Exploded exploded_time;
......@@ -865,7 +902,7 @@ void CaptureModeController::OnVideoRecordCountDownFinished() {
DCHECK(current_video_file_path_.empty());
recording_start_time_ = base::TimeTicks::Now();
current_video_file_path_ = BuildVideoPath(base::Time::Now());
current_video_file_path_ = BuildVideoPath();
video_file_handler_ = VideoFileHandler::Create(
blocking_task_runner_, current_video_file_path_,
kVideoBufferCapacityBytes, kLowDiskSpaceThresholdInBytes,
......
......@@ -84,6 +84,11 @@ class ASH_EXPORT CaptureModeController
// update |last_capture_region_update_time_|.
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
// capture depending on the current selected |source_| and |type_|, and ends
// the capture session.
......@@ -151,14 +156,15 @@ class ASH_EXPORT CaptureModeController
// the capture session is still active when called, so they can retrieve the
// capture parameters they need. They will end the sessions themselves.
// 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);
// 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
// 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.
void OnImageCaptured(base::Time timestamp,
void OnImageCaptured(const base::FilePath& path,
scoped_refptr<base::RefCountedMemory> png_bytes);
// Called back when an attempt to save the image file has been completed, with
......@@ -190,12 +196,16 @@ class ASH_EXPORT CaptureModeController
base::Optional<int> button_index);
// Builds a path for a file of an image screenshot, or a video screen
// recording, which were taken at |timestamp|.
base::FilePath BuildImagePath(base::Time timestamp) const;
base::FilePath BuildVideoPath(base::Time timestamp) const;
// Used by the above two functions by providing the corresponding file name
// |format_string| to a capture type (image or video).
base::FilePath BuildPath(const char* const format_string,
// recording, builds with display index if there are
// multiple displays.
base::FilePath BuildImagePath() const;
base::FilePath BuildVideoPath() const;
base::FilePath BuildImagePathForDisplay(int display_index) const;
// Used by the above three functions by providing the corresponding file name
// |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.
......
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