| Index: webrtc/pc/mediasession_unittest.cc
 | 
| diff --git a/webrtc/pc/mediasession_unittest.cc b/webrtc/pc/mediasession_unittest.cc
 | 
| index a6f6658d81fd39d191aa1297440c31146e19cf86..8f60f129e266e34954d55e71cbf2f38266971347 100644
 | 
| --- a/webrtc/pc/mediasession_unittest.cc
 | 
| +++ b/webrtc/pc/mediasession_unittest.cc
 | 
| @@ -73,6 +73,8 @@ using cricket::SEC_ENABLED;
 | 
|  using cricket::SEC_REQUIRED;
 | 
|  using rtc::CS_AES_CM_128_HMAC_SHA1_32;
 | 
|  using rtc::CS_AES_CM_128_HMAC_SHA1_80;
 | 
| +using rtc::CS_AEAD_AES_128_GCM;
 | 
| +using rtc::CS_AEAD_AES_256_GCM;
 | 
|  
 | 
|  static const AudioCodec kAudioCodecs1[] = {
 | 
|      AudioCodec(103, "ISAC", 16000, -1, 1),
 | 
| @@ -444,6 +446,52 @@ class MediaSessionDescriptionFactoryTest : public testing::Test {
 | 
|      return true;
 | 
|    }
 | 
|  
 | 
| +  void TestVideoGcmCipher(bool gcm_offer, bool gcm_answer) {
 | 
| +    MediaSessionOptions offer_opts;
 | 
| +    offer_opts.recv_video = true;
 | 
| +    offer_opts.crypto_options.enable_gcm_crypto_suites = gcm_offer;
 | 
| +    MediaSessionOptions answer_opts;
 | 
| +    answer_opts.recv_video = true;
 | 
| +    answer_opts.crypto_options.enable_gcm_crypto_suites = gcm_answer;
 | 
| +    f1_.set_secure(SEC_ENABLED);
 | 
| +    f2_.set_secure(SEC_ENABLED);
 | 
| +    rtc::scoped_ptr<SessionDescription> offer(
 | 
| +        f1_.CreateOffer(offer_opts, NULL));
 | 
| +    ASSERT_TRUE(offer.get() != NULL);
 | 
| +    rtc::scoped_ptr<SessionDescription> answer(
 | 
| +        f2_.CreateAnswer(offer.get(), answer_opts, NULL));
 | 
| +    const ContentInfo* ac = answer->GetContentByName("audio");
 | 
| +    const ContentInfo* vc = answer->GetContentByName("video");
 | 
| +    ASSERT_TRUE(ac != NULL);
 | 
| +    ASSERT_TRUE(vc != NULL);
 | 
| +    EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
 | 
| +    EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
 | 
| +    const AudioContentDescription* acd =
 | 
| +        static_cast<const AudioContentDescription*>(ac->description);
 | 
| +    const VideoContentDescription* vcd =
 | 
| +        static_cast<const VideoContentDescription*>(vc->description);
 | 
| +    EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
 | 
| +    EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
 | 
| +    EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
 | 
| +    EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
 | 
| +    EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
 | 
| +    if (gcm_offer && gcm_answer) {
 | 
| +      ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
 | 
| +    } else {
 | 
| +      ASSERT_CRYPTO(acd, 1U, CS_AES_CM_128_HMAC_SHA1_32);
 | 
| +    }
 | 
| +    EXPECT_EQ(MEDIA_TYPE_VIDEO, vcd->type());
 | 
| +    EXPECT_EQ(MAKE_VECTOR(kVideoCodecsAnswer), vcd->codecs());
 | 
| +    EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
 | 
| +    EXPECT_TRUE(vcd->rtcp_mux());                 // negotiated rtcp-mux
 | 
| +    if (gcm_offer && gcm_answer) {
 | 
| +      ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
 | 
| +    } else {
 | 
| +      ASSERT_CRYPTO(vcd, 1U, CS_AES_CM_128_HMAC_SHA1_80);
 | 
| +    }
 | 
| +    EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
 | 
| +  }
 | 
| +
 | 
|   protected:
 | 
|    MediaSessionDescriptionFactory f1_;
 | 
|    MediaSessionDescriptionFactory f2_;
 | 
| @@ -757,6 +805,34 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswer) {
 | 
|    EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
 | 
|  }
 | 
|  
 | 
| +// Create a typical audio answer with GCM ciphers enabled, and ensure it
 | 
| +// matches what we expect.
 | 
| +TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAudioAnswerGcm) {
 | 
| +  f1_.set_secure(SEC_ENABLED);
 | 
| +  f2_.set_secure(SEC_ENABLED);
 | 
| +  MediaSessionOptions options;
 | 
| +  options.crypto_options.enable_gcm_crypto_suites = true;
 | 
| +  rtc::scoped_ptr<SessionDescription> offer(
 | 
| +      f1_.CreateOffer(options, NULL));
 | 
| +  ASSERT_TRUE(offer.get() != NULL);
 | 
| +  rtc::scoped_ptr<SessionDescription> answer(
 | 
| +      f2_.CreateAnswer(offer.get(), options, NULL));
 | 
| +  const ContentInfo* ac = answer->GetContentByName("audio");
 | 
| +  const ContentInfo* vc = answer->GetContentByName("video");
 | 
| +  ASSERT_TRUE(ac != NULL);
 | 
| +  ASSERT_TRUE(vc == NULL);
 | 
| +  EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
 | 
| +  const AudioContentDescription* acd =
 | 
| +      static_cast<const AudioContentDescription*>(ac->description);
 | 
| +  EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
 | 
| +  EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
 | 
| +  EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
 | 
| +  EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
 | 
| +  EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
 | 
| +  ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
 | 
| +  EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), acd->protocol());
 | 
