shill: Make nl80211 broadcast callback a list of callbacks.

This will allow multiple callbacks to be called when an nl80211 message
is received.  This allows a user to add a callback without displacing
others (e.g. disconnect metrics).

BUG=chromium-os:35468
TEST=unit tests, manual tests

Change-Id: I19d6cfac5754ea1d2a699de80d4465c49fec888c
Reviewed-on: https://gerrit.chromium.org/gerrit/36061
Reviewed-by: mukesh agrawal <quiche@chromium.org>
Commit-Ready: Wade Guthrie <wdg@google.com>
Tested-by: Wade Guthrie <wdg@google.com>
diff --git a/config80211_unittest.cc b/config80211_unittest.cc
index 153542e..4bcf6f2 100644
--- a/config80211_unittest.cc
+++ b/config80211_unittest.cc
@@ -11,22 +11,24 @@
 
 #include "shill/config80211.h"
 
+#include <list>
+#include <string>
+#include <vector>
+
+#include <base/bind.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <netlink/attr.h>
 #include <netlink/netlink.h>
 
-#include <string>
-#include <vector>
-
-#include <base/bind.h>
-
+#include "shill/mock_callback80211_object.h"
 #include "shill/mock_nl80211_socket.h"
 #include "shill/nl80211_socket.h"
 #include "shill/user_bound_nlmessage.h"
 
 using base::Bind;
 using base::Unretained;
+using std::list;
 using std::string;
 using std::vector;
 using testing::_;
@@ -261,10 +263,10 @@
 // ff ff c0 3f 0e 77 e8 7f c0 3f 0e 77 e8 7f c0 0e 02 00]
 
 const unsigned char kDeauthenticateFrame[] = {
- 0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f,
- 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f, 0xc0, 0x0e,
- 0x02, 0x00
+  0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f,
+  0xc0, 0x3f, 0x0e, 0x77, 0xe8, 0x7f, 0xc0, 0x0e,
+  0x02, 0x00
 };
 
 const unsigned char kNL80211_CMD_DEAUTHENTICATE[] = {
@@ -335,7 +337,7 @@
   0x03, 0x00, 0x00, 0x00,
 };
 
-}  // namespace {}
+}  // namespace
 
 class Config80211Test : public Test {
  public:
@@ -363,33 +365,34 @@
   Config80211::Callback callback_;
 };
 
-MATCHER_P(IsEqualToCallback, callback, "") {
-  const Config80211::Callback *arg_cb =
-      reinterpret_cast<const Config80211::Callback *>(arg);
-  const Config80211::Callback *callback_cb =
-      reinterpret_cast<const Config80211::Callback *>(callback);
-  if (arg_cb == callback_cb)
-    return true;
-  if (arg_cb == reinterpret_cast<const Config80211::Callback *>(NULL))
+// Checks a config80211 parameter to make sure it contains |callback_arg|
+// in its list of broadcast callbacks.
+MATCHER_P(ContainsCallback, callback_arg, "") {
+  if (arg == reinterpret_cast<void *>(NULL)) {
+    LOG(WARNING) << "NULL parameter";
     return false;
-  if (callback_cb == reinterpret_cast<const Config80211::Callback *>(NULL))
-    return arg_cb->is_null();
-  return arg_cb->Equals(*callback_cb);
+  }
+  const Config80211 *config80211 = static_cast<Config80211 *>(arg);
+  const Config80211::Callback callback =
+      static_cast<const Config80211::Callback>(callback_arg);
+
+  return config80211->FindBroadcastCallback(callback);
 }
 
 TEST_F(Config80211Test, AddLinkTest) {
   SetupConfig80211Object();
 
-  // Create a default callback.
+  // Create a broadcast callback.
   TestCallbackObject callback_object;
 
   // Install the callback and subscribe to events using it, wifi down
-  // (shouldn't actually send the subscription request).
+  // (shouldn't actually send the subscription request until wifi comes up).
   EXPECT_CALL(socket_, AddGroupMembership(_)).Times(0);
   EXPECT_CALL(socket_, DisableSequenceChecking()).Times(0);
-  EXPECT_CALL(socket_, SetNetlinkCallback(_,_)).Times(0);
+  EXPECT_CALL(socket_, SetNetlinkCallback(_, _)).Times(0);
 
-  config80211_->SetDefaultCallback(callback_object.GetCallback());
+  EXPECT_TRUE(config80211_->AddBroadcastCallback(
+      callback_object.GetCallback()));
   Config80211::EventType scan_event = Config80211::kEventTypeScan;
   string scan_event_string;
   EXPECT_TRUE(Config80211::GetEventTypeString(scan_event, &scan_event_string));
@@ -401,14 +404,14 @@
   EXPECT_CALL(socket_, DisableSequenceChecking())
       .WillOnce(Return(true));
   EXPECT_CALL(socket_, SetNetlinkCallback(
-      _, IsEqualToCallback(&callback_object.GetCallback())))
+      _, ContainsCallback(callback_object.GetCallback())))
       .WillOnce(Return(true));
   config80211_->SetWifiState(Config80211::kWifiUp);
 
   // Second subscribe, same event (should do nothing).
   EXPECT_CALL(socket_, AddGroupMembership(_)).Times(0);
   EXPECT_CALL(socket_, DisableSequenceChecking()).Times(0);
-  EXPECT_CALL(socket_, SetNetlinkCallback(_,_)).Times(0);
+  EXPECT_CALL(socket_, SetNetlinkCallback(_, _)).Times(0);
   EXPECT_TRUE(config80211_->SubscribeToEvents(scan_event));
 
   // Bring the wifi back down.
@@ -430,7 +433,7 @@
       .Times(2)
       .WillRepeatedly(Return(true));
   EXPECT_CALL(socket_, SetNetlinkCallback(
-      _, IsEqualToCallback(&callback_object.GetCallback())))
+       _, ContainsCallback(callback_object.GetCallback())))
       .Times(2)
       .WillRepeatedly(Return(true));
   config80211_->SetWifiState(Config80211::kWifiUp);