Index: wp-admin/includes/ajax-actions.php
===================================================================
--- wp-admin/includes/ajax-actions.php	(revision 23704)
+++ wp-admin/includes/ajax-actions.php	(working copy)
@@ -1043,15 +1043,12 @@
 		unset($_POST['post_category']);
 
 	$do_autosave = (bool) $_POST['autosave'];
-	$do_lock = true;
 	$data = '';
 	$supplemental = array();
 	$id = $revision_id = 0;
 
-	/* translators: draft saved date format, see http://php.net/date */
-	$draft_saved_date_format = __('g:i:s a');
-	/* translators: %s: date and time */
-	$message = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
+	if ( ! $user_id = get_current_user_id() )
+		wp_die('-1');
 
 	$post_id = (int) $_POST['post_id'];
 	$_POST['ID'] = $_POST['post_ID'] = $post_id;
@@ -1059,17 +1056,6 @@
 	if ( 'auto-draft' == $post->post_status )
 		$_POST['post_status'] = 'draft';
 
-	if ( $last = wp_check_post_lock( $post->ID ) ) {
-		// This will change after we have per-user autosaves
-		$do_autosave = $do_lock = false;
-
-		$last_user = get_userdata( $last );
-		$last_user_name = $last_user ? $last_user->display_name : __( 'Someone' );
-		$data = __( 'Autosave disabled.' );
-
-		$supplemental['disable_autosave'] = 'disable';
-	}
-
 	if ( 'page' == $post->post_type ) {
 		if ( !current_user_can('edit_page', $post->ID) )
 			wp_die( __( 'You are not allowed to edit this page.' ) );
@@ -1079,17 +1065,28 @@
 	}
 
 	if ( $do_autosave ) {
-		// Drafts and auto-drafts are just overwritten by autosave
-		if ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) {
+		// Drafts and auto-drafts are just overwritten by autosave for the same user
+		if ( $user_id == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
 			$id = edit_post();
-		} else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
+		} else { // Non drafts are not overwritten. The autosave is stored in a special post revision for each user.
 			$revision_id = wp_create_post_autosave( $post->ID );
 			if ( is_wp_error($revision_id) )
 				$id = $revision_id;
 			else
 				$id = $post->ID;
 		}
