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