Extension syncing: Introduce a NeedsSync pref
[chromium-blink-merge.git] / extensions / browser / info_map.cc
blobc97832ca4b29d8d86b1bff953726ab4a9c272c65
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.
5 #include "extensions/browser/info_map.h"
7 #include "base/strings/string_util.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "extensions/browser/content_verifier.h"
10 #include "extensions/common/constants.h"
11 #include "extensions/common/extension.h"
12 #include "extensions/common/extension_resource.h"
13 #include "extensions/common/extension_set.h"
14 #include "extensions/common/manifest_handlers/incognito_info.h"
15 #include "extensions/common/manifest_handlers/shared_module_info.h"
16 #include "extensions/common/permissions/permissions_data.h"
17 #include "url/gurl.h"
19 using content::BrowserThread;
21 namespace extensions {
23 namespace {
25 void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
27 } // namespace
29 struct InfoMap::ExtraData {
30 // When the extension was installed.
31 base::Time install_time;
33 // True if the user has allowed this extension to run in incognito mode.
34 bool incognito_enabled;
36 // True if the user has disabled notifications for this extension manually.
37 bool notifications_disabled;
39 ExtraData();
40 ~ExtraData();
43 InfoMap::ExtraData::ExtraData()
44 : incognito_enabled(false), notifications_disabled(false) {
47 InfoMap::ExtraData::~ExtraData() {}
49 InfoMap::InfoMap() {
52 void InfoMap::AddExtension(const Extension* extension,
53 base::Time install_time,
54 bool incognito_enabled,
55 bool notifications_disabled) {
56 CheckOnValidThread();
57 extensions_.Insert(extension);
58 disabled_extensions_.Remove(extension->id());
60 extra_data_[extension->id()].install_time = install_time;
61 extra_data_[extension->id()].incognito_enabled = incognito_enabled;
62 extra_data_[extension->id()].notifications_disabled = notifications_disabled;
65 void InfoMap::RemoveExtension(const std::string& extension_id,
66 const UnloadedExtensionInfo::Reason reason) {
67 CheckOnValidThread();
68 const Extension* extension = extensions_.GetByID(extension_id);
69 extra_data_.erase(extension_id); // we don't care about disabled extra data
70 bool was_uninstalled = (reason != UnloadedExtensionInfo::REASON_DISABLE &&
71 reason != UnloadedExtensionInfo::REASON_TERMINATE);
72 if (extension) {
73 if (!was_uninstalled)
74 disabled_extensions_.Insert(extension);
75 extensions_.Remove(extension_id);
76 } else if (was_uninstalled) {
77 // If the extension was uninstalled, make sure it's removed from the map of
78 // disabled extensions.
79 disabled_extensions_.Remove(extension_id);
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 .
85 NOTREACHED() << extension_id;
89 base::Time InfoMap::GetInstallTime(const std::string& extension_id) const {
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();
96 bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const {
97 // Keep in sync with duplicate in extensions/browser/process_manager.cc.
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;
104 bool InfoMap::CanCrossIncognito(const Extension* extension) const {
105 // This is duplicated from ExtensionService :(.
106 return IsIncognitoEnabled(extension->id()) &&
107 !IncognitoInfo::IsSplitMode(extension);
110 void InfoMap::RegisterExtensionProcess(const std::string& extension_id,
111 int process_id,
112 int site_instance_id) {
113 if (!process_map_.Insert(extension_id, process_id, site_instance_id)) {
114 NOTREACHED() << "Duplicate extension process registration for: "
115 << extension_id << "," << process_id << ".";
119 void InfoMap::UnregisterExtensionProcess(const std::string& extension_id,
120 int process_id,
121 int site_instance_id) {
122 if (!process_map_.Remove(extension_id, process_id, site_instance_id)) {
123 NOTREACHED() << "Unknown extension process registration for: "
124 << extension_id << "," << process_id << ".";
128 void InfoMap::UnregisterAllExtensionsInProcess(int process_id) {
129 process_map_.RemoveAllFromProcess(process_id);
132 bool InfoMap::SecurityOriginHasAPIPermission(
133 const GURL& origin,
134 int process_id,
135 APIPermission::ID permission) const {
136 CheckOnValidThread();
137 if (origin.SchemeIs(kExtensionScheme)) {
138 const std::string& id = origin.host();
139 const Extension* extension = extensions_.GetByID(id);
140 return extension &&
141 extension->permissions_data()->HasAPIPermission(permission) &&
142 process_map_.Contains(id, process_id);
144 for (const auto& extension : extensions_) {
145 if (extension->web_extent().MatchesSecurityOrigin(origin) &&
146 extension->permissions_data()->HasAPIPermission(permission) &&
147 process_map_.Contains(extension->id(), process_id)) {
148 return true;
151 return false;
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;
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;
175 return false;
178 std::string path = file_url.path();
179 ExtensionResource resource;
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;
191 if (!SharedModuleInfo::ImportsExtensionById(extension, new_extension_id))
192 return false;
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);
200 if (resource.empty())
201 return false;
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;
208 *file_path = resource_file_path;
209 return true;
212 QuotaService* InfoMap::GetQuotaService() {
213 CheckOnValidThread();
214 if (!quota_service_)
215 quota_service_.reset(new QuotaService());
216 return quota_service_.get();
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;
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;
235 void InfoMap::SetContentVerifier(ContentVerifier* verifier) {
236 content_verifier_ = verifier;
239 InfoMap::~InfoMap() {
240 if (quota_service_) {
241 BrowserThread::DeleteSoon(
242 BrowserThread::IO, FROM_HERE, quota_service_.release());
246 } // namespace extensions