Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: ui/snapshot/screenshot_grabber.cc

Issue 706013004: Move non-browser specific ScreenshotTaker code to ui/snapshot. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Merge and fix gn Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/snapshot/screenshot_grabber.h ('k') | ui/snapshot/screenshot_grabber_observer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/snapshot/screenshot_grabber.h"
6
7 #include <climits>
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "base/files/file_util.h"
13 #include "base/logging.h"
14 #include "base/task_runner.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "base/time/time.h"
17 #include "ui/gfx/image/image.h"
18 #include "ui/snapshot/snapshot.h"
19
20 #if defined(USE_AURA)
21 #include "ui/aura/window.h"
22 #endif
23
24 namespace ui {
25
26 namespace {
27 // The minimum interval between two screenshot commands. It has to be
28 // more than 1000 to prevent the conflict of filenames.
29 const int kScreenshotMinimumIntervalInMS = 1000;
30
31 using ShowNotificationCallback =
32 base::Callback<void(ScreenshotGrabberObserver::Result screenshot_result,
33 const base::FilePath& screenshot_path)>;
34
35 void SaveScreenshot(scoped_refptr<base::TaskRunner> ui_task_runner,
36 const ShowNotificationCallback& callback,
37 const base::FilePath& screenshot_path,
38 scoped_refptr<base::RefCountedBytes> png_data,
39 ScreenshotGrabberDelegate::FileResult result,
40 const base::FilePath& local_path) {
41 DCHECK(!base::MessageLoopForUI::IsCurrent());
42 DCHECK(!screenshot_path.empty());
43
44 // Convert FileResult into ScreenshotGrabberObserver::Result.
45 ScreenshotGrabberObserver::Result screenshot_result =
46 ScreenshotGrabberObserver::SCREENSHOT_SUCCESS;
47 switch (result) {
48 case ScreenshotGrabberDelegate::FILE_SUCCESS:
49 // Successfully got a local file to write to, write png data.
50 DCHECK_GT(static_cast<int>(png_data->size()), 0);
51 if (static_cast<size_t>(base::WriteFile(
52 local_path, reinterpret_cast<char*>(&(png_data->data()[0])),
53 static_cast<int>(png_data->size()))) != png_data->size()) {
54 LOG(ERROR) << "Failed to save to " << local_path.value();
55 screenshot_result =
56 ScreenshotGrabberObserver::SCREENSHOT_WRITE_FILE_FAILED;
57 }
58 break;
59 case ScreenshotGrabberDelegate::FILE_CHECK_DIR_FAILED:
60 screenshot_result =
61 ScreenshotGrabberObserver::SCREENSHOT_CHECK_DIR_FAILED;
62 break;
63 case ScreenshotGrabberDelegate::FILE_CREATE_DIR_FAILED:
64 screenshot_result =
65 ScreenshotGrabberObserver::SCREENSHOT_CREATE_DIR_FAILED;
66 break;
67 case ScreenshotGrabberDelegate::FILE_CREATE_FAILED:
68 screenshot_result =
69 ScreenshotGrabberObserver::SCREENSHOT_CREATE_FILE_FAILED;
70 break;
71 }
72
73 // Report the result on the UI thread.
74 ui_task_runner->PostTask(
75 FROM_HERE, base::Bind(callback, screenshot_result, screenshot_path));
76 }
77
78 void EnsureLocalDirectoryExists(
79 const base::FilePath& path,
80 ScreenshotGrabberDelegate::FileCallback callback) {
81 DCHECK(!base::MessageLoopForUI::IsCurrent());
82 DCHECK(!path.empty());
83
84 if (!base::CreateDirectory(path.DirName())) {
85 LOG(ERROR) << "Failed to ensure the existence of "
86 << path.DirName().value();
87 callback.Run(ScreenshotGrabberDelegate::FILE_CREATE_DIR_FAILED, path);
88 return;
89 }
90
91 callback.Run(ScreenshotGrabberDelegate::FILE_SUCCESS, path);
92 }
93
94 } // namespace
95
96 void ScreenshotGrabberDelegate::PrepareFileAndRunOnBlockingPool(
97 const base::FilePath& path,
98 scoped_refptr<base::TaskRunner> blocking_task_runner,
99 const FileCallback& callback_on_blocking_pool) {
100 blocking_task_runner->PostTask(
101 FROM_HERE,
102 base::Bind(EnsureLocalDirectoryExists, path, callback_on_blocking_pool));
103 }
104
105 ScreenshotGrabber::ScreenshotGrabber(
106 ScreenshotGrabberDelegate* client,
107 scoped_refptr<base::TaskRunner> blocking_task_runner)
108 : client_(client),
109 blocking_task_runner_(blocking_task_runner),
110 factory_(this) {
111 }
112
113 ScreenshotGrabber::~ScreenshotGrabber() {
114 }
115
116 void ScreenshotGrabber::TakeScreenshot(gfx::NativeWindow window,
117 const gfx::Rect& rect,
118 const base::FilePath& screenshot_path) {
119 DCHECK(base::MessageLoopForUI::IsCurrent());
120 last_screenshot_timestamp_ = base::TimeTicks::Now();
121
122 bool is_partial = true;
123 // Window identifier is used to log a message on failure to capture a full
124 // screen (i.e. non partial) screenshot. The only time is_partial can be
125 // false, we will also have an identification string for the window.
126 std::string window_identifier;
127 #if defined(USE_AURA)
128 aura::Window* aura_window = static_cast<aura::Window*>(window);
129 is_partial = rect.size() != aura_window->bounds().size();
130 window_identifier = aura_window->GetBoundsInScreen().ToString();
131 #endif
132 ui::GrabWindowSnapshotAsync(
133 window, rect, blocking_task_runner_,
134 base::Bind(&ScreenshotGrabber::GrabWindowSnapshotAsyncCallback,
135 factory_.GetWeakPtr(), window_identifier, screenshot_path,
136 is_partial));
137 }
138
139 bool ScreenshotGrabber::CanTakeScreenshot() {
140 return last_screenshot_timestamp_.is_null() ||
141 base::TimeTicks::Now() - last_screenshot_timestamp_ >
142 base::TimeDelta::FromMilliseconds(kScreenshotMinimumIntervalInMS);
143 }
144
145 void ScreenshotGrabber::NotifyScreenshotCompleted(
146 ScreenshotGrabberObserver::Result screenshot_result,
147 const base::FilePath& screenshot_path) {
148 DCHECK(base::MessageLoopForUI::IsCurrent());
149 FOR_EACH_OBSERVER(ScreenshotGrabberObserver, observers_,
150 OnScreenshotCompleted(screenshot_result, screenshot_path));
151 }
152
153 void ScreenshotGrabber::AddObserver(ScreenshotGrabberObserver* observer) {
154 observers_.AddObserver(observer);
155 }
156
157 void ScreenshotGrabber::RemoveObserver(ScreenshotGrabberObserver* observer) {
158 observers_.RemoveObserver(observer);
159 }
160
161 bool ScreenshotGrabber::HasObserver(
162 const ScreenshotGrabberObserver* observer) const {
163 return observers_.HasObserver(observer);
164 }
165
166 void ScreenshotGrabber::GrabWindowSnapshotAsyncCallback(
167 const std::string& window_identifier,
168 base::FilePath screenshot_path,
169 bool is_partial,
170 scoped_refptr<base::RefCountedBytes> png_data) {
171 DCHECK(base::MessageLoopForUI::IsCurrent());
172 if (!png_data.get()) {
173 if (is_partial) {
174 LOG(ERROR) << "Failed to grab the window screenshot";
175 NotifyScreenshotCompleted(
176 ScreenshotGrabberObserver::SCREENSHOT_GRABWINDOW_PARTIAL_FAILED,
177 screenshot_path);
178 } else {
179 LOG(ERROR) << "Failed to grab the window screenshot for "
180 << window_identifier;
181 NotifyScreenshotCompleted(
182 ScreenshotGrabberObserver::SCREENSHOT_GRABWINDOW_FULL_FAILED,
183 screenshot_path);
184 }
185 return;
186 }
187
188 ShowNotificationCallback notification_callback(base::Bind(
189 &ScreenshotGrabber::NotifyScreenshotCompleted, factory_.GetWeakPtr()));
190 client_->PrepareFileAndRunOnBlockingPool(
191 screenshot_path, blocking_task_runner_,
192 base::Bind(&SaveScreenshot, base::MessageLoop::current()->task_runner(),
193 notification_callback, screenshot_path, png_data));
194 }
195
196 } // namespace ui
OLDNEW
« no previous file with comments | « ui/snapshot/screenshot_grabber.h ('k') | ui/snapshot/screenshot_grabber_observer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698