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

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: Using factory callback for prompts 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 PromptFactory* prompt_factory) {
35 if (prompt_factory) {
Andrew T Wilson (Slow) 2017/02/10 17:17:21 This is OK, but the other way to do this is to hav
Ivan Šandrk 2017/02/10 18:46:25 Done.
36 return prompt_factory->Run();
37 }
38 return base::MakeUnique<ExtensionInstallPrompt>(web_contents);
39 }
40
41 // This class is the internal implementation of HandlePermissionRequest(). It
42 // contains the actual prompt showing and resolving logic, and it caches the
43 // user choices.
44 class PublicSessionPermissionHelper {
45 public:
46 PublicSessionPermissionHelper();
47 PublicSessionPermissionHelper(PublicSessionPermissionHelper&& other);
48 ~PublicSessionPermissionHelper();
49
50 void HandlePermissionRequestImpl(const Extension& extension,
51 const PermissionIDSet& requested_permissions,
52 content::WebContents* web_contents,
53 const RequestResolvedCallback& callback,
54 PromptFactory* prompt_factory);
55
56 private:
57 void ResolvePermissionPrompt(
58 const ExtensionInstallPrompt* prompt,
59 const PermissionIDSet& unprompted_permissions,
60 ExtensionInstallPrompt::Result prompt_result);
61
62 PermissionIDSet FilterAllowedPermissions(
63 const PermissionIDSet& permissions);
64
65 struct RequestCallback {
66 RequestCallback(const RequestResolvedCallback& callback,
67 const PermissionIDSet& permission_list);
68 RequestCallback(const RequestCallback& other);
69 ~RequestCallback();
70 RequestResolvedCallback callback;
71 PermissionIDSet permission_list;
72 };
73 using RequestCallbackList = std::vector<RequestCallback>;
74
75 std::set<std::unique_ptr<ExtensionInstallPrompt>> prompts_;
76 PermissionIDSet prompted_permission_set_;
77 PermissionIDSet allowed_permission_set_;
78 PermissionIDSet denied_permission_set_;
79 RequestCallbackList callbacks_;
80
81 DISALLOW_COPY_AND_ASSIGN(PublicSessionPermissionHelper);
82 };
83
84 PublicSessionPermissionHelper::PublicSessionPermissionHelper() {}
85
86 PublicSessionPermissionHelper::PublicSessionPermissionHelper(
87 PublicSessionPermissionHelper&& other) = default;
88
89 PublicSessionPermissionHelper::~PublicSessionPermissionHelper() {}
90
91 void PublicSessionPermissionHelper::HandlePermissionRequestImpl(
92 const Extension& extension,
93 const PermissionIDSet& requested_permissions,
94 content::WebContents* web_contents,
95 const RequestResolvedCallback& callback,
96 PromptFactory* prompt_factory) {
97 CHECK(web_contents);
98
99 PermissionIDSet unresolved_permissions = PermissionIDSet::Difference(
100 requested_permissions, allowed_permission_set_);
101 unresolved_permissions = PermissionIDSet::Difference(
102 unresolved_permissions, denied_permission_set_);
103 if (unresolved_permissions.empty()) {
104 // All requested permissions are already resolved.
105 callback.Run(FilterAllowedPermissions(requested_permissions));
106 return;
107 }
108
109 // Since not all permissions are resolved yet, queue the callback to be called
110 // when all of them are resolved.
111 callbacks_.push_back(RequestCallback(callback, requested_permissions));
112
113 PermissionIDSet unprompted_permissions = PermissionIDSet::Difference(
114 unresolved_permissions, prompted_permission_set_);
115 if (unprompted_permissions.empty()) {
116 // Some permissions aren't resolved yet, but they are currently being
117 // prompted for, so no need to show a prompt.
118 return;
119 }
120
121 // Some permissions need prompting, setup the prompt and show it.
122 APIPermissionSet new_apis;
123 for (const auto& permission : unprompted_permissions) {
124 prompted_permission_set_.insert(permission.id());
125 new_apis.insert(permission.id());
126 }
127 auto permission_set = base::MakeUnique<PermissionSet>(
128 new_apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet());
129 auto prompt = CreateExtensionInstallPrompt(web_contents, prompt_factory);
130 // This Unretained is safe because the lifetime of this object is until
131 // process exit.
132 prompt->ShowDialog(
133 base::Bind(&PublicSessionPermissionHelper::ResolvePermissionPrompt,
134 base::Unretained(this), prompt.get(),
135 std::move(unprompted_permissions)),
136 &extension,
137 nullptr, // Use the extension icon.
138 base::MakeUnique<ExtensionInstallPrompt::Prompt>(
139 ExtensionInstallPrompt::PERMISSIONS_PROMPT),
140 std::move(permission_set),
141 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
142 prompts_.insert(std::move(prompt));
143 }
144
145 void PublicSessionPermissionHelper::ResolvePermissionPrompt(
146 const ExtensionInstallPrompt* prompt,
147 const PermissionIDSet& unprompted_permissions,
148 ExtensionInstallPrompt::Result prompt_result) {
149 const bool allowed =
150 prompt_result == ExtensionInstallPrompt::Result::ACCEPTED;
151 for (const auto& permission : unprompted_permissions) {
152 prompted_permission_set_.erase(permission.id());
153 if (allowed)
Devlin 2017/02/10 19:54:46 Optional: for fanciness, PermissionIdSet& add_to_s
Ivan Šandrk 2017/02/13 13:18:20 Seems nice. Done.
154 allowed_permission_set_.insert(permission.id());
155 else
156 denied_permission_set_.insert(permission.id());
157 }
158
159 // Here a list of callbacks to be invoked is created first from callbacks_,
160 // then those callbacks are invoked later because a callback can change
161 // callbacks_ while we're traversing them.
162 RequestCallbackList callbacks_to_invoke;
163 for (auto callback = callbacks_.begin(); callback != callbacks_.end(); ) {
164 if (prompted_permission_set_.ContainsAnyID(callback->permission_list)) {
165 // The request is still waiting on other permissions to be resolved - wait
166 // until all of them are resolved before calling the callback.
167 callback++;
168 continue;
169 }
170 callbacks_to_invoke.push_back(std::move(*callback));
171 callback = callbacks_.erase(callback);
172 }
173 for (auto callback = callbacks_to_invoke.begin();
174 callback != callbacks_to_invoke.end(); callback++) {
175 callback->callback.Run(FilterAllowedPermissions(callback->permission_list));
176 }
177
178 // Dispose of the prompt as it's not needed anymore.
179 auto iter = std::find_if(
180 prompts_.begin(), prompts_.end(),
181 [prompt](const std::unique_ptr<ExtensionInstallPrompt>& check) {
182 return check.get() == prompt;
183 });
184 DCHECK(iter != prompts_.end());
185 prompts_.erase(iter);
186 }
187
188 PermissionIDSet PublicSessionPermissionHelper::FilterAllowedPermissions(
189 const PermissionIDSet& permissions) {
190 PermissionIDSet allowed_permissions;
191 for (auto iter = permissions.begin(); iter != permissions.end(); iter++) {
192 if (allowed_permission_set_.ContainsID(*iter)) {
193 allowed_permissions.insert(iter->id());
194 }
195 }
196 return allowed_permissions;
197 }
198
199 PublicSessionPermissionHelper::RequestCallback::RequestCallback(
200 const RequestResolvedCallback& callback,
201 const PermissionIDSet& permission_list)
202 : callback(callback),
203 permission_list(permission_list) {}
204
205 PublicSessionPermissionHelper::RequestCallback::RequestCallback(
206 const RequestCallback& other) = default;
207
208 PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {}
209
210 base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky
211 g_helpers = LAZY_INSTANCE_INITIALIZER;
212
213 } // namespace
214
215 void HandlePermissionRequest(const Extension& extension,
216 const PermissionIDSet& requested_permissions,
217 content::WebContents* web_contents,
218 const RequestResolvedCallback& callback,
219 PromptFactory* prompt_factory) {
220 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
221 return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl(
222 extension, requested_permissions, web_contents, callback, prompt_factory);
223 }
224
225 void ResetPermissionsForTesting() {
226 g_helpers = LAZY_INSTANCE_INITIALIZER;
227 }
228
229 } // namespace permission_helper
230 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698