Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 7634)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadOsmTask.java	(revision 7636)
@@ -45,6 +45,4 @@
     protected DataSet downloadedData;
     protected DownloadTask downloadTask;
-
-    protected OsmDataLayer targetLayer;
 
     protected String newLayerName = null;
@@ -171,13 +169,131 @@
     }
 
-    protected class DownloadTask extends PleaseWaitRunnable {
-        protected OsmServerReader reader;
+    /**
+     * Superclass of internal download task.
+     * @since 7635
+     */
+    public static abstract class AbstractInternalTask extends PleaseWaitRunnable {
+
+        protected final boolean newLayer;
         protected DataSet dataSet;
-        protected boolean newLayer;
+
+        /**
+         * Constructs a new {@code AbstractInternalTask}.
+         *
+         * @param newLayer if {@code true}, force download to a new layer
+         * @param title message for the user
+         * @param ignoreException If true, exception will be propagated to calling code. If false then
+         * exception will be thrown directly in EDT. When this runnable is executed using executor framework
+         * then use false unless you read result of task (because exception will get lost if you don't)
+         */
+        public AbstractInternalTask(boolean newLayer, String title, boolean ignoreException) {
+            super(title, ignoreException);
+            this.newLayer = newLayer;
+        }
+
+        /**
+         * Constructs a new {@code AbstractInternalTask}.
+         *
+         * @param newLayer if {@code true}, force download to a new layer
+         * @param title message for the user
+         * @param progressMonitor progress monitor
+         * @param ignoreException If true, exception will be propagated to calling code. If false then
+         * exception will be thrown directly in EDT. When this runnable is executed using executor framework
+         * then use false unless you read result of task (because exception will get lost if you don't)
+         */
+        public AbstractInternalTask(boolean newLayer, String title, ProgressMonitor progressMonitor, boolean ignoreException) {
+            super(title, progressMonitor, ignoreException);
+            this.newLayer = newLayer;
+        }
+
+        protected OsmDataLayer getEditLayer() {
+            if (!Main.isDisplayingMapView()) return null;
+            return Main.main.getEditLayer();
+        }
+
+        protected int getNumDataLayers() {
+            int count = 0;
+            if (!Main.isDisplayingMapView()) return 0;
+            Collection<Layer> layers = Main.map.mapView.getAllLayers();
+            for (Layer layer : layers) {
+                if (layer instanceof OsmDataLayer) {
+                    count++;
+                }
+            }
+            return count;
+        }
+
+        protected OsmDataLayer getFirstDataLayer() {
+            if (!Main.isDisplayingMapView()) return null;
+            Collection<Layer> layers = Main.map.mapView.getAllLayersAsList();
+            for (Layer layer : layers) {
+                if (layer instanceof OsmDataLayer)
+                    return (OsmDataLayer) layer;
+            }
+            return null;
+        }
+
+        protected OsmDataLayer createNewLayer(String layerName) {
+            if (layerName == null || layerName.isEmpty()) {
+                layerName = OsmDataLayer.createNewName();
+            }
+            return new OsmDataLayer(dataSet, layerName, null);
+        }
+
+        protected OsmDataLayer createNewLayer() {
+            return createNewLayer(null);
+        }
+
+        protected void computeBboxAndCenterScale(Bounds bounds) {
+            BoundingXYVisitor v = new BoundingXYVisitor();
+            if (bounds != null) {
+                v.visit(bounds);
+            } else {
+                v.computeBoundingBox(dataSet.getNodes());
+            }
+            Main.map.mapView.recalculateCenterScale(v);
+        }
+
+        protected OsmDataLayer addNewLayerIfRequired(String newLayerName, Bounds bounds) {
+            int numDataLayers = getNumDataLayers();
+            if (newLayer || numDataLayers == 0 || (numDataLayers > 1 && getEditLayer() == null)) {
+                // the user explicitly wants a new layer, we don't have any layer at all
+                // or it is not clear which layer to merge to
+                //
+                final OsmDataLayer layer = createNewLayer(newLayerName);
+                final boolean isDisplayingMapView = Main.isDisplayingMapView();
+
+                Main.main.addLayer(layer);
+
+                // If the mapView is not there yet, we cannot calculate the bounds (see constructor of MapView).
+                // Otherwise jump to the current download.
+                if (isDisplayingMapView) {
+                    computeBboxAndCenterScale(bounds);
+                }
+                return layer;
+            }
+            return null;
+        }
+
+        protected void loadData(String newLayerName, Bounds bounds) {
+            OsmDataLayer layer = addNewLayerIfRequired(newLayerName, bounds);
+            if (layer == null) {
+                layer = getEditLayer();
+                if (layer == null) {
+                    layer = getFirstDataLayer();
+                }
+                layer.mergeFrom(dataSet);
+                computeBboxAndCenterScale(bounds);
+                layer.onPostDownloadFromServer();
+            }
+        }
+    }
+
+    protected class DownloadTask extends AbstractInternalTask {
+        protected final OsmServerReader reader;
 
         public DownloadTask(boolean newLayer, OsmServerReader reader, ProgressMonitor progressMonitor) {
-            super(tr("Downloading data"), progressMonitor, false);
+            super(newLayer, tr("Downloading data"), progressMonitor, false);
             this.reader = reader;
-            this.newLayer = newLayer;
         }
 
@@ -186,5 +302,6 @@
         }
 
-        @Override public void realRun() throws IOException, SAXException, OsmTransferException {
+        @Override
+        public void realRun() throws IOException, SAXException, OsmTransferException {
             try {
                 if (isCanceled())
@@ -208,43 +325,6 @@
         }
 
-        protected OsmDataLayer getEditLayer() {
-            if (!Main.isDisplayingMapView()) return null;
-            return Main.main.getEditLayer();
-        }
-
-        protected int getNumDataLayers() {
-            int count = 0;
-            if (!Main.isDisplayingMapView()) return 0;
-            Collection<Layer> layers = Main.map.mapView.getAllLayers();
-            for (Layer layer : layers) {
-                if (layer instanceof OsmDataLayer) {
-                    count++;
-                }
-            }
-            return count;
-        }
-
-        protected OsmDataLayer getFirstDataLayer() {
-            if (!Main.isDisplayingMapView()) return null;
-            Collection<Layer> layers = Main.map.mapView.getAllLayersAsList();
-            for (Layer layer : layers) {
-                if (layer instanceof OsmDataLayer)
-                    return (OsmDataLayer) layer;
-            }
-            return null;
-        }
-
-        protected OsmDataLayer createNewLayer(String layerName) {
-            if (layerName == null || layerName.isEmpty()) {
-                layerName = OsmDataLayer.createNewName();
-            }
-            return new OsmDataLayer(dataSet, layerName, null);
-        }
-
-        protected OsmDataLayer createNewLayer() {
-            return createNewLayer(null);
-        }
-
-        @Override protected void finish() {
+        @Override
+        protected void finish() {
             if (isFailed() || isCanceled())
                 return;
@@ -259,41 +339,9 @@
 
             rememberDownloadedData(dataSet);
-            int numDataLayers = getNumDataLayers();
-            if (newLayer || numDataLayers == 0 || (numDataLayers > 1 && getEditLayer() == null)) {
-                // the user explicitly wants a new layer, we don't have any layer at all
-                // or it is not clear which layer to merge to
-                //
-                targetLayer = createNewLayer(newLayerName);
-                final boolean isDisplayingMapView = Main.isDisplayingMapView();
-
-                Main.main.addLayer(targetLayer);
-
-                // If the mapView is not there yet, we cannot calculate the bounds (see constructor of MapView).
-                // Otherwise jump to the current download.
-                if (isDisplayingMapView) {
-                    computeBboxAndCenterScale();
-                }
-            } else {
-                targetLayer = getEditLayer();
-                if (targetLayer == null) {
-                    targetLayer = getFirstDataLayer();
-                }
-                targetLayer.mergeFrom(dataSet);
-                computeBboxAndCenterScale();
-                targetLayer.onPostDownloadFromServer();
-            }
-        }
-
-        protected void computeBboxAndCenterScale() {
-            BoundingXYVisitor v = new BoundingXYVisitor();
-            if (currentBounds != null) {
-                v.visit(currentBounds);
-            } else {
-                v.computeBoundingBox(dataSet.getNodes());
-            }
-            Main.map.mapView.recalculateCenterScale(v);
-        }
-
-        @Override protected void cancel() {
+            loadData(newLayerName, currentBounds);
+        }
+
+        @Override
+        protected void cancel() {
             setCanceled(true);
             if (reader != null) {
Index: trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 7634)
+++ trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java	(revision 7636)
@@ -75,5 +75,4 @@
      * exception will be thrown directly in EDT. When this runnable is executed using executor framework
      * then use false unless you read result of task (because exception will get lost if you don't)
-     * @throws IllegalArgumentException thrown if parent is null
      */
     public PleaseWaitRunnable(String title, ProgressMonitor progressMonitor, boolean ignoreException) {
Index: trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java	(revision 7634)
+++ trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java	(revision 7636)
@@ -33,5 +33,5 @@
      */
     static final int protocolMajorVersion = 1;
-    static final int protocolMinorVersion = 5;
+    static final int protocolMinorVersion = 6;
 
     /**
Index: trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java	(revision 7634)
+++ trunk/src/org/openstreetmap/josm/io/remotecontrol/RequestProcessor.java	(revision 7636)
@@ -31,4 +31,5 @@
 import org.openstreetmap.josm.io.remotecontrol.handler.ImportHandler;
 import org.openstreetmap.josm.io.remotecontrol.handler.LoadAndZoomHandler;
+import org.openstreetmap.josm.io.remotecontrol.handler.LoadDataHandler;
 import org.openstreetmap.josm.io.remotecontrol.handler.LoadObjectHandler;
 import org.openstreetmap.josm.io.remotecontrol.handler.OpenFileHandler;
@@ -126,4 +127,5 @@
         addRequestHandlerClass(LoadAndZoomHandler.command, LoadAndZoomHandler.class, true);
         addRequestHandlerClass(LoadAndZoomHandler.command2, LoadAndZoomHandler.class, true);
+        addRequestHandlerClass(LoadDataHandler.command, LoadDataHandler.class, true);
         addRequestHandlerClass(ImageryHandler.command, ImageryHandler.class, true);
         addRequestHandlerClass(AddNodeHandler.command, AddNodeHandler.class, true);
Index: trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadDataHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadDataHandler.java	(revision 7636)
+++ trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/LoadDataHandler.java	(revision 7636)
@@ -0,0 +1,151 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.remotecontrol.handler;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.io.OsmReader;
+import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;
+
+/**
+ * Handler to load data directly from the URL.
+ * @since 7634
+ */
+public class LoadDataHandler extends RequestHandler {
+
+    private static final String OSM_MIME_TYPE = "application/x-osm+xml";
+
+    /**
+     * The remote control command name used to import data.
+     */
+    public static final String command = "load_data";
+
+    /**
+     * Holds the data input string
+     */
+    private String data;
+
+    /**
+     * Holds the mime type. Currently only OSM_MIME_TYPE is supported
+     * But it could be extended to text/csv, application/gpx+xml, ... or even binary encoded data
+     */
+    private String mimeType;
+
+    @Override
+    protected void handleRequest() throws RequestHandlerErrorException {
+        try {
+            // Transform data string to inputstream
+            InputStream source = new ByteArrayInputStream(data.getBytes("UTF-8"));
+            DataSet dataSet = new DataSet();
+            if (mimeType != null && mimeType.contains(OSM_MIME_TYPE))
+                dataSet = OsmReader.parseDataSet(source, null);
+            Main.worker.submit(new LoadDataTask(isLoadInNewLayer(), dataSet, args.get("layer_name")));
+        } catch (Exception e) {
+            Main.warn("Problem with data: " + data);
+            throw new RequestHandlerErrorException(e);
+        }
+    }
+
+    @Override
+    public String[] getMandatoryParams() {
+        return new String[]{"data"};
+    }
+
+    @Override
+    public String[] getOptionalParams() {
+        return new String[] {"new_layer", "mime_type", "layer_name"};
+    }
+
+    @Override
+    public String getUsage() {
+        return "Reads data encoded directly in the URL and adds it to the current data set";
+    }
+
+    @Override
+    public String[] getUsageExamples() {
+        return new String[] {
+                "/load_data?layer_name=extra_layer&new_layer=true&data=%3Cosm%3E%3Cnode%3E...%3C%2Fnode%3E%3C%2Fosm%3E" };
+    }
+
+    @Override
+    public String getPermissionMessage() {
+        return tr("Remote Control has been asked to load the following data:")
+                + "<br>" + data;
+    }
+
+    @Override
+    public PermissionPrefWithDefault getPermissionPref() {
+        // Same permission as the import data, as the difference from a user pov is minimal
+        return PermissionPrefWithDefault.IMPORT_DATA;
+    }
+
+    @Override
+    protected void parseArgs() {
+        if (request.indexOf('?') == -1)
+            return; // nothing to do
+
+        Map<String, String> args = new HashMap<>();
+
+        // The data itself shouldn't contain any &, = or ? chars.
+        // Those are reserved for the URL parsing
+        // and should be URL encoded as %26, %3D or %3F
+        String query = request.substring(request.indexOf('?') + 1);
+        String[] params = query.split("&");
+        for (String param : params) {
+            String[] kv = param.split("=");
+            if (kv.length == 2)
+                args.put(kv[0], kv[1]);
+        }
+        this.args = args;
+    }
+
+    @Override
+    protected void validateRequest() throws RequestHandlerBadRequestException {
+        if (args.get("data") == null)
+            throw new RequestHandlerBadRequestException("RemoteControl: No data defined in URL");
+        try {
+            data = URLDecoder.decode(args.get("data"), "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RequestHandlerBadRequestException("RemoteControl: UnsupportedEncodingException: " + e.getMessage(), e);
+        }
+        mimeType = args.get("mime_type");
+        if (mimeType == null) {
+            mimeType = OSM_MIME_TYPE;
+        }
+    }
+
+    protected class LoadDataTask extends DownloadOsmTask.AbstractInternalTask {
+
+        protected final String layerName;
+
+        public LoadDataTask(boolean newLayer, DataSet dataSet, String layerName) {
+            super(newLayer, tr("Loading data"), false);
+            this.dataSet = dataSet;
+            this.layerName = layerName;
+        }
+
+        @Override
+        public void realRun() {
+            // No real run, the data is already loaded
+        }
+
+        @Override
+        protected void cancel() {
+            // No Cancel, would be hard without a real run
+        }
+
+        @Override
+        protected void finish() {
+            loadData(layerName, null);
+        }
+    }
+}
