Commit 7fa67e3f authored by Ahmed Fakhry's avatar Ahmed Fakhry Committed by Commit Bot

capture_mode: Add logic to capture images

This CL implements the image capture part of this feature,
from all the possible sources, and handles saving the image
files and showing preview notifications as well as error
notifications.

Later CLs will implement logic to disable capture mode
operations such as policy or Data Leak Prevention (DLP).

BUG=1121699

Change-Id: I6dfba6f57adb0c48270b4d5ebb71e7d28fe489df
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2376476
Commit-Queue: Ahmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804036}
parent 11d2a7ec
......@@ -2691,6 +2691,18 @@ Here are some things you can try to get started.
</message>
<!-- Capture Mode -->
<message name="IDS_ASH_SCREEN_CAPTURE_DISABLED_TITLE" desc="The title of the notification when capture mode is disabled.">
Screen capture disabled
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_FAILURE_TITLE" desc="The title of the notification when capture mode fails.">
An error occurred
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_DISABLED_MESSAGE" desc="The text of the notification when capture mode is disabled.">
The ability to screen capture has been disabled by your administrator.
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_FAILURE_MESSAGE" desc="The text of the notification when capture mode fails.">
Failed to capture screen
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_DISPLAY_SOURCE" desc="The name that is the display source of the screen capture notification.">
Screen capture
</message>
......
c4ac976289a1db5f5e982fdd4148d219848331ac
\ No newline at end of file
c4ac976289a1db5f5e982fdd4148d219848331ac
\ No newline at end of file
79ed560659475d7632f6a9266546b4a7f7bc5de7
\ No newline at end of file
79ed560659475d7632f6a9266546b4a7f7bc5de7
\ No newline at end of file
This diff is collapsed.
......@@ -10,8 +10,15 @@
#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 "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
namespace base {
class FilePath;
class Time;
} // namespace base
namespace ash {
......@@ -62,11 +69,43 @@ class ASH_EXPORT CaptureModeController {
void EndVideoRecording();
private:
// Show notification for the newly taken screenshot or screen recording.
void ShowNotification(const base::FilePath& screen_capture_path);
// Returns true if doing a screen capture is currently allowed, false
// otherwise.
bool IsCaptureAllowed() 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. 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 an image screenshot file that was taken at |timestamp|.
base::FilePath BuildImagePath(base::Time timestamp) const;
std::unique_ptr<CaptureModeDelegate> delegate_;
CaptureModeType type_ = CaptureModeType::kImage;
......
......@@ -88,6 +88,15 @@ CaptureModeSession::~CaptureModeSession() {
SetMouseWarpEnabled(old_mouse_warp_status_);
}
aura::Window* CaptureModeSession::GetSelectedWindow() const {
// Note that the capture bar widget is activatable, so we can't use
// window_util::GetActiveWindow(). Instead, we use the MRU window tracker and
// get the top-most window if any.
auto mru_windows =
Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
return mru_windows.empty() ? nullptr : mru_windows[0];
}
void CaptureModeSession::OnCaptureSourceChanged(CaptureModeSource new_source) {
capture_mode_bar_view_->OnCaptureSourceChanged(new_source);
SetMouseWarpEnabled(new_source != CaptureModeSource::kRegion);
......@@ -136,14 +145,8 @@ void CaptureModeSession::OnTouchEvent(ui::TouchEvent* event) {
}
gfx::Rect CaptureModeSession::GetSelectedWindowBounds() const {
// Note that the capture bar widget is activatable, so we can't use
// window_util::GetActiveWindow(). Instead, we use the MRU window tracker and
// get the top-most window if any.
auto mru_windows =
Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk);
if (!mru_windows.empty())
return mru_windows[0]->bounds();
return gfx::Rect();
auto* window = GetSelectedWindow();
return window ? window->bounds() : gfx::Rect();
}
void CaptureModeSession::RefreshStackingOrder(aura::Window* parent_container) {
......
......@@ -38,10 +38,15 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
CaptureModeSession& operator=(const CaptureModeSession&) = delete;
~CaptureModeSession() override;
aura::Window* current_root() const { return current_root_; }
CaptureModeBarView* capture_mode_bar_view() const {
return capture_mode_bar_view_;
}
// Gets the current window selected for |kWindow| capture source. Returns
// nullptr if no window is available for selection.
aura::Window* GetSelectedWindow() const;
// Called when either the capture source or type changes.
void OnCaptureSourceChanged(CaptureModeSource new_source);
void OnCaptureTypeChanged(CaptureModeType new_type);
......@@ -57,7 +62,7 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
void OnTouchEvent(ui::TouchEvent* event) override;
private:
// Gets the current window selected for |kWindow| capture source.
// Gets the bounds of current window selected for |kWindow| capture source.
gfx::Rect GetSelectedWindowBounds() const;
// Ensures that the bar widget is on top of everything, and the overlay (which
......
......@@ -16,4 +16,8 @@ base::FilePath TestCaptureModeDelegate::GetActiveUserDownloadsDir() const {
void TestCaptureModeDelegate::ShowScreenCaptureItemInFolder(
const base::FilePath& file_path) {}
bool TestCaptureModeDelegate::Uses24HourFormat() const {
return false;
}
} // namespace ash
......@@ -19,6 +19,7 @@ class TestCaptureModeDelegate : public CaptureModeDelegate {
// CaptureModeDelegate:
base::FilePath GetActiveUserDownloadsDir() const override;
void ShowScreenCaptureItemInFolder(const base::FilePath& file_path) override;
bool Uses24HourFormat() const override;
};
} // namespace ash
......
......@@ -27,6 +27,11 @@ class ASH_PUBLIC_EXPORT CaptureModeDelegate {
// Shows the screenshot or screen recording item in the screen capture folder.
virtual void ShowScreenCaptureItemInFolder(
const base::FilePath& file_path) = 0;
// Returns true if the current user is using the 24-hour format (i.e. 14:00
// vs. 2:00 PM). This is used to build the file name of the captured image or
// video.
virtual bool Uses24HourFormat() const = 0;
};
} // namespace ash
......
......@@ -5,10 +5,13 @@
#include "chrome/browser/ui/ash/chrome_capture_mode_delegate.h"
#include "base/files/file_path.h"
#include "base/i18n/time_formatting.h"
#include "chrome/browser/download/download_prefs.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "chromeos/login/login_state/login_state.h"
#include "components/prefs/pref_service.h"
ChromeCaptureModeDelegate::ChromeCaptureModeDelegate() = default;
......@@ -26,3 +29,12 @@ void ChromeCaptureModeDelegate::ShowScreenCaptureItemInFolder(
platform_util::ShowItemInFolder(ProfileManager::GetActiveUserProfile(),
file_path);
}
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;
}
......@@ -20,6 +20,7 @@ class ChromeCaptureModeDelegate : public ash::CaptureModeDelegate {
// ash::CaptureModeDelegate:
base::FilePath GetActiveUserDownloadsDir() const override;
void ShowScreenCaptureItemInFolder(const base::FilePath& file_path) override;
bool Uses24HourFormat() const override;
};
#endif // CHROME_BROWSER_UI_ASH_CHROME_CAPTURE_MODE_DELEGATE_H_
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