diff -pu a/nss/lib/ssl/ssl3con.c b/nss/lib/ssl/ssl3con.c
--- a/nss/lib/ssl/ssl3con.c	2013-07-31 14:17:20.669282120 -0700
+++ b/nss/lib/ssl/ssl3con.c	2013-07-31 14:28:56.549496061 -0700
@@ -9912,8 +9912,10 @@ ssl3_SendNextProto(sslSocket *ss)
     int padding_len;
     static const unsigned char padding[32] = {0};
 
-    if (ss->ssl3.nextProto.len == 0)
+    if (ss->ssl3.nextProto.len == 0 ||
+        ss->ssl3.nextProtoState == SSL_NEXT_PROTO_SELECTED) {
 	return SECSuccess;
+    }
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
diff -pu a/nss/lib/ssl/ssl3ext.c b/nss/lib/ssl/ssl3ext.c
--- a/nss/lib/ssl/ssl3ext.c	2013-07-31 14:10:00.342814862 -0700
+++ b/nss/lib/ssl/ssl3ext.c	2013-07-31 14:28:56.549496061 -0700
@@ -53,8 +53,12 @@ static SECStatus ssl3_HandleRenegotiationInfoXtn(sslSocket *ss,
     PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss,
 			PRUint16 ex_type, SECItem *data);
+static SECStatus ssl3_ClientHandleAppProtoXtn(sslSocket *ss,
+			PRUint16 ex_type, SECItem *data);
 static SECStatus ssl3_ServerHandleNextProtoNegoXtn(sslSocket *ss,
 			PRUint16 ex_type, SECItem *data);
