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.
4
5 #include "extensions/browser/info_map.h"
6
7 #include "content/public/browser/browser_thread.h"
8 #include "extensions/browser/content_verifier.h"
9 #include "extensions/common/constants.h"
10 #include "extensions/common/extension.h"
11 #include "extensions/common/extension_set.h"
12 #include "extensions/common/manifest_handlers/incognito_info.h"
13 #include "extensions/common/permissions/permissions_data.h"
14
15 using content::BrowserThread;
16
17 namespace extensions {
18
19 namespace {
20
CheckOnValidThread()21 void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
22
23 } // namespace
24
25 struct InfoMap::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 // True if the user has disabled notifications for this extension manually.
33 bool notifications_disabled;
34
35 ExtraData();
36 ~ExtraData();
37 };
38
ExtraData()39 InfoMap::ExtraData::ExtraData() : incognito_enabled(false) {}
40
~ExtraData()41 InfoMap::ExtraData::~ExtraData() {}
42
InfoMap()43 InfoMap::InfoMap() : signin_process_id_(-1) {}
44
process_map() const45 const ProcessMap& InfoMap::process_map() const { return process_map_; }
46
worker_process_map() const47 const ProcessMap& InfoMap::worker_process_map() const {
48 return worker_process_map_;
49 }
50
AddExtension(const Extension * extension,base::Time install_time,bool incognito_enabled,bool notifications_disabled)51 void InfoMap::AddExtension(const Extension* extension,
52 base::Time install_time,
53 bool incognito_enabled,
54 bool notifications_disabled) {
55 CheckOnValidThread();
56 extensions_.Insert(extension);
57 disabled_extensions_.Remove(extension->id());
58
59 extra_data_[extension->id()].install_time = install_time;
60 extra_data_[extension->id()].incognito_enabled = incognito_enabled;
61 extra_data_[extension->id()].notifications_disabled = notifications_disabled;
62 }
63
RemoveExtension(const std::string & extension_id,const UnloadedExtensionInfo::Reason reason)64 void InfoMap::RemoveExtension(const std::string& extension_id,
65 const UnloadedExtensionInfo::Reason reason) {
66 CheckOnValidThread();
67 const Extension* extension = extensions_.GetByID(extension_id);
68 extra_data_.erase(extension_id); // we don't care about disabled extra data
69 bool was_uninstalled = (reason != UnloadedExtensionInfo::REASON_DISABLE &&
70 reason != UnloadedExtensionInfo::REASON_TERMINATE);
71 if (extension) {
72 if (!was_uninstalled)
73 disabled_extensions_.Insert(extension);
74 extensions_.Remove(extension_id);
75 } else if (was_uninstalled) {
76 // If the extension was uninstalled, make sure it's removed from the map of
77 // disabled extensions.
78 disabled_extensions_.Remove(extension_id);
79 } else {
80 // NOTE: This can currently happen if we receive multiple unload
81 // notifications, e.g. setting incognito-enabled state for a
82 // disabled extension (e.g., via sync). See
83 // http://code.google.com/p/chromium/issues/detail?id=50582 .
84 NOTREACHED() << extension_id;
85 }
86 }
87
GetInstallTime(const std::string & extension_id) const88 base::Time InfoMap::GetInstallTime(const std::string& extension_id) const {
89 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
90 if (iter != extra_data_.end())
91 return iter->second.install_time;
92 return base::Time();
93 }
94
IsIncognitoEnabled(const std::string & extension_id) const95 bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const {
96 // Keep in sync with duplicate in extensions/browser/process_manager.cc.
97 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
98 if (iter != extra_data_.end())
99 return iter->second.incognito_enabled;
100 return false;
101 }
102
CanCrossIncognito(const Extension * extension) const103 bool InfoMap::CanCrossIncognito(const Extension* extension) const {
104 // This is duplicated from ExtensionService :(.
105 return IsIncognitoEnabled(extension->id()) &&
106 !IncognitoInfo::IsSplitMode(extension);
107 }
108
RegisterExtensionProcess(const std::string & extension_id,int process_id,int site_instance_id)109 void InfoMap::RegisterExtensionProcess(const std::string& extension_id,
110 int process_id,
111 int site_instance_id) {
112 if (!process_map_.Insert(extension_id, process_id, site_instance_id)) {
113 NOTREACHED() << "Duplicate extension process registration for: "
114 << extension_id << "," << process_id << ".";
115 }
116 }
117
UnregisterExtensionProcess(const std::string & extension_id,int process_id,int site_instance_id)118 void InfoMap::UnregisterExtensionProcess(const std::string& extension_id,
119 int process_id,
120 int site_instance_id) {
121 if (!process_map_.Remove(extension_id, process_id, site_instance_id)) {
122 NOTREACHED() << "Unknown extension process registration for: "
123 << extension_id << "," << process_id << ".";
124 }
125 }
126
UnregisterAllExtensionsInProcess(int process_id)127 void InfoMap::UnregisterAllExtensionsInProcess(int process_id) {
128 process_map_.RemoveAllFromProcess(process_id);
129 }
130
RegisterExtensionWorkerProcess(const std::string & extension_id,int process_id,int site_instance_id)131 void InfoMap::RegisterExtensionWorkerProcess(const std::string& extension_id,
132 int process_id,
133 int site_instance_id) {
134 if (!worker_process_map_.Insert(extension_id, process_id, site_instance_id)) {
135 NOTREACHED() << "Duplicate extension worker process registration for: "
136 << extension_id << "," << process_id << ".";
137 }
138 }
139
UnregisterExtensionWorkerProcess(int process_id)140 void InfoMap::UnregisterExtensionWorkerProcess(int process_id) {
141 worker_process_map_.RemoveAllFromProcess(process_id);
142 }
143
GetExtensionsWithAPIPermissionForSecurityOrigin(const GURL & origin,int process_id,APIPermission::ID permission,ExtensionSet * extensions) const144 void InfoMap::GetExtensionsWithAPIPermissionForSecurityOrigin(
145 const GURL& origin,
146 int process_id,
147 APIPermission::ID permission,
148 ExtensionSet* extensions) const {
149 DCHECK(extensions);
150
151 if (origin.SchemeIs(kExtensionScheme)) {
152 const std::string& id = origin.host();
153 const Extension* extension = extensions_.GetByID(id);
154 if (extension &&
155 extension->permissions_data()->HasAPIPermission(permission) &&
156 process_map_.Contains(id, process_id)) {
157 extensions->Insert(extension);
158 }
159 return;
160 }
161
162 ExtensionSet::const_iterator i = extensions_.begin();
163 for (; i != extensions_.end(); ++i) {
164 if ((*i)->web_extent().MatchesSecurityOrigin(origin) &&
165 process_map_.Contains((*i)->id(), process_id) &&
166 (*i)->permissions_data()->HasAPIPermission(permission)) {
167 extensions->Insert(*i);
168 }
169 }
170 }
171
SecurityOriginHasAPIPermission(const GURL & origin,int process_id,APIPermission::ID permission) const172 bool InfoMap::SecurityOriginHasAPIPermission(const GURL& origin,
173 int process_id,
174 APIPermission::ID permission)
175 const {
176 ExtensionSet extensions;
177 GetExtensionsWithAPIPermissionForSecurityOrigin(
178 origin, process_id, permission, &extensions);
179 return !extensions.is_empty();
180 }
181
GetQuotaService()182 QuotaService* InfoMap::GetQuotaService() {
183 CheckOnValidThread();
184 if (!quota_service_)
185 quota_service_.reset(new QuotaService());
186 return quota_service_.get();
187 }
188
SetSigninProcess(int process_id)189 void InfoMap::SetSigninProcess(int process_id) {
190 signin_process_id_ = process_id;
191 }
192
IsSigninProcess(int process_id) const193 bool InfoMap::IsSigninProcess(int process_id) const {
194 return process_id == signin_process_id_;
195 }
196
SetNotificationsDisabled(const std::string & extension_id,bool notifications_disabled)197 void InfoMap::SetNotificationsDisabled(
198 const std::string& extension_id,
199 bool notifications_disabled) {
200 ExtraDataMap::iterator iter = extra_data_.find(extension_id);
201 if (iter != extra_data_.end())
202 iter->second.notifications_disabled = notifications_disabled;
203 }
204
AreNotificationsDisabled(const std::string & extension_id) const205 bool InfoMap::AreNotificationsDisabled(
206 const std::string& extension_id) const {
207 ExtraDataMap::const_iterator iter = extra_data_.find(extension_id);
208 if (iter != extra_data_.end())
209 return iter->second.notifications_disabled;
210 return false;
211 }
212
SetContentVerifier(ContentVerifier * verifier)213 void InfoMap::SetContentVerifier(ContentVerifier* verifier) {
214 content_verifier_ = verifier;
215 }
216
~InfoMap()217 InfoMap::~InfoMap() {
218 if (quota_service_) {
219 BrowserThread::DeleteSoon(
220 BrowserThread::IO, FROM_HERE, quota_service_.release());
221 }
222 }
223
224 } // namespace extensions
225