OLD | NEW |
| (Empty) |
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/chromeos/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 | |
OLD | NEW |