+static PRInt32 ssl3_ClientSendAppProtoXtn(sslSocket *ss, PRBool append,
+					       PRUint32 maxBytes);
 static PRInt32 ssl3_ClientSendNextProtoNegoXtn(sslSocket *ss, PRBool append,
 					       PRUint32 maxBytes);
 static PRInt32 ssl3_SendUseSRTPXtn(sslSocket *ss, PRBool append,
@@ -252,6 +256,7 @@ static const ssl3HelloExtensionHandler serverHelloHandlersTLS[] = {
     { ssl_session_ticket_xtn,     &ssl3_ClientHandleSessionTicketXtn },
     { ssl_renegotiation_info_xtn, &ssl3_HandleRenegotiationInfoXtn },
     { ssl_next_proto_nego_xtn,    &ssl3_ClientHandleNextProtoNegoXtn },
+    { ssl_app_layer_protocol_xtn, &ssl3_ClientHandleAppProtoXtn },
     { ssl_use_srtp_xtn,           &ssl3_HandleUseSRTPXtn },
     { ssl_channel_id_xtn,         &ssl3_ClientHandleChannelIDXtn },
     { ssl_cert_status_xtn,        &ssl3_ClientHandleStatusRequestXtn },
@@ -271,18 +276,19 @@ static const ssl3HelloExtensionHandler serverHelloHandlersSSL3[] = {
  */
 static const 
 ssl3HelloExtensionSender clientHelloSendersTLS[SSL_MAX_EXTENSIONS] = {
-    { ssl_server_name_xtn,        &ssl3_SendServerNameXtn        },
-    { ssl_renegotiation_info_xtn, &ssl3_SendRenegotiationInfoXtn },
+    { ssl_server_name_xtn,            &ssl3_SendServerNameXtn        },
+    { ssl_renegotiation_info_xtn,     &ssl3_SendRenegotiationInfoXtn },
 #ifdef NSS_ENABLE_ECC
-    { ssl_elliptic_curves_xtn,    &ssl3_SendSupportedCurvesXtn },
-    { ssl_ec_point_formats_xtn,   &ssl3_SendSupportedPointFormatsXtn },
+    { ssl_elliptic_curves_xtn,        &ssl3_SendSupportedCurvesXtn },
+    { ssl_ec_point_formats_xtn,       &ssl3_SendSupportedPointFormatsXtn },
 #endif
-    { ssl_session_ticket_xtn,     &ssl3_SendSessionTicketXtn },
-    { ssl_next_proto_nego_xtn,    &ssl3_ClientSendNextProtoNegoXtn },
-    { ssl_use_srtp_xtn,           &ssl3_SendUseSRTPXtn },
-    { ssl_channel_id_xtn,         &ssl3_ClientSendChannelIDXtn },
-    { ssl_cert_status_xtn,        &ssl3_ClientSendStatusRequestXtn },
-    { ssl_signature_algorithms_xtn, &ssl3_ClientSendSigAlgsXtn }
+    { ssl_session_ticket_xtn,         &ssl3_SendSessionTicketXtn },
+    { ssl_next_proto_nego_xtn,        &ssl3_ClientSendNextProtoNegoXtn },
+    { ssl_app_layer_protocol_xtn,     &ssl3_ClientSendAppProtoXtn },
+    { ssl_use_srtp_xtn,               &ssl3_SendUseSRTPXtn },
+    { ssl_channel_id_xtn,             &ssl3_ClientSendChannelIDXtn },
+    { ssl_cert_status_xtn,            &ssl3_ClientSendStatusRequestXtn },
+    { ssl_signature_algorithms_xtn,   &ssl3_ClientSendSigAlgsXtn }
     /* any extra entries will appear as { 0, NULL }    */
 };
 
@@ -606,6 +612,11 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
 
     PORT_Assert(!ss->firstHsDone);
 
+    if (ssl3_ExtensionNegotiated(ss, ssl_app_layer_protocol_xtn)) {
+	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+	return SECFailure;
+    }
+
     rv = ssl3_ValidateNextProtoNego(data->data, data->len);
     if (rv != SECSuccess)
 	return rv;
@@ -639,6 +650,44 @@ ssl3_ClientHandleNextProtoNegoXtn(sslSocket *ss, PRUint16 ex_type,
     return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &result);
 }
 
+static SECStatus
+ssl3_ClientHandleAppProtoXtn(sslSocket *ss, PRUint16 ex_type, SECItem *data)
+{
+    const unsigned char* d = data->data;
+    PRUint16 name_list_len;
+    SECItem protocol_name;
+
+    if (ssl3_ExtensionNegotiated(ss, ssl_next_proto_nego_xtn)) {
+	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+	return SECFailure;
+    }
+
+    /* The extension data from the server has the following format:
+     *   uint16 name_list_len;
+     *   uint8 len;
+     *   uint8 protocol_name[len]; */
+    if (data->len < 4 || data->len > 2 + 1 + 255) {
+	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+	return SECFailure;
+    }
+
+    name_list_len = ((PRUint16) d[0]) << 8 |
+	            ((PRUint16) d[1]);
+    if (name_list_len != data->len - 2 ||
+	d[2] != data->len - 3) {
+	PORT_SetError(SSL_ERROR_NEXT_PROTOCOL_DATA_INVALID);
+	return SECFailure;
+    }
+
+    protocol_name.data = data->data + 3;
+    protocol_name.len = data->len - 3;
+
+    SECITEM_FreeItem(&ss->ssl3.nextProto, PR_FALSE);
+    ss->ssl3.nextProtoState = SSL_NEXT_PROTO_SELECTED;
+    ss->xtnData.negotiated[ss->xtnData.numNegotiated++] = ex_type;
+    return SECITEM_CopyItem(NULL, &ss->ssl3.nextProto, &protocol_name);
+}
+
 static PRInt32
 ssl3_ClientSendNextProtoNegoXtn(sslSocket * ss, PRBool append,
 				PRUint32 maxBytes)
@@ -672,6 +721,70 @@ loser:
     return -1;
 }
 
+static PRInt32
+ssl3_ClientSendAppProtoXtn(sslSocket * ss, PRBool append, PRUint32 maxBytes)
+{
+    PRInt32 extension_length;
+    unsigned char *alpn_protos = NULL;
+
+    /* Renegotiations do not send this extension. */
+    if (!ss->opt.nextProtoNego.data || ss->firstHsDone) {
+	return 0;
+    }
+
+    extension_length = 2 /* extension type */ + 2 /* extension length */ +
+                       2 /* protocol name list length */ +
+                       ss->opt.nextProtoNego.len;
+
+    if (append && maxBytes >= extension_length) {
+	/* NPN requires that the client's fallback protocol is first in the
+	 * list. However, ALPN sends protocols in preference order. So we
+	 * allocate a buffer and move the first protocol to the end of the
+	 * list. */
+	SECStatus rv;
+	const unsigned int len = ss->opt.nextProtoNego.len;
+
+	alpn_protos = PORT_Alloc(len);
+	if (alpn_protos == NULL) {
+	    return SECFailure;
+	}
+	if (len > 0) {
+	    /* Each protocol string is prefixed with a single byte length. */
+	    unsigned int i = ss->opt.nextProtoNego.data[0] + 1;
+	    if (i <= len) {
+		memcpy(alpn_protos, &ss->opt.nextProtoNego.data[i], len - i);
+		memcpy(alpn_protos + len - i, ss->opt.nextProtoNego.data, i);
+	    } else {
+		/* This seems to be invalid data so we'll send as-is. */
+		memcpy(alpn_protos, ss->opt.nextProtoNego.data, len);
+	    }
+	}
+
+	rv = ssl3_AppendHandshakeNumber(ss, ssl_app_layer_protocol_xtn, 2);
+	if (rv != SECSuccess)
+	    goto loser;
+	rv = ssl3_AppendHandshakeNumber(ss, extension_length - 4, 2);
+	if (rv != SECSuccess)
+	    goto loser;
+	rv = ssl3_AppendHandshakeVariable(ss, alpn_protos, len, 2);
+	PORT_Free(alpn_protos);
+	alpn_protos = NULL;
+	if (rv != SECSuccess)
+	    goto loser;
+	ss->xtnData.advertised[ss->xtnData.numAdvertised++] =
+		ssl_app_layer_protocol_xtn;
+    } else if (maxBytes < extension_length) {
+	return 0;
+    }
+
+    return extension_length;
+
+loser:
+    if (alpn_protos)
+	PORT_Free(alpn_protos);
+    return -1;
+}
+
 static SECStatus
 ssl3_ClientHandleChannelIDXtn(sslSocket *ss, PRUint16 ex_type,
 			     SECItem *data)
diff -pu a/nss/lib/ssl/ssl.h b/nss/lib/ssl/ssl.h
--- a/nss/lib/ssl/ssl.h	2013-07-31 14:10:35.113325316 -0700
+++ b/nss/lib/ssl/ssl.h	2013-07-31 14:28:56.589496647 -0700
@@ -203,6 +203,16 @@ SSL_IMPORT SECStatus SSL_SetNextProtoCal
  * protocol in server-preference order. If no matching protocol is found it
  * selects the first supported protocol.
  *
+ * Using this function also allows the client to transparently support ALPN.
+ * The same set of protocols will be advertised via ALPN and, if the server
+ * uses ALPN to select a protocol, SSL_GetNextProto will return
+ * SSL_NEXT_PROTO_SELECTED as the state.
+ *
+ * Since NPN uses the first protocol as the fallback protocol, when sending an
+ * ALPN extension, the first protocol is moved to the end of the list. This
+ * indicates that the fallback protocol is the least preferred. The other
+ * protocols should be in preference order.
+ *
  * The supported protocols are specified in |data| in wire-format (8-bit
  * length-prefixed). For example: "\010http/1.1\006spdy/2". */
 SSL_IMPORT SECStatus SSL_SetNextProtoNego(PRFileDesc *fd,
@@ -212,7 +217,8 @@ SSL_IMPORT SECStatus SSL_SetNextProtoNeg
 typedef enum SSLNextProtoState { 
   SSL_NEXT_PROTO_NO_SUPPORT = 0, /* No peer support                */
   SSL_NEXT_PROTO_NEGOTIATED = 1, /* Mutual agreement               */
-  SSL_NEXT_PROTO_NO_OVERLAP = 2  /* No protocol overlap found      */
+  SSL_NEXT_PROTO_NO_OVERLAP = 2, /* No protocol overlap found      */
+  SSL_NEXT_PROTO_SELECTED   = 3  /* Server selected proto (ALPN)   */
 } SSLNextProtoState;
 
 /* SSL_GetNextProto can be used in the HandshakeCallback or any time after
diff -pu a/nss/lib/ssl/sslt.h b/nss/lib/ssl/sslt.h
--- a/nss/lib/ssl/sslt.h	2013-07-31 14:13:43.806096237 -0700
+++ b/nss/lib/ssl/sslt.h	2013-07-31 14:28:56.609496941 -0700
@@ -195,12 +195,13 @@ typedef enum {
 #endif
     ssl_signature_algorithms_xtn     = 13,
     ssl_use_srtp_xtn                 = 14,
+    ssl_app_layer_protocol_xtn       = 16,
     ssl_session_ticket_xtn           = 35,
     ssl_next_proto_nego_xtn          = 13172,
     ssl_channel_id_xtn               = 30031,
     ssl_renegotiation_info_xtn       = 0xff01	/* experimental number */
 } SSLExtensionType;
 
-#define SSL_MAX_EXTENSIONS             10
+#define SSL_MAX_EXTENSIONS             11
 
 #endif /* __sslt_h_ */