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

Side by Side Diff: chrome/browser/media/public_session_media_access_handler.cc

Issue 2532323003: Public Sessions - prompt the user for audioCapture/videoCapture requests (Closed)
Patch Set: Rebase Created 4 years 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 2016 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/media/public_session_media_access_handler.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/bind_helpers.h"
11 #include "base/memory/ptr_util.h"
12 #include "chromeos/login/login_state.h"
13 #include "content/public/browser/web_contents.h"
14 #include "extensions/common/extension.h"
15 #include "extensions/common/permissions/manifest_permission_set.h"
16 #include "extensions/common/permissions/permission_set.h"
17 #include "extensions/common/url_pattern_set.h"
18
19 namespace {
20
21 // Returns true if we're in a Public Session.
22 bool IsPublicSession() {
23 #if defined(OS_CHROMEOS)
Devlin 2016/12/02 20:40:28 This should only be compiled on CrOS; remove ifdef
Ivan Šandrk 2016/12/05 13:10:51 Done.
24 if (chromeos::LoginState::IsInitialized()) {
Devlin 2016/12/02 20:40:28 simplify to return chromeos::LoginState::IsInitial
Ivan Šandrk 2016/12/05 13:10:50 Done.
25 return chromeos::LoginState::Get()->IsPublicSessionUser();
26 }
27 #endif
28 return false;
29 }
30
31 } // namespace
32
33 PublicSessionMediaAccessHandler::PublicSessionMediaAccessHandler() {}
34
35 PublicSessionMediaAccessHandler::~PublicSessionMediaAccessHandler() {}
36
37 bool PublicSessionMediaAccessHandler::SupportsStreamType(
38 const content::MediaStreamType type,
39 const extensions::Extension* extension) {
40 return ExtensionMediaAccessHandler::SupportsStreamType(type, extension);
Devlin 2016/12/02 20:40:28 No need to override this if we just return the par
Ivan Šandrk 2016/12/05 13:10:51 Acknowledged.
41 }
42
43 bool PublicSessionMediaAccessHandler::CheckMediaAccessPermission(
44 content::WebContents* web_contents,
45 const GURL& security_origin,
46 content::MediaStreamType type,
47 const extensions::Extension* extension) {
48 return ExtensionMediaAccessHandler::CheckMediaAccessPermission(
Devlin 2016/12/02 20:40:28 ditto
Ivan Šandrk 2016/12/05 13:10:51 Acknowledged.
49 web_contents, security_origin, type, extension);
50 }
51
52 void PublicSessionMediaAccessHandler::HandleRequest(
53 content::WebContents* web_contents,
54 const content::MediaStreamRequest& request,
55 const content::MediaResponseCallback& callback,
56 const extensions::Extension* extension) {
57 // This class handles requests for Public Sessions only, outside of them just
58 // pass the request through to the original class.
59 if (!(IsPublicSession() && extension && extension->is_platform_app()))
Sergey Ulanov 2016/12/02 20:29:47 don't need to check extension here. This function
Ivan Šandrk 2016/12/05 13:10:51 Done.
60 return ExtensionMediaAccessHandler::HandleRequest(web_contents, request,
Sergey Ulanov 2016/12/02 20:29:47 need {} for multi-line if blocks: https://google.g
Ivan Šandrk 2016/12/05 13:10:51 Done.
61 callback, extension);
62
63 bool needs_prompt = false;
64 extensions::APIPermissionSet new_apis;
65 const UserChoice& user_choice = user_choice_cache_[extension->id()];
66
67 if (user_choice.NeedsPrompting(request.audio_type)) {
68 new_apis.insert(extensions::APIPermission::kAudioCapture);
69 needs_prompt = true;
70 }
71 if (user_choice.NeedsPrompting(request.video_type)) {
72 new_apis.insert(extensions::APIPermission::kVideoCapture);
73 needs_prompt = true;
74 }
75
76 if (needs_prompt) {
Sergey Ulanov 2016/12/02 20:29:47 The code would be more readable if you handle !nee
Devlin 2016/12/02 20:40:28 (+1)
Ivan Šandrk 2016/12/05 13:10:51 Good point!
77 auto permission_set = base::MakeUnique<extensions::PermissionSet>(
78 new_apis, extensions::ManifestPermissionSet(),
79 extensions::URLPatternSet(), extensions::URLPatternSet());
80
81 auto prompt = base::MakeUnique<ExtensionInstallPrompt>(web_contents);
82 // Raw copy used *only* for calling ShowDialog (to avoid the awkward
83 // situation where the same unique_ptr is used as this and is passed through
84 // inside a callback).
85 auto prompt_raw = prompt.get();
86
87 // "Dialog closed" callback owns the prompt, hence the prompt gets destroyed
88 // together with the callback. The callback is guaranteed to be destroyed
Andrew T Wilson (Slow) 2016/12/04 19:57:01 how is the destruction of the callback guaranteed?
Ivan Šandrk 2016/12/05 17:04:46 Changed the approach.
89 // even if it's not run.
90 prompt_raw->ShowDialog(
91 base::Bind(&PublicSessionMediaAccessHandler::ResolvePermissionPrompt,
92 base::Unretained(this), web_contents, request, callback,
93 extension, std::move(prompt)),
94 extension,
95 nullptr, // Uses the extension icon.
96 base::MakeUnique<ExtensionInstallPrompt::Prompt>(
97 ExtensionInstallPrompt::PERMISSIONS_PROMPT),
98 std::move(permission_set),
99 ExtensionInstallPrompt::GetDefaultShowDialogCallback());
100 return;
101 }
102
103 ChainHandleRequest(web_contents, request, callback, extension);
104 }
105
106 void PublicSessionMediaAccessHandler::ChainHandleRequest(
107 content::WebContents* web_contents,
108 const content::MediaStreamRequest& request,
109 const content::MediaResponseCallback& callback,
110 const extensions::Extension* extension) {
111 DCHECK(IsPublicSession() && extension && extension->is_platform_app());
112 const UserChoice& user_choice = user_choice_cache_[extension->id()];
113 content::MediaStreamRequest request_copy(request);
114
115 if (!user_choice.IsAllowed(content::MEDIA_DEVICE_AUDIO_CAPTURE))
Andrew T Wilson (Slow) 2016/12/04 19:57:01 Can you comment about what this code is doing?
Ivan Šandrk 2016/12/05 17:04:46 Done.
116 request_copy.audio_type = content::MEDIA_NO_SERVICE;
117 if (!user_choice.IsAllowed(content::MEDIA_DEVICE_VIDEO_CAPTURE))
118 request_copy.video_type = content::MEDIA_NO_SERVICE;
119
120 // Pass the request through to the original class.
121 ExtensionMediaAccessHandler::HandleRequest(web_contents, request_copy,
122 callback, extension);
123 }
124
125 void PublicSessionMediaAccessHandler::ResolvePermissionPrompt(
126 content::WebContents* web_contents,
127 const content::MediaStreamRequest& request,
128 const content::MediaResponseCallback& callback,
129 const extensions::Extension* extension,
130 const std::unique_ptr<ExtensionInstallPrompt>& prompt,
131 ExtensionInstallPrompt::Result prompt_result) {
132 bool allowed = (prompt_result == ExtensionInstallPrompt::Result::ACCEPTED);
Devlin 2016/12/02 20:40:28 nit: parens unnecessary
Ivan Šandrk 2016/12/05 13:10:51 Done.
133 UserChoice& user_choice = user_choice_cache_[extension->id()];
134
135 if (user_choice.NeedsPrompting(request.audio_type))
136 user_choice.Set(content::MEDIA_DEVICE_AUDIO_CAPTURE, allowed);
137 if (user_choice.NeedsPrompting(request.video_type))
138 user_choice.Set(content::MEDIA_DEVICE_VIDEO_CAPTURE, allowed);
139
140 ChainHandleRequest(web_contents, request, callback, extension);
141 }
142
143 bool PublicSessionMediaAccessHandler::UserChoice::IsAllowed(
144 content::MediaStreamType type) const {
145 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
Sergey Ulanov 2016/12/02 20:29:47 nit: Maybe replace this with a switch statement Sa
Ivan Šandrk 2016/12/05 13:10:51 Done.
146 return !audio_prompted_ || audio_allowed_;
147 } else {
Devlin 2016/12/02 20:40:28 I like Sergey's idea about the switch, so probably
Ivan Šandrk 2016/12/05 13:10:51 Good point.
148 DCHECK(type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
149 return !video_prompted_ || video_allowed_;
150 }
151 }
152
153 bool PublicSessionMediaAccessHandler::UserChoice::NeedsPrompting(
154 content::MediaStreamType type) const {
155 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
156 return !audio_prompted_;
157 }
158 if (type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
159 return !video_prompted_;
160 }
161 return false;
Sergey Ulanov 2016/12/02 20:29:47 add NOTREACHED() here?
Ivan Šandrk 2016/12/05 13:10:51 This part is hit sometimes (when type is content::
162 }
163
164 void PublicSessionMediaAccessHandler::UserChoice::Set(
165 content::MediaStreamType type, bool allowed) {
166 if (type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
167 DCHECK(!audio_prompted_);
168 audio_prompted_ = true;
169 audio_allowed_ = allowed;
170 } else {
171 DCHECK(type == content::MEDIA_DEVICE_VIDEO_CAPTURE);
Devlin 2016/12/02 20:40:28 nit: DCHECK_EQ
Ivan Šandrk 2016/12/05 13:10:51 Done.
172 DCHECK(!video_prompted_);
173 video_prompted_ = true;
174 video_allowed_ = allowed;
175 }
176 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698