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