diff --git a/file_entity.module b/file_entity.module
index 96923e3..c4b3f4f 100644
--- a/file_entity.module
+++ b/file_entity.module
@@ -1491,8 +1491,6 @@ function file_entity_ctools_plugin_api($owner, $api) {
  *
  * Stream wrappers that are considered private should implement a 'private'
  * flag equal to TRUE in hook_stream_wrappers().
- *
- * @todo Unify core's hook_file_download() as a 'download' op of file_entity_access().
  */
 
 /**
@@ -1595,8 +1593,6 @@ function file_entity_access($op, $file = NULL, $account = NULL) {
  * Implements hook_file_entity_access().
  */
 function file_entity_file_entity_access($op, $file, $account) {
-  $grants = array();
-
   // If the file URI is invalid, deny access.
   if (is_object($file) && !file_valid_uri($file->uri)) {
     return FILE_ENTITY_ACCESS_DENY;
@@ -1626,23 +1622,28 @@ function file_entity_file_entity_access($op, $file, $account) {
     }
   }
 
-  if ($op == 'view' && is_object($file) && file_uri_scheme($file->uri) == 'private') {
-    // When viewing private files, we can only invoke hook_file_download()
-    // if the $account user objet matches the current user.
-    if ($GLOBALS['user']->uid == $account->uid) {
-      foreach (module_implements('file_download') as $module) {
-        $access = module_invoke($module, 'file_download', $file->uri);
-        if ($access === -1) {
-          return FILE_ENTITY_ACCESS_DENY;
-        }
-        elseif (!empty($access)) {
-          $grants[] = $access;
-        }
-      }
-    }
+  return !empty($grants) ? FILE_ENTITY_ACCESS_ALLOW : FILE_ENTITY_ACCESS_IGNORE;
+}
+
+/**
+ * Implements hook_file_download().
+ */
+function file_entity_file_download($uri) {
+  // Load the file from the URI.
+  $file = file_uri_to_object($uri);
+
+  // An existing file wasn't found, so we don't control access.
+  // E.g. image derivatives will fall here.
+  if (empty($file->fid)) {
+    return NULL;
   }
 
-  return !empty($grants) ? FILE_ENTITY_ACCESS_ALLOW : FILE_ENTITY_ACCESS_IGNORE;
+  // Allow the user to download the file if they have appropriate permissions.
+  if (file_entity_access('view', $file)) {
+    return file_get_content_headers($file);
+  }
+
+  return -1;
 }
 
 /**
diff --git a/tests/file_entity.test b/tests/file_entity.test
index 7b1f8df..e0b7c32 100644
--- a/tests/file_entity.test
+++ b/tests/file_entity.test
@@ -39,6 +39,55 @@ class FileEntityTestHelper extends DrupalWebTestCase {
   }
 
   /**
+   * Helper for testFileEntityPrivateDownloadAccess() test.
+   *
+   * Defines several cases for accesing private files.
+   *
+   * @return array
+   *   Array of associative arrays, each one having the next keys:
+   *   - "message" string with the assertion message.
+   *   - "permissions" array of permissions or NULL for anonymous user.
+   *   - "expect" expected HTTP response code.
+   *   - "owner" Optional boolean indicating if the user is a file owner.
+   */
+  protected function getPrivateDownloadAccessCases() {
+    return array(
+      array(
+        'message' => "File owners cannot download their own files unless they are granted the 'view own private files' permission.",
+        'permissions' => array(),
+        'expect' => 403,
+        'owner' => TRUE,
+      ),
+      array(
+        'message' => "File owners can download their own files as they have been granted the 'view own private files' permission.",
+        'permissions' => array('view own private files'),
+        'expect' => 200,
+        'owner' => TRUE,
+      ),
+      array(
+        'message' => "Anonymous users cannot download private files.",
+        'permissions' => NULL,
+        'expect' => 403,
+      ),
+      array(
+        'message' => "Authenticated users cannot download each other's private files.",
+        'permissions' => array(),
+        'expect' => 403,
+      ),
+      array(
+        'message' => "Users who can view public files are not able to download private files.",
+        'permissions' => array('view files'),
+        'expect' => 403,
+      ),
+      array(
+        'message' => "Users who bypass file access can download any file.",
+        'permissions' => array('bypass file access'),
+        'expect' => 200,
+      ),
+    );
+  }
+
+  /**
    * Retrieves a sample file of the specified type.
    */
   function getTestFile($type_name, $size = NULL) {
@@ -965,4 +1014,42 @@ class FileEntityAccessTestCase extends FileEntityTestHelper {
     $this->drupalGet("file/{$file->fid}/delete");
     $this->assertResponse(200, 'Users with access can access the file add page');
   }
+
+  /**
+   * Test to see if we have access to download private files when granted the permissions.
+   */
+  function testFileEntityPrivateDownloadAccess() {
+    foreach ($this->getPrivateDownloadAccessCases() as $case) {
+      // Create users and login only if non-anonymous.
+      $authenticated_user = !is_null($case['permissions']);
+      if ($authenticated_user) {
+        $account = $this->drupalCreateUser($case['permissions']);
+        $this->drupalLogin($account);
+      }
+
+      // Create private, permanent files owned by this user only he's an owner.
+      if (!empty($case['owner'])) {
+        $file = next($this->files['text']);
+        $file->status = FILE_STATUS_PERMANENT;
+        $file->uid = $account->uid;
+        file_save($file);
+        $file = file_move($file, 'private://');
+
+        // Check if the physical file is there.
+        $arguments = array('%name' => $file->filename, '%username' => $account->name, '%uri' => $file->uri);
+        $this->assertTrue(is_file($file->uri), format_string('File %name owned by %username successfully created at %uri.', $arguments));
+        $url = file_create_url($file->uri);
+        $message_file_info = ' ' . format_string('File %uri was checked.', array('%uri' => $file->uri));
+      }
+
+      // Try to download the file.
+      $this->drupalGet($url);
+      $this->assertResponse($case['expect'], $case['message'] . $message_file_info);
+
+      // Logout authenticated users.
+      if ($authenticated_user) {
+        $this->drupalLogout();
+      }
+    }
+  }
 }