-		$data = $message;
+
+		if ( is_wp_error($id) ) {
+			// is_wp_error($id) overwrites $data in WP_Ajax_Response but no point in doing wp_create_nonce('update-post_' . $id) below
+			// todo: Needs review. The errors generated in WP_Ajax_Response and parsed with wpAjax.parseAjaxResponse() haven't been used for many years.
+			$data = $id;
+			$id = 0;
+		} else {
+			/* translators: draft saved date format, see http://php.net/date */
+			$draft_saved_date_format = __('g:i:s a');
+			/* translators: %s: date and time */
+			$data = sprintf( __('Draft saved at %s.'), date_i18n( $draft_saved_date_format ) );
+		}
 	} else {
 		if ( ! empty( $_POST['auto_draft'] ) )
 			$id = 0; // This tells us it didn't actually save
@@ -1103,12 +1100,8 @@
 		$supplemental['replace-samplepermalinknonce'] = wp_create_nonce('samplepermalink');
 		$supplemental['replace-closedpostboxesnonce'] = wp_create_nonce('closedpostboxes');
 		$supplemental['replace-_ajax_linking_nonce'] = wp_create_nonce( 'internal-linking' );
-		if ( $id ) {
-			if ( $_POST['post_type'] == 'post' )
-				$supplemental['replace-_wpnonce'] = wp_create_nonce('update-post_' . $id);
-			elseif ( $_POST['post_type'] == 'page' )
-				$supplemental['replace-_wpnonce'] = wp_create_nonce('update-page_' . $id);
-		}
+		if ( $id )
+			$supplemental['replace-_wpnonce'] = wp_create_nonce('update-post_' . $id);
 	}
 
 	$x = new WP_Ajax_Response( array(
Index: wp-admin/includes/post.php
===================================================================
--- wp-admin/includes/post.php	(revision 23704)
+++ wp-admin/includes/post.php	(working copy)
@@ -1266,11 +1266,13 @@
 	if ( is_wp_error( $translated ) )
 		return $translated;
 
-	// Only store one autosave. If there is already an autosave, overwrite it.
-	if ( $old_autosave = wp_get_post_autosave( $post_id ) ) {
+	$post_author = get_current_user_id();
+
+	// Store one autosave per author. If there is already an autosave, overwrite it.
+	if ( $old_autosave = wp_get_post_autosave( $post_id, $post_author ) ) {
 		$new_autosave = _wp_post_revision_fields( $_POST, true );
 		$new_autosave['ID'] = $old_autosave->ID;
-		$new_autosave['post_author'] = get_current_user_id();
+		$new_autosave['post_author'] = $post_author;
 		return wp_update_post( $new_autosave );
 	}
 
@@ -1325,7 +1327,8 @@
 			wp_die(__('You are not allowed to edit this post.'));
 	}
 
-	if ( 'draft' == $post->post_status ) {
+	$user_id = get_current_user_id();
+	if ( 'draft' == $post->post_status && $user_id == $post->post_author ) {
 		$id = edit_post();
 	} else { // Non drafts are not overwritten. The autosave is stored in a special post revision.
 		$id = wp_create_post_autosave( $post->ID );
@@ -1336,7 +1339,7 @@
 	if ( is_wp_error($id) )
 		wp_die( $id->get_error_message() );
 
-	if ( $_POST['post_status'] == 'draft'  ) {
+	if ( $_POST['post_status'] == 'draft' && $user_id == $post->post_author ) {
 		$url = add_query_arg( 'preview', 'true', get_permalink($id) );
 	} else {
 		$nonce = wp_create_nonce('post_preview_' . $id);
Index: wp-admin/post.php
===================================================================
--- wp-admin/post.php	(revision 23704)
+++ wp-admin/post.php	(working copy)
@@ -173,13 +173,13 @@
 
 	if ( ! wp_check_post_lock( $post->ID ) ) {
 		$active_post_lock = wp_set_post_lock( $post->ID );
-
-		if ( 'attachment' !== $post_type )
-			wp_enqueue_script('autosave');
 	}
 
 	add_action( 'admin_footer', '_admin_notice_post_locked' );
 
+	if ( 'attachment' !== $post_type )
+		wp_enqueue_script('autosave');
+
 	$title = $post_type_object->labels->edit_item;
 	$post = get_post($post_id, OBJECT, 'edit');
 
Index: wp-includes/js/autosave.js
===================================================================
--- wp-includes/js/autosave.js	(revision 23704)
+++ wp-includes/js/autosave.js	(working copy)
@@ -1,4 +1,4 @@
-var autosave, autosaveLast = '', autosavePeriodical, autosaveOldMessage = '', autosaveDelayPreview = false, notSaved = true, blockSave = false, fullscreen, autosaveLockRelease = true;
+var autosave, autosaveLast = '', autosavePeriodical, autosaveDelayPreview = false, notSaved = true, blockSave = false, fullscreen, autosaveLockRelease = true;
 
 jQuery(document).ready( function($) {
 
@@ -130,49 +130,29 @@
 	}
 });
 
-function autosave_parse_response(response) {
-	var res = wpAjax.parseAjaxResponse(response, 'autosave'), message = '', postID, sup;
+function autosave_parse_response( response ) {
+	var res = wpAjax.parseAjaxResponse(response, 'autosave'), post_id, sup;
 
 	if ( res && res.responses && res.responses.length ) {
-		message = res.responses[0].data; // The saved message or error.
-		// someone else is editing: disable autosave, set errors
 		if ( res.responses[0].supplemental ) {
 			sup = res.responses[0].supplemental;
-			if ( 'disable' == sup['disable_autosave'] ) {
-				autosave = function() {};
-				autosaveLockRelease = false;
-				res = { errors: true };
-			}
 
-			if ( sup['active-post-lock'] ) {
-				jQuery('#active_post_lock').val( sup['active-post-lock'] );
-			}
-
-			if ( sup['alert'] ) {
-				jQuery('#autosave-alert').remove();
-				jQuery('#titlediv').after('<div id="autosave-alert" class="error below-h2"><p>' + sup['alert'] + '</p></div>');
-			}
-
-			jQuery.each(sup, function(selector, value) {
-				if ( selector.match(/^replace-/) ) {
-					jQuery('#'+selector.replace('replace-', '')).val(value);
-				}
+			jQuery.each( sup, function( selector, value ) {
+				if ( selector.match(/^replace-/) )
+					jQuery( '#' + selector.replace('replace-', '') ).val( value );
 			});
 		}
 
-		// if no errors: add slug UI
+		// if no errors: add slug UI and update autosave-message
 		if ( !res.errors ) {
-			postID = parseInt( res.responses[0].id, 10 );
-			if ( !isNaN(postID) && postID > 0 ) {
-				autosave_update_slug(postID);
-			}
+			if ( post_id = parseInt( res.responses[0].id, 10 ) )
+				autosave_update_slug( post_id );
+
+			if ( res.responses[0].data ) // update autosave message
+				jQuery('.autosave-message').text( res.responses[0].data );
 		}
 	}
-	if ( message ) { // update autosave message
-		jQuery('.autosave-message').html(message);
-	} else if ( autosaveOldMessage && res ) {
-		jQuery('.autosave-message').html( autosaveOldMessage );
-	}
+
 	return res;
 }
 
@@ -186,16 +166,19 @@
 // called when autosaving new post
 function autosave_saved_new(response) {
 	blockSave = false;
-	var res = autosave_parse_response(response), postID;
+	var res = autosave_parse_response(response), post_id;
 
 	if ( res && res.responses.length && !res.errors ) {
 		// An ID is sent only for real auto-saves, not for autosave=0 "keepalive" saves
-		postID = parseInt( res.responses[0].id, 10 );
-		if ( !isNaN(postID) && postID > 0 ) {
+		post_id = parseInt( res.responses[0].id, 10 );
+
+		if ( post_id ) {
 			notSaved = false;
 			jQuery('#auto_draft').val('0'); // No longer an auto-draft
 		}
+
 		autosave_enable_buttons();
+
 		if ( autosaveDelayPreview ) {
 			autosaveDelayPreview = false;
 			doPreview();
@@ -286,7 +269,6 @@
 		successCallback = autosave_saved; // pre-existing post
 	}
 
-	autosaveOldMessage = jQuery('#autosave').html();
 	jQuery.ajax({
 		data: post_data,
 		beforeSend: doAutoSave ? autosave_loading : null,
Index: wp-includes/revision.php
===================================================================
--- wp-includes/revision.php	(revision 23704)
+++ wp-includes/revision.php	(working copy)
@@ -135,54 +135,35 @@
  * Retrieve the autosaved data of the specified post.
  *
  * Returns a post object containing the information that was autosaved for the
- * specified post.
+ * specified post. If the optional $user_id is passed, returns the autosave for that user
+ * otherwise returns the latest autosave.
  *
  * @package WordPress
  * @subpackage Post_Revisions
  * @since 2.6.0
- *
+ * @uses wp_get_post_revisions()
+ *  
  * @param int $post_id The post ID.
+ * @param int $user_id optional The post author ID.
  * @return object|bool The autosaved data or false on failure or when no autosave exists.
  */
-function wp_get_post_autosave( $post_id ) {
+function wp_get_post_autosave( $post_id, $user_id = 0 ) {
+	$revisions = wp_get_post_revisions($post_id);
 
-	if ( !$post = get_post( $post_id ) )
-		return false;
+	foreach ( $revisions as $revision ) {
+		if ( false !== strpos( $revision->post_name, "{$post_id}-autosave" ) ) {
+			if ( $user_id && $user_id != $revision->post_author )
+				continue;
 
-	$q = array(
-		'name' => "{$post->ID}-autosave",
-		'post_parent' => $post->ID,
-		'post_type' => 'revision',
-		'post_status' => 'inherit'
-	);
+			return $revision;
+			break;
+		}
+	}
 
-	// Use WP_Query so that the result gets cached
-	$autosave_query = new WP_Query;
-
-	add_action( 'parse_query', '_wp_get_post_autosave_hack' );
-	$autosave = $autosave_query->query( $q );
-	remove_action( 'parse_query', '_wp_get_post_autosave_hack' );
-
-	if ( $autosave && is_array($autosave) && is_object($autosave[0]) )
-		return $autosave[0];
-
 	return false;
 }
 
 /**
- * Internally used to hack WP_Query into submission.
- *
- * @package WordPress
- * @subpackage Post_Revisions
- * @since 2.6.0
- *
- * @param object $query WP_Query object
- */
-function _wp_get_post_autosave_hack( $query ) {
-	$query->is_single = false;
-}
-
-/**
  * Determines if the specified post is a revision.
  *
  * @package WordPress
@@ -195,6 +176,7 @@
 function wp_is_post_revision( $post ) {
 	if ( !$post = wp_get_post_revision( $post ) )
 		return false;
+
 	return (int) $post->post_parent;
 }
 
@@ -211,9 +193,11 @@
 function wp_is_post_autosave( $post ) {
 	if ( !$post = wp_get_post_revision( $post ) )
 		return false;
-	if ( "{$post->post_parent}-autosave" !== $post->post_name )
-		return false;
-	return (int) $post->post_parent;
+
+	if ( false !== strpos( $post->post_name, "{$post->post_parent}-autosave" ) )
+		return (int) $post->post_parent;
+
+	return false;
 }
 
 /**
@@ -234,6 +218,7 @@
 		$post = get_object_vars( $post );
 	elseif ( !is_array($post) )
 		$post = get_post($post, ARRAY_A);
+
 	if ( !$post || empty($post['ID']) )
 		return;
 
@@ -249,6 +234,7 @@
 
 	if ( $revision_id )
 		do_action( '_wp_put_post_revision', $revision_id );
+
 	return $revision_id;
 }
 
@@ -312,8 +298,9 @@
 		$fields = array_keys( _wp_post_revision_fields() );
 
 	$update = array();
-	foreach( array_intersect( array_keys( $revision ), $fields ) as $field )
+	foreach( array_intersect( array_keys( $revision ), $fields ) as $field ) {
 		$update[$field] = $revision[$field];
+	}
 
 	if ( !$update )
 		return false;
@@ -374,8 +361,6 @@
  * @return array empty if no revisions
  */
 function wp_get_post_revisions( $post_id = 0, $args = null ) {
-	if ( ! WP_POST_REVISIONS )
-		return array();
 	if ( ( !$post = get_post( $post_id ) ) || empty( $post->ID ) )
 		return array();
 
@@ -385,6 +370,7 @@
 
 	if ( !$revisions = get_children( $args ) )
 		return array();
+
 	return $revisions;
 }
 
