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 "extensions/common/extension_set.h" 6 7 #include "extensions/common/constants.h" 8 #include "extensions/common/url_pattern_set.h" 9 #include "url/gurl.h" 10 #include "url/origin.h" 11 12 namespace extensions { 13 14 namespace { 15 GetExtensionIdByURL(const GURL & url)16ExtensionId GetExtensionIdByURL(const GURL& url) { 17 if (url.SchemeIs(kExtensionScheme)) 18 return url.host(); 19 20 // Trying url::Origin is important to properly handle extension schemes inside 21 // blob: and filesystem: URLs, which won't match the extension scheme check 22 // above. 23 url::Origin origin = url::Origin::Create(url); 24 if (origin.scheme() == kExtensionScheme) 25 return origin.host(); 26 27 return ExtensionId(); 28 } 29 30 } // namespace 31 const_iterator()32ExtensionSet::const_iterator::const_iterator() {} 33 const_iterator(const const_iterator & other)34ExtensionSet::const_iterator::const_iterator(const const_iterator& other) 35 : it_(other.it_) { 36 } 37 const_iterator(ExtensionMap::const_iterator it)38ExtensionSet::const_iterator::const_iterator(ExtensionMap::const_iterator it) 39 : it_(it) { 40 } 41 ~const_iterator()42ExtensionSet::const_iterator::~const_iterator() {} 43 ExtensionSet()44ExtensionSet::ExtensionSet() { 45 } 46 ~ExtensionSet()47ExtensionSet::~ExtensionSet() { 48 } 49 size() const50size_t ExtensionSet::size() const { 51 return extensions_.size(); 52 } 53 is_empty() const54bool ExtensionSet::is_empty() const { 55 return extensions_.empty(); 56 } 57 Contains(const ExtensionId & extension_id) const58bool ExtensionSet::Contains(const ExtensionId& extension_id) const { 59 return extensions_.find(extension_id) != extensions_.end(); 60 } 61 Insert(const scoped_refptr<const Extension> & extension)62bool ExtensionSet::Insert(const scoped_refptr<const Extension>& extension) { 63 auto iter = extensions_.find(extension->id()); 64 if (iter != extensions_.end()) { 65 iter->second = extension; 66 return false; // Had a previous entry. 67 } 68 extensions_.emplace(extension->id(), extension); 69 return true; // New entry added. 70 } 71 InsertAll(const ExtensionSet & extensions)72bool ExtensionSet::InsertAll(const ExtensionSet& extensions) { 73 size_t before = size(); 74 for (ExtensionSet::const_iterator iter = extensions.begin(); 75 iter != extensions.end(); ++iter) { 76 Insert(*iter); 77 } 78 return size() != before; 79 } 80 Remove(const ExtensionId & id)81bool ExtensionSet::Remove(const ExtensionId& id) { 82 return extensions_.erase(id) > 0; 83 } 84 Clear()85void ExtensionSet::Clear() { 86 extensions_.clear(); 87 } 88 GetExtensionOrAppIDByURL(const GURL & url) const89ExtensionId ExtensionSet::GetExtensionOrAppIDByURL(const GURL& url) const { 90 ExtensionId extension_id = GetExtensionIdByURL(url); 91 if (!extension_id.empty()) 92 return extension_id; 93 94 // GetHostedAppByURL already supports filesystem: URLs (via MatchesURL). 95 // TODO(crbug/852162): Add support for blob: URLs in MatchesURL. 96 const Extension* extension = GetHostedAppByURL(url); 97 if (!extension) 98 return ExtensionId(); 99 100 return extension->id(); 101 } 102 GetExtensionOrAppByURL(const GURL & url) const103const Extension* ExtensionSet::GetExtensionOrAppByURL(const GURL& url) const { 104 ExtensionId extension_id = GetExtensionIdByURL(url); 105 if (!extension_id.empty()) 106 return GetByID(extension_id); 107 108 // GetHostedAppByURL already supports filesystem: URLs (via MatchesURL). 109 // TODO(crbug/852162): Add support for blob: URLs in MatchesURL. 110 return GetHostedAppByURL(url); 111 } 112 GetAppByURL(const GURL & url) const113const Extension* ExtensionSet::GetAppByURL(const GURL& url) const { 114 const Extension* extension = GetExtensionOrAppByURL(url); 115 return (extension && extension->is_app()) ? extension : NULL; 116 } 117 GetHostedAppByURL(const GURL & url) const118const Extension* ExtensionSet::GetHostedAppByURL(const GURL& url) const { 119 for (auto iter = extensions_.cbegin(); iter != extensions_.cend(); ++iter) { 120 if (iter->second->web_extent().MatchesURL(url)) 121 return iter->second.get(); 122 } 123 124 return NULL; 125 } 126 GetHostedAppByOverlappingWebExtent(const URLPatternSet & extent) const127const Extension* ExtensionSet::GetHostedAppByOverlappingWebExtent( 128 const URLPatternSet& extent) const { 129 for (auto iter = extensions_.cbegin(); iter != extensions_.cend(); ++iter) { 130 if (iter->second->web_extent().OverlapsWith(extent)) 131 return iter->second.get(); 132 } 133 134 return NULL; 135 } 136 InSameExtent(const GURL & old_url,const GURL & new_url) const137bool ExtensionSet::InSameExtent(const GURL& old_url, 138 const GURL& new_url) const { 139 return GetExtensionOrAppByURL(old_url) == 140 GetExtensionOrAppByURL(new_url); 141 } 142 GetByID(const ExtensionId & id) const143const Extension* ExtensionSet::GetByID(const ExtensionId& id) const { 144 auto i = extensions_.find(id); 145 if (i != extensions_.end()) 146 return i->second.get(); 147 return nullptr; 148 } 149 GetIDs() const150ExtensionIdSet ExtensionSet::GetIDs() const { 151 ExtensionIdSet ids; 152 for (auto it = extensions_.cbegin(); it != extensions_.cend(); ++it) { 153 ids.insert(it->first); 154 } 155 return ids; 156 } 157 ExtensionBindingsAllowed(const GURL & url) const158bool ExtensionSet::ExtensionBindingsAllowed(const GURL& url) const { 159 if (url.SchemeIs(kExtensionScheme)) 160 return true; 161 162 for (auto it = extensions_.cbegin(); it != extensions_.cend(); ++it) { 163 if (it->second->location() == Manifest::COMPONENT && 164 it->second->web_extent().MatchesURL(url)) 165 return true; 166 } 167 168 return false; 169 } 170 171 } // namespace extensions 172