diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index ea91cd7..0e7de31 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -2117,6 +2117,12 @@ function menu_local_tasks($level = 0) {
     // Remove the depth, we are interested only in their relative placement.
     $tabs = array_values($tabs);
     $data['tabs'] = $tabs;
+    if (!empty($router_item['route_name'])) {
+      // Look for route-based tabs.
+      $manager = Drupal::service('plugin.manager.system.menu_local_task');
+      $local_tasks = $manager->getLocalTasksForRoute($router_item['route_name']);
+      debug(count($local_tasks), NULL, 1);
+    }
 
     // Allow modules to dynamically add further tasks.
     $module_handler = Drupal::moduleHandler();
diff --git a/core/modules/system/lib/Drupal/system/Annotation/MenuLocalTaskPlugin.php b/core/modules/system/lib/Drupal/system/Annotation/MenuLocalTaskPlugin.php
new file mode 100644
index 0000000..42a66e3
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Annotation/MenuLocalTaskPlugin.php
@@ -0,0 +1,60 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Annotation\MenuLocalTaskPlugin.
+ */
+
+namespace Drupal\system\Annotation;
+
+use Drupal\Component\Annotation\Plugin;
+
+/**
+ * Defines a MenuLocalTaskPlugin type annotation object.
+ *
+ * @Annotation
+ */
+class MenuLocalTaskPlugin extends Plugin {
+
+  /**
+   * The ID.
+   *
+   * @var string
+   */
+  public $id;
+
+  /**
+   * The static title for the local action.
+   *
+   * @var string
+   */
+  public $title;
+
+  /**
+   * The route name.
+   *
+   * @var string
+   */
+  public $route_name;
+
+  /**
+   * The plugin ID of the root tab.
+   *
+   * @var array
+   */
+  public $tab_root_id;
+
+  /**
+   * The plugin ID of the parent tab (or NULL for a top-level tab).
+   *
+   * @var array
+   */
+  public $tab_parent_id;
+  
+  /**
+   * The weight of the tab.
+   *
+   * @var array
+   */
+  public $weight;
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/MenuLocalTaskBase.php b/core/modules/system/lib/Drupal/system/Plugin/MenuLocalTaskBase.php
new file mode 100644
index 0000000..d3a1810
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/MenuLocalTaskBase.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\MenuLocalActionBase.
+ */
+
+namespace Drupal\system\Plugin;
+
+use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
+use Drupal\Core\Plugin\ContainerFactoryPluginBase;
+use Drupal\system\Plugin\MenuLocalTaskInterface;
+use Drupal\Core\StringTranslation\Translator\TranslatorInterface;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Provides defaults and base methods for menu local action plugins.
+ *
+ * @todo This class needs more documetation and/or @see references.
+ */
+abstract class MenuLocalTaskBase extends ContainerFactoryPluginBase implements MenuLocalTaskInterface {
+  /**
+   * String translation object.
+   *
+   * @var \Drupal\Core\StringTranslation\Translator\TranslatorInterface
+   */
+  protected $t;
+
+  /**
+   * URL generator object.
+   *
+   * @var \Symfony\Component\Routing\Generator\UrlGeneratorInterface
+   */
+  protected $generator;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static(
+      $container->get('string_translation'),
+      $container->get('url_generator'),
+      $configuration,
+      $plugin_id,
+      $plugin_definition
+    );
+  }
+
+  public function __construct(TranslatorInterface $string_translation,  UrlGeneratorInterface $generator, array $configuration, $plugin_id, array $plugin_definition) {
+    // This is available for subclasses that need to translate
+    // a dynamic title.
+    $this->t = $string_translation;
+    $this->generator = $generator;
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRouteName() {
+    return $this->pluginDefinition['route_name'];
+  }
+
+  /**
+   * Return the title to be shown for this local task.
+   */
+  public function getTitle() {
+    // Subclasses may pull in the request or specific attributes as parameters.
+    return $this->pluginDefinition['title'];
+  }
+
+  /**
+   * Retun the Drupal path corresponding to the route.
+   */
+  public function getPath() {
+    // Subclasses may set a request into the generator or
+    // use any desired method to generate the path.
+    $path = $this->generator->generate($this->getRouteName());
+    // In order to get the Drupal path the base URL has
+    // to be stripped off.
+    $base_url = $this->generator->getContext()->getBaseUrl();
+    if (!empty($base_url) && strpos($path, $base_url) === 0) {
+      $path = substr($path, strlen($base_url));
+    }
+    return trim($path, '/');
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/MenuLocalTaskInterface.php b/core/modules/system/lib/Drupal/system/Plugin/MenuLocalTaskInterface.php
new file mode 100644
index 0000000..eef0f42
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/MenuLocalTaskInterface.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\MenuLocalActionInterface.
+ */
+
+namespace Drupal\system\Plugin;
+
+/**
+ * Defines an interface for menu local actions.
+ */
+interface MenuLocalTaskInterface {
+
+  /**
+   * Get the route name from the settings.
+   *
+   * @return string
+   *   The name of the route this action links to.
+   */
+  public function getRouteName();
+}
diff --git a/core/modules/system/lib/Drupal/system/Plugin/Type/MenuLocalTaskManager.php b/core/modules/system/lib/Drupal/system/Plugin/Type/MenuLocalTaskManager.php
new file mode 100644
index 0000000..733f0f4
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Plugin/Type/MenuLocalTaskManager.php
@@ -0,0 +1,139 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\system\Plugin\Type\MenuLocalTaskManager.
+ */
+
+namespace Drupal\system\Plugin\Type;
+
+use Drupal\Core\Controller\ControllerResolver;
+use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
+use Drupal\Core\Plugin\Discovery\AlterDecorator;
+use Drupal\Core\Plugin\Discovery\CacheDecorator;
+use Drupal\Core\Plugin\DefaultPluginManager;
+use Drupal\system\Plugin\MenuLocalActionInterface;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Manages discovery and instantiation of menu local task plugins.
+ *
+ * This manager finds plugs the put a local task (usuall a tab) on Drupal
+ * pages. Derivatives are supported for modules that wish to generate
+ * new tabs not in code.
+ */
+class MenuLocalTaskManager extends DefaultPluginManager {
+
+  /**
+   * A controller resolver object.
+   *
+   * @var \Drupal\Core\Controller\ControllerResolver
+   */
+  protected $controllerResolver;
+
+  /**
+   * A request object.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
+   * The plugin instances.
+   *
+   * @var array
+   */
+  protected $instances = array();
+
+  /**
+   * The plugin info for all plugins with a common root.
+   *
+   * @var array
+   */
+  protected $tasks = array();
+
+  /**
+   * Constructs a \Drupal\system\Plugin\Type\MenuLocalActionManager object.
+   *
+   * @param \Traversable $namespaces
+   *   An object that implements \Traversable which contains the root paths
+   *   keyed by the corresponding namespace to look for plugin implementations,
+   * @param \Drupal\Core\Controller\ControllerResolver $controller_resolver
+   *   An object to use in introspecting route methods.
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object to use for building titles and paths for plugin instances.
+   */
+  public function __construct(\Traversable $namespaces, ControllerResolver $controller_resolver, Request $request) {
+    $annotation_namespaces = array('Drupal\system\Annotation' => $namespaces['Drupal\system']);
+    parent::__construct('Menu', $namespaces, $annotation_namespaces, 'Drupal\system\Annotation\MenuLocalTaskPlugin');
+    $this->controllerResolver = $controller_resolver;
+    $this->request = $request;
+  }
+
+  public function getTitle(MenuLocalTaskInterface $local_task) {
+    $controller = array($local_task, 'getTitle');
+    $arguments = $this->controllerResolver->getArguments($this->request, $controller);
+
+    if (is_callable($controller)) {
+      return call_user_func_array($controller, $arguments);
+    }
+    // @todo What to do if it is not callable.
+    return '';
+  }
+
+  public function getPath(MenuLocalTaskInterface $local_task) {
+    $controller = array($local_task, 'getPath');
+    $arguments = $this->controllerResolver->getArguments($this->request, $controller);
+    if (is_callable($controller)) {
+      return call_user_func_array($controller, $arguments);
+    }
+    // @todo What to do if it is not callable.
+    return '';
+  }
+
+  /**
+   * Find all local actions that appear on a named route.
+   *
+   * @param string $route_name
+   *
+   * @return array
+   *   Objects implementing MenuLocalActionInterface that appear on the route path.
+   */
+  public function getLocalTasksForRoute($route_name) {
+
+    if (!isset($this->instances[$route_name])) {
+      $this->instances[$route_name] = array();
+      $this->tasks[$route_name] = array();
+      // @todo - optimize this lookup by compiling or caching.
+      $definitions = $this->getDefinitions();
+      foreach ($definitions as $plugin_id => $task_info) {
+        // We build the hierarchy by finding all tabs that should
+        // appear on the current route.
+        $tab_root_ids = array();
+        $parents = array();
+        if ($route_name == $task_info['route_name']) {
+          $this->tasks[$route_name][$plugin_id] = $task_info;
+          $tab_root_ids[$task_info['tab_root_id']] = TRUE;
+          // Tabs that link to the current route are viable parents
+          // and their children should be visible also.
+          $parents[$plugin_id] = TRUE;
+        }
+
+        if ($tab_root_ids) {
+          // Find all the plugins with the same root and that are at the top
+          // level or that have a visible parent.
+          foreach ($definitions  as $plugin_id => $task_info) {
+            if (!empty($tab_root_ids[$task_info['tab_root_id']]) && (empty($task_info['tab_parent_id']) || !empty($parents[$task_info['tab_parent_id']]))) {
+              $this->tasks[$route_name][$plugin_id] = $task_info;
+            }
+          }
+        }
+      }
+    }
+    debug($this->tasks[$route_name], NULL,1);
+    // $plugin = $this->createInstance($plugin_id);
+    // $this->instances[$route_name][$plugin_id] = $plugin;
+    return $this->instances[$route_name];
+  }
+}
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 6aefa00..5c85885 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -6,6 +6,9 @@ services:
   plugin.manager.system.plugin_ui:
     class: Drupal\system\Plugin\Type\PluginUIManager
     arguments: ['@container.namespaces']
+  plugin.manager.system.menu_local_task:
+    class: Drupal\system\Plugin\Type\MenuLocalTaskManager
+    arguments: ['@container.namespaces', '@controller_resolver', '@request']
   system.manager:
     class: Drupal\system\SystemManager
     arguments: ['@module_handler', '@database']
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsListTask.php b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsListTask.php
new file mode 100644
index 0000000..f0ac3df
--- /dev/null
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsListTask.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\views_ui\Plugin\Menu\AddViewLocalAction.
+ */
+
+namespace Drupal\views_ui\Plugin\Menu;
+
+use Drupal\Core\Annotation\Translation;
+use Drupal\system\Plugin\MenuLocalTaskBase;
+use Drupal\system\Annotation\MenuLocalTaskPlugin;
+
+
+/**
+ * @MenuLocalTaskPlugin(
+ *   id = "views_ui_list_tab",
+ *   route_name = "views_ui.list",
+ *   title = @Translation("List"),
+ *   tab_root_id = "views_ui_list_tab"
+ * )
+ */
+class ViewsListTask extends MenuLocalTaskBase {
+
+}
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsAdvancedTask.php b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsAdvancedTask.php
new file mode 100644
index 0000000..59c09a7
--- /dev/null
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsAdvancedTask.php
@@ -0,0 +1,26 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\views_ui\Plugin\Menu\ViewsSettingsBasicTask.
+ */
+
+namespace Drupal\views_ui\Plugin\Menu;
+
+use Drupal\Core\Annotation\Translation;
+use Drupal\system\Plugin\MenuLocalTaskBase;
+use Drupal\system\Annotation\MenuLocalTaskPlugin;
+
+
+/**
+ * @MenuLocalTaskPlugin(
+ *   id = "views_ui_settings_advanced_tab",
+ *   route_name = "views_ui.settings.advanced",
+ *   title = @Translation("Advanced"),
+ *   tab_root_id = "views_ui_list_tab",
+ *   tab_parent_id = "views_ui_settings_tab",
+ *   weight = "10"
+ * )
+ */
+class ViewsSettingsAdvancedTask extends MenuLocalTaskBase {
+
+}
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsBasicTask.php b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsBasicTask.php
new file mode 100644
index 0000000..bf0eacf
--- /dev/null
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsBasicTask.php
@@ -0,0 +1,25 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\views_ui\Plugin\Menu\ViewsSettingsBasicTask.
+ */
+
+namespace Drupal\views_ui\Plugin\Menu;
+
+use Drupal\Core\Annotation\Translation;
+use Drupal\system\Plugin\MenuLocalTaskBase;
+use Drupal\system\Annotation\MenuLocalTaskPlugin;
+
+
+/**
+ * @MenuLocalTaskPlugin(
+ *   id = "views_ui_settings_basic_tab",
+ *   route_name = "views_ui.settings.basic",
+ *   title = @Translation("Basic"),
+ *   tab_root_id = "views_ui_list_tab",
+ *   tab_parent_id = "views_ui_settings_tab"
+ * )
+ */
+class ViewsSettingsBasicTask extends MenuLocalTaskBase {
+
+}
diff --git a/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsTask.php b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsTask.php
new file mode 100644
index 0000000..498aa72
--- /dev/null
+++ b/core/modules/views_ui/lib/Drupal/views_ui/Plugin/Menu/ViewsSettingsTask.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\views_ui\Plugin\Menu\ViewsSettingsTask.
+ */
+
+namespace Drupal\views_ui\Plugin\Menu;
+
+use Drupal\Core\Annotation\Translation;
+use Drupal\system\Plugin\MenuLocalTaskBase;
+use Drupal\system\Annotation\MenuLocalTaskPlugin;
+
+
+/**
+ * @MenuLocalTaskPlugin(
+ *   id = "views_ui_settings_tab",
+ *   route_name = "views_ui.settings.basic",
+ *   title = @Translation("Settings"),
+ *   tab_root_id = "views_ui_list_tab"
+ * )
+ */
+class ViewsSettingsTask extends MenuLocalTaskBase {
+
+}
