blob: c97832ca4b29d8d86b1bff953726ab4a9c272c65 [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
peterb514ab0d2015-07-02 12:10:51132bool InfoMap::SecurityOriginHasAPIPermission(
[email protected]c7cd5942013-04-30 03:31:01133 const GURL& origin,
134 int process_id,
peterb514ab0d2015-07-02 12:10:51135 APIPermission::ID permission) const {
136 CheckOnValidThread();
[email protected]38427a12013-11-09 17:34:20137 if (origin.SchemeIs(kExtensionScheme)) {
[email protected]34eec7ffe32011-11-02 23:49:02138 const std::string& id = origin.host();
[email protected]af73c252012-07-27 00:16:39139 const Extension* extension = extensions_.GetByID(id);
peterb514ab0d2015-07-02 12:10:51140 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]076ebeda2014-06-06 21:47:26146 extension->permissions_data()->HasAPIPermission(permission) &&
peterb514ab0d2015-07-02 12:10:51147 process_map_.Contains(extension->id(), process_id)) {
148 return true;
[email protected]34eec7ffe32011-11-02 23:49:02149 }
150 }
peterb514ab0d2015-07-02 12:10:51151 return false;
[email protected]34eec7ffe32011-11-02 23:49:02152}
[email protected]36296912012-03-20 11:08:49153
[email protected]f30ee8b2014-08-15 15:20:22154// 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.
157bool 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
elijahtaylorfb585bff2014-10-09 04:51:41191 if (!SharedModuleInfo::ImportsExtensionById(extension, new_extension_id))
[email protected]f30ee8b2014-08-15 15:20:22192 return false;
[email protected]f30ee8b2014-08-15 15:20:22193
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]38427a12013-11-09 17:34:20212QuotaService* InfoMap::GetQuotaService() {
[email protected]36296912012-03-20 11:08:49213 CheckOnValidThread();
[email protected]3eeddd892013-04-17 17:00:11214 if (!quota_service_)
[email protected]38427a12013-11-09 17:34:20215 quota_service_.reset(new QuotaService());
[email protected]36296912012-03-20 11:08:49216 return quota_service_.get();
217}
[email protected]5f2a4752012-04-27 22:18:58218
[email protected]9afacd22013-11-13 20:23:31219void 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
227bool 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]fd3df7782014-05-08 23:54:27235void InfoMap::SetContentVerifier(ContentVerifier* verifier) {
236 content_verifier_ = verifier;
237}
238
[email protected]38427a12013-11-09 17:34:20239InfoMap::~InfoMap() {
[email protected]3eeddd892013-04-17 17:00:11240 if (quota_service_) {
[email protected]38427a12013-11-09 17:34:20241 BrowserThread::DeleteSoon(
242 BrowserThread::IO, FROM_HERE, quota_service_.release());
[email protected]5f2a4752012-04-27 22:18:58243 }
244}
[email protected]38427a12013-11-09 17:34:20245
246} // namespace extensions