diff --git a/modules/system/system.module b/modules/system/system.module
index 5af9ad4..4483d7f 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -1800,17 +1800,6 @@ function system_authorized_run($callback, $file, $arguments = array(), $page_tit
 }
 
 /**
- * Use authorize.php to run batch_process().
- *
- * @see batch_process()
- */
-function system_authorized_batch_process() {
-  $finish_url = system_authorized_get_url();
-  $process_url = system_authorized_get_url(array('query' => array('batch' => '1')));
-  batch_process($finish_url, $process_url);
-}
-
-/**
  * @} End of "defgroup authorize".
  */
 
diff --git a/modules/update/update.authorize.inc b/modules/update/update.authorize.inc
index f4be44e..be86e62 100644
--- a/modules/update/update.authorize.inc
+++ b/modules/update/update.authorize.inc
@@ -23,6 +23,24 @@
  *   - 'local_url': The locally installed location of new code to update with.
  */
 function update_authorize_run_update($filetransfer, $projects) {
+  update_authorize_batch_set_update($filetransfer, $projects);
+  batch_process();
+}
+
+/**
+ * Initiates a batch for updating existing projects.
+ *
+ * @param $filetransfer
+ *   The FileTransfer object created by authorize.php for use during this
+ *   operation.
+ * @param $projects
+ *   A nested array of projects to install into the live webroot, keyed by
+ *   project name. Each subarray contains the following keys:
+ *   - 'project': The canonical project short name.
+ *   - 'updater_name': The name of the Updater class to use for this project.
+ *   - 'local_url': The locally installed location of new code to update with.
+ */
+function update_authorize_batch_set_update($filetransfer, $projects) {
   $operations = array();
   foreach ($projects as $project => $project_info) {
     $operations[] = array(
@@ -45,8 +63,11 @@ function update_authorize_run_update($filetransfer, $projects) {
   );
 
   batch_set($batch);
-  // Invoke the batch via authorize.php.
-  system_authorized_batch_process();
+
+  // Force the batch to be invoked via authorize.php.
+  $batch = &batch_get();
+  $batch['url'] = system_authorized_get_url(array('query' => array('batch' => '1')));
+  $batch['redirect'] = system_authorized_get_url();
 }
 
 /**
@@ -64,6 +85,25 @@ function update_authorize_run_update($filetransfer, $projects) {
  *   already been downloaded and extracted into.
  */
 function update_authorize_run_install($filetransfer, $project, $updater_name, $local_url) {
+  update_authorize_batch_set_install($filetransfer, $project, $updater_name, $local_url);
+  batch_process();
+}
+
+/**
+ * Initiates a batch for installing a new project.
+ *
+ * @param FileTransfer $filetransfer
+ *   The FileTransfer object created by authorize.php for use during this
+ *   operation.
+ * @param string $project
+ *   The canonical project short name (e.g. {system}.name).
+ * @param string $updater_name
+ *   The name of the Updater class to use for installing this project.
+ * @param string $local_url
+ *   The URL to the locally installed temp directory where the project has
+ *   already been downloaded and extracted into.
+ */
+function update_authorize_batch_set_install($filetransfer, $project, $updater_name, $local_url) {
   $operations[] = array(
     'update_authorize_batch_copy_project',
     array(
@@ -85,8 +125,10 @@ function update_authorize_run_install($filetransfer, $project, $updater_name, $l
   );
   batch_set($batch);
 
-  // Invoke the batch via authorize.php.
-  system_authorized_batch_process();
+  // Force the batch to be invoked via authorize.php.
+  $batch = &batch_get();
+  $batch['url'] = system_authorized_get_url(array('query' => array('batch' => '1')));
+  $batch['redirect'] = system_authorized_get_url();
 }
 
 /**
diff --git a/modules/update/update.manager.inc b/modules/update/update.manager.inc
index b0def17..580dcc0 100644
--- a/modules/update/update.manager.inc
+++ b/modules/update/update.manager.inc
@@ -426,12 +426,12 @@ function update_manager_update_ready_form_submit($form, &$form_state) {
     // If the owner of the last directory we extracted is the same as the
     // owner of our configuration directory (e.g. sites/default) where we're
     // trying to install the code, there's no need to prompt for FTP/SSH
-    // credentials. Instead, we instantiate a FileTransferLocal and invoke
-    // update_authorize_run_update() directly.
+    // credentials. Instead, we instantiate a FileTransferLocal and start a
+    // batch that will update the projects directly.
     if (fileowner($project_real_location) == fileowner(conf_path())) {
       module_load_include('inc', 'update', 'update.authorize');
       $filetransfer = new FileTransferLocal(DRUPAL_ROOT);
-      update_authorize_run_update($filetransfer, $updates);
+      update_authorize_batch_set_update($filetransfer, $updates);
     }
     // Otherwise, go through the regular workflow to prompt for FTP/SSH
     // credentials and invoke update_authorize_run_update() indirectly with
@@ -701,12 +701,12 @@ function update_manager_install_form_submit($form, &$form_state) {
   // If the owner of the directory we extracted is the same as the
   // owner of our configuration directory (e.g. sites/default) where we're
   // trying to install the code, there's no need to prompt for FTP/SSH
-  // credentials. Instead, we instantiate a FileTransferLocal and invoke
-  // update_authorize_run_install() directly.
+  // credentials. Instead, we instantiate a FileTransferLocal and start a batch
+  // that will install the project directly.
   if (fileowner($project_real_location) == fileowner(conf_path())) {
     module_load_include('inc', 'update', 'update.authorize');
     $filetransfer = new FileTransferLocal(DRUPAL_ROOT);
-    call_user_func_array('update_authorize_run_install', array_merge(array($filetransfer), $arguments));
+    call_user_func_array('update_authorize_batch_set_install', array_merge(array($filetransfer), $arguments));
   }
   // Otherwise, go through the regular workflow to prompt for FTP/SSH
   // credentials and invoke update_authorize_run_install() indirectly with
