Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(125)

Side by Side Diff: chrome/browser/chromeos/extensions/public_session_permission_helper.cc

Issue 2552203007: Public Sessions - prompt the user for pageCapture requests (Closed)
Patch Set: Drew's comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/extensions/public_session_permission_helper.h"
6
7 #include <algorithm>
8 #include <map>
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
15 #include "base/lazy_instance.h"
16 #include "base/macros.h"
17 #include "base/memory/ptr_util.h"
18 #include "chrome/browser/extensions/extension_install_prompt.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/web_contents.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/extension_id.h"
23 #include "extensions/common/permissions/manifest_permission_set.h"
24 #include "extensions/common/permissions/permission_set.h"
25 #include "extensions/common/url_pattern_set.h"
26
27 namespace extensions {
28 namespace permission_helper {
29
30 namespace {
31
32 std::unique_ptr<ExtensionInstallPrompt> CreateExtensionInstallPrompt(
33 content::WebContents* web_contents) {
34 return base::MakeUnique<ExtensionInstallPrompt>(web_contents);
35 }
36
37 // This class is the internal implementation of HandlePermissionRequest(). It
38 // contains the actual prompt showing and resolving logic, and it caches the
39 // user choices.
40 class PublicSessionPermissionHelper {
41 public:
42 PublicSessionPermissionHelper();
43 PublicSessionPermissionHelper(PublicSessionPermissionHelper&& other);
44 ~PublicSessionPermissionHelper();
45
46 void HandlePermissionRequestImpl(const Extension& extension,
47 const PermissionIDSet& requested_permissions,
48 content::WebContents* web_contents,
49 const RequestResolvedCallback& callback,
50 const PromptFactory& prompt_factory);
51
52 private:
53 void ResolvePermissionPrompt(
54 const ExtensionInstallPrompt* prompt,
55 const PermissionIDSet& unprompted_permissions,
56 ExtensionInstallPrompt::Result prompt_result);
57
58 PermissionIDSet FilterAllowedPermissions(
59 const PermissionIDSet& permissions);
60
61 struct RequestCallback {
62 RequestCallback(const RequestResolvedCallback& callback,
63 const PermissionIDSet& permission_list);
64 RequestCallback(const RequestCallback& other);
65 ~RequestCallback();
66 RequestResolvedCallback callback;
67 PermissionIDSet permission_list;
68 };
69 using RequestCallbackList = std::vector<RequestCallback>;
70
71 std::set<std::unique_ptr<ExtensionInstallPrompt>> prompts_;
72 PermissionIDSet prompted_permission_set_;
73 PermissionIDSet allowed_permission_set_;
74 PermissionIDSet denied_permission_set_;
75 RequestCallbackList callbacks_;
76
77 DISALLOW_COPY_AND_ASSIGN(PublicSessionPermissionHelper);
78 };
79
80 PublicSessionPermissionHelper::PublicSessionPermissionHelper() {}
81
82 PublicSessionPermissionHelper::PublicSessionPermissionHelper(
83 PublicSessionPermissionHelper&& other) = default;
84
85 PublicSessionPermissionHelper::~PublicSessionPermissionHelper() {}
86
87 void PublicSessionPermissionHelper::HandlePermissionRequestImpl(
88 const Extension& extension,
89 const PermissionIDSet& requested_permissions,
90 content::WebContents* web_contents,
91 const RequestResolvedCallback& callback,
92 const PromptFactory& prompt_factory) {
93 CHECK(web_contents);
94
95 PermissionIDSet unresolved_permissions = PermissionIDSet::Difference(
96 requested_permissions, allowed_permission_set_);
97 unresolved_permissions = PermissionIDSet::Difference(
98 unresolved_permissions, denied_permission_set_);
99 if (unresolved_permissions.empty()) {
100 // All requested permissions are already resolved.
101 callback.Run(FilterAllowedPermissions(requested_permissions));
102 return;
103 }
104
105 // Since not all permissions are resolved yet, queue the callback to be called
106 // when all of them are resolved.
107 callbacks_.push_back(RequestCallback(callback, requested_permissions));
108
109 PermissionIDSet unprompted_permissions = PermissionIDSet::Difference(
110 unresolved_permissions, prompted_permission_set_);
111 if (unprompted_permissions.empty()) {
112 // Some permissions aren't resolved yet, but they are currently being
113 // prompted for, so no need to show a prompt.
114 return;
115 }
116
117 // Some permissions need prompting, setup the prompt and show it.
118 APIPermissionSet new_apis;
119 for (const auto& permission : unprompted_permissions) {
120 prompted_permission_set_.insert(permission.id());
121 new_apis.insert(permission.id());
122 }
123 auto permission_set = base::MakeUnique<PermissionSet>(
124 new_apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet());
125 auto prompt = prompt_factory.Run(web_contents);
126 // This Unretained is safe because the lifetime of this object is until
127 // process exit.
128 prompt->ShowDialog(
129 base::Bind(&PublicSessionPermissionHelper::ResolvePermissionPrompt,
130 base::Unretained(this), prompt.get(),
131 std::move(unprompted_permissions)),
132 &extension,
133 nullptr, // Use the extension icon.
134 base::MakeUnique<ExtensionInstallPrompt::Prompt>(
135 ExtensionInstallPrompt::PERMISSIONS_PROMPT),
136 std::move(permission_set),
137 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
138 prompts_.insert(std::move(prompt));
139 }
140
141 void PublicSessionPermissionHelper::ResolvePermissionPrompt(
142 const ExtensionInstallPrompt* prompt,
143 const PermissionIDSet& unprompted_permissions,
144 ExtensionInstallPrompt::Result prompt_result) {
145 const bool allowed =
146 prompt_result == ExtensionInstallPrompt::Result::ACCEPTED;
147 for (const auto& permission : unprompted_permissions) {
148 prompted_permission_set_.erase(permission.id());
149 if (allowed)
150 allowed_permission_set_.insert(permission.id());
151 else
152 denied_permission_set_.insert(permission.id());
153 }
154
155 // Here a list of callbacks to be invoked is created first from callbacks_,
156 // then those callbacks are invoked later because a callback can change
157 // callbacks_ while we're traversing them.
158 RequestCallbackList callbacks_to_invoke;
159 for (auto callback = callbacks_.begin(); callback != callbacks_.end(); ) {
160 if (prompted_permission_set_.ContainsAnyID(callback->permission_list)) {
161 // The request is still waiting on other permissions to be resolved - wait
162 // until all of them are resolved before calling the callback.
163 callback++;
164 continue;
165 }
166 callbacks_to_invoke.push_back(std::move(*callback));
167 callback = callbacks_.erase(callback);
168 }
169 for (auto callback = callbacks_to_invoke.begin();
170 callback != callbacks_to_invoke.end(); callback++) {
171 callback->callback.Run(FilterAllowedPermissions(callback->permission_list));
172 }
173
174 // Dispose of the prompt as it's not needed anymore.
175 auto iter = std::find_if(
176 prompts_.begin(), prompts_.end(),
177 [prompt](const std::unique_ptr<ExtensionInstallPrompt>& check) {
178 return check.get() == prompt;
179 });
180 DCHECK(iter != prompts_.end());
181 prompts_.erase(iter);
182 }
183
184 PermissionIDSet PublicSessionPermissionHelper::FilterAllowedPermissions(
185 const PermissionIDSet& permissions) {
186 PermissionIDSet allowed_permissions;
187 for (auto iter = permissions.begin(); iter != permissions.end(); iter++) {
188 if (allowed_permission_set_.ContainsID(*iter)) {
189 allowed_permissions.insert(iter->id());
190 }
191 }
192 return allowed_permissions;
193 }
194
195 PublicSessionPermissionHelper::RequestCallback::RequestCallback(
196 const RequestResolvedCallback& callback,
197 const PermissionIDSet& permission_list)
198 : callback(callback),
199 permission_list(permission_list) {}
200
201 PublicSessionPermissionHelper::RequestCallback::RequestCallback(
202 const RequestCallback& other) = default;
203
204 PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {}
205
206 base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky
207 g_helpers = LAZY_INSTANCE_INITIALIZER;
208
209 } // namespace
210
211 void HandlePermissionRequest(const Extension& extension,
212 const PermissionIDSet& requested_permissions,
213 content::WebContents* web_contents,
214 const RequestResolvedCallback& callback,
215 const PromptFactory& prompt_factory) {
216 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
217 const PromptFactory& factory = prompt_factory.is_null()
218 ? base::Bind(&CreateExtensionInstallPrompt)
219 : prompt_factory;
220 return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl(
221 extension, requested_permissions, web_contents, callback, factory);
222 }
223
224 void ResetPermissionsForTesting() {
225 g_helpers = LAZY_INSTANCE_INITIALIZER;
226 }
227
228 } // namespace permission_helper
229 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698