diff --git a/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp b/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp
deleted file mode 100644
index bd3fe0aa95d9ee379f50e8346dabeda249219106..0000000000000000000000000000000000000000
--- a/src/plugins/qmlprofiler/localqmlprofilerrunner.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#include "localqmlprofilerrunner.h"
-#include "qmlprofilerplugin.h"
-#include "qmlprofilerruncontrol.h"
-
-#include <projectexplorer/runconfiguration.h>
-#include <projectexplorer/environmentaspect.h>
-#include <projectexplorer/devicesupport/idevice.h>
-#include <projectexplorer/kitinformation.h>
-#include <projectexplorer/projectexplorer.h>
-#include <projectexplorer/target.h>
-
-#include <qmldebug/qmldebugcommandlinearguments.h>
-
-#include <utils/temporaryfile.h>
-
-#include <QTcpServer>
-#include <QTemporaryFile>
-
-using namespace ProjectExplorer;
-
-namespace QmlProfiler {
-
-QString LocalQmlProfilerRunner::findFreeSocket()
-{
-    Utils::TemporaryFile file("qmlprofiler-freesocket");
-    if (file.open()) {
-        return file.fileName();
-    } else {
-        qWarning() << "Could not open a temporary file to find a debug socket.";
-        return QString();
-    }
-}
-
-Utils::Port LocalQmlProfilerRunner::findFreePort(QString &host)
-{
-    QTcpServer server;
-    if (!server.listen(QHostAddress::LocalHost)
-            && !server.listen(QHostAddress::LocalHostIPv6)) {
-        qWarning() << "Cannot open port on host for QML profiling.";
-        return Utils::Port();
-    }
-    host = server.serverAddress().toString();
-    return Utils::Port(server.serverPort());
-}
-
-LocalQmlProfilerRunner::LocalQmlProfilerRunner(const Configuration &configuration,
-                                               QmlProfilerRunner *runner) :
-    QObject(runner->runControl()),
-    m_runControl(runner->runControl()),
-    m_configuration(configuration)
-{
-    auto runControl = runner->runControl();
-    connect(&m_launcher, &ApplicationLauncher::appendMessage,
-            this, &LocalQmlProfilerRunner::appendMessage);
-    connect(this, &LocalQmlProfilerRunner::stopped,
-            runner, &QmlProfilerRunner::notifyRemoteFinished);
-    connect(this, &LocalQmlProfilerRunner::appendMessage,
-            runControl, &RunControl::appendMessage);
-    connect(runControl, &RunControl::starting,
-            this, &LocalQmlProfilerRunner::start);
-    connect(runControl, &RunControl::finished,
-            this, &LocalQmlProfilerRunner::stop);
-
-    m_outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput());
-
-    connect(runControl, &RunControl::appendMessageRequested,
-            this, [this](RunControl *runControl, const QString &msg, Utils::OutputFormat format) {
-        Q_UNUSED(runControl);
-        Q_UNUSED(format);
-        m_outputParser.processOutput(msg);
-    });
-
-    connect(&m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
-            runControl, [this, runControl, runner](Utils::Port port) {
-        runControl->notifyRemoteSetupDone(port);
-        runner->notifyRemoteSetupDone(port);
-    });
-
-    connect(&m_outputParser, &QmlDebug::QmlOutputParser::noOutputMessage,
-            runControl, [this, runControl, runner]() {
-        runControl->notifyRemoteSetupDone(Utils::Port());
-        runner->notifyRemoteSetupDone(Utils::Port());
-    });
-
-    connect(&m_outputParser, &QmlDebug::QmlOutputParser::connectingToSocketMessage,
-            runControl, [this, runControl, runner]() {
-        runControl->notifyRemoteSetupDone(Utils::Port());
-        runner->notifyRemoteSetupDone(Utils::Port());
-    });
-
-    connect(&m_outputParser, &QmlDebug::QmlOutputParser::errorMessage,
-            runControl, [this, runControl, runner](const QString &message) {
-        runControl->notifyRemoteSetupFailed(message);
-        runner->notifyRemoteSetupFailed(message);
-    });
-}
-
-void LocalQmlProfilerRunner::start()
-{
-    QTC_ASSERT(!m_configuration.socket.isEmpty() || m_configuration.port.isValid(), return);
-
-    StandardRunnable runnable = m_configuration.debuggee;
-    QString arguments = m_configuration.socket.isEmpty() ?
-                QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices,
-                                               m_configuration.port) :
-                QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlProfilerServices,
-                                                 m_configuration.socket);
-
-
-    if (!m_configuration.debuggee.commandLineArguments.isEmpty())
-        arguments += QLatin1Char(' ') + m_configuration.debuggee.commandLineArguments;
-
-    runnable.commandLineArguments = arguments;
-    runnable.runMode = ApplicationLauncher::Gui;
-
-    // queue this, as the process can already die in the call to start().
-    // We want the started() signal to be emitted before the stopped() signal.
-    connect(&m_launcher, &ApplicationLauncher::processExited,
-            this, &LocalQmlProfilerRunner::spontaneousStop,
-            Qt::QueuedConnection);
-    m_launcher.start(runnable);
-
-    emit started();
-}
-
-void LocalQmlProfilerRunner::spontaneousStop(int exitCode, QProcess::ExitStatus status)
-{
-    Q_UNUSED(exitCode);
-    Q_UNUSED(status);
-    disconnect(&m_launcher, &ApplicationLauncher::processExited,
-               this, &LocalQmlProfilerRunner::spontaneousStop);
-
-    emit stopped();
-}
-
-void LocalQmlProfilerRunner::stop()
-{
-    if (m_launcher.isRunning())
-        m_launcher.stop();
-}
-
-} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/localqmlprofilerrunner.h b/src/plugins/qmlprofiler/localqmlprofilerrunner.h
deleted file mode 100644
index 4758405a7aaca51e8844f0920d11245dbaa808c2..0000000000000000000000000000000000000000
--- a/src/plugins/qmlprofiler/localqmlprofilerrunner.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-****************************************************************************/
-
-#pragma once
-
-#include "qmlprofiler_global.h"
-#include <utils/environment.h>
-#include <utils/port.h>
-#include <projectexplorer/applicationlauncher.h>
-#include <projectexplorer/runnables.h>
-#include <qmldebug/qmloutputparser.h>
-
-namespace QmlProfiler {
-
-class QmlProfilerRunner;
-
-class QMLPROFILER_EXPORT LocalQmlProfilerRunner : public QObject
-{
-    Q_OBJECT
-
-public:
-    struct Configuration {
-        ProjectExplorer::StandardRunnable debuggee;
-        Utils::Port port;
-        QString socket;
-    };
-
-    LocalQmlProfilerRunner(const Configuration &configuration,
-                           QmlProfilerRunner *runner);
-
-    static Utils::Port findFreePort(QString &host);
-    static QString findFreeSocket();
-
-signals:
-    void started();
-    void stopped();
-    void appendMessage(const QString &message, Utils::OutputFormat format);
-
-private:
-    void spontaneousStop(int exitCode, QProcess::ExitStatus status);
-    void start();
-    void stop();
-
-    ProjectExplorer::RunControl *m_runControl;
-    Configuration m_configuration;
-    ProjectExplorer::ApplicationLauncher m_launcher;
-    QmlDebug::QmlOutputParser m_outputParser;
-};
-
-} // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofiler.pro b/src/plugins/qmlprofiler/qmlprofiler.pro
index 799b627abf9b1012a69f555ef622ed2efef19e69..0995840d2bc3c22a10f1b062151a15dee96f223a 100644
--- a/src/plugins/qmlprofiler/qmlprofiler.pro
+++ b/src/plugins/qmlprofiler/qmlprofiler.pro
@@ -9,7 +9,6 @@ SOURCES += \
     flamegraphmodel.cpp \
     flamegraphview.cpp \
     inputeventsmodel.cpp \
