OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 /** | 5 /** |
6 * @fileoverview | 6 * @fileoverview |
7 * A class for moving clipboard items between the plugin and the OS. | 7 * A class for moving clipboard items between the plugin and the OS. |
8 */ | 8 */ |
9 | 9 |
10 'use strict'; | |
11 | |
12 /** @suppress {duplicate} */ | 10 /** @suppress {duplicate} */ |
13 var remoting = remoting || {}; | 11 var remoting = remoting || {}; |
14 | 12 |
15 /** | 13 (function() { |
16 * @constructor | 14 |
17 */ | 15 'use strict'; |
18 remoting.Clipboard = function() { | |
19 }; | |
20 | 16 |
21 /** | 17 /** |
22 * @private | 18 * @private |
23 * @enum {string} | 19 * @enum {string} |
24 */ | 20 */ |
25 remoting.Clipboard.prototype.ItemTypes = { | 21 var ItemTypes = { |
26 TEXT_TYPE: 'text/plain', | 22 TEXT_TYPE: 'text/plain', |
27 TEXT_UTF8_TYPE: 'text/plain; charset=UTF-8' | 23 TEXT_UTF8_TYPE: 'text/plain; charset=UTF-8' |
28 }; | 24 }; |
29 | 25 |
30 /** @private {string} */ | 26 /** |
31 remoting.Clipboard.prototype.previousContent = ""; | 27 * @constructor |
28 * @param {remoting.ClientPlugin} plugin | |
29 * @implements {base.Disposable} | |
30 */ | |
31 remoting.Clipboard = function(plugin) { | |
32 /** @private {string} */ | |
33 this.previousContent_ = ''; | |
32 | 34 |
33 /** @private {boolean} */ | 35 /** @private {boolean} */ |
34 remoting.Clipboard.prototype.itemFromHostTextPending = false; | 36 this.itemFromHostTextPending_ = false; |
35 | 37 |
36 /** @private {boolean} */ | 38 /** @private {boolean} */ |
37 remoting.Clipboard.prototype.blockOneClipboardSend_ = false; | 39 this.blockOneClipboardSend_ = true; |
38 | 40 |
39 /** | 41 /** @private */ |
40 * Notifies this object that a session has started. | 42 this.plugin_ = plugin; |
41 * | 43 |
42 * @return {void} Nothing. | 44 /** @private */ |
43 */ | 45 this.eventHooks_ = new base.Disposables( |
44 remoting.Clipboard.prototype.startSession = function() { | 46 new base.DomEventHook(plugin.element(), 'focus', |
kelvinp
2015/04/09 00:28:26
moved from connectedView.js
| |
45 // Clear the store of items sent and received. Those items now relate to a | 47 this.initiateToHost_.bind(this), false), |
46 // previous session. | 48 new base.DomEventHook(window, 'paste', this.onPaste_.bind(this), false), |
kelvinp
2015/04/09 00:28:26
moved from remoting.js
| |
47 this.previousContent = ""; | 49 new base.DomEventHook(window, 'copy', this.onCopy_.bind(this), false)); |
48 this.itemFromHostTextPending = false; | |
49 | 50 |
50 // Do a paste operation, but make sure the resulting clipboard data isn't sent | 51 // Do a paste operation, but make sure the resulting clipboard data isn't sent |
51 // to the host. This stops the host seeing items that were placed on the | 52 // to the host. This stops the host seeing items that were placed on the |
52 // clipboard before the session began. The user may not have intended such | 53 // clipboard before the session began. The user may not have intended such |
53 // items to be sent to the host. | 54 // items to be sent to the host. |
54 this.blockOneClipboardSend_ = true; | 55 this.initiateToHost_(); |
55 this.initiateToHost(); | 56 this.plugin_.setClipboardHandler(this.fromHost_.bind(this)); |
57 }; | |
58 | |
59 remoting.Clipboard.prototype.dispose = function() { | |
60 this.plugin_.setClipboardHandler(base.doNothing); | |
61 this.plugin_ = null; | |
62 base.dispose(this.eventHooks_); | |
63 this.eventHooks_ = null; | |
56 }; | 64 }; |
57 | 65 |
58 /** | 66 /** |
59 * Accepts a clipboard from the OS, and sends any changed clipboard items to | 67 * Accepts a clipboard from the OS, and sends any changed clipboard items to |
60 * the host. | 68 * the host. |
61 * | 69 * |
62 * Currently only text items are supported. | 70 * Currently only text items are supported. |
63 * | 71 * |
64 * @param {ClipboardData} clipboardData | 72 * @param {ClipboardData} clipboardData |
65 * @return {void} Nothing. | 73 * @return {void} Nothing. |
74 * @private | |
66 */ | 75 */ |
67 remoting.Clipboard.prototype.toHost = function(clipboardData) { | 76 remoting.Clipboard.prototype.toHost_ = function(clipboardData) { |
68 if (!clipboardData || !clipboardData.types || !clipboardData.getData) { | 77 if (!clipboardData || !clipboardData.types || !clipboardData.getData) { |
69 console.log('Got invalid clipboardData.'); | 78 console.log('Got invalid clipboardData.'); |
70 return; | 79 return; |
71 } | 80 } |
72 if (!remoting.clientSession) { | |
73 return; | |
74 } | |
75 for (var i = 0; i < clipboardData.types.length; i++) { | 81 for (var i = 0; i < clipboardData.types.length; i++) { |
76 var type = clipboardData.types[i]; | 82 var type = clipboardData.types[i]; |
77 var item = clipboardData.getData(type); | 83 var item = clipboardData.getData(type); |
78 if (!item) { | 84 if (!item) { |
79 item = ""; | 85 item = ''; |
80 } | 86 } |
81 console.log('Got clipboard from OS, type: ' + type + | 87 console.log('Got clipboard from OS, type: ' + type + |
82 ' length: ' + item.length + ' new: ' + | 88 ' length: ' + item.length + ' new: ' + |
83 (item != this.previousContent) + ' blocking-send: ' + | 89 (item != this.previousContent_) + ' blocking-send: ' + |
84 this.blockOneClipboardSend_); | 90 this.blockOneClipboardSend_); |
85 // The browser presents text clipboard items as 'text/plain'. | 91 // The browser presents text clipboard items as 'text/plain'. |
86 if (type == this.ItemTypes.TEXT_TYPE) { | 92 if (type == ItemTypes.TEXT_TYPE) { |
87 // Don't send the same item more than once. Otherwise the item may be | 93 // Don't send the same item more than once. Otherwise the item may be |
88 // sent to and fro indefinitely. | 94 // sent to and fro indefinitely. |
89 if (item != this.previousContent) { | 95 if (item != this.previousContent_) { |
90 if (!this.blockOneClipboardSend_) { | 96 if (!this.blockOneClipboardSend_) { |
91 // The plugin's JSON reader emits UTF-8. | 97 // The plugin's JSON reader emits UTF-8. |
92 console.log('Sending clipboard to host.'); | 98 console.log('Sending clipboard to host.'); |
93 remoting.clientSession.sendClipboardItem( | 99 remoting.clientSession.sendClipboardItem( |
94 this.ItemTypes.TEXT_UTF8_TYPE, item); | 100 ItemTypes.TEXT_UTF8_TYPE, item); |
95 } | 101 } |
96 this.previousContent = item; | 102 this.previousContent_ = item; |
97 } | 103 } |
98 } | 104 } |
99 } | 105 } |
100 this.blockOneClipboardSend_ = false; | 106 this.blockOneClipboardSend_ = false; |
101 }; | 107 }; |
102 | 108 |
103 /** | 109 /** |
104 * Accepts a clipboard item from the host, and stores it so that toOs() will | 110 * Accepts a clipboard item from the host, and stores it so that toOs() will |
105 * subsequently send it to the OS clipboard. | 111 * subsequently send it to the OS clipboard. |
106 * | 112 * |
107 * @param {string} mimeType The MIME type of the clipboard item. | 113 * @param {string} mimeType The MIME type of the clipboard item. |
108 * @param {string} item The clipboard item. | 114 * @param {string} item The clipboard item. |
109 * @return {void} Nothing. | 115 * @return {void} Nothing. |
110 */ | 116 */ |
111 remoting.Clipboard.prototype.fromHost = function(mimeType, item) { | 117 remoting.Clipboard.prototype.fromHost_ = function(mimeType, item) { |
112 // The plugin's JSON layer will correctly convert only UTF-8 data sent from | 118 // The plugin's JSON layer will correctly convert only UTF-8 data sent from |
113 // the host. | 119 // the host. |
114 console.log('Got clipboard from host, type: ' + mimeType + | 120 console.log('Got clipboard from host, type: ' + mimeType + |
115 ' length: ' + item.length + ' new: ' + | 121 ' length: ' + item.length + ' new: ' + |
116 (item != this.previousContent)); | 122 (item != this.previousContent_)); |
117 if (mimeType != this.ItemTypes.TEXT_UTF8_TYPE) { | 123 if (mimeType != ItemTypes.TEXT_UTF8_TYPE) { |
118 return; | 124 return; |
119 } | 125 } |
120 if (item == this.previousContent) { | 126 if (item == this.previousContent_) { |
121 return; | 127 return; |
122 } | 128 } |
123 this.previousContent = item; | 129 this.previousContent_ = item; |
124 this.itemFromHostTextPending = true; | 130 this.itemFromHostTextPending_ = true; |
125 this.initiateToOs(); | 131 this.initiateToOs_(); |
126 }; | 132 }; |
127 | 133 |
128 /** | 134 /** |
129 * Moves any pending clipboard items to a ClipboardData object. | 135 * Moves any pending clipboard items to a ClipboardData object. |
130 * | 136 * |
131 * @param {ClipboardData} clipboardData | 137 * @param {ClipboardData} clipboardData |
132 * @return {boolean} Whether any clipboard items were moved to the ClipboardData | 138 * @return {boolean} Whether any clipboard items were moved to the ClipboardData |
133 * object. | 139 * object. |
140 * @private | |
134 */ | 141 */ |
135 remoting.Clipboard.prototype.toOs = function(clipboardData) { | 142 remoting.Clipboard.prototype.toOs_ = function(clipboardData) { |
136 if (!this.itemFromHostTextPending) { | 143 if (!this.itemFromHostTextPending_) { |
137 console.log('Got unexpected clipboard copy event.'); | 144 console.log('Got unexpected clipboard copy event.'); |
138 return false; | 145 return false; |
139 } | 146 } |
140 // The JSON layer between the plugin and this webapp converts UTF-8 to the | 147 // The JSON layer between the plugin and this webapp converts UTF-8 to the |
141 // JS string encoding. The browser will convert JS strings to the correct | 148 // JS string encoding. The browser will convert JS strings to the correct |
142 // encoding, per OS and locale conventions, provided the data type is | 149 // encoding, per OS and locale conventions, provided the data type is |
143 // 'text/plain'. | 150 // 'text/plain'. |
144 console.log('Setting OS clipboard, length: ' + this.previousContent.length); | 151 console.log('Setting OS clipboard, length: ' + this.previousContent_.length); |
145 clipboardData.setData(this.ItemTypes.TEXT_TYPE, this.previousContent); | 152 clipboardData.setData(ItemTypes.TEXT_TYPE, this.previousContent_); |
146 this.itemFromHostTextPending = false; | 153 this.itemFromHostTextPending_ = false; |
147 return true; | 154 return true; |
148 }; | 155 }; |
149 | 156 |
150 /** | 157 /** |
151 * Initiates the process of sending any fresh items on the OS clipboard, to the | 158 * Initiates the process of sending any fresh items on the OS clipboard, to the |
152 * host. | 159 * host. |
153 * | 160 * |
154 * This method makes the browser fire a paste event, which provides access to | 161 * This method makes the browser fire a paste event, which provides access to |
155 * the OS clipboard. That event will be caught by a handler in the document, | 162 * the OS clipboard. That event will be caught by a handler in the document, |
156 * which will call toHost(). | 163 * which will call toHost(). |
164 * @private | |
157 */ | 165 */ |
158 remoting.Clipboard.prototype.initiateToHost = function() { | 166 remoting.Clipboard.prototype.initiateToHost_ = function() { |
159 // It would be cleaner to send a paste command to the plugin element, | 167 // It would be cleaner to send a paste command to the plugin element, |
160 // but that's not supported. | 168 // but that's not supported. |
161 //console.log('Initiating clipboard paste.'); | 169 //console.log('Initiating clipboard paste.'); |
162 document.execCommand("paste"); | 170 document.execCommand('paste'); |
163 }; | 171 }; |
164 | 172 |
165 /** | 173 /** |
166 * Initiates the process of sending any items freshly received from the host, | 174 * Initiates the process of sending any items freshly received from the host, |
167 * to the OS clipboard. | 175 * to the OS clipboard. |
168 * | 176 * |
169 * This method makes the browser fire a copy event, which provides access to | 177 * This method makes the browser fire a copy event, which provides access to |
170 * the OS clipboard. That event will be caught by a handler in the document, | 178 * the OS clipboard. That event will be caught by a handler in the document, |
171 * which will call toOs(). | 179 * which will call toOs(). |
180 * @private | |
172 */ | 181 */ |
173 remoting.Clipboard.prototype.initiateToOs = function() { | 182 remoting.Clipboard.prototype.initiateToOs_ = function() { |
174 // It would be cleaner to send a paste command to the plugin element, | 183 // It would be cleaner to send a paste command to the plugin element, |
175 // but that's not supported. | 184 // but that's not supported. |
176 console.log('Initiating clipboard copy.'); | 185 console.log('Initiating clipboard copy.'); |
177 document.execCommand("copy"); | 186 document.execCommand('copy'); |
178 }; | 187 }; |
179 | 188 |
180 /** @type {remoting.Clipboard} */ | 189 /** |
181 remoting.clipboard = null; | 190 * Callback function called when the browser window gets a paste operation. |
191 * | |
192 * @param {Event} event | |
193 * @return {void} Nothing. | |
194 * @private | |
195 */ | |
196 remoting.Clipboard.prototype.onPaste_ = function(event) { | |
197 if (event && event.clipboardData) { | |
198 this.toHost_(event.clipboardData); | |
199 } | |
200 }; | |
201 | |
202 /** | |
203 * Callback function called when the browser window gets a copy operation. | |
204 * | |
205 * @param {Event} event | |
206 * @return {void} Nothing. | |
207 * @private | |
208 */ | |
209 remoting.Clipboard.prototype.onCopy_ = function(event) { | |
210 if (event && event.clipboardData && this.toOs_(event.clipboardData)) { | |
211 // The default action may overwrite items that we added to clipboardData. | |
212 event.preventDefault(); | |
213 } | |
214 }; | |
215 | |
216 })(); | |
OLD | NEW |