| +}
 | 
| +
 | 
|  // Create a typical video answer, and ensure it matches what we expect.
 | 
|  TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
 | 
|    MediaSessionOptions opts;
 | 
| @@ -791,6 +867,24 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswer) {
 | 
|    EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
 | 
|  }
 | 
|  
 | 
| +// Create a typical video answer with GCM ciphers enabled, and ensure it
 | 
| +// matches what we expect.
 | 
| +TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcm) {
 | 
| +  TestVideoGcmCipher(true, true);
 | 
| +}
 | 
| +
 | 
| +// Create a typical video answer with GCM ciphers enabled for the offer only,
 | 
| +// and ensure it matches what we expect.
 | 
| +TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmOffer) {
 | 
| +  TestVideoGcmCipher(true, false);
 | 
| +}
 | 
| +
 | 
| +// Create a typical video answer with GCM ciphers enabled for the answer only,
 | 
| +// and ensure it matches what we expect.
 | 
| +TEST_F(MediaSessionDescriptionFactoryTest, TestCreateVideoAnswerGcmAnswer) {
 | 
| +  TestVideoGcmCipher(false, true);
 | 
| +}
 | 
| +
 | 
|  TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
 | 
|    MediaSessionOptions opts;
 | 
|    opts.data_channel_type = cricket::DCT_RTP;
 | 
| @@ -824,6 +918,40 @@ TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswer) {
 | 
|    EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
 | 
|  }
 | 
|  
 | 
| +TEST_F(MediaSessionDescriptionFactoryTest, TestCreateDataAnswerGcm) {
 | 
| +  MediaSessionOptions opts;
 | 
| +  opts.data_channel_type = cricket::DCT_RTP;
 | 
| +  opts.crypto_options.enable_gcm_crypto_suites = true;
 | 
| +  f1_.set_secure(SEC_ENABLED);
 | 
| +  f2_.set_secure(SEC_ENABLED);
 | 
| +  rtc::scoped_ptr<SessionDescription> offer(f1_.CreateOffer(opts, NULL));
 | 
| +  ASSERT_TRUE(offer.get() != NULL);
 | 
| +  rtc::scoped_ptr<SessionDescription> answer(
 | 
| +      f2_.CreateAnswer(offer.get(), opts, NULL));
 | 
| +  const ContentInfo* ac = answer->GetContentByName("audio");
 | 
| +  const ContentInfo* vc = answer->GetContentByName("data");
 | 
| +  ASSERT_TRUE(ac != NULL);
 | 
| +  ASSERT_TRUE(vc != NULL);
 | 
| +  EXPECT_EQ(std::string(NS_JINGLE_RTP), ac->type);
 | 
| +  EXPECT_EQ(std::string(NS_JINGLE_RTP), vc->type);
 | 
| +  const AudioContentDescription* acd =
 | 
| +      static_cast<const AudioContentDescription*>(ac->description);
 | 
| +  const DataContentDescription* vcd =
 | 
| +      static_cast<const DataContentDescription*>(vc->description);
 | 
| +  EXPECT_EQ(MEDIA_TYPE_AUDIO, acd->type());
 | 
| +  EXPECT_EQ(MAKE_VECTOR(kAudioCodecsAnswer), acd->codecs());
 | 
| +  EXPECT_EQ(kAutoBandwidth, acd->bandwidth());  // negotiated auto bw
 | 
| +  EXPECT_NE(0U, acd->first_ssrc());             // a random nonzero ssrc
 | 
| +  EXPECT_TRUE(acd->rtcp_mux());                 // negotiated rtcp-mux
 | 
| +  ASSERT_CRYPTO(acd, 1U, CS_AEAD_AES_256_GCM);
 | 
| +  EXPECT_EQ(MEDIA_TYPE_DATA, vcd->type());
 | 
| +  EXPECT_EQ(MAKE_VECTOR(kDataCodecsAnswer), vcd->codecs());
 | 
| +  EXPECT_NE(0U, vcd->first_ssrc());             // a random nonzero ssrc
 | 
| +  EXPECT_TRUE(vcd->rtcp_mux());                 // negotiated rtcp-mux
 | 
| +  ASSERT_CRYPTO(vcd, 1U, CS_AEAD_AES_256_GCM);
 | 
| +  EXPECT_EQ(std::string(cricket::kMediaProtocolSavpf), vcd->protocol());
 | 
| +}
 | 
| +
 | 
|  // Verifies that the order of the media contents in the offer is preserved in
 | 
|  // the answer.
 | 
|  TEST_F(MediaSessionDescriptionFactoryTest, TestCreateAnswerContentOrder) {
 | 
| 
 |