From 7ccbb22f3c28b38ed6879d0c768b0424a2253276 Mon Sep 17 00:00:00 2001
From: Helmut Hummel <helmut.hummel@typo3.org>
Date: Fri, 21 Mar 2014 13:27:08 +0100
Subject: [PATCH] [TASK] Cleanup Ajax URL inline settings

This change streamlines the use of Ajax URLs
by auto-publishing all Ajax URLs to JavaScript
inline settings.

All Ajax URLs can now also be looked up in
JavaScript by providing the AjaxID like that:

var ajaxUrl = TYPO3.settings.ajaxUrls['TxMyExt::process'];

All code has been adapted to reflect this change.

Resolves: #57096
Documentation: #56347
Releases: 6.2
Change-Id: I4a441f51dcb3551874082077c52918b3fc6a9b0f
Reviewed-on: https://review.typo3.org/28602
Reviewed-by: Markus Klein
Tested-by: Markus Klein
Reviewed-by: Stefan Neufeind
Tested-by: Stefan Neufeind
---
 NEWS.md                                       | 11 ++---
 typo3/js/tree.js                              |  8 +---
 .../Classes/Controller/BackendController.php  |  8 ----
 .../Classes/Form/Element/InlineElement.php    |  2 -
 .../backend/Classes/Form/FormEngine.php       |  6 ---
 .../Classes/Template/DocumentTemplate.php     |  2 -
 .../Classes/Toolbar/ShortcutToolbarItem.php   |  5 ---
 .../Classes/Utility/BackendUtility.php        |  5 +++
 .../Public/JavaScript/DragUploader.js         |  4 +-
 .../Public/JavaScript/jsfunc.inline.js        |  2 +-
 .../JavaScript/jsfunc.tceforms_suggest.js     |  2 +-
 .../Public/JavaScript/loginrefresh.js         | 12 +++---
 .../Resources/Public/JavaScript/modulemenu.js |  4 +-
 .../Public/JavaScript/shortcutmenu.js         | 10 ++---
 .../sysext/core/Classes/Page/PageRenderer.php | 15 +++++++
 .../Classes/Controller/FileListController.php |  2 -
 .../Classes/Hook/BackendControllerHook.php    | 42 +++++++++++++++++++
 typo3/sysext/impexp/ext_localconf.php         |  6 +++
 .../Classes/Browser/ElementBrowser.php        |  2 -
 .../Classes/Hook/BackendHookForAjaxLogin.php  |  1 -
 20 files changed, 93 insertions(+), 56 deletions(-)
 create mode 100644 typo3/sysext/impexp/Classes/Hook/BackendControllerHook.php
 create mode 100644 typo3/sysext/impexp/ext_localconf.php

diff --git a/NEWS.md b/NEWS.md
index 62539ac732e6..c3e03d2d1302 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -58,12 +58,13 @@ custom label for each category field.
 * Ajax API addition
 
 New API has been added to register an Ajax handler for the backend.
-\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerAjaxHandler('TxMyExt::process', '\Vendor\Ext\AjaxHandler->process');
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::registerAjaxHandler('TxMyExt::process', 'Vendor\\Ext\\AjaxHandler->process');
 
-Along with that, new API has been added to get the Ajax URL for a given AjaxId.
-This URL will contain a CSRF protection token that will be checked
-in the ajax.php dispatcher:
-$ajaxUrl = \TYPO3\CMS\Core\Utility\BackendUtility::getAjaxUrl('TxMyExt::process');
+Along with that, URLs to all registered handlers will be
+published to JavaScript inline settings and can be looked up
+by providing the Ajax ID:
+
+var ajaxUrl = TYPO3.settings.ajaxUrls['TxMyExt::process'];
 
 Registering an Ajax script the "old" way by just adding it to TYPO3_CONF_VARS has been deprecated,
 but no deprecation log is been written and the handler still work in a backwards compatible way.
