Page MenuHomeWickedGov Phorge

ext.centralNotice.geoIP.js
No OneTemporary

Size
4 KB
Referenced Files
None
Subscribers
None

ext.centralNotice.geoIP.js

/**
* Processes location data and sets up a promise that resolves with that data.
* Sets the global window.Geo and provides the public mw.geoIP object.
* TODO Deprecate global window.Geo
* TODO Move this out of CentralNotice. See https://phabricator.wikimedia.org/T102848
*/
( function () {
var COOKIE_NAME = 'GeoIP',
geoPromise;
/**
* Parse geo data in cookieValue and return an object with properties from
* the fields therein. Returns null if the value couldn't be parsed or
* doesn't contain location data.
*
* The cookie will look like one of the following:
* - "US:CO:Denver:39.6762:-104.887:v4"
* - ":::::v4"
*
* @param {string} cookieValue
* @return {?Object}
*/
function parseCookieValue( cookieValue ) {
// TODO Verify that these Regexes are optimal. (Why no anchors? Why the
// semicolon in the last group?)
var matches =
// Parse cookie format currently set by WMF servers
cookieValue.match( /([^:]*):([^:]*):([^:]*):([^:]*):([^:]*):([^;]*)/ ) ||
// If that didn't match, try the old cookie format (no region data).
// Even though these are session cookies, some might still be around.
cookieValue.match( /([^:]*):([^:]*):([^:]*):([^:]*):([^;]*)/ );
// No matches...? Boo, no data from geo cookie.
if ( !matches ) {
return null;
}
// If the matches were from the old cookie format, add an empty region
// element.
if ( matches.length === 6 ) {
matches = matches.slice( 0, 2 ).concat( [ '' ] )
.concat( matches.slice( 2 ) );
}
// There was no info found if there's no country field, or if it's
// empty
if ( ( typeof matches[ 1 ] !== 'string' ) || ( matches[ 1 ].length === 0 ) ) {
return null;
}
// Return a juicy Geo object
return {
country: matches[ 1 ],
region: matches[ 2 ],
city: matches[ 3 ],
lat: matches[ 4 ] && parseFloat( matches[ 4 ] ),
lon: matches[ 5 ] && parseFloat( matches[ 5 ] ),
af: matches[ 6 ]
};
}
/**
* Serialize a geo object and store it in the cookie
*
* @param {Object} geo
*/
function storeGeoInCookie( geo ) {
var parts = [
geo.country,
geo.region || '',
( geo.city && geo.city.replace( /[^a-z]/i, '_' ) ) || '',
geo.lat || '',
geo.lon || '',
geo.af || ''
],
cookieValue = parts.join( ':' );
$.cookie( COOKIE_NAME, cookieValue, { path: '/' } );
}
/**
* Public geoIP object
*/
mw.geoIP = {
/**
* Don't call this function! It is only exposed for tests.
*
* Set a promise that resolves with geo. First try to get data from the
* GeoIP cookie. If that fails, and if a background lookup callback
* module is configured, try the background lookup.
*
* @private
*/
makeGeoWithPromise: function () {
var cookieValue = $.cookie( COOKIE_NAME ),
geo, lookupModule;
// Were we able to read the cookie?
if ( cookieValue ) {
geo = parseCookieValue( cookieValue );
// All good? Resolve with geo and get outta here.
if ( geo ) {
geoPromise = $.Deferred().resolve( geo ).promise();
return;
}
}
// Handle no geo data from the cookie.
// If there's a background lookup to fall back to, do that
lookupModule =
mw.config.get( 'wgCentralNoticeGeoIPBackgroundLookupModule' );
if ( lookupModule ) {
geoPromise = mw.loader.using( lookupModule )
.then( function () {
var lookupCallback = require( lookupModule );
// Chaining lookup: here we return the promise provided by
// lookupCallback(). The result of that promise (geo object)
// will be what then() resolves to, and what future then()
// handlers get.
return lookupCallback();
} );
// If the lookup was successful, store geo in a cookie
geoPromise.then( function ( g ) {
storeGeoInCookie( g );
} );
// If no background lookup is available, we don't have geo data
} else {
geoPromise = $.Deferred().reject().promise();
}
},
/**
* Returns a promise that resolves with geo when it's available. While
* it's usually available right away, it may not be if a background
* call is performed.
*
* @return {jQuery.Promise}
*/
getPromise: function () {
return geoPromise;
}
};
mw.geoIP.makeGeoWithPromise();
// For legacy code, set global window.Geo TODO: deprecate
geoPromise.done( function ( geo ) {
window.Geo = geo;
} );
}() );

File Metadata

Mime Type
text/plain
Expires
Fri, Jul 3, 21:27 (21 h, 4 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
5c/af/fc7f8f67d19d497b964a854a2194
Default Alt Text
ext.centralNotice.geoIP.js (4 KB)

Event Timeline