OLD | NEW |
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 12 matching lines...) Expand all Loading... |
23 #include "chrome/browser/prefs/pref_service.h" | 23 #include "chrome/browser/prefs/pref_service.h" |
24 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
25 #include "chrome/browser/profiles/profile_manager.h" | 25 #include "chrome/browser/profiles/profile_manager.h" |
26 #include "chrome/browser/ui/window_snapshot/window_snapshot.h" | 26 #include "chrome/browser/ui/window_snapshot/window_snapshot.h" |
27 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
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/login/user_manager.h" | 34 #include "chrome/browser/chromeos/login/user_manager.h" |
34 #endif | 35 #endif |
35 | 36 |
36 namespace { | 37 namespace { |
37 const int kScreenshotMinimumIntervalInMS = 500; | 38 const int kScreenshotMinimumIntervalInMS = 500; |
38 | 39 |
39 bool ShouldUse24HourClock() { | 40 bool ShouldUse24HourClock() { |
40 #if defined(OS_CHROMEOS) | 41 #if defined(OS_CHROMEOS) |
41 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); | 42 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); |
42 if (profile) { | 43 if (profile) { |
43 PrefService* pref_service = profile->GetPrefs(); | 44 PrefService* pref_service = profile->GetPrefs(); |
44 if (pref_service) { | 45 if (pref_service) { |
45 return pref_service->GetBoolean(prefs::kUse24HourClock); | 46 return pref_service->GetBoolean(prefs::kUse24HourClock); |
46 } | 47 } |
47 } | 48 } |
48 #endif | 49 #endif |
49 return base::GetHourClockType() == base::k24HourClock; | 50 return base::GetHourClockType() == base::k24HourClock; |
50 } | 51 } |
51 | 52 |
52 FilePath GetScreenshotPath(const FilePath& base_directory, | 53 std::string GetScreenShotBaseFilename(bool use_24hour_clock) { |
53 bool use_24hour_clock) { | |
54 base::Time::Exploded now; | 54 base::Time::Exploded now; |
55 base::Time::Now().LocalExplode(&now); | 55 base::Time::Now().LocalExplode(&now); |
56 | 56 |
57 // We don't use base/i18n/time_formatting.h here because it doesn't | 57 // 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 | 58 // support our format. Don't use ICU either to avoid i18n file names |
59 // for non-English locales. | 59 // for non-English locales. |
60 // TODO(mukai): integrate this logic somewhere time_formatting.h | 60 // TODO(mukai): integrate this logic somewhere time_formatting.h |
61 std::string file_name = base::StringPrintf( | 61 std::string file_name = base::StringPrintf( |
62 "Screenshot %d-%02d-%02d ", now.year, now.month, now.day_of_month); | 62 "Screenshot %d-%02d-%02d ", now.year, now.month, now.day_of_month); |
63 | 63 |
64 if (use_24hour_clock) { | 64 if (use_24hour_clock) { |
65 file_name.append(base::StringPrintf( | 65 file_name.append(base::StringPrintf( |
66 "%02d:%02d:%02d", now.hour, now.minute, now.second)); | 66 "%02d:%02d:%02d", now.hour, now.minute, now.second)); |
67 } else { | 67 } else { |
68 int hour = now.hour; | 68 int hour = now.hour; |
69 if (hour > 12) { | 69 if (hour > 12) { |
70 hour -= 12; | 70 hour -= 12; |
71 } else if (hour == 0) { | 71 } else if (hour == 0) { |
72 hour = 12; | 72 hour = 12; |
73 } | 73 } |
74 file_name.append(base::StringPrintf( | 74 file_name.append(base::StringPrintf( |
75 "%d:%02d:%02d ", hour, now.minute, now.second)); | 75 "%d:%02d:%02d ", hour, now.minute, now.second)); |
76 file_name.append((now.hour >= 12) ? "PM" : "AM"); | 76 file_name.append((now.hour >= 12) ? "PM" : "AM"); |
77 } | 77 } |
78 | 78 |
| 79 return file_name; |
| 80 } |
| 81 |
| 82 FilePath GetScreenshotPath(const FilePath& base_directory, |
| 83 const std::string& base_name) { |
| 84 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
79 for (int retry = 0; retry < INT_MAX; retry++) { | 85 for (int retry = 0; retry < INT_MAX; retry++) { |
80 std::string retry_suffix; | 86 std::string retry_suffix; |
81 if (retry > 0) | 87 if (retry > 0) |
82 retry_suffix = base::StringPrintf(" (%d)", retry + 1); | 88 retry_suffix = base::StringPrintf(" (%d)", retry + 1); |
83 | 89 |
84 FilePath file_path = base_directory.AppendASCII( | 90 FilePath file_path = base_directory.AppendASCII( |
85 file_name + retry_suffix + ".png"); | 91 base_name + retry_suffix + ".png"); |
86 if (!file_util::PathExists(file_path)) | 92 if (!file_util::PathExists(file_path)) |
87 return file_path; | 93 return file_path; |
88 } | 94 } |
89 | |
90 return FilePath(); | 95 return FilePath(); |
91 } | 96 } |
92 | 97 |
93 // |is_logged_in| is used only for ChromeOS. Otherwise it is always true. | 98 void SaveScreenshotToLocalFile(scoped_refptr<base::RefCountedBytes> png_data, |
94 void SaveScreenshot(const FilePath& screenshot_directory, | 99 const FilePath& screenshot_path) { |
95 bool use_24hour_clock, | |
96 scoped_refptr<base::RefCountedBytes> png_data) { | |
97 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); | 100 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); |
98 | |
99 FilePath screenshot_path = GetScreenshotPath( | |
100 screenshot_directory, use_24hour_clock); | |
101 | |
102 if (screenshot_path.empty()) { | |
103 LOG(ERROR) << "Failed to find a screenshot file name."; | |
104 return; | |
105 } | |
106 | |
107 if (static_cast<size_t>(file_util::WriteFile( | 101 if (static_cast<size_t>(file_util::WriteFile( |
108 screenshot_path, | 102 screenshot_path, |
109 reinterpret_cast<char*>(&(png_data->data()[0])), | 103 reinterpret_cast<char*>(&(png_data->data()[0])), |
110 png_data->size())) != png_data->size()) { | 104 png_data->size())) != png_data->size()) { |
111 LOG(ERROR) << "Failed to save to " << screenshot_path.value(); | 105 LOG(ERROR) << "Failed to save to " << screenshot_path.value(); |
112 } | 106 } |
113 } | 107 } |
114 | 108 |
| 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. |
| 121 #ifdef OS_CHROMEOS |
| 122 void SaveScreenshotToGData(scoped_refptr<base::RefCountedBytes> png_data, |
| 123 gdata::GDataFileError error, |
| 124 const FilePath& local_path) { |
| 125 if (error != gdata::GDATA_FILE_OK) { |
| 126 LOG(ERROR) << "Failed to write screenshot image to Google Drive: " << error; |
| 127 return; |
| 128 } |
| 129 SaveScreenshotToLocalFile(png_data, local_path); |
| 130 } |
| 131 |
| 132 void PostSaveScreenshotTask(const FilePath& screenshot_directory, |
| 133 const std::string& base_name, |
| 134 scoped_refptr<base::RefCountedBytes> png_data) { |
| 135 if (gdata::util::IsUnderGDataMountPoint(screenshot_directory)) { |
| 136 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); |
| 137 if (profile) { |
| 138 // TODO(kinaba,mukai): crbug.com/140749. Take care of the case |
| 139 // "base_name.png" already exists. |
| 140 gdata::util::PrepareWritableFileAndRun( |
| 141 profile, |
| 142 screenshot_directory.Append(base_name + ".png"), |
| 143 base::Bind(&SaveScreenshotToGData, png_data)); |
| 144 } |
| 145 } else { |
| 146 content::BrowserThread::PostTask( |
| 147 content::BrowserThread::FILE, FROM_HERE, |
| 148 base::Bind(&SaveScreenshot, screenshot_directory, base_name, png_data)); |
| 149 } |
| 150 } |
| 151 #else |
| 152 void PostSaveScreenshotTask(const FilePath& screenshot_directory, |
| 153 const std::string& base_name, |
| 154 scoped_refptr<base::RefCountedBytes> png_data) { |
| 155 content::BrowserThread::PostTask( |
| 156 content::BrowserThread::FILE, FROM_HERE, |
| 157 base::Bind(&SaveScreenshot, screenshot_directory, base_name, png_data)); |
| 158 } |
| 159 #endif |
| 160 |
115 bool AreScreenshotsDisabled() { | 161 bool AreScreenshotsDisabled() { |
116 return g_browser_process->local_state()->GetBoolean( | 162 return g_browser_process->local_state()->GetBoolean( |
117 prefs::kDisableScreenshots); | 163 prefs::kDisableScreenshots); |
118 } | 164 } |
119 | 165 |
120 bool GrabWindowSnapshot(aura::Window* window, | 166 bool GrabWindowSnapshot(aura::Window* window, |
121 const gfx::Rect& snapshot_bounds, | 167 const gfx::Rect& snapshot_bounds, |
122 std::vector<unsigned char>* png_data) { | 168 std::vector<unsigned char>* png_data) { |
123 #if defined(OS_LINUX) | 169 #if defined(OS_LINUX) |
124 // browser::GrabWindowSnapshot checks this too, but RootWindow::GrabSnapshot | 170 // browser::GrabWindowSnapshot checks this too, but RootWindow::GrabSnapshot |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext( | 221 DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext( |
176 ash::Shell::GetInstance()->delegate()->GetCurrentBrowserContext()); | 222 ash::Shell::GetInstance()->delegate()->GetCurrentBrowserContext()); |
177 screenshot_directory = download_prefs->DownloadPath(); | 223 screenshot_directory = download_prefs->DownloadPath(); |
178 } else { | 224 } else { |
179 if (!file_util::GetTempDir(&screenshot_directory)) { | 225 if (!file_util::GetTempDir(&screenshot_directory)) { |
180 LOG(ERROR) << "Failed to find temporary directory."; | 226 LOG(ERROR) << "Failed to find temporary directory."; |
181 return; | 227 return; |
182 } | 228 } |
183 } | 229 } |
184 | 230 |
185 bool use_24hour_clock = ShouldUse24HourClock(); | |
186 | |
187 if (GrabWindowSnapshot(window, rect, &png_data->data())) { | 231 if (GrabWindowSnapshot(window, rect, &png_data->data())) { |
188 last_screenshot_timestamp_ = base::Time::Now(); | 232 last_screenshot_timestamp_ = base::Time::Now(); |
189 DisplayVisualFeedback(rect); | 233 DisplayVisualFeedback(rect); |
190 content::BrowserThread::PostTask( | 234 PostSaveScreenshotTask(screenshot_directory, |
191 content::BrowserThread::FILE, FROM_HERE, | 235 GetScreenShotBaseFilename(ShouldUse24HourClock()), |
192 base::Bind(&SaveScreenshot, screenshot_directory, use_24hour_clock, | 236 png_data); |
193 png_data)); | |
194 } else { | 237 } else { |
195 LOG(ERROR) << "Failed to grab the window screenshot"; | 238 LOG(ERROR) << "Failed to grab the window screenshot"; |
196 } | 239 } |
197 } | 240 } |
198 | 241 |
199 bool ScreenshotTaker::CanTakeScreenshot() { | 242 bool ScreenshotTaker::CanTakeScreenshot() { |
200 return last_screenshot_timestamp_.is_null() || | 243 return last_screenshot_timestamp_.is_null() || |
201 base::Time::Now() - last_screenshot_timestamp_ > | 244 base::Time::Now() - last_screenshot_timestamp_ > |
202 base::TimeDelta::FromMilliseconds( | 245 base::TimeDelta::FromMilliseconds( |
203 kScreenshotMinimumIntervalInMS); | 246 kScreenshotMinimumIntervalInMS); |
(...skipping 14 matching lines...) Expand all Loading... |
218 ash::internal::kShellWindowId_OverlayContainer)->layer(); | 261 ash::internal::kShellWindowId_OverlayContainer)->layer(); |
219 parent->Add(visual_feedback_layer_.get()); | 262 parent->Add(visual_feedback_layer_.get()); |
220 visual_feedback_layer_->SetVisible(true); | 263 visual_feedback_layer_->SetVisible(true); |
221 | 264 |
222 MessageLoopForUI::current()->PostDelayedTask( | 265 MessageLoopForUI::current()->PostDelayedTask( |
223 FROM_HERE, | 266 FROM_HERE, |
224 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer, | 267 base::Bind(&ScreenshotTaker::CloseVisualFeedbackLayer, |
225 base::Unretained(this)), | 268 base::Unretained(this)), |
226 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs)); | 269 base::TimeDelta::FromMilliseconds(kVisualFeedbackLayerDisplayTimeMs)); |
227 } | 270 } |
OLD | NEW |