WebRTC should generate default private address even when adapter enumeration is disabled.

Introduce a DefaultAddressProvider such that rtc::Network can't access other part of NetworkManager.

This also removes the hack of generating the loopback address. The dependency has been removed by https://codereview.chromium.org/1417023003/

BUG=webrtc:5061
R=pthatcher@webrtc.org

Review URL: https://codereview.webrtc.org/1411253008 .

Cr-Commit-Position: refs/heads/master@{#10590}
diff --git a/talk/app/webrtc/peerconnectioninterface.h b/talk/app/webrtc/peerconnectioninterface.h
index 77caa9d..b7814e5 100644
--- a/talk/app/webrtc/peerconnectioninterface.h
+++ b/talk/app/webrtc/peerconnectioninterface.h
@@ -248,9 +248,6 @@
     // TODO(pthatcher): Rename this ice_servers, but update Chromium
     // at the same time.
     IceServers servers;
-    // A localhost candidate is signaled whenever a candidate with the any
-    // address is allocated.
-    bool enable_localhost_ice_candidate;
     BundlePolicy bundle_policy;
     RtcpMuxPolicy rtcp_mux_policy;
     TcpCandidatePolicy tcp_candidate_policy;
@@ -262,7 +259,6 @@
 
     RTCConfiguration()
         : type(kAll),
-          enable_localhost_ice_candidate(false),
           bundle_policy(kBundlePolicyBalanced),
           rtcp_mux_policy(kRtcpMuxPolicyNegotiate),
           tcp_candidate_policy(kTcpCandidatePolicyEnabled),
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index 11b2d60..1fc2a37 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -743,12 +743,6 @@
   port_allocator()->set_candidate_filter(
       ConvertIceTransportTypeToCandidateFilter(rtc_configuration.type));
 
-  if (rtc_configuration.enable_localhost_ice_candidate) {
-    port_allocator()->set_flags(
-        port_allocator()->flags() |
-        cricket::PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE);
-  }
-
   return true;
 }
 
diff --git a/webrtc/base/fakenetwork.h b/webrtc/base/fakenetwork.h
index fb99d59..4d98c6c6 100644
--- a/webrtc/base/fakenetwork.h
+++ b/webrtc/base/fakenetwork.h
@@ -76,6 +76,7 @@
   }
 
   using NetworkManagerBase::set_enumeration_permission;
+  using NetworkManagerBase::set_default_local_addresses;
 
  private:
   void DoUpdateNetworks() {
@@ -95,6 +96,7 @@
                                           it->hostname(),
                                           prefix,
                                           prefix_length));
+      net->set_default_local_address_provider(this);
       net->AddIP(it->ipaddr());
       networks.push_back(net.release());
     }
@@ -111,6 +113,9 @@
   int next_index_ = 0;
   int start_count_ = 0;
   bool sent_first_update_ = false;
+
+  IPAddress default_local_ipv4_address_;
+  IPAddress default_local_ipv6_address_;
 };
 
 }  // namespace rtc
diff --git a/webrtc/base/ipaddress.cc b/webrtc/base/ipaddress.cc
index 316207f..f0698e5 100644
--- a/webrtc/base/ipaddress.cc
+++ b/webrtc/base/ipaddress.cc
@@ -506,4 +506,15 @@
   }
   return rtc::IPAddress();
 }
+
+IPAddress GetAnyIP(int family) {
+  if (family == AF_INET) {
+    return rtc::IPAddress(INADDR_ANY);
+  }
+  if (family == AF_INET6) {
+    return rtc::IPAddress(in6addr_any);
+  }
+  return rtc::IPAddress();
+}
+
 }  // Namespace rtc
diff --git a/webrtc/base/ipaddress.h b/webrtc/base/ipaddress.h
index fe2d6e2..0789017 100644
--- a/webrtc/base/ipaddress.h
+++ b/webrtc/base/ipaddress.h
@@ -180,6 +180,7 @@
 IPAddress TruncateIP(const IPAddress& ip, int length);
 
 IPAddress GetLoopbackIP(int family);
+IPAddress GetAnyIP(int family);
 
 // Returns the number of contiguously set bits, counting from the MSB in network
 // byte order, in this IPAddress. Bits after the first 0 encountered are not
diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc
index 32b2a91..f35dcba 100644
--- a/webrtc/base/network.cc
+++ b/webrtc/base/network.cc
@@ -151,6 +151,12 @@
 
 }  // namespace
 
+// These addresses are used as the targets to find out the default local address
+// on a multi-homed endpoint. They are actually DNS servers.
+const char kPublicIPv4Host[] = "8.8.8.8";
+const char kPublicIPv6Host[] = "2001:4860:4860::8888";
+const int kPublicPort = 53;  // DNS port.
+
 std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
                            int prefix_length) {
   std::ostringstream ost;
@@ -169,6 +175,10 @@
   return ENUMERATION_ALLOWED;
 }
 
+bool NetworkManager::GetDefaultLocalAddress(int family, IPAddress* addr) const {
+  return false;
+}
+
 NetworkManagerBase::NetworkManagerBase()
     : enumeration_permission_(NetworkManager::ENUMERATION_ALLOWED),
       max_ipv6_networks_(kMaxIPv6Networks),
@@ -191,6 +201,7 @@
     const rtc::IPAddress ipv4_any_address(INADDR_ANY);
     ipv4_any_address_network_.reset(
         new rtc::Network("any", "any", ipv4_any_address, 0));
+    ipv4_any_address_network_->set_default_local_address_provider(this);
     ipv4_any_address_network_->AddIP(ipv4_any_address);
   }
   networks->push_back(ipv4_any_address_network_.get());
@@ -200,6 +211,7 @@
       const rtc::IPAddress ipv6_any_address(in6addr_any);
       ipv6_any_address_network_.reset(
           new rtc::Network("any", "any", ipv6_any_address, 0));
+      ipv6_any_address_network_->set_default_local_address_provider(this);
       ipv6_any_address_network_->AddIP(ipv6_any_address);
     }
     networks->push_back(ipv6_any_address_network_.get());
@@ -321,6 +333,28 @@
   }
 }
 
+void NetworkManagerBase::set_default_local_addresses(const IPAddress& ipv4,
+                                                     const IPAddress& ipv6) {
+  if (ipv4.family() == AF_INET) {
+    default_local_ipv4_address_ = ipv4;
+  }
+  if (ipv6.family() == AF_INET6) {
+    default_local_ipv6_address_ = ipv6;
+  }
+}
+
+bool NetworkManagerBase::GetDefaultLocalAddress(int family,
+                                                IPAddress* ipaddr) const {
+  if (family == AF_INET) {
+    *ipaddr = default_local_ipv4_address_;
+    return true;
+  } else if (family == AF_INET6) {
+    *ipaddr = default_local_ipv6_address_;
+    return true;
+  }
+  return false;
+}
+
 BasicNetworkManager::BasicNetworkManager()
     : thread_(NULL), sent_first_update_(false), start_count_(0),
       network_ignore_mask_(kDefaultNetworkIgnoreMask),
@@ -409,10 +443,9 @@
 #endif
       // TODO(phoglund): Need to recognize other types as well.
       scoped_ptr<Network> network(new Network(cursor->ifa_name,
-                                              cursor->ifa_name,
-                                              prefix,
-                                              prefix_length,
-                                              adapter_type));
+                                              cursor->ifa_name, prefix,
+                                              prefix_length, adapter_type));
+      network->set_default_local_address_provider(this);
       network->set_scope_id(scope_id);
       network->AddIP(ip);
       network->set_ignored(IsIgnoredNetwork(*network));
@@ -563,11 +596,9 @@
             // TODO(phoglund): Need to recognize other types as well.
             adapter_type = ADAPTER_TYPE_LOOPBACK;
           }
-          scoped_ptr<Network> network(new Network(name,
-                                                  description,
-                                                  prefix,
-                                                  prefix_length,
-                                                  adapter_type));
+          scoped_ptr<Network> network(new Network(name, description, prefix,
+                                                  prefix_length, adapter_type));
+          network->set_default_local_address_provider(this);
           network->set_scope_id(scope_id);
           network->AddIP(ip);
           bool ignored = IsIgnoredNetwork(*network);
@@ -724,6 +755,25 @@
   }
 }
 
+IPAddress BasicNetworkManager::QueryDefaultLocalAddress(int family) const {
+  ASSERT(thread_ == Thread::Current());
+  ASSERT(thread_->socketserver() != nullptr);
+  ASSERT(family == AF_INET || family == AF_INET6);
+
+  scoped_ptr<AsyncSocket> socket(
+      thread_->socketserver()->CreateAsyncSocket(family, SOCK_DGRAM));
+  if (!socket) {
+    return IPAddress();
+  }
+
+  if (!socket->Connect(
+          SocketAddress(family == AF_INET ? kPublicIPv4Host : kPublicIPv6Host,
+                        kPublicPort))) {
+    return IPAddress();
+  }
+  return socket->GetLocalAddress().ipaddr();
+}
+
 void BasicNetworkManager::UpdateNetworksOnce() {
   if (!start_count_)
     return;
@@ -735,7 +785,10 @@
     SignalError();
   } else {
     bool changed;
-    MergeNetworkList(list, &changed);
+    NetworkManager::Stats stats;
+    MergeNetworkList(list, &changed, &stats);
+    set_default_local_addresses(QueryDefaultLocalAddress(AF_INET),
+                                QueryDefaultLocalAddress(AF_INET6));
     if (changed || !sent_first_update_) {
       SignalNetworksChanged();
       sent_first_update_ = true;
@@ -766,21 +819,34 @@
   }
 }
 
-Network::Network(const std::string& name, const std::string& desc,
-                 const IPAddress& prefix, int prefix_length)
-    : name_(name), description_(desc), prefix_(prefix),
+Network::Network(const std::string& name,
+                 const std::string& desc,
+                 const IPAddress& prefix,
+                 int prefix_length)
+    : name_(name),
+      description_(desc),
+      prefix_(prefix),
       prefix_length_(prefix_length),
-      key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
-      ignored_(false), type_(ADAPTER_TYPE_UNKNOWN), preference_(0) {
-}
+      key_(MakeNetworkKey(name, prefix, prefix_length)),
+      scope_id_(0),
+      ignored_(false),
+      type_(ADAPTER_TYPE_UNKNOWN),
+      preference_(0) {}
 
-Network::Network(const std::string& name, const std::string& desc,
-                 const IPAddress& prefix, int prefix_length, AdapterType type)
-    : name_(name), description_(desc), prefix_(prefix),
+Network::Network(const std::string& name,
+                 const std::string& desc,
+                 const IPAddress& prefix,
+                 int prefix_length,
+                 AdapterType type)
+    : name_(name),
+      description_(desc),
+      prefix_(prefix),
       prefix_length_(prefix_length),
-      key_(MakeNetworkKey(name, prefix, prefix_length)), scope_id_(0),
-      ignored_(false), type_(type), preference_(0) {
-}
+      key_(MakeNetworkKey(name, prefix, prefix_length)),
+      scope_id_(0),
+      ignored_(false),
+      type_(type),
+      preference_(0) {}
 
 Network::~Network() = default;
 
diff --git a/webrtc/base/network.h b/webrtc/base/network.h
index ab3a88d..ccd205e 100644
--- a/webrtc/base/network.h
+++ b/webrtc/base/network.h
@@ -28,6 +28,9 @@
 
 namespace rtc {
 
+extern const char kPublicIPv4Host[];
+extern const char kPublicIPv6Host[];
+
 class Network;
 class NetworkMonitorInterface;
 class Thread;
@@ -51,9 +54,17 @@
 std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix,
                            int prefix_length);
 
+class DefaultLocalAddressProvider {
+ public:
+  virtual ~DefaultLocalAddressProvider() = default;
+  // The default local address is the local address used in multi-homed endpoint
+  // when the any address (0.0.0.0 or ::) is used as the local address.
+  virtual bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const = 0;
+};
+
 // Generic network manager interface. It provides list of local
 // networks.
-class NetworkManager {
+class NetworkManager : public DefaultLocalAddressProvider {
  public:
   typedef std::vector<Network*> NetworkList;
 
@@ -67,7 +78,7 @@
   };
 
   NetworkManager();
-  virtual ~NetworkManager();
+  ~NetworkManager() override;
 
   // Called when network list is updated.
   sigslot::signal0<> SignalNetworksChanged;
@@ -99,6 +110,8 @@
   // TODO(guoweis): remove this body when chromium implements this.
   virtual void GetAnyAddressNetworks(NetworkList* networks) {}
 
+  bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const override;
+
   // Dumps a list of networks available to LS_INFO.
   virtual void DumpNetworks(bool include_ignored) {}
 
@@ -128,6 +141,8 @@
 
   EnumerationPermission enumeration_permission() const override;
 
+  bool GetDefaultLocalAddress(int family, IPAddress* ipaddr) const override;
+
  protected:
   typedef std::map<std::string, Network*> NetworkMap;
   // Updates |networks_| with the networks listed in |list|. If
@@ -146,6 +161,9 @@
     enumeration_permission_ = state;
   }
 
+  void set_default_local_addresses(const IPAddress& ipv4,
+                                   const IPAddress& ipv6);
+
  private:
   friend class NetworkTest;
 
@@ -159,6 +177,9 @@
 
   rtc::scoped_ptr<rtc::Network> ipv4_any_address_network_;
   rtc::scoped_ptr<rtc::Network> ipv6_any_address_network_;
+
+  IPAddress default_local_ipv4_address_;
+  IPAddress default_local_ipv6_address_;
 };
 
 // Basic implementation of the NetworkManager interface that gets list
@@ -220,6 +241,11 @@
   // based on the network's property instead of any individual IP.
   bool IsIgnoredNetwork(const Network& network) const;
 
+  // This function connects a UDP socket to a public address and returns the
+  // local address associated it. Since it binds to the "any" address
+  // internally, it returns the default local address on a multi-homed endpoint.
+  IPAddress QueryDefaultLocalAddress(int family) const;
+
  private:
   friend class NetworkTest;
 
@@ -247,13 +273,26 @@
 // Represents a Unix-type network interface, with a name and single address.
 class Network {
  public:
-  Network(const std::string& name, const std::string& description,
-          const IPAddress& prefix, int prefix_length);
+  Network(const std::string& name,
+          const std::string& description,
+          const IPAddress& prefix,
+          int prefix_length);
 
-  Network(const std::string& name, const std::string& description,
-          const IPAddress& prefix, int prefix_length, AdapterType type);
+  Network(const std::string& name,
+          const std::string& description,
+          const IPAddress& prefix,
+          int prefix_length,
+          AdapterType type);
   ~Network();
 
+  const DefaultLocalAddressProvider* default_local_address_provider() {
+    return default_local_address_provider_;
+  }
+  void set_default_local_address_provider(
+      const DefaultLocalAddressProvider* provider) {
+    default_local_address_provider_ = provider;
+  }
+
   // Returns the name of the interface this network is associated wtih.
   const std::string& name() const { return name_; }
 
@@ -323,6 +362,7 @@
   std::string ToString() const;
 
  private:
+  const DefaultLocalAddressProvider* default_local_address_provider_ = nullptr;
   std::string name_;
   std::string description_;
   IPAddress prefix_;
diff --git a/webrtc/base/network_unittest.cc b/webrtc/base/network_unittest.cc
index 4362221..5324e86 100644
--- a/webrtc/base/network_unittest.cc
+++ b/webrtc/base/network_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "webrtc/base/network.h"
 
+#include "webrtc/base/nethelpers.h"
 #include "webrtc/base/networkmonitor.h"
 #include <vector>
 #if defined(WEBRTC_POSIX)
@@ -96,6 +97,11 @@
   bool callback_called_;
 };
 
+class TestBasicNetworkManager : public BasicNetworkManager {
+ public:
+  using BasicNetworkManager::QueryDefaultLocalAddress;
+};
+
 // Test that the Network ctor works properly.
 TEST_F(NetworkTest, TestNetworkConstruct) {
   Network ipv4_network1("test_eth0", "Test Network Adapter 1",
@@ -842,4 +848,19 @@
   NetworkMonitorFactory::ReleaseFactory(factory);
 }
 
+TEST_F(NetworkTest, DefaultPrivateAddress) {
+  TestBasicNetworkManager manager;
+  manager.StartUpdating();
+  std::vector<Network*> networks;
+  manager.GetNetworks(&networks);
+  for (auto& network : networks) {
+    if (network->GetBestIP().family() == AF_INET) {
+      EXPECT_TRUE(manager.QueryDefaultLocalAddress(AF_INET) != IPAddress());
+    } else if (network->GetBestIP().family() == AF_INET6) {
+      EXPECT_TRUE(manager.QueryDefaultLocalAddress(AF_INET6) != IPAddress());
+    }
+  }
+  manager.StopUpdating();
+}
+
 }  // namespace rtc
diff --git a/webrtc/p2p/base/port_unittest.cc b/webrtc/p2p/base/port_unittest.cc
index 4a4ed32..c3e5df6 100644
--- a/webrtc/p2p/base/port_unittest.cc
+++ b/webrtc/p2p/base/port_unittest.cc
@@ -456,9 +456,8 @@
   }
   UDPPort* CreateUdpPort(const SocketAddress& addr,
                          PacketSocketFactory* socket_factory) {
-    return UDPPort::Create(main_, socket_factory, &network_,
-                           addr.ipaddr(), 0, 0, username_, password_,
-                           std::string(), false);
+    return UDPPort::Create(main_, socket_factory, &network_, addr.ipaddr(), 0,
+                           0, username_, password_, std::string(), true);
   }
   TCPPort* CreateTcpPort(const SocketAddress& addr) {
     return CreateTcpPort(addr, &socket_factory_);
diff --git a/webrtc/p2p/base/portallocator.h b/webrtc/p2p/base/portallocator.h
index 4f8ec2f..38650a5 100644
--- a/webrtc/p2p/base/portallocator.h
+++ b/webrtc/p2p/base/portallocator.h
@@ -46,10 +46,14 @@
   PORTALLOCATOR_ENABLE_SHARED_UFRAG = 0x80,
   PORTALLOCATOR_ENABLE_SHARED_SOCKET = 0x100,
   PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE = 0x200,
+  // When specified, we'll only allocate the STUN candidate for the public
+  // interface as seen by regular http traffic and the HOST candidate associated
+  // with the default local interface.
   PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION = 0x400,
-  // When specified, a loopback candidate will be generated if
-  // PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION is specified.
-  PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE = 0x800,
+  // When specified along with PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION, the
+  // default local candidate mentioned above will not be allocated. Only the
+  // STUN candidate will be.
+  PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE = 0x800,
   // Disallow use of UDP when connecting to a relay server. Since proxy servers
   // usually don't handle UDP, using UDP will leak the IP address.
   PORTALLOCATOR_DISABLE_UDP_RELAY = 0x1000,
diff --git a/webrtc/p2p/base/stunport.cc b/webrtc/p2p/base/stunport.cc
index 86eaf65..ab8b2bf 100644
--- a/webrtc/p2p/base/stunport.cc
+++ b/webrtc/p2p/base/stunport.cc
@@ -13,6 +13,7 @@
 #include "webrtc/p2p/base/common.h"
 #include "webrtc/p2p/base/portallocator.h"
 #include "webrtc/p2p/base/stun.h"
+#include "webrtc/base/checks.h"
 #include "webrtc/base/common.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/ipaddress.h"
@@ -169,15 +170,19 @@
                  const std::string& username,
                  const std::string& password,
                  const std::string& origin,
-                 bool emit_localhost_for_anyaddress)
-    : Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
-           username, password),
+                 bool emit_local_for_anyaddress)
+    : Port(thread,
+           factory,
+           network,
+           socket->GetLocalAddress().ipaddr(),
+           username,
+           password),
       requests_(thread),
       socket_(socket),
       error_(0),
       ready_(false),
       stun_keepalive_delay_(KEEPALIVE_DELAY),
-      emit_localhost_for_anyaddress_(emit_localhost_for_anyaddress) {
+      emit_local_for_anyaddress_(emit_local_for_anyaddress) {
   requests_.set_origin(origin);
 }
 
@@ -190,7 +195,7 @@
                  const std::string& username,
                  const std::string& password,
                  const std::string& origin,
-                 bool emit_localhost_for_anyaddress)
+                 bool emit_local_for_anyaddress)
     : Port(thread,
            LOCAL_PORT_TYPE,
            factory,
@@ -205,7 +210,7 @@
       error_(0),
       ready_(false),
       stun_keepalive_delay_(KEEPALIVE_DELAY),
-      emit_localhost_for_anyaddress_(emit_localhost_for_anyaddress) {
+      emit_local_for_anyaddress_(emit_local_for_anyaddress) {
   requests_.set_origin(origin);
 }
 
@@ -297,13 +302,11 @@
 void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
                                   const rtc::SocketAddress& address) {
   // When adapter enumeration is disabled and binding to the any address, the
-  // loopback address will be issued as a candidate instead if
-  // |emit_localhost_for_anyaddress| is true. This is to allow connectivity on
-  // demo pages without STUN/TURN to work.
+  // default local address will be issued as a candidate instead if
+  // |emit_local_for_anyaddress| is true. This is to allow connectivity for
+  // applications which absolutely requires a HOST candidate.
   rtc::SocketAddress addr = address;
-  if (addr.IsAnyIP() && emit_localhost_for_anyaddress_) {
-    addr.SetIP(rtc::GetLoopbackIP(addr.family()));
-  }
+  MaybeSetDefaultLocalAddress(&addr);
 
   AddAddress(addr, addr, rtc::SocketAddress(), UDP_PROTOCOL_NAME, "", "",
              LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST, 0, false);
@@ -401,6 +404,19 @@
   }
 }
 
+void UDPPort::MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const {
+  if (!addr->IsAnyIP() || !emit_local_for_anyaddress_ ||
+      !Network()->default_local_address_provider()) {
+    return;
+  }
+  rtc::IPAddress default_address;
+  bool result =
+      Network()->default_local_address_provider()->GetDefaultLocalAddress(
+          addr->family(), &default_address);
+  RTC_DCHECK(result && !default_address.IsNil());
+  addr->SetIP(default_address);
+}
+
 void UDPPort::OnStunBindingRequestSucceeded(
     const rtc::SocketAddress& stun_server_addr,
     const rtc::SocketAddress& stun_reflected_addr) {
@@ -418,6 +434,7 @@
       !HasCandidateWithAddress(stun_reflected_addr)) {
 
     rtc::SocketAddress related_address = socket_->GetLocalAddress();
+    MaybeSetDefaultLocalAddress(&related_address);
     if (!(candidate_filter() & CF_HOST)) {
       // If candidate filter doesn't have CF_HOST specified, empty raddr to
       // avoid local address leakage.
diff --git a/webrtc/p2p/base/stunport.h b/webrtc/p2p/base/stunport.h
index 62b23cf..6e7a239 100644
--- a/webrtc/p2p/base/stunport.h
+++ b/webrtc/p2p/base/stunport.h
@@ -35,10 +35,9 @@
                          const std::string& username,
                          const std::string& password,
                          const std::string& origin,
-                         bool emit_localhost_for_anyaddress) {
-    UDPPort* port = new UDPPort(thread, factory, network, socket,
-                                username, password, origin,
-                                emit_localhost_for_anyaddress);
+                         bool emit_local_for_anyaddress) {
+    UDPPort* port = new UDPPort(thread, factory, network, socket, username,
+                                password, origin, emit_local_for_anyaddress);
     if (!port->Init()) {
       delete port;
       port = NULL;
@@ -55,11 +54,10 @@
                          const std::string& username,
                          const std::string& password,
                          const std::string& origin,
-                         bool emit_localhost_for_anyaddress) {
-    UDPPort* port = new UDPPort(thread, factory, network,
-                                ip, min_port, max_port,
-                                username, password, origin,
-                                emit_localhost_for_anyaddress);
+                         bool emit_local_for_anyaddress) {
+    UDPPort* port =
+        new UDPPort(thread, factory, network, ip, min_port, max_port, username,
+                    password, origin, emit_local_for_anyaddress);
     if (!port->Init()) {
       delete port;
       port = NULL;
@@ -115,7 +113,7 @@
           const std::string& username,
           const std::string& password,
           const std::string& origin,
-          bool emit_localhost_for_anyaddress);
+          bool emit_local_for_anyaddress);
 
   UDPPort(rtc::Thread* thread,
           rtc::PacketSocketFactory* factory,
@@ -124,7 +122,7 @@
           const std::string& username,
           const std::string& password,
           const std::string& origin,
-          bool emit_localhost_for_anyaddress);
+          bool emit_local_for_anyaddress);
 
   bool Init();
 
@@ -150,6 +148,10 @@
 
   void SendStunBindingRequests();
 
+  // Helper function which will set |addr|'s IP to the default local address if
+  // |addr| is the "any" address and |emit_local_for_anyaddress_| is true.
+  void MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const;
+
  private:
   // A helper class which can be called repeatedly to resolve multiple
   // addresses, as opposed to rtc::AsyncResolverInterface, which can only
@@ -211,8 +213,9 @@
   bool ready_;
   int stun_keepalive_delay_;
 
-  // This is true when PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE is specified.
-  bool emit_localhost_for_anyaddress_;
+  // This is true by default and false when
+  // PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE is specified.
+  bool emit_local_for_anyaddress_;
 
   friend class StunBindingRequest;
 };
diff --git a/webrtc/p2p/client/basicportallocator.cc b/webrtc/p2p/client/basicportallocator.cc
index 21c8921..865fbbb 100644
--- a/webrtc/p2p/client/basicportallocator.cc
+++ b/webrtc/p2p/client/basicportallocator.cc
@@ -436,7 +436,8 @@
 
   // When adapter enumeration is disabled, disable CF_HOST at port level so
   // local address is not leaked by stunport in the candidate's related address.
-  if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
+  if ((flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) &&
+      (flags() & PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE)) {
     candidate_filter &= ~CF_HOST;
   }
   port->set_candidate_filter(candidate_filter);
@@ -600,25 +601,6 @@
       return true;
     }
 
-    // If PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE is specified and it's
-    // loopback address, we should allow it as it's for demo page connectivity
-    // when no TURN/STUN specified.
-    if (c.address().IsLoopbackIP() &&
-        (flags() & PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE) != 0) {
-      return true;
-    }
-
-    // This is just to prevent the case when binding to any address (all 0s), if
-    // somehow the host candidate address is not all 0s. Either because local
-    // installed proxy changes the address or a packet has been sent for any
-    // reason before getsockname is called.
-    if (flags() & PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) {
-      LOG(LS_WARNING) << "Received non-0 host address: "
-                      << c.address().ToString()
-                      << " when adapter enumeration is disabled";
-      return false;
-    }
-
     return ((filter & CF_HOST) != 0);
   }
   return false;
@@ -882,19 +864,19 @@
   // TODO(mallinath) - Remove UDPPort creating socket after shared socket
   // is enabled completely.
   UDPPort* port = NULL;
-  bool emit_localhost_for_anyaddress =
-    IsFlagSet(PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE);
+  bool emit_local_candidate_for_anyaddress =
+      !IsFlagSet(PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
   if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
     port = UDPPort::Create(
         session_->network_thread(), session_->socket_factory(), network_,
         udp_socket_.get(), session_->username(), session_->password(),
-        session_->allocator()->origin(), emit_localhost_for_anyaddress);
+        session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
   } else {
     port = UDPPort::Create(
         session_->network_thread(), session_->socket_factory(), network_, ip_,
         session_->allocator()->min_port(), session_->allocator()->max_port(),
         session_->username(), session_->password(),
-        session_->allocator()->origin(), emit_localhost_for_anyaddress);
+        session_->allocator()->origin(), emit_local_candidate_for_anyaddress);
   }
 
   if (port) {
diff --git a/webrtc/p2p/client/portallocator_unittest.cc b/webrtc/p2p/client/portallocator_unittest.cc
index 9617688..45545f5 100644
--- a/webrtc/p2p/client/portallocator_unittest.cc
+++ b/webrtc/p2p/client/portallocator_unittest.cc
@@ -114,6 +114,12 @@
   void AddInterface(const SocketAddress& addr, const std::string& if_name) {
     network_manager_.AddInterface(addr, if_name);
   }
+  // The default route is the public address that STUN server will observe when
+  // the endpoint is sitting on the public internet and the local port is bound
+  // to the "any" address. This may be different from the default local address
+  // which the endpoint observes. This can occur if the route to the public
+  // endpoint like 8.8.8.8 (specified as the default local address) is
+  // different from the route to the STUN server (the default route).
   void AddInterfaceAsDefaultRoute(const SocketAddress& addr) {
     AddInterface(addr);
     // When a binding comes from the any address, the |addr| will be used as the
@@ -254,6 +260,8 @@
       const rtc::IPAddress& stun_candidate_addr,
       const rtc::IPAddress& relay_candidate_udp_transport_addr,
       const rtc::IPAddress& relay_candidate_tcp_transport_addr) {
+    network_manager_.set_default_local_addresses(kPrivateAddr.ipaddr(),
+                                                 rtc::IPAddress());
     if (!session_) {
       EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
     }
@@ -268,16 +276,20 @@
     if (!host_candidate_addr.IsNil()) {
       EXPECT_PRED5(CheckCandidate, candidates_[total_candidates],
                    cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
-                   rtc::SocketAddress(host_candidate_addr, 0));
+                   rtc::SocketAddress(kPrivateAddr.ipaddr(), 0));
       ++total_candidates;
     }
     if (!stun_candidate_addr.IsNil()) {
       EXPECT_PRED5(CheckCandidate, candidates_[total_candidates],
                    cricket::ICE_CANDIDATE_COMPONENT_RTP, "stun", "udp",
                    rtc::SocketAddress(stun_candidate_addr, 0));
-      EXPECT_EQ(rtc::EmptySocketAddressWithFamily(
-                    candidates_[total_candidates].address().family()),
-                candidates_[total_candidates].related_address());
+      rtc::IPAddress related_address = host_candidate_addr;
+      if (host_candidate_addr.IsNil()) {
+        related_address =
+            rtc::GetAnyIP(candidates_[total_candidates].address().family());
+      }
+      EXPECT_EQ(related_address,
+                candidates_[total_candidates].related_address().ipaddr());
       ++total_candidates;
     }
     if (!relay_candidate_udp_transport_addr.IsNil()) {
@@ -589,7 +601,6 @@
 // candidate_filter() is set to CF_RELAY and no relay is specified.
 TEST_F(PortAllocatorTest,
        TestDisableAdapterEnumerationWithoutNatRelayTransportOnly) {
-  AddInterfaceAsDefaultRoute(kClientAddr);
   ResetWithStunServerNoNat(kStunAddr);
   allocator().set_candidate_filter(cricket::CF_RELAY);
   // Expect to see no ports and no candidates.
@@ -597,86 +608,88 @@
                                  rtc::IPAddress(), rtc::IPAddress());
 }
 
-// Test that we should only get STUN and TURN candidates when adapter
-// enumeration is disabled.
-TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationBehindNat) {
-  AddInterface(kClientAddr);
-  // GTURN is not configured here.
-  ResetWithStunServerAndNat(kStunAddr);
-  AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
-  // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, and both STUN and
-  // TURN/UDP candidates.
-  CheckDisableAdapterEnumeration(3U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
-                                 kTurnUdpExtAddr.ipaddr(), rtc::IPAddress());
-}
-
-// Test that even with multiple interfaces, the result should still be one STUN
-// and one TURN candidate since we bind to any address (i.e. all 0s).
+// Test that even with multiple interfaces, the result should still be a single
+// default private, one STUN and one TURN candidate since we bind to any address
+// (i.e. all 0s).
 TEST_F(PortAllocatorTest,
        TestDisableAdapterEnumerationBehindNatMultipleInterfaces) {
   AddInterface(kPrivateAddr);
   AddInterface(kPrivateAddr2);
   ResetWithStunServerAndNat(kStunAddr);
   AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
-  // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, and both STUN and
-  // TURN/UDP candidates.
-  CheckDisableAdapterEnumeration(3U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
-                                 kTurnUdpExtAddr.ipaddr(), rtc::IPAddress());
+  // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, and a default private,
+  // STUN and TURN/UDP candidates.
+  CheckDisableAdapterEnumeration(3U, kPrivateAddr.ipaddr(),
+                                 kNatUdpAddr.ipaddr(), kTurnUdpExtAddr.ipaddr(),
+                                 rtc::IPAddress());
 }
 
-// Test that we should get STUN, TURN/UDP and TURN/TCP candidates when a
-// TURN/TCP server is specified.
+// Test that we should get a default private, STUN, TURN/UDP and TURN/TCP
+// candidates when both TURN/UDP and TURN/TCP servers are specified.
 TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationBehindNatWithTcp) {
   turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
-  AddInterface(kClientAddr);
-  // GTURN is not configured here.
+  AddInterface(kPrivateAddr);
   ResetWithStunServerAndNat(kStunAddr);
   AddTurnServers(kTurnUdpIntAddr, kTurnTcpIntAddr);
-  // Expect to see 4 ports - STUN, TURN/UDP, TURN/TCP and TCP port. STUN,
-  // TURN/UDP, and TURN/TCP candidates.
-  CheckDisableAdapterEnumeration(4U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
-                                 kTurnUdpExtAddr.ipaddr(),
+  // Expect to see 4 ports - STUN, TURN/UDP, TURN/TCP and TCP port. A default
+  // private, STUN, TURN/UDP, and TURN/TCP candidates.
+  CheckDisableAdapterEnumeration(4U, kPrivateAddr.ipaddr(),
+                                 kNatUdpAddr.ipaddr(), kTurnUdpExtAddr.ipaddr(),
                                  kTurnUdpExtAddr.ipaddr());
 }
 
-// Test that we should only get STUN and TURN candidates when adapter
-// enumeration is disabled. Since the endpoint is not behind NAT, the srflx
-// address should be the public client interface.
-TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNat) {
-  AddInterfaceAsDefaultRoute(kClientAddr);
-  ResetWithStunServerNoNat(kStunAddr);
-  AddTurnServers(kTurnUdpIntAddr, rtc::SocketAddress());
-  // Expect to see 3 ports: STUN, TURN/UDP and TCP ports, but only both STUN and
-  // TURN candidates. The STUN candidate should have kClientAddr as srflx
-  // address, and TURN candidate with kClientAddr as the related address.
-  CheckDisableAdapterEnumeration(3U, rtc::IPAddress(), kClientAddr.ipaddr(),
-                                 kTurnUdpExtAddr.ipaddr(), rtc::IPAddress());
+// Test that when adapter enumeration is disabled, for endpoints without
+// STUN/TURN specified, a default private candidate is still generated.
+TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNatOrServers) {
+  ResetWithNoServersOrNat();
+  // Expect to see 2 ports: STUN and TCP ports, one default private candidate.
+  CheckDisableAdapterEnumeration(2U, kPrivateAddr.ipaddr(), rtc::IPAddress(),
+                                 rtc::IPAddress(), rtc::IPAddress());
 }
 
