[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 5 | #include "extensions/browser/info_map.h" |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 6 | |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 7 | #include "base/strings/string_util.h" |
[email protected] | c38831a1 | 2011-10-28 12:44:49 | [diff] [blame] | 8 | #include "content/public/browser/browser_thread.h" |
[email protected] | fd3df778 | 2014-05-08 23:54:27 | [diff] [blame] | 9 | #include "extensions/browser/content_verifier.h" |
[email protected] | 885c0e9 | 2012-11-13 20:27:42 | [diff] [blame] | 10 | #include "extensions/common/constants.h" |
[email protected] | e4452d3 | 2013-11-15 23:07:41 | [diff] [blame] | 11 | #include "extensions/common/extension.h" |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 12 | #include "extensions/common/extension_resource.h" |
[email protected] | 289c44b | 2013-12-17 03:26:57 | [diff] [blame] | 13 | #include "extensions/common/extension_set.h" |
[email protected] | 1f7de25 | 2013-11-06 22:02:00 | [diff] [blame] | 14 | #include "extensions/common/manifest_handlers/incognito_info.h" |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 15 | #include "extensions/common/manifest_handlers/shared_module_info.h" |
[email protected] | 076ebeda | 2014-06-06 21:47:26 | [diff] [blame] | 16 | #include "extensions/common/permissions/permissions_data.h" |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 17 | #include "url/gurl.h" |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 18 | |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 19 | using content::BrowserThread; |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 20 | |
| 21 | namespace extensions { |
[email protected] | 631bb74 | 2011-11-02 11:29:39 | [diff] [blame] | 22 | |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 23 | namespace { |
| 24 | |
[email protected] | 54ee819 | 2014-03-29 17:37:24 | [diff] [blame] | 25 | void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); } |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 26 | |
| 27 | } // namespace |
| 28 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 29 | struct InfoMap::ExtraData { |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 30 | // When the extension was installed. |
| 31 | base::Time install_time; |
| 32 | |
| 33 | // True if the user has allowed this extension to run in incognito mode. |
| 34 | bool incognito_enabled; |
| 35 | |
[email protected] | 9afacd2 | 2013-11-13 20:23:31 | [diff] [blame] | 36 | // True if the user has disabled notifications for this extension manually. |
| 37 | bool notifications_disabled; |
| 38 | |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 39 | ExtraData(); |
| 40 | ~ExtraData(); |
| 41 | }; |
| 42 | |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 43 | InfoMap::ExtraData::ExtraData() |
| 44 | : incognito_enabled(false), notifications_disabled(false) { |
| 45 | } |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 46 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 47 | InfoMap::ExtraData::~ExtraData() {} |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 48 | |
rogerta | cbd2bb4 | 2015-03-20 15:12:33 | [diff] [blame] | 49 | InfoMap::InfoMap() { |
[email protected] | 896c6d5 | 2014-01-28 21:40:21 | [diff] [blame] | 50 | } |
| 51 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 52 | void InfoMap::AddExtension(const Extension* extension, |
| 53 | base::Time install_time, |
[email protected] | 9afacd2 | 2013-11-13 20:23:31 | [diff] [blame] | 54 | bool incognito_enabled, |
| 55 | bool notifications_disabled) { |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 56 | CheckOnValidThread(); |
[email protected] | be0a2cfd | 2011-06-02 21:36:42 | [diff] [blame] | 57 | extensions_.Insert(extension); |
| 58 | disabled_extensions_.Remove(extension->id()); |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 59 | |
| 60 | extra_data_[extension->id()].install_time = install_time; |
| 61 | extra_data_[extension->id()].incognito_enabled = incognito_enabled; |
[email protected] | 9afacd2 | 2013-11-13 20:23:31 | [diff] [blame] | 62 | extra_data_[extension->id()].notifications_disabled = notifications_disabled; |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 63 | } |
| 64 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 65 | void InfoMap::RemoveExtension(const std::string& extension_id, |
| 66 | const UnloadedExtensionInfo::Reason reason) { |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 67 | CheckOnValidThread(); |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 68 | const Extension* extension = extensions_.GetByID(extension_id); |
| 69 | extra_data_.erase(extension_id); // we don't care about disabled extra data |
[email protected] | b0af479 | 2013-10-23 09:12:13 | [diff] [blame] | 70 | bool was_uninstalled = (reason != UnloadedExtensionInfo::REASON_DISABLE && |
| 71 | reason != UnloadedExtensionInfo::REASON_TERMINATE); |
[email protected] | be0a2cfd | 2011-06-02 21:36:42 | [diff] [blame] | 72 | if (extension) { |
[email protected] | b3f7fe2 | 2011-11-11 19:27:56 | [diff] [blame] | 73 | if (!was_uninstalled) |
[email protected] | be0a2cfd | 2011-06-02 21:36:42 | [diff] [blame] | 74 | disabled_extensions_.Insert(extension); |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 75 | extensions_.Remove(extension_id); |
[email protected] | b3f7fe2 | 2011-11-11 19:27:56 | [diff] [blame] | 76 | } else if (was_uninstalled) { |
[email protected] | dd163fb0 | 2011-05-04 22:22:17 | [diff] [blame] | 77 | // If the extension was uninstalled, make sure it's removed from the map of |
| 78 | // disabled extensions. |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 79 | disabled_extensions_.Remove(extension_id); |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 80 | } else { |
| 81 | // NOTE: This can currently happen if we receive multiple unload |
| 82 | // notifications, e.g. setting incognito-enabled state for a |
| 83 | // disabled extension (e.g., via sync). See |
| 84 | // http://code.google.com/p/chromium/issues/detail?id=50582 . |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 85 | NOTREACHED() << extension_id; |
[email protected] | 4361c7c | 2010-09-30 21:57:53 | [diff] [blame] | 86 | } |
| 87 | } |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 88 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 89 | base::Time InfoMap::GetInstallTime(const std::string& extension_id) const { |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 90 | ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); |
| 91 | if (iter != extra_data_.end()) |
| 92 | return iter->second.install_time; |
| 93 | return base::Time(); |
| 94 | } |
| 95 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 96 | bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const { |
[email protected] | 98b6d94 | 2013-11-10 00:34:07 | [diff] [blame] | 97 | // Keep in sync with duplicate in extensions/browser/process_manager.cc. |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 98 | ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); |
| 99 | if (iter != extra_data_.end()) |
| 100 | return iter->second.incognito_enabled; |
| 101 | return false; |
| 102 | } |
| 103 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 104 | bool InfoMap::CanCrossIncognito(const Extension* extension) const { |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 105 | // This is duplicated from ExtensionService :(. |
| 106 | return IsIncognitoEnabled(extension->id()) && |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 107 | !IncognitoInfo::IsSplitMode(extension); |
[email protected] | c357acb4 | 2011-06-09 20:52:42 | [diff] [blame] | 108 | } |
[email protected] | 8add541 | 2011-10-01 21:02:14 | [diff] [blame] | 109 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 110 | void InfoMap::RegisterExtensionProcess(const std::string& extension_id, |
| 111 | int process_id, |
| 112 | int site_instance_id) { |
[email protected] | 6bc04fd8 | 2011-12-04 02:29:35 | [diff] [blame] | 113 | if (!process_map_.Insert(extension_id, process_id, site_instance_id)) { |
[email protected] | 6f37144 | 2011-11-09 06:45:46 | [diff] [blame] | 114 | NOTREACHED() << "Duplicate extension process registration for: " |
| 115 | << extension_id << "," << process_id << "."; |
| 116 | } |
[email protected] | 8add541 | 2011-10-01 21:02:14 | [diff] [blame] | 117 | } |
| 118 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 119 | void InfoMap::UnregisterExtensionProcess(const std::string& extension_id, |
| 120 | int process_id, |
| 121 | int site_instance_id) { |
[email protected] | 6bc04fd8 | 2011-12-04 02:29:35 | [diff] [blame] | 122 | if (!process_map_.Remove(extension_id, process_id, site_instance_id)) { |
[email protected] | 6f37144 | 2011-11-09 06:45:46 | [diff] [blame] | 123 | NOTREACHED() << "Unknown extension process registration for: " |
| 124 | << extension_id << "," << process_id << "."; |
| 125 | } |
[email protected] | 8add541 | 2011-10-01 21:02:14 | [diff] [blame] | 126 | } |
| 127 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 128 | void InfoMap::UnregisterAllExtensionsInProcess(int process_id) { |
[email protected] | 6bc04fd8 | 2011-12-04 02:29:35 | [diff] [blame] | 129 | process_map_.RemoveAllFromProcess(process_id); |
[email protected] | 8add541 | 2011-10-01 21:02:14 | [diff] [blame] | 130 | } |
[email protected] | 34eec7ffe3 | 2011-11-02 23:49:02 | [diff] [blame] | 131 | |
peter | b514ab0d | 2015-07-02 12:10:51 | [diff] [blame] | 132 | bool InfoMap::SecurityOriginHasAPIPermission( |
[email protected] | c7cd594 | 2013-04-30 03:31:01 | [diff] [blame] | 133 | const GURL& origin, |
| 134 | int process_id, |
peter | b514ab0d | 2015-07-02 12:10:51 | [diff] [blame] | 135 | APIPermission::ID permission) const { |
| 136 | CheckOnValidThread(); |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 137 | if (origin.SchemeIs(kExtensionScheme)) { |
[email protected] | 34eec7ffe3 | 2011-11-02 23:49:02 | [diff] [blame] | 138 | const std::string& id = origin.host(); |
[email protected] | af73c25 | 2012-07-27 00:16:39 | [diff] [blame] | 139 | const Extension* extension = extensions_.GetByID(id); |
peter | b514ab0d | 2015-07-02 12:10:51 | [diff] [blame] | 140 | return extension && |
| 141 | extension->permissions_data()->HasAPIPermission(permission) && |
| 142 | process_map_.Contains(id, process_id); |
| 143 | } |
| 144 | for (const auto& extension : extensions_) { |
| 145 | if (extension->web_extent().MatchesSecurityOrigin(origin) && |
[email protected] | 076ebeda | 2014-06-06 21:47:26 | [diff] [blame] | 146 | extension->permissions_data()->HasAPIPermission(permission) && |
peter | b514ab0d | 2015-07-02 12:10:51 | [diff] [blame] | 147 | process_map_.Contains(extension->id(), process_id)) { |
| 148 | return true; |
[email protected] | 34eec7ffe3 | 2011-11-02 23:49:02 | [diff] [blame] | 149 | } |
| 150 | } |
peter | b514ab0d | 2015-07-02 12:10:51 | [diff] [blame] | 151 | return false; |
[email protected] | 34eec7ffe3 | 2011-11-02 23:49:02 | [diff] [blame] | 152 | } |
[email protected] | 3629691 | 2012-03-20 11:08:49 | [diff] [blame] | 153 | |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 154 | // This function is security sensitive. Bugs could cause problems that break |
| 155 | // restrictions on local file access or NaCl's validation caching. If you modify |
| 156 | // this function, please get a security review from a NaCl person. |
| 157 | bool InfoMap::MapUrlToLocalFilePath(const GURL& file_url, |
| 158 | bool use_blocking_api, |
| 159 | base::FilePath* file_path) { |
| 160 | // Check that the URL is recognized by the extension system. |
| 161 | const Extension* extension = extensions_.GetExtensionOrAppByURL(file_url); |
| 162 | if (!extension) |
| 163 | return false; |
| 164 | |
| 165 | // This is a short-cut which avoids calling a blocking file operation |
| 166 | // (GetFilePath()), so that this can be called on the IO thread. It only |
| 167 | // handles a subset of the urls. |
| 168 | if (!use_blocking_api) { |
| 169 | if (file_url.SchemeIs(extensions::kExtensionScheme)) { |
| 170 | std::string path = file_url.path(); |
| 171 | base::TrimString(path, "/", &path); // Remove first slash |
| 172 | *file_path = extension->path().AppendASCII(path); |
| 173 | return true; |
| 174 | } |
| 175 | return false; |
| 176 | } |
| 177 | |
| 178 | std::string path = file_url.path(); |
| 179 | ExtensionResource resource; |
| 180 | |
| 181 | if (SharedModuleInfo::IsImportedPath(path)) { |
| 182 | // Check if this is a valid path that is imported for this extension. |
| 183 | std::string new_extension_id; |
| 184 | std::string new_relative_path; |
| 185 | SharedModuleInfo::ParseImportedPath( |
| 186 | path, &new_extension_id, &new_relative_path); |
| 187 | const Extension* new_extension = extensions_.GetByID(new_extension_id); |
| 188 | if (!new_extension) |
| 189 | return false; |
| 190 | |
elijahtaylor | fb585bff | 2014-10-09 04:51:41 | [diff] [blame] | 191 | if (!SharedModuleInfo::ImportsExtensionById(extension, new_extension_id)) |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 192 | return false; |
[email protected] | f30ee8b | 2014-08-15 15:20:22 | [diff] [blame] | 193 | |
| 194 | resource = new_extension->GetResource(new_relative_path); |
| 195 | } else { |
| 196 | // Check that the URL references a resource in the extension. |
| 197 | resource = extension->GetResource(path); |
| 198 | } |
| 199 | |
| 200 | if (resource.empty()) |
| 201 | return false; |
| 202 | |
| 203 | // GetFilePath is a blocking function call. |
| 204 | const base::FilePath resource_file_path = resource.GetFilePath(); |
| 205 | if (resource_file_path.empty()) |
| 206 | return false; |
| 207 | |
| 208 | *file_path = resource_file_path; |
| 209 | return true; |
| 210 | } |
| 211 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 212 | QuotaService* InfoMap::GetQuotaService() { |
[email protected] | 3629691 | 2012-03-20 11:08:49 | [diff] [blame] | 213 | CheckOnValidThread(); |
[email protected] | 3eeddd89 | 2013-04-17 17:00:11 | [diff] [blame] | 214 | if (!quota_service_) |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 215 | quota_service_.reset(new QuotaService()); |
[email protected] | 3629691 | 2012-03-20 11:08:49 | [diff] [blame] | 216 | return quota_service_.get(); |
| 217 | } |
[email protected] | 5f2a475 | 2012-04-27 22:18:58 | [diff] [blame] | 218 | |
[email protected] | 9afacd2 | 2013-11-13 20:23:31 | [diff] [blame] | 219 | void InfoMap::SetNotificationsDisabled( |
| 220 | const std::string& extension_id, |
| 221 | bool notifications_disabled) { |
| 222 | ExtraDataMap::iterator iter = extra_data_.find(extension_id); |
| 223 | if (iter != extra_data_.end()) |
| 224 | iter->second.notifications_disabled = notifications_disabled; |
| 225 | } |
| 226 | |
| 227 | bool InfoMap::AreNotificationsDisabled( |
| 228 | const std::string& extension_id) const { |
| 229 | ExtraDataMap::const_iterator iter = extra_data_.find(extension_id); |
| 230 | if (iter != extra_data_.end()) |
| 231 | return iter->second.notifications_disabled; |
| 232 | return false; |
| 233 | } |
| 234 | |
[email protected] | fd3df778 | 2014-05-08 23:54:27 | [diff] [blame] | 235 | void InfoMap::SetContentVerifier(ContentVerifier* verifier) { |
| 236 | content_verifier_ = verifier; |
| 237 | } |
| 238 | |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 239 | InfoMap::~InfoMap() { |
[email protected] | 3eeddd89 | 2013-04-17 17:00:11 | [diff] [blame] | 240 | if (quota_service_) { |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 241 | BrowserThread::DeleteSoon( |
| 242 | BrowserThread::IO, FROM_HERE, quota_service_.release()); |
[email protected] | 5f2a475 | 2012-04-27 22:18:58 | [diff] [blame] | 243 | } |
| 244 | } |
[email protected] | 38427a1 | 2013-11-09 17:34:20 | [diff] [blame] | 245 | |
| 246 | } // namespace extensions |