15976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org/*
25976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * libjingle
35976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Copyright 2004--2005, Google Inc.
45976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
55976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * Redistribution and use in source and binary forms, with or without
65976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * modification, are permitted provided that the following conditions are met:
75976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
85976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
95976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer.
105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     this list of conditions and the following disclaimer in the documentation
125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     and/or other materials provided with the distribution.
135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *  3. The name of the author may not be used to endorse or promote products
145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *     derived from this software without specific prior written permission.
155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org *
165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org */
275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <vector>
295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <string>
305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <map>
315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <algorithm>
325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <sstream>
335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include <iostream>
345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/common.h"
355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/base/stringencode.h"
365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/constants.h"
375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org#include "talk/xmpp/rostermoduleimpl.h"
385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgnamespace buzz {
405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// enum prase and persist helpers ----------------------------------------------
425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool
435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgStringToPresenceShow(const std::string& input, XmppPresenceShow* show) {
445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // If this becomes a perf issue we can use a hash or a map here
455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (STR_SHOW_AWAY == input)
465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *show = XMPP_PRESENCE_AWAY;
475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (STR_SHOW_DND == input)
485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *show = XMPP_PRESENCE_DND;
495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (STR_SHOW_XA == input)
505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *show = XMPP_PRESENCE_XA;
515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (STR_SHOW_CHAT == input)
525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *show = XMPP_PRESENCE_CHAT;
535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (STR_EMPTY == input)
545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *show = XMPP_PRESENCE_DEFAULT;
555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else
565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool
625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgPresenceShowToString(XmppPresenceShow show, const char** output) {
635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  switch(show) {
645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case XMPP_PRESENCE_AWAY:
655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *output = STR_SHOW_AWAY;
665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case XMPP_PRESENCE_CHAT:
685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *output = STR_SHOW_CHAT;
695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case XMPP_PRESENCE_XA:
715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *output = STR_SHOW_XA;
725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case XMPP_PRESENCE_DND:
745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *output = STR_SHOW_DND;
755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    case XMPP_PRESENCE_DEFAULT:
775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *output = STR_EMPTY;
785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  *output = STR_EMPTY;
825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool
865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgStringToSubscriptionState(const std::string& subscription,
875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          const std::string& ask,
885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                          XmppSubscriptionState* state)
895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org{
905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (ask == "subscribe")
915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (subscription == "none") {
935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *state = XMPP_SUBSCRIPTION_NONE_ASKED;
945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (subscription == "from") {
975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *state = XMPP_SUBSCRIPTION_FROM_ASKED;
985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (ask == STR_EMPTY)
1015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
1025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (subscription == "none") {
1035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *state = XMPP_SUBSCRIPTION_NONE;
1045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
1055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (subscription == "from") {
1075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *state = XMPP_SUBSCRIPTION_FROM;
1085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
1095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (subscription == "to") {
1115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *state = XMPP_SUBSCRIPTION_TO;
1125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
1135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (subscription == "both") {
1155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *state = XMPP_SUBSCRIPTION_BOTH;
1165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
1175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
1185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
1195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
1215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgstatic bool
1245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgStringToSubscriptionRequestType(const std::string& string,
1255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                XmppSubscriptionRequestType* type)
1265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org{
1275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (string == "subscribe")
1285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *type = XMPP_REQUEST_SUBSCRIBE;
1295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (string == "unsubscribe")
1305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *type = XMPP_REQUEST_UNSUBSCRIBE;
1315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (string == "subscribed")
1325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *type = XMPP_REQUEST_SUBSCRIBED;
1335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (string == "unsubscribed")
1345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *type = XMPP_REQUEST_UNSUBSCRIBED;
1355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else
1365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return false;
1375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return true;
1385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// XmppPresenceImpl class ------------------------------------------------------
1415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresence*
1425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresence::Create() {
1435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return new XmppPresenceImpl();
1445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::XmppPresenceImpl() {
1475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst Jid
1505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::jid() const {
1515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
1525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return Jid();
1535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return Jid(raw_xml_->Attr(QN_FROM));
1555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceAvailable
1585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::available() const {
1595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
1605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_PRESENCE_UNAVAILABLE;
1615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (raw_xml_->Attr(QN_TYPE) == "unavailable")
1635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_PRESENCE_UNAVAILABLE;
1645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (raw_xml_->Attr(QN_TYPE) == "error")
1655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_PRESENCE_ERROR;
1665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else
1675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_PRESENCE_AVAILABLE;
1685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
1715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::set_available(XmppPresenceAvailable available) {
1725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
1735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
1745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (available == XMPP_PRESENCE_AVAILABLE)
1765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->ClearAttr(QN_TYPE);
1775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (available == XMPP_PRESENCE_UNAVAILABLE)
1785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->SetAttr(QN_TYPE, "unavailable");
1795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else if (available == XMPP_PRESENCE_ERROR)
1805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->SetAttr(QN_TYPE, "error");
1815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
1825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceShow
1855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::presence_show() const {
1865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
1875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_PRESENCE_DEFAULT;
1885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmppPresenceShow show = XMPP_PRESENCE_DEFAULT;
1905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  StringToPresenceShow(raw_xml_->TextNamed(QN_SHOW), &show);
1915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return show;
1925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
1955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::set_presence_show(XmppPresenceShow show) {
1965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
1975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
1985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
1995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const char* show_string;
2005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if(!PresenceShowToString(show, &show_string))
2025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
2035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_->ClearNamedChildren(QN_SHOW);
2055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (show!=XMPP_PRESENCE_DEFAULT) {
2075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->AddElement(new XmlElement(QN_SHOW));
2085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->AddText(show_string, 1);
2095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
2125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgint
2155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::priority() const {
2165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
2175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return 0;
2185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  int raw_priority = 0;
2205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!talk_base::FromString(raw_xml_->TextNamed(QN_PRIORITY), &raw_priority))
2215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_priority = 0;
2225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (raw_priority < -128)
2235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_priority = -128;
2245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (raw_priority > 127)
2255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_priority = 127;
2265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return raw_priority;
2285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
2315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::set_priority(int priority) {
2325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
2335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
2345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (priority < -128 || priority > 127)
2365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
2375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_->ClearNamedChildren(QN_PRIORITY);
2395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (0 != priority) {
2405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string priority_string;
2415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (talk_base::ToString(priority, &priority_string)) {
2425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      raw_xml_->AddElement(new XmlElement(QN_PRIORITY));
2435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      raw_xml_->AddText(priority_string, 1);
2445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
2485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string
2515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::status() const {
2525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
2535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return STR_EMPTY;
2545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement* status_element;
2565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement* element;
2575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Search for a status element with no xml:lang attribute on it.  if we can't
2595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // find that then just return the first status element in the stanza.
2605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (status_element = element = raw_xml_->FirstNamed(QN_STATUS);
2615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       element;
2625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       element = element->NextNamed(QN_STATUS)) {
2635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!element->HasAttr(QN_XML_LANG)) {
2645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      status_element = element;
2655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      break;
2665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
2675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (status_element) {
2705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return status_element->BodyText();
2715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return STR_EMPTY;
2745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
2775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::set_status(const std::string& status) {
2785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
2795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
2805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_->ClearNamedChildren(QN_STATUS);
2825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (status != STR_EMPTY) {
2845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->AddElement(new XmlElement(QN_STATUS));
2855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->AddText(status, 1);
2865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
2875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
2895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
2905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceConnectionStatus
2925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::connection_status() const {
2935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
2945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return XMPP_CONNECTION_STATUS_UNKNOWN;
2955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
2965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement* con = raw_xml_->FirstNamed(QN_GOOGLE_PSTN_CONFERENCE_STATUS);
2975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (con) {
2985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    std::string status = con->Attr(QN_ATTR_STATUS);
2995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTING)
3005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return XMPP_CONNECTION_STATUS_CONNECTING;
3015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    else if (status == STR_PSTN_CONFERENCE_STATUS_CONNECTED)
3025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return XMPP_CONNECTION_STATUS_CONNECTED;
303204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org    else if (status == STR_PSTN_CONFERENCE_STATUS_JOINING)
304204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org            return XMPP_CONNECTION_STATUS_JOINING;
3055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    else if (status == STR_PSTN_CONFERENCE_STATUS_HANGUP)
3065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        return XMPP_CONNECTION_STATUS_HANGUP;
3075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_CONNECTION_STATUS_CONNECTED;
3105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string
3135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::google_user_id() const {
3145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
3155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return std::string();
3165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement* muc_user_x = raw_xml_->FirstNamed(QN_MUC_USER_X);
3185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (muc_user_x) {
3195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmlElement* muc_user_item = muc_user_x->FirstNamed(QN_MUC_USER_ITEM);
3205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (muc_user_item) {
3215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return muc_user_item->Attr(QN_GOOGLE_USER_ID);
3225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
3235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return std::string();
3265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string
3295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::nickname() const {
3305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
3315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return std::string();
3325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement* nickname = raw_xml_->FirstNamed(QN_NICKNAME);
3345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (nickname) {
3355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return nickname->BodyText();
3365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
3375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return std::string();
3395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst XmlElement*
3425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::raw_xml() const {
3435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
3445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const_cast<XmppPresenceImpl*>(this)->CreateRawXmlSkeleton();
3455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return raw_xml_.get();
3465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
3495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::set_raw_xml(const XmlElement * xml) {
3505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!xml ||
3515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      xml->Name() != QN_PRESENCE)
3525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
3535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
354204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org  const std::string& type = xml->Attr(QN_TYPE);
355204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org  if (type != STR_EMPTY && type != "unavailable")
356204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org    return XMPP_RETURN_BADARGUMENT;
3575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
358204b178db6a965bcdee700f384174d4303e8e9d8stefan@webrtc.org  raw_xml_.reset(new XmlElement(*xml));
3595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
3605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
3635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresenceImpl::CreateRawXmlSkeleton() {
3645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_.reset(new XmlElement(QN_PRESENCE));
3655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// XmppRosterContactImpl -------------------------------------------------------
3685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContact*
3695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContact::Create() {
3705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return new XmppRosterContactImpl();
3715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::XmppRosterContactImpl() {
3745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ResetGroupCache();
3755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
3785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::SetXmlFromWire(const XmlElement* xml) {
3795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ResetGroupCache();
3805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (xml)
3815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_.reset(new XmlElement(*xml));
3825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else
3835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_.reset(NULL);
3845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
3875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::ResetGroupCache() {
3885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  group_count_ = -1;
3895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  group_index_returned_ = -1;
3905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  group_returned_ = NULL;
3915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst Jid
3945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::jid() const {
3955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return Jid(raw_xml_->Attr(QN_JID));
3965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
3975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
3985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
3995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::set_jid(const Jid& jid)
4005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org{
4015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
4025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
4035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!jid.IsValid())
4055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
4065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_->SetAttr(QN_JID, jid.Str());
4085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
4105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string
4135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::name() const {
4145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return raw_xml_->Attr(QN_NAME);
4155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
4185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::set_name(const std::string& name) {
4195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
4205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
4215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (name == STR_EMPTY)
4235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->ClearAttr(QN_NAME);
4245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  else
4255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->SetAttr(QN_NAME, name);
4265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
4285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppSubscriptionState
4315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::subscription_state() const {
4325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
4335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_SUBSCRIPTION_NONE;
4345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmppSubscriptionState state = XMPP_SUBSCRIPTION_NONE;
4365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (StringToSubscriptionState(raw_xml_->Attr(QN_SUBSCRIPTION),
4385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                raw_xml_->Attr(QN_ASK),
4395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                &state))
4405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return state;
4415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_SUBSCRIPTION_NONE;
4435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgsize_t
4465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::GetGroupCount() const {
4475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
4485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return 0;
4495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (-1 == group_count_) {
4515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmlElement *group_element = raw_xml_->FirstNamed(QN_ROSTER_GROUP);
4525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    int group_count = 0;
4535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    while(group_element) {
4545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      group_count++;
4555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      group_element = group_element->NextNamed(QN_ROSTER_GROUP);
4565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
4575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(group_count > 0); // protect the cast
4595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
4605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    me->group_count_ = group_count;
4615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return group_count_;
4645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst std::string
4675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::GetGroup(size_t index) const {
4685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (index >= GetGroupCount())
4695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return STR_EMPTY;
4705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // We cache the last group index and element that we returned.  This way
4725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // going through the groups in order is order n and not n^2.  This could be
4735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // enhanced if necessary by starting at the cached value if the index asked
4745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // is after the cached one.
4755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (group_index_returned_ >= 0 &&
4765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      index == static_cast<size_t>(group_index_returned_) + 1)
4775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
4785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
4795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    me->group_returned_ = group_returned_->NextNamed(QN_ROSTER_GROUP);
4805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ASSERT(group_returned_ != NULL);
4815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    me->group_index_returned_++;
4825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (group_index_returned_ < 0 ||
4835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org             static_cast<size_t>(group_index_returned_) != index) {
4845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmlElement * group_element = raw_xml_->FirstNamed(QN_ROSTER_GROUP);
4855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    size_t group_index = 0;
4865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    while(group_index < index) {
4875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      ASSERT(group_element != NULL);
4885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      group_index++;
4895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      group_element = group_element->NextNamed(QN_ROSTER_GROUP);
4905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
4915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmppRosterContactImpl * me = const_cast<XmppRosterContactImpl*>(this);
4935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    me->group_index_returned_ = static_cast<int>(group_index);
4945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    me->group_returned_ = group_element;
4955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
4965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
4975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return group_returned_->BodyText();
4985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
4995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
5015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::AddGroup(const std::string& group) {
5025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (group == STR_EMPTY)
5035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
5045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
5065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    CreateRawXmlSkeleton();
5075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (FindGroup(group, NULL, NULL))
5095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_OK;
5105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_->AddElement(new XmlElement(QN_ROSTER_GROUP));
5125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_->AddText(group, 1);
5135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ++group_count_;
5145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
5165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
5195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::RemoveGroup(const std::string& group) {
5205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (group == STR_EMPTY)
5215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
5225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
5245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_OK;
5255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlChild * child_before;
5275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (FindGroup(group, NULL, &child_before)) {
5285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    raw_xml_->RemoveChildAfter(child_before);
5295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ResetGroupCache();
5305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
5325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool
5355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::FindGroup(const std::string& group,
5365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                 XmlElement** element,
5375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                 XmlChild** child_before) {
5385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlChild * prev_child = NULL;
5395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlChild * next_child;
5405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlChild * child;
5415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (child = raw_xml_->FirstChild(); child; child = next_child) {
5425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    next_child = child->NextChild();
5435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!child->IsText() &&
5445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        child->AsElement()->Name() == QN_ROSTER_GROUP &&
5455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        child->AsElement()->BodyText() == group) {
5465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (element)
5475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        *element = child->AsElement();
5485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (child_before)
5495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        *child_before = prev_child;
5505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return true;
5515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
5525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    prev_child = child;
5535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
5545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
5565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst XmlElement*
5595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::raw_xml() const {
5605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!raw_xml_)
5615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const_cast<XmppRosterContactImpl*>(this)->CreateRawXmlSkeleton();
5625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return raw_xml_.get();
5635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
5665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::set_raw_xml(const XmlElement* xml) {
5675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!xml ||
5685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      xml->Name() != QN_ROSTER_ITEM ||
5695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      xml->HasAttr(QN_SUBSCRIPTION) ||
5705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      xml->HasAttr(QN_ASK))
5715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
5725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ResetGroupCache();
5745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_.reset(new XmlElement(*xml));
5765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
5785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
5815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterContactImpl::CreateRawXmlSkeleton() {
5825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  raw_xml_.reset(new XmlElement(QN_ROSTER_ITEM));
5835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org// XmppRosterModuleImpl --------------------------------------------------------
5865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModule *
5875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModule::Create() {
5885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return new XmppRosterModuleImpl();
5895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::XmppRosterModuleImpl() :
5925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_handler_(NULL),
5935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  incoming_presence_map_(new JidPresenceVectorMap()),
5945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  incoming_presence_vector_(new PresenceVector()),
5955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  contacts_(new ContactVector()) {
5965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
5985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
5995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::~XmppRosterModuleImpl() {
6005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DeleteIncomingPresence();
6015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  DeleteContacts();
6025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
6055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::set_roster_handler(XmppRosterHandler * handler) {
6065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_handler_ = handler;
6075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return XMPP_RETURN_OK;
6085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterHandler*
6115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::roster_handler() {
6125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return roster_handler_;
6135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppPresence*
6165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::outgoing_presence() {
6175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return &outgoing_presence_;
6185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
6215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::BroadcastPresence() {
6225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Scrub the outgoing presence
6235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const XmlElement* element = outgoing_presence_.raw_xml();
6245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(!element->HasAttr(QN_TO) &&
6265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         !element->HasAttr(QN_FROM) &&
6275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          (element->Attr(QN_TYPE) == STR_EMPTY ||
6285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org           element->Attr(QN_TYPE) == "unavailable"));
6295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!engine())
6315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADSTATE;
6325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return engine()->SendStanza(element);
6345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
6375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::SendDirectedPresence(const XmppPresence* presence,
6385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                           const Jid& to_jid) {
6395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!presence)
6405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
6415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!engine())
6435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADSTATE;
6445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement element(*(presence->raw_xml()));
6465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (element.Name() != QN_PRESENCE ||
6485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      element.HasAttr(QN_TO) ||
6495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      element.HasAttr(QN_FROM))
6505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
6515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (element.HasAttr(QN_TYPE)) {
6535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (element.Attr(QN_TYPE) != STR_EMPTY &&
6545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        element.Attr(QN_TYPE) != "unavailable") {
6555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return XMPP_RETURN_BADARGUMENT;
6565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
6575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
6585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  element.SetAttr(QN_TO, to_jid.Str());
6605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return engine()->SendStanza(&element);
6625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgsize_t
6655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::GetIncomingPresenceCount() {
6665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return incoming_presence_vector_->size();
6675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst XmppPresence*
6705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::GetIncomingPresence(size_t index) {
6715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (index >= incoming_presence_vector_->size())
6725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
6735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (*incoming_presence_vector_)[index];
6745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgsize_t
6775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::GetIncomingPresenceForJidCount(const Jid& jid)
6785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org{
6795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // find the vector in the map
6805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  JidPresenceVectorMap::iterator pos;
6815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  pos = incoming_presence_map_->find(jid);
6825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (pos == incoming_presence_map_->end())
6835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return 0;
6845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(pos->second != NULL);
6865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return pos->second->size();
6885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
6895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst XmppPresence*
6915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::GetIncomingPresenceForJid(const Jid& jid,
6925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                size_t index) {
6935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  JidPresenceVectorMap::iterator pos;
6945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  pos = incoming_presence_map_->find(jid);
6955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (pos == incoming_presence_map_->end())
6965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
6975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
6985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(pos->second != NULL);
6995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (index >= pos->second->size())
7015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
7025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (*pos->second)[index];
7045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
7075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::RequestRosterUpdate() {
7085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!engine())
7095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADSTATE;
7105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement roster_get(QN_IQ);
7125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_get.AddAttr(QN_TYPE, "get");
7135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_get.AddAttr(QN_ID, engine()->NextId());
7145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_get.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
7155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return engine()->SendIq(&roster_get, this, NULL);
7165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgsize_t
7195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::GetRosterContactCount() {
7205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return contacts_->size();
7215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst XmppRosterContact*
7245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::GetRosterContact(size_t index) {
7255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (index >= contacts_->size())
7265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
7275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return (*contacts_)[index];
7285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass RosterPredicate {
7315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgpublic:
7325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit RosterPredicate(const Jid& jid) : jid_(jid) {
7335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool operator() (XmppRosterContactImpl *& contact) {
7365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return contact->jid() == jid_;
7375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
7385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgprivate:
7405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Jid jid_;
7415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
7425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgconst XmppRosterContact*
7445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::FindRosterContact(const Jid& jid) {
7455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ContactVector::iterator pos;
7465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  pos = std::find_if(contacts_->begin(),
7485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     contacts_->end(),
7495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                     RosterPredicate(jid));
7505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (pos == contacts_->end())
7515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return NULL;
7525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return *pos;
7545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
7575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::RequestRosterChange(
7585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const XmppRosterContact* contact) {
7595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!contact)
7605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
7615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Jid jid = contact->jid();
7635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!jid.IsValid())
7655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
7665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!engine())
7685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADSTATE;
7695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const XmlElement* contact_xml = contact->raw_xml();
7715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (contact_xml->Name() != QN_ROSTER_ITEM ||
7725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      contact_xml->HasAttr(QN_SUBSCRIPTION) ||
7735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      contact_xml->HasAttr(QN_ASK))
7745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
7755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement roster_add(QN_IQ);
7775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddAttr(QN_TYPE, "set");
7785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddAttr(QN_ID, engine()->NextId());
7795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
7805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddElement(new XmlElement(*contact_xml), 1);
7815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return engine()->SendIq(&roster_add, this, NULL);
7835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
7845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
7865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::RequestRosterRemove(const Jid& jid) {
7875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!jid.IsValid())
7885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
7895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!engine())
7915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADSTATE;
7925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
7935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement roster_add(QN_IQ);
7945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddAttr(QN_TYPE, "set");
7955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddAttr(QN_ID, engine()->NextId());
7965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddElement(new XmlElement(QN_ROSTER_QUERY, true));
7975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddAttr(QN_JID, jid.Str(), 1);
7985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  roster_add.AddAttr(QN_SUBSCRIPTION, "remove", 1);
7995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return engine()->SendIq(&roster_add, this, NULL);
8015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
8045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::RequestSubscription(const Jid& jid) {
8055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return SendSubscriptionRequest(jid, "subscribe");
8065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
8095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::CancelSubscription(const Jid& jid) {
8105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return SendSubscriptionRequest(jid, "unsubscribe");
8115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
8145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::ApproveSubscriber(const Jid& jid) {
8155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return SendSubscriptionRequest(jid, "subscribed");
8165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
8195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::CancelSubscriber(const Jid& jid) {
8205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return SendSubscriptionRequest(jid, "unsubscribed");
8215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
8245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::IqResponse(XmppIqCookie, const XmlElement * stanza) {
8255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // The only real Iq response that we expect to recieve are initial roster
8265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // population
8275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (stanza->Attr(QN_TYPE) == "error")
8285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
8295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (roster_handler_)
8305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      roster_handler_->RosterError(this, stanza);
8315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return;
8335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(stanza->Attr(QN_TYPE) == "result");
8365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  InternalRosterItems(stanza);
8385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgbool
8415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::HandleStanza(const XmlElement * stanza)
8425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org{
8435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(engine() != NULL);
8445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // There are two types of stanzas that we care about: presence and roster push
8465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Iqs
8475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (stanza->Name() == QN_PRESENCE) {
8485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string&  jid_string = stanza->Attr(QN_FROM);
8495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Jid jid(jid_string);
8505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!jid.IsValid())
8525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false; // if the Jid isn't valid, don't process
8535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& type = stanza->Attr(QN_TYPE);
8555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmppSubscriptionRequestType request_type;
8565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (StringToSubscriptionRequestType(type, &request_type))
8575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      InternalSubscriptionRequest(jid, stanza, request_type);
8585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    else if (type == "unavailable" || type == STR_EMPTY)
8595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      InternalIncomingPresence(jid, stanza);
8605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    else if (type == "error")
8615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      InternalIncomingPresenceError(jid, stanza);
8625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    else
8635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
8645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
8665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else if (stanza->Name() == QN_IQ) {
8675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const XmlElement * roster_query = stanza->FirstNamed(QN_ROSTER_QUERY);
8685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!roster_query || stanza->Attr(QN_TYPE) != "set")
8695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      return false;
8705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    InternalRosterItems(stanza);
8725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // respond to the IQ
8745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmlElement result(QN_IQ);
8755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    result.AddAttr(QN_TYPE, "result");
8765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    result.AddAttr(QN_TO, stanza->Attr(QN_FROM));
8775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    result.AddAttr(QN_ID, stanza->Attr(QN_ID));
8785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    engine()->SendStanza(&result);
8805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return true;
8815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
8825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return false;
8845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
8855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
8865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
8875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::DeleteIncomingPresence() {
8885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Clear out the vector of all presence notifications
8895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
8905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    PresenceVector::iterator pos;
8915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for (pos = incoming_presence_vector_->begin();
8925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         pos < incoming_presence_vector_->end();
8935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         ++pos) {
8945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      XmppPresenceImpl * presence = *pos;
8955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      *pos = NULL;
8965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete presence;
8975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
8985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    incoming_presence_vector_->clear();
8995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Clear out all of the small presence vectors per Jid
9025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
9035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    JidPresenceVectorMap::iterator pos;
9045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    for (pos = incoming_presence_map_->begin();
9055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         pos != incoming_presence_map_->end();
9065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org         ++pos) {
9075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      PresenceVector* presence_vector = pos->second;
9085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      pos->second = NULL;
9095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete presence_vector;
9105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
9115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    incoming_presence_map_->clear();
9125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
9165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::DeleteContacts() {
9175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ContactVector::iterator pos;
9185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (pos = contacts_->begin();
9195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       pos < contacts_->end();
9205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       ++pos) {
9215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    XmppRosterContact* contact = *pos;
9225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    *pos = NULL;
9235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    delete contact;
9245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  contacts_->clear();
9265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppReturnStatus
9295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::SendSubscriptionRequest(const Jid& jid,
9305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                              const std::string& type) {
9315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!jid.IsValid())
9325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADARGUMENT;
9335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!engine())
9355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return XMPP_RETURN_BADSTATE;
9365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmlElement presence_request(QN_PRESENCE);
9385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  presence_request.AddAttr(QN_TO, jid.Str());
9395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  presence_request.AddAttr(QN_TYPE, type);
9405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  return engine()->SendStanza(&presence_request);
9425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
9465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::InternalSubscriptionRequest(const Jid& jid,
9475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                  const XmlElement* stanza,
9485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                  XmppSubscriptionRequestType
9495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                    request_type) {
9505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (roster_handler_)
9515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    roster_handler_->SubscriptionRequest(this, jid, request_type, stanza);
9525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
9535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgclass PresencePredicate {
9555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgpublic:
9565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  explicit PresencePredicate(const Jid& jid) : jid_(jid) {
9575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool operator() (XmppPresenceImpl *& contact) {
9605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return contact->jid() == jid_;
9615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgprivate:
9645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Jid jid_;
9655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org};
9665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
9685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::InternalIncomingPresence(const Jid& jid,
9695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                               const XmlElement* stanza) {
9705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool added = false;
9715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  Jid bare_jid = jid.BareJid();
9725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // First add the presence to the map
9745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  JidPresenceVectorMap::iterator pos;
9755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  pos = incoming_presence_map_->find(jid.BareJid());
9765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (pos == incoming_presence_map_->end()) {
9775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // Insert a new entry into the map.  Get the position of this new entry
9785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    pos = (incoming_presence_map_->insert(
9795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            std::make_pair(bare_jid, new PresenceVector()))).first;
9805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
9815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  PresenceVector * presence_vector = pos->second;
9835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  ASSERT(presence_vector != NULL);
9845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Try to find this jid in the bare jid bucket
9865976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  PresenceVector::iterator presence_pos;
9875976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  XmppPresenceImpl* presence;
9885976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  presence_pos = std::find_if(presence_vector->begin(),
9895976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                              presence_vector->end(),
9905976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                              PresencePredicate(jid));
9915976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
9925976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Update/add it to the bucket
9935976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (presence_pos == presence_vector->end()) {
9945976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    presence = new XmppPresenceImpl();
9955976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (XMPP_RETURN_OK == presence->set_raw_xml(stanza)) {
9965976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      added = true;
9975976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      presence_vector->push_back(presence);
9985976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else {
9995976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      delete presence;
10005976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      presence = NULL;
10015976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
10025976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  } else {
10035976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    presence = *presence_pos;
10045976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    presence->set_raw_xml(stanza);
10055976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10065976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10075976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // now add to the comprehensive vector
10085976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (added)
10095976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    incoming_presence_vector_->push_back(presence);
10105976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10115976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Call back to the user with the changed presence information
10125976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (roster_handler_)
10135976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    roster_handler_->IncomingPresenceChanged(this, presence);
10145976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10155976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10165976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10175976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
10185976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::InternalIncomingPresenceError(const Jid& jid,
10195976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                                                    const XmlElement* stanza) {
10205976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (roster_handler_)
10215976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    roster_handler_->SubscriptionError(this, jid, stanza);
10225976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10235976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10245976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgvoid
10255976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.orgXmppRosterModuleImpl::InternalRosterItems(const XmlElement* stanza) {
10265976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  const XmlElement* result_data = stanza->FirstNamed(QN_ROSTER_QUERY);
10275976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (!result_data)
10285976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    return; // unknown stuff in result!
10295976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10305976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  bool all_new = contacts_->empty();
10315976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10325976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  for (const XmlElement* roster_item = result_data->FirstNamed(QN_ROSTER_ITEM);
10335976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       roster_item;
10345976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org       roster_item = roster_item->NextNamed(QN_ROSTER_ITEM))
10355976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  {
10365976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    const std::string& jid_string = roster_item->Attr(QN_JID);
10375976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    Jid jid(jid_string);
10385976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!jid.IsValid())
10395976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      continue;
10405976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10415976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // This algorithm is N^2 on the number of incoming contacts after the
10425976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // initial load. There is no way to do this faster without allowing
10435976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // duplicates, introducing more data structures or write a custom data
10445976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // structure.  We'll see if this becomes a perf problem and fix it if it
10455976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    // does.
10465976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    ContactVector::iterator pos = contacts_->end();
10475976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10485976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (!all_new) {
10495976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      pos = std::find_if(contacts_->begin(),
10505976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         contacts_->end(),
10515976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org                         RosterPredicate(jid));
10525976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
10535976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10545976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    if (pos != contacts_->end()) { // Update/remove a current contact
10555976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (roster_item->Attr(QN_SUBSCRIPTION) == "remove") {
10565976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        XmppRosterContact* contact = *pos;
10575976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        contacts_->erase(pos);
10585976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        if (roster_handler_)
10595976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          roster_handler_->ContactRemoved(this, contact,
10605976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            std::distance(contacts_->begin(), pos));
10615976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        delete contact;
10625976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      } else {
10635976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        XmppRosterContact* old_contact = *pos;
10645976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        *pos = new XmppRosterContactImpl();
10655976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        (*pos)->SetXmlFromWire(roster_item);
10665976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        if (roster_handler_)
10675976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org          roster_handler_->ContactChanged(this, old_contact,
10685976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org            std::distance(contacts_->begin(), pos));
10695976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        delete old_contact;
10705976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      }
10715976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    } else { // Add a new contact
10725976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      XmppRosterContactImpl* contact = new XmppRosterContactImpl();
10735976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      contact->SetXmlFromWire(roster_item);
10745976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      contacts_->push_back(contact);
10755976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org      if (roster_handler_ && !all_new)
10765976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org        roster_handler_->ContactsAdded(this, contacts_->size() - 1, 1);
10775976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    }
10785976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  }
10795976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10805976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  // Send a consolidated update if all contacts are new
10815976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org  if (roster_handler_ && all_new)
10825976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org    roster_handler_->ContactsAdded(this, 0, contacts_->size());
10835976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
10845976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org
10855976650443d68ccfadf1dea24999ee459dd2819mflodman@webrtc.org}
1086