blob: f1f73fced03255244b1a2b9158d8d8022b010a96 [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.
#ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_CONTROLLER_H_
#define ASH_CAPTURE_MODE_CAPTURE_MODE_CONTROLLER_H_
#include <memory>
#include "ash/ash_export.h"
#include "ash/capture_mode/capture_mode_types.h"
#include "ash/public/cpp/capture_mode_delegate.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
namespace base {
class FilePath;
class Time;
} // namespace base
namespace ash {
class CaptureModeSession;
// Controls starting and ending a Capture Mode session and its behavior.
class ASH_EXPORT CaptureModeController {
public:
explicit CaptureModeController(std::unique_ptr<CaptureModeDelegate> delegate);
CaptureModeController(const CaptureModeController&) = delete;
CaptureModeController& operator=(const CaptureModeController&) = delete;
~CaptureModeController();
// Convenience function to get the controller instance, which is created and
// owned by Shell.
static CaptureModeController* Get();
CaptureModeType type() const { return type_; }
CaptureModeSource source() const { return source_; }
CaptureModeSession* capture_mode_session() const {
return capture_mode_session_.get();
}
gfx::Rect user_capture_region() const { return user_capture_region_; }
void set_user_capture_region(const gfx::Rect& region) {
user_capture_region_ = region;
}
bool is_recording_in_progress() const { return is_recording_in_progress_; }
// Returns true if a capture mode session is currently active.
bool IsActive() const { return !!capture_mode_session_; }
// Sets the capture source/type, which will be applied to an ongoing capture
// session (if any), or to a future capture session when Start() is called.
void SetSource(CaptureModeSource source);
void SetType(CaptureModeType type);
// Starts a new capture session with the most-recently used |type_| and
// |source_|.
void Start();
// Stops an existing capture session.
void Stop();
// 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.
void PerformCapture();
void EndVideoRecording();
private:
// Returns true if doing a screen capture is currently allowed, false
// otherwise.
bool IsCaptureAllowed() const;
// Returns the capture parameters for the capture operation that is about to
// be performed (i.e. the window to be captured, and the capture bounds). If
// nothing is to be captured (e.g. when there's no window selected in a
// kWindow source, or no region is selected in a kRegion source), then a
// base::nullopt is returned.
struct CaptureParams {
aura::Window* window = nullptr;
// The capture bounds, either in root coordinates (in kFullscreen or kRegion
// capture sources), or window-local coordinates (in a kWindow capture
// source). The bounds are never empty when in kImage capture type. However,
// in kVideo capture type, they're non-empty only in a kRegion capture
// source, since the recording service needs them to crop the frame.
gfx::Rect bounds;
};
base::Optional<CaptureParams> GetCaptureParams() const;
// The below functions start the actual image/video capture. They expect that
// 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();
void CaptureVideo();
// 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
// PNG format.
void OnImageCaptured(base::Time timestamp,
scoped_refptr<base::RefCountedMemory> png_bytes);
// Called back when an attempt to save the image file has been completed, with
// |success| indicating whether the attempt succeeded for failed. |png_bytes|
// is the buffer containing the captured image in a PNG format, which will be
// used to show a preview of the image in a notification, and save it as a
// bitmap in the clipboard. If saving was successful, then the image was saved
// in |path|.
void OnImageFileSaved(scoped_refptr<base::RefCountedMemory> png_bytes,
const base::FilePath& path,
bool success);
// Shows a preview notification of the newly taken screenshot or screen
// recording.
void ShowPreviewNotification(const base::FilePath& screen_capture_path,
const gfx::Image& preview_image);
void HandleNotificationClicked(const base::FilePath& screen_capture_path,
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,
base::Time timestamp) const;
std::unique_ptr<CaptureModeDelegate> delegate_;
CaptureModeType type_ = CaptureModeType::kImage;
CaptureModeSource source_ = CaptureModeSource::kRegion;
// We remember the user selected capture region when the source is |kRegion|
// between sessions. Initially, this value is empty at which point we display
// a message to the user instructing them to start selecting a region.
gfx::Rect user_capture_region_;
std::unique_ptr<CaptureModeSession> capture_mode_session_;
// True when video recording is in progress.
bool is_recording_in_progress_ = false;
base::WeakPtrFactory<CaptureModeController> weak_ptr_factory_{this};
};
} // namespace ash
#endif // ASH_CAPTURE_MODE_CAPTURE_MODE_CONTROLLER_H_