 Chromium Code Reviews
 Chromium Code Reviews Issue 2858013002:
  PS - Showing permission prompt for activeTab  (Closed)
    
  
    Issue 2858013002:
  PS - Showing permission prompt for activeTab  (Closed) 
  | 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->SetPermissions( | |
| 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 if (!PermissionCheckNeeded(extension)) | |
| 
Devlin
2017/05/23 19:28:03
return !PermissionCheckNeeded(extension) || allowe
 
Ivan Šandrk
2017/05/24 09:29:01
Done.
 | |
| 179 return true; | |
| 180 return allowed_permission_set_.ContainsID(permission); | |
| 137 } | 181 } | 
| 138 | 182 | 
| 139 void PublicSessionPermissionHelper::ResolvePermissionPrompt( | 183 void PublicSessionPermissionHelper::ResolvePermissionPrompt( | 
| 140 const ExtensionInstallPrompt* prompt, | 184 const ExtensionInstallPrompt* prompt, | 
| 141 const PermissionIDSet& unprompted_permissions, | 185 const PermissionIDSet& unprompted_permissions, | 
| 142 ExtensionInstallPrompt::Result prompt_result) { | 186 ExtensionInstallPrompt::Result prompt_result) { | 
| 143 PermissionIDSet& add_to_set = | 187 PermissionIDSet& add_to_set = | 
| 144 prompt_result == ExtensionInstallPrompt::Result::ACCEPTED ? | 188 prompt_result == ExtensionInstallPrompt::Result::ACCEPTED ? | 
| 145 allowed_permission_set_ : denied_permission_set_; | 189 allowed_permission_set_ : denied_permission_set_; | 
| 146 for (const auto& permission : unprompted_permissions) { | 190 for (const auto& permission : unprompted_permissions) { | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 PublicSessionPermissionHelper::RequestCallback::RequestCallback( | 240 PublicSessionPermissionHelper::RequestCallback::RequestCallback( | 
| 197 const RequestCallback& other) = default; | 241 const RequestCallback& other) = default; | 
| 198 | 242 | 
| 199 PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {} | 243 PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {} | 
| 200 | 244 | 
| 201 base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky | 245 base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky | 
| 202 g_helpers = LAZY_INSTANCE_INITIALIZER; | 246 g_helpers = LAZY_INSTANCE_INITIALIZER; | 
| 203 | 247 | 
| 204 } // namespace | 248 } // namespace | 
| 205 | 249 | 
| 206 void HandlePermissionRequest(const Extension& extension, | 250 bool HandlePermissionRequest(const Extension& extension, | 
| 207 const PermissionIDSet& requested_permissions, | 251 const PermissionIDSet& requested_permissions, | 
| 208 content::WebContents* web_contents, | 252 content::WebContents* web_contents, | 
| 209 const RequestResolvedCallback& callback, | 253 const RequestResolvedCallback& callback, | 
| 210 const PromptFactory& prompt_factory) { | 254 const PromptFactory& prompt_factory) { | 
| 211 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 255 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 
| 212 const PromptFactory& factory = prompt_factory.is_null() | 256 const PromptFactory& factory = prompt_factory.is_null() | 
| 213 ? base::Bind(&CreateExtensionInstallPrompt) | 257 ? base::Bind(&CreateExtensionInstallPrompt) | 
| 214 : prompt_factory; | 258 : prompt_factory; | 
| 215 return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl( | 259 return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl( | 
| 216 extension, requested_permissions, web_contents, callback, factory); | 260 extension, requested_permissions, web_contents, callback, factory); | 
| 217 } | 261 } | 
| 218 | 262 | 
| 263 bool PermissionAllowed(const Extension* extension, | |
| 264 APIPermission::ID permission) { | |
| 265 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 266 return g_helpers.Get()[extension->id()].PermissionAllowedImpl(extension, | |
| 267 permission); | |
| 268 } | |
| 269 | |
| 219 void ResetPermissionsForTesting() { | 270 void ResetPermissionsForTesting() { | 
| 220 // Clear out the std::map between tests. Just setting g_helpers to | 271 // Clear out the std::map between tests. Just setting g_helpers to | 
| 221 // LAZY_INSTANCE_INITIALIZER again causes a memory leak (because of the | 272 // LAZY_INSTANCE_INITIALIZER again causes a memory leak (because of the | 
| 222 // LazyInstance::Leaky). | 273 // LazyInstance::Leaky). | 
| 223 g_helpers.Get().clear(); | 274 g_helpers.Get().clear(); | 
| 224 } | 275 } | 
| 225 | 276 | 
| 226 } // namespace permission_helper | 277 } // namespace permission_helper | 
| 227 } // namespace extensions | 278 } // namespace extensions | 
| OLD | NEW |