15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/ash/screenshot_taker.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <climits> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/shell.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ash/shell_delegate.h" 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/system/system_notifier.h" 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/base64.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/i18n/time_formatting.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted_memory.h" 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/prefs/pref_service.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/sequenced_worker_pool.h" 23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_prefs.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/notifications/notification_ui_manager.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/common/pref_names.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "content/public/browser/user_metrics.h" 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "grit/ash_strings.h" 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "grit/theme_resources.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/clipboard/clipboard.h" 37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ui/base/clipboard/scoped_clipboard_writer.h" 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image.h" 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/snapshot/snapshot.h" 421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/strings/grit/ui_strings.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS) 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_interface.h" 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h" 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/chromeos/file_manager/open_util.h" 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service.h" 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/notifications/desktop_notification_service_factory.h" 50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "chromeos/login/login_state.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The minimum interval between two screenshot commands. It has to be 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// more than 1000 to prevent the conflict of filenames. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kScreenshotMinimumIntervalInMS = 1000; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kNotificationId[] = "screenshot"; 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_CHROMEOS) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kNotificationOriginUrl[] = "chrome://screenshot"; 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kImageClipboardFormatPrefix[] = "<img src='data:image/png;base64,"; 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const char kImageClipboardFormatSuffix[] = "'>"; 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void CopyScreenshotToClipboard(scoped_refptr<base::RefCountedString> png_data) { 68e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string encoded; 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Base64Encode(png_data->data(), &encoded); 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Only cares about HTML because ChromeOS doesn't need other formats. 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(dcheng): Why don't we take advantage of the ability to write bitmaps 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // to the clipboard here? 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) { 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ui::ScopedClipboardWriter scw(ui::CLIPBOARD_TYPE_COPY_PASTE); 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string html(kImageClipboardFormatPrefix); 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) html += encoded; 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) html += kImageClipboardFormatSuffix; 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scw.WriteHTML(base::UTF8ToUTF16(html), std::string()); 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::RecordAction(base::UserMetricsAction("Screenshot_CopyClipboard")); 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ReadFileAndCopyToClipboardLocal(const base::FilePath& screenshot_path) { 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_refptr<base::RefCountedString> png_data(new base::RefCountedString()); 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!base::ReadFileToString(screenshot_path, &(png_data->data()))) { 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Failed to read the screenshot file: " 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << screenshot_path.value(); 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserThread::PostTask( 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserThread::UI, FROM_HERE, 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(CopyScreenshotToClipboard, png_data)); 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_CHROMEOS) 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ReadFileAndCopyToClipboardDrive(drive::FileError error, 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const base::FilePath& file_path, 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<drive::ResourceEntry> entry) { 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (error != drive::FILE_ERROR_OK) { 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LOG(ERROR) << "Failed to read the screenshot path on drive: " 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) << drive::FileErrorToString(error); 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserThread::GetBlockingPool()->PostTask( 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&ReadFileAndCopyToClipboardLocal, file_path)); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Delegate for a notification. This class has two roles: to implement callback 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// methods for notification, and to provide an identity of the associated 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// notification. 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class ScreenshotTakerNotificationDelegate : public NotificationDelegate { 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public: 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerNotificationDelegate(bool success, 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile, 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path) 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : success_(success), 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) profile_(profile), 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path_(screenshot_path) { 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Overridden from NotificationDelegate: 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Display() OVERRIDE {} 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Error() OVERRIDE {} 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Close(bool by_user) OVERRIDE {} 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual void Click() OVERRIDE { 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!success_) 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) 1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_manager::util::ShowItemInFolder(profile_, screenshot_path_); 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#else 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(sschmitz): perhaps add similar action for Windows. 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) virtual void ButtonClick(int button_index) OVERRIDE { 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(success_ && button_index == 0); 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // To avoid keeping the screenshot image on memory, it will re-read the 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // screenshot file and copy it to the clipboard. 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(OS_CHROMEOS) 148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (drive::util::IsUnderDriveMountPoint(screenshot_path_)) { 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) drive::FileSystemInterface* file_system = 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) drive::util::GetFileSystemByProfile(profile_); 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) file_system->GetFile( 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) drive::util::ExtractDrivePath(screenshot_path_), 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&ReadFileAndCopyToClipboardDrive)); 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserThread::GetBlockingPool()->PostTask( 158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FROM_HERE, base::Bind( 159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &ReadFileAndCopyToClipboardLocal, screenshot_path_)); 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) virtual bool HasClickedListener() OVERRIDE { return success_; } 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual std::string id() const OVERRIDE { 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(kNotificationId); 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch virtual content::WebContents* GetWebContents() const OVERRIDE { 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private: 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) virtual ~ScreenshotTakerNotificationDelegate() {} 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const bool success_; 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Profile* profile_; 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath screenshot_path_; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScreenshotTakerNotificationDelegate); 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)typedef base::Callback< 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void(ScreenshotTakerObserver::Result screenshot_result, 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path)> ShowNotificationCallback; 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SaveScreenshotInternal(const ShowNotificationCallback& callback, 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path, 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& local_path, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(!local_path.empty()); 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerObserver::Result result = 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerObserver::SCREENSHOT_SUCCESS; 191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (static_cast<size_t>(base::WriteFile( 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) local_path, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(&(png_data->data()[0])), 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_data->size())) != png_data->size()) { 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Failed to save to " << local_path.value(); 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result = ScreenshotTakerObserver::SCREENSHOT_WRITE_FILE_FAILED; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserThread::PostTask( 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserThread::UI, FROM_HERE, 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(callback, result, screenshot_path)); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SaveScreenshot(const ShowNotificationCallback& callback, 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path, 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!screenshot_path.empty()); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::CreateDirectory(screenshot_path.DirName())) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to ensure the existence of " 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << screenshot_path.DirName().value(); 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserThread::PostTask( 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserThread::UI, FROM_HERE, 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(callback, 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerObserver::SCREENSHOT_CREATE_DIR_FAILED, 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path)); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SaveScreenshotInternal(callback, screenshot_path, screenshot_path, png_data); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(kinaba): crbug.com/140425, remove this ungly #ifdef dispatch. 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS) 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SaveScreenshotToDrive(const ShowNotificationCallback& callback, 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path, 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data, 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) drive::FileError error, 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& local_path) { 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |screenshot_path| is used in the notification callback. 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // |local_path| is a temporary file in a hidden cache directory used for 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // internal work generated by drive::util::PrepareWritableFileAndRun. 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (error != drive::FILE_ERROR_OK) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to write screenshot image to Google Drive: " << error; 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserThread::PostTask( 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) content::BrowserThread::UI, FROM_HERE, 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(callback, 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerObserver::SCREENSHOT_CREATE_FILE_FAILED, 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path)); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SaveScreenshotInternal(callback, screenshot_path, local_path, png_data); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnsureDirectoryExistsCallback( 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ShowNotificationCallback& callback, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& screenshot_path, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data, 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) drive::FileError error) { 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // It is okay to fail with FILE_ERROR_EXISTS since anyway the directory 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the target file exists. 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (error == drive::FILE_ERROR_OK || 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) error == drive::FILE_ERROR_EXISTS) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drive::util::PrepareWritableFileAndRun( 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) screenshot_path, 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&SaveScreenshotToDrive, 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback, 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path, 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) png_data)); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to ensure the existence of the specified directory " 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "in Google Drive: " << error; 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback.Run(ScreenshotTakerObserver::SCREENSHOT_CHECK_DIR_FAILED, 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PostSaveScreenshotTask(const ShowNotificationCallback& callback, 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Profile* profile, 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path, 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drive::util::IsUnderDriveMountPoint(screenshot_path)) { 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) drive::util::EnsureDirectoryExists( 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) profile, 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path.DirName(), 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Bind(&EnsureDirectoryExistsCallback, 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback, 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) profile, 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path, 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) png_data)); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::BrowserThread::GetBlockingPool()->PostTask( 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, base::Bind(&SaveScreenshot, 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback, 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path, 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) png_data)); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PostSaveScreenshotTask(const ShowNotificationCallback& callback, 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Profile* profile, 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path, 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::BrowserThread::GetBlockingPool()->PostTask( 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FROM_HERE, base::Bind(&SaveScreenshot, 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) callback, 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_path, 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) png_data)); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool ShouldUse24HourClock() { 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_CHROMEOS) 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile = ProfileManager::GetActiveUserProfile(); 3063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (profile) { 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return profile->GetPrefs()->GetBoolean(prefs::kUse24HourClock); 3083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 3103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return base::GetHourClockType() == base::k24HourClock; 3113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)std::string GetScreenshotBaseFilename() { 3143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Time::Exploded now; 3153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Time::Now().LocalExplode(&now); 3163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // We don't use base/i18n/time_formatting.h here because it doesn't 3183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // support our format. Don't use ICU either to avoid i18n file names 3193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // for non-English locales. 3203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(mukai): integrate this logic somewhere time_formatting.h 3213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::string file_name = base::StringPrintf( 3223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "Screenshot %d-%02d-%02d at ", now.year, now.month, now.day_of_month); 3233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (ShouldUse24HourClock()) { 3253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) file_name.append(base::StringPrintf( 3263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "%02d.%02d.%02d", now.hour, now.minute, now.second)); 3273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 3283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int hour = now.hour; 3293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (hour > 12) { 3303551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) hour -= 12; 3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (hour == 0) { 3323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) hour = 12; 3333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) file_name.append(base::StringPrintf( 3353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) "%d.%02d.%02d ", hour, now.minute, now.second)); 3363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) file_name.append((now.hour >= 12) ? "PM" : "AM"); 3373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return file_name; 3403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool GetScreenshotDirectory(base::FilePath* directory) { 3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool is_logged_in = true; 3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(OS_CHROMEOS) 3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) is_logged_in = chromeos::LoginState::Get()->IsUserLoggedIn(); 3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (is_logged_in) { 3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DownloadPrefs* download_prefs = DownloadPrefs::FromBrowserContext( 3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ProfileManager::GetActiveUserProfile()); 3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) *directory = download_prefs->DownloadPath(); 3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetTempDir(directory)) { 3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "Failed to find temporary directory."; 3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return false; 3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return true; 3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if defined(OS_CHROMEOS) 363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int GetScreenshotNotificationTitle( 364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ScreenshotTakerObserver::Result screenshot_result) { 365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (screenshot_result) { 366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ScreenshotTakerObserver::SCREENSHOTS_DISABLED: 367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IDS_ASH_SCREENSHOT_NOTIFICATION_TITLE_DISABLED; 368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ScreenshotTakerObserver::SCREENSHOT_SUCCESS: 369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IDS_ASH_SCREENSHOT_NOTIFICATION_TITLE_SUCCESS; 370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) default: 371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IDS_ASH_SCREENSHOT_NOTIFICATION_TITLE_FAIL; 372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 375424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int GetScreenshotNotificationText( 376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ScreenshotTakerObserver::Result screenshot_result) { 377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (screenshot_result) { 378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ScreenshotTakerObserver::SCREENSHOTS_DISABLED: 379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IDS_ASH_SCREENSHOT_NOTIFICATION_TEXT_DISABLED; 380424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case ScreenshotTakerObserver::SCREENSHOT_SUCCESS: 381424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IDS_ASH_SCREENSHOT_NOTIFICATION_TEXT_SUCCESS; 382424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) default: 383424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IDS_ASH_SCREENSHOT_NOTIFICATION_TEXT_FAIL; 384424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif 387424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ScreenshotTaker::ScreenshotTaker() 3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : profile_for_test_(NULL), 3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci factory_(this) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScreenshotTaker::~ScreenshotTaker() { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScreenshotTaker::HandleTakeScreenshotForAllRootWindows() { 399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (g_browser_process->local_state()-> 400424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetBoolean(prefs::kDisableScreenshots)) { 401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ShowNotification(ScreenshotTakerObserver::SCREENSHOTS_DISABLED, 402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::FilePath()); 403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath screenshot_directory; 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!screenshot_directory_for_test_.empty()) { 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_directory = screenshot_directory_for_test_; 4083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (!GetScreenshotDirectory(&screenshot_directory)) { 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ShowNotification(ScreenshotTakerObserver::SCREENSHOT_GET_DIR_FAILED, 410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string screenshot_basename = !screenshot_basename_for_test_.empty() ? 4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) screenshot_basename_for_test_ : GetScreenshotBaseFilename(); 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window::Windows root_windows = ash::Shell::GetAllRootWindows(); 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Reorder root_windows to take the primary root window's snapshot at first. 4181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) aura::Window* primary_root = ash::Shell::GetPrimaryRootWindow(); 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*(root_windows.begin()) != primary_root) { 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_windows.erase(std::find( 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) root_windows.begin(), root_windows.end(), primary_root)); 422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) root_windows.insert(root_windows.begin(), primary_root); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < root_windows.size(); ++i) { 425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) aura::Window* root_window = root_windows[i]; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string basename = screenshot_basename; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect rect = root_window->bounds(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_windows.size() > 1) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) basename += base::StringPrintf(" - Display %d", static_cast<int>(i + 1)); 430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath screenshot_path = 431c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_directory.AppendASCII(basename + ".png"); 4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GrabFullWindowSnapshotAsync( 4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) root_window, rect, GetProfile(), screenshot_path, i); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::RecordAction(base::UserMetricsAction("Screenshot_TakeFull")); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScreenshotTaker::HandleTakePartialScreenshot( 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) aura::Window* window, const gfx::Rect& rect) { 440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (g_browser_process->local_state()-> 441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetBoolean(prefs::kDisableScreenshots)) { 442424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ShowNotification(ScreenshotTakerObserver::SCREENSHOTS_DISABLED, 443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::FilePath()); 444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 446e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath screenshot_directory; 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!screenshot_directory_for_test_.empty()) { 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_directory = screenshot_directory_for_test_; 4513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else if (!GetScreenshotDirectory(&screenshot_directory)) { 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ShowNotification(ScreenshotTakerObserver::SCREENSHOT_GET_DIR_FAILED, 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath()); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string screenshot_basename = !screenshot_basename_for_test_.empty() ? 4583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) screenshot_basename_for_test_ : GetScreenshotBaseFilename(); 459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FilePath screenshot_path = 460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_directory.AppendASCII(screenshot_basename + ".png"); 4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GrabPartialWindowSnapshotAsync(window, rect, GetProfile(), screenshot_path); 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::RecordAction(base::UserMetricsAction("Screenshot_TakePartial")); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ScreenshotTaker::CanTakeScreenshot() { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return last_screenshot_timestamp_.is_null() || 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time::Now() - last_screenshot_timestamp_ > 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds( 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kScreenshotMinimumIntervalInMS); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_CHROMEOS) 473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Notification* ScreenshotTaker::CreateNotification( 474c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerObserver::Result screenshot_result, 475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path) { 476c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string notification_id(kNotificationId); 477c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We cancel a previous screenshot notification, if any, to ensure we get 478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // a fresh notification pop-up. 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) g_browser_process->notification_ui_manager()->CancelById(notification_id); 4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const base::string16 replace_id(base::UTF8ToUTF16(notification_id)); 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool success = 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (screenshot_result == ScreenshotTakerObserver::SCREENSHOT_SUCCESS); 483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) message_center::RichNotificationData optional_field; 484f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (success) { 485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16 label = l10n_util::GetStringUTF16( 486f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) IDS_MESSAGE_CENTER_NOTIFICATION_BUTTON_COPY_SCREENSHOT_TO_CLIPBOARD); 487f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) optional_field.buttons.push_back(message_center::ButtonInfo(label)); 488f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return new Notification( 490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) message_center::NOTIFICATION_TYPE_SIMPLE, 491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GURL(kNotificationOriginUrl), 492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) l10n_util::GetStringUTF16( 493424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetScreenshotNotificationTitle(screenshot_result)), 494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) l10n_util::GetStringUTF16( 495424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetScreenshotNotificationText(screenshot_result)), 496424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ui::ResourceBundle::GetSharedInstance().GetImageNamed( 497424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) IDR_SCREENSHOT_NOTIFICATION_ICON), 498f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebTextDirectionDefault, 499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message_center::NotifierId( 500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message_center::NotifierId::SYSTEM_COMPONENT, 501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::system_notifier::kNotifierScreenshot), 502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) l10n_util::GetStringUTF16(IDS_MESSAGE_CENTER_NOTIFIER_SCREENSHOT_NAME), 503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) replace_id, 504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) optional_field, 505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ScreenshotTakerNotificationDelegate( 506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) success, GetProfile(), screenshot_path)); 507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 5085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif 509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ScreenshotTaker::ShowNotification( 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ScreenshotTakerObserver::Result screenshot_result, 512c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& screenshot_path) { 513e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if defined(OS_CHROMEOS) 515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Do not show a notification that a screenshot was taken while no user is 516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // logged in, since it is confusing for the user to get a message about it 517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // after he logs in (crbug.com/235217). 518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!chromeos::LoginState::Get()->IsUserLoggedIn()) 519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(sschmitz): make this work for Windows. 522c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DesktopNotificationService* const service = 523c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DesktopNotificationServiceFactory::GetForProfile(GetProfile()); 52458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (service->IsNotifierEnabled(message_center::NotifierId( 525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message_center::NotifierId::SYSTEM_COMPONENT, 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ash::system_notifier::kNotifierScreenshot))) { 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<Notification> notification( 528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CreateNotification(screenshot_result, screenshot_path)); 529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) g_browser_process->notification_ui_manager()->Add(*notification, 530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetProfile()); 531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) FOR_EACH_OBSERVER(ScreenshotTakerObserver, observers_, 534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) OnScreenshotCompleted(screenshot_result, screenshot_path)); 535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ScreenshotTaker::AddObserver(ScreenshotTakerObserver* observer) { 538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) observers_.AddObserver(observer); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ScreenshotTaker::RemoveObserver(ScreenshotTakerObserver* observer) { 542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) observers_.RemoveObserver(observer); 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ScreenshotTaker::HasObserver(ScreenshotTakerObserver* observer) const { 546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return observers_.HasObserver(observer); 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScreenshotTaker::GrabWindowSnapshotAsyncCallback( 5505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath screenshot_path, 5515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_partial, 5525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int window_idx, 5535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<base::RefCountedBytes> png_data) { 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!png_data.get()) { 5555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (is_partial) { 5565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to grab the window screenshot"; 5575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShowNotification( 5585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScreenshotTakerObserver::SCREENSHOT_GRABWINDOW_PARTIAL_FAILED, 5595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) screenshot_path); 5605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 5615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to grab the window screenshot for " << window_idx; 5625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShowNotification( 5635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScreenshotTakerObserver::SCREENSHOT_GRABWINDOW_FULL_FAILED, 5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) screenshot_path); 5655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 5675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) PostSaveScreenshotTask( 5705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&ScreenshotTaker::ShowNotification, factory_.GetWeakPtr()), 5715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GetProfile(), 5725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) screenshot_path, 5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) png_data); 5745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScreenshotTaker::GrabPartialWindowSnapshotAsync( 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window, 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Rect& snapshot_bounds, 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile, 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath screenshot_path) { 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_screenshot_timestamp_ = base::Time::Now(); 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_partial = true; 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int window_idx = -1; // unused 5855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::GrabWindowSnapshotAsync( 5865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window, 5875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) snapshot_bounds, 5885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::GetBlockingPool(), 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&ScreenshotTaker::GrabWindowSnapshotAsyncCallback, 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) factory_.GetWeakPtr(), 5915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) screenshot_path, 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_partial, 5935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_idx)); 5945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 5955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ScreenshotTaker::GrabFullWindowSnapshotAsync( 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) aura::Window* window, 5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const gfx::Rect& snapshot_bounds, 5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Profile* profile, 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath screenshot_path, 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int window_idx) { 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) last_screenshot_timestamp_ = base::Time::Now(); 6035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool is_partial = false; 6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::GrabWindowSnapshotAsync( 6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window, 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) snapshot_bounds, 6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::BrowserThread::GetBlockingPool(), 6095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&ScreenshotTaker::GrabWindowSnapshotAsyncCallback, 6105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) factory_.GetWeakPtr(), 6115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) screenshot_path, 6125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) is_partial, 6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) window_idx)); 6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 616c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)Profile* ScreenshotTaker::GetProfile() { 617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (profile_for_test_) 618c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return profile_for_test_; 6195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ProfileManager::GetActiveUserProfile(); 620c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 621c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 622c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ScreenshotTaker::SetScreenshotDirectoryForTest( 623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::FilePath& directory) { 624c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_directory_for_test_ = directory; 625c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 626c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 627c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ScreenshotTaker::SetScreenshotBasenameForTest( 628c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const std::string& basename) { 629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) screenshot_basename_for_test_ = basename; 630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ScreenshotTaker::SetScreenshotProfileForTest(Profile* profile) { 633c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) profile_for_test_ = profile; 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635