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