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 "base/strings/string_util.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "extensions/browser/content_verifier.h"
10 #include "extensions/browser/unloaded_extension_reason.h"
11 #include "extensions/common/constants.h"
12 #include "extensions/common/extension.h"
13 #include "extensions/common/extension_resource.h"
14 #include "extensions/common/extension_set.h"
15 #include "extensions/common/manifest_handlers/incognito_info.h"
16 #include "extensions/common/permissions/permissions_data.h"
17 #include "url/gurl.h"
18 
19 using content::BrowserThread;
20 
21 namespace extensions {
22 
23 namespace {
24 
CheckOnValidThread()25 void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
26 
27 }  // namespace
28 
29 struct InfoMap::ExtraData {
30   // 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 
36   // True if the user has disabled notifications for this extension manually.
37   bool notifications_disabled;
38 
39   ExtraData();
40   ~ExtraData();
41 };
42 
ExtraData()43 InfoMap::ExtraData::ExtraData()
44     : incognito_enabled(false), notifications_disabled(false) {
45 }
46 
~ExtraData()47 InfoMap::ExtraData::~ExtraData() {}
48 
InfoMap()49 InfoMap::InfoMap() {}
50 
extensions() const51 const ExtensionSet& InfoMap::extensions() const {
52   CheckOnValidThread();
53   return extensions_;
54 }
55 
disabled_extensions() const56 const ExtensionSet& InfoMap::disabled_extensions() const {
57   CheckOnValidThread();
58   return disabled_extensions_;
59 }
60 
AddExtension(const Extension * extension,base::Time install_time,bool incognito_enabled,bool notifications_disabled)61 void InfoMap::AddExtension(const Extension* extension,
62                            base::Time install_time,
63                            bool incognito_enabled,
64                            bool notifications_disabled) {
65   CheckOnValidThread();
66   extensions_.Insert(extension);
67   disabled_extensions_.Remove(extension->id());
68 
69   extra_data_[extension->id()].install_time = install_time;
70   extra_data_[extension->id()].incognito_enabled = incognito_enabled;
71   extra_data_[extension->id()].notifications_disabled = notifications_disabled;
72 }
73 
RemoveExtension(const std::string & extension_id,const UnloadedExtensionReason reason)74 void InfoMap::RemoveExtension(const std::string& extension_id,
75                               const UnloadedExtensionReason reason) {
76   CheckOnValidThread();
77   const Extension* extension = extensions_.GetByID(extension_id);
78   extra_data_.erase(extension_id);  // we don't care about disabled extra data
79   bool was_uninstalled = (reason != UnloadedExtensionReason::DISABLE &&
80                           reason != UnloadedExtensionReason::TERMINATE);
81   if (extension) {
82     if (!was_uninstalled)
83       disabled_extensions_.Insert(extension);
84     extensions_.Remove(extension_id);
85   } else if (was_uninstalled) {
86     // If the extension was uninstalled, make sure it's removed from the map of
87     // disabled extensions.
88     disabled_extensions_.Remove(extension_id);
89   } else {
90     // NOTE: This can currently happen if we receive multiple unload
91     // notifications, e.g. setting incognito-enabled state for a
92     // disabled extension (e.g., via sync).  See
93     // http://code.google.com/p/chromium/issues/detail?id=50582 .
94     NOTREACHED() << extension_id;
95   }
96 }
97 
GetInstallTime(const std::string & extension_id) const98 base::Time InfoMap::GetInstallTime(const std::string& extension_id) const {
99   auto iter = extra_data_.find(extension_id);
100   if (iter != extra_data_.end())
101     return iter->second.install_time;
102   return base::Time();
103 }
104 
IsIncognitoEnabled(const std::string & extension_id) const105 bool InfoMap::IsIncognitoEnabled(const std::string& extension_id) const {
106   // Keep in sync with duplicate in extensions/browser/process_manager.cc.
107   auto iter = extra_data_.find(extension_id);
108   if (iter != extra_data_.end())
109     return iter->second.incognito_enabled;
110   return false;
111 }
112 
CanCrossIncognito(const Extension * extension) const113 bool InfoMap::CanCrossIncognito(const Extension* extension) const {
114   // This is duplicated from ExtensionService :(.
115   return IsIncognitoEnabled(extension->id()) &&
116          !IncognitoInfo::IsSplitMode(extension);
117 }
118 
RegisterExtensionProcess(const std::string & extension_id,int process_id,int site_instance_id)119 void InfoMap::RegisterExtensionProcess(const std::string& extension_id,
120                                        int process_id,
121                                        int site_instance_id) {
122   if (!process_map_.Insert(extension_id, process_id, site_instance_id)) {
123     NOTREACHED() << "Duplicate extension process registration for: "
124                  << extension_id << "," << process_id << ".";
125   }
126 }
127 
UnregisterExtensionProcess(const std::string & extension_id,int process_id,int site_instance_id)128 void InfoMap::UnregisterExtensionProcess(const std::string& extension_id,
129                                          int process_id,
130                                          int site_instance_id) {
131   if (!process_map_.Remove(extension_id, process_id, site_instance_id)) {
132     NOTREACHED() << "Unknown extension process registration for: "
133                  << extension_id << "," << process_id << ".";
134   }
135 }
136 
UnregisterAllExtensionsInProcess(int process_id)137 void InfoMap::UnregisterAllExtensionsInProcess(int process_id) {
138   process_map_.RemoveAllFromProcess(process_id);
139 }
140 
GetQuotaService()141 QuotaService* InfoMap::GetQuotaService() {
142   CheckOnValidThread();
143   if (!quota_service_)
144     quota_service_.reset(new QuotaService());
145   return quota_service_.get();
146 }
147 
SetNotificationsDisabled(const std::string & extension_id,bool notifications_disabled)148 void InfoMap::SetNotificationsDisabled(
149     const std::string& extension_id,
150     bool notifications_disabled) {
151   auto iter = extra_data_.find(extension_id);
152   if (iter != extra_data_.end())
153     iter->second.notifications_disabled = notifications_disabled;
154 }
155 
AreNotificationsDisabled(const std::string & extension_id) const156 bool InfoMap::AreNotificationsDisabled(
157     const std::string& extension_id) const {
158   auto iter = extra_data_.find(extension_id);
159   if (iter != extra_data_.end())
160     return iter->second.notifications_disabled;
161   return false;
162 }
163 
SetContentVerifier(ContentVerifier * verifier)164 void InfoMap::SetContentVerifier(ContentVerifier* verifier) {
165   content_verifier_ = verifier;
166 }
167 
SetIsLockScreenContext(bool is_lock_screen_context)168 void InfoMap::SetIsLockScreenContext(bool is_lock_screen_context) {
169   process_map_.set_is_lock_screen_context(is_lock_screen_context);
170 }
171 
172 InfoMap::~InfoMap() = default;
173 
174 }  // namespace extensions
175