-// Test that when adapter enumeration is disabled, for endpoints without
-// STUN/TURN specified, no candidate is generated.
-TEST_F(PortAllocatorTest, TestDisableAdapterEnumerationWithoutNatOrServers) {
-  AddInterfaceAsDefaultRoute(kClientAddr);
-  ResetWithNoServersOrNat();
-  // Expect to see 2 ports: STUN and TCP ports, but no candidate.
+// Test that when adapter enumeration is disabled, with
+// PORTALLOCATOR_DISABLE_LOCALHOST_CANDIDATE specified, for endpoints not behind
+// a NAT, there is no local candidate.
+TEST_F(PortAllocatorTest,
+       TestDisableAdapterEnumerationWithoutNatLocalhostCandidateDisabled) {
+  ResetWithStunServerNoNat(kStunAddr);
+  EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+  session_->set_flags(cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
+  // Expect to see 2 ports: STUN and TCP ports, localhost candidate and STUN
+  // candidate.
   CheckDisableAdapterEnumeration(2U, rtc::IPAddress(), rtc::IPAddress(),
                                  rtc::IPAddress(), rtc::IPAddress());
 }
 
 // Test that when adapter enumeration is disabled, with
-// PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE specified, for endpoints not behind
-// a NAT, there are a localhost candidate in addition to a STUN candidate.
-TEST_F(PortAllocatorTest,
-       TestDisableAdapterEnumerationWithoutNatLocalhostCandidateRequested) {
-  AddInterfaceAsDefaultRoute(kClientAddr);
+// PORTALLOCATOR_DISABLE_LOCALHOST_CANDIDATE specified, for endpoints not behind
+// a NAT, there is no local candidate. However, this specified default route
+// (kClientAddr) which was discovered when sending STUN requests, will become
+// the srflx addresses.
+TEST_F(
+    PortAllocatorTest,
+    TestDisableAdapterEnumerationWithoutNatLocalhostCandidateDisabledWithDifferentDefaultRoute) {
   ResetWithStunServerNoNat(kStunAddr);
+  AddInterfaceAsDefaultRoute(kClientAddr);
   EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
-  session_->set_flags(cricket::PORTALLOCATOR_ENABLE_LOCALHOST_CANDIDATE);
+  session_->set_flags(cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
   // Expect to see 2 ports: STUN and TCP ports, localhost candidate and STUN
   // candidate.
-  CheckDisableAdapterEnumeration(2U, rtc::GetLoopbackIP(AF_INET),
-                                 kClientAddr.ipaddr(), rtc::IPAddress(),
-                                 rtc::IPAddress());
+  CheckDisableAdapterEnumeration(2U, rtc::IPAddress(), kClientAddr.ipaddr(),
+                                 rtc::IPAddress(), rtc::IPAddress());
+}
+
+// Test that when adapter enumeration is disabled, with
+// PORTALLOCATOR_DISABLE_LOCALHOST_CANDIDATE specified, for endpoints behind a
+// NAT, there is only one STUN candidate.
+TEST_F(PortAllocatorTest,
+       TestDisableAdapterEnumerationWithNatLocalhostCandidateDisabled) {
+  ResetWithStunServerAndNat(kStunAddr);
+  EXPECT_TRUE(CreateSession(cricket::ICE_CANDIDATE_COMPONENT_RTP));
+  session_->set_flags(cricket::PORTALLOCATOR_DISABLE_DEFAULT_LOCAL_CANDIDATE);
+  // Expect to see 2 ports: STUN and TCP ports, and single STUN candidate.
+  CheckDisableAdapterEnumeration(2U, rtc::IPAddress(), kNatUdpAddr.ipaddr(),
+                                 rtc::IPAddress(), rtc::IPAddress());
 }
 
 // Test that we disable relay over UDP, and only TCP is used when connecting to
@@ -1244,7 +1257,8 @@
 // adapters, the PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION is specified
 // automatically.
 TEST_F(PortAllocatorTest, TestNetworkPermissionBlocked) {
-  AddInterface(kClientAddr);
+  network_manager_.set_default_local_addresses(kPrivateAddr.ipaddr(),
+                                               rtc::IPAddress());
   network_manager_.set_enumeration_permission(
       rtc::NetworkManager::ENUMERATION_BLOCKED);
   allocator().set_flags(allocator().flags() |
@@ -1258,7 +1272,10 @@
                     cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION);
   session_->StartGettingPorts();
   EXPECT_EQ_WAIT(1U, ports_.size(), kDefaultAllocationTimeout);
-  EXPECT_EQ(0U, candidates_.size());
+  EXPECT_EQ(1U, candidates_.size());
+  EXPECT_PRED5(CheckCandidate, candidates_[0],
+               cricket::ICE_CANDIDATE_COMPONENT_RTP, "local", "udp",
+               kPrivateAddr);
   EXPECT_TRUE((session_->flags() &
                cricket::PORTALLOCATOR_DISABLE_ADAPTER_ENUMERATION) != 0);
 }