MarkTraceur has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/197347

Change subject: WIP Use promises for handlers and transports
......................................................................

WIP Use promises for handlers and transports

WIP because there's a potential bug in core chunked uploads that I want
to make sure is a bug in core, then I can finish testing this.

Bug: T92640
Change-Id: I010ad9aa93999ad8a2fca5a5b4bce871f8255a7d
---
M resources/controller/uw.controller.Upload.js
M resources/mw.ApiUploadFormDataHandler.js
M resources/mw.ApiUploadHandler.js
M resources/mw.FirefoggHandler.js
M resources/mw.FirefoggTransport.js
M resources/mw.FormDataTransport.js
M resources/mw.IframeTransport.js
7 files changed, 267 insertions(+), 220 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/UploadWizard 
refs/changes/47/197347/1

diff --git a/resources/controller/uw.controller.Upload.js 
b/resources/controller/uw.controller.Upload.js
index 3c800bc..f9fccac 100644
--- a/resources/controller/uw.controller.Upload.js
+++ b/resources/controller/uw.controller.Upload.js
@@ -143,7 +143,7 @@
        };
 
        UP.transitionStarter = function ( upload ) {
-               upload.start();
+               return upload.start();
        };
 
        uw.controller.Upload = Upload;
diff --git a/resources/mw.ApiUploadFormDataHandler.js 
b/resources/mw.ApiUploadFormDataHandler.js
index a45fcbe..c1f9efa 100644
--- a/resources/mw.ApiUploadFormDataHandler.js
+++ b/resources/mw.ApiUploadFormDataHandler.js
@@ -24,21 +24,7 @@
                this.transport = new mw.FormDataTransport(
                        this.$form[0].action,
                        this.formData
-               ).on( 'progress', function ( evt, xhr ) {
-                       var fraction;
-
-                       if ( upload.state === 'aborted' ) {
-                               xhr.abort();
-                               return;
-                       }
-
-                       if ( evt.lengthComputable ) {
-                               fraction = parseFloat( evt.loaded / evt.total );
-                               upload.setTransportProgress( fraction );
-                       }
-               } ).on( 'transported', function ( result ) {
-                       upload.setTransported( result );
-               } ).on( 'update-stage', function ( stage ) {
+               ).on( 'update-stage', function ( stage ) {
                        upload.ui.setStatus( 'mwe-upwiz-' + stage );
                } );
        };
@@ -47,36 +33,46 @@
                /**
                 * Optain a fresh edit token.
                 * If successful, store token and call a callback.
-                * @param ok callback on success
-                * @param err callback on error
+                * @return {jQuery.Promise}
                 */
-               configureEditToken: function ( callerOk, err ) {
-                       var handler = this,
-                               ok = function ( token ) {
-                                       handler.formData.token = token;
-                                       callerOk();
-                               };
+               configureEditToken: function () {
+                       var handler = this;
 
-                       this.api.getEditToken().done( ok ).fail( err );
+                       return this.api.getEditToken().then( function ( token ) 
{
+                               handler.formData.token = token;
+                       } );
                },
 
                /**
                 * Kick off the upload!
+                * @return {jQuery.Promise}
                 */
                start: function () {
-                       function ok() {
+                       var handler = this;
+
+                       return this.configureEditToken().then( function () {
                                handler.beginTime = ( new Date() ).getTime();
                                handler.upload.ui.setStatus( 
'mwe-upwiz-transport-started' );
                                handler.upload.ui.showTransportProgress();
-                               handler.transport.upload( handler.upload.file );
-                       }
+                               return handler.transport.upload( 
handler.upload.file )
+                                       .progress( function ( evt, xhr ) {
+                                               var fraction;
 
-                       function err( code, info ) {
+                                               if ( upload.state === 'aborted' 
) {
+                                                       xhr.abort();
+                                                       return;
+                                               }
+
+                                               if ( evt.lengthComputable ) {
+                                                       fraction = parseFloat( 
evt.loaded / evt.total );
+                                                       
handler.upload.setTransportProgress( fraction );
+                                               }
+                                       } ).then( function ( result ) {
+                                               handler.upload.setTransported( 
result );
+                                       } );
+                       }, function ( code, info ) {
                                handler.upload.setError( code, info );
-                       }
-
-                       var handler = this;
-                       this.configureEditToken( ok, err );
+                       } );
                }
        };
 }( mediaWiki, jQuery ) );
