diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php b/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php
index 9a5cbde..0019dff 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Form/SettingsForm.php
@@ -7,9 +7,12 @@
 
 namespace Drupal\aggregator\Form;
 
-use Drupal\system\SystemConfigFormBase;
-use Drupal\Core\Config\ConfigFactory;
 use Drupal\aggregator\Plugin\AggregatorPluginManager;
+use Drupal\Component\Utility\String;
+use Drupal\Core\Form\FormInterface;
+use Drupal\Core\Config\ConfigFactory;
+use Drupal\Core\StringTranslation\TranslationManager;
+use Drupal\system\SystemConfigFormBase;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -18,6 +21,13 @@
 class SettingsForm extends SystemConfigFormBase {
 
   /**
+   * The configuration object factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
+   */
+  protected $configFactory;
+
+  /**
    * The aggregator plugin managers.
    *
    * @var array
@@ -25,6 +35,13 @@ class SettingsForm extends SystemConfigFormBase {
   protected $managers = array();
 
   /**
+   * The instantiated plugin instances.
+   *
+   * @var array
+   */
+  protected $instances = array();
+
+  /**
    * The aggregator plugin definitions.
    *
    * @var array
@@ -40,6 +57,8 @@ class SettingsForm extends SystemConfigFormBase {
    *
    * @param \Drupal\Core\Config\ConfigFactory $config_factory
    *   The factory for configuration objects.
+   * @param \Drupal\Core\StringTranslation\TranslationManager $string_translation
+   *   The string translation service.
    * @param \Drupal\aggregator\Plugin\AggregatorPluginManager $fetcher_manager
    *   The aggregator fetcher plugin manager.
    * @param \Drupal\aggregator\Plugin\AggregatorPluginManager $parser_manager
@@ -47,8 +66,9 @@ class SettingsForm extends SystemConfigFormBase {
    * @param \Drupal\aggregator\Plugin\AggregatorPluginManager $processor_manager
    *   The aggregator processor plugin manager.
    */
-  public function __construct(ConfigFactory $config_factory, AggregatorPluginManager $fetcher_manager, AggregatorPluginManager $parser_manager, AggregatorPluginManager $processor_manager) {
+  public function __construct(ConfigFactory $config_factory, TranslationManager $string_translation, AggregatorPluginManager $fetcher_manager, AggregatorPluginManager $parser_manager, AggregatorPluginManager $processor_manager) {
     $this->configFactory = $config_factory;
+    $this->translation = $string_translation;
     $this->managers = array(
       'fetcher' => $fetcher_manager,
       'parser' => $parser_manager,
@@ -57,17 +77,18 @@ public function __construct(ConfigFactory $config_factory, AggregatorPluginManag
     // Get all available fetcher, parser and processor definitions.
     foreach (array('fetcher', 'parser', 'processor') as $type) {
       foreach ($this->managers[$type]->getDefinitions() as $id => $definition) {
-        $this->definitions[$type][$id] = format_string('@title <span class="description">@description</span>', array('@title' => $definition['title'], '@description' => $definition['description']));
+        $this->definitions[$type][$id] = String::format('@title <span class="description">@description</span>', array('@title' => $definition['title'], '@description' => $definition['description']));
       }
     }
   }
 
   /**
-   * Implements \Drupal\Core\ControllerInterface::create().
+   * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('config.factory'),
+      $container->get('string_translation'),
       $container->get('plugin.manager.aggregator.fetcher'),
       $container->get('plugin.manager.aggregator.parser'),
       $container->get('plugin.manager.aggregator.processor')
@@ -75,14 +96,14 @@ public static function create(ContainerInterface $container) {
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::getFormID().
+   * {@inheritdoc}
    */
   public function getFormID() {
     return 'aggregator_admin_form';
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::buildForm().
+   * {@inheritdoc}
    */
   public function buildForm(array $form, array &$form_state) {
     $config = $this->configFactory->get('aggregator.settings');
@@ -90,11 +111,11 @@ public function buildForm(array $form, array &$form_state) {
     // Global aggregator settings.
     $form['aggregator_allowed_html_tags'] = array(
       '#type' => 'textfield',
-      '#title' => t('Allowed HTML tags'),
+      '#title' => $this->translation->translate('Allowed HTML tags'),
       '#size' => 80,
       '#maxlength' => 255,
       '#default_value' => $config->get('items.allowed_html'),
-      '#description' => t('A space-separated list of HTML tags allowed in the content of feed items. Disallowed tags are stripped from the content.'),
+      '#description' => $this->translation->translate('A space-separated list of HTML tags allowed in the content of feed items. Disallowed tags are stripped from the content.'),
     );
 
     // Only show basic configuration if there are actually options.
@@ -102,8 +123,8 @@ public function buildForm(array $form, array &$form_state) {
     if (count($this->definitions['fetcher']) > 1) {
       $basic_conf['aggregator_fetcher'] = array(
         '#type' => 'radios',
-        '#title' => t('Fetcher'),
-        '#description' => t('Fetchers download data from an external source. Choose a fetcher suitable for the external source you would like to download from.'),
+        '#title' => $this->translation->translate('Fetcher'),
+        '#description' => $this->translation->translate('Fetchers download data from an external source. Choose a fetcher suitable for the external source you would like to download from.'),
         '#options' => $this->definitions['fetcher'],
         '#default_value' => $config->get('fetcher'),
       );
@@ -111,8 +132,8 @@ public function buildForm(array $form, array &$form_state) {
     if (count($this->definitions['parser']) > 1) {
       $basic_conf['aggregator_parser'] = array(
         '#type' => 'radios',
-        '#title' => t('Parser'),
-        '#description' => t('Parsers transform downloaded data into standard structures. Choose a parser suitable for the type of feeds you would like to aggregate.'),
+        '#title' => $this->translation->translate('Parser'),
+        '#description' => $this->translation->translate('Parsers transform downloaded data into standard structures. Choose a parser suitable for the type of feeds you would like to aggregate.'),
         '#options' => $this->definitions['parser'],
         '#default_value' => $config->get('parser'),
       );
@@ -120,8 +141,8 @@ public function buildForm(array $form, array &$form_state) {
     if (count($this->definitions['processor']) > 1) {
       $basic_conf['aggregator_processors'] = array(
         '#type' => 'checkboxes',
-        '#title' => t('Processors'),
-        '#description' => t('Processors act on parsed feed data, for example they store feed items. Choose the processors suitable for your task.'),
+        '#title' => $this->translation->translate('Processors'),
+        '#description' => $this->translation->translate('Processors act on parsed feed data, for example they store feed items. Choose the processors suitable for your task.'),
         '#options' => $this->definitions['processor'],
         '#default_value' => $config->get('processors'),
       );
@@ -129,35 +150,70 @@ public function buildForm(array $form, array &$form_state) {
     if (count($basic_conf)) {
       $form['basic_conf'] = array(
         '#type' => 'details',
-        '#title' => t('Basic configuration'),
-        '#description' => t('For most aggregation tasks, the default settings are fine.'),
+        '#title' => $this->translation->translate('Basic configuration'),
+        '#description' => $this->translation->translate('For most aggregation tasks, the default settings are fine.'),
         '#collapsed' => FALSE,
       );
       $form['basic_conf'] += $basic_conf;
     }
 
+    // Call buildForm() on the active fetcher and parser.
+    foreach (array('fetcher', 'parser') as $type) {
+      $active = $config->get($type);
+      if (array_key_exists($active, $this->definitions[$type])) {
+        $instance = $this->managers[$type]->createInstance($active);
+        if ($instance instanceof FormInterface) {
+          $form = $instance->buildForm($form, $form_state);
+          // Store the instance for validate and submit handlers.
+          $this->instances[] = $instance;
+        }
+      }
+    }
+
     // Implementing processor plugins will expect an array at $form['processors'].
     $form['processors'] = array();
-    // Call settingsForm() for each active processor.
+    // Call buildForm() for each active processor.
     foreach ($this->definitions['processor'] as $id => $definition) {
       if (in_array($id, $config->get('processors'))) {
-        $form = $this->managers['processor']->createInstance($id)->settingsForm($form, $form_state);
+        $instance = $this->managers['processor']->createInstance($id);
+        if ($instance instanceof FormInterface) {
+          $form = $instance->buildForm($form, $form_state);
+          // Store the instance for validate and submit handlers.
+          $this->instances[] = $instance;
+        }
       }
     }
-    return parent::buildForm($form, $form_state);
+
+    $form['actions']['#type'] = 'actions';
+    $form['actions']['submit'] = array(
+      '#type' => 'submit',
+      '#value' => $this->translation->translate('Save configuration'),
+      '#button_type' => 'primary',
+    );
+    $form['#theme'] = 'system_config_form';
+    return $form;
   }
 
   /**
-   * Implements \Drupal\Core\Form\FormInterface::submitForm().
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+    parent::validateForm($form, $form_state);
+    // Let active plugins validate their settings.
+    foreach ($this->instances as $instance) {
+      $instance->validateForm($form, $form_state);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function submitForm(array &$form, array &$form_state) {
     parent::submitForm($form, $form_state);
     $config = $this->configFactory->get('aggregator.settings');
-    // Let active processors save their settings.
-    foreach ($this->definitions['processor'] as $id => $definition) {
-      if (in_array($id, $config->get('processors'))) {
-        $this->managers['processor']->createInstance($id)->settingsSubmit($form, $form_state);
-      }
+    // Let active plugins save their settings.
+    foreach ($this->instances as $instance) {
+      $instance->submitForm($form, $form_state);
     }
 
     $config->set('items.allowed_html', $form_state['values']['aggregator_allowed_html_tags']);
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php
index 12e41cd..0c1c802 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginManager.php
@@ -8,10 +8,10 @@
 namespace Drupal\aggregator\Plugin;
 
 use Drupal\Component\Plugin\PluginManagerBase;
-use Drupal\Component\Plugin\Factory\DefaultFactory;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery;
 use Drupal\Core\Plugin\Discovery\CacheDecorator;
+use Drupal\Core\Plugin\Factory\ContainerFactory;
 
 /**
  * Manages aggregator plugins.
@@ -40,6 +40,7 @@ public function __construct($type, \Traversable $namespaces) {
 
     $this->discovery = new AnnotatedClassDiscovery("aggregator/$type", $namespaces, $annotation_namespaces, $type_annotations[$type]);
     $this->discovery = new CacheDecorator($this->discovery, "aggregator_$type:" . language(Language::TYPE_INTERFACE)->langcode);
-    $this->factory = new DefaultFactory($this->discovery);
+    $this->factory = new ContainerFactory($this);
   }
+
 }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginSettingsBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginSettingsBase.php
new file mode 100644
index 0000000..d4dcf52
--- /dev/null
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/AggregatorPluginSettingsBase.php
@@ -0,0 +1,31 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\aggregator\Plugin\AggregatorPluginSettingsBase.
+ */
+
+namespace Drupal\aggregator\Plugin;
+
+use Drupal\Core\Plugin\ContainerFactoryPluginBase;
+use Drupal\Core\Form\FormInterface;
+
+/**
+ * Base class for aggregator's plugin implementations.
+ */
+abstract class AggregatorPluginSettingsBase extends ContainerFactoryPluginBase implements FormInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'aggregator_admin_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, array &$form_state) {
+  }
+
+}
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php
index b670383..844abb0 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/ProcessorInterface.php
@@ -21,31 +21,6 @@
 interface ProcessorInterface {
 
   /**
-   * Returns a form to configure settings for the processor.
-   *
-   * @param array $form
-   *   The form definition array where the settings form is being included in.
-   * @param array $form_state
-   *   An associative array containing the current state of the form.
-   *
-   * @return array
-   *   The form elements for the processor settings.
-   */
-  public function settingsForm(array $form, array &$form_state);
-
-  /**
-   * Adds processor specific submission handling for the configuration form.
-   *
-   * @param array $form
-   *   The form definition array where the settings form is being included in.
-   * @param array $form_state
-   *   An associative array containing the current state of the form.
-   *
-   * @see \Drupal\aggregator\Plugin\ProcessorInterface::settingsForm()
-   */
-  public function settingsSubmit(array $form, array &$form_state);
-
-  /**
    * Processes feed data.
    *
    * @param \Drupal\aggregator\Plugin\Core\Entity\Feed $feed
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
index e98411e..cd16869 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/fetcher/DefaultFetcher.php
@@ -11,8 +11,10 @@
 use Drupal\aggregator\Plugin\Core\Entity\Feed;
 use Drupal\aggregator\Annotation\AggregatorFetcher;
 use Drupal\Core\Annotation\Translation;
+use Guzzle\Http\Client;
 use Guzzle\Http\Exception\BadResponseException;
 use Guzzle\Http\Exception\RequestException;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines a default fetcher implementation.
@@ -28,11 +30,34 @@
 class DefaultFetcher implements FetcherInterface {
 
   /**
-   * Implements \Drupal\aggregator\Plugin\FetcherInterface::fetch().
+   * The HTTP client to fetch the feed data with.
+   *
+   * @var \Guzzle\Http\Client
+   */
+  protected $httpClient;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($container->get('http_default_client'));
+  }
+
+  /**
+   * Constructs a DefaultFetcher object.
+   *
+   * @param \Guzzle\Http\Client $http_client
+   *   A Guzzle client object.
+   */
+  public function __construct(Client $http_client) {
+    $this->httpClient = $http_client;
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function fetch(Feed $feed) {
-    // @todo: Inject the http client.
-    $request = \Drupal::httpClient()->get($feed->url->value);
+    $request = $this->httpClient->get($feed->url->value);
     $feed->source_string = FALSE;
 
     // Generate conditional GET headers.
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php
index eab6e9b..bf70ae9 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/parser/DefaultParser.php
@@ -68,7 +68,14 @@ class DefaultParser implements ParserInterface {
   protected $item;
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ParserInterface::parse().
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static();
+  }
+
+  /**
+   * {@inheritdoc}
    */
   public function parse(Feed $feed) {
     // Filter the input data.
@@ -90,7 +97,7 @@ public function parse(Feed $feed) {
       $feed->image->value = !empty($image['url']) ? $image['url'] : '';
 
       // Clear the page and block caches.
-      cache_invalidate_tags(array('content' => TRUE));
+      Cache::invalidateTags(array('content' => TRUE));
 
       return TRUE;
     }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php
index 6b160ff..a3649b6 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Plugin/aggregator/processor/DefaultProcessor.php
@@ -7,12 +7,14 @@
 
 namespace Drupal\aggregator\Plugin\aggregator\processor;
 
-use Drupal\Component\Plugin\PluginBase;
-use Drupal\aggregator\Plugin\ProcessorInterface;
-use Drupal\aggregator\Plugin\Core\Entity\Feed;
-use Drupal\aggregator\Annotation\AggregatorProcessor;
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Database\Database;
+use Drupal\Core\Config\ConfigFactory;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
+use Drupal\aggregator\Plugin\ProcessorInterface;
+use Drupal\aggregator\Plugin\Core\Entity\Feed;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines a default processor implementation.
@@ -25,13 +27,44 @@
  *   description = @Translation("Creates lightweight records from feed items.")
  * )
  */
-class DefaultProcessor extends PluginBase implements ProcessorInterface {
+class DefaultProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface {
+
+  /**
+   * Contains the configuration object factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
+   */
+  protected $configFactory;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('config.factory'));
+  }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsForm().
+   * Constructs a DefaultProcessor object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Config\ConfigFactory $config
+   *   The configuration factory object.
    */
-  public function settingsForm(array $form, array &$form_state) {
-    $config = config('aggregator.settings');
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigFactory $config) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $config = $this->configFactory->get('aggregator.settings');
     $processors = $config->get('processors');
     $info = $this->getDefinition();
     $items = drupal_map_assoc(array(3, 5, 10, 15, 20, 25), array($this, 'formatItems'));
@@ -84,10 +117,10 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsSubmit().
+   * {@inheritdoc}
    */
-  public function settingsSubmit(array $form, array &$form_state) {
-    $config = config('aggregator.settings');
+  public function submitForm(array $form, array &$form_state) {
+    $config = $this->configFactory->get('aggregator.settings');
     $config->set('items.expire', $form_state['values']['aggregator_clear'])
       ->set('items.teaser_length', $form_state['values']['aggregator_teaser_length'])
       ->set('source.list_max', $form_state['values']['aggregator_summary_items'])
@@ -96,7 +129,7 @@ public function settingsSubmit(array $form, array &$form_state) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::process().
+   * {@inheritdoc}
    */
   public function process(Feed $feed) {
     if (!is_array($feed->items)) {
@@ -147,7 +180,7 @@ public function process(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::remove().
+   * {@inheritdoc}
    */
   public function remove(Feed $feed) {
     $iids = Database::getConnection()->query('SELECT iid FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->id()))->fetchCol();
@@ -159,12 +192,10 @@ public function remove(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess().
-   *
-   * Expires items from a feed depending on expiration settings.
+   * {@inheritdoc}
    */
   public function postProcess(Feed $feed) {
-    $aggregator_clear = config('aggregator.settings')->get('items.expire');
+    $aggregator_clear = $this->configFactory->get('aggregator.settings')->get('items.expire');
 
     if ($aggregator_clear != AGGREGATOR_CLEAR_NEVER) {
       // Remove all items that are older than flush item timer.
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
index 0452453..6450975 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
@@ -336,17 +336,17 @@ function getEmptyOpml() {
   }
 
   function getRSS091Sample() {
-    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_rss091.xml';
+    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_rss091.xml';
   }
 
   function getAtomSample() {
     // The content of this sample ATOM feed is based directly off of the
     // example provided in RFC 4287.
-    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_atom.xml';
+    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_atom.xml';
   }
 
   function getHtmlEntitiesSample() {
-    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/aggregator_test_title_entities.xml';
+    return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/tests/modules/aggregator_test/aggregator_test_title_entities.xml';
   }
 
   /**
diff --git a/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php b/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php
new file mode 100644
index 0000000..a2d8adf
--- /dev/null
+++ b/core/modules/aggregator/tests/Drupal/aggregator/Tests/Plugin/AggregatorPluginSettingsBaseTest.php
@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\aggregator\Tests\Plugin\AggregatorPluginSettingsBaseTest
+ */
+
+namespace Drupal\aggregator\Tests\Plugin;
+
+use Drupal\aggregator\Form\SettingsForm;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests plugins settings on aggregator plugins.
+ *
+ * @group Aggregator
+ */
+class AggregatorPluginSettingsBaseTest extends UnitTestCase {
+
+  /**
+   * The aggregator settings form object under test.
+   *
+   * @var \Drupal\aggregator\Form\SettingsForm
+   */
+  protected $settingsForm;
+
+  /**
+   * The stubbed config factory object.
+   *
+   * @var \PHPUnit_Framework_MockObject_MockBuilder
+   */
+  protected $configFactory;
+
+  /**
+   * The stubbed aggregator plugin managers array.
+   *
+   * @var array
+   */
+  protected $managers;
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Aggregator plugin settings tests',
+      'description' => 'Test settings configuration of individual aggregator plugins.',
+      'group' => 'Aggregator',
+    );
+  }
+
+  public function setUp() {
+    $this->configFactory = $this->getConfigFactoryStub(
+      array(
+        'aggregator.settings' => array(
+          'processors' => array('aggregator_test'),
+        ),
+        'aggregator_test.settings' => array(),
+      )
+    );
+    foreach (array('fetcher', 'parser', 'processor') as $type) {
+      $this->managers[$type] = $this->getMockBuilder('Drupal\aggregator\Plugin\AggregatorPluginManager')
+        ->disableOriginalConstructor()
+        ->getMock();
+      $this->managers[$type]->expects($this->once())
+        ->method('getDefinitions')
+        ->will($this->returnValue(array('aggregator_test' => array('title' => '', 'description' => ''))));
+    }
+
+    $this->settingsForm = new SettingsForm(
+      $this->configFactory,
+      $this->getStringTranslationStub(),
+      $this->managers['fetcher'],
+      $this->managers['parser'],
+      $this->managers['processor']
+    );
+  }
+
+  /**
+   * Test for AggregatorPluginSettingsBase.
+   *
+   * Ensure that the settings form calls build, validate and submit methods on
+   * plugins that extend AggregatorPluginSettingsBase.
+   */
+  public function testSettingsForm() {
+    $form_state = array();
+    $test_processor = $this->getMock(
+      'Drupal\aggregator_test\Plugin\aggregator\processor\TestProcessor',
+      array('buildForm', 'validateForm', 'submitForm'),
+      array(array(), 'aggregator_test', array(), $this->configFactory)
+    );
+    $test_processor->expects($this->at(0))
+      ->method('buildForm')
+      ->with($this->anything(), $form_state)
+      ->will($this->returnArgument(0));
+    $test_processor->expects($this->at(1))
+      ->method('validateForm')
+      ->with($this->anything(), $form_state);
+    // @todo Restore when we get rid of drupal_set_message().
+    /*$test_processor->expects($this->at(2))
+      ->method('submitForm')
+      ->with($this->anything(), $form_state);*/
+    $this->managers['processor']->expects($this->once())
+      ->method('createInstance')
+      ->with($this->equalTo('aggregator_test'))
+      ->will($this->returnValue($test_processor));
+    $form = $this->settingsForm->buildForm(array(), $form_state);
+    $this->settingsForm->validateForm($form, $form_state);
+    // @todo Restore when we get rid of drupal_set_message().
+    //$this->settingsForm->submitForm($form, $form_state);
+  }
+
+}
diff --git a/core/modules/aggregator/tests/aggregator_test.info.yml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.info.yml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test.info.yml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.info.yml
diff --git a/core/modules/aggregator/tests/aggregator_test.module b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.module
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test.module
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test.module
diff --git a/core/modules/aggregator/tests/aggregator_test_atom.xml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_atom.xml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test_atom.xml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_atom.xml
diff --git a/core/modules/aggregator/tests/aggregator_test_rss091.xml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_rss091.xml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test_rss091.xml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_rss091.xml
diff --git a/core/modules/aggregator/tests/aggregator_test_title_entities.xml b/core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_title_entities.xml
similarity index 100%
rename from core/modules/aggregator/tests/aggregator_test_title_entities.xml
rename to core/modules/aggregator/tests/modules/aggregator_test/aggregator_test_title_entities.xml
diff --git a/core/modules/aggregator/tests/config/aggregator_test.settings.yml b/core/modules/aggregator/tests/modules/aggregator_test/config/aggregator_test.settings.yml
similarity index 100%
rename from core/modules/aggregator/tests/config/aggregator_test.settings.yml
rename to core/modules/aggregator/tests/modules/aggregator_test/config/aggregator_test.settings.yml
diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php
similarity index 100%
rename from core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php
rename to core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/fetcher/TestFetcher.php
diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php
similarity index 100%
rename from core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php
rename to core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/parser/TestParser.php
diff --git a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
similarity index 50%
rename from core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
rename to core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
index e218b8a..ebbe673 100644
--- a/core/modules/aggregator/tests/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
+++ b/core/modules/aggregator/tests/modules/aggregator_test/lib/Drupal/aggregator_test/Plugin/aggregator/processor/TestProcessor.php
@@ -7,11 +7,13 @@
 
 namespace Drupal\aggregator_test\Plugin\aggregator\processor;
 
-use Drupal\Component\Plugin\PluginBase;
+use Drupal\aggregator\Plugin\AggregatorPluginSettingsBase;
 use Drupal\aggregator\Plugin\ProcessorInterface;
 use Drupal\aggregator\Plugin\Core\Entity\Feed;
 use Drupal\aggregator\Annotation\AggregatorProcessor;
 use Drupal\Core\Annotation\Translation;
+use Drupal\Core\Config\ConfigFactory;
+use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
  * Defines a default processor implementation.
@@ -24,14 +26,44 @@
  *   description = @Translation("Test generic processor functionality.")
  * )
  */
-class TestProcessor extends PluginBase implements ProcessorInterface {
+class TestProcessor extends AggregatorPluginSettingsBase implements ProcessorInterface {
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsForm().
+   * Contains the configuration object factory.
+   *
+   * @var \Drupal\Core\Config\ConfigFactory
    */
-  public function settingsForm(array $form, array &$form_state) {
-    $config = config('aggregator.settings');
-    $processors = $config->get('processors');
+  protected $configFactory;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container, array $configuration, $plugin_id, array $plugin_definition) {
+    return new static($configuration, $plugin_id, $plugin_definition, $container->get('config.factory'));
+  }
+
+  /**
+   * Constructs a DefaultProcessor object.
+   *
+   * @param array $configuration
+   *   A configuration array containing information about the plugin instance.
+   * @param string $plugin_id
+   *   The plugin_id for the plugin instance.
+   * @param array $plugin_definition
+   *   The plugin implementation definition.
+   * @param \Drupal\Core\Config\ConfigFactory $config
+   *   The configuration factory object.
+   */
+  public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigFactory $config) {
+    parent::__construct($configuration, $plugin_id, $plugin_definition);
+    $this->configFactory = $config;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $processors = $this->configFactory->get('aggregator.settings')->get('processors');
     $info = $this->getDefinition();
 
     $form['processors'][$info['id']] = array(
@@ -46,22 +78,22 @@ public function settingsForm(array $form, array &$form_state) {
       '#type' => 'number',
       '#min' => 1,
       '#max' => 1000,
-      '#default_value' => config('aggregator_test.settings')->get('items.dummy_length'),
+      '#default_value' => $this->configFactory->get('aggregator_test.settings')->get('items.dummy_length'),
     );
     return $form;
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::settingsSubmit().
+   * {@inheritdoc}
    */
-  public function settingsSubmit(array $form, array &$form_state) {
-    config('aggregator_test.settings')
+  public function submitForm(array &$form, array &$form_state) {
+    $this->configFactory->get('aggregator_test.settings')
       ->set('items.dummy_length', $form_state['values']['dummy_length'])
       ->save();
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::process().
+   * {@inheritdoc}
    */
   public function process(Feed $feed) {
     foreach ($feed->items as &$item) {
@@ -71,7 +103,7 @@ public function process(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::remove().
+   * {@inheritdoc}
    */
   public function remove(Feed $feed) {
     // Append a random number, just to change the feed description.
@@ -79,11 +111,12 @@ public function remove(Feed $feed) {
   }
 
   /**
-   * Implements \Drupal\aggregator\Plugin\ProcessorInterface::postProcess().
+   * {@inheritdoc}
    */
   public function postProcess(Feed $feed) {
     // Double the refresh rate.
     $feed->refresh->value *= 2;
     $feed->save();
   }
+
 }
diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php
index 1856011..bb37564 100644
--- a/core/tests/Drupal/Tests/UnitTestCase.php
+++ b/core/tests/Drupal/Tests/UnitTestCase.php
@@ -134,4 +134,19 @@ public function getConfigStorageStub(array $configs) {
     return $config_storage;
   }
 
+  /**
+   * Returns a stub translation manager that just returns the passed string.
+   *
+   * @return \PHPUnit_Framework_MockObject_MockBuilder
+   *   A MockBuilder object of \Drupal\Core\StringTranslation\TranslationManager
+   */
+  public function getStringTranslationStub() {
+    $translation = $this->getMockBuilder('Drupal\Core\StringTranslation\TranslationManager')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $translation->expects($this->any())
+      ->method('translate')
+      ->will($this->returnArgument(0));
+    return $translation;
+  }
 }
