Index: wp-admin/includes/class-wp-plugin-install-list-table.php
===================================================================
--- wp-admin/includes/class-wp-plugin-install-list-table.php	(revision 28967)
+++ wp-admin/includes/class-wp-plugin-install-list-table.php	(working copy)
@@ -13,6 +13,28 @@
 		return current_user_can('install_plugins');
 	}
 
+	/**
+	 * Return a list of slugs of installed plugins, if known.
+	 */
+	public function get_installed_plugin_stubs() {
+		$slugs = array();
+		
+		// Use the transient data from the updates API to determine the slugs of known installed plugins.
+		// This code might be better placed elsewhere, perhaps even within get_plugins().
+		$plugin_info = get_site_transient('update_plugins');
+		if ( isset( $plugin_info->no_update ) ) {
+			foreach ( $plugin_info->no_update as $plugin ) {
+				$slugs[] = $plugin->slug;
+			}
+		}
+		if ( isset( $plugin_info->response ) ) {
+			foreach ( $plugin_info->response as $plugin ) {
+				$slugs[] = $plugin->slug;
+			}
+		}
+		return $slugs;
+	}
+
 	public function prepare_items() {
 		include( ABSPATH . 'wp-admin/includes/plugin-install.php' );
 
@@ -63,8 +85,13 @@
 		if ( empty( $tab ) || ( !isset( $tabs[ $tab ] ) && !in_array( $tab, (array) $nonmenu_tabs ) ) )
 			$tab = key( $tabs );
 
-		$args = array( 'page' => $paged, 'per_page' => $per_page, 'fields' => array( 'last_updated' => true, 'downloaded' => true ) );
-
+		$args = array( 'page' => $paged, 'per_page' => $per_page, 
+			'fields' => array( 'last_updated' => true, 'downloaded' => true ),
+			// Send the locale and installed plugin slugs to the API so it can provide context-sensitive results.
+			'locale' => get_locale(),
+			'installed_plugins' => $this->get_installed_plugin_stubs(),
+		);
+		
 		switch ( $tab ) {
 			case 'search':
 				$type = isset( $_REQUEST['type'] ) ? wp_unslash( $_REQUEST['type'] ) : 'term';
Index: wp-admin/includes/class-wp-plugins-list-table.php
===================================================================
--- wp-admin/includes/class-wp-plugins-list-table.php	(revision 28967)
+++ wp-admin/includes/class-wp-plugins-list-table.php	(working copy)
@@ -108,8 +108,17 @@
 					unset( $recently_activated[$key] );
 			update_option( 'recently_activated', $recently_activated );
 		}
+		
+		$plugin_info = get_site_transient( 'update_plugins' );
 
 		foreach ( (array) $plugins['all'] as $plugin_file => $plugin_data ) {
+			// Extra info if known. array_merge() ensures $plugin_data has precedence if keys collide.
+			if ( isset( $plugin_info->response[ $plugin_file ] ) ) {
+				$plugins['all'][$plugin_file] = $plugin_data = array_merge( (array)$plugin_info->response[ $plugin_file ], $plugin_data );
+			} elseif ( isset( $plugin_info->no_update[ $plugin_file ] ) ) {
+				$plugins['all'][$plugin_file] = $plugin_data = array_merge( (array)$plugin_info->no_update[ $plugin_file ], $plugin_data );
+			}
+
 			// Filter into individual sections
 			if ( is_multisite() && ! $screen->in_admin( 'network' ) && is_network_only_plugin( $plugin_file ) && ! is_plugin_active( $plugin_file ) ) {
 				// On the non-network screen, filter out network-only plugins as long as they're not individually activated
@@ -344,6 +353,7 @@
 		$actions = array(
 			'deactivate' => '',
 			'activate' => '',
+			'details' => '',
 			'edit' => '',
 			'delete' => '',
 		);
@@ -392,6 +402,14 @@
 					if ( ! is_multisite() && current_user_can('delete_plugins') )
 						$actions['delete'] = '<a href="' . wp_nonce_url('plugins.php?action=delete-selected&amp;checked[]=' . $plugin_file . '&amp;plugin_status=' . $context . '&amp;paged=' . $page . '&amp;s=' . $s, 'bulk-plugins') . '" title="' . esc_attr__('Delete this plugin') . '" class="delete">' . __('Delete') . '</a>';
 				} // end if $is_active
+				
+				// Extra data from the updates API, if available
+				if ( isset( $plugin_data['slug'] ) ) {
+					$actions['details'] = '<a href="' . self_admin_url( 'plugin-install.php?tab=plugin-information&amp;plugin=' . $plugin_data['slug'] .
+								'&amp;TB_iframe=true&amp;width=600&amp;height=550' ) . '" class="thickbox" title="' .
+								esc_attr( sprintf( __( 'More information about %s' ), $plugin_data['Name'] ) ) . '">' . __( 'Details' ) . '</a>';
+				}
+				
 			 } // end if $screen->in_admin( 'network' )
 
 			if ( ( ! is_multisite() || $screen->in_admin( 'network' ) ) && current_user_can('edit_plugins') && is_writable(WP_PLUGIN_DIR . '/' . $plugin_file) )
Index: wp-includes/update.php
===================================================================
--- wp-includes/update.php	(revision 28967)
+++ wp-includes/update.php	(working copy)
@@ -277,6 +277,7 @@
 			'plugins'      => json_encode( $to_send ),
 			'translations' => json_encode( $translations ),
 			'locale'       => json_encode( $locales ),
+			'all'          => json_encode( true ),
 		),
 		'user-agent' => 'WordPress/' . $wp_version . '; ' . get_bloginfo( 'url' )
 	);
@@ -286,6 +287,7 @@
 	}
 
 	$url = $http_url = 'http://api.wordpress.org/plugins/update-check/1.1/';
+
 	if ( $ssl = wp_http_supports( array( 'ssl' ) ) )
 		$url = set_url_scheme( $url, 'https' );
 
@@ -303,13 +305,20 @@
 		$plugin = (object) $plugin;
 	}
 	unset( $plugin );
+	foreach ( $response['no_update'] as &$plugin ) {
+		$plugin = (object) $plugin;
+	}
+	unset( $plugin );
 
 	if ( is_array( $response ) ) {
 		$new_option->response = $response['plugins'];
 		$new_option->translations = $response['translations'];
+		// TODO: Perhaps better to store no_update in a separate transient with an expiry?
+		$new_option->no_update = $response['no_update'];
 	} else {
 		$new_option->response = array();
 		$new_option->translations = array();
+		$new_option->no_update = array();
 	}
 
 	set_site_transient( 'update_plugins', $new_option );
