@@ -6,6 +6,7 @@ var formatLocale = require('d3-format').formatLocale;
66var isNumeric = require ( 'fast-isnumeric' ) ;
77var b64encode = require ( 'base64-arraybuffer' ) ;
88
9+ var version = require ( '../version' ) . version ;
910var Registry = require ( '../registry' ) ;
1011var PlotSchema = require ( '../plot_api/plot_schema' ) ;
1112var Template = require ( '../plot_api/plot_template' ) ;
@@ -201,40 +202,57 @@ function positionPlayWithData(gd, container) {
201202}
202203
203204plots . sendDataToCloud = function ( gd ) {
204- var destUrl = ( window . PLOTLYENV || { } ) . BASE_URL || gd . _context . plotlyServerURL ;
205- if ( ! destUrl ) {
205+ var baseUrl = ( window . PLOTLYENV || { } ) . BASE_URL || gd . _context . plotlyServerURL ;
206+ if ( ! baseUrl ) {
206207 console . error ( 'No destination URL provided (plotlyServerURL is not set)' ) ;
207208 return ;
208209 }
209210
211+ // Plotly Cloud origin, used to validate incoming messages and to target outgoing ones.
212+ var cloudOrigin ;
213+ try {
214+ cloudOrigin = new URL ( baseUrl ) . origin ;
215+ } catch ( e ) {
216+ console . error ( 'Invalid plotlyServerURL: ' + baseUrl ) ;
217+ return ;
218+ }
219+
220+ // The page that handles login and signals back when authentication succeeds.
221+ var uploadUrl = baseUrl . replace ( / \/ + $ / , '' ) + '/upload' ;
222+
210223 gd . emit ( 'plotly_beforeexport' ) ;
211224
212- var hiddenformDiv = d3 . select ( gd )
213- . append ( 'div' )
214- . attr ( 'id' , 'hiddenform' )
215- . style ( 'display' , 'none' ) ;
225+ // Build the request body: the chart JSON plus the plotly.js version used to
226+ // generate it, so Cloud can host the chart with a compatible plotly.js version.
227+ var chart = JSON . parse ( plots . graphJson ( gd , false , 'keepdata' ) ) ;
228+ chart . version = version ;
229+
230+ // Open the Cloud login page in a new tab. We keep a reference so we can post
231+ // the chart back to it once Cloud reports that authentication succeeded.
232+ var cloudWindow = window . open ( uploadUrl , '_blank' ) ;
233+ if ( ! cloudWindow ) {
234+ console . error ( 'Unable to open Plotly Cloud (the popup may have been blocked)' ) ;
235+ gd . emit ( 'plotly_afterexport' ) ;
236+ return ;
237+ }
216238
217- var hiddenform = hiddenformDiv
218- . append ( 'form' )
219- . attr ( {
220- action : destUrl ,
221- method : 'post' ,
222- target : '_blank'
223- } ) ;
239+ var handleMessage = function ( event ) {
240+ // Only trust messages coming from the Cloud origin.
241+ if ( event . origin !== cloudOrigin ) return ;
224242
225- var hiddenformInput = hiddenform
226- . append ( 'input' )
227- . attr ( {
228- type : 'text' ,
229- name : 'data'
230- } ) ;
243+ if ( event . data && event . data . type === 'authenticated' ) {
244+ cloudWindow . postMessage ( {
245+ type : 'chart' ,
246+ chart : chart
247+ } , cloudOrigin ) ;
248+
249+ window . removeEventListener ( 'message' , handleMessage ) ;
250+ gd . emit ( 'plotly_afterexport' ) ;
251+ }
252+ } ;
231253
232- hiddenformInput . node ( ) . value = plots . graphJson ( gd , false , 'keepdata' ) ;
233- console . log ( `sending chart object to ${ destUrl } ` ) ;
234- hiddenform . node ( ) . submit ( ) ;
235- hiddenformDiv . remove ( ) ;
254+ window . addEventListener ( 'message' , handleMessage ) ;
236255
237- gd . emit ( 'plotly_afterexport' ) ;
238256 return false ;
239257} ;
240258
0 commit comments