-    localqmlprofilerrunner.cpp \
     memoryusagemodel.cpp \
     pixmapcachemodel.cpp \
     qmlevent.cpp \
@@ -50,7 +49,6 @@ HEADERS += \
     flamegraphmodel.h \
     flamegraphview.h \
     inputeventsmodel.h \
-    localqmlprofilerrunner.h \
     memoryusagemodel.h \
     pixmapcachemodel.h \
     qmlevent.h \
diff --git a/src/plugins/qmlprofiler/qmlprofiler.qbs b/src/plugins/qmlprofiler/qmlprofiler.qbs
index 5202d0eb37535213ff31c0a4f6b70bb366ed63df..b509ac07a365d05f06ae422a848bd76f7ff5ca16 100644
--- a/src/plugins/qmlprofiler/qmlprofiler.qbs
+++ b/src/plugins/qmlprofiler/qmlprofiler.qbs
@@ -24,7 +24,6 @@ QtcPlugin {
             "flamegraphmodel.cpp", "flamegraphmodel.h",
             "flamegraphview.cpp", "flamegraphview.h",
             "inputeventsmodel.cpp", "inputeventsmodel.h",
-            "localqmlprofilerrunner.cpp", "localqmlprofilerrunner.h",
             "memoryusagemodel.cpp", "memoryusagemodel.h",
             "pixmapcachemodel.cpp", "pixmapcachemodel.h",
             "qmlevent.cpp", "qmlevent.h",
diff --git a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
index 91fc6b278cbb35c6d5f5cf914ffa7f1bdf149288..8cce222c513daddc5905c855bfd2fdd5db0d4bd2 100644
--- a/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
+++ b/src/plugins/qmlprofiler/qmlprofilermodelmanager.h
@@ -37,6 +37,8 @@
 #include <QObject>
 #include <functional>
 
+namespace ProjectExplorer { class RunConfiguration; }
+
 namespace QmlProfiler {
 class QmlProfilerModelManager;
 class QmlProfilerNotesModel;
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
index 337467dfb78b6d71339f65e395d61329d183e203..fb74804aa2ac5f93c3863ed7ccbde7b0478ec383 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.cpp
@@ -23,9 +23,10 @@
 **
 ****************************************************************************/
 
+#include "qmlprofilerclientmanager.h"
 #include "qmlprofilerruncontrol.h"
-#include "localqmlprofilerrunner.h"
 #include "qmlprofilertool.h"
+#include "qmlprofilerplugin.h"
 
 #include <debugger/analyzer/analyzermanager.h>
 #include <debugger/analyzer/analyzerstartparameters.h>
@@ -33,30 +34,38 @@
 #include <coreplugin/icore.h>
 #include <coreplugin/helpmanager.h>
 
+#include <projectexplorer/devicesupport/idevice.h>
 #include <projectexplorer/environmentaspect.h>
 #include <projectexplorer/kitinformation.h>
 #include <projectexplorer/localapplicationruncontrol.h>
+#include <projectexplorer/projectexplorer.h>
 #include <projectexplorer/projectexplorerconstants.h>
 #include <projectexplorer/projectexplorericons.h>
+#include <projectexplorer/runconfiguration.h>
 #include <projectexplorer/runnables.h>
 #include <projectexplorer/target.h>
 
 #include <qtsupport/qtsupportconstants.h>
+
 #include <qmldebug/qmloutputparser.h>
+#include <qmldebug/qmldebugcommandlinearguments.h>
 
 #include <utils/qtcassert.h>
+#include <utils/temporaryfile.h>
 
+#include <QApplication>
 #include <QMainWindow>
 #include <QMessageBox>
-#include <QTimer>
-#include <QTcpServer>
-#include <QApplication>
 #include <QMessageBox>
 #include <QPushButton>
+#include <QTcpServer>
+#include <QTemporaryFile>
+#include <QTimer>
 
 using namespace Debugger;
 using namespace Core;
 using namespace ProjectExplorer;
+using namespace QmlProfiler::Internal;
 
 namespace QmlProfiler {
 
@@ -69,6 +78,10 @@ class QmlProfilerRunner::QmlProfilerRunnerPrivate
 public:
     QmlProfilerStateManager *m_profilerState = 0;
     QTimer m_noDebugOutputTimer;
+    bool m_isLocal = false;
+    QmlProfilerRunner::Configuration m_configuration;
+    ProjectExplorer::ApplicationLauncher m_launcher;
+    QmlDebug::QmlOutputParser m_outputParser;
 };
 
 //
@@ -100,20 +113,48 @@ QmlProfilerRunner::~QmlProfilerRunner()
 
 void QmlProfilerRunner::start()
 {
-    runControl()->reportApplicationStart();
     Internal::QmlProfilerTool::instance()->finalizeRunControl(this);
-    QTC_ASSERT(d->m_profilerState, runControl()->reportApplicationStop(); return);
+    QTC_ASSERT(d->m_profilerState, return);
 
-    QTC_ASSERT(connection().is<AnalyzerConnection>(), runControl()->reportApplicationStop(); return);
+    QTC_ASSERT(connection().is<AnalyzerConnection>(), return);
     auto conn = connection().as<AnalyzerConnection>();
 
-    if (conn.analyzerPort.isValid())
-        emit processRunning(conn.analyzerPort);
+    if (conn.analyzerPort.isValid()) {
+        auto clientManager = Internal::QmlProfilerTool::clientManager();
+        clientManager->setTcpConnection(conn.analyzerHost, conn.analyzerPort);
+        clientManager->connectToTcpServer();
+    }
     else if (conn.analyzerSocket.isEmpty())
         d->m_noDebugOutputTimer.start();
 
     d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
-    emit runControl()->starting();
+
+    if (d->m_isLocal) {
+        QTC_ASSERT(!d->m_configuration.socket.isEmpty() || d->m_configuration.port.isValid(), return);
+
+        StandardRunnable debuggee = runnable().as<StandardRunnable>();
+        QString arguments = d->m_configuration.socket.isEmpty() ?
+                    QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices,
+                                                   d->m_configuration.port) :
+                    QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlProfilerServices,
+                                                     d->m_configuration.socket);
+
+
+        if (!debuggee.commandLineArguments.isEmpty())
+            arguments += ' ' + debuggee.commandLineArguments;
+
+        debuggee.commandLineArguments = arguments;
+        debuggee.runMode = ApplicationLauncher::Gui;
+
+        // queue this, as the process can already die in the call to start().
+        // We want the started() signal to be emitted before the stopped() signal.
+        connect(&d->m_launcher, &ApplicationLauncher::processExited,
+                this, &QmlProfilerRunner::spontaneousStop,
+                Qt::QueuedConnection);
+        d->m_launcher.start(debuggee);
+
+        emit localRunnerStarted();
+    }
 }
 
 void QmlProfilerRunner::stop()
