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