1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_notification_observer.h"
6
7#include <vector>
8
9#include "base/logging.h"
10#include "base/strings/stringprintf.h"
11#include "extensions/common/extension.h"
12
13namespace extensions {
14
15namespace {
16
17std::string Str(const std::vector<extensions::NotificationType>& types) {
18  std::string str = "[";
19  bool needs_comma = false;
20  for (std::vector<extensions::NotificationType>::const_iterator it =
21           types.begin();
22       it != types.end();
23       ++it) {
24    if (needs_comma)
25      str += ",";
26    needs_comma = true;
27    str += base::StringPrintf("%d", *it);
28  }
29  str += "]";
30  return str;
31}
32
33}  // namespace
34
35ExtensionNotificationObserver::ExtensionNotificationObserver(
36    content::NotificationSource source,
37    const std::set<std::string>& extension_ids)
38    : extension_ids_(extension_ids) {
39  registrar_.Add(
40      this, extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED, source);
41  registrar_.Add(
42      this,
43      extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED,
44      source);
45  registrar_.Add(
46      this, extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED, source);
47}
48
49ExtensionNotificationObserver::~ExtensionNotificationObserver() {}
50
51testing::AssertionResult ExtensionNotificationObserver::CheckNotifications() {
52  return CheckNotifications(std::vector<extensions::NotificationType>());
53}
54
55testing::AssertionResult ExtensionNotificationObserver::CheckNotifications(
56    extensions::NotificationType type) {
57  return CheckNotifications(std::vector<extensions::NotificationType>(1, type));
58}
59
60testing::AssertionResult ExtensionNotificationObserver::CheckNotifications(
61    extensions::NotificationType t1,
62    extensions::NotificationType t2) {
63  std::vector<extensions::NotificationType> types;
64  types.push_back(t1);
65  types.push_back(t2);
66  return CheckNotifications(types);
67}
68
69testing::AssertionResult ExtensionNotificationObserver::CheckNotifications(
70    extensions::NotificationType t1,
71    extensions::NotificationType t2,
72    extensions::NotificationType t3) {
73  std::vector<extensions::NotificationType> types;
74  types.push_back(t1);
75  types.push_back(t2);
76  types.push_back(t3);
77  return CheckNotifications(types);
78}
79
80testing::AssertionResult ExtensionNotificationObserver::CheckNotifications(
81    extensions::NotificationType t1,
82    extensions::NotificationType t2,
83    extensions::NotificationType t3,
84    extensions::NotificationType t4,
85    extensions::NotificationType t5,
86    extensions::NotificationType t6) {
87  std::vector<extensions::NotificationType> types;
88  types.push_back(t1);
89  types.push_back(t2);
90  types.push_back(t3);
91  types.push_back(t4);
92  types.push_back(t5);
93  types.push_back(t6);
94  return CheckNotifications(types);
95}
96
97// content::NotificationObserver implementation.
98void ExtensionNotificationObserver::Observe(
99    int type,
100    const content::NotificationSource& source,
101    const content::NotificationDetails& details) {
102  switch (type) {
103    case extensions::NOTIFICATION_EXTENSION_WILL_BE_INSTALLED_DEPRECATED: {
104      const Extension* extension =
105          content::Details<const InstalledExtensionInfo>(details)->extension;
106      if (extension_ids_.count(extension->id()))
107        notifications_.push_back(
108            static_cast<extensions::NotificationType>(type));
109      break;
110    }
111
112    case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED: {
113      const Extension* extension =
114          content::Details<const Extension>(details).ptr();
115      if (extension_ids_.count(extension->id()))
116        notifications_.push_back(
117            static_cast<extensions::NotificationType>(type));
118      break;
119    }
120
121    case extensions::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
122      UnloadedExtensionInfo* reason =
123          content::Details<UnloadedExtensionInfo>(details).ptr();
124      if (extension_ids_.count(reason->extension->id())) {
125        notifications_.push_back(
126            static_cast<extensions::NotificationType>(type));
127        // The only way that extensions are unloaded in these tests is
128        // by blacklisting.
129        EXPECT_EQ(UnloadedExtensionInfo::REASON_BLACKLIST,
130                  reason->reason);
131      }
132      break;
133    }
134
135    default:
136      NOTREACHED();
137      break;
138  }
139}
140
141testing::AssertionResult ExtensionNotificationObserver::CheckNotifications(
142    const std::vector<extensions::NotificationType>& types) {
143  testing::AssertionResult result = (notifications_ == types) ?
144      testing::AssertionSuccess() :
145      testing::AssertionFailure() << "Expected " << Str(types) << ", " <<
146                                     "Got " << Str(notifications_);
147  notifications_.clear();
148  return result;
149}
150
151}  // namespace extensions
152