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

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
139 // "base_name.png" already exists.
140 gdata::util::PrepareWritableFileAndRun( 147 gdata::util::PrepareWritableFileAndRun(
141 profile, 148 profile,
142 screenshot_directory.Append(base_name + ".png"), 149 screenshot_path,
143 base::Bind(&SaveScreenshotToGData, png_data)); 150 base::Bind(&SaveScreenshotToGData, png_data));
144 } 151 }
145 } else { 152 } else {
146 content::BrowserThread::PostTask( 153 content::BrowserThread::PostTask(
147 content::BrowserThread::FILE, FROM_HERE, 154 content::BrowserThread::FILE, FROM_HERE,
148 base::Bind(&SaveScreenshot, screenshot_directory, base_name, png_data)); 155 base::Bind(&SaveScreenshot, screenshot_path, png_data));
149 } 156 }
150 } 157 }
151 #else 158 #else
152 void PostSaveScreenshotTask(const FilePath& screenshot_directory, 159 void PostSaveScreenshotTask(const FilePath& screenshot_path,
153 const std::string& base_name,
154 scoped_refptr<base::RefCountedBytes> png_data) { 160 scoped_refptr<base::RefCountedBytes> png_data) {
155 content::BrowserThread::PostTask( 161 content::BrowserThread::PostTask(
156 content::BrowserThread::FILE, FROM_HERE, 162 content::BrowserThread::FILE, FROM_HERE,
157 base::Bind(&SaveScreenshot, screenshot_directory, base_name, png_data)); 163 base::Bind(&SaveScreenshot, screenshot_path, png_data));
158 } 164 }
159 #endif 165 #endif
160 166
161 bool AreScreenshotsDisabled() {
162 return g_browser_process->local_state()->GetBoolean(
163 prefs::kDisableScreenshots);
164 }
165
166 bool GrabWindowSnapshot(aura::Window* window, 167 bool GrabWindowSnapshot(aura::Window* window,
167 const gfx::Rect& snapshot_bounds, 168 const gfx::Rect& snapshot_bounds,
168 std::vector<unsigned char>* png_data) { 169 std::vector<unsigned char>* png_data) {
169 #if defined(OS_LINUX) 170 #if defined(OS_LINUX)
170 // chrome::GrabWindowSnapshotForUser checks this too, but 171 // chrome::GrabWindowSnapshotForUser checks this too, but
171 // RootWindow::GrabSnapshot does not. 172 // RootWindow::GrabSnapshot does not.
172 if (AreScreenshotsDisabled()) 173 if (AreScreenshotsDisabled())
173 return false; 174 return false;
174 175
175 // We use XGetImage() for Linux/ChromeOS for performance reasons. 176 // We use XGetImage() for Linux/ChromeOS for performance reasons.
176 // See crbug.com/119492 177 // See crbug.com/119492
177 // TODO(mukai): remove this when the performance issue has been fixed. 178 // TODO(mukai): remove this when the performance issue has been fixed.
178 if (window->GetRootWindow()->GrabSnapshot(snapshot_bounds, png_data)) 179 if (window->GetRootWindow()->GrabSnapshot(snapshot_bounds, png_data))
179 return true; 180 return true;
180 #endif // OS_LINUX 181 #endif // OS_LINUX
181 182
182 return chrome::GrabWindowSnapshotForUser(window, png_data, snapshot_bounds); 183 return chrome::GrabWindowSnapshotForUser(window, png_data, snapshot_bounds);
183 } 184 }
184 185
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 186 } // namespace
193 187
194 ScreenshotTaker::ScreenshotTaker() { 188 ScreenshotTaker::ScreenshotTaker() {
195 } 189 }
196 190
197 ScreenshotTaker::~ScreenshotTaker() { 191 ScreenshotTaker::~ScreenshotTaker() {
198 } 192 }
199 193
200 void ScreenshotTaker::HandleTakeScreenshot(aura::Window* window) { 194 void ScreenshotTaker::HandleTakeScreenshotForAllRootWindows() {
201 HandleTakePartialScreenshot(window, window->bounds()); 195 FilePath screenshot_directory;
196 if (!GetScreenshotDirectory(&screenshot_directory))
197 return;
198
199 std::string screenshot_basename = GetScreenshotBaseFilename();
200 ash::Shell::RootWindowList root_windows = ash::Shell::GetAllRootWindows();
201 for (size_t i = 0; i < root_windows.size(); ++i) {
202 aura::RootWindow* root_window = root_windows[i];
203 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes);
204 std::string basename = screenshot_basename;
205 gfx::Rect rect = root_window->bounds();
206 if (root_windows.size() > 1)
207 basename += base::StringPrintf(" - Display %d", static_cast<int>(i + 1));
208 if (GrabWindowSnapshot(root_window, rect, &png_data->data())) {
209 DisplayVisualFeedback(rect);
210 PostSaveScreenshotTask(
211 screenshot_directory.AppendASCII(basename + ".png"), png_data);
212 } else {
213 LOG(ERROR) << "Failed to grab the window screenshot for " << i;
214 }
215 }
216 last_screenshot_timestamp_ = base::Time::Now();
202 } 217 }
203 218
204 void ScreenshotTaker::HandleTakePartialScreenshot( 219 void ScreenshotTaker::HandleTakePartialScreenshot(
205 aura::Window* window, const gfx::Rect& rect) { 220 aura::Window* window, const gfx::Rect& rect) {
206 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 221 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
207 222
208 if (AreScreenshotsDisabled()) 223 FilePath screenshot_directory;
224 if (!GetScreenshotDirectory(&screenshot_directory))
209 return; 225 return;
210 226
211 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); 227 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes);
212 228
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())) { 229 if (GrabWindowSnapshot(window, rect, &png_data->data())) {
231 last_screenshot_timestamp_ = base::Time::Now(); 230 last_screenshot_timestamp_ = base::Time::Now();
232 DisplayVisualFeedback(rect); 231 DisplayVisualFeedback(rect);
233 PostSaveScreenshotTask(screenshot_directory, 232 PostSaveScreenshotTask(
234 GetScreenShotBaseFilename(ShouldUse24HourClock()), 233 screenshot_directory.AppendASCII(GetScreenshotBaseFilename() + ".png"),
235 png_data); 234 png_data);
236 } else { 235 } else {
237 LOG(ERROR) << "Failed to grab the window screenshot"; 236 LOG(ERROR) << "Failed to grab the window screenshot";
238 } 237 }
239 } 238 }
240 239
241 bool ScreenshotTaker::CanTakeScreenshot() { 240 bool ScreenshotTaker::CanTakeScreenshot() {
242 return last_screenshot_timestamp_.is_null() || 241 return last_screenshot_timestamp_.is_null() ||
243 base::Time::Now() - last_screenshot_timestamp_ > 242 base::Time::Now() - last_screenshot_timestamp_ >
244 base::TimeDelta::FromMilliseconds( 243 base::TimeDelta::FromMilliseconds(
245 kScreenshotMinimumIntervalInMS); 244 kScreenshotMinimumIntervalInMS);
(...skipping 14 matching lines...) Expand all
260 ash::internal::kShellWindowId_OverlayContainer)->layer(); 259 ash::internal::kShellWindowId_OverlayContainer)->layer();
261 parent->Add(visual_feedback_layer_.get()); 260 parent->Add(visual_feedback_layer_.get());
262 visual_feedback_layer_->SetVisible(true); 261 visual_feedback_layer_->SetVisible(true);
263 262
264 MessageLoopForUI::current()->PostDelayedTask( 263 MessageLoopForUI::current()->PostDelayedTask(
265 FROM_HERE, 264 FROM_HERE,
266 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer, 265 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer,
267 base::Unretained(this)), 266 base::Unretained(this)),
268 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs)); 267 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs));
269 } 268 }
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