blob: 438043466e6dcc99a1428d17b3c381bf28514f1e [file] [log] [blame]
[email protected]57118ea2020-07-17 03:17:141// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/ash/clipboard_util.h"
6
7#include "base/base64.h"
8#include "base/files/file_util.h"
9#include "base/memory/ref_counted_memory.h"
10#include "base/metrics/user_metrics.h"
11#include "base/threading/scoped_blocking_call.h"
12#include "content/public/browser/browser_task_traits.h"
13#include "content/public/browser/browser_thread.h"
14#include "services/data_decoder/public/cpp/decode_image.h"
15#include "ui/base/clipboard/clipboard.h"
16#include "ui/base/clipboard/scoped_clipboard_writer.h"
17
18namespace clipboard_util {
19namespace {
20
21const char kImageClipboardFormatPrefix[] = "<img src='data:image/png;base64,";
22const char kImageClipboardFormatSuffix[] = "'>";
23
24void CopyImageToClipboard(scoped_refptr<base::RefCountedString> png_data,
25 const SkBitmap& decoded_image) {
26 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
27
28 std::string encoded;
29 base::Base64Encode(png_data->data(), &encoded);
30 {
31 ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste);
32
33 // Send both HTML and and Image formats to clipboard. HTML format is needed
34 // by ARC, while Image is needed by Hangout.
35 std::string html(kImageClipboardFormatPrefix);
36 html += encoded;
37 html += kImageClipboardFormatSuffix;
38 scw.WriteHTML(base::UTF8ToUTF16(html), std::string());
39 scw.WriteImage(decoded_image);
40 }
41}
42
43void DecodeFileAndCopyToClipboard(
44 scoped_refptr<base::RefCountedString> png_data) {
45 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
46
47 // Decode the image in sandboxed process because |png_data| comes from
48 // external storage.
49 data_decoder::DecodeImageIsolated(
50 std::vector<uint8_t>(png_data->data().begin(), png_data->data().end()),
51 data_decoder::mojom::ImageCodec::DEFAULT, false,
52 data_decoder::kDefaultMaxSizeInBytes, gfx::Size(),
53 base::BindOnce(&CopyImageToClipboard, png_data));
54}
55
56} // namespace
57
58void ReadFileAndCopyToClipboardLocal(const base::FilePath& local_file) {
59 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
60 base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
61 base::BlockingType::WILL_BLOCK);
62 scoped_refptr<base::RefCountedString> png_data(new base::RefCountedString());
63 if (!base::ReadFileToString(local_file, &(png_data->data()))) {
64 LOG(ERROR) << "Failed to read the screenshot file: " << local_file.value();
65 return;
66 }
67
68 content::GetUIThreadTaskRunner({})->PostTask(
69 FROM_HERE, base::BindOnce(&DecodeFileAndCopyToClipboard, png_data));
70}
71} // namespace clipboard_util