OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/extensions/public_session_permission_helper.h" | 5 #include "chrome/browser/chromeos/extensions/public_session_permission_helper.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <map> | 8 #include <map> |
9 #include <memory> | 9 #include <memory> |
10 #include <utility> | 10 #include <utility> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/bind.h" | 13 #include "base/bind.h" |
14 #include "base/bind_helpers.h" | 14 #include "base/bind_helpers.h" |
15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
16 #include "base/macros.h" | 16 #include "base/macros.h" |
17 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
| 18 #include "chrome/browser/chromeos/extensions/device_local_account_management_pol
icy_provider.h" |
18 #include "chrome/browser/extensions/extension_install_prompt.h" | 19 #include "chrome/browser/extensions/extension_install_prompt.h" |
| 20 #include "chrome/browser/profiles/profiles_state.h" |
| 21 #include "chrome/grit/generated_resources.h" |
19 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/web_contents.h" | 23 #include "content/public/browser/web_contents.h" |
21 #include "extensions/common/extension.h" | 24 #include "extensions/common/extension.h" |
22 #include "extensions/common/extension_id.h" | 25 #include "extensions/common/extension_id.h" |
| 26 #include "extensions/common/permissions/api_permission_set.h" |
23 #include "extensions/common/permissions/manifest_permission_set.h" | 27 #include "extensions/common/permissions/manifest_permission_set.h" |
| 28 #include "extensions/common/permissions/permission_message.h" |
24 #include "extensions/common/permissions/permission_set.h" | 29 #include "extensions/common/permissions/permission_set.h" |
25 #include "extensions/common/url_pattern_set.h" | 30 #include "extensions/common/url_pattern_set.h" |
| 31 #include "ui/base/l10n/l10n_util.h" |
26 | 32 |
27 namespace extensions { | 33 namespace extensions { |
28 namespace permission_helper { | 34 namespace permission_helper { |
29 | 35 |
30 namespace { | 36 namespace { |
31 | 37 |
32 std::unique_ptr<ExtensionInstallPrompt> CreateExtensionInstallPrompt( | 38 std::unique_ptr<ExtensionInstallPrompt> CreateExtensionInstallPrompt( |
33 content::WebContents* web_contents) { | 39 content::WebContents* web_contents) { |
34 return base::MakeUnique<ExtensionInstallPrompt>(web_contents); | 40 return base::MakeUnique<ExtensionInstallPrompt>(web_contents); |
35 } | 41 } |
36 | 42 |
| 43 bool PermissionCheckNeeded(const Extension* extension) { |
| 44 return !chromeos::DeviceLocalAccountManagementPolicyProvider::IsWhitelisted( |
| 45 extension->id()); |
| 46 } |
| 47 |
37 // This class is the internal implementation of HandlePermissionRequest(). It | 48 // This class is the internal implementation of HandlePermissionRequest(). It |
38 // contains the actual prompt showing and resolving logic, and it caches the | 49 // contains the actual prompt showing and resolving logic, and it caches the |
39 // user choices. | 50 // user choices. |
40 class PublicSessionPermissionHelper { | 51 class PublicSessionPermissionHelper { |
41 public: | 52 public: |
42 PublicSessionPermissionHelper(); | 53 PublicSessionPermissionHelper(); |
43 PublicSessionPermissionHelper(PublicSessionPermissionHelper&& other); | 54 PublicSessionPermissionHelper(PublicSessionPermissionHelper&& other); |
44 ~PublicSessionPermissionHelper(); | 55 ~PublicSessionPermissionHelper(); |
45 | 56 |
46 void HandlePermissionRequestImpl(const Extension& extension, | 57 bool HandlePermissionRequestImpl(const Extension& extension, |
47 const PermissionIDSet& requested_permissions, | 58 const PermissionIDSet& requested_permissions, |
48 content::WebContents* web_contents, | 59 content::WebContents* web_contents, |
49 const RequestResolvedCallback& callback, | 60 const RequestResolvedCallback& callback, |
50 const PromptFactory& prompt_factory); | 61 const PromptFactory& prompt_factory); |
51 | 62 |
| 63 bool PermissionAllowedImpl(const Extension* extension, |
| 64 APIPermission::ID permission); |
| 65 |
52 private: | 66 private: |
53 void ResolvePermissionPrompt(const ExtensionInstallPrompt* prompt, | 67 void ResolvePermissionPrompt(const ExtensionInstallPrompt* prompt, |
54 const PermissionIDSet& unprompted_permissions, | 68 const PermissionIDSet& unprompted_permissions, |
55 ExtensionInstallPrompt::Result prompt_result); | 69 ExtensionInstallPrompt::Result prompt_result); |
56 | 70 |
57 PermissionIDSet FilterAllowedPermissions(const PermissionIDSet& permissions); | 71 PermissionIDSet FilterAllowedPermissions(const PermissionIDSet& permissions); |
58 | 72 |
59 struct RequestCallback { | 73 struct RequestCallback { |
60 RequestCallback(const RequestResolvedCallback& callback, | 74 RequestCallback(const RequestResolvedCallback& callback, |
61 const PermissionIDSet& permission_list); | 75 const PermissionIDSet& permission_list); |
(...skipping 13 matching lines...) Expand all Loading... |
75 DISALLOW_COPY_AND_ASSIGN(PublicSessionPermissionHelper); | 89 DISALLOW_COPY_AND_ASSIGN(PublicSessionPermissionHelper); |
76 }; | 90 }; |
77 | 91 |
78 PublicSessionPermissionHelper::PublicSessionPermissionHelper() {} | 92 PublicSessionPermissionHelper::PublicSessionPermissionHelper() {} |
79 | 93 |
80 PublicSessionPermissionHelper::PublicSessionPermissionHelper( | 94 PublicSessionPermissionHelper::PublicSessionPermissionHelper( |
81 PublicSessionPermissionHelper&& other) = default; | 95 PublicSessionPermissionHelper&& other) = default; |
82 | 96 |
83 PublicSessionPermissionHelper::~PublicSessionPermissionHelper() {} | 97 PublicSessionPermissionHelper::~PublicSessionPermissionHelper() {} |
84 | 98 |
85 void PublicSessionPermissionHelper::HandlePermissionRequestImpl( | 99 bool PublicSessionPermissionHelper::HandlePermissionRequestImpl( |
86 const Extension& extension, | 100 const Extension& extension, |
87 const PermissionIDSet& requested_permissions, | 101 const PermissionIDSet& requested_permissions, |
88 content::WebContents* web_contents, | 102 content::WebContents* web_contents, |
89 const RequestResolvedCallback& callback, | 103 const RequestResolvedCallback& callback, |
90 const PromptFactory& prompt_factory) { | 104 const PromptFactory& prompt_factory) { |
91 CHECK(web_contents); | 105 DCHECK(profiles::IsPublicSession()); |
| 106 if (!PermissionCheckNeeded(&extension)) { |
| 107 if (!callback.is_null()) |
| 108 callback.Run(requested_permissions); |
| 109 return true; |
| 110 } |
92 | 111 |
93 PermissionIDSet unresolved_permissions = PermissionIDSet::Difference( | 112 PermissionIDSet unresolved_permissions = PermissionIDSet::Difference( |
94 requested_permissions, allowed_permission_set_); | 113 requested_permissions, allowed_permission_set_); |
95 unresolved_permissions = PermissionIDSet::Difference( | 114 unresolved_permissions = PermissionIDSet::Difference( |
96 unresolved_permissions, denied_permission_set_); | 115 unresolved_permissions, denied_permission_set_); |
97 if (unresolved_permissions.empty()) { | 116 if (unresolved_permissions.empty()) { |
98 // All requested permissions are already resolved. | 117 // All requested permissions are already resolved. |
99 callback.Run(FilterAllowedPermissions(requested_permissions)); | 118 if (!callback.is_null()) |
100 return; | 119 callback.Run(FilterAllowedPermissions(requested_permissions)); |
| 120 return true; |
101 } | 121 } |
102 | 122 |
103 // Since not all permissions are resolved yet, queue the callback to be called | 123 // Since not all permissions are resolved yet, queue the callback to be called |
104 // when all of them are resolved. | 124 // when all of them are resolved. |
105 callbacks_.push_back(RequestCallback(callback, requested_permissions)); | 125 if (!callback.is_null()) |
| 126 callbacks_.push_back(RequestCallback(callback, requested_permissions)); |
106 | 127 |
107 PermissionIDSet unprompted_permissions = PermissionIDSet::Difference( | 128 PermissionIDSet unprompted_permissions = PermissionIDSet::Difference( |
108 unresolved_permissions, prompted_permission_set_); | 129 unresolved_permissions, prompted_permission_set_); |
109 if (unprompted_permissions.empty()) { | 130 if (unprompted_permissions.empty()) { |
110 // Some permissions aren't resolved yet, but they are currently being | 131 // Some permissions aren't resolved yet, but they are currently being |
111 // prompted for, so no need to show a prompt. | 132 // prompted for, so no need to show a prompt. |
112 return; | 133 return false; |
113 } | 134 } |
114 | 135 |
115 // Some permissions need prompting, setup the prompt and show it. | 136 // Some permissions need prompting, setup the prompt and show it. |
116 APIPermissionSet new_apis; | 137 APIPermissionSet new_apis; |
117 for (const auto& permission : unprompted_permissions) { | 138 for (const auto& permission : unprompted_permissions) { |
118 prompted_permission_set_.insert(permission.id()); | 139 prompted_permission_set_.insert(permission.id()); |
119 new_apis.insert(permission.id()); | 140 new_apis.insert(permission.id()); |
120 } | 141 } |
121 auto permission_set = base::MakeUnique<PermissionSet>( | 142 auto permission_set = base::MakeUnique<PermissionSet>( |
122 new_apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet()); | 143 new_apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet()); |
123 auto prompt = prompt_factory.Run(web_contents); | 144 auto prompt = prompt_factory.Run(web_contents); |
| 145 |
| 146 auto permissions_prompt = base::MakeUnique<ExtensionInstallPrompt::Prompt>( |
| 147 ExtensionInstallPrompt::PERMISSIONS_PROMPT); |
| 148 // activeTab has no permission message by default, so one is added here. |
| 149 if (unprompted_permissions.ContainsID(APIPermission::kActiveTab)) { |
| 150 PermissionMessages messages; |
| 151 messages.push_back(PermissionMessage( |
| 152 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_CURRENT_HOST), |
| 153 extensions::PermissionIDSet())); |
| 154 permissions_prompt->AddPermissions( |
| 155 messages, ExtensionInstallPrompt::REGULAR_PERMISSIONS); |
| 156 } |
| 157 |
124 // This Unretained is safe because the lifetime of this object is until | 158 // This Unretained is safe because the lifetime of this object is until |
125 // process exit. | 159 // process exit. |
126 prompt->ShowDialog( | 160 prompt->ShowDialog( |
127 base::Bind(&PublicSessionPermissionHelper::ResolvePermissionPrompt, | 161 base::Bind(&PublicSessionPermissionHelper::ResolvePermissionPrompt, |
128 base::Unretained(this), prompt.get(), | 162 base::Unretained(this), prompt.get(), |
129 std::move(unprompted_permissions)), | 163 std::move(unprompted_permissions)), |
130 &extension, | 164 &extension, |
131 nullptr, // Use the extension icon. | 165 nullptr, // Use the extension icon. |
132 base::MakeUnique<ExtensionInstallPrompt::Prompt>( | 166 std::move(permissions_prompt), |
133 ExtensionInstallPrompt::PERMISSIONS_PROMPT), | |
134 std::move(permission_set), | 167 std::move(permission_set), |
135 ExtensionInstallPrompt::GetDefaultShowDialogCallback()); | 168 ExtensionInstallPrompt::GetDefaultShowDialogCallback()); |
136 prompts_.insert(std::move(prompt)); | 169 prompts_.insert(std::move(prompt)); |
| 170 |
| 171 return false; |
| 172 } |
| 173 |
| 174 bool PublicSessionPermissionHelper::PermissionAllowedImpl( |
| 175 const Extension* extension, |
| 176 APIPermission::ID permission) { |
| 177 DCHECK(profiles::IsPublicSession()); |
| 178 return !PermissionCheckNeeded(extension) || |
| 179 allowed_permission_set_.ContainsID(permission); |
137 } | 180 } |
138 | 181 |
139 void PublicSessionPermissionHelper::ResolvePermissionPrompt( | 182 void PublicSessionPermissionHelper::ResolvePermissionPrompt( |
140 const ExtensionInstallPrompt* prompt, | 183 const ExtensionInstallPrompt* prompt, |
141 const PermissionIDSet& unprompted_permissions, | 184 const PermissionIDSet& unprompted_permissions, |
142 ExtensionInstallPrompt::Result prompt_result) { | 185 ExtensionInstallPrompt::Result prompt_result) { |
143 PermissionIDSet& add_to_set = | 186 PermissionIDSet& add_to_set = |
144 prompt_result == ExtensionInstallPrompt::Result::ACCEPTED ? | 187 prompt_result == ExtensionInstallPrompt::Result::ACCEPTED ? |
145 allowed_permission_set_ : denied_permission_set_; | 188 allowed_permission_set_ : denied_permission_set_; |
146 for (const auto& permission : unprompted_permissions) { | 189 for (const auto& permission : unprompted_permissions) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 PublicSessionPermissionHelper::RequestCallback::RequestCallback( | 239 PublicSessionPermissionHelper::RequestCallback::RequestCallback( |
197 const RequestCallback& other) = default; | 240 const RequestCallback& other) = default; |
198 | 241 |
199 PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {} | 242 PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {} |
200 | 243 |
201 base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky | 244 base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky |
202 g_helpers = LAZY_INSTANCE_INITIALIZER; | 245 g_helpers = LAZY_INSTANCE_INITIALIZER; |
203 | 246 |
204 } // namespace | 247 } // namespace |
205 | 248 |
206 void HandlePermissionRequest(const Extension& extension, | 249 bool HandlePermissionRequest(const Extension& extension, |
207 const PermissionIDSet& requested_permissions, | 250 const PermissionIDSet& requested_permissions, |
208 content::WebContents* web_contents, | 251 content::WebContents* web_contents, |
209 const RequestResolvedCallback& callback, | 252 const RequestResolvedCallback& callback, |
210 const PromptFactory& prompt_factory) { | 253 const PromptFactory& prompt_factory) { |
211 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 254 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
212 const PromptFactory& factory = prompt_factory.is_null() | 255 const PromptFactory& factory = prompt_factory.is_null() |
213 ? base::Bind(&CreateExtensionInstallPrompt) | 256 ? base::Bind(&CreateExtensionInstallPrompt) |
214 : prompt_factory; | 257 : prompt_factory; |
215 return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl( | 258 return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl( |
216 extension, requested_permissions, web_contents, callback, factory); | 259 extension, requested_permissions, web_contents, callback, factory); |
217 } | 260 } |
218 | 261 |
| 262 bool PermissionAllowed(const Extension* extension, |
| 263 APIPermission::ID permission) { |
| 264 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 265 return g_helpers.Get()[extension->id()].PermissionAllowedImpl(extension, |
| 266 permission); |
| 267 } |
| 268 |
219 void ResetPermissionsForTesting() { | 269 void ResetPermissionsForTesting() { |
220 // Clear out the std::map between tests. Just setting g_helpers to | 270 // Clear out the std::map between tests. Just setting g_helpers to |
221 // LAZY_INSTANCE_INITIALIZER again causes a memory leak (because of the | 271 // LAZY_INSTANCE_INITIALIZER again causes a memory leak (because of the |
222 // LazyInstance::Leaky). | 272 // LazyInstance::Leaky). |
223 g_helpers.Get().clear(); | 273 g_helpers.Get().clear(); |
224 } | 274 } |
225 | 275 |
226 } // namespace permission_helper | 276 } // namespace permission_helper |
227 } // namespace extensions | 277 } // namespace extensions |
OLD | NEW |