diff --git a/resources/mw.ApiUploadHandler.js b/resources/mw.ApiUploadHandler.js
index d0e42c6..b61c3fd 100644
--- a/resources/mw.ApiUploadHandler.js
+++ b/resources/mw.ApiUploadHandler.js
@@ -65,14 +65,12 @@
                 * @param callback to return true on success
                 */
                configureEditToken: function ( callerOk, err ) {
-                       function ok( token ) {
-                               handler.addFormInputIfMissing( 'token', token );
-                               callerOk();
-                       }
-
                        var handler = this;
 
-                       this.api.getEditToken().done( ok ).fail( err );
+                       return this.api.getEditToken()
+                               .then( function ( token ) {
+                                       handler.addFormInputIfMissing( 'token', 
token );
+                               } );
                },
 
                /**
@@ -100,23 +98,23 @@
 
                /**
                 * Kick off the upload!
+                * @return {jQuery.Promise}
                 */
                start: function () {
-                       function ok() {
-                               handler.beginTime = ( new Date() ).getTime();
-                               handler.upload.ui.setStatus( 
'mwe-upwiz-transport-started' );
-                               handler.upload.ui.showTransportProgress();
-                               handler.transport.getSetUpStatus().done( 
function () {
-                                       handler.$form.submit();
-                               } );
-                       }
-
-                       function err( code, info ) {
-                               handler.upload.setError( code, info );
-                       }
-
                        var handler = this;
-                       this.configureEditToken( ok, err );
+
+                       return this.configureEditToken()
+                               .then( function () {
+                                       var deferred = $.Deferred();
+
+                                       handler.beginTime = ( new Date() 
).getTime();
+                                       handler.upload.ui.setStatus( 
'mwe-upwiz-transport-started' );
+                                       
handler.upload.ui.showTransportProgress();
+
+                                       return handler.transport.upload();
+                               }, function ( code, info ) {
+                                       handler.upload.setError( code, info );
+                               } );
                }
        };
 }( mediaWiki, jQuery ) );
diff --git a/resources/mw.FirefoggHandler.js b/resources/mw.FirefoggHandler.js
index d9a4101..b56c5df 100644
--- a/resources/mw.FirefoggHandler.js
+++ b/resources/mw.FirefoggHandler.js
@@ -44,25 +44,8 @@
                                        file,
                                        this.api,
                                        fogg
-                               ).on( 'progress', function ( data ) {
-                                       if ( upload.state === 'aborted' ) {
-                                               fogg.cancel();
-                                       } else {
-                                               upload.setTransportProgress( 
data.progress );
-                                               upload.ui.setStatus( 
'mwe-upwiz-encoding' );
-                                       }
-                               } ).on( 'transported', function ( result ) {
-                                       mw.log( 
'FirefoggTransport::getTransport> Transport done ' + JSON.stringify( result ) );
-                                       upload.setTransported( result );
-                               } ).on( 'encoding', function () {
-                                       upload.ui.setStatus( 
'mwe-upwiz-encoding' );
-                               } ).on( 'starting', function ( file ) {
-                                       upload.ui.setStatus( 
'mwe-upwiz-uploading' );
-                                       upload.file = file;
-                                       transport.uploadHandler = new 
mw.ApiUploadFormDataHandler( upload, handler.api );
-                                       transport.uploadHandler.start();
-                               } );
-
+                               );
+                               
                                this.transport = transport;
                        }
 
@@ -72,9 +55,13 @@
                /**
                 * If chunks are disabled transcode then upload else
                 * upload and transcode at the same time
+                * @return {jQuery.Promise}
                 */
                start: function () {
-                       var title;
+                       var title,
+                               transport = this.getTransport(),
+                               handler = this,
+                               upload = this.upload;
 
                        mw.log( 'mw.FirefoggHandler::start> Upload start!' );
 
@@ -90,7 +77,26 @@
                        this.beginTime = ( new Date() ).getTime();
                        this.upload.ui.setStatus( 'mwe-upwiz-transport-started' 
);
                        this.upload.ui.showTransportProgress();
-                       this.getTransport().doUpload();
+                       return this.getTransport().upload()
+                               .progress( function ( data ) {
+                                       if ( data === 'encoding' ) {
+                                               upload.ui.setStatus( 
'mwe-upwiz-encoding' );
+                                       } else if ( upload.state === 'aborted' 
) {
+                                               fogg.cancel();
+                                       } else {
+                                               upload.setTransportProgress( 
data.progress );
+                                               upload.ui.setStatus( 
'mwe-upwiz-encoding' );
+                                       }
+                               } ).then( function ( file ) {
+                                       // Encoding finished, now transport.
+                                       upload.ui.setStatus( 
'mwe-upwiz-uploading' );
+                                       upload.file = file;
+                                       transport.uploadHandler = new 
mw.ApiUploadFormDataHandler( upload, handler.api );
+                                       return transport.uploadHandler.start();
+                               }, function ( result ) {
+                                       mw.log( 
'FirefoggTransport::getTransport> Transport done ' + JSON.stringify( result ) );
+                                       upload.setTransported( result );
+                               } );
                }
        };
 }( mediaWiki ) );
diff --git a/resources/mw.FirefoggTransport.js 
b/resources/mw.FirefoggTransport.js
index 534b0c5..ee2bbc6 100644
--- a/resources/mw.FirefoggTransport.js
+++ b/resources/mw.FirefoggTransport.js
@@ -4,61 +4,55 @@
        /**
         * Represents a "transport" for files to upload; in this case using 
Firefogg.
         * @class mw.FirefoggTransport
-        * @mixins OO.EventEmitter
         * @constructor
         * @param {File} file
         * @param {mw.Api} api
         * @param {Firefogg} fogg Firefogg instance
         */
        mw.FirefoggTransport = function ( file, api, fogg ) {
-               oo.EventEmitter.call( this );
-
                this.fileToUpload = file;
                this.api = api;
                this.fogg = fogg;
        };
 
-       oo.mixinClass( mw.FirefoggTransport, oo.EventEmitter );
-
        FTP = mw.FirefoggTransport.prototype;
 
        /**
         * Do an upload
+        * @return {jQuery.Promise}
         */
-       FTP.doUpload = function () {
-               var fileToUpload = this.fileToUpload, transport = this;
+       FTP.upload = function () {
+               var fileToUpload = this.fileToUpload, transport = this,
+                       deferred = $.Deferred();
 
                //Encode or passthrough Firefogg before upload
                if ( this.isUploadFormat() ) {
-                       this.doFormDataUpload( fileToUpload );
-               } else {
-                       this.emit( 'encoding' );
-                       this.fogg.encode( JSON.stringify( 
this.getEncodeSettings() ),
-                               function (result, file) {
-                                       result = JSON.parse(result);
-                                       if ( result.progress === 1 ) {
-                                               //encoding done
-                                               
transport.doFormDataUpload(file);
-                                       } else {
-                                               //encoding failed
-                                               var response = {
-                                                       error: {
-                                                               code: 500,
-                                                               info: 'Encoding 
failed'
-                                                       }
-                                               };
-
-                                               transport.emit( 'transported', 
response );
-                                       }
-                               }, function ( progress ) { //progress
-                                       transport.emit( 'progress', JSON.parse( 
progress ) );
-                               }
-                       );
+                       return $.Deferred().resolve( fileToUpload );
                }
-       };
 
-       FTP.doFormDataUpload = function ( file ) {
-               this.emit( 'starting', file );
+               deferred.notify( 'encoding' );
+
+               this.fogg.encode( JSON.stringify( this.getEncodeSettings() ),
+                       function ( result, file ) {
+                               result = JSON.parse(result);
+                               if ( result.progress === 1 ) {
+                                       //encoding done
+                                       deferred.resolve( file );
+                               } else {
+                                       //encoding failed
+                                       deferred.reject( {
+                                               error: {
+                                                       code: 500,
+                                                       info: 'Encoding failed'
+                                               }
+                                       } );
+                               }
+                       }, function ( progress ) {
+                               deferred.notify( JSON.parse( progress ) );
+                       }
+               );
+
+               return deferred.promise();
        };
 
        /**
diff --git a/resources/mw.FormDataTransport.js 
b/resources/mw.FormDataTransport.js
index 36c84c4..87bb2f9 100644
--- a/resources/mw.FormDataTransport.js
+++ b/resources/mw.FormDataTransport.js
@@ -55,18 +55,19 @@
 
        /**
         * Creates an XHR and sets some generic event handlers on it.
+        * @param {jQuery.Deferred} deferred Object to send events to.
         * @return XMLHttpRequest
         */
-       FDTP.createXHR = function () {
+       FDTP.createXHR = function ( deferred ) {
                var xhr = new XMLHttpRequest(),
                        transport = this;
 
                xhr.upload.addEventListener( 'progress', function ( evt ) {
-                       transport.emit( 'progress', evt );
+                       deferred.progress( evt, xhr );
                }, false );
 
                xhr.addEventListener( 'abort', function ( evt ) {
-                       transport.emitParsedResponse( evt );
+                       deferred.reject( transport.parseResponse( evt ) );
                }, false );
 
                return xhr;
@@ -122,8 +123,12 @@
                }
        };
 
+       /**
+        * Start the upload with the provided file.
+        * @return {jQuery.Promise}
+        */
        FDTP.upload = function ( file ) {
-               var formData,
+               var formData, deferred,
                        transport = this;
 
                // use timestamp + filename to avoid conflicts on server
@@ -134,28 +139,39 @@
                }).join('');
 
                if ( this.config.enableChunked && file.size > this.chunkSize ) {
-                       this.uploadChunk( file, 0 );
+                       return this.uploadChunk( file, 0 );
                } else {
-                       this.xhr = this.createXHR();
-                       this.xhr.addEventListener('load', function (evt) {
-                               transport.emitParsedResponse( evt );
+                       deferred = $.Deferred();
+                       this.xhr = this.createXHR( deferred );
+                       this.xhr.addEventListener( 'load', function ( evt ) {
+                               deferred.resolve( transport.parseResponse( evt 
) );
                        }, false);
-                       this.xhr.addEventListener('error', function (evt) {
-                               transport.emitParsedResponse( evt );
+                       this.xhr.addEventListener( 'error', function ( evt ) {
+                               deferred.reject( transport.parseResponse( evt ) 
);
                        }, false);
 
                        formData = this.createFormData( this.tempname );
                        formData.append( 'file', file );
 
                        this.sendData( this.xhr, formData );
+
+                       return deferred.promise();
                }
        };
 
+       /**
+        * Upload a single chunk.
+        * @param {File} file
+        * @param {number} offset Offset in bytes.
+        * @return {jQuery.Promise}
+        */
        FDTP.uploadChunk = function ( file, offset ) {
                var formData,
+                       deferred = $.Deferred(),
                        transport = this,
                        bytesAvailable = file.size,
                        chunk;
+
                if ( this.aborted ) {
                        if ( this.xhr ) {
                                this.xhr.abort();
@@ -172,55 +188,9 @@
                        chunk = file.slice(offset, offset + this.chunkSize, 
file.type);
                }
 
-               this.xhr = this.createXHR();
-               this.xhr.addEventListener('load', function (evt) {
-                       transport.responseText = evt.target.responseText;
-                       transport.parseResponse(evt, function (response) {
-                               if (response.upload && response.upload.filekey) 
{
-                                       transport.filekey = 
response.upload.filekey;
-                               }
-                               if (response.upload && response.upload.result 
=== 'Success') {
-                                       //upload finished and can be unstashed 
later
-                                       transport.emit( 'transported', response 
);
-                               } else if (response.upload && 
response.upload.result === 'Poll') {
-                                       //Server not ready, wait for 3 seconds
-                                       setTimeout(function () {
-                                               transport.checkStatus();
-                                       }, 3000);
-                               } else if (response.upload && 
response.upload.result === 'Continue') {
-                                       //reset retry counter
-                                       transport.retries = 0;
-                                       //start uploading next chunk
-                                       transport.uploadChunk( file, 
response.upload.offset );
-                               } else {
-                                       //failed to upload, try again in 3 
seconds
-                                       transport.retries++;
-                                       if (transport.maxRetries > 0 && 
transport.retries >= transport.maxRetries) {
-                                               mw.log.warn( 'Max retries 
exceeded on unknown response' );
-                                               //upload failed, raise response
-                                               transport.emit( 'transported', 
response );
-                                       } else {
-                                               mw.log( 'Retry #' + 
transport.retries + ' on unknown response' );
-                                               setTimeout(function () {
-                                                       transport.uploadChunk( 
file, offset );
-                                               }, 3000);
-                                       }
-                               }
-                       });
-               }, false);
-               this.xhr.addEventListener('error', function (evt) {
-                       //failed to upload, try again in 3 second
-                       transport.retries++;
-                       if (transport.maxRetries > 0 && transport.retries >= 
transport.maxRetries) {
-                               mw.log.warn( 'Max retries exceeded on error 
event' );
-                               transport.emitParsedResponse( evt );
-                       } else {
-                               mw.log( 'Retry #' + transport.retries + ' on 
error event' );
-                               setTimeout(function () {
-                                       transport.uploadChunk( file, offset );
-                               }, 3000);
-                       }
-               }, false);
+               this.xhr = this.createXHR( deferred );
+               this.xhr.addEventListener( 'load', deferred.resolve, false );
+               this.xhr.addEventListener( 'error', deferred.reject, false );
 
                formData = this.createFormData( this.tempname, offset );
 
@@ -240,8 +210,99 @@
                }
 
                this.sendData( this.xhr, formData );
+
+               return deferred.promise().then( function ( evt ) {
+                       return transport.parseResponse( evt );
+               }, function ( evt ) {
+                       return transport.parseResponse( evt );
+               } ).then( function ( response ) {
+                       if ( response.upload && response.upload.result ) {
+                               switch ( response.upload.result ) {
+                                       case 'Continue':
+                                               // Reset retry counter
+                                               transport.retries = 0;
+                                               // Start uploading next chunk
+                                               return transport.uploadChunk( 
file, response.upload.offset );
+                                       case 'Success':
+                                               // Just pass the response 
through.
+                                               return response;
+                                       case 'Poll':
+                                               // Need to retry with 
checkStatus.
+                                               return 
transport.retryWithMethod( 'checkStatus' );
+                               }
+                       } else {
+                               // Failed to upload, try again in 3 seconds
+                               return transport.maybeRetry(
+                                       'on unknown response',
+                                       response,
+                                       'uploadChunk',
+                                       file, offset
+                               );
+                       }
+               }, function ( response ) {
+                       return transport.maybeRetry(
+                               'on error event',
+                               response,
+                               'uploadChunk',
+                               file, offset
+                       );
+               } );
        };
 
+       /**
+        * Handle possible retry event - rejected if maximum retries already 
fired.
+        * @param {string} contextMsg
+        * @param {Object} response
+        * @param {string} retryMethod
+        * @param {File} [file]
+        * @param {number} [offset]
+        * @return {jQuery.Promise}
+        */
+       FDTP.maybeRetry = function ( contextMsg, response, retryMethod, file, 
offset ) {
+               var transport = this;
+               
+               this.retries++;
+
+               if ( this.tooManyRetries() ) {
+                       mw.log.warn( 'Max retries exceeded ' + contextMsg );
+                       return $.Deferred().reject( response );
+               } else {
+                       mw.log( 'Retry #' + this.retries + ' ' + contextMsg );
+                       return this.retryWithMethod( retryMethod, file, offset 
);
+               }
+       };
+
+       /**
+        * Have we retried too many times already?
+        * @return {boolean}
+        */
+       FDTP.tooManyRetries = function () {
+               return this.maxRetries > 0 && this.retries >= this.maxRetries;
+       };
+
+       /**
+        * Either retry uploading or checking the status.
+        * @param {'uploadChunk'|'checkStatus'} methodName
+        * @param {File} [file]
+        * @param {number} [offset]
+        * @return {jQuery.Promise}
+        */
+       FDTP.retryWithMethod = function ( methodName, file, offset ) {
+               var retryDeferred,
+                       transport = this;
+
+               retryDeferred = $.Deferred();
+               setTimeout( function () {
+                       transport[methodName]( file, offset ).then( 
retryDeferred.resolve, retryDeferred.reject );
+               }, 3000 );
+
+               return retryDeferred.promise();
+       };
+
+       /**
+        * Check the status of the upload.
+        * @return {jQuery.Promise}
+        */
        FDTP.checkStatus = function () {
                var transport = this,
                        params = {};
@@ -258,41 +319,40 @@
                });
                params.checkstatus =  true;
                params.filekey =  this.filekey;
-               this.api.post( params )
-                       .done( function (response) {
-                               if (response.upload && response.upload.result 
=== 'Poll') {
+               return this.api.post( params )
+                       .then( function ( response ) {
+                               if ( response.upload && response.upload.result 
=== 'Poll' ) {
                                        //If concatenation takes longer than 10 
minutes give up
                                        if ( ( ( new Date() ).getTime() - 
transport.firstPoll ) > 10 * 60 * 1000 ) {
-                                               transport.emit( 'transported', {
+                                               return $.Deferred().reject( {
                                                        code: 'server-error',
                                                        info: 'unknown server 
error'
                                                } );
-                                       //Server not ready, wait for 3 more 
seconds
                                        } else {
                                                if ( response.upload.stage === 
undefined && window.console ) {
                                                        window.console.log( 
'Unable to check file\'s status' );
+                                                       return 
$.Deferred().reject();
                                                } else {
                                                        //Statuses that can be 
returned:
                                                        // * queued
                                                        // * publish
                                                        // * assembling
                                                        transport.emit( 
'update-stage', response.upload.stage );
-                                                       setTimeout(function () {
-                                                               
transport.checkStatus();
-                                                       }, 3000);
+                                                       return 
transport.retryWithMethod( 'checkStatus' );
                                                }
                                        }
-                               } else {
-                                       transport.emit( 'transported', response 
);
                                }
-                       } )
-                       .fail( function (status, response) {
-                               transport.emit( 'transported', response );
                        } );
        };
 
-       FDTP.parseResponse = function ( evt, cb ) {
+       /**
+        * Parse response from the server.
+        * @param {Event} evt
+        * @return {Object}
+        */
+       FDTP.parseResponse = function ( evt ) {
                var response;
+
                try {
                        response = $.parseJSON(evt.target.responseText);
                } catch ( e ) {
@@ -304,20 +364,7 @@
                        };
                }
 
-               cb( response );
-       };
-
-       /**
-        * Emits a 'transported' event with an object indicating status,
-        * parsed from JSON in the event body.
-        * @param {Event} evt The response event.
-        */
-       FDTP.emitParsedResponse = function ( evt ) {
-               var transport = this;
-
-               this.parseResponse( evt, function ( response ) {
-                       transport.emit( 'transported', response );
-               } );
+               return response;
        };
 
        FDTP.geckoFormData = function () {
diff --git a/resources/mw.IframeTransport.js b/resources/mw.IframeTransport.js
index 063c97a..90cb719 100644
--- a/resources/mw.IframeTransport.js
+++ b/resources/mw.IframeTransport.js
@@ -17,7 +17,6 @@
                oo.EventEmitter.call( this );
 
                function setupFormCallback() {
-                       transport.configureForm();
                        transport.$iframe.off( 'load', setupFormCallback );
                        transport.setUpStatus.resolve();
                }
@@ -71,29 +70,6 @@
        };
 
        /**
-        * Configure a form with a File Input so that it submits to the iframe
-        * Ensure callback on completion of upload
-        */
-       ITP.configureForm = function () {
-               var transport = this;
-
-               // Set the form target to the iframe
-               this.$form.prop( 'target', this.iframeId );
-
-               // attach an additional handler to the form, so, when 
submitted, it starts showing the progress
-               // XXX this is lame .. there should be a generic way to 
indicate busy status...
-               this.$form.submit( function () {
-                       return true;
-               } );
-
-               // Set up the completion callback
-               this.$iframe.load( function () {
-                       transport.emit( 'progress', 1.0 );
-                       transport.processIframeResult( this );
-               } );
-       };
-
-       /**
         * Process the result of the form submission, returned to an iframe.
         * This is the iframe's onload event.
         *
@@ -136,6 +112,36 @@
                }
 
                // Process the API result
-               this.emit( 'transported', response );
+               return response;
+       };
+
+       /**
+        * Start the upload.
+        * @return {jQuery.Promise}
+        */
+       ITP.upload = function () {
+               var transport = this;
+
+               return this.getSetUpStatus().then( function () {
+                       var deferred = $.Deferred();
+
+                       // Set the form target to the iframe
+                       transport.$form.prop( 'target', this.iframeId );
+
+                       // attach an additional handler to the form, so, when 
submitted, it starts showing the progress
+                       // XXX this is lame .. there should be a generic way to 
indicate busy status...
+                       transport.$form.submit( function () {
+                               return true;
+                       } );
+
+                       transport.$iframe.on( 'load', function () {
+                               deferred.notify( 1.0 );
+                               deferred.resolve( 
transport.processIframeResult() );
+                       } );
+
+                       transport.$form.submit();
+
+                       return deferred.promise();
+               } );
        };
 }( mediaWiki, jQuery, OO ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/197347
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I010ad9aa93999ad8a2fca5a5b4bce871f8255a7d
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/UploadWizard
Gerrit-Branch: master
Gerrit-Owner: MarkTraceur <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to