1// Copyright 2013 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'use strict'; 6 7/** 8 * @param {WebView} webView Web View tag. 9 * @param {string} url Share Url for an entry. 10 * @param {ShareClient.Observer} observer Observer instance. 11 * @constructor 12 */ 13function ShareClient(webView, url, observer) { 14 this.webView_ = webView; 15 this.url_ = url; 16 this.observer_ = observer; 17 this.loaded_ = false; 18 this.loading_ = false; 19 this.onMessageBound_ = this.onMessage_.bind(this); 20 this.onLoadStopBound_ = this.onLoadStop_.bind(this); 21 this.onLoadAbortBound_ = this.onLoadAbort_.bind(this); 22} 23 24/** 25 * Source origin of the client. 26 * @type {string} 27 * @const 28 */ 29ShareClient.SHARE_ORIGIN = 30 'chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj'; 31 32/** 33 * Target origin of the embedded dialog. 34 * @type {string} 35 * @const 36 */ 37ShareClient.SHARE_TARGET = 'https://drive.google.com'; 38 39/** 40 * Observes for state changes of the embedded dialog. 41 * @interface 42 */ 43ShareClient.Observer = function() { 44}; 45 46/** 47 * Notifies about the embedded dialog being loaded. 48 */ 49ShareClient.Observer.prototype.onLoaded = function() { 50}; 51 52/** 53 * Notifies when the the embedded dialog failed to load. 54 */ 55ShareClient.Observer.prototype.onLoadingFailed = function() { 56}; 57 58/** 59 * Notifies about changed dimensions of the embedded dialog. 60 * @param {number} width Width in pixels. 61 * @param {number} height Height in pixels. 62 * @param {function()} callback Completion callback. Call when finished 63 * handling the resize. 64 */ 65ShareClient.Observer.prototype.onResized = function(width, height, callback) { 66}; 67 68/** 69 * Notifies about the embedded dialog being closed. 70 */ 71ShareClient.Observer.prototype.onClosed = function() { 72}; 73 74/** 75 * Handles messages from the embedded dialog. 76 * @param {Event} e Message event. 77 * @private 78 */ 79ShareClient.prototype.onMessage_ = function(e) { 80 if (e.origin != ShareClient.SHARE_TARGET && !window.IN_TEST) { 81 // Logs added temporarily to track crbug.com/288783. 82 console.debug('Received a message from an illegal origin: ' + e.origin); 83 return; 84 } 85 86 var data = JSON.parse(e.data); 87 // Logs added temporarily to track crbug.com/288783. 88 console.debug('Received message: ' + data.type); 89 90 switch (data.type) { 91 case 'resize': 92 this.observer_.onResized(data.args.width, 93 data.args.height, 94 this.postMessage_.bind(this, 'resizeComplete')); 95 break; 96 case 'prepareForVisible': 97 this.postMessage_('prepareComplete'); 98 if (!this.loaded_) { 99 this.loading_ = false; 100 this.loaded_ = true; 101 this.observer_.onLoaded(); 102 } 103 break; 104 case 'setVisible': 105 if (!data.args.visible) 106 this.observer_.onClosed(); 107 break; 108 } 109}; 110 111/** 112 * Handles completion of the web view request. 113 * @param {Event} e Message event. 114 * @private 115 */ 116ShareClient.prototype.onLoadStop_ = function(e) { 117 // Logs added temporarily to track crbug.com/288783. 118 console.debug('Web View loaded.'); 119 120 this.postMessage_('makeBodyVisible'); 121}; 122 123/** 124 * Handles termination of the web view request. 125 * @param {Event} e Message event. 126 * @private 127 */ 128ShareClient.prototype.onLoadAbort_ = function(e) { 129 // Logs added temporarily to track crbug.com/288783. 130 console.debug('Web View failed to load with error: ' + e.reason + ', url: ' + 131 e.url + ' while requested: ' + this.url_); 132 133 this.observer_.onLoadFailed(); 134}; 135 136/** 137 * Sends a message to the embedded dialog. 138 * @param {string} type Message type. 139 * @param {Object=} opt_args Optional arguments. 140 * @private 141 */ 142ShareClient.prototype.postMessage_ = function(type, opt_args) { 143 // Logs added temporarily to track crbug.com/288783. 144 console.debug('Sending message: ' + type); 145 146 var message = { 147 type: type, 148 args: opt_args 149 }; 150 this.webView_.contentWindow.postMessage( 151 JSON.stringify(message), 152 !window.IN_TEST ? ShareClient.SHARE_TARGET : '*'); 153}; 154 155/** 156 * Loads the embedded dialog. Can be called only one. 157 */ 158ShareClient.prototype.load = function() { 159 if (this.loading_ || this.loaded_) 160 throw new Error('Already loaded.'); 161 this.loading_ = true; 162 163 // Logs added temporarily to track crbug.com/288783. 164 console.debug('Loading.'); 165 166 window.addEventListener('message', this.onMessageBound_); 167 this.webView_.addEventListener('loadstop', this.onLoadStopBound_); 168 this.webView_.addEventListener('loadabort', this.onLoadAbortBound_); 169 this.webView_.setAttribute('src', this.url_); 170}; 171 172/** 173 * Aborts loading of the embedded dialog and performs cleanup. 174 */ 175ShareClient.prototype.abort = function() { 176 window.removeEventListener('message', this.onMessageBound_); 177 this.webView_.removeEventListener('loadstop', this.onLoadStopBound_); 178 this.webView_.removeEventListener( 179 'loadabort', this.onLoadAbortBound_); 180 this.webView_.stop(); 181}; 182 183/** 184 * Cleans the dialog by removing all handlers. 185 */ 186ShareClient.prototype.dispose = function() { 187 this.abort(); 188}; 189