Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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 "base/memory/scoped_ptr.h" | |
| 6 #include "chrome/browser/extensions/extension_service.h" | |
| 7 #include "chrome/browser/extensions/extension_service_test_base.h" | |
| 8 #include "chrome/browser/extensions/permissions_updater.h" | |
| 9 #include "chrome/browser/profiles/profile.h" | |
| 10 #include "chrome/common/extensions/permissions/chrome_permission_message_provide r.h" | |
| 11 #include "chrome/grit/generated_resources.h" | |
| 12 #include "components/crx_file/id_util.h" | |
| 13 #include "extensions/browser/extension_prefs.h" | |
| 14 #include "extensions/browser/extension_registry.h" | |
| 15 #include "extensions/common/extension_builder.h" | |
| 16 #include "extensions/common/manifest.h" | |
| 17 #include "extensions/common/manifest_handlers/permissions_parser.h" | |
| 18 #include "extensions/common/permissions/permissions_data.h" | |
| 19 #include "extensions/common/test_util.h" | |
| 20 #include "testing/gtest/include/gtest/gtest.h" | |
| 21 #include "ui/base/l10n/l10n_util.h" | |
| 22 | |
| 23 namespace extensions { | |
| 24 | |
| 25 // Tests that ChromePermissionMessageProvider provides not only correct, but | |
| 26 // meaningful permission messages that coalesce correctly where appropriate. | |
| 27 // There are 3 types of permission messages that need to be tested: | |
| 28 // 1. The combined list of active permissions, displayed at install time (or | |
| 29 // when the app has been disabled automatically and needs to be re-enabled) | |
| 30 // 2. The split list of active permissions, displayed in the App Info dialog, | |
| 31 // where the optional permissions are individually revokable | |
| 32 // 3. The list of requested optional permissions, displayed in a prompt to the | |
| 33 // user when the app requests these during runtime | |
| 34 // Some of these tests are currently 'anti-tests' - they demonstrate existing | |
|
scheib
2014/09/25 17:55:44
Call out the naming convention:
"Some of these tes
sashab
2014/09/29 08:03:35
Done.
| |
| 35 // problematic functionality. These tests are prefixed with AntiTest_ and will | |
| 36 // be changed as the correct behaviour is implemented. TODOs in the test explain | |
| 37 // the currently problematic behaviour. | |
| 38 class PermissionMessagesUnittest : public ExtensionServiceTestBase { | |
|
scheib
2014/09/25 17:55:44
Cite the existence of this test suite at the top o
sashab
2014/09/29 08:03:36
Good idea. Done.
| |
| 39 public: | |
| 40 PermissionMessagesUnittest() | |
| 41 : message_provider_(new ChromePermissionMessageProvider()) {} | |
| 42 virtual ~PermissionMessagesUnittest() {} | |
| 43 | |
| 44 // Overridden from testing::Test: | |
| 45 virtual void SetUp() OVERRIDE { | |
| 46 ExtensionServiceTestBase::SetUp(); | |
| 47 InitializeExtensionService(CreateDefaultInitParams()); | |
| 48 InitializeProcessManager(); | |
| 49 } | |
| 50 | |
| 51 protected: | |
| 52 void CreateAndInstallAppWithPermissions(ListBuilder& required_permissions, | |
| 53 ListBuilder& optional_permissions) { | |
| 54 app_ = test_util::BuildApp(ExtensionBuilder().Pass()) | |
| 55 .MergeManifest( | |
| 56 DictionaryBuilder() | |
| 57 .Set("permissions", required_permissions) | |
| 58 .Set("optional_permissions", optional_permissions)) | |
| 59 .SetID(crx_file::id_util::GenerateId("app")) | |
| 60 .SetLocation(Manifest::INTERNAL) | |
| 61 .Build(); | |
| 62 service()->AddExtension(app_.get()); | |
| 63 } | |
| 64 | |
| 65 void CreateAndInstallExtensionWithPermissions( | |
| 66 ListBuilder& required_permissions, | |
| 67 ListBuilder& optional_permissions) { | |
| 68 app_ = test_util::BuildExtension(ExtensionBuilder().Pass()) | |
| 69 .MergeManifest( | |
| 70 DictionaryBuilder() | |
| 71 .Set("permissions", required_permissions) | |
| 72 .Set("optional_permissions", optional_permissions)) | |
| 73 .SetID(crx_file::id_util::GenerateId("extension")) | |
| 74 .SetLocation(Manifest::INTERNAL) | |
| 75 .Build(); | |
| 76 service()->AddExtension(app_.get()); | |
| 77 } | |
| 78 | |
| 79 // Returns the permission messages that would display in the prompt that | |
| 80 // requests all the optional permissions for the current |app_|. | |
| 81 std::vector<base::string16> RequestOptionalPermissions() { | |
|
scheib
2014/09/25 17:55:44
This name seems a tad confusing to me still. Perha
sashab
2014/09/29 08:03:35
Changed to GetOptionalPermissionMessages() :)
| |
| 82 scoped_refptr<const PermissionSet> granted_permissions = | |
| 83 ExtensionPrefs::Get(profile())->GetGrantedPermissions(app_->id()); | |
| 84 scoped_refptr<const PermissionSet> optional_permissions = | |
| 85 PermissionsParser::GetOptionalPermissions(app_.get()); | |
| 86 scoped_refptr<const PermissionSet> requested_permissions = | |
| 87 PermissionSet::CreateDifference(optional_permissions.get(), | |
| 88 granted_permissions.get()); | |
| 89 return GetMessages(requested_permissions); | |
| 90 } | |
| 91 | |
| 92 void GrantOptionalPermissions() { | |
| 93 PermissionsUpdater perms_updater(profile()); | |
| 94 perms_updater.AddPermissions( | |
| 95 app_.get(), | |
| 96 PermissionsParser::GetOptionalPermissions(app_.get()).get()); | |
| 97 } | |
| 98 | |
| 99 std::vector<base::string16> active_permissions() { | |
| 100 return GetMessages(app_->permissions_data()->active_permissions()); | |
| 101 } | |
| 102 | |
| 103 std::vector<base::string16> withheld_permissions() { | |
| 104 return GetMessages(app_->permissions_data()->withheld_permissions()); | |
| 105 } | |
| 106 | |
| 107 std::vector<base::string16> granted_permissions() { | |
| 108 return GetMessages( | |
| 109 ExtensionPrefs::Get(profile())->GetGrantedPermissions(app_->id())); | |
| 110 } | |
| 111 | |
| 112 std::vector<base::string16> required_permissions() { | |
| 113 return GetMessages(PermissionsParser::GetRequiredPermissions(app_.get())); | |
| 114 } | |
| 115 | |
| 116 std::vector<base::string16> optional_permissions() { | |
| 117 return GetMessages(PermissionsParser::GetOptionalPermissions(app_.get())); | |
| 118 } | |
| 119 | |
| 120 private: | |
| 121 std::vector<base::string16> GetMessages( | |
| 122 scoped_refptr<const PermissionSet> permissions) { | |
| 123 return message_provider_->GetWarningMessages(permissions.get(), | |
| 124 app_->GetType()); | |
| 125 } | |
| 126 | |
| 127 scoped_ptr<ChromePermissionMessageProvider> message_provider_; | |
| 128 scoped_refptr<const Extension> app_; | |
| 129 | |
| 130 DISALLOW_COPY_AND_ASSIGN(PermissionMessagesUnittest); | |
| 131 }; | |
| 132 | |
| 133 // If an app has both the 'serial' and 'USB' permission, they should coalesce | |
| 134 // into a single permission message. | |
| 135 TEST_F(PermissionMessagesUnittest, RequiredPermissionMessagesCoalesce) { | |
| 136 CreateAndInstallAppWithPermissions( | |
| 137 ListBuilder().Append("serial").Append("usb").Pass(), | |
| 138 ListBuilder().Pass()); | |
| 139 | |
| 140 ASSERT_EQ(1U, required_permissions().size()); | |
| 141 EXPECT_EQ(l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_USB_SERIAL), | |
| 142 required_permissions()[0]); | |
| 143 | |
| 144 ASSERT_EQ(0U, optional_permissions().size()); | |
| 145 } | |
| 146 | |
| 147 // If an app has both the 'history' and 'tabs' permission, one should hide the | |
| 148 // other (the 'history' permission has superset permissions). | |
| 149 TEST_F(PermissionMessagesUnittest, HistoryHidesTabsMessage) { | |
| 150 CreateAndInstallExtensionWithPermissions( | |
| 151 ListBuilder().Append("tabs").Append("history").Pass(), | |
| 152 ListBuilder().Pass()); | |
| 153 | |
| 154 ASSERT_EQ(1U, required_permissions().size()); | |
| 155 EXPECT_EQ( | |
| 156 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 157 required_permissions()[0]); | |
| 158 | |
| 159 ASSERT_EQ(0U, optional_permissions().size()); | |
| 160 } | |
| 161 | |
| 162 // If an app requests the 'history' permission, but already has the 'tabs' | |
| 163 // permission, only the new coalesced message is displayed. | |
| 164 TEST_F(PermissionMessagesUnittest, MixedPermissionMessagesCoalesceOnceGranted) { | |
| 165 CreateAndInstallExtensionWithPermissions( | |
| 166 ListBuilder().Append("tabs").Pass(), | |
| 167 ListBuilder().Append("history").Pass()); | |
| 168 | |
| 169 ASSERT_EQ(1U, required_permissions().size()); | |
| 170 EXPECT_EQ( | |
| 171 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ), | |
| 172 required_permissions()[0]); | |
| 173 | |
| 174 ASSERT_EQ(1U, optional_permissions().size()); | |
| 175 EXPECT_EQ( | |
| 176 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 177 optional_permissions()[0]); | |
| 178 | |
| 179 ASSERT_EQ(1U, active_permissions().size()); | |
| 180 EXPECT_EQ( | |
| 181 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ), | |
| 182 active_permissions()[0]); | |
| 183 | |
| 184 ASSERT_EQ(1U, RequestOptionalPermissions().size()); | |
| 185 EXPECT_EQ( | |
| 186 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 187 RequestOptionalPermissions()[0]); | |
| 188 | |
| 189 GrantOptionalPermissions(); | |
| 190 | |
| 191 ASSERT_EQ(1U, active_permissions().size()); | |
| 192 EXPECT_EQ( | |
| 193 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 194 active_permissions()[0]); | |
| 195 } | |
| 196 | |
| 197 // If an app requests the 'tabs' permission but already has the 'history' | |
| 198 // permission, a prompt is displayed to request this permission, but it doesn't | |
| 199 // appear in the final list of permissions since it is a subset of an already | |
| 200 // granted permission. | |
|
scheib
2014/09/25 17:55:44
Call out more explicitly what is 'AntiTest' about
sashab
2014/09/29 08:03:36
Thanks. Updated both.
| |
| 201 TEST_F(PermissionMessagesUnittest, | |
| 202 AntiTest_PromptCanRequestSubsetOfAlreadyGrantedPermissions) { | |
| 203 CreateAndInstallExtensionWithPermissions( | |
| 204 ListBuilder().Append("history").Pass(), | |
| 205 ListBuilder().Append("tabs").Pass()); | |
| 206 | |
| 207 ASSERT_EQ(1U, required_permissions().size()); | |
| 208 EXPECT_EQ( | |
| 209 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 210 required_permissions()[0]); | |
| 211 | |
| 212 ASSERT_EQ(1U, optional_permissions().size()); | |
| 213 EXPECT_EQ( | |
| 214 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ), | |
| 215 optional_permissions()[0]); | |
| 216 | |
| 217 ASSERT_EQ(1U, active_permissions().size()); | |
| 218 EXPECT_EQ( | |
| 219 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 220 active_permissions()[0]); | |
| 221 | |
| 222 // TODO(sashab): This prompt should display no permissions, since READ is a | |
| 223 // subset permission of WRITE. | |
| 224 ASSERT_EQ(1U, RequestOptionalPermissions().size()); | |
| 225 EXPECT_EQ( | |
| 226 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ), | |
| 227 RequestOptionalPermissions()[0]); | |
| 228 | |
| 229 GrantOptionalPermissions(); | |
| 230 | |
| 231 ASSERT_EQ(1U, active_permissions().size()); | |
| 232 EXPECT_EQ( | |
| 233 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_WRITE), | |
| 234 active_permissions()[0]); | |
| 235 } | |
| 236 | |
| 237 // If an app requests the 'sessions' permission, nothing is displayed in the | |
| 238 // permission request prompt, but the required permissions for the app are | |
| 239 // actually modified. | |
| 240 TEST_F(PermissionMessagesUnittest, | |
| 241 AntiTest_PromptCanBeEmptyButCausesChangeInPermissions) { | |
| 242 CreateAndInstallExtensionWithPermissions( | |
| 243 ListBuilder().Append("tabs").Pass(), | |
| 244 ListBuilder().Append("sessions").Pass()); | |
| 245 | |
| 246 ASSERT_EQ(1U, required_permissions().size()); | |
| 247 EXPECT_EQ( | |
| 248 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ), | |
| 249 required_permissions()[0]); | |
| 250 | |
| 251 ASSERT_EQ(0U, optional_permissions().size()); | |
| 252 | |
| 253 ASSERT_EQ(1U, active_permissions().size()); | |
| 254 EXPECT_EQ( | |
| 255 l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ), | |
| 256 active_permissions()[0]); | |
| 257 | |
| 258 // TODO(sashab): This prompt should display the sessions permission message, | |
| 259 // as well as warn the user that it can affect the existing 'tab' permission. | |
| 260 ASSERT_EQ(0U, RequestOptionalPermissions().size()); | |
| 261 | |
| 262 GrantOptionalPermissions(); | |
| 263 | |
| 264 ASSERT_EQ(1U, active_permissions().size()); | |
| 265 EXPECT_EQ(l10n_util::GetStringUTF16( | |
| 266 IDS_EXTENSION_PROMPT_WARNING_HISTORY_READ_AND_SESSIONS), | |
| 267 active_permissions()[0]); | |
| 268 } | |
| 269 | |
| 270 } // namespace extensions | |
| OLD | NEW |