diff --git a/typo3/js/tree.js b/typo3/js/tree.js
index 1c9d2b5461f1..b6e481e5cdd5 100644
--- a/typo3/js/tree.js
+++ b/typo3/js/tree.js
@@ -117,10 +117,6 @@ var DragDrop = {
 
 var Tree = {
 	ajaxID: 'SC_alt_db_navframe::expandCollapse',	// has to be either "SC_alt_db_navframe::expandCollapse" or "SC_alt_file_navframe::expandCollapse"
-	ajaxUrls: {
-		'SC_alt_file_navframe::expandCollapse': TYPO3.settings.Tree['SC_alt_file_navframe'].ajaxUrl,
-		'SC_alt_db_navframe::expandCollapse': TYPO3.settings.Tree['SC_alt_db_navframe'].ajaxUrl
-	},
 	frameSetModule: null,
 	activateDragDrop: true,
 	highlightClass: 'active',
@@ -136,7 +132,7 @@ var Tree = {
 
 			// fallback if AJAX is not possible (e.g. IE < 6)
 		if (typeof Ajax.getTransport() !== 'object') {
-			window.location.href = this.ajaxUrls[this.ajaxID] + '&PM=' + encodeURIComponent(params) + scope;
+			window.location.href = TYPO3.settings.ajaxUrls[this.ajaxID] + '&PM=' + encodeURIComponent(params) + scope;
 			return;
 		}
 
@@ -156,7 +152,7 @@ var Tree = {
 		} else {
 			obj.style.cursor = 'wait';
 		}
-		var call = new Ajax.Request(this.ajaxUrls[this.ajaxID], {
+		var call = new Ajax.Request(TYPO3.settings.ajaxUrls[this.ajaxID], {
 			method: 'get',
 			parameters: 'PM=' + encodeURIComponent(params) + scope,
 			onComplete: function(xhr) {
diff --git a/typo3/sysext/backend/Classes/Controller/BackendController.php b/typo3/sysext/backend/Classes/Controller/BackendController.php
index e97be59ebc90..bcdc34c28a5e 100644
--- a/typo3/sysext/backend/Classes/Controller/BackendController.php
+++ b/typo3/sysext/backend/Classes/Controller/BackendController.php
@@ -103,14 +103,6 @@ class BackendController {
 		$this->pageRenderer->enableExtJSQuickTips();
 		$this->pageRenderer->addJsInlineCode('consoleOverrideWithDebugPanel', '//already done', FALSE);
 		$this->pageRenderer->addExtDirectCode();
-		$this->pageRenderer->addInlineSetting('ModuleMenu.getData', 'ajaxUrl', BackendUtility::getAjaxUrl('ModuleMenu::getData'));
-		$this->pageRenderer->addInlineSetting('ModuleMenu.saveMenuState', 'ajaxUrl', BackendUtility::getAjaxUrl('ModuleMenu::saveMenuState'));
-		$this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::login', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::login'));
-		$this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::logout', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::logout'));
-		$this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::refreshLogin', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::refreshLogin'));
-		$this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::isTimedOut', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::isTimedOut'));
-		$this->pageRenderer->addInlineSetting('BackendLogin.BackendLogin::getChallenge', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::getChallenge'));
-		$this->pageRenderer->addInlineSetting('ImportExport', 'moduleUrl', BackendUtility::getModuleUrl('xMOD_tximpexp'));
 		// Add default BE javascript
 		$this->js = '';
 		$this->jsFiles = array(
diff --git a/typo3/sysext/backend/Classes/Form/Element/InlineElement.php b/typo3/sysext/backend/Classes/Form/Element/InlineElement.php
index 20b399f94871..eb9a981123fe 100644
--- a/typo3/sysext/backend/Classes/Form/Element/InlineElement.php
+++ b/typo3/sysext/backend/Classes/Form/Element/InlineElement.php
@@ -942,8 +942,6 @@ class InlineElement {
 		$pageRenderer = $GLOBALS['SOBE']->doc->getPageRenderer();
 		$pageRenderer->loadRequireJsModule('TYPO3/CMS/Filelist/FileListLocalisation');
 		$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader');
-		$pageRenderer->addInlineSetting('DragUploader', 'ajaxUrl', BackendUtility::getAjaxUrl('TYPO3_tcefile::process'));
-		$pageRenderer->addInlineSetting('DragUploader', 'ajaxFlashMessagesUrl', BackendUtility::getAjaxUrl('DocumentTemplate::getFlashMessages'));
 		$pageRenderer->addInlineLanguagelabelFile(
 			\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('lang') . 'locallang_core.xlf',
 			'file_upload'
diff --git a/typo3/sysext/backend/Classes/Form/FormEngine.php b/typo3/sysext/backend/Classes/Form/FormEngine.php
index 8c2dc8c16742..b45e0fd8c20d 100644
--- a/typo3/sysext/backend/Classes/Form/FormEngine.php
+++ b/typo3/sysext/backend/Classes/Form/FormEngine.php
@@ -5642,10 +5642,6 @@ TBE_EDITOR.customEvalFunctions[\'' . $evalData . '\'] = function(value) {
 				// We want to load jQuery-ui inside our js. Enable this using requirejs.
 				$pageRenderer->loadRequireJs();
 				$this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js');
-				$pageRenderer->addInlineSetting('TCEFORMS.Inline.setExpandedCollapsedState', 'ajaxUrl', BackendUtility::getAjaxUrl('t3lib_TCEforms_inline::setExpandedCollapsedState'));
-				$pageRenderer->addInlineSetting('TCEFORMS.Inline.synchronizeLocalizeRecords', 'ajaxUrl', BackendUtility::getAjaxUrl('t3lib_TCEforms_inline::synchronizeLocalizeRecords'));
-				$pageRenderer->addInlineSetting('TCEFORMS.Inline.getRecordDetails', 'ajaxUrl', BackendUtility::getAjaxUrl('t3lib_TCEforms_inline::getRecordDetails'));
-				$pageRenderer->addInlineSetting('TCEFORMS.Inline.createNewRecord', 'ajaxUrl', BackendUtility::getAjaxUrl('t3lib_TCEforms_inline::createNewRecord'));
 				$out .= '
 				inline.setPrependFormFieldNames("' . $this->inline->prependNaming . '");
 				inline.setNoTitleString("' . addslashes(BackendUtility::getNoRecordTitle(TRUE)) . '");
@@ -5653,13 +5649,11 @@ TBE_EDITOR.customEvalFunctions[\'' . $evalData . '\'] = function(value) {
 				// Always include JS functions for Suggest fields as we don't know what will come
 				$this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js');
 				$this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_selectboxfilter.js');
-				$pageRenderer->addInlineSetting('TCEFORMS.Suggest', 'ajaxUrl', BackendUtility::getAjaxUrl('t3lib_TCEforms_suggest::searchRecord'));
 			} else {
 				// If Suggest fields were processed, add the JS functions
 				if ($this->suggest->suggestCount > 0) {
 					$pageRenderer->loadScriptaculous();
 					$this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js');
-					$pageRenderer->addInlineSetting('TCEFORMS.Suggest', 'ajaxUrl', BackendUtility::getAjaxUrl('t3lib_TCEforms_suggest::searchRecord'));
 				}
 				if ($this->multiSelectFilterCount > 0) {
 					$pageRenderer->loadScriptaculous();
diff --git a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php
index e85756ef351c..c5f75f798d52 100644
--- a/typo3/sysext/backend/Classes/Template/DocumentTemplate.php
+++ b/typo3/sysext/backend/Classes/Template/DocumentTemplate.php
@@ -1586,8 +1586,6 @@ function jumpToUrl(URL) {
 		$this->pageRenderer->loadPrototype();
 		$this->loadJavascriptLib('sysext/backend/Resources/Public/JavaScript/common.js');
 		$this->loadJavascriptLib('js/tree.js');
-		$this->getPageRenderer()->addInlineSetting('Tree.SC_alt_db_navframe', 'ajaxUrl', BackendUtility::getAjaxUrl('SC_alt_db_navframe::expandCollapse'));
-		$this->getPageRenderer()->addInlineSetting('Tree.SC_alt_file_navframe', 'ajaxUrl', BackendUtility::getAjaxUrl('SC_alt_file_navframe::expandCollapse'));
 		// Setting prefs for drag & drop
 		$this->JScodeArray['dragdrop'] = '
 			DragDrop.changeURL = "' . $this->backPath . 'alt_clickmenu.php";
diff --git a/typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php b/typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php
index 30f626fd8962..9ad02bc3c681 100644
--- a/typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php
+++ b/typo3/sysext/backend/Classes/Toolbar/ShortcutToolbarItem.php
@@ -228,11 +228,6 @@ class ShortcutToolbarItem implements \TYPO3\CMS\Backend\Toolbar\ToolbarItemHookI
 	 */
 	protected function addJavascriptToBackend() {
 		$this->backendReference->addJavascriptFile('sysext/backend/Resources/Public/JavaScript/shortcutmenu.js');
-		$this->backendReference->getPageRenderer()->addInlineSetting('ShortcutMenu.saveShortcut', 'ajaxUrl', BackendUtility::getAjaxUrl('ShortcutMenu::saveShortcut'));
-		$this->backendReference->getPageRenderer()->addInlineSetting('ShortcutMenu.delete', 'ajaxUrl', BackendUtility::getAjaxUrl('ShortcutMenu::delete'));
-		$this->backendReference->getPageRenderer()->addInlineSetting('ShortcutMenu.getGroups', 'ajaxUrl', BackendUtility::getAjaxUrl('ShortcutMenu::getGroups'));
-		$this->backendReference->getPageRenderer()->addInlineSetting('ShortcutMenu.render', 'ajaxUrl', BackendUtility::getAjaxUrl('ShortcutMenu::render'));
-		$this->backendReference->getPageRenderer()->addInlineSetting('ShortcutMenu.create', 'ajaxUrl', BackendUtility::getAjaxUrl('ShortcutMenu::create'));
 	}
 
 	/**
diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
index 67b3ca432c76..b39a3a9b21b1 100644
--- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php
+++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
@@ -2972,11 +2972,16 @@ class BackendUtility {
 	/**
 	 * Returns the Ajax URL for a given AjaxID including a CSRF token.
 	 *
+	 * This method is only called by the core and must not be used by extensions.
+	 * Ajax URLs of all registered backend Ajax handlers are automatically published
+	 * to JavaScript inline settings: TYPO3.settings.ajaxUrls['ajaxId']
+	 *
 	 * @param string $ajaxIdentifier Identifier of the AJAX callback
 	 * @param array $urlParameters URL parameters that should be added as key value pairs
 	 * @param bool/string $backPathOverride Backpath that should be used instead of the global $BACK_PATH
 	 * @param bool $returnAbsoluteUrl If set to TRUE, the URL returned will be absolute, $backPathOverride will be ignored in this case
 	 * @return string Calculated URL
+	 * @internal
 	 */
 	static public function getAjaxUrl($ajaxIdentifier, array $urlParameters = array(), $backPathOverride = FALSE, $returnAbsoluteUrl = FALSE) {
 		if ($backPathOverride) {
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js b/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
index 55343d9e6a89..0adbccce9ba2 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/DragUploader.js
@@ -163,7 +163,7 @@ define('TYPO3/CMS/Backend/DragUploader', ['jquery'], function($) {
 				me.queueLength--;
 				if (me.queueLength == 0) {
 					$.ajax({
-						url: TYPO3.settings.DragUploader.ajaxFlashMessagesUrl,
+						url: TYPO3.settings.ajaxUrls['DocumentTemplate::getFlashMessages'],
 						cache: false,
 						success: function(data) {
 							var messages = $('#typo3-messages');
@@ -349,7 +349,7 @@ define('TYPO3/CMS/Backend/DragUploader', ['jquery'], function($) {
 			formData.append('upload_1', me.file);
 
 			var s = $.extend(true, {}, $.ajaxSettings, {
-				url: TYPO3.settings.DragUploader.ajaxUrl,
+				url: TYPO3.settings.ajaxUrls['TYPO3_tcefile::process'],
 				contentType: false,
 				processData: false,
 				data: formData,
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
index 2d6d34e19cb7..beac3bb7653b 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.inline.js
@@ -191,7 +191,7 @@ var inline = {
 	makeAjaxCall: function(method, params, lock, context) {
 		var max, url='', urlParams='', options={};
 		if (method && params && params.length && this.lockAjaxMethod(method, lock)) {
-			url = TBE_EDITOR.getBackendPath() + TYPO3.settings.TCEFORMS.Inline[method].ajaxUrl;
+			url = TBE_EDITOR.getBackendPath() + TYPO3.settings.ajaxUrls['t3lib_TCEforms_inline::' + method];
 			urlParams = '';
 			for (var i=0, max=params.length; i<max; i++) {
 				urlParams += '&ajax[' + i + ']=' + encodeURIComponent(params[i]);
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js
index 5caefec6216d..b450c75bafee 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/jsfunc.tceforms_suggest.js
@@ -60,7 +60,7 @@ TCEForms.Suggest = Class.create({
 		this.suggestResultList = objectId + 'SuggestChoices';
 		this.fieldType = fieldType;
 
-		new Ajax.Autocompleter(this.suggestField, this.suggestResultList, PATH_typo3 + TYPO3.settings.TCEFORMS.Suggest.ajaxUrl, {
+		new Ajax.Autocompleter(this.suggestField, this.suggestResultList, PATH_typo3 + TYPO3.settings.ajaxUrls['t3lib_TCEforms_suggest::searchRecord'], {
 				paramName: 'value',
 				minChars: (minimumCharacters ? minimumCharacters : this.minimumCharacters),
 				updateElement: this.addElementToList.bind(this),
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/loginrefresh.js b/typo3/sysext/backend/Resources/Public/JavaScript/loginrefresh.js
index f6fd15a5778c..c6144e9e34ef 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/loginrefresh.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/loginrefresh.js
@@ -41,7 +41,7 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, {
 			run: function(){
 				// interval run
 				Ext.Ajax.request({
-					url: TYPO3.settings.BackendLogin['BackendLogin::isTimedOut'].ajaxUrl,
+					url: TYPO3.settings.ajaxUrls['BackendLogin::isTimedOut'],
 					params: {
 						'skipSessionUpdate': 1
 					},
@@ -88,7 +88,7 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, {
 
 	initComponents: function() {
 		var loginPanel = new Ext.FormPanel({
-			url: TYPO3.settings.BackendLogin['BackendLogin::login'].ajaxUrl,
+			url: TYPO3.settings.ajaxUrls['BackendLogin::login'],
 			id: 'loginform',
 			title: TYPO3.LLL.core.refresh_login_title,
 			defaultType: 'textfield',
@@ -187,7 +187,7 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, {
 				text: TYPO3.LLL.core.refresh_login_refresh_button,
 				handler: function() {
 					var refresh = Ext.Ajax.request({
-						url: TYPO3.settings.BackendLogin['BackendLogin::isTimedOut'].ajaxUrl,
+						url: TYPO3.settings.ajaxUrls['BackendLogin::isTimedOut'],
 						method: 'GET',
 						scope: this
 					});
@@ -232,7 +232,7 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, {
 		if (TYPO3.configuration.showRefreshLoginPopup) {
 			//log off for sure
 			Ext.Ajax.request({
-				url: TYPO3.settings.BackendLogin['BackendLogin::logout'].ajaxUrl,
+				url: TYPO3.settings.ajaxUrls['BackendLogin::logout'],
 				method: 'GET',
 				scope: this,
 				success: function(response, opts) {
@@ -315,7 +315,7 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, {
 	triggerSubmitForm: function() {
 		if (TYPO3.configuration.securityLevel === 'superchallenged' || TYPO3.configuration.securityLevel === 'challenged') {
 			Ext.Ajax.request({
-				url: TYPO3.settings.BackendLogin['BackendLogin::getChallenge'].ajaxUrl,
+				url: TYPO3.settings.ajaxUrls['BackendLogin::getChallenge'],
 				params: {
 					'skipSessionUpdate': 1
 				},
@@ -331,7 +331,7 @@ Ext.ux.TYPO3.loginRefresh = Ext.extend(Ext.util.Observable, {
 			});
 		} else if (TYPO3.configuration.securityLevel === 'rsa') {
 			Ext.Ajax.request({
-				url: TYPO3.settings.BackendLogin['BackendLogin::getRsaPublicKey'].ajaxUrl,
+				url: TYPO3.settings.ajaxUrls['BackendLogin::getRsaPublicKey'],
 				params: {
 					'skipSessionUpdate': 1
 				},
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/modulemenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/modulemenu.js
index 0663943b40b5..f97695d2c2ee 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/modulemenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/modulemenu.js
@@ -47,7 +47,7 @@ TYPO3.ModuleMenu.Store = new Ext.data.JsonStore({
 		{name: 'subitems', type: 'int'},
 		'sub'
 	],
-	url: TYPO3.settings.ModuleMenu.getData.ajaxUrl,
+	url: TYPO3.settings.ajaxUrls['ModuleMenu::getData'],
 	baseParams: {
 		'action': 'getModules'
 	},
@@ -165,7 +165,7 @@ TYPO3.ModuleMenu.App = {
 						}
 						// save menu state
 						Ext.Ajax.request({
-							url: TYPO3.settings.ModuleMenu.saveMenuState.ajaxUrl,
+							url: TYPO3.settings.ajaxUrls['ModuleMenu::saveMenuState'],
 							params: {
 								'menuid': 'modmenu_' + id,
 								'state': state
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/shortcutmenu.js b/typo3/sysext/backend/Resources/Public/JavaScript/shortcutmenu.js
index f505bbdd92f1..767b0e8e5275 100644
--- a/typo3/sysext/backend/Resources/Public/JavaScript/shortcutmenu.js
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/shortcutmenu.js
@@ -58,7 +58,7 @@ var ShortcutMenu = Class.create({
 			var shortcutId = element.up('tr.shortcut').identify().slice(9);
 
 				// map InPlaceEditor to edit icons
-			var edit = new Ajax.InPlaceEditor('shortcut-label-' + shortcutId, TYPO3.settings.ShortcutMenu.saveShortcut.ajaxUrl, {
+			var edit = new Ajax.InPlaceEditor('shortcut-label-' + shortcutId, TYPO3.settings.ajaxUrls['ShortcutMenu::saveShortcut'], {
 				externalControl     : 'shortcut-edit-' + shortcutId,
 				externalControlOnly : true,
 				highlightcolor      : '#f9f9f9',
@@ -91,7 +91,7 @@ var ShortcutMenu = Class.create({
 					var deleteControl = event.element();
 					var shortcutId = deleteControl.up('tr.shortcut').identify().slice(9);
 
-					var del = new Ajax.Request(TYPO3.settings.ShortcutMenu.delete.ajaxUrl, {
+					var del = new Ajax.Request(TYPO3.settings.ajaxUrls['ShortcutMenu::delete'], {
 						parameters : '&shortcutId=' + shortcutId,
 						onComplete : this.reRenderMenu.bind(this)
 					});
@@ -158,7 +158,7 @@ var ShortcutMenu = Class.create({
 		selectField.appendChild(option);
 
 			// get the groups
-		var getGroups = new Ajax.Request(TYPO3.settings.ShortcutMenu.getGroups.ajaxUrl, {
+		var getGroups = new Ajax.Request(TYPO3.settings.ajaxUrls['ShortcutMenu::getGroups'], {
 			method: 'get',
 			asynchronous: false, // needs to be synchronous to build the options before adding the selectfield
 			requestHeaders: {Accept: 'application/json'},
@@ -201,7 +201,7 @@ var ShortcutMenu = Class.create({
 
 		var render = new Ajax.Updater(
 			container,
-			backPath + TYPO3.settings.ShortcutMenu.render.ajaxUrl,
+			backPath + TYPO3.settings.ajaxUrls['ShortcutMenu::render'],
 			{
 				asynchronous : false
 			}
@@ -227,7 +227,7 @@ var ShortcutMenu = Class.create({
 
 		// synchrous call to wait for it to complete and call the render
 		// method with backpath _afterwards_
-		var call = new Ajax.Request(backPath + TYPO3.settings.ShortcutMenu.create.ajaxUrl, {
+		var call = new Ajax.Request(backPath + TYPO3.settings.ajaxUrls['ShortcutMenu::create'], {
 			parameters : 'module=' + moduleName + '&url=' + url,
 			asynchronous : false
 		});
diff --git a/typo3/sysext/core/Classes/Page/PageRenderer.php b/typo3/sysext/core/Classes/Page/PageRenderer.php
index 1af3566bbc8d..d87b2093ef82 100644
--- a/typo3/sysext/core/Classes/Page/PageRenderer.php
+++ b/typo3/sysext/core/Classes/Page/PageRenderer.php
@@ -28,6 +28,7 @@ namespace TYPO3\CMS\Core\Page;
  *  This copyright notice MUST APPEAR in all copies of the script!
  ***************************************************************/
 
+use TYPO3\CMS\Backend\Utility\BackendUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
 /**
@@ -2244,6 +2245,9 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
 				$this->csConvObj->convArray($this->inlineSettings, $this->getCharSet(), 'utf-8');
 			}
 		}
+		if (TYPO3_MODE === 'BE') {
+			$this->addAjaxUrlsToInlineSettings();
+		}
 		$inlineSettings = $this->inlineLanguageLabels ? 'TYPO3.lang = ' . json_encode($this->inlineLanguageLabels) . ';' : '';
 		$inlineSettings .= $this->inlineSettings ? 'TYPO3.settings = ' . json_encode($this->inlineSettings) . ';' : '';
 		if ($this->addExtCore || $this->addExtJS) {
@@ -2293,6 +2297,17 @@ class PageRenderer implements \TYPO3\CMS\Core\SingletonInterface {
 		return $out;
 	}
 
+	/**
+	 * Make URLs to all backend ajax handlers available as inline setting.
+	 */
+	protected function addAjaxUrlsToInlineSettings() {
+		$ajaxUrls = array();
+		foreach (array_keys($GLOBALS['TYPO3_CONF_VARS']['BE']['AJAX']) as $ajaxHandler) {
+			$ajaxUrls[$ajaxHandler] = BackendUtility::getAjaxUrl($ajaxHandler);
+		}
+		$this->inlineSettings['ajaxUrls'] = $ajaxUrls;
+	}
+
 	/**
 	 * Renders the HTML script tag for the given jQuery version.
 	 *
diff --git a/typo3/sysext/filelist/Classes/Controller/FileListController.php b/typo3/sysext/filelist/Classes/Controller/FileListController.php
index adf1937299f9..2b408115646e 100644
--- a/typo3/sysext/filelist/Classes/Controller/FileListController.php
+++ b/typo3/sysext/filelist/Classes/Controller/FileListController.php
@@ -334,8 +334,6 @@ class FileListController {
 				&& $this->folderObject->checkActionPermission('write')
 			) {
 				$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/DragUploader');
-				$pageRenderer->addInlineSetting('DragUploader', 'ajaxUrl', BackendUtility::getAjaxUrl('TYPO3_tcefile::process'));
-				$pageRenderer->addInlineSetting('DragUploader', 'ajaxFlashMessagesUrl', BackendUtility::getAjaxUrl('DocumentTemplate::getFlashMessages'));
 				$pageRenderer->addInlineLanguagelabelFile(
 					\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('lang') . 'locallang_core.xlf',
 					'file_upload'
diff --git a/typo3/sysext/impexp/Classes/Hook/BackendControllerHook.php b/typo3/sysext/impexp/Classes/Hook/BackendControllerHook.php
new file mode 100644
index 000000000000..7817edf137fd
--- /dev/null
+++ b/typo3/sysext/impexp/Classes/Hook/BackendControllerHook.php
@@ -0,0 +1,42 @@
+<?php
+namespace TYPO3\CMS\Impexp\Hook;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2014 Helmut Hummel <helmut.hummel@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+
+/**
+ * This class adds import export related JavaScript to the backend
+ */
+class BackendControllerHook {
+	/**
+	 * Adds ImportExport-specific JavaScript
+	 *
+	 * @param array $configuration
+	 * @param \TYPO3\CMS\Backend\Controller\BackendController $backendController
+	 * @return void
+	 */
+	public function addJavaScript(array $configuration, \TYPO3\CMS\Backend\Controller\BackendController $backendController) {
+		$backendController->getPageRenderer()->addInlineSetting('ImportExport', 'moduleUrl', BackendUtility::getModuleUrl('xMOD_tximpexp'));
+	}
+}
diff --git a/typo3/sysext/impexp/ext_localconf.php b/typo3/sysext/impexp/ext_localconf.php
new file mode 100644
index 000000000000..6d4009a6e610
--- /dev/null
+++ b/typo3/sysext/impexp/ext_localconf.php
@@ -0,0 +1,6 @@
+<?php
+if (!defined('TYPO3_MODE')) {
+	die('Access denied.');
+}
+
+$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['typo3/backend.php']['constructPostProcess'][] = 'TYPO3\\CMS\\Impexp\\Hook\\BackendControllerHook->addJavaScript';
\ No newline at end of file
diff --git a/typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php b/typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php
index 35250b203fd7..a92f59c0e056 100644
--- a/typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php
+++ b/typo3/sysext/recordlist/Classes/Browser/ElementBrowser.php
@@ -367,8 +367,6 @@ class ElementBrowser {
 		$this->doc->getPageRenderer()->loadPrototype();
 		$this->doc->loadJavascriptLib('js/browse_links.js');
 		$this->doc->loadJavascriptLib('js/tree.js');
-		$this->doc->getPageRenderer()->addInlineSetting('Tree.SC_alt_db_navframe', 'ajaxUrl', BackendUtility::getAjaxUrl('SC_alt_db_navframe::expandCollapse'));
-		$this->doc->getPageRenderer()->addInlineSetting('Tree.SC_alt_file_navframe', 'ajaxUrl', BackendUtility::getAjaxUrl('SC_alt_file_navframe::expandCollapse'));
 	}
 
 	/**
diff --git a/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php b/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php
index 2274af166939..6ae6dd373af7 100644
--- a/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php
+++ b/typo3/sysext/rsaauth/Classes/Hook/BackendHookForAjaxLogin.php
@@ -48,6 +48,5 @@ class BackendHookForAjaxLogin {
 		foreach ($files as $file) {
 			$backendController->getPageRenderer()->addJsLibrary($file, $javascriptPath . $file);
 		}
-		$backendController->getPageRenderer()->addInlineSetting('BackendLogin.BackendLogin::getRsaPublicKey', 'ajaxUrl', BackendUtility::getAjaxUrl('BackendLogin::getRsaPublicKey'));
 	}
 }
-- 
GitLab