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