AndyRussG has uploaded a new change for review. https://gerrit.wikimedia.org/r/243180
Change subject: WIP BannerHistoryLog: timeout for users without sendBeacon ...................................................................... WIP BannerHistoryLog: timeout for users without sendBeacon Change-Id: I95175dbe538668528c28ede08e87df99014519b8 --- M CentralNotice.modules.php M CentralNotice.php M i18n/en.json M i18n/qqq.json M resources/subscribing/ext.centralNotice.bannerHistoryLogger.js 5 files changed, 86 insertions(+), 27 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/CentralNotice refs/changes/80/243180/1 diff --git a/CentralNotice.modules.php b/CentralNotice.modules.php index 4e37b1e..db43f0c 100644 --- a/CentralNotice.modules.php +++ b/CentralNotice.modules.php @@ -145,6 +145,8 @@ 'centralnotice-banner-history-logger-max-entry-age-help', 'centralnotice-banner-history-logger-max-entries', 'centralnotice-banner-history-logger-max-entries-help', + 'centralnotice-banner-history-logger-wait-log-no-send-beacon', + 'centralnotice-banner-history-logger-wait-log-no-send-beacon-help', // Legacy campaigns 'centralnotice-set-record-impression-sample-rate', diff --git a/CentralNotice.php b/CentralNotice.php index ddc4371..faff5d7 100644 --- a/CentralNotice.php +++ b/CentralNotice.php @@ -268,6 +268,11 @@ 'type' => 'integer', 'labelMsg' => 'centralnotice-banner-history-logger-max-entries', 'helpMsg' => 'centralnotice-banner-history-logger-max-entries-help' + ), + 'waitLogNoSendBeacon' => array( + 'type' => 'integer', + 'labelMsg' => 'centralnotice-banner-history-logger-wait-log-no-send-beacon', + 'helpMsg' => 'centralnotice-banner-history-logger-wait-log-no-send-beacon-help' ) ) ), diff --git a/i18n/en.json b/i18n/en.json index 9441d1f..e4893e9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -267,6 +267,8 @@ "centralnotice-banner-history-logger-max-entry-age-help": "Log entries older than this will be expired and will not be sent back to the server.", "centralnotice-banner-history-logger-max-entries": "Maximum number of entries to keep in log", "centralnotice-banner-history-logger-max-entries-help": "If more history is recorded before the log is sent to the server, the oldest items will disappear.", + "centralnotice-banner-history-logger-wait-log-no-send-beacon": "Timeout for sending the log without sendBeacon (in milliseconds)", + "centralnotice-banner-history-logger-wait-log-no-send-beacon-help": "If the log is sometimes sent right before navigating to a different page, some browsers require a maximum time to wait before giving up on sending the log.", "centralnotice-legacy-support": "Legacy support", "centralnotice-legacy-support-help": "Settings for compatibility with older banners that rely on Special:RecordImpression or include JavaScript that hides the banner.", "centralnotice-set-record-impression-sample-rate": "Set sample rate for Special:RecordImpression", diff --git a/i18n/qqq.json b/i18n/qqq.json index 0ffbc04..91acd42 100644 --- a/i18n/qqq.json +++ b/i18n/qqq.json @@ -290,6 +290,8 @@ "centralnotice-banner-history-logger-max-entry-age-help": "Help text for the log expiration age field", "centralnotice-banner-history-logger-max-entries": "Label for the banner history logger campaign mixin maximum number of log entries control in the administration UI", "centralnotice-banner-history-logger-max-entries-help": "Help text for the maximum log size field", + "centralnotice-banner-history-logger-wait-log-no-send-beacon": "Label for field for time limit to delay sending the log without sendBeacon, for the banner history logger campaign mixin", + "centralnotice-banner-history-logger-wait-log-no-send-beacon-help": "Help text for field for time limit to delay sending the log without sendBeacon, for the banner history logger campaign mixin", "centralnotice-legacy-support": "Name of the legacy support campaign mixin, for administration UI control", "centralnotice-legacy-support-help": "Description of the legacy support feature", "centralnotice-set-record-impression-sample-rate": "Label for the control to activate setting the sample rate for Special:RecordImpression, for the legacy support campaign mixin", diff --git a/resources/subscribing/ext.centralNotice.bannerHistoryLogger.js b/resources/subscribing/ext.centralNotice.bannerHistoryLogger.js index 6f9160c..aa0457d 100644 --- a/resources/subscribing/ext.centralNotice.bannerHistoryLogger.js +++ b/resources/subscribing/ext.centralNotice.bannerHistoryLogger.js @@ -10,6 +10,7 @@ var cn = mw.centralNotice, // Guaranteed to exist; we depend on display RL module bhLogger, mixin = new cn.Mixin( 'bannerHistoryLogger' ), + waitLogNoSendBeacon, now = Math.round( ( new Date() ).getTime() / 1000 ), log, readyToLogDeferredObj = $.Deferred(), @@ -190,6 +191,52 @@ } /** + * Send the log. If sendBeacon is available, send normally via EventLogging. + * If not, use an $.ajax with a timeout as per waitLogNoSendBeacon. + * + * Returns a promise that resolves as soon as the log is sent for users + * with sendBeacon. For users without sendBeacon, if the log is sent before + * the timeout, the promise resolves, otherwise it rejects. + * + * Note: Do Not Track is already handled at this module's entry points, as + * well as by EventLogging. + * + * @param elData Event log data + * @returns {jQuery.Promise} + */ + function sendLog( elData ) { + var deferred = $.Deferred(), + elPromise; + + // If the browser has sendBeacon, resolve when EventLogging does + if ( navigator.sendBeacon ) { + elPromise = mw.eventLog.logEvent( EVENT_LOGGING_SCHEMA, elData ); + + } else { + + // No sendBeacon? Do an ajax call and set a time limit to wait + // for it to return. + setTimeout( function () { + deferred.reject(); + }, waitLogNoSendBeacon ); + + elPromise = $.ajax( { + url: makeEventLoggingURL, + timeout: waitLogNoSendBeacon, + method: 'POST' + } ); + } + + elPromise.done( function () { + deferred.resolve(); + } ).fail( function() { + deferred.reject(); + } ); + + return deferred.promise(); + } + + /** * Check the EventLogging URL we'd get from this data isn't too big. Here * we copy some of the same processes done by ext.eventLogging. * @@ -198,23 +245,24 @@ * @returns {boolean} true if the EL payload size is OK */ function checkEventLoggingURLSize( elData ) { + return ( makeEventLoggingURL( elData ).length <= mw.eventLog.maxUrlSize ); + } - var fullElData = { - event : elData, - revision : 13172419, // Coordinate with CentralNotice.hooks.php - schema : EVENT_LOGGING_SCHEMA, - webHost : location.hostname, - wiki : mw.config.get( 'wgDBname' ) - }, - - url = mw.eventLog.makeBeaconUrl( fullElData ); - - return ( url.length <= mw.eventLog.maxUrlSize ); + function makeEventLoggingURL( elData ) { + return mw.eventLog.makeBeaconUrl( { + event : elData, + revision : 13447710, // Coordinate with CentralNotice.hooks.php + schema : EVENT_LOGGING_SCHEMA, + webHost : location.hostname, + wiki : mw.config.get( 'wgDBname' ) + } ); } // Set a function to run after a campaign is chosen and after a banner for // that campaign is chosen or not mixin.setPostBannerHandler( function( mixinParams ) { + + waitLogNoSendBeacon = mixinParams.waitLogNoSendBeacon; // Bow out if DNT if ( doNotTrackEnabled() ) { @@ -266,20 +314,18 @@ // Send a sample to the server if ( Math.random() < rate ) { - mw.eventLog.logEvent( - EVENT_LOGGING_SCHEMA, - makeEventLoggingData( rate ) - ); + sendLog( makeEventLoggingData( rate ) ).always( function () { - inSample = true; - logSent = true; + inSample = true; + logSent = true; + + // By resolving only after sampling and possibly + // sending the log, we ensure that a sampled log + // would be sent first. That simplifies the logic + // for whether to send in other circumstances. + readyToLogDeferredObj.resolve(); + } ); } - - // By resolving only after sampling and possibly sending the - // log, we ensure that a sampled log would be sent first. That - // simplifies the logic for whether to send in other - // circumstances. - readyToLogDeferredObj.resolve(); } ); } ); } ); @@ -319,17 +365,19 @@ // It's likely that this will be resolved by the time we get here readyToLogDeferredObj.done( function() { + // This is included in the done() function to ensure a sampled + // log would be sent first (see above). if ( logSent ) { deferred.resolve(); return; } - mw.eventLog.logEvent( - EVENT_LOGGING_SCHEMA, - makeEventLoggingData() - ).always( function() { + sendLog( makeEventLoggingData() ).done( function() { deferred.resolve(); + } ).fail( function () { + deferred.reject(); } ); + } ); return deferred.promise(); -- To view, visit https://gerrit.wikimedia.org/r/243180 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I95175dbe538668528c28ede08e87df99014519b8 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/CentralNotice Gerrit-Branch: master Gerrit-Owner: AndyRussG <andrew.green...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits