blob: 00b2437b682d7a7f2f67c6973fcafc8a5ef1b4e9 [file] [log] [blame]
[email protected]38427a12013-11-09 17:34:201// Copyright 2013 The Chromium Authors. All rights reserved.
[email protected]4361c7c2010-09-30 21:57:532// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]38427a12013-11-09 17:34:205#include "extensions/browser/info_map.h"
[email protected]4361c7c2010-09-30 21:57:536
[email protected]f30ee8b2014-08-15 15:20:227#include "base/strings/string_util.h"
[email protected]c38831a12011-10-28 12:44:498#include "content/public/browser/browser_thread.h"
[email protected]fd3df7782014-05-08 23:54:279#include "extensions/browser/content_verifier.h"
[email protected]885c0e92012-11-13 20:27:4210#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4111#include "extensions/common/extension.h"
[email protected]f30ee8b2014-08-15 15:20:2212#include "extensions/common/extension_resource.h"
[email protected]289c44b2013-12-17 03:26:5713#include "extensions/common/extension_set.h"
[email protected]1f7de252013-11-06 22:02:0014#include "extensions/common/manifest_handlers/incognito_info.h"
[email protected]f30ee8b2014-08-15 15:20:2215#include "extensions/common/manifest_handlers/shared_module_info.h"
[email protected]076ebeda2014-06-06 21:47:2616#include "extensions/common/permissions/permissions_data.h"
[email protected]f30ee8b2014-08-15 15:20:2217#include "url/gurl.h"
[email protected]4361c7c2010-09-30 21:57:5318
[email protected]631bb742011-11-02 11:29:3919using content::BrowserThread;
[email protected]38427a12013-11-09 17:34:2020
21namespace extensions {
[email protected]631bb742011-11-02 11:29:3922
[email protected]4361c7c2010-09-30 21:57:5323namespace {
24
[email protected]54ee8192014-03-29 17:37:2425void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
[email protected]4361c7c2010-09-30 21:57:5326
27} // namespace
28
[email protected]38427a12013-11-09 17:34:2029struct InfoMap::ExtraData {
[email protected]c357acb42011-06-09 20:52:4230 // 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]9afacd22013-11-13 20:23:3136 // True if the user has disabled notifications for this extension manually.
37 bool notifications_disabled;
38
[email protected]c357acb42011-06-09 20:52:4239 ExtraData();
40 ~ExtraData();
41};
42
[email protected]f30ee8b2014-08-15 15:20:2243InfoMap::ExtraData::ExtraData()
44 : incognito_enabled(false), notifications_disabled(false) {
45}
[email protected]c357acb42011-06-09 20:52:4246
[email protected]38427a12013-11-09 17:34:2047InfoMap::ExtraData::~ExtraData() {}
[email protected]c357acb42011-06-09 20:52:4248
rogertacbd2bb42015-03-20 15:12:3349InfoMap::InfoMap() {
[email protected]896c6d52014-01-28 21:40:2150}
51
[email protected]38427a12013-11-09 17:34:2052void InfoMap::AddExtension(const Extension* extension,
53 base::Time install_time,
[email protected]9afacd22013-11-13 20:23:3154 bool incognito_enabled,
55 bool notifications_disabled) {
[email protected]4361c7c2010-09-30 21:57:5356 CheckOnValidThread();
[email protected]be0a2cfd2011-06-02 21:36:4257 extensions_.Insert(extension);
58 disabled_extensions_.Remove(extension->id());
[email protected]c357acb42011-06-09 20:52:4259
60 extra_data_[extension->id()].install_time = install_time;
61 extra_data_[extension->id()].incognito_enabled = incognito_enabled;
[email protected]9afacd22013-11-13 20:23:3162 extra_data_[extension->id()].notifications_disabled = notifications_disabled;
[email protected]4361c7c2010-09-30 21:57:5363}
64
[email protected]38427a12013-11-09 17:34:2065void InfoMap::RemoveExtension(const std::string& extension_id,
66 const UnloadedExtensionInfo::Reason reason) {
[email protected]4361c7c2010-09-30 21:57:5367 CheckOnValidThread();
[email protected]c357acb42011-06-09 20:52:4268 const Extension* extension = extensions_.GetByID(extension_id);
69 extra_data_.erase(extension_id); // we don't care about disabled extra data
[email protected]b0af4792013-10-23 09:12:1370 bool was_uninstalled = (reason != UnloadedExtensionInfo::REASON_DISABLE &&
71 reason != UnloadedExtensionInfo::REASON_TERMINATE);
[email protected]be0a2cfd2011-06-02 21:36:4272 if (extension) {
[email protected]b3f7fe22011-11-11 19:27:5673 if (!was_uninstalled)
[email protected]be0a2cfd2011-06-02 21:36:4274 disabled_extensions_.Insert(extension);
[email protected]c357acb42011-06-09 20:52:4275 extensions_.Remove(extension_id);
[email protected]b3f7fe22011-11-11 19:27:5676 } else if (was_uninstalled) {
[email protected]dd163fb02011-05-04 22:22:1777 // If the extension was uninstalled, make sure it's removed from the map of
78 // disabled extensions.
[email protected]c357acb42011-06-09 20:52:4279 disabled_extensions_.Remove(extension_id);
[email protected]4361c7c2010-09-30 21:57:5380 } 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]c357acb42011-06-09 20:52:4285 NOTREACHED() << extension_id;
[email protected]4361c7c2010-09-30 21:57:5386 }
87}
[email protected]c357acb42011-06-09 20:52:4288
[email protected]38427a12013-11-09 17:34:2089base::Time InfoMap::GetInstallTime(const std::string& extension_id) const {
[email protected]c357acb42011-06-09 20:52:4290 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]38427a12013-11-09 17:34:2096bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const {
[email protected]98b6d942013-11-10 00:34:0797 // Keep in sync with duplicate in extensions/browser/process_manager.cc.
[email protected]c357acb42011-06-09 20:52:4298 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]38427a12013-11-09 17:34:20104bool InfoMap::CanCrossIncognito(const Extension* extension) const {
[email protected]c357acb42011-06-09 20:52:42105 // This is duplicated from ExtensionService :(.
106 return IsIncognitoEnabled(extension->id()) &&
[email protected]38427a12013-11-09 17:34:20107 !IncognitoInfo::IsSplitMode(extension);
[email protected]c357acb42011-06-09 20:52:42108}
[email protected]8add5412011-10-01 21:02:14109
[email protected]38427a12013-11-09 17:34:20110void InfoMap::RegisterExtensionProcess(const std::string& extension_id,
111 int process_id,
112 int site_instance_id) {
[email protected]6bc04fd82011-12-04 02:29:35113 if (!process_map_.Insert(extension_id, process_id, site_instance_id)) {
[email protected]6f371442011-11-09 06:45:46114 NOTREACHED() << "Duplicate extension process registration for: "
115 << extension_id << "," << process_id << ".";
116 }
[email protected]8add5412011-10-01 21:02:14117}
118
[email protected]38427a12013-11-09 17:34:20119void InfoMap::UnregisterExtensionProcess(const std::string& extension_id,
120 int process_id,
121 int site_instance_id) {
[email protected]6bc04fd82011-12-04 02:29:35122 if (!process_map_.Remove(extension_id, process_id, site_instance_id)) {
[email protected]6f371442011-11-09 06:45:46123 NOTREACHED() << "Unknown extension process registration for: "
124 << extension_id << "," << process_id << ".";
125 }
[email protected]8add5412011-10-01 21:02:14126}
127
[email protected]38427a12013-11-09 17:34:20128void InfoMap::UnregisterAllExtensionsInProcess(int process_id) {
[email protected]6bc04fd82011-12-04 02:29:35129 process_map_.RemoveAllFromProcess(process_id);
[email protected]8add5412011-10-01 21:02:14130}
[email protected]34eec7ffe32011-11-02 23:49:02131
[email protected]38427a12013-11-09 17:34:20132void InfoMap::GetExtensionsWithAPIPermissionForSecurityOrigin(
[email protected]c7cd5942013-04-30 03:31:01133 const GURL& origin,
134 int process_id,
[email protected]38427a12013-11-09 17:34:20135 APIPermission::ID permission,
[email protected]c7cd5942013-04-30 03:31:01136 ExtensionSet* extensions) const {
137 DCHECK(extensions);
138
[email protected]38427a12013-11-09 17:34:20139 if (origin.SchemeIs(kExtensionScheme)) {
[email protected]34eec7ffe32011-11-02 23:49:02140 const std::string& id = origin.host();
[email protected]af73c252012-07-27 00:16:39141 const Extension* extension = extensions_.GetByID(id);
[email protected]076ebeda2014-06-06 21:47:26142 if (extension &&
143 extension->permissions_data()->HasAPIPermission(permission) &&
[email protected]c7cd5942013-04-30 03:31:01144 process_map_.Contains(id, process_id)) {
145 extensions->Insert(extension);
146 }
147 return;
[email protected]34eec7ffe32011-11-02 23:49:02148 }
149
[email protected]84df8332011-12-06 18:22:46150 ExtensionSet::const_iterator i = extensions_.begin();
[email protected]34eec7ffe32011-11-02 23:49:02151 for (; i != extensions_.end(); ++i) {
[email protected]84df8332011-12-06 18:22:46152 if ((*i)->web_extent().MatchesSecurityOrigin(origin) &&
153 process_map_.Contains((*i)->id(), process_id) &&
[email protected]076ebeda2014-06-06 21:47:26154 (*i)->permissions_data()->HasAPIPermission(permission)) {
[email protected]c7cd5942013-04-30 03:31:01155 extensions->Insert(*i);
[email protected]34eec7ffe32011-11-02 23:49:02156 }
157 }
[email protected]c7cd5942013-04-30 03:31:01158}
159
[email protected]38427a12013-11-09 17:34:20160bool InfoMap::SecurityOriginHasAPIPermission(const GURL& origin,
161 int process_id,
162 APIPermission::ID permission)
163 const {
[email protected]c7cd5942013-04-30 03:31:01164 ExtensionSet extensions;
165 GetExtensionsWithAPIPermissionForSecurityOrigin(
166 origin, process_id, permission, &extensions);
167 return !extensions.is_empty();
[email protected]34eec7ffe32011-11-02 23:49:02168}
[email protected]36296912012-03-20 11:08:49169
[email protected]f30ee8b2014-08-15 15:20:22170// This function is security sensitive. Bugs could cause problems that break
171// restrictions on local file access or NaCl's validation caching. If you modify
172// this function, please get a security review from a NaCl person.
173bool InfoMap::MapUrlToLocalFilePath(const GURL& file_url,
174 bool use_blocking_api,
175 base::FilePath* file_path) {
176 // Check that the URL is recognized by the extension system.
177 const Extension* extension = extensions_.GetExtensionOrAppByURL(file_url);
178 if (!extension)
179 return false;
180
181 // This is a short-cut which avoids calling a blocking file operation
182 // (GetFilePath()), so that this can be called on the IO thread. It only
183 // handles a subset of the urls.
184 if (!use_blocking_api) {
185 if (file_url.SchemeIs(extensions::kExtensionScheme)) {
186 std::string path = file_url.path();
187 base::TrimString(path, "/", &path); // Remove first slash
188 *file_path = extension->path().AppendASCII(path);
189 return true;
190 }
191 return false;
192 }
193
194 std::string path = file_url.path();
195 ExtensionResource resource;
196
197 if (SharedModuleInfo::IsImportedPath(path)) {
198 // Check if this is a valid path that is imported for this extension.
199 std::string new_extension_id;
200 std::string new_relative_path;
201 SharedModuleInfo::ParseImportedPath(
202 path, &new_extension_id, &new_relative_path);
203 const Extension* new_extension = extensions_.GetByID(new_extension_id);
204 if (!new_extension)
205 return false;
206
elijahtaylorfb585bff2014-10-09 04:51:41207 if (!SharedModuleInfo::ImportsExtensionById(extension, new_extension_id))
[email protected]f30ee8b2014-08-15 15:20:22208 return false;
[email protected]f30ee8b2014-08-15 15:20:22209
210 resource = new_extension->GetResource(new_relative_path);
211 } else {
212 // Check that the URL references a resource in the extension.
213 resource = extension->GetResource(path);
214 }
215
216 if (resource.empty())
217 return false;
218
219 // GetFilePath is a blocking function call.
220 const base::FilePath resource_file_path = resource.GetFilePath();
221 if (resource_file_path.empty())
222 return false;
223
224 *file_path = resource_file_path;
225 return true;
226}
227
[email protected]38427a12013-11-09 17:34:20228QuotaService* InfoMap::GetQuotaService() {
[email protected]36296912012-03-20 11:08:49229 CheckOnValidThread();
[email protected]3eeddd892013-04-17 17:00:11230 if (!quota_service_)
[email protected]38427a12013-11-09 17:34:20231 quota_service_.reset(new QuotaService());
[email protected]36296912012-03-20 11:08:49232 return quota_service_.get();
233}
[email protected]5f2a4752012-04-27 22:18:58234
[email protected]9afacd22013-11-13 20:23:31235void InfoMap::SetNotificationsDisabled(
236 const std::string& extension_id,
237 bool notifications_disabled) {
238 ExtraDataMap::iterator iter = extra_data_.find(extension_id);
239 if (iter != extra_data_.end())
240 iter->second.notifications_disabled = notifications_disabled;
241}
242
243bool InfoMap::AreNotificationsDisabled(
244 const std::string& extension_id) const {
245 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
246 if (iter != extra_data_.end())
247 return iter->second.notifications_disabled;
248 return false;
249}
250
[email protected]fd3df7782014-05-08 23:54:27251void InfoMap::SetContentVerifier(ContentVerifier* verifier) {
252 content_verifier_ = verifier;
253}
254
[email protected]38427a12013-11-09 17:34:20255InfoMap::~InfoMap() {
[email protected]3eeddd892013-04-17 17:00:11256 if (quota_service_) {
[email protected]38427a12013-11-09 17:34:20257 BrowserThread::DeleteSoon(
258 BrowserThread::IO, FROM_HERE, quota_service_.release());
[email protected]5f2a4752012-04-27 22:18:58259 }
260}
[email protected]38427a12013-11-09 17:34:20261
262} // namespace extensions