@@ -148,7 +189,6 @@ void QmlProfilerRunner::notifyRemoteFinished()
     switch (d->m_profilerState->currentState()) {
     case QmlProfilerStateManager::AppRunning:
         d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying);
-        runControl()->reportApplicationStop();
         break;
     case QmlProfilerStateManager::Idle:
         break;
@@ -177,7 +217,7 @@ void QmlProfilerRunner::cancelProcess()
         return;
     }
     }
-    runControl()->reportApplicationStop();
+    runControl()->initiateStop();
 }
 
 void QmlProfilerRunner::notifyRemoteSetupFailed(const QString &errorMessage)
@@ -200,7 +240,6 @@ void QmlProfilerRunner::notifyRemoteSetupFailed(const QString &errorMessage)
     // KILL
     d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppDying);
     d->m_noDebugOutputTimer.stop();
-    runControl()->reportApplicationStop();
 }
 
 void QmlProfilerRunner::wrongSetupMessageBoxFinished(int button)
@@ -219,8 +258,11 @@ void QmlProfilerRunner::notifyRemoteSetupDone(Utils::Port port)
         QTC_ASSERT(connection().is<AnalyzerConnection>(), return);
         port = connection().as<AnalyzerConnection>().analyzerPort;
     }
-    if (port.isValid())
-        emit processRunning(port);
+    if (port.isValid()) {
+        auto clientManager = Internal::QmlProfilerTool::clientManager();
+        clientManager->setTcpConnection(connection().as<AnalyzerConnection>().analyzerHost, port);
+        clientManager->connectToTcpServer();
+    }
 }
 
 void QmlProfilerRunner::registerProfilerStateManager( QmlProfilerStateManager *profilerState )
