Index: wp-admin/update.php
===================================================================
--- wp-admin/update.php	(revision 17523)
+++ wp-admin/update.php	(working copy)
@@ -146,6 +146,31 @@
 
 		include(ABSPATH . 'wp-admin/admin-footer.php');
 
+	} elseif ( 'sideload-plugin' == $action ) {
+
+		if ( ! current_user_can('install_plugins') )
+			wp_die(__('You do not have sufficient permissions to install plugins for this site.'));
+
+		check_admin_referer('plugin-sideload');
+
+		$download_url = esc_url_raw( stripslashes( $_POST['pluginurl'] ) );
+
+		$title = __('Plugin Install');
+		$parent_file = 'plugins.php';
+		$submenu_file = 'plugin-install.php';
+		require_once(ABSPATH . 'wp-admin/admin-header.php');
+
+		$title = sprintf( __('Installing Plugin from URL: %s'), $download_url );
+		$nonce = 'plugin-sideload';
+		$url = 'update.php?action=sideload-plugin&pluginurl=' . urlencode( stripslashes( $_POST['pluginurl'] ) );
+
+		$type = 'web';
+
+		$upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact('title', 'url', 'nonce') ) );
+		$upgrader->install( $download_url );
+
+		include(ABSPATH . 'wp-admin/admin-footer.php');
+
 	} elseif ( 'upgrade-theme' == $action ) {
 
 		if ( ! current_user_can('update_themes') )
Index: wp-admin/includes/class-wp-plugin-install-list-table.php
===================================================================
--- wp-admin/includes/class-wp-plugin-install-list-table.php	(revision 17523)
+++ wp-admin/includes/class-wp-plugin-install-list-table.php	(working copy)
@@ -30,6 +30,7 @@
 		if ( 'search' == $tab )
 			$tabs['search']	= __( 'Search Results' );
 		$tabs['upload'] = __( 'Upload' );
+		$tabs['url'] = __( 'From URL' );
 		$tabs['featured'] = _x( 'Featured','Plugin Installer' );
 		$tabs['popular']  = _x( 'Popular','Plugin Installer' );
 		$tabs['new']      = _x( 'Newest','Plugin Installer' );
Index: wp-admin/includes/plugin-install.php
===================================================================
--- wp-admin/includes/plugin-install.php	(revision 17523)
+++ wp-admin/includes/plugin-install.php	(working copy)
@@ -136,10 +136,8 @@
 /**
  * Upload from zip
  * @since 2.8.0
- *
- * @param string $page
  */
-function install_plugins_upload( $page = 1 ) {
+function install_plugins_upload() {
 ?>
 	<h4><?php _e('Install a plugin in .zip format') ?></h4>
 	<p class="install-help"><?php _e('If you have a plugin in a .zip format, you may install it by uploading it here.') ?></p>
@@ -151,9 +149,27 @@
 	</form>
 <?php
 }
-add_action('install_plugins_upload', 'install_plugins_upload', 10, 1);
+add_action('install_plugins_upload', 'install_plugins_upload');
 
 /**
+ * Sideload from arbitrary URL
+ * @since 3.1.0
+ */
+function install_plugins_url() {
+?>
+	<h4><?php _e('Install a plugin from a URL') ?></h4>
+	<p class="install-help"><?php _e('If you have the URL to a plugin in .zip format, you may install it by providing the URL here.') ?></p>
+	<form method="post" action="<?php echo self_admin_url('update.php?action=sideload-plugin') ?>">
+		<?php wp_nonce_field( 'plugin-sideload' ) ?>
+		<label class="screen-reader-text" for="pluginzip"><?php _e('URL to Plugin zip file'); ?></label>
+		<input type="input" type="text" class="large-text" id="pluginurl" name="pluginurl" />
+		<input type="submit" class="button" value="<?php esc_attr_e('Install Now') ?>" />
+	</form>
+<?php
+}
+add_action('install_plugins_url', 'install_plugins_url');
+
+/**
  * Display plugin content based on plugin list.
  *
  * @since 2.7.0
