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

Side by Side Diff: chrome/browser/ui/ash/screenshot_taker.cc

Issue 13105002: Screenshot effect non-obvious (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: window fix Created 7 years, 8 months 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/ash/screenshot_taker.h" 5 #include "chrome/browser/ui/ash/screenshot_taker.h"
6 6
7 #include <climits> 7 #include <climits>
8 #include <string> 8 #include <string>
9 9
10 #include "ash/shell.h" 10 #include "ash/shell.h"
11 #include "ash/shell_delegate.h"
12 #include "ash/shell_window_ids.h"
13 #include "base/bind.h" 11 #include "base/bind.h"
14 #include "base/file_util.h" 12 #include "base/file_util.h"
15 #include "base/files/file_path.h"
16 #include "base/logging.h" 13 #include "base/logging.h"
17 #include "base/memory/ref_counted_memory.h" 14 #include "base/memory/ref_counted_memory.h"
18 #include "base/stringprintf.h" 15 #include "base/stringprintf.h"
19 #include "base/threading/sequenced_worker_pool.h" 16 #include "base/threading/sequenced_worker_pool.h"
20 #include "base/time.h" 17 #include "base/time.h"
18 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/download/download_prefs.h" 20 #include "chrome/browser/download/download_prefs.h"
21 #include "chrome/browser/notifications/notification.h"
22 #include "chrome/browser/notifications/notification_ui_manager.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/profiles/profile_manager.h"
24 #include "chrome/browser/ui/webui/screenshot_source.h" 24 #include "chrome/browser/ui/webui/screenshot_source.h"
25 #include "chrome/browser/ui/window_snapshot/window_snapshot.h" 25 #include "chrome/browser/ui/window_snapshot/window_snapshot.h"
26 #include "content/public/browser/browser_thread.h" 26 #include "content/public/browser/browser_thread.h"
27 #include "grit/ash_strings.h"
28 #include "grit/theme_resources.h"
27 #include "ui/aura/root_window.h" 29 #include "ui/aura/root_window.h"
28 #include "ui/aura/window.h" 30 #include "ui/aura/window.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/base/resource/resource_bundle.h"
33 #include "ui/gfx/image/image.h"
29 34
30 #if defined(OS_CHROMEOS) 35 #if defined(OS_CHROMEOS)
31 #include "chrome/browser/chromeos/drive/drive_file_system_util.h" 36 #include "chrome/browser/chromeos/drive/drive_file_system_util.h"
37 #include "chrome/browser/chromeos/extensions/file_manager_util.h"
32 #include "chrome/browser/chromeos/login/user_manager.h" 38 #include "chrome/browser/chromeos/login/user_manager.h"
33 #endif 39 #endif
34 40
35 namespace { 41 namespace {
36 // How opaque should the layer that we flash onscreen to provide visual
37 // feedback after the screenshot is taken be?
38 const float kVisualFeedbackLayerOpacity = 0.25f;
39
40 // How long should the visual feedback layer be displayed?
41 const int64 kVisualFeedbackLayerDisplayTimeMs = 100;
42
43 // The minimum interval between two screenshot commands. It has to be 42 // The minimum interval between two screenshot commands. It has to be
44 // more than 1000 to prevent the conflict of filenames. 43 // more than 1000 to prevent the conflict of filenames.
45 const int kScreenshotMinimumIntervalInMS = 1000; 44 const int kScreenshotMinimumIntervalInMS = 1000;
46 45
46 const char kNotificationOriginUrl[] = "chrome://screenshot";
47 47
48 void SaveScreenshotInternal(const base::FilePath& screenshot_path, 48 // Delegate for a notification. This class has two roles: to implement callback
49 // methods for notification, and to provide an identity of the associated
50 // notification.
51 class ScreenshotTakerNotificationDelegate : public NotificationDelegate {
52 public:
53 ScreenshotTakerNotificationDelegate(const std::string& id_text,
54 bool success,
55 const base::FilePath& screenshot_path)
56 : id_text_(id_text),
57 success_(success),
58 screenshot_path_(screenshot_path) {
59 }
60
61 // Overridden from NotificationDelegate:
62 virtual void Display() OVERRIDE {}
63 virtual void Error() OVERRIDE {}
64 virtual void Close(bool by_user) OVERRIDE {}
65 virtual void Click() OVERRIDE {
66 if (!success_)
67 return;
68 #if defined(OS_CHROMEOS)
69 file_manager_util::ShowFileInFolder(screenshot_path_);
70 #else
71 // TODO(sschmitz): perhaps add similar action for Windows.
72 #endif
73 }
74 virtual std::string id() const OVERRIDE { return id_text_; }
75 virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE {
76 return NULL;
77 }
78
79 private:
80 virtual ~ScreenshotTakerNotificationDelegate() {}
81
82 const std::string id_text_;
83 const bool success_;
84 const base::FilePath screenshot_path_;
85
86 DISALLOW_COPY_AND_ASSIGN(ScreenshotTakerNotificationDelegate);
87 };
88
89 void ShowNotificationCaller(base::WeakPtr<ScreenshotTaker> screenshot_taker,
sky 2013/04/03 23:16:09 Is there a reason you went with WeakPtr here rathe
sschmitz 2013/04/04 01:06:08 Using Callback instead. Done.
90 ScreenshotTakerObserver::Result screenshot_result,
91 const base::FilePath& screenshot_path) {
92 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
93 if (screenshot_taker.get())
94 screenshot_taker->ShowNotification(screenshot_result, screenshot_path);
95 }
96
97 void PostShowNotification(base::WeakPtr<ScreenshotTaker> screenshot_taker,
98 ScreenshotTakerObserver::Result screenshot_result,
99 const base::FilePath& screenshot_path) {
100 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
101 content::BrowserThread::PostTask(
102 content::BrowserThread::UI, FROM_HERE,
103 base::Bind(&ShowNotificationCaller,
104 screenshot_taker,
105 screenshot_result,
106 screenshot_path));
107 }
108
109 void SaveScreenshotInternal(base::WeakPtr<ScreenshotTaker> screenshot_taker,
110 const base::FilePath& screenshot_path,
49 scoped_refptr<base::RefCountedBytes> png_data) { 111 scoped_refptr<base::RefCountedBytes> png_data) {
50 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 112 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
51 DCHECK(!screenshot_path.empty()); 113 DCHECK(!screenshot_path.empty());
114 ScreenshotTakerObserver::Result result =
115 ScreenshotTakerObserver::SCREENSHOT_SUCCESS;
52 if (static_cast<size_t>(file_util::WriteFile( 116 if (static_cast<size_t>(file_util::WriteFile(
53 screenshot_path, 117 screenshot_path,
54 reinterpret_cast<char*>(&(png_data->data()[0])), 118 reinterpret_cast<char*>(&(png_data->data()[0])),
55 png_data->size())) != png_data->size()) { 119 png_data->size())) != png_data->size()) {
56 LOG(ERROR) << "Failed to save to " << screenshot_path.value(); 120 LOG(ERROR) << "Failed to save to " << screenshot_path.value();
121 result = ScreenshotTakerObserver::SCREENSHOT_WRITE_FILE_FAILED;
57 } 122 }
123 PostShowNotification(screenshot_taker, result, screenshot_path);
58 } 124 }
59 125
60 void SaveScreenshot(const base::FilePath& screenshot_path, 126 void SaveScreenshot(base::WeakPtr<ScreenshotTaker> screenshot_taker,
127 const base::FilePath& screenshot_path,
61 scoped_refptr<base::RefCountedBytes> png_data) { 128 scoped_refptr<base::RefCountedBytes> png_data) {
62 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 129 DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
63 DCHECK(!screenshot_path.empty()); 130 DCHECK(!screenshot_path.empty());
64 131
65 if (!file_util::CreateDirectory(screenshot_path.DirName())) { 132 if (!file_util::CreateDirectory(screenshot_path.DirName())) {
66 LOG(ERROR) << "Failed to ensure the existence of " 133 LOG(ERROR) << "Failed to ensure the existence of "
67 << screenshot_path.DirName().value(); 134 << screenshot_path.DirName().value();
135 PostShowNotification(
136 screenshot_taker,
137 ScreenshotTakerObserver::SCREENSHOT_CREATE_DIR_FAILED,
138 screenshot_path);
68 return; 139 return;
69 } 140 }
70 SaveScreenshotInternal(screenshot_path, png_data); 141 SaveScreenshotInternal(screenshot_taker, screenshot_path, png_data);
71 } 142 }
72 143
73 // TODO(kinaba): crbug.com/140425, remove this ungly #ifdef dispatch. 144 // TODO(kinaba): crbug.com/140425, remove this ungly #ifdef dispatch.
74 #if defined(OS_CHROMEOS) 145 #if defined(OS_CHROMEOS)
75 void SaveScreenshotToDrive(scoped_refptr<base::RefCountedBytes> png_data, 146 void SaveScreenshotToDrive(base::WeakPtr<ScreenshotTaker> screenshot_taker,
147 scoped_refptr<base::RefCountedBytes> png_data,
76 drive::DriveFileError error, 148 drive::DriveFileError error,
77 const base::FilePath& local_path) { 149 const base::FilePath& local_path) {
78 if (error != drive::DRIVE_FILE_OK) { 150 if (error != drive::DRIVE_FILE_OK) {
79 LOG(ERROR) << "Failed to write screenshot image to Google Drive: " << error; 151 LOG(ERROR) << "Failed to write screenshot image to Google Drive: " << error;
152 PostShowNotification(
153 screenshot_taker,
154 ScreenshotTakerObserver::SCREENSHOT_CREATE_FILE_FAILED,
155 local_path);
80 return; 156 return;
81 } 157 }
82 SaveScreenshotInternal(local_path, png_data); 158 SaveScreenshotInternal(screenshot_taker, local_path, png_data);
83 } 159 }
84 160
85 void EnsureDirectoryExistsCallback( 161 void EnsureDirectoryExistsCallback(
162 base::WeakPtr<ScreenshotTaker> screenshot_taker,
86 Profile* profile, 163 Profile* profile,
87 const base::FilePath& screenshot_path, 164 const base::FilePath& screenshot_path,
88 scoped_refptr<base::RefCountedBytes> png_data, 165 scoped_refptr<base::RefCountedBytes> png_data,
89 drive::DriveFileError error) { 166 drive::DriveFileError error) {
90 // It is okay to fail with DRIVE_FILE_ERROR_EXISTS since anyway the directory 167 // It is okay to fail with DRIVE_FILE_ERROR_EXISTS since anyway the directory
91 // of the target file exists. 168 // of the target file exists.
92 if (error == drive::DRIVE_FILE_OK || 169 if (error == drive::DRIVE_FILE_OK ||
93 error == drive::DRIVE_FILE_ERROR_EXISTS) { 170 error == drive::DRIVE_FILE_ERROR_EXISTS) {
171 // Note: The last two arguments of SaveScreenshotToDrive are appended by
172 // PrepareWritableFileAndRun.
94 drive::util::PrepareWritableFileAndRun( 173 drive::util::PrepareWritableFileAndRun(
95 profile, 174 profile,
96 screenshot_path, 175 screenshot_path,
97 base::Bind(&SaveScreenshotToDrive, png_data)); 176 base::Bind(&SaveScreenshotToDrive, screenshot_taker, png_data));
98 } else { 177 } else {
99 LOG(ERROR) << "Failed to ensure the existence of the specified directory " 178 LOG(ERROR) << "Failed to ensure the existence of the specified directory "
100 << "in Google Drive: " << error; 179 << "in Google Drive: " << error;
180 ShowNotificationCaller(
181 screenshot_taker,
182 ScreenshotTakerObserver::SCREENSHOT_CHECK_DIR_FAILED,
183 screenshot_path);
101 } 184 }
102 } 185 }
103 186
104 void PostSaveScreenshotTask(const base::FilePath& screenshot_path, 187 void PostSaveScreenshotTask(base::WeakPtr<ScreenshotTaker> screenshot_taker,
188 Profile* profile,
189 const base::FilePath& screenshot_path,
105 scoped_refptr<base::RefCountedBytes> png_data) { 190 scoped_refptr<base::RefCountedBytes> png_data) {
106 if (drive::util::IsUnderDriveMountPoint(screenshot_path)) { 191 if (drive::util::IsUnderDriveMountPoint(screenshot_path)) {
107 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); 192 // Note: The last argument of EnsureDirectoryExistsCallback is
108 if (profile) { 193 // appended by EnsureDirectoryExists.
109 drive::util::EnsureDirectoryExists( 194 drive::util::EnsureDirectoryExists(
110 profile, 195 profile,
111 screenshot_path.DirName(), 196 screenshot_path.DirName(),
112 base::Bind(&EnsureDirectoryExistsCallback, 197 base::Bind(&EnsureDirectoryExistsCallback,
113 profile, 198 screenshot_taker,
114 screenshot_path, 199 profile,
115 png_data)); 200 screenshot_path,
116 } 201 png_data));
117 } else { 202 } else {
118 content::BrowserThread::GetBlockingPool()->PostTask( 203 content::BrowserThread::GetBlockingPool()->PostTask(
119 FROM_HERE, base::Bind(&SaveScreenshot, screenshot_path, png_data)); 204 FROM_HERE, base::Bind(&SaveScreenshot,
205 screenshot_taker,
206 screenshot_path,
207 png_data));
120 } 208 }
121 } 209 }
122 #else 210 #else
123 void PostSaveScreenshotTask(const base::FilePath& screenshot_path, 211 void PostSaveScreenshotTask(base::WeakPtr<ScreenshotTaker> screenshot_taker,
212 Profile* profile,
213 const base::FilePath& screenshot_path,
124 scoped_refptr<base::RefCountedBytes> png_data) { 214 scoped_refptr<base::RefCountedBytes> png_data) {
125 content::BrowserThread::GetBlockingPool()->PostTask( 215 content::BrowserThread::GetBlockingPool()->PostTask(
126 FROM_HERE, base::Bind(&SaveScreenshot, screenshot_path, png_data)); 216 FROM_HERE, base::Bind(&SaveScreenshot,
217 screenshot_taker,
218 screenshot_path,
219 png_data));
127 } 220 }
128 #endif 221 #endif
129 222
130 bool GrabWindowSnapshot(aura::Window* window, 223 bool GrabWindowSnapshot(aura::Window* window,
131 const gfx::Rect& snapshot_bounds, 224 const gfx::Rect& snapshot_bounds,
132 std::vector<unsigned char>* png_data) { 225 std::vector<unsigned char>* png_data) {
133 #if defined(OS_LINUX) 226 #if defined(OS_LINUX)
134 // chrome::GrabWindowSnapshotForUser checks this too, but 227 // chrome::GrabWindowSnapshotForUser checks this too, but
135 // RootWindow::GrabSnapshot does not. 228 // RootWindow::GrabSnapshot does not.
136 if (ScreenshotSource::AreScreenshotsDisabled()) 229 if (ScreenshotSource::AreScreenshotsDisabled())
137 return false; 230 return false;
138 231
139 // We use XGetImage() for Linux/ChromeOS for performance reasons. 232 // We use XGetImage() for Linux/ChromeOS for performance reasons.
140 // See crbug.com/119492 233 // See crbug.com/119492
141 // TODO(mukai): remove this when the performance issue has been fixed. 234 // TODO(mukai): remove this when the performance issue has been fixed.
142 if (window->GetRootWindow()->GrabSnapshot(snapshot_bounds, png_data)) 235 if (window->GetRootWindow()->GrabSnapshot(snapshot_bounds, png_data))
143 return true; 236 return true;
144 #endif // OS_LINUX 237 #endif // OS_LINUX
145 238
146 return chrome::GrabWindowSnapshotForUser(window, png_data, snapshot_bounds); 239 return chrome::GrabWindowSnapshotForUser(window, png_data, snapshot_bounds);
147 } 240 }
148 241
149 } // namespace 242 } // namespace
150 243
151 ScreenshotTaker::ScreenshotTaker() { 244 ScreenshotTaker::ScreenshotTaker(Profile* profile)
245 : profile_(profile),
246 ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {
247 DCHECK(profile_);
152 } 248 }
153 249
154 ScreenshotTaker::~ScreenshotTaker() { 250 ScreenshotTaker::~ScreenshotTaker() {
155 } 251 }
156 252
157 void ScreenshotTaker::HandleTakeScreenshotForAllRootWindows() { 253 void ScreenshotTaker::HandleTakeScreenshotForAllRootWindows() {
158 base::FilePath screenshot_directory; 254 base::FilePath screenshot_directory;
159 if (!ScreenshotSource::GetScreenshotDirectory(&screenshot_directory)) 255 if (!screenshot_directory_for_test_.empty()) {
256 screenshot_directory = screenshot_directory_for_test_;
257 } else if (!ScreenshotSource::GetScreenshotDirectory(&screenshot_directory)) {
258 ShowNotification(ScreenshotTakerObserver::SCREENSHOT_GET_DIR_FAILED,
259 base::FilePath());
160 return; 260 return;
261 }
262 std::string screenshot_basename = !screenshot_basename_for_test_.empty() ?
263 screenshot_basename_for_test_ :
264 ScreenshotSource::GetScreenshotBaseFilename();
161 265
162 std::string screenshot_basename =
163 ScreenshotSource::GetScreenshotBaseFilename();
164 ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows(); 266 ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
165 // Reorder root_windows to take the primary root window's snapshot at first. 267 // Reorder root_windows to take the primary root window's snapshot at first.
166 aura::RootWindow* primary_root = ash::Shell::GetPrimaryRootWindow(); 268 aura::RootWindow* primary_root = ash::Shell::GetPrimaryRootWindow();
167 if (*(root_windows.begin()) != primary_root) { 269 if (*(root_windows.begin()) != primary_root) {
168 root_windows.erase(std::find( 270 root_windows.erase(std::find(
169 root_windows.begin(), root_windows.end(), primary_root)); 271 root_windows.begin(), root_windows.end(), primary_root));
170 root_windows.insert(root_windows.begin(), primary_root); 272 root_windows.insert(root_windows.begin(), primary_root);
171 } 273 }
172 for (size_t i = 0; i < root_windows.size(); ++i) { 274 for (size_t i = 0; i < root_windows.size(); ++i) {
173 aura::RootWindow* root_window = root_windows[i]; 275 aura::RootWindow* root_window = root_windows[i];
174 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); 276 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes);
175 std::string basename = screenshot_basename; 277 std::string basename = screenshot_basename;
176 gfx::Rect rect = root_window->bounds(); 278 gfx::Rect rect = root_window->bounds();
177 if (root_windows.size() > 1) 279 if (root_windows.size() > 1)
178 basename += base::StringPrintf(" - Display %d", static_cast<int>(i + 1)); 280 basename += base::StringPrintf(" - Display %d", static_cast<int>(i + 1));
281 base::FilePath screenshot_path =
282 screenshot_directory.AppendASCII(basename + ".png");
179 if (GrabWindowSnapshot(root_window, rect, &png_data->data())) { 283 if (GrabWindowSnapshot(root_window, rect, &png_data->data())) {
180 DisplayVisualFeedback(rect); 284 PostSaveScreenshotTask(factory_.GetWeakPtr(), profile_,
181 PostSaveScreenshotTask( 285 screenshot_path, png_data);
182 screenshot_directory.AppendASCII(basename + ".png"), png_data);
183 } else { 286 } else {
184 LOG(ERROR) << "Failed to grab the window screenshot for " << i; 287 LOG(ERROR) << "Failed to grab the window screenshot for " << i;
288 ShowNotification(
289 ScreenshotTakerObserver::SCREENSHOT_GRABWINDOW_FULL_FAILED,
290 screenshot_path);
185 } 291 }
186 } 292 }
187 last_screenshot_timestamp_ = base::Time::Now(); 293 last_screenshot_timestamp_ = base::Time::Now();
188 } 294 }
189 295
190 void ScreenshotTaker::HandleTakePartialScreenshot( 296 void ScreenshotTaker::HandleTakePartialScreenshot(
191 aura::Window* window, const gfx::Rect& rect) { 297 aura::Window* window, const gfx::Rect& rect) {
192 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 298 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
193 299
194 base::FilePath screenshot_directory; 300 base::FilePath screenshot_directory;
195 if (!ScreenshotSource::GetScreenshotDirectory(&screenshot_directory)) 301 if (!screenshot_directory_for_test_.empty()) {
302 screenshot_directory = screenshot_directory_for_test_;
303 } else if (!ScreenshotSource::GetScreenshotDirectory(&screenshot_directory)) {
304 ShowNotification(ScreenshotTakerObserver::SCREENSHOT_GET_DIR_FAILED,
305 base::FilePath());
196 return; 306 return;
307 }
197 308
198 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); 309 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes);
199 310
311 std::string screenshot_basename = !screenshot_basename_for_test_.empty() ?
312 screenshot_basename_for_test_ :
313 ScreenshotSource::GetScreenshotBaseFilename();
314 base::FilePath screenshot_path =
315 screenshot_directory.AppendASCII(screenshot_basename + ".png");
200 if (GrabWindowSnapshot(window, rect, &png_data->data())) { 316 if (GrabWindowSnapshot(window, rect, &png_data->data())) {
201 last_screenshot_timestamp_ = base::Time::Now(); 317 last_screenshot_timestamp_ = base::Time::Now();
202 DisplayVisualFeedback(rect); 318 PostSaveScreenshotTask(factory_.GetWeakPtr(), profile_,
203 PostSaveScreenshotTask( 319 screenshot_path, png_data);
204 screenshot_directory.AppendASCII(
205 ScreenshotSource::GetScreenshotBaseFilename() + ".png"),
206 png_data);
207 } else { 320 } else {
208 LOG(ERROR) << "Failed to grab the window screenshot"; 321 LOG(ERROR) << "Failed to grab the window screenshot";
322 ShowNotification(
323 ScreenshotTakerObserver::SCREENSHOT_GRABWINDOW_PARTIAL_FAILED,
324 screenshot_path);
209 } 325 }
210 } 326 }
211 327
212 bool ScreenshotTaker::CanTakeScreenshot() { 328 bool ScreenshotTaker::CanTakeScreenshot() {
213 return last_screenshot_timestamp_.is_null() || 329 return last_screenshot_timestamp_.is_null() ||
214 base::Time::Now() - last_screenshot_timestamp_ > 330 base::Time::Now() - last_screenshot_timestamp_ >
215 base::TimeDelta::FromMilliseconds( 331 base::TimeDelta::FromMilliseconds(
216 kScreenshotMinimumIntervalInMS); 332 kScreenshotMinimumIntervalInMS);
217 } 333 }
218 334
219 void ScreenshotTaker::CloseVisualFeedbackLayer() { 335 void ScreenshotTaker::ShowNotification(
220 visual_feedback_layer_.reset(); 336 ScreenshotTakerObserver::Result screenshot_result,
337 const base::FilePath& screenshot_path) {
338 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
339 static int id = 0;
340 std::string id_text = base::StringPrintf("screenshot_%3.3d", ++id);
341 string16 replace_id = UTF8ToUTF16(id_text);
342 bool success =
343 (screenshot_result == ScreenshotTakerObserver::SCREENSHOT_SUCCESS);
344 Notification notification(
345 GURL(kNotificationOriginUrl),
346 ui::ResourceBundle::GetSharedInstance().GetImageNamed(
347 IDR_SCREENSHOT_NOTIFICATION_ICON),
348 l10n_util::GetStringUTF16(
349 success ?
350 IDS_ASH_SCREENSHOT_NOTIFICATION_TITLE_SUCCESS :
351 IDS_ASH_SCREENSHOT_NOTIFICATION_TITLE_FAIL),
352 success ?
353 #if defined(OS_CHROMEOS)
354 l10n_util::GetStringUTF16(IDS_ASH_SCREENSHOT_NOTIFICATION_TEXT_SUCCESS) :
355 #else
356 string16() : // TODO(sschmitz): Add desired text for Windows.
357 #endif
358 l10n_util::GetStringUTF16(IDS_ASH_SCREENSHOT_NOTIFICATION_TEXT_FAIL),
359 WebKit::WebTextDirectionDefault,
360 string16(),
361 replace_id,
362 new ScreenshotTakerNotificationDelegate(id_text,
363 success,
364 screenshot_path));
365 g_browser_process->notification_ui_manager()->Add(notification, profile_);
366
367 FOR_EACH_OBSERVER(ScreenshotTakerObserver, observers_,
368 OnScreenshotCompleted(screenshot_result, screenshot_path));
221 } 369 }
222 370
223 void ScreenshotTaker::DisplayVisualFeedback(const gfx::Rect& rect) { 371 void ScreenshotTaker::AddObserver(ScreenshotTakerObserver* observer) {
224 visual_feedback_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); 372 observers_.AddObserver(observer);
225 visual_feedback_layer_->SetColor(SK_ColorWHITE); 373 }
226 visual_feedback_layer_->SetOpacity(kVisualFeedbackLayerOpacity);
227 visual_feedback_layer_->SetBounds(rect);
228 374
229 ui::Layer* parent = ash::Shell::GetContainer( 375 void ScreenshotTaker::RemoveObserver(ScreenshotTakerObserver* observer) {
230 ash::Shell::GetActiveRootWindow(), 376 observers_.RemoveObserver(observer);
231 ash::internal::kShellWindowId_OverlayContainer)->layer(); 377 }
232 parent->Add(visual_feedback_layer_.get());
233 visual_feedback_layer_->SetVisible(true);
234 378
235 MessageLoopForUI::current()->PostDelayedTask( 379 bool ScreenshotTaker::HasObserver(ScreenshotTakerObserver* observer) const {
236 FROM_HERE, 380 return observers_.HasObserver(observer);
237 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer,
238 base::Unretained(this)),
239 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs));
240 } 381 }
382
383 void ScreenshotTaker::SetScreenshotDirectoryForTest(
384 const base::FilePath& directory) {
385 screenshot_directory_for_test_ = directory;
386 }
387
388 void ScreenshotTaker::SetScreenshotBasenameForTest(
389 const std::string& basename){
390 screenshot_basename_for_test_ = basename;
391 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698