1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <algorithm>
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/stl_util.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/api/manifest_types.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/permissions/api_permission_set.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "extensions/common/error_utils.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "extensions/common/url_pattern.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace rcd = net::registry_controlled_domains;
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace extensions {
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace externally_connectable_errors {
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kErrorInvalid[] = "Invalid value for 'externally_connectable'";
26868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kErrorInvalidMatchPattern[] = "Invalid match pattern '*'";
27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kErrorInvalidId[] = "Invalid ID '*'";
287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const char kErrorNothingSpecified[] =
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "'externally_connectable' specifies neither 'matches' nor 'ids'; "
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    "nothing will be able to connect";
31868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kErrorTopLevelDomainsNotAllowed[] =
32868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "\"*\" is an effective top level domain for which wildcard subdomains such "
33868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "as \"*\" are not allowed";
34868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kErrorWildcardHostsNotAllowed[] =
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    "Wildcard domain patterns such as \"*\" are not allowed";
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace externally_connectable_errors
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace keys = extension_manifest_keys;
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace errors = externally_connectable_errors;
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using api::manifest_types::ExternallyConnectable;
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kAllIds[] = "*";
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)template <typename T>
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)std::vector<T> Sorted(const std::vector<T>& in) {
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::vector<T> out = in;
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  std::sort(out.begin(), out.end());
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return out;
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} // namespace
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExternallyConnectableHandler::ExternallyConnectableHandler() {}
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExternallyConnectableHandler::~ExternallyConnectableHandler() {}
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool ExternallyConnectableHandler::Parse(Extension* extension,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         string16* error) {
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::Value* externally_connectable = NULL;
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(extension->manifest()->Get(keys::kExternallyConnectable,
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   &externally_connectable));
645e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  std::vector<InstallWarning> install_warnings;
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ExternallyConnectableInfo> info =
665e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      ExternallyConnectableInfo::FromValue(*externally_connectable,
675e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                                           &install_warnings,
685e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                                           error);
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!info)
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!info->matches.is_empty()) {
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    PermissionsData::GetInitialAPIPermissions(extension)->insert(
73868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        APIPermission::kWebConnectable);
74868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
755e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  extension->AddInstallWarnings(install_warnings);
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  extension->SetManifestData(keys::kExternallyConnectable, info.release());
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const std::vector<std::string> ExternallyConnectableHandler::Keys() const {
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return SingleKey(keys::kExternallyConnectable);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExternallyConnectableInfo* ExternallyConnectableInfo::Get(
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const Extension* extension) {
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return static_cast<ExternallyConnectableInfo*>(
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extension->GetManifestData(keys::kExternallyConnectable));
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)scoped_ptr<ExternallyConnectableInfo> ExternallyConnectableInfo::FromValue(
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::Value& value,
945e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    std::vector<InstallWarning>* install_warnings,
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    string16* error) {
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<ExternallyConnectable> externally_connectable =
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      ExternallyConnectable::FromValue(value);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!externally_connectable) {
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *error = UTF8ToUTF16(errors::kErrorInvalid);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return scoped_ptr<ExternallyConnectableInfo>();
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  URLPatternSet matches;
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (externally_connectable->matches) {
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (std::vector<std::string>::iterator it =
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             externally_connectable->matches->begin();
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         it != externally_connectable->matches->end(); ++it) {
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Safe to use SCHEME_ALL here; externally_connectable gives a page ->
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // extension communication path, not the other way.
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      URLPattern pattern(URLPattern::SCHEME_ALL);
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (pattern.Parse(*it) != URLPattern::PARSE_SUCCESS) {
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            errors::kErrorInvalidMatchPattern, *it);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return scoped_ptr<ExternallyConnectableInfo>();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
118868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Wildcard hosts are not allowed.
119868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (pattern.host().empty()) {
1205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        // Warning not error for forwards compatibility.
1215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        install_warnings->push_back(
1225e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)            InstallWarning::Text(ErrorUtils::FormatErrorMessage(
1235e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                errors::kErrorWildcardHostsNotAllowed, *it)));
1245e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        continue;
125868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Wildcards on subdomains of a TLD are not allowed.
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      size_t registry_length = rcd::GetRegistryLength(
129868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          pattern.host(),
130868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          // This means that things that look like TLDs - the foobar in
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          // http://google.foobar - count as TLDs.
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          rcd::INCLUDE_UNKNOWN_REGISTRIES,
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          // This means that effective TLDs like appspot.com count as TLDs;
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          // codereview.appspot.com and evil.appspot.com are different.
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          rcd::INCLUDE_PRIVATE_REGISTRIES);
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (registry_length == std::string::npos) {
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        // The URL parsing combined with host().empty() should have caught this.
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        NOTREACHED() << *it;
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            errors::kErrorInvalidMatchPattern, *it);
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        return scoped_ptr<ExternallyConnectableInfo>();
143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Broad match patterns like "*.com", "*.co.uk", and even "*.appspot.com"
146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // are not allowed. However just "appspot.com" is ok.
147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (registry_length == 0 && pattern.match_subdomains()) {
1485e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        // Warning not error for forwards compatibility.
1495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        install_warnings->push_back(InstallWarning::Text(
1505e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)            ErrorUtils::FormatErrorMessage(
1515e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                errors::kErrorTopLevelDomainsNotAllowed,
1525e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                pattern.host().c_str(),
1535e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                *it)));
1545e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)        continue;
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      matches.AddPattern(pattern);
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::vector<std::string> ids;
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool all_ids = false;
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (externally_connectable->ids) {
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    for (std::vector<std::string>::iterator it =
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             externally_connectable->ids->begin();
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         it != externally_connectable->ids->end(); ++it) {
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (*it == kAllIds) {
169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        all_ids = true;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else if (Extension::IdIsValid(*it)) {
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        ids.push_back(*it);
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      } else {
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        *error = ErrorUtils::FormatErrorMessageUTF16(
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            errors::kErrorInvalidId, *it);
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        return scoped_ptr<ExternallyConnectableInfo>();
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!externally_connectable->matches &&
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      !externally_connectable->ids) {
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    install_warnings->push_back(InstallWarning::Text(
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        errors::kErrorNothingSpecified));
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return make_scoped_ptr(
187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      new ExternallyConnectableInfo(matches, ids, all_ids));
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExternallyConnectableInfo::~ExternallyConnectableInfo() {}
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ExternallyConnectableInfo::ExternallyConnectableInfo(
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const URLPatternSet& matches,
194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::vector<std::string>& ids,
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool all_ids)
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : matches(matches), ids(Sorted(ids)), all_ids(all_ids) {}
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool ExternallyConnectableInfo::IdCanConnect(const std::string& id) {
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (all_ids)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return true;
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(base::STLIsSorted(ids));
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return std::binary_search(ids.begin(), ids.end(), id);
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}   // namespace extensions
206