Extract SIGPIPE ignoring code to a common place.
[chromium-blink-merge.git] / chrome / common / extensions / url_pattern_set.cc
blob691e75039bd3c231f4c0733a9663cb91469a3b3d
1 // Copyright (c) 2012 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.
5 #include "chrome/common/extensions/url_pattern_set.h"
7 #include <algorithm>
8 #include <iterator>
10 #include "base/logging.h"
11 #include "base/memory/linked_ptr.h"
12 #include "base/values.h"
13 #include "chrome/common/extensions/extension_error_utils.h"
14 #include "content/public/common/url_constants.h"
15 #include "extensions/common/url_pattern.h"
16 #include "googleurl/src/gurl.h"
18 namespace {
20 const char kInvalidURLPatternError[] = "Invalid url pattern '*'";
22 } // namespace
24 // static
25 void URLPatternSet::CreateDifference(const URLPatternSet& set1,
26 const URLPatternSet& set2,
27 URLPatternSet* out) {
28 out->ClearPatterns();
29 std::set_difference(set1.patterns_.begin(), set1.patterns_.end(),
30 set2.patterns_.begin(), set2.patterns_.end(),
31 std::inserter<std::set<URLPattern> >(
32 out->patterns_, out->patterns_.begin()));
35 // static
36 void URLPatternSet::CreateIntersection(const URLPatternSet& set1,
37 const URLPatternSet& set2,
38 URLPatternSet* out) {
39 out->ClearPatterns();
40 std::set_intersection(set1.patterns_.begin(), set1.patterns_.end(),
41 set2.patterns_.begin(), set2.patterns_.end(),
42 std::inserter<std::set<URLPattern> >(
43 out->patterns_, out->patterns_.begin()));
46 // static
47 void URLPatternSet::CreateUnion(const URLPatternSet& set1,
48 const URLPatternSet& set2,
49 URLPatternSet* out) {
50 out->ClearPatterns();
51 std::set_union(set1.patterns_.begin(), set1.patterns_.end(),
52 set2.patterns_.begin(), set2.patterns_.end(),
53 std::inserter<std::set<URLPattern> >(
54 out->patterns_, out->patterns_.begin()));
57 // static
58 void URLPatternSet::CreateUnion(const std::vector<URLPatternSet>& sets,
59 URLPatternSet* out) {
60 out->ClearPatterns();
61 if (sets.empty())
62 return;
64 // N-way union algorithm is basic O(nlog(n)) merge algorithm.
66 // Do the first merge step into a working set so that we don't mutate any of
67 // the input.
68 std::vector<URLPatternSet> working;
69 for (size_t i = 0; i < sets.size(); i += 2) {
70 if (i + 1 < sets.size()) {
71 URLPatternSet u;
72 URLPatternSet::CreateUnion(sets[i], sets[i + 1], &u);
73 working.push_back(u);
74 } else {
75 working.push_back(sets[i]);
79 for (size_t skip = 1; skip < working.size(); skip *= 2) {
80 for (size_t i = 0; i < (working.size() - skip); i += skip) {
81 URLPatternSet u;
82 URLPatternSet::CreateUnion(working[i], working[i + skip], &u);
83 working[i].patterns_.swap(u.patterns_);
87 out->patterns_.swap(working[0].patterns_);
90 URLPatternSet::URLPatternSet() {}
92 URLPatternSet::URLPatternSet(const URLPatternSet& rhs)
93 : patterns_(rhs.patterns_) {}
95 URLPatternSet::URLPatternSet(const std::set<URLPattern>& patterns)
96 : patterns_(patterns) {}
98 URLPatternSet::~URLPatternSet() {}
100 URLPatternSet& URLPatternSet::operator=(const URLPatternSet& rhs) {
101 patterns_ = rhs.patterns_;
102 return *this;
105 bool URLPatternSet::operator==(const URLPatternSet& other) const {
106 return patterns_ == other.patterns_;
109 bool URLPatternSet::is_empty() const {
110 return patterns_.empty();
113 size_t URLPatternSet::size() const {
114 return patterns_.size();
117 bool URLPatternSet::AddPattern(const URLPattern& pattern) {
118 return patterns_.insert(pattern).second;
121 void URLPatternSet::AddPatterns(const URLPatternSet& set) {
122 patterns_.insert(set.patterns().begin(),
123 set.patterns().end());
126 void URLPatternSet::ClearPatterns() {
127 patterns_.clear();
130 bool URLPatternSet::Contains(const URLPatternSet& set) const {
131 return std::includes(patterns_.begin(), patterns_.end(),
132 set.patterns_.begin(), set.patterns_.end());
135 bool URLPatternSet::MatchesURL(const GURL& url) const {
136 for (URLPatternSet::const_iterator pattern = patterns_.begin();
137 pattern != patterns_.end(); ++pattern) {
138 if (pattern->MatchesURL(url))
139 return true;
142 return false;
145 bool URLPatternSet::MatchesSecurityOrigin(const GURL& origin) const {
146 for (URLPatternSet::const_iterator pattern = patterns_.begin();
147 pattern != patterns_.end(); ++pattern) {
148 if (pattern->MatchesSecurityOrigin(origin))
149 return true;
152 return false;
155 bool URLPatternSet::OverlapsWith(const URLPatternSet& other) const {
156 // Two extension extents overlap if there is any one URL that would match at
157 // least one pattern in each of the extents.
158 for (URLPatternSet::const_iterator i = patterns_.begin();
159 i != patterns_.end(); ++i) {
160 for (URLPatternSet::const_iterator j = other.patterns().begin();
161 j != other.patterns().end(); ++j) {
162 if (i->OverlapsWith(*j))
163 return true;
167 return false;
170 scoped_ptr<base::ListValue> URLPatternSet::ToValue() const {
171 scoped_ptr<ListValue> value(new ListValue);
172 for (URLPatternSet::const_iterator i = patterns_.begin();
173 i != patterns_.end(); ++i)
174 value->AppendIfNotPresent(Value::CreateStringValue(i->GetAsString()));
175 return value.Pass();
178 bool URLPatternSet::Populate(const std::vector<std::string>& patterns,
179 int valid_schemes,
180 bool allow_file_access,
181 std::string* error) {
182 ClearPatterns();
183 for (size_t i = 0; i < patterns.size(); ++i) {
184 URLPattern pattern(valid_schemes);
185 if (pattern.Parse(patterns[i]) != URLPattern::PARSE_SUCCESS) {
186 if (error) {
187 *error = ExtensionErrorUtils::FormatErrorMessage(
188 kInvalidURLPatternError, patterns[i]);
189 } else {
190 LOG(ERROR) << "Invalid url pattern: " << patterns[i];
192 return false;
194 if (!allow_file_access && pattern.MatchesScheme(chrome::kFileScheme)) {
195 pattern.SetValidSchemes(
196 pattern.valid_schemes() & ~URLPattern::SCHEME_FILE);
198 AddPattern(pattern);
200 return true;
203 bool URLPatternSet::Populate(const base::ListValue& value,
204 int valid_schemes,
205 bool allow_file_access,
206 std::string* error) {
207 std::vector<std::string> patterns;
208 for (size_t i = 0; i < value.GetSize(); ++i) {
209 std::string item;
210 if (!value.GetString(i, &item))
211 return false;
212 patterns.push_back(item);
214 return Populate(patterns, valid_schemes, allow_file_access, error);