diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index 3875be205897f819d2a2b23d735bfe6a97531cfe..34b152d1a32c86c4972fb2e6867ff2158389586d 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -3,6 +3,10 @@
 Feeds 7.x 2.0 XXXXXXXXXXXXXXXXXXX
 ---------------------------------
 
+- #728534 alex_b: Remove FeedsFeedNodeProcessor. If you have used
+  FeedsFeedNodeProcessor in the past, use FeedsNodeProcessor (Node Processor)
+  instead now. It supports all of FeedsFeedNodeProcessor's functionality and
+  more.
 - #929066 alex_b: Track all imported items. Note: All views that use 'Feeds
   Item' fields or relationships need updating.
 - #930018 alex_b: Don't show file upload when 'Supply path directly' is
diff --git a/feeds.plugins.inc b/feeds.plugins.inc
index 0992542d001b4368908fbfdb38507a69e9e13286..00723eb91ac6e2a334c4622d9da827c1ad159181 100644
--- a/feeds.plugins.inc
+++ b/feeds.plugins.inc
@@ -141,17 +141,6 @@ function _feeds_feeds_plugins() {
       'path' => $path,
     ),
   );
-  $info['FeedsFeedNodeProcessor'] = array(
-    'name' => 'Feed Node processor',
-    'description' => 'Create <em>Feed nodes</em>.',
-    'help' => 'Create <em>Feed nodes</em> from parsed content. Feed nodes are nodes that can import feeds themselves. This can be useful for instance when importing OPML feeds.',
-    'handler' => array(
-      'parent' => 'FeedsProcessor',
-      'class' => 'FeedsFeedNodeProcessor',
-      'file' => 'FeedsFeedNodeProcessor.inc',
-      'path' => $path,
-    ),
-  );
   $info['FeedsUserProcessor'] = array(
     'name' => 'User processor',
     'description' => 'Create users.',
diff --git a/feeds_news/feeds_news.feeds_importer_default.inc b/feeds_news/feeds_news.feeds_importer_default.inc
index 4fe041c7c921db45905739e5bb9058bd3f2774e7..4e1ca4e09c5211d14ca00670f8a96e1fdad0b97e 100644
--- a/feeds_news/feeds_news.feeds_importer_default.inc
+++ b/feeds_news/feeds_news.feeds_importer_default.inc
@@ -87,10 +87,11 @@ function feeds_news_feeds_importer_default() {
       'config' => array(),
     ),
     'processor' => array(
-      'plugin_key' => 'FeedsFeedNodeProcessor',
+      'plugin_key' => 'FeedsNodeProcessor',
       'config' => array(
         'content_type' => 'feed',
         'update_existing' => 0,
+        'expire' => '-1',
         'mappings' => array(
           0 => array(
             'source' => 'title',
@@ -99,7 +100,7 @@ function feeds_news_feeds_importer_default() {
           ),
           1 => array(
             'source' => 'xmlurl',
-            'target' => 'source',
+            'target' => 'feeds_source',
             'unique' => 1,
           ),
         ),
diff --git a/plugins/FeedsFeedNodeProcessor.inc b/plugins/FeedsFeedNodeProcessor.inc
deleted file mode 100644
index 00926e748062855d1a0820962d2ea88a30fdeddf..0000000000000000000000000000000000000000
--- a/plugins/FeedsFeedNodeProcessor.inc
+++ /dev/null
@@ -1,226 +0,0 @@
-<?php
-// $Id$
-
-/**
- * @file
- * Class definition of FeedsFeedNodeProcessor.
- */
-
-/**
- * Creates *feed* nodes from feed items. The difference to FeedsNodeProcessor is
- * that this plugin only creates nodes that are feed nodes themselves.
- */
-class FeedsFeedNodeProcessor extends FeedsProcessor {
-
-  /**
-   * Implements FeedsProcessor::process().
-   */
-  public function process(FeedsSource $source, FeedsParserResult $parser_result) {
-    $state = $source->state(FEEDS_PROCESS);
-    while ($item = $parser_result->shiftItem()) {
-
-      // If the target item does not exist OR if update_existing is enabled,
-      // map and save.
-      if (!$nid = $this->existingItemId($source, $parser_result) || $this->config['update_existing']) {
-
-        // Map item to a node.
-        $node = $this->map($source, $parser_result);
-
-        // If updating populate nid and vid avoiding an expensive node_load().
-        if (!empty($nid)) {
-          $node->nid = $nid;
-          $node->vid = db_query("SELECT vid FROM {node} WHERE nid = :nid", array(':nid' => $nid))->fetchField();
-        }
-
-        // Save the node.
-        node_save($node);
-
-        if ($nid) {
-          $state->updated++;
-        }
-        else {
-          $state->created++;
-        }
-      }
-    }
-    if ($source->progressImporting() != FEEDS_BATCH_COMPLETE) {
-      return;
-    }
-
-    // Set messages.
-    if ($state->created) {
-      drupal_set_message(format_plural($state->created, 'Created @number @type node.', 'Created @number @type nodes.', array('@number' => $state->created, '@type' => $this->config['content_type'])));
-    }
-    elseif ($state->updated) {
-      drupal_set_message(format_plural($state->updated, 'Updated @number @type node.', 'Updated @number @type nodes.', array('@number' => $state->updated, '@type' => $this->config['content_type'])));
-    }
-    else {
-      drupal_set_message(t('There is no new content.'));
-    }
-  }
-
-  /**
-   * Implements FeedsProcessor::clear().
-   */
-  public function clear(FeedsSource $source) {
-    // Do not support deleting imported items as we would have to delete all
-    // items of the content type we imported which may contain nodes that a
-    // user created by hand.
-    throw new Exception(t('This configuration does not support deleting imported items.'));
-  }
-
-  /**
-   * Execute mapping on an item.
-   */
-  protected function map(FeedsSource $source, FeedsParserResult $result) {
-
-    // Prepare node object.
-    static $included;
-    if (!$included) {
-      module_load_include('inc', 'node', 'node.pages');
-      $included = TRUE;
-    }
-    $target_node = new stdClass();
-    $target_node->type = $this->config['content_type'];
-    $target_node->feeds = array();
-    // Suppress auto import, we may be creating many feeds
-    $target_node->feeds['suppress_import'] = TRUE;
-    node_object_prepare($target_node);
-
-    /*
-    Assign an aggregated node always to current user.
-    @todo This won't work in all cases as the assumption here is that
-    import is happening one off when user is logged in. Assumption breaks if
-    feed node processor is being used for aggregation on cron time and a
-    specific user should still be the owner of the imported feed nodes.
-    */
-    global $user;
-    $target_node->uid = $user->uid;
-
-    // Have parent class do the iterating.
-    return parent::map($source, $result, $target_node);
-  }
-
-  /**
-   * Override parent::configDefaults().
-   */
-  public function configDefaults() {
-    return array(
-      'content_type' => '',
-      'update_existing' => 0,
-      'mappings' => array(),
-    );
-  }
-
-  /**
-   * Override parent::configForm().
-   */
-  public function configForm(&$form_state) {
-    $feeds = feeds_importer_load_all();
-    $types = array();
-    foreach ($feeds as $feed) {
-      if ($feed->id != $this->id && !empty($feed->config['content_type'])) {
-        $types[$feed->config['content_type']] = check_plain(node_type_get_name($feed->config['content_type']));
-      }
-    }
-    if (empty($types)) {
-      $types[''] = t('No feed node content type available');
-    }
-    else {
-      $types = array(
-        '' => t('Select'),
-      ) + $types;
-    }
-    $form = array();
-    $form['content_type'] = array(
-      '#type' => 'select',
-      '#title' => t('Content type'),
-      '#description' => t('Choose node type to create from this feed. Only node types with attached importer configurations are listed here. <strong>Note:</strong> Users with "import !feed_id feeds" permissions will be able to <strong>import</strong> nodes of the content type selected here regardless of the node level permissions. However, users with "clear !feed_id permissions" need to have sufficient node level permissions to delete the imported nodes.', array('!feed_id' => $this->id)),
-      '#options' => $types,
-      '#default_value' => $this->config['content_type'],
-    );
-    // @todo Implement real updating.
-    $form['update_existing'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Replace existing feed nodes'),
-      '#description' => t('If an existing node is found for an imported node, replace it. Existing nodes will be determined using mappings that are a "unique target".'),
-      '#default_value' => $this->config['update_existing'],
-    );
-    return $form;
-  }
-
-  /**
-   * Override setTargetElement to operate on a target item that is a node.
-   */
-  public function setTargetElement($target_node, $target_element, $value) {
-    if ($target_element == 'source') {
-      // Get the class of the feed node importer's fetcher and set the source
-      // property. See feeds_node_update() how $node->feeds gets stored.
-      $class = get_class($this->feedNodeImporter()->fetcher);
-      $target_node->feeds[$class]['source'] = $value;
-    }
-    elseif ($target_element == 'body') {
-      $target_node->teaser = $value;
-      $target_node->body = $value;
-    }
-    elseif (in_array($target_element, array('title', 'status', 'created'))) {
-      $target_node->$target_element = $value;
-    }
-  }
-
-  /**
-   * Return available mapping targets.
-   */
-  public function getMappingTargets() {
-    $targets = array(
-      'title' => array(
-        'name' => t('Title'),
-        'description' => t('The title of the feed node.'),
-       ),
-      'status' => array(
-        'name' => t('Published status'),
-        'description' => t('Whether a feed node is published or not. 1 stands for published, 0 for not published.'),
-      ),
-      'created' => array(
-        'name' => t('Published date'),
-        'description' => t('The UNIX time when a node has been published.'),
-      ),
-      'body' => array(
-        'name' => t('Body'),
-        'description' => t('The body of the node. The teaser will be the same as the entire body.'),
-      ),
-      'source' => array(
-        'name' => t('Feed source'),
-        'description' => t('Depending on the selected fetcher, this could be for example a URL or a path to a file.'),
-        'optional_unique' => TRUE,
-      ),
-    );
-    return $targets;
-  }
-
-  /**
-   * Get nid of an existing feed item node if available.
-   */
-  protected function existingItemId(FeedsSource $source, FeedsParserResult $result) {
-
-    // We only support one unique target: source
-    foreach ($this->uniqueTargets($source, $result) as $target => $value) {
-      if ($target == 'source') {
-        return db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", array(':id' => $this->feedNodeImporter()->id, ':source' => $value))->fetchField();
-      }
-    }
-    return 0;
-  }
-
-  /**
-   * Helper for retrieving the importer object for the feed nodes to produce.
-   */
-  protected function feedNodeImporter() {
-   if ($id = feeds_get_importer_id($this->config['content_type'])) {
-      return feeds_importer($id);
-    }
-    else {
-      throw new Exception(t('Content type to be created is not a valid Feed content type.'));
-    }
-  }
-}
diff --git a/plugins/FeedsNodeProcessor.inc b/plugins/FeedsNodeProcessor.inc
index d3c5debd489e812a9b80348ffe6130a7ff88e681..45eda88c74790c90e8d69bcf5a39908bb1e1175b 100644
--- a/plugins/FeedsNodeProcessor.inc
+++ b/plugins/FeedsNodeProcessor.inc
@@ -261,6 +261,17 @@ class FeedsNodeProcessor extends FeedsProcessor {
           $target_node->created = $value->getValue();
         }
         break;
+      case 'feeds_source':
+        // Get the class of the feed node importer's fetcher and set the source
+        // property. See feeds_node_update() how $node->feeds gets stored.
+        if ($id = feeds_get_importer_id($this->config['content_type'])) {
+          $class = get_class(feeds_importer($id)->fetcher);
+          $target_node->feeds[$class]['source'] = $value;
+          // This effectively suppresses 'import on submission' feature.
+          // See feeds_node_insert().
+          $target_node->feeds['suppress_import'] = TRUE;
+        }
+        break;
       default:
         parent::setTargetElement($target_node, $target_element, $value);
         break;
@@ -298,6 +309,15 @@ class FeedsNodeProcessor extends FeedsProcessor {
         'description' => t('The UNIX time when a node has been published.'),
       ),
     );
+    // If the target content type is a Feed node, expose its source field.
+    if ($id = feeds_get_importer_id($this->config['content_type'])) {
+      $name = feeds_importer($id)->config['name'];
+      $targets['feeds_source'] = array(
+        'name' => t('Feed source'),
+        'description' => t('The content type created by this processor is a Feed Node, it represents a source itself. Depending on the fetcher selected on the importer "@importer", this field is expected to be for example a URL or a path to a file.', array('@importer' => $name)),
+        'optional_unique' => TRUE,
+      );
+    }
 
     // Let other modules expose mapping targets.
     self::loadMappers();
@@ -321,6 +341,11 @@ class FeedsNodeProcessor extends FeedsProcessor {
         case 'nid':
           $nid = db_query("SELECT nid FROM {node} WHERE nid = :nid", array(':nid' => $value))->fetchField();
           break;
+        case 'feeds_source':
+          if ($id = feeds_get_importer_id($this->importer->config['content_type'])) {
+            $nid = db_query("SELECT fs.feed_nid FROM {node} n JOIN {feeds_source} fs ON n.nid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", array(':id' => $id, ':source' => $value))->fetchField();
+          }
+          break;
       }
       if ($nid) {
         // Return with the first nid found.