@@ -242,7 +284,6 @@ void QmlProfilerRunner::profilerStateChanged()
 {
     switch (d->m_profilerState->currentState()) {
     case QmlProfilerStateManager::Idle:
-        runControl()->reportApplicationStop();
         d->m_noDebugOutputTimer.stop();
         break;
     default:
@@ -250,4 +291,82 @@ void QmlProfilerRunner::profilerStateChanged()
     }
 }
 
+QString QmlProfilerRunner::findFreeSocket()
+{
+    Utils::TemporaryFile file("qmlprofiler-freesocket");
+    if (file.open()) {
+        return file.fileName();
+    } else {
+        qWarning() << "Could not open a temporary file to find a debug socket.";
+        return QString();
+    }
+}
+
+Utils::Port QmlProfilerRunner::findFreePort(QString &host)
+{
+    QTcpServer server;
+    if (!server.listen(QHostAddress::LocalHost)
+            && !server.listen(QHostAddress::LocalHostIPv6)) {
+        qWarning() << "Cannot open port on host for QML profiling.";
+        return Utils::Port();
+    }
+    host = server.serverAddress().toString();
+    return Utils::Port(server.serverPort());
+}
+
+void QmlProfilerRunner::setLocalConfiguration(const Configuration &configuration)
+{
+    d->m_isLocal = true;
+    d->m_configuration = configuration;
+    connect(&d->m_launcher, &ApplicationLauncher::appendMessage,
+            this, &QmlProfilerRunner::appendMessage);
+    connect(this, &QmlProfilerRunner::localRunnerStopped,
+            this, &QmlProfilerRunner::notifyRemoteFinished);
+    connect(runControl(), &RunControl::finished,
+            this, &QmlProfilerRunner::stopLocalRunner);
+
+    d->m_outputParser.setNoOutputText(ApplicationLauncher::msgWinCannotRetrieveDebuggingOutput());
+
+    connect(runControl(), &RunControl::appendMessageRequested,
+            this, [this](RunControl *, const QString &msg, Utils::OutputFormat) {
+        d->m_outputParser.processOutput(msg);
+    });
+
+    connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::waitingForConnectionOnPort,
+            this, [this](Utils::Port port) {
+        notifyRemoteSetupDone(port);
+    });
+
+    connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::noOutputMessage,
+            this, [this] {
+        notifyRemoteSetupDone(Utils::Port());
+    });
+
+    connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::connectingToSocketMessage,
+            this, [this] {
+        notifyRemoteSetupDone(Utils::Port());
+    });
+
+    connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::errorMessage,
+            this, [this](const QString &message) {
+        notifyRemoteSetupFailed(message);
+    });
+}
+
+void QmlProfilerRunner::spontaneousStop(int exitCode, QProcess::ExitStatus status)
+{
+    Q_UNUSED(exitCode);
+    Q_UNUSED(status);
+    disconnect(&d->m_launcher, &ApplicationLauncher::processExited,
+               this, &QmlProfilerRunner::spontaneousStop);
+
+    emit localRunnerStopped();
+}
+
+void QmlProfilerRunner::stopLocalRunner()
+{
+    if (d->m_launcher.isRunning())
+        d->m_launcher.stop();
+}
+
 } // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrol.h b/src/plugins/qmlprofiler/qmlprofilerruncontrol.h
index 9ff6106d36f7eafa6de59f303636fd79ba8d3f06..00979d01a7f247b6ff324b10561363f3c39971f8 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrol.h
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrol.h
@@ -28,7 +28,12 @@
 #include "qmlprofilerstatemanager.h"
 
 #include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/runnables.h>
+
 #include <utils/outputformat.h>
+#include <utils/port.h>
+
+#include <qmldebug/qmloutputparser.h>
 
 namespace QmlProfiler {
 
@@ -40,22 +45,37 @@ public:
     QmlProfilerRunner(ProjectExplorer::RunControl *runControl);
     ~QmlProfilerRunner() override;
 
+    struct Configuration {
+        Utils::Port port;
+        QString socket;
+    };
+    void setLocalConfiguration(const Configuration &conf);
+
     void registerProfilerStateManager( QmlProfilerStateManager *profilerState );
 
     void notifyRemoteSetupDone(Utils::Port port);
     void notifyRemoteSetupFailed(const QString &errorMessage);
-    void start() override;
-    void stop() override;
     void cancelProcess();
     void notifyRemoteFinished();
 
+    static Utils::Port findFreePort(QString &host);
+    static QString findFreeSocket();
+
 signals:
-    void processRunning(Utils::Port port);
+    void localRunnerStarted();
+    void localRunnerStopped();
 
 private:
+    void start() override;
+    void stop() override;
+
     void wrongSetupMessageBoxFinished(int);
     void profilerStateChanged();
 
+    void spontaneousStop(int exitCode, QProcess::ExitStatus status);
+    void startLocalRunner();
+    void stopLocalRunner();
+
     class QmlProfilerRunnerPrivate;
     QmlProfilerRunnerPrivate *d;
 };
diff --git a/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp b/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp
index e6cf9ee79ea0d130ce8d386c9c4529b4069cfbe9..c1239ef67428e5fbc6daf527b4f2efcb3602a66e 100644
--- a/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilerruncontrolfactory.cpp
@@ -24,7 +24,6 @@
 ****************************************************************************/
 
 #include "qmlprofilerruncontrolfactory.h"
-#include "localqmlprofilerrunner.h"
 #include "qmlprofilerruncontrol.h"
 #include "qmlprofilerrunconfigurationaspect.h"
 
@@ -60,6 +59,8 @@ static bool isLocal(RunConfiguration *runConfiguration)
 QmlProfilerRunControlFactory::QmlProfilerRunControlFactory(QObject *parent) :
     IRunControlFactory(parent)
 {
+    RunControl::registerWorkerCreator(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE,
+        [this](RunControl *runControl) { return new QmlProfilerRunner(runControl); });
 }
 
 bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, Core::Id mode) const
@@ -67,44 +68,33 @@ bool QmlProfilerRunControlFactory::canRun(RunConfiguration *runConfiguration, Co
     return mode == ProjectExplorer::Constants::QML_PROFILER_RUN_MODE && isLocal(runConfiguration);
 }
 
-RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *errorMessage)
+RunControl *QmlProfilerRunControlFactory::create(RunConfiguration *runConfiguration, Core::Id mode, QString *)
 {
     QTC_ASSERT(canRun(runConfiguration, mode), return 0);
     QTC_ASSERT(runConfiguration->runnable().is<StandardRunnable>(), return 0);
-    auto runnable = runConfiguration->runnable().as<StandardRunnable>();
-
-    if (runnable.executable.isEmpty()) {
-        if (errorMessage)
-            *errorMessage = tr("No executable file to launch.");
-        return 0;
-    }
 
     Kit *kit = runConfiguration->target()->kit();
     AnalyzerConnection connection;
     const QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
     if (version) {
         if (version->qtVersion() >= QtSupport::QtVersionNumber(5, 6, 0))
-            connection.analyzerSocket = LocalQmlProfilerRunner::findFreeSocket();
+            connection.analyzerSocket = QmlProfilerRunner::findFreeSocket();
         else
-            connection.analyzerPort = LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
+            connection.analyzerPort = QmlProfilerRunner::findFreePort(connection.analyzerHost);
     } else {
         qWarning() << "Running QML profiler on Kit without Qt version??";
-        connection.analyzerPort = LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
+        connection.analyzerPort = QmlProfilerRunner::findFreePort(connection.analyzerHost);
     }
 
     auto runControl = new RunControl(runConfiguration, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
-    auto runWorker = runControl->createWorker(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
-    runControl->setRunnable(runnable);
     runControl->setConnection(connection);
 
-    LocalQmlProfilerRunner::Configuration conf;
-    conf.debuggee = runnable;
-    if (EnvironmentAspect *environment = runConfiguration->extraAspect<EnvironmentAspect>())
-        conf.debuggee.environment = environment->environment();
+    QmlProfilerRunner::Configuration conf;
     conf.socket = connection.analyzerSocket;
     conf.port = connection.analyzerPort;
 
-    (void) new LocalQmlProfilerRunner(conf, qobject_cast<QmlProfilerRunner *>(runWorker));
+    auto runner = new QmlProfilerRunner(runControl);
+    runner->setLocalConfiguration(conf);
     return runControl;
 }
 
diff --git a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
index 3060c8f1400ac0c88833f0c139a373c0ced90b04..a0bdaed6cc118e6e4c467818122e5570bb2429af 100644
--- a/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertextmark.cpp
@@ -25,8 +25,9 @@
 #include "qmlprofilertextmark.h"
 #include "qmlprofilerconstants.h"
 
-#include <QPainter>
+#include <QLabel>
 #include <QLayout>
+#include <QPainter>
 
 namespace QmlProfiler {
 namespace Internal {
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.cpp b/src/plugins/qmlprofiler/qmlprofilertool.cpp
index 0c57588fc15c7a4b2478d97346e5c074077be3d6..0a087b38354e49f9a7b1743d4cdb90e9e10da182 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.cpp
+++ b/src/plugins/qmlprofiler/qmlprofilertool.cpp
@@ -247,17 +247,12 @@ QmlProfilerTool::QmlProfilerTool(QObject *parent)
     // is available, then we can populate the file finder
     d->m_profilerModelManager->populateFileFinder();
 
-    auto runWorkerCreator = [this](RunControl *runControl) {
-       return createRunner(runControl, Debugger::startupRunConfiguration());
-    };
-
     QString description = tr("The QML Profiler can be used to find performance "
                              "bottlenecks in applications using QML.");
 
     d->m_startAction = Debugger::createStartAction();
     d->m_stopAction = Debugger::createStopAction();
 
-    RunControl::registerWorkerCreator(ProjectExplorer::Constants::QML_PROFILER_RUN_MODE, runWorkerCreator);
     act = new QAction(tr("QML Profiler"), this);
     act->setToolTip(description);
     menu->addAction(ActionManager::registerAction(act, "QmlProfiler.Local"),
@@ -328,11 +323,13 @@ void QmlProfilerTool::updateRunActions()
     }
 }
 
-RunWorker *QmlProfilerTool::createRunner(RunControl *runControl, RunConfiguration *runConfiguration)
+void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
 {
     d->m_toolBusy = true;
+    auto runControl = runWorker->runControl();
+    auto runConfiguration = runControl->runConfiguration();
     if (runConfiguration) {
-        QmlProfilerRunConfigurationAspect *aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
+        auto aspect = static_cast<QmlProfilerRunConfigurationAspect *>(
                     runConfiguration->extraAspect(Constants::SETTINGS));
         if (aspect) {
             if (QmlProfilerSettings *settings = static_cast<QmlProfilerSettings *>(aspect->currentSettings())) {
@@ -343,7 +340,6 @@ RunWorker *QmlProfilerTool::createRunner(RunControl *runControl, RunConfiguratio
         }
     }
 
-    auto runWorker = new QmlProfilerRunner(runControl);
     connect(runControl, &RunControl::finished, this, [this, runControl] {
         d->m_toolBusy = false;
         updateRunActions();
@@ -353,11 +349,6 @@ RunWorker *QmlProfilerTool::createRunner(RunControl *runControl, RunConfiguratio
     connect(d->m_stopAction, &QAction::triggered, runControl, &RunControl::stop);
 
     updateRunActions();
-    return runWorker;
-}
-
-void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
-{
     runWorker->registerProfilerStateManager(d->m_profilerState);
     QmlProfilerClientManager *clientManager = d->m_profilerConnections;
 
@@ -376,20 +367,10 @@ void QmlProfilerTool::finalizeRunControl(QmlProfilerRunner *runWorker)
     // Initialize m_projectFinder
     //
 
-    auto runControl = runWorker->runControl();
-    RunConfiguration *runConfiguration = runControl->runConfiguration();
     if (runConfiguration) {
         d->m_profilerModelManager->populateFileFinder(runConfiguration);
     }
 
-    if (connection.analyzerSocket.isEmpty()) {
-        QString host = connection.analyzerHost;
-        connect(runWorker, &QmlProfilerRunner::processRunning,
-                clientManager, [clientManager, host](Utils::Port port) {
-            clientManager->setTcpConnection(host, port);
-            clientManager->connectToTcpServer();
-        });
-    }
     connect(clientManager, &QmlProfilerClientManager::connectionFailed,
             runWorker, [this, clientManager, runWorker]() {
         QMessageBox *infoBox = new QMessageBox(ICore::mainWindow());
@@ -873,6 +854,11 @@ void QmlProfilerTool::showNonmodalWarning(const QString &warningMsg)
     noExecWarning->show();
 }
 
+QmlProfilerClientManager *QmlProfilerTool::clientManager()
+{
+    return s_instance->d->m_profilerConnections;
+}
+
 void QmlProfilerTool::profilerStateChanged()
 {
     switch (d->m_profilerState->currentState()) {
diff --git a/src/plugins/qmlprofiler/qmlprofilertool.h b/src/plugins/qmlprofiler/qmlprofilertool.h
index aeffca178b7a696d90e9d5f5d1a188b76da2581c..17ecd0c80615bc5b8be332e21b93b5b713d7b18e 100644
--- a/src/plugins/qmlprofiler/qmlprofilertool.h
+++ b/src/plugins/qmlprofiler/qmlprofilertool.h
@@ -29,11 +29,8 @@
 #include "qmlprofilerconstants.h"
 #include "qmlprofilereventtypes.h"
 
-#include <debugger/analyzer/analyzermanager.h>
-
-QT_BEGIN_NAMESPACE
-class QMessageBox;
-QT_END_NAMESPACE
+#include <QAction>
+#include <QObject>
 
 namespace QmlProfiler {
 
@@ -41,6 +38,8 @@ class QmlProfilerRunner;
 
 namespace Internal {
 
+class QmlProfilerClientManager;
+
 class QMLPROFILER_EXPORT QmlProfilerTool : public QObject
 {
     Q_OBJECT
@@ -51,8 +50,6 @@ public:
 
     static QmlProfilerTool *instance();
 
-    ProjectExplorer::RunWorker *createRunner(ProjectExplorer::RunControl *runControl,
-                                         ProjectExplorer::RunConfiguration *runConfiguration = 0);
     void finalizeRunControl(QmlProfilerRunner *runWorker);
 
     bool prepareTool();
@@ -68,6 +65,8 @@ public:
     static void logError(const QString &msg);
     static void showNonmodalWarning(const QString &warningMsg);
 
+    static QmlProfilerClientManager *clientManager();
+
 public slots:
     void profilerStateChanged();
     void clientRecordingChanged();
diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
index 48d316549265a394596cd6444bf9f5a84ff9e541..db97b33ef4d2572a0dbeffcea82c9d70d4f11259 100644
--- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
+++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.cpp
@@ -29,9 +29,14 @@
 
 #include <debugger/analyzer/analyzermanager.h>
 #include <debugger/analyzer/analyzerstartparameters.h>
+
+#include <projectexplorer/runnables.h>
+
 #include <QtTest>
 #include <QTcpServer>
 
+using namespace ProjectExplorer;
+
 namespace QmlProfiler {
 namespace Internal {
 
@@ -39,14 +44,14 @@ LocalQmlProfilerRunnerTest::LocalQmlProfilerRunnerTest(QObject *parent) : QObjec
 {
 }
 
-void LocalQmlProfilerRunnerTest::connectRunner(LocalQmlProfilerRunner *runner)
+void LocalQmlProfilerRunnerTest::connectRunner(QmlProfilerRunner *runner)
 {
-    connect(runner, &LocalQmlProfilerRunner::started, this, [this] {
+    connect(runner, &QmlProfilerRunner::localRunnerStarted, this, [this] {
         QVERIFY(!running);
         ++runCount;
         running = true;
     });
-    connect(runner, &LocalQmlProfilerRunner::stopped, this, [this] {
+    connect(runner, &QmlProfilerRunner::localRunnerStopped, this, [this] {
         QVERIFY(running);
         running = false;
     });
@@ -54,16 +59,17 @@ void LocalQmlProfilerRunnerTest::connectRunner(LocalQmlProfilerRunner *runner)
 
 void LocalQmlProfilerRunnerTest::testRunner()
 {
-    configuration.debuggee.executable = "\\-/|\\-/";
-    configuration.debuggee.environment = Utils::Environment::systemEnvironment();
+    debuggee.executable = "\\-/|\\-/";
+    debuggee.environment = Utils::Environment::systemEnvironment();
 
     // should not be used anywhere but cannot be empty
     configuration.socket = connection.analyzerSocket = QString("invalid");
 
     rc = new ProjectExplorer::RunControl(nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
-    auto worker = new QmlProfilerRunner(rc);
+    rc->setRunnable(debuggee);
     rc->setConnection(connection);
-    auto runner = new LocalQmlProfilerRunner(configuration, worker);
+    auto runner = new QmlProfilerRunner(rc);
+    runner->setLocalConfiguration(configuration);
     connectRunner(runner);
 
     rc->initiateStart();
@@ -75,17 +81,18 @@ void LocalQmlProfilerRunnerTest::testRunner1()
     QTRY_COMPARE_WITH_TIMEOUT(runCount, 1, 10000);
     QTRY_VERIFY_WITH_TIMEOUT(!running, 10000);
 
-    configuration.socket = connection.analyzerSocket = LocalQmlProfilerRunner::findFreeSocket();
-    configuration.debuggee.executable = QCoreApplication::applicationFilePath();
+    configuration.socket = connection.analyzerSocket = QmlProfilerRunner::findFreeSocket();
 
+    debuggee.executable = QCoreApplication::applicationFilePath();
     // comma is used to specify a test function. In this case, an invalid one.
-    configuration.debuggee.commandLineArguments = QString("-test QmlProfiler,");
+    debuggee.commandLineArguments = QString("-test QmlProfiler,");
 
     delete rc;
     rc = new ProjectExplorer::RunControl(nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
-    auto worker = new QmlProfilerRunner(rc);
+    rc->setRunnable(debuggee);
     rc->setConnection(connection);
-    auto runner = new LocalQmlProfilerRunner(configuration, worker);
+    auto runner = new QmlProfilerRunner(rc);
+    runner->setLocalConfiguration(configuration);
     connectRunner(runner);
     rc->initiateStart();
     QTimer::singleShot(0, this, &LocalQmlProfilerRunnerTest::testRunner2);
@@ -98,15 +105,16 @@ void LocalQmlProfilerRunnerTest::testRunner2()
 
     delete rc;
 
-    configuration.debuggee.commandLineArguments.clear();
+    debuggee.commandLineArguments.clear();
     configuration.socket.clear();
     connection.analyzerSocket.clear();
     configuration.port = connection.analyzerPort =
-            LocalQmlProfilerRunner::findFreePort(connection.analyzerHost);
+            QmlProfilerRunner::findFreePort(connection.analyzerHost);
     rc = new ProjectExplorer::RunControl(nullptr, ProjectExplorer::Constants::QML_PROFILER_RUN_MODE);
-    auto worker = new QmlProfilerRunner(rc);
+    rc->setRunnable(debuggee);
     rc->setConnection(connection);
-    auto runner = new LocalQmlProfilerRunner(configuration, worker);
+    auto runner = new QmlProfilerRunner(rc);
+    runner->setLocalConfiguration(configuration);
     connectRunner(runner);
     rc->initiateStart();
 
@@ -129,7 +137,7 @@ void LocalQmlProfilerRunnerTest::testRunner4()
 void LocalQmlProfilerRunnerTest::testFindFreePort()
 {
     QString host;
-    Utils::Port port = LocalQmlProfilerRunner::findFreePort(host);
+    Utils::Port port = QmlProfilerRunner::findFreePort(host);
     QVERIFY(port.isValid());
     QVERIFY(!host.isEmpty());
     QTcpServer server;
@@ -138,7 +146,7 @@ void LocalQmlProfilerRunnerTest::testFindFreePort()
 
 void LocalQmlProfilerRunnerTest::testFindFreeSocket()
 {
-    QString socket = LocalQmlProfilerRunner::findFreeSocket();
+    QString socket = QmlProfilerRunner::findFreeSocket();
     QVERIFY(!socket.isEmpty());
     QVERIFY(!QFile::exists(socket));
     QFile file(socket);
@@ -146,6 +154,5 @@ void LocalQmlProfilerRunnerTest::testFindFreeSocket()
     file.close();
 }
 
-
 } // namespace Internal
 } // namespace QmlProfiler
diff --git a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h
index de538e70a89e21ba93a1ebb1b115642333be37b1..69c1604bcec8a976f000d24c64f3eb069f322e3d 100644
--- a/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h
+++ b/src/plugins/qmlprofiler/tests/localqmlprofilerrunner_test.h
@@ -25,8 +25,8 @@
 
 #pragma once
 
-#include <qmlprofiler/localqmlprofilerrunner.h>
 #include <qmlprofiler/qmlprofilermodelmanager.h>
+#include <qmlprofiler/qmlprofilerruncontrol.h>
 #include <debugger/analyzer/analyzerstartparameters.h>
 
 namespace QmlProfiler {
@@ -44,7 +44,7 @@ private slots:
     void testFindFreeSocket();
 
 private:
-    void connectRunner(LocalQmlProfilerRunner *runner);
+    void connectRunner(QmlProfilerRunner *runner);
     void testRunner1();
     void testRunner2();
     void testRunner3();
@@ -53,8 +53,9 @@ private:
     bool running = false;
     int runCount = 0;
     ProjectExplorer::RunControl *rc = nullptr;
+    ProjectExplorer::StandardRunnable debuggee;
     Debugger::AnalyzerConnection connection;
-    LocalQmlProfilerRunner::Configuration configuration;
+    QmlProfilerRunner::Configuration configuration;
 };
 
 } // namespace Internal
diff --git a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
index fed9b53d32587e7b16becb4e261363fc2ac5854e..f898782ec1778e0efd1954dc22c59303568017a9 100644
--- a/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
+++ b/src/plugins/qmlprofiler/tests/qmlprofilerclientmanager_test.cpp
@@ -24,7 +24,7 @@
 ****************************************************************************/
 
 #include "qmlprofilerclientmanager_test.h"
-#include <qmlprofiler/localqmlprofilerrunner.h>
+#include <qmlprofiler/qmlprofilerruncontrol.h>
 #include <qmldebug/qpacketprotocol.h>
 #include <projectexplorer/applicationlauncher.h>
 
@@ -69,7 +69,7 @@ void QmlProfilerClientManagerTest::testConnectionFailure_data()
     QVarLengthArray<QmlProfilerStateManager *> stateManagers({nullptr, &stateManager});
 
     QString hostName;
-    Utils::Port port = LocalQmlProfilerRunner::findFreePort(hostName);
+    Utils::Port port = QmlProfilerRunner::findFreePort(hostName);
 
     QTest::addColumn<QString>("host");
     QVarLengthArray<QString> hosts({"", "/-/|\\-\\|/-", hostName});
@@ -78,8 +78,7 @@ void QmlProfilerClientManagerTest::testConnectionFailure_data()
     QVarLengthArray<Utils::Port> ports({Utils::Port(), Utils::Port(5), port});
 
     QTest::addColumn<QString>("socket");
-    QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-",
-                                      LocalQmlProfilerRunner::findFreeSocket()});
+    QVarLengthArray<QString> sockets({"", "/-/|\\-\\|/-", QmlProfilerRunner::findFreeSocket()});
 
     foreach (QmlProfilerModelManager *modelManager, modelManagers) {
         foreach (QmlProfilerStateManager *stateManager, stateManagers) {
@@ -174,7 +173,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveTcp()
     clientManager.setModelManager(&modelManager);
 
     QString hostName;
-    Utils::Port port = LocalQmlProfilerRunner::findFreePort(hostName);
+    Utils::Port port = QmlProfilerRunner::findFreePort(hostName);
 
     QTcpServer server;
     server.listen(QHostAddress(hostName), port.number());
@@ -203,7 +202,7 @@ void QmlProfilerClientManagerTest::testUnresponsiveLocal()
     clientManager.setProfilerStateManager(&stateManager);
     clientManager.setModelManager(&modelManager);
 
-    QString socketFile = LocalQmlProfilerRunner::findFreeSocket();
+    QString socketFile = QmlProfilerRunner::findFreeSocket();
     QLocalSocket socket;
     QSignalSpy connectionSpy(&socket, SIGNAL(connected()));
 
@@ -256,7 +255,7 @@ void QmlProfilerClientManagerTest::testResponsiveTcp()
     QFETCH(quint32, flushInterval);
 
     QString hostName;
-    Utils::Port port = LocalQmlProfilerRunner::findFreePort(hostName);
+    Utils::Port port = QmlProfilerRunner::findFreePort(hostName);
 
     QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
     QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
@@ -315,7 +314,7 @@ void QmlProfilerClientManagerTest::testResponsiveLocal()
 {
     QFETCH(quint32, flushInterval);
 
-    QString socketFile = LocalQmlProfilerRunner::findFreeSocket();
+    QString socketFile = QmlProfilerRunner::findFreeSocket();
 
     QSignalSpy openedSpy(&clientManager, SIGNAL(connectionOpened()));
     QSignalSpy closedSpy(&clientManager, SIGNAL(connectionClosed()));
@@ -381,7 +380,7 @@ void QmlProfilerClientManagerTest::testInvalidData()
     clientManager.setModelManager(&modelManager);
 
     QString hostName;
-    Utils::Port port = LocalQmlProfilerRunner::findFreePort(hostName);
+    Utils::Port port = QmlProfilerRunner::findFreePort(hostName);
 
     bool dataSent = false;
     QTcpServer server;
@@ -412,7 +411,7 @@ void QmlProfilerClientManagerTest::testInvalidData()
 
 void QmlProfilerClientManagerTest::testStopRecording()
 {
-    QString socketFile = LocalQmlProfilerRunner::findFreeSocket();
+    QString socketFile = QmlProfilerRunner::findFreeSocket();
 
     {
         QmlProfilerClientManager clientManager;