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#ifndef EXTENSIONS_COMMON_EXTENSION_SET_H_
6#define EXTENSIONS_COMMON_EXTENSION_SET_H_
7
8#include <iterator>
9#include <map>
10#include <string>
11
12#include "base/callback.h"
13#include "base/gtest_prod_util.h"
14#include "base/memory/ref_counted.h"
15#include "extensions/common/extension.h"
16#include "url/gurl.h"
17
18namespace extensions {
19
20// The one true extension container. Extensions are identified by their id.
21// Only one extension can be in the set with a given ID.
22class ExtensionSet {
23 public:
24  typedef std::pair<base::FilePath, std::string> ExtensionPathAndDefaultLocale;
25  typedef std::map<std::string, scoped_refptr<const Extension> > ExtensionMap;
26  typedef base::Callback<void(const ExtensionIdSet&)>
27      ModificationCallback;
28
29  // Iteration over the values of the map (given that it's an ExtensionSet,
30  // it should iterate like a set iterator).
31  class const_iterator : public std::iterator<std::input_iterator_tag,
32                                              scoped_refptr<const Extension> > {
33   public:
34    const_iterator();
35    const_iterator(const const_iterator& other);
36    explicit const_iterator(ExtensionMap::const_iterator it);
37    ~const_iterator();
38    const_iterator& operator++() {
39      ++it_;
40      return *this;
41    }
42    const_iterator operator++(int) {
43      const const_iterator old(*this);
44      ++it_;
45      return old;
46    }
47    const scoped_refptr<const Extension>& operator*() const {
48      return it_->second;
49    }
50    const scoped_refptr<const Extension>* operator->() const {
51      return &it_->second;
52    }
53    bool operator!=(const const_iterator& other) const {
54      return it_ != other.it_;
55    }
56    bool operator==(const const_iterator& other) const {
57      return it_ == other.it_;
58    }
59
60   private:
61    ExtensionMap::const_iterator it_;
62  };
63
64  ExtensionSet();
65  ~ExtensionSet();
66
67  size_t size() const;
68  bool is_empty() const;
69
70  // Iteration support.
71  const_iterator begin() const { return const_iterator(extensions_.begin()); }
72  const_iterator end() const { return const_iterator(extensions_.end()); }
73
74  // Returns true if the set contains the specified extension.
75  bool Contains(const std::string& id) const;
76
77  // Adds the specified extension to the set. The set becomes an owner. Any
78  // previous extension with the same ID is removed.
79  // Returns true if there is no previous extension.
80  bool Insert(const scoped_refptr<const Extension>& extension);
81
82  // Copies different items from |extensions| to the current set and returns
83  // whether anything changed.
84  bool InsertAll(const ExtensionSet& extensions);
85
86  // Removes the specified extension.
87  // Returns true if the set contained the specified extnesion.
88  bool Remove(const std::string& id);
89
90  // Removes all extensions.
91  void Clear();
92
93  // Returns the extension ID, or empty if none. This includes web URLs that
94  // are part of an extension's web extent.
95  std::string GetExtensionOrAppIDByURL(const GURL& url) const;
96
97  // Returns the Extension, or NULL if none.  This includes web URLs that are
98  // part of an extension's web extent.
99  // NOTE: This can return NULL if called before UpdateExtensions receives
100  // bulk extension data (e.g. if called from
101  // EventBindings::HandleContextCreated)
102  const Extension* GetExtensionOrAppByURL(const GURL& url) const;
103
104  // Returns the app specified by the given |url|, if one exists. This will
105  // return NULL if there is no entry with |url|, or if the extension with
106  // |url| is not an app.
107  const Extension* GetAppByURL(const GURL& url) const;
108
109  // Returns the hosted app whose web extent contains the URL.
110  const Extension* GetHostedAppByURL(const GURL& url) const;
111
112  // Returns a hosted app that contains any URL that overlaps with the given
113  // extent, if one exists.
114  const Extension* GetHostedAppByOverlappingWebExtent(
115      const URLPatternSet& extent) const;
116
117  // Returns true if |new_url| is in the extent of the same extension as
118  // |old_url|.  Also returns true if neither URL is in an app.
119  bool InSameExtent(const GURL& old_url, const GURL& new_url) const;
120
121  // Look up an Extension object by id.
122  const Extension* GetByID(const std::string& id) const;
123
124  // Gets the IDs of all extensions in the set.
125  ExtensionIdSet GetIDs() const;
126
127  // Returns true if |info| should get extension api bindings and be permitted
128  // to make api calls. Note that this is independent of what extension
129  // permissions the given extension has been granted.
130  bool ExtensionBindingsAllowed(const GURL& url) const;
131
132  void set_modification_callback(
133      const ModificationCallback& modification_callback) {
134    modification_callback_ = modification_callback;
135  }
136
137 private:
138  FRIEND_TEST_ALL_PREFIXES(ExtensionSetTest, ExtensionSet);
139
140  ExtensionMap extensions_;
141
142  // If non-null, called with the extension ids in this set after a modification
143  // occurred. This is not called on Clear() which is typically used when
144  // discarding the set (e.g., on shutdown) and we do not want to track that as
145  // a real modification.
146  ModificationCallback modification_callback_;
147
148  DISALLOW_COPY_AND_ASSIGN(ExtensionSet);
149};
150
151}  // namespace extensions
152
153#endif  // EXTENSIONS_COMMON_EXTENSION_SET_H_
154