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/browser/info_map.h" 6 7 #include "content/public/browser/browser_thread.h" 8 #include "extensions/browser/content_verifier.h" 9 #include "extensions/common/constants.h" 10 #include "extensions/common/extension.h" 11 #include "extensions/common/extension_set.h" 12 #include "extensions/common/manifest_handlers/incognito_info.h" 13 #include "extensions/common/permissions/permissions_data.h" 14 15 using content::BrowserThread; 16 17 namespace extensions { 18 19 namespace { 20 21 void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); } 22 23 } // namespace 24 25 struct InfoMap::ExtraData { 26 // When the extension was installed. 27 base::Time install_time; 28 29 // True if the user has allowed this extension to run in incognito mode. 30 bool incognito_enabled; 31 32 // True if the user has disabled notifications for this extension manually. 33 bool notifications_disabled; 34 35 ExtraData(); 36 ~ExtraData(); 37 }; 38 39 InfoMap::ExtraData::ExtraData() : incognito_enabled(false) {} 40 41 InfoMap::ExtraData::~ExtraData() {} 42 43 InfoMap::InfoMap() : signin_process_id_(-1) {} 44 45 const ProcessMap& InfoMap::process_map() const { return process_map_; } 46 47 const ProcessMap& InfoMap::worker_process_map() const { 48 return worker_process_map_; 49 } 50 51 void InfoMap::AddExtension(const Extension* extension, 52 base::Time install_time, 53 bool incognito_enabled, 54 bool notifications_disabled) { 55 CheckOnValidThread(); 56 extensions_.Insert(extension); 57 disabled_extensions_.Remove(extension->id()); 58 59 extra_data_[extension->id()].install_time = install_time; 60 extra_data_[extension->id()].incognito_enabled = incognito_enabled; 61 extra_data_[extension->id()].notifications_disabled = notifications_disabled; 62 } 63 64 void InfoMap::RemoveExtension(const std::string& extension_id, 65 const UnloadedExtensionInfo::Reason reason) { 66 CheckOnValidThread(); 67 const Extension* extension = extensions_.GetByID(extension_id); 68 extra_data_.erase(extension_id); // we don't care about disabled extra data 69 bool was_uninstalled = (reason != UnloadedExtensionInfo::REASON_DISABLE && 70 reason != UnloadedExtensionInfo::REASON_TERMINATE); 71 if (extension) { 72 if (!was_uninstalled) 73 disabled_extensions_.Insert(extension); 74 extensions_.Remove(extension_id); 75 } else if (was_uninstalled) { 76 // If the extension was uninstalled, make sure it's removed from the map of 77 // disabled extensions. 78 disabled_extensions_.Remove(extension_id); 79 } else { 80 // NOTE: This can currently happen if we receive multiple unload 81 // notifications, e.g. setting incognito-enabled state for a 82 // disabled extension (e.g., via sync). See 83 // http://code.google.com/p/chromium/issues/detail?id=50582 . 84 NOTREACHED() << extension_id; 85 } 86 } 87 88 base::Time InfoMap::GetInstallTime(const std::string& extension_id) const { 89 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); 90 if (iter != extra_data_.end()) 91 return iter->second.install_time; 92 return base::Time(); 93 } 94 95 bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const { 96 // Keep in sync with duplicate in extensions/browser/process_manager.cc. 97 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); 98 if (iter != extra_data_.end()) 99 return iter->second.incognito_enabled; 100 return false; 101 } 102 103 bool InfoMap::CanCrossIncognito(const Extension* extension) const { 104 // This is duplicated from ExtensionService :(. 105 return IsIncognitoEnabled(extension->id()) && 106 !IncognitoInfo::IsSplitMode(extension); 107 } 108 109 void InfoMap::RegisterExtensionProcess(const std::string& extension_id, 110 int process_id, 111 int site_instance_id) { 112 if (!process_map_.Insert(extension_id, process_id, site_instance_id)) { 113 NOTREACHED() << "Duplicate extension process registration for: " 114 << extension_id << "," << process_id << "."; 115 } 116 } 117 118 void InfoMap::UnregisterExtensionProcess(const std::string& extension_id, 119 int process_id, 120 int site_instance_id) { 121 if (!process_map_.Remove(extension_id, process_id, site_instance_id)) { 122 NOTREACHED() << "Unknown extension process registration for: " 123 << extension_id << "," << process_id << "."; 124 } 125 } 126 127 void InfoMap::UnregisterAllExtensionsInProcess(int process_id) { 128 process_map_.RemoveAllFromProcess(process_id); 129 } 130 131 void InfoMap::RegisterExtensionWorkerProcess(const std::string& extension_id, 132 int process_id, 133 int site_instance_id) { 134 if (!worker_process_map_.Insert(extension_id, process_id, site_instance_id)) { 135 NOTREACHED() << "Duplicate extension worker process registration for: " 136 << extension_id << "," << process_id << "."; 137 } 138 } 139 140 void InfoMap::UnregisterExtensionWorkerProcess(int process_id) { 141 worker_process_map_.RemoveAllFromProcess(process_id); 142 } 143 144 void InfoMap::GetExtensionsWithAPIPermissionForSecurityOrigin( 145 const GURL& origin, 146 int process_id, 147 APIPermission::ID permission, 148 ExtensionSet* extensions) const { 149 DCHECK(extensions); 150 151 if (origin.SchemeIs(kExtensionScheme)) { 152 const std::string& id = origin.host(); 153 const Extension* extension = extensions_.GetByID(id); 154 if (extension && 155 extension->permissions_data()->HasAPIPermission(permission) && 156 process_map_.Contains(id, process_id)) { 157 extensions->Insert(extension); 158 } 159 return; 160 } 161 162 ExtensionSet::const_iterator i = extensions_.begin(); 163 for (; i != extensions_.end(); ++i) { 164 if ((*i)->web_extent().MatchesSecurityOrigin(origin) && 165 process_map_.Contains((*i)->id(), process_id) && 166 (*i)->permissions_data()->HasAPIPermission(permission)) { 167 extensions->Insert(*i); 168 } 169 } 170 } 171 172 bool InfoMap::SecurityOriginHasAPIPermission(const GURL& origin, 173 int process_id, 174 APIPermission::ID permission) 175 const { 176 ExtensionSet extensions; 177 GetExtensionsWithAPIPermissionForSecurityOrigin( 178 origin, process_id, permission, &extensions); 179 return !extensions.is_empty(); 180 } 181 182 QuotaService* InfoMap::GetQuotaService() { 183 CheckOnValidThread(); 184 if (!quota_service_) 185 quota_service_.reset(new QuotaService()); 186 return quota_service_.get(); 187 } 188 189 void InfoMap::SetSigninProcess(int process_id) { 190 signin_process_id_ = process_id; 191 } 192 193 bool InfoMap::IsSigninProcess(int process_id) const { 194 return process_id == signin_process_id_; 195 } 196 197 void InfoMap::SetNotificationsDisabled( 198 const std::string& extension_id, 199 bool notifications_disabled) { 200 ExtraDataMap::iterator iter = extra_data_.find(extension_id); 201 if (iter != extra_data_.end()) 202 iter->second.notifications_disabled = notifications_disabled; 203 } 204 205 bool InfoMap::AreNotificationsDisabled( 206 const std::string& extension_id) const { 207 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); 208 if (iter != extra_data_.end()) 209 return iter->second.notifications_disabled; 210 return false; 211 } 212 213 void InfoMap::SetContentVerifier(ContentVerifier* verifier) { 214 content_verifier_ = verifier; 215 } 216 217 InfoMap::~InfoMap() { 218 if (quota_service_) { 219 BrowserThread::DeleteSoon( 220 BrowserThread::IO, FROM_HERE, quota_service_.release()); 221 } 222 } 223 224 } // namespace extensions 225