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

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

Powered by Google App Engine
This is Rietveld 408576698