Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / remoting / host / clipboard_aura.cc
1 // Copyright 2014 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 "remoting/host/clipboard_aura.h"
6
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/timer/timer.h"
9 #include "content/public/browser/browser_thread.h"
10 #include "remoting/base/constants.h"
11 #include "remoting/proto/event.pb.h"
12 #include "remoting/protocol/clipboard_stub.h"
13 #include "ui/base/clipboard/clipboard.h"
14 #include "ui/base/clipboard/scoped_clipboard_writer.h"
15
16 namespace {
17
18 // Clipboard polling interval in milliseconds.
19 const int64 kClipboardPollingIntervalMs = 500;
20
21 }  // namespace
22
23 namespace remoting {
24
25 class ClipboardAura::Core {
26  public:
27   Core();
28
29   // Mirror the public interface.
30   void Start(scoped_ptr<protocol::ClipboardStub> client_clipboard);
31   void InjectClipboardEvent(const protocol::ClipboardEvent& event);
32   void Stop();
33
34   // Overrides the clipboard polling interval for unit test.
35   void SetPollingIntervalForTesting(base::TimeDelta polling_interval);
36
37  private:
38   void CheckClipboardForChanges();
39
40   scoped_ptr<protocol::ClipboardStub> client_clipboard_;
41   scoped_ptr<base::RepeatingTimer<Core>> clipboard_polling_timer_;
42   uint64 current_change_count_;
43   base::TimeDelta polling_interval_;
44
45   DISALLOW_COPY_AND_ASSIGN(Core);
46 };
47
48 ClipboardAura::ClipboardAura(
49     scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
50     : core_(new Core()),
51       ui_task_runner_(ui_task_runner) {
52 }
53
54 ClipboardAura::~ClipboardAura() {
55   ui_task_runner_->DeleteSoon(FROM_HERE, core_.release());
56 }
57
58 void ClipboardAura::Start(
59     scoped_ptr<protocol::ClipboardStub> client_clipboard) {
60   ui_task_runner_->PostTask(
61       FROM_HERE, base::Bind(&Core::Start, base::Unretained(core_.get()),
62                             base::Passed(&client_clipboard)));
63 }
64
65 void ClipboardAura::InjectClipboardEvent(
66     const protocol::ClipboardEvent& event) {
67   ui_task_runner_->PostTask(FROM_HERE,
68                             base::Bind(&Core::InjectClipboardEvent,
69                                        base::Unretained(core_.get()), event));
70 }
71
72 void ClipboardAura::Stop() {
73   ui_task_runner_->PostTask(
74       FROM_HERE, base::Bind(&Core::Stop, base::Unretained(core_.get())));
75 };
76
77 void ClipboardAura::SetPollingIntervalForTesting(
78     base::TimeDelta polling_interval) {
79   core_->SetPollingIntervalForTesting(polling_interval);
80 }
81
82 ClipboardAura::Core::Core()
83     : current_change_count_(0),
84       polling_interval_(
85           base::TimeDelta::FromMilliseconds(kClipboardPollingIntervalMs)) {
86 }
87
88 void ClipboardAura::Core::Start(
89     scoped_ptr<protocol::ClipboardStub> client_clipboard) {
90   client_clipboard_.reset(client_clipboard.release());
91
92   // Aura doesn't provide a clipboard-changed notification. The only way to
93   // detect clipboard changes is by polling.
94   clipboard_polling_timer_.reset(new base::RepeatingTimer<Core>());
95   clipboard_polling_timer_->Start(
96       FROM_HERE, polling_interval_, this,
97       &ClipboardAura::Core::CheckClipboardForChanges);
98 }
99
100 void ClipboardAura::Core::InjectClipboardEvent(
101     const protocol::ClipboardEvent& event) {
102   // Currently we only handle UTF-8 text.
103   if (event.mime_type().compare(kMimeTypeTextUtf8) != 0) {
104     return;
105   }
106
107   ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_COPY_PASTE);
108   clipboard_writer.WriteText(base::UTF8ToUTF16(event.data()));
109
110   // Update local change-count to prevent this change from being picked up by
111   // CheckClipboardForChanges.
112   current_change_count_++;
113 }
114
115 void ClipboardAura::Core::Stop() {
116   clipboard_polling_timer_.reset();
117   client_clipboard_.reset();
118 }
119
120 void ClipboardAura::Core::SetPollingIntervalForTesting(
121     base::TimeDelta polling_interval) {
122   polling_interval_ = polling_interval;
123 }
124
125 void ClipboardAura::Core::CheckClipboardForChanges() {
126   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
127   uint64 change_count =
128       clipboard->GetSequenceNumber(ui::CLIPBOARD_TYPE_COPY_PASTE);
129
130   if (change_count == current_change_count_) {
131     return;
132   }
133
134   current_change_count_ = change_count;
135
136   protocol::ClipboardEvent event;
137   std::string data;
138
139   clipboard->ReadAsciiText(ui::CLIPBOARD_TYPE_COPY_PASTE, &data);
140   event.set_mime_type(kMimeTypeTextUtf8);
141   event.set_data(data);
142
143   client_clipboard_->InjectClipboardEvent(event);
144 }
145
146 scoped_ptr<Clipboard> Clipboard::Create() {
147   return make_scoped_ptr(
148       new ClipboardAura(content::BrowserThread::GetMessageLoopProxyForThread(
149           content::BrowserThread::UI)));
150 }
151
152 }  // namespace remoting