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

Side by Side Diff: components/screenshot_taker/screenshot_taker.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: Restrict to use_aura==1 and fix gn build Created 6 years, 1 month 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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 "components/screenshot_taker/screenshot_taker.h"
6
7 #include <climits>
8 #include <string>
9
10 #include "base/bind.h"
11 #include "base/files/file_util.h"
12 #include "base/logging.h"
13 #include "base/threading/sequenced_worker_pool.h"
14 #include "base/time/time.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "ui/aura/window.h"
17 #include "ui/gfx/image/image.h"
18 #include "ui/snapshot/snapshot.h"
19
20 namespace {
21 // The minimum interval between two screenshot commands. It has to be
22 // more than 1000 to prevent the conflict of filenames.
23 const int kScreenshotMinimumIntervalInMS = 1000;
24
25 typedef base::Callback<
26 void(ScreenshotTakerObserver::Result screenshot_result,
27 const base::FilePath& screenshot_path)> ShowNotificationCallback;
28
29 void SaveScreenshot(const ShowNotificationCallback& callback,
30 const base::FilePath& screenshot_path,
31 scoped_refptr<base::RefCountedBytes> png_data,
32 ScreenshotTakerClient::WritableFileResult result,
33 const base::FilePath& local_path) {
34 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
35 DCHECK(!screenshot_path.empty());
36
37 // Convert WritableFileResult into ScreenshotTakerObserver::Result.
38 ScreenshotTakerObserver::Result screenshot_result =
39 ScreenshotTakerObserver::SCREENSHOT_SUCCESS;
40 switch(result) {
41 case ScreenshotTakerClient::WRITABLE_FILE_SUCCESS:
42 // Successful so far, continue to attempt to take screenshot.
43 break;
44 case ScreenshotTakerClient::WRITABLE_FILE_CHECK_DIR_FAILED:
45 screenshot_result =
46 ScreenshotTakerObserver::SCREENSHOT_CHECK_DIR_FAILED;
47 break;
48 case ScreenshotTakerClient::WRITABLE_FILE_CREATE_DIR_FAILED:
49 screenshot_result =
50 ScreenshotTakerObserver::SCREENSHOT_CREATE_DIR_FAILED;
51 break;
52 case ScreenshotTakerClient::WRITABLE_FILE_CREATE_FAILED:
53 screenshot_result =
54 ScreenshotTakerObserver::SCREENSHOT_CREATE_FILE_FAILED;
55 break;
56 }
57
58 if (screenshot_result == ScreenshotTakerObserver::SCREENSHOT_SUCCESS &&
59 static_cast<size_t>(base::WriteFile(
60 local_path,
61 reinterpret_cast<char*>(&(png_data->data()[0])),
62 png_data->size())) != png_data->size()) {
63 LOG(ERROR) << "Failed to save to " << local_path.value();
64 screenshot_result = ScreenshotTakerObserver::SCREENSHOT_WRITE_FILE_FAILED;
65 }
66
67 // Report the result on the UI thread.
68 content::BrowserThread::PostTask(
69 content::BrowserThread::UI, FROM_HERE,
70 base::Bind(callback, screenshot_result, screenshot_path));
71 }
72
73 void EnsureLocalDirectoryExists(
74 const base::FilePath& path,
75 ScreenshotTakerClient::WritableFileCallback callback) {
76 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
77 DCHECK(!path.empty());
78
79 if (!base::CreateDirectory(path.DirName())) {
80 LOG(ERROR) << "Failed to ensure the existence of "
81 << path.DirName().value();
82 content::BrowserThread::PostTask(
83 content::BrowserThread::UI, FROM_HERE,
84 base::Bind(callback,
85 ScreenshotTakerClient::WRITABLE_FILE_CREATE_DIR_FAILED,
86 path));
87 return;
88 }
89
90 callback.Run(ScreenshotTakerClient::WRITABLE_FILE_SUCCESS, path);
91 }
92
93 } // namespace
94
95 void ScreenshotTakerClient::PrepareWritableFileAndRunOnBlockingPool(
96 const base::FilePath& path,
97 WritableFileCallback callback_on_blocking_pool) {
98 content::BrowserThread::GetBlockingPool()->PostTask(
99 FROM_HERE, base::Bind(EnsureLocalDirectoryExists,
100 path,
101 callback_on_blocking_pool));
102 }
103
104 ScreenshotTaker::ScreenshotTaker(ScreenshotTakerClient* client)
105 : client_(client),
106 factory_(this) {
107 }
108
109 ScreenshotTaker::~ScreenshotTaker() {
110 }
111
112 void ScreenshotTaker::TakeScreenshot(
113 aura::Window* window,
114 const gfx::Rect& rect,
115 const base::FilePath& screenshot_path) {
116 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
117 last_screenshot_timestamp_ = base::Time::Now();
118
119 bool is_partial = rect == window->bounds();
120 ui::GrabWindowSnapshotAsync(
121 window,
122 rect,
123 content::BrowserThread::GetBlockingPool(),
124 base::Bind(&ScreenshotTaker::GrabWindowSnapshotAsyncCallback,
125 factory_.GetWeakPtr(),
126 window->GetBoundsInScreen().ToString(),
127 screenshot_path,
128 is_partial));
129 }
130
131 bool ScreenshotTaker::CanTakeScreenshot() {
132 return last_screenshot_timestamp_.is_null() ||
133 base::Time::Now() - last_screenshot_timestamp_ >
134 base::TimeDelta::FromMilliseconds(
135 kScreenshotMinimumIntervalInMS);
136 }
137
138 void ScreenshotTaker::NotifyScreenshotCompleted(
139 ScreenshotTakerObserver::Result screenshot_result,
140 const base::FilePath& screenshot_path) {
141 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
142 FOR_EACH_OBSERVER(ScreenshotTakerObserver, observers_,
143 OnScreenshotCompleted(screenshot_result, screenshot_path));
144 }
145
146 void ScreenshotTaker::AddObserver(ScreenshotTakerObserver* observer) {
147 observers_.AddObserver(observer);
148 }
149
150 void ScreenshotTaker::RemoveObserver(ScreenshotTakerObserver* observer) {
151 observers_.RemoveObserver(observer);
152 }
153
154 bool ScreenshotTaker::HasObserver(
155 const ScreenshotTakerObserver* observer) const {
156 return observers_.HasObserver(observer);
157 }
158
159 void ScreenshotTaker::GrabWindowSnapshotAsyncCallback(
160 const std::string& screen_bounds,
161 base::FilePath screenshot_path,
162 bool is_partial,
163 scoped_refptr<base::RefCountedBytes> png_data) {
164 if (!png_data.get()) {
165 if (is_partial) {
166 LOG(ERROR) << "Failed to grab the window screenshot";
167 NotifyScreenshotCompleted(
168 ScreenshotTakerObserver::SCREENSHOT_GRABWINDOW_PARTIAL_FAILED,
169 screenshot_path);
170 } else {
171 LOG(ERROR) << "Failed to grab the window screenshot for "
172 << screen_bounds;
173 NotifyScreenshotCompleted(
174 ScreenshotTakerObserver::SCREENSHOT_GRABWINDOW_FULL_FAILED,
175 screenshot_path);
176 }
177 return;
178 }
179
180 client_->PrepareWritableFileAndRunOnBlockingPool(
181 screenshot_path, base::Bind(
182 &SaveScreenshot,
183 base::Bind(&ScreenshotTaker::NotifyScreenshotCompleted,
184 factory_.GetWeakPtr()),
185 screenshot_path,
186 png_data));
187 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698