Jdlrobson has uploaded a new change for review.

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

Change subject: WIP: Use core code where available for api
......................................................................

WIP: Use core code where available for api

* Reduce the amount of custom Api code we have here based on developments
in core.

Note for nearby and uploads we use JSONP to aid local development for requests
that do not require any authentication. The offering in core enforces use of
CORS.

TODO:
* Nearby when using $wgMFNearbyEndpoint should use JSONP not CORS

Dependency: Ib5f8d5060bbf66d57c34bc8573061b69e5034b85
Bug: T110102
Change-Id: Iadd08d44519f76a4f6d45921a6c15a3ac8732b93
---
M includes/Resources.php
M resources/mobile.foreignApi/ForeignApi.js
M resources/mobile.startup/api.js
M resources/mobile.watchlist/WatchListApi.js
D tests/qunit/mobile.foreignApi/test_ForeignApi.js
M tests/qunit/mobile.startup/test_api.js
6 files changed, 35 insertions(+), 263 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend 
refs/changes/35/233635/1

diff --git a/includes/Resources.php b/includes/Resources.php
index a6f1f03..ce36f17 100644
--- a/includes/Resources.php
+++ b/includes/Resources.php
@@ -497,6 +497,7 @@
        'mobile.foreignApi' => $wgMFResourceFileModuleBoilerplate + array(
                'dependencies' => array(
                        'mobile.startup',
+                       'mediawiki.ForeignApi.core',
                ),
                'scripts' => array(
                        'resources/mobile.foreignApi/ForeignApi.js',
diff --git a/resources/mobile.foreignApi/ForeignApi.js 
b/resources/mobile.foreignApi/ForeignApi.js
index 2e762b3..a4fef37 100644
--- a/resources/mobile.foreignApi/ForeignApi.js
+++ b/resources/mobile.foreignApi/ForeignApi.js
@@ -1,127 +1,29 @@
-( function ( M, $ ) {
-       var api = M.require( 'api' ),
-               Api = api.Api,
-               ForeignApi;
+( function ( M ) {
+       var ForeignApi,
+               Api = M.require( 'mobile.startup/Api' );
 
        /**
         * Extends API for cross origin requests
+        * Uses JSONP for non-post requests
         * @class ForeignApi
         * @extends Api
+        * @extends mw.ForeignApi
         */
-       ForeignApi = Api.extend( {
-               /**
-                * Get a central auth token from the current host for use on 
the foreign api.
-                * @return {jQuery.Deferred}
-                */
-               getCentralAuthToken: function () {
-                       var data = {
-                               action: 'centralauthtoken'
-                       };
-                       // central auth token must be requested from the Api 
(not ForeignApi)
-                       return api.get( data ).then( function ( resp ) {
-                               if ( resp.error ) {
-                                       return false;
-                               } else {
-                                       return 
resp.centralauthtoken.centralauthtoken;
-                               }
-                       } );
-               },
-               /**
-                * Get a token from a foreign API
-                * @param {String} type of token you want to retrieve
-                * @param {String} centralAuthToken to help get it
-                * @return {jQuery.Deferred}
-                */
-               getToken: function ( type, centralAuthToken ) {
-                       var data = {
-                               action: 'query',
-                               meta: 'tokens',
-                               origin: this.getOrigin(),
-                               centralauthtoken: centralAuthToken,
-                               type: type
-                       };
-                       return this.ajax( data ).then( function ( resp ) {
-                               return resp.query.tokens[type + 'token'];
-                       } );
-               },
-               /**
-                * Post to API with support for central auth tokens
-                * If the user is anonymous, then post using the csrftoken 
received from the remote wiki.
-                * @param {String} tokenType Ignored. `'csrf'` is always used
-                * @param {Object} data Data to be preprocessed and added to 
options
-                * @param {Object} options Parameters passed to $.ajax()
-                * @return {jQuery.Deferred}
-                */
-               postWithToken: function ( tokenType, data, options ) {
-                       var self = this,
-                               d = $.Deferred();
-
-                       options = options || {};
-                       options.xhrFields = {
-                               withCredentials: true
-                       };
-                       // In case it is a file upload we need to append origin 
to query string.
-                       options.url = self.apiUrl + '?origin=' + 
self.getOrigin();
-
-                       data.origin = self.getOrigin();
-
-                       // first let's sort out the token
-                       self.getCentralAuthToken().done( function ( 
centralAuthTokenOne ) {
-                               self.getToken( tokenType, centralAuthTokenOne 
).done( function ( token ) {
-                                       self.getCentralAuthToken().done( 
function ( centralAuthTokenTwo ) {
-                                               data.centralauthtoken = 
centralAuthTokenTwo;
-                                               data.token = token;
-                                               Api.prototype.post.call( self, 
data, options ).done( function ( resp ) {
-                                                       d.resolve( resp );
-                                               } ).fail( $.proxy( d, 'reject' 
) );
-                                       } ).fail( $.proxy( d, 'reject' ) );
-                               } ).fail( $.proxy( d, 'reject' ) );
-                       } ).fail( function ( code ) {
-                               if ( code !== 'notloggedin' ) {
-                                       d.reject();
-                                       return;
-                               }
-                               // So the user is not logged in locally.
-                               // Get the remote CSRF token
-                               Api.prototype.ajax.call(
-                                       self, {
-                                               action: 'query',
-                                               meta: 'tokens',
-                                               type: 'csrf'
-                                       }, {
-                                               url: options.url
-                                       }
-                               ).done( function ( resp ) {
-                                       if ( resp.query && resp.query.tokens && 
resp.query.tokens.csrftoken ) {
-                                               data.token = 
resp.query.tokens.csrftoken;
-                                               Api.prototype.post.call( self, 
data, options ).done( function ( resp ) {
-                                                       d.resolve( resp );
-                                               } ).fail( $.proxy( d, 'reject' 
) );
-                                       } else {
-                                               d.reject();
-                                       }
-                               } ).fail( $.proxy( d, 'reject' ) );
-                       } );
-                       return d;
-               },
+       ForeignApi = Api.extend( mw.ForeignApi.prototype ).extend( {
                /** @inheritdoc */
+               initialize: function ( options ) {
+                       options = options || {};
+                       options.ajax = options.ajax || {};
+                       options.ajax.dataType = 'jsonp';
+                       mw.ForeignApi.call( this, this.apiUrl, options );
+                       Api.prototype.initialize.call( this, options );
+               },
                ajax: function ( data, options ) {
                        options = options || {};
-                       if ( !options.url ) {
-                               options.url = this.apiUrl;
-                       }
-                       // Tokens need to be requested without jsonp
-                       if ( options.type !== 'POST' && data.action !== 
'tokens' && data.meta !== 'tokens' ) {
-                               options.dataType = 'jsonp';
-                       }
-                       return Api.prototype.ajax.call( this, data, options );
-               },
-               /** @inheritdoc */
-               initialize: function () {
-                       Api.prototype.initialize.apply( this, arguments );
+                       return mw.ForeignApi.prototype.ajax.call( this, data, 
options );
                }
        } );
 
-       M.define( 'modules/ForeignApi', ForeignApi );
+       M.define( 'mobile.foreignApi/ForeignApi', ForeignApi ).deprecate( 
'modules/ForeignApi' );
 
-}( mw.mobileFrontend, jQuery ) );
+}( mw.mobileFrontend ) );
diff --git a/resources/mobile.startup/api.js b/resources/mobile.startup/api.js
index 2b96b0f..87c85b1 100644
--- a/resources/mobile.startup/api.js
+++ b/resources/mobile.startup/api.js
@@ -1,99 +1,39 @@
 ( function ( M, $ ) {
-
-       var Api, api,
+       var api,
+               Api = mw.Api,
                EventEmitter = M.require( 'eventemitter' );
 
-       /**
-        * JavaScript wrapper for a horrible API. Use to retrieve things.
-        * @class Api
-        * @extends EventEmitter
-        */
        Api = EventEmitter.extend( mw.Api.prototype ).extend( {
                /**
                 * @property {String} apiUrl
                 * URL to the api endpoint (api.php)
                 */
-               apiUrl: mw.util.wikiScript( 'api' ),
-
+               apiUrl: undefined,
                /**
                 * @inheritdoc
                 */
-               initialize: function () {
-                       mw.Api.apply( this, arguments );
-                       EventEmitter.prototype.initialize.apply( this, 
arguments );
+               initialize: function ( options ) {
                        this.requests = [];
-                       this.tokenCache = {};
+                       if ( this.apiUrl ) {
+                               options = options || {};
+                               options.ajax = options.ajax || {};
+                               options.ajax.url = this.apiUrl;
+                       }
+                       mw.Api.call( this, options );
+                       EventEmitter.prototype.initialize.apply( this, 
arguments );
                },
-
                /**
-                * A wrapper for $.ajax() to be used when calling server APIs.
-                * Sets URL to API URL and default data type to JSON.
-                * Preprocesses data argument in the following way:
-                * - removes boolean values equal to false
-                * - concatenates Array values with '|'
-                *
-                *     @example
-                *     <code>
-                *     ajax( { a: false, b: [1, 2, 3] }, { type: 'post' } );
-                *     // is equal to
-                *     $.ajax( {
-                *         type: 'post',
-                *         data: { b: '1|2|3' }
-                *     } );
-                *     </code>
-                *
+                * @inheritdoc
                 * @method
                 * @param {Object} data Data to be preprocessed and added to 
options
                 * @param {Object} options Parameters passed to $.ajax()
                 * @return {jQuery.Deferred} Object returned by $.ajax()
                 */
                ajax: function ( data, options ) {
-                       var key, request, self = this;
-
-                       options = options || {};
-
-                       if ( typeof data !== 'string' ) {
-                               for ( key in data ) {
-                                       if ( data.hasOwnProperty( key ) ) {
-                                               if ( data[key] === false ) {
-                                                       delete data[key];
-                                               } else if ( $.isArray( 
data[key] ) ) {
-                                                       data[key] = 
data[key].join( '|' );
-                                               }
-                                       }
-                               }
-                       }
-
-                       /**
-                        * This setups support for upload progress events.
-                        * See 
https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#make-upload-progress-notifications
-                        * FIXME: move to mw.Api (although no EventEmitter in 
core)?
-                        * @ignore
-                        * @returns {jqXHR}
-                        */
-                       options.xhr = function () {
-                               var xhr = $.ajaxSettings.xhr();
-                               if ( xhr.upload ) {
-                                       // need to bind this event before we 
open the connection (see note at
-                                       // 
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress)
-                                       xhr.upload.addEventListener( 
'progress', function ( ev ) {
-                                               if ( ev.lengthComputable ) {
-                                                       /**
-                                                        * @event progress
-                                                        * Fired when a pending 
XHR request fires a progress event.
-                                                        */
-                                                       self.emit( 'progress', 
request, ev.loaded / ev.total );
-                                               }
-                                       } );
-                               }
-                               return xhr;
-                       };
-
-                       request = mw.Api.prototype.ajax.call( this, data, 
options );
+                       var request = mw.Api.prototype.ajax.call( this, data, 
options );
                        this.requests.push( request );
                        return request;
                },
-
                /**
                 * Abort all unfinished requests issued by this Api object.
                 * FIXME: move to mw.Api
@@ -104,25 +44,10 @@
                                request.abort();
                        } );
                },
-
-               /**
-                * Returns the current URL including protocol
-                *
-                * @method
-                * @return {String}
-                */
-               getOrigin: function () {
-                       var origin = window.location.protocol + '//' + 
window.location.hostname;
-                       if ( window.location.port ) {
-                               origin += ':' + window.location.port;
-                       }
-                       return origin;
-               }
        } );
-
        api = new Api();
        api.Api = Api;
-
        M.define( 'api', api );
+       M.define( 'mobile.startup/Api', Api );
 
 }( mw.mobileFrontend, jQuery ) );
diff --git a/resources/mobile.watchlist/WatchListApi.js 
b/resources/mobile.watchlist/WatchListApi.js
index 2316c26..ddc39d8 100644
--- a/resources/mobile.watchlist/WatchListApi.js
+++ b/resources/mobile.watchlist/WatchListApi.js
@@ -14,9 +14,11 @@
         * @extends Api
         */
        WatchListApi = Api.extend( {
-               /** @inheritdoc */
+               /** @inheritdoc
+                * FIXME: parameter - Api.initialize gets passed options not a 
string.
+                */
                initialize: function ( lastTitle ) {
-                       Api.prototype.initialize.apply( this, arguments );
+                       Api.prototype.initialize.call( this, {} );
                        // Try to keep it in sync with 
SpecialMobileWatchlist::LIMIT (php)
                        this.limit = 50;
 
diff --git a/tests/qunit/mobile.foreignApi/test_ForeignApi.js 
b/tests/qunit/mobile.foreignApi/test_ForeignApi.js
deleted file mode 100644
index 65904a9..0000000
--- a/tests/qunit/mobile.foreignApi/test_ForeignApi.js
+++ /dev/null
@@ -1,41 +0,0 @@
-( function ( M, $ ) {
-       var ForeignApi = M.require( 'modules/ForeignApi' ),
-               api = M.require( 'api' );
-
-       QUnit.module( 'MobileFrontend ForeignApi' );
-
-       // Test whether postWithToken() works when the user is logged out
-       QUnit.test( '#postWithToken - anon', 1, function ( assert ) {
-               var self = this,
-                       foreignApi = new ForeignApi(),
-                       editToken = mw.user.tokens.get( 'editToken' ),
-                       spy = this.sandbox.spy( api.Api.prototype, 'post' );
-
-               // Make sure the central auth token cannot be received
-               this.stub( foreignApi, 'getCentralAuthToken' ).returns(
-                       $.Deferred().rejectWith( self, [ 'notloggedin' ] )
-               );
-
-               // And ajax must return the csrftoken
-               this.stub( api.Api.prototype, 'ajax' ).returns(
-                       $.Deferred().resolveWith( self, [ {
-                               query: {
-                                       tokens: {
-                                               csrftoken: editToken
-                                       }
-                               }
-                       } ] )
-               );
-
-               // Now, let's post some data
-               foreignApi.postWithToken( 'csrf', { some: 'data' }, {} );
-
-               // POST must be called with the editToken, and not with the 
centralAuthToken
-               assert.ok( spy.calledWith( {
-                       origin: foreignApi.getOrigin(),
-                       some: 'data',
-                       token: editToken
-               } ), 'Posting to ForeignApi with token when the user is logged 
out works!' );
-       } );
-
-}( mw.mobileFrontend, jQuery ) );
diff --git a/tests/qunit/mobile.startup/test_api.js 
b/tests/qunit/mobile.startup/test_api.js
index ab71e36..879a6bc 100644
--- a/tests/qunit/mobile.startup/test_api.js
+++ b/tests/qunit/mobile.startup/test_api.js
@@ -50,23 +50,6 @@
                }
        } );
 
-       QUnit.test( '#ajax', 1, function ( assert ) {
-               this.api.ajax( {
-                       falseBool: false,
-                       trueBool: true,
-                       list: [ 'one', 2, 'three' ],
-                       normal: 'test'
-               } );
-               assert.ok(
-                       mw.Api.prototype.ajax.calledWithMatch( {
-                               trueBool: true,
-                               list: 'one|2|three',
-                               normal: 'test'
-                       } ),
-                       'set defaults and transform boolean and array data'
-               );
-       } );
-
        QUnit.test( '#abort', 2, function ( assert ) {
                this.api.get( {
                        a: 1

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Iadd08d44519f76a4f6d45921a6c15a3ac8732b93
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/MobileFrontend
Gerrit-Branch: master
Gerrit-Owner: Jdlrobson <[email protected]>

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

Reply via email to