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

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

Issue 10827193: Brushes up the code of screenshot filename. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/ash/screenshot_taker.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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"
(...skipping 17 matching lines...) Expand all
28 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
29 #include "ui/aura/root_window.h" 29 #include "ui/aura/root_window.h"
30 #include "ui/aura/window.h" 30 #include "ui/aura/window.h"
31 31
32 #if defined(OS_CHROMEOS) 32 #if defined(OS_CHROMEOS)
33 #include "chrome/browser/chromeos/gdata/gdata_util.h" 33 #include "chrome/browser/chromeos/gdata/gdata_util.h"
34 #include "chrome/browser/chromeos/login/user_manager.h" 34 #include "chrome/browser/chromeos/login/user_manager.h"
35 #endif 35 #endif
36 36
37 namespace { 37 namespace {
38 const int kScreenshotMinimumIntervalInMS = 500; 38 // How opaque should the layer that we flash onscreen to provide visual
39 // feedback after the screenshot is taken be?
40 const float kVisualFeedbackLayerOpacity = 0.25f;
41
42 // How long should the visual feedback layer be displayed?
43 const int64 kVisualFeedbackLayerDisplayTimeMs = 100;
44
45 // The minimum interval between two screenshot commands. It has to be
46 // more than 1000 to prevent the conflict of filenames.
47 const int kScreenshotMinimumIntervalInMS = 1000;
39 48
40 bool ShouldUse24HourClock() { 49 bool ShouldUse24HourClock() {
41 #if defined(OS_CHROMEOS) 50 #if defined(OS_CHROMEOS)
42 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); 51 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
43 if (profile) { 52 if (profile) {
44 PrefService* pref_service = profile->GetPrefs(); 53 PrefService* pref_service = profile->GetPrefs();
45 if (pref_service) { 54 if (pref_service) {
46 return pref_service->GetBoolean(prefs::kUse24HourClock); 55 return pref_service->GetBoolean(prefs::kUse24HourClock);
47 } 56 }
48 } 57 }
49 #endif 58 #endif
50 return base::GetHourClockType() == base::k24HourClock; 59 return base::GetHourClockType() == base::k24HourClock;
51 } 60 }
52 61
53 std::string GetScreenShotBaseFilename(bool use_24hour_clock) { 62 bool AreScreenshotsDisabled() {
63 return g_browser_process->local_state()->GetBoolean(
64 prefs::kDisableScreenshots);
65 }
66
67 std::string GetScreenshotBaseFilename() {
54 base::Time::Exploded now; 68 base::Time::Exploded now;
55 base::Time::Now().LocalExplode(&now); 69 base::Time::Now().LocalExplode(&now);
56 70
57 // We don't use base/i18n/time_formatting.h here because it doesn't 71 // We don't use base/i18n/time_formatting.h here because it doesn't
58 // support our format. Don't use ICU either to avoid i18n file names 72 // support our format. Don't use ICU either to avoid i18n file names
59 // for non-English locales. 73 // for non-English locales.
60 // TODO(mukai): integrate this logic somewhere time_formatting.h 74 // TODO(mukai): integrate this logic somewhere time_formatting.h
61 std::string file_name = base::StringPrintf( 75 std::string file_name = base::StringPrintf(
62 "Screenshot %d-%02d-%02d at ", now.year, now.month, now.day_of_month); 76 "Screenshot %d-%02d-%02d at ", now.year, now.month, now.day_of_month);
63 77
64 if (use_24hour_clock) { 78 if (ShouldUse24HourClock()) {
65 file_name.append(base::StringPrintf( 79 file_name.append(base::StringPrintf(
66 "%02d.%02d.%02d", now.hour, now.minute, now.second)); 80 "%02d.%02d.%02d", now.hour, now.minute, now.second));
67 } else { 81 } else {
68 int hour = now.hour; 82 int hour = now.hour;
69 if (hour > 12) { 83 if (hour > 12) {
70 hour -= 12; 84 hour -= 12;
71 } else if (hour == 0) { 85 } else if (hour == 0) {
72 hour = 12; 86 hour = 12;
73 } 87 }
74 file_name.append(base::StringPrintf( 88 file_name.append(base::StringPrintf(
75 "%d.%02d.%02d ", hour, now.minute, now.second)); 89 "%d.%02d.%02d ", hour, now.minute, now.second));
76 file_name.append((now.hour >= 12) ? "PM" : "AM"); 90 file_name.append((now.hour >= 12) ? "PM" : "AM");
77 } 91 }
78 92
79 return file_name; 93 return file_name;
80 } 94 }
81 95
82 FilePath GetScreenshotPath(const FilePath& base_directory, 96 bool GetScreenshotDirectory(FilePath* directory) {
83 const std::string& base_name) { 97 if (AreScreenshotsDisabled())
84 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 98 return false;
85 for (int retry = 0; retry < INT_MAX; retry++) {
86 std::string retry_suffix;
87 if (retry > 0)
88 retry_suffix = base::StringPrintf(" (%d)", retry + 1);
89 99
90 FilePath file_path = base_directory.AppendASCII( 100 bool is_logged_in = true;
91 base_name + retry_suffix + ".png"); 101 #if defined(OS_CHROMEOS)
92 if (!file_util::PathExists(file_path)) 102 is_logged_in = chromeos::UserManager::Get()->IsUserLoggedIn();
93 return file_path; 103 #endif
104
105 if (is_logged_in) {
106 DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext(
107 ash::Shell::GetInstance()->delegate()->GetCurrentBrowserContext());
108 *directory = download_prefs->DownloadPath();
109 } else {
110 if (!file_util::GetTempDir(directory)) {
111 LOG(ERROR) << "Failed to find temporary directory.";
112 return false;
113 }
94 } 114 }
95 return FilePath(); 115 return true;
96 } 116 }
97 117
98 void SaveScreenshotToLocalFile(scoped_refptr<base::RefCountedBytes> png_data, 118 void SaveScreenshot(const FilePath& screenshot_path,
99 const FilePath& screenshot_path) { 119 scoped_refptr<base::RefCountedBytes> png_data) {
100 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); 120 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
121 DCHECK(!screenshot_path.empty());
101 if (static_cast<size_t>(file_util::WriteFile( 122 if (static_cast<size_t>(file_util::WriteFile(
102 screenshot_path, 123 screenshot_path,
103 reinterpret_cast<char*>(&(png_data->data()[0])), 124 reinterpret_cast<char*>(&(png_data->data()[0])),
104 png_data->size())) != png_data->size()) { 125 png_data->size())) != png_data->size()) {
105 LOG(ERROR) << "Failed to save to " << screenshot_path.value(); 126 LOG(ERROR) << "Failed to save to " << screenshot_path.value();
106 } 127 }
107 } 128 }
108 129
109 void SaveScreenshot(const FilePath& screenshot_directory,
110 const std::string& base_name,
111 scoped_refptr<base::RefCountedBytes> png_data) {
112 FilePath screenshot_path = GetScreenshotPath(screenshot_directory, base_name);
113 if (screenshot_path.empty()) {
114 LOG(ERROR) << "Failed to find a screenshot file name.";
115 return;
116 }
117 SaveScreenshotToLocalFile(png_data, screenshot_path);
118 }
119
120 // TODO(kinaba): crbug.com/140425, remove this ungly #ifdef dispatch. 130 // TODO(kinaba): crbug.com/140425, remove this ungly #ifdef dispatch.
121 #ifdef OS_CHROMEOS 131 #ifdef OS_CHROMEOS
122 void SaveScreenshotToGData(scoped_refptr<base::RefCountedBytes> png_data, 132 void SaveScreenshotToGData(scoped_refptr<base::RefCountedBytes> png_data,
123 gdata::GDataFileError error, 133 gdata::GDataFileError error,
124 const FilePath& local_path) { 134 const FilePath& local_path) {
125 if (error != gdata::GDATA_FILE_OK) { 135 if (error != gdata::GDATA_FILE_OK) {
126 LOG(ERROR) << "Failed to write screenshot image to Google Drive: " << error; 136 LOG(ERROR) << "Failed to write screenshot image to Google Drive: " << error;
127 return; 137 return;
128 } 138 }
129 SaveScreenshotToLocalFile(png_data, local_path); 139 SaveScreenshot(local_path, png_data);
130 } 140 }
131 141
132 void PostSaveScreenshotTask(const FilePath& screenshot_directory, 142 void PostSaveScreenshotTask(const FilePath& screenshot_path,
133 const std::string& base_name,
134 scoped_refptr<base::RefCountedBytes> png_data) { 143 scoped_refptr<base::RefCountedBytes> png_data) {
135 if (gdata::util::IsUnderGDataMountPoint(screenshot_directory)) { 144 if (gdata::util::IsUnderGDataMountPoint(screenshot_path)) {
136 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); 145 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
137 if (profile) { 146 if (profile) {
138 // TODO(kinaba,mukai): crbug.com/140749. Take care of the case 147 // TODO(kinaba,mukai): crbug.com/140749. Take care of the case
139 // "base_name.png" already exists. 148 // "base_name.png" already exists.
kinaba 2012/08/07 05:01:30 We can remove this comment.
Jun Mukai 2012/08/07 05:03:27 Done.
140 gdata::util::PrepareWritableFileAndRun( 149 gdata::util::PrepareWritableFileAndRun(
141 profile, 150 profile,
142 screenshot_directory.Append(base_name + ".png"), 151 screenshot_path,
143 base::Bind(&SaveScreenshotToGData, png_data)); 152 base::Bind(&SaveScreenshotToGData, png_data));
144 } 153 }
145 } else { 154 } else {
146 content::BrowserThread::PostTask( 155 content::BrowserThread::PostTask(
147 content::BrowserThread::FILE, FROM_HERE, 156 content::BrowserThread::FILE, FROM_HERE,
148 base::Bind(&SaveScreenshot, screenshot_directory, base_name, png_data)); 157 base::Bind(&SaveScreenshot, screenshot_path, png_data));
149 } 158 }
150 } 159 }
151 #else 160 #else
152 void PostSaveScreenshotTask(const FilePath& screenshot_directory, 161 void PostSaveScreenshotTask(const FilePath& screenshot_path,
153 const std::string& base_name,
154 scoped_refptr<base::RefCountedBytes> png_data) { 162 scoped_refptr<base::RefCountedBytes> png_data) {
155 content::BrowserThread::PostTask( 163 content::BrowserThread::PostTask(
156 content::BrowserThread::FILE, FROM_HERE, 164 content::BrowserThread::FILE, FROM_HERE,
157 base::Bind(&SaveScreenshot, screenshot_directory, base_name, png_data)); 165 base::Bind(&SaveScreenshot, screenshot_path, png_data));
158 } 166 }
159 #endif 167 #endif
160 168
161 bool AreScreenshotsDisabled() {
162 return g_browser_process->local_state()->GetBoolean(
163 prefs::kDisableScreenshots);
164 }
165
166 bool GrabWindowSnapshot(aura::Window* window, 169 bool GrabWindowSnapshot(aura::Window* window,
167 const gfx::Rect& snapshot_bounds, 170 const gfx::Rect& snapshot_bounds,
168 std::vector<unsigned char>* png_data) { 171 std::vector<unsigned char>* png_data) {
169 #if defined(OS_LINUX) 172 #if defined(OS_LINUX)
170 // chrome::GrabWindowSnapshotForUser checks this too, but 173 // chrome::GrabWindowSnapshotForUser checks this too, but
171 // RootWindow::GrabSnapshot does not. 174 // RootWindow::GrabSnapshot does not.
172 if (AreScreenshotsDisabled()) 175 if (AreScreenshotsDisabled())
173 return false; 176 return false;
174 177
175 // We use XGetImage() for Linux/ChromeOS for performance reasons. 178 // We use XGetImage() for Linux/ChromeOS for performance reasons.
176 // See crbug.com/119492 179 // See crbug.com/119492
177 // TODO(mukai): remove this when the performance issue has been fixed. 180 // TODO(mukai): remove this when the performance issue has been fixed.
178 if (window->GetRootWindow()->GrabSnapshot(snapshot_bounds, png_data)) 181 if (window->GetRootWindow()->GrabSnapshot(snapshot_bounds, png_data))
179 return true; 182 return true;
180 #endif // OS_LINUX 183 #endif // OS_LINUX
181 184
182 return chrome::GrabWindowSnapshotForUser(window, png_data, snapshot_bounds); 185 return chrome::GrabWindowSnapshotForUser(window, png_data, snapshot_bounds);
183 } 186 }
184 187
185 // How opaque should the layer that we flash onscreen to provide visual
186 // feedback after the screenshot is taken be?
187 const float kVisualFeedbackLayerOpacity = 0.25f;
188
189 // How long should the visual feedback layer be displayed?
190 const int64 kVisualFeedbackLayerDisplayTimeMs = 100;
191
192 } // namespace 188 } // namespace
193 189
194 ScreenshotTaker::ScreenshotTaker() { 190 ScreenshotTaker::ScreenshotTaker() {
195 } 191 }
196 192
197 ScreenshotTaker::~ScreenshotTaker() { 193 ScreenshotTaker::~ScreenshotTaker() {
198 } 194 }
199 195
200 void ScreenshotTaker::HandleTakeScreenshot(aura::Window* window) { 196 void ScreenshotTaker::HandleTakeScreenshotForAllRootWindows() {
201 HandleTakePartialScreenshot(window, window->bounds()); 197 FilePath screenshot_directory;
198 if (!GetScreenshotDirectory(&screenshot_directory))
199 return;
200
201 std::string screenshot_basename = GetScreenshotBaseFilename();
202 ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
203 for (size_t i = 0; i < root_windows.size(); ++i) {
204 aura::RootWindow* root_window = root_windows[i];
205 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes);
206 std::string basename = screenshot_basename;
207 gfx::Rect rect = root_window->bounds();
208 if (root_windows.size() > 1)
209 basename += base::StringPrintf(" - %d", static_cast<int>(i + 1));
210 if (GrabWindowSnapshot(root_window, rect, &png_data->data())) {
211 DisplayVisualFeedback(rect);
212 PostSaveScreenshotTask(
213 screenshot_directory.AppendASCII(basename + ".png"), png_data);
214 } else {
215 LOG(ERROR) << "Failed to grab the window screenshot for " << i;
216 }
217 }
218 last_screenshot_timestamp_ = base::Time::Now();
202 } 219 }
203 220
204 void ScreenshotTaker::HandleTakePartialScreenshot( 221 void ScreenshotTaker::HandleTakePartialScreenshot(
205 aura::Window* window, const gfx::Rect& rect) { 222 aura::Window* window, const gfx::Rect& rect) {
206 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 223 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
207 224
208 if (AreScreenshotsDisabled()) 225 FilePath screenshot_directory;
226 if (!GetScreenshotDirectory(&screenshot_directory))
209 return; 227 return;
210 228
211 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); 229 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes);
212 230
213 bool is_logged_in = true;
214 #if defined(OS_CHROMEOS)
215 is_logged_in = chromeos::UserManager::Get()->IsUserLoggedIn();
216 #endif
217
218 FilePath screenshot_directory;
219 if (is_logged_in) {
220 DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext(
221 ash::Shell::GetInstance()->delegate()->GetCurrentBrowserContext());
222 screenshot_directory = download_prefs->DownloadPath();
223 } else {
224 if (!file_util::GetTempDir(&screenshot_directory)) {
225 LOG(ERROR) << "Failed to find temporary directory.";
226 return;
227 }
228 }
229
230 if (GrabWindowSnapshot(window, rect, &png_data->data())) { 231 if (GrabWindowSnapshot(window, rect, &png_data->data())) {
231 last_screenshot_timestamp_ = base::Time::Now(); 232 last_screenshot_timestamp_ = base::Time::Now();
232 DisplayVisualFeedback(rect); 233 DisplayVisualFeedback(rect);
233 PostSaveScreenshotTask(screenshot_directory, 234 PostSaveScreenshotTask(
234 GetScreenShotBaseFilename(ShouldUse24HourClock()), 235 screenshot_directory.AppendASCII(GetScreenshotBaseFilename() + ".png"),
235 png_data); 236 png_data);
236 } else { 237 } else {
237 LOG(ERROR) << "Failed to grab the window screenshot"; 238 LOG(ERROR) << "Failed to grab the window screenshot";
238 } 239 }
239 } 240 }
240 241
241 bool ScreenshotTaker::CanTakeScreenshot() { 242 bool ScreenshotTaker::CanTakeScreenshot() {
242 return last_screenshot_timestamp_.is_null() || 243 return last_screenshot_timestamp_.is_null() ||
243 base::Time::Now() - last_screenshot_timestamp_ > 244 base::Time::Now() - last_screenshot_timestamp_ >
244 base::TimeDelta::FromMilliseconds( 245 base::TimeDelta::FromMilliseconds(
245 kScreenshotMinimumIntervalInMS); 246 kScreenshotMinimumIntervalInMS);
(...skipping 14 matching lines...) Expand all
260 ash::internal::kShellWindowId_OverlayContainer)->layer(); 261 ash::internal::kShellWindowId_OverlayContainer)->layer();
261 parent->Add(visual_feedback_layer_.get()); 262 parent->Add(visual_feedback_layer_.get());
262 visual_feedback_layer_->SetVisible(true); 263 visual_feedback_layer_->SetVisible(true);
263 264
264 MessageLoopForUI::current()->PostDelayedTask( 265 MessageLoopForUI::current()->PostDelayedTask(
265 FROM_HERE, 266 FROM_HERE,
266 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer, 267 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer,
267 base::Unretained(this)), 268 base::Unretained(this)),
268 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs)); 269 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs));
269 } 270 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/ash/screenshot_taker.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698