• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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