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. 4 5 #include "chrome/browser/extensions/extension_info_map.h" 6 7 #include "chrome/common/extensions/extension.h" 8 #include "chrome/common/extensions/extension_set.h" 9 #include "chrome/common/extensions/incognito_handler.h" 10 #include "chrome/common/url_constants.h" 11 #include "content/public/browser/browser_thread.h" 12 #include "extensions/common/constants.h" 13 14 using content::BrowserThread; 15 using extensions::Extension; 16 17 namespace { 18 19 void CheckOnValidThread() { 20 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 21 } 22 23 } // namespace 24 25 struct ExtensionInfoMap::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 ExtraData(); 33 ~ExtraData(); 34 }; 35 36 ExtensionInfoMap::ExtraData::ExtraData() : incognito_enabled(false) {} 37 38 ExtensionInfoMap::ExtraData::~ExtraData() {} 39 40 ExtensionInfoMap::ExtensionInfoMap() : signin_process_id_(-1) {} 41 42 const extensions::ProcessMap& ExtensionInfoMap::process_map() const { 43 return process_map_; 44 } 45 46 void ExtensionInfoMap::AddExtension(const Extension* extension, 47 base::Time install_time, 48 bool incognito_enabled) { 49 CheckOnValidThread(); 50 extensions_.Insert(extension); 51 disabled_extensions_.Remove(extension->id()); 52 53 extra_data_[extension->id()].install_time = install_time; 54 extra_data_[extension->id()].incognito_enabled = incognito_enabled; 55 } 56 57 void ExtensionInfoMap::RemoveExtension(const std::string& extension_id, 58 const extension_misc::UnloadedExtensionReason reason) { 59 CheckOnValidThread(); 60 const Extension* extension = extensions_.GetByID(extension_id); 61 extra_data_.erase(extension_id); // we don't care about disabled extra data 62 bool was_uninstalled = (reason != extension_misc::UNLOAD_REASON_DISABLE && 63 reason != extension_misc::UNLOAD_REASON_TERMINATE); 64 if (extension) { 65 if (!was_uninstalled) 66 disabled_extensions_.Insert(extension); 67 extensions_.Remove(extension_id); 68 } else if (was_uninstalled) { 69 // If the extension was uninstalled, make sure it's removed from the map of 70 // disabled extensions. 71 disabled_extensions_.Remove(extension_id); 72 } else { 73 // NOTE: This can currently happen if we receive multiple unload 74 // notifications, e.g. setting incognito-enabled state for a 75 // disabled extension (e.g., via sync). See 76 // http://code.google.com/p/chromium/issues/detail?id=50582 . 77 NOTREACHED() << extension_id; 78 } 79 } 80 81 base::Time ExtensionInfoMap::GetInstallTime( 82 const std::string& extension_id) const { 83 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); 84 if (iter != extra_data_.end()) 85 return iter->second.install_time; 86 return base::Time(); 87 } 88 89 bool ExtensionInfoMap::IsIncognitoEnabled( 90 const std::string& extension_id) const { 91 // Keep in sync with duplicate in extension_process_manager.cc. 92 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); 93 if (iter != extra_data_.end()) 94 return iter->second.incognito_enabled; 95 return false; 96 } 97 98 bool ExtensionInfoMap::CanCrossIncognito(const Extension* extension) const { 99 // This is duplicated from ExtensionService :(. 100 return IsIncognitoEnabled(extension->id()) && 101 !extensions::IncognitoInfo::IsSplitMode(extension); 102 } 103 104 void ExtensionInfoMap::RegisterExtensionProcess(const std::string& extension_id, 105 int process_id, 106 int site_instance_id) { 107 if (!process_map_.Insert(extension_id, process_id, site_instance_id)) { 108 NOTREACHED() << "Duplicate extension process registration for: " 109 << extension_id << "," << process_id << "."; 110 } 111 } 112 113 void ExtensionInfoMap::UnregisterExtensionProcess( 114 const std::string& extension_id, 115 int process_id, 116 int site_instance_id) { 117 if (!process_map_.Remove(extension_id, process_id, site_instance_id)) { 118 NOTREACHED() << "Unknown extension process registration for: " 119 << extension_id << "," << process_id << "."; 120 } 121 } 122 123 void ExtensionInfoMap::UnregisterAllExtensionsInProcess(int process_id) { 124 process_map_.RemoveAllFromProcess(process_id); 125 } 126 127 void ExtensionInfoMap::GetExtensionsWithAPIPermissionForSecurityOrigin( 128 const GURL& origin, 129 int process_id, 130 extensions::APIPermission::ID permission, 131 ExtensionSet* extensions) const { 132 DCHECK(extensions); 133 134 if (origin.SchemeIs(extensions::kExtensionScheme)) { 135 const std::string& id = origin.host(); 136 const Extension* extension = extensions_.GetByID(id); 137 if (extension && extension->HasAPIPermission(permission) && 138 process_map_.Contains(id, process_id)) { 139 extensions->Insert(extension); 140 } 141 return; 142 } 143 144 ExtensionSet::const_iterator i = extensions_.begin(); 145 for (; i != extensions_.end(); ++i) { 146 if ((*i)->web_extent().MatchesSecurityOrigin(origin) && 147 process_map_.Contains((*i)->id(), process_id) && 148 (*i)->HasAPIPermission(permission)) { 149 extensions->Insert(*i); 150 } 151 } 152 } 153 154 bool ExtensionInfoMap::SecurityOriginHasAPIPermission( 155 const GURL& origin, int process_id, 156 extensions::APIPermission::ID permission) const { 157 ExtensionSet extensions; 158 GetExtensionsWithAPIPermissionForSecurityOrigin( 159 origin, process_id, permission, &extensions); 160 return !extensions.is_empty(); 161 } 162 163 ExtensionsQuotaService* ExtensionInfoMap::GetQuotaService() { 164 CheckOnValidThread(); 165 if (!quota_service_) 166 quota_service_.reset(new ExtensionsQuotaService()); 167 return quota_service_.get(); 168 } 169 170 void ExtensionInfoMap::SetSigninProcess(int process_id) { 171 signin_process_id_ = process_id; 172 } 173 174 bool ExtensionInfoMap::IsSigninProcess(int process_id) const { 175 return process_id == signin_process_id_; 176 } 177 178 ExtensionInfoMap::~ExtensionInfoMap() { 179 if (quota_service_) { 180 BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, 181 quota_service_.release()); 182